summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format17
-rw-r--r--.gitignore3
-rw-r--r--.mailmap9
-rw-r--r--Documentation/ABI/testing/debugfs-moxtet23
-rw-r--r--Documentation/ABI/testing/sysfs-bus-moxtet-devices17
-rw-r--r--Documentation/ABI/testing/sysfs-devices-soc7
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-efi8
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm37
-rw-r--r--Documentation/PCI/index.rst2
-rw-r--r--Documentation/PCI/pci-error-recovery.rst5
-rw-r--r--Documentation/PCI/pciebus-howto.rst (renamed from Documentation/PCI/picebus-howto.rst)0
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.html73
-rw-r--r--Documentation/RCU/rculist_nulls.txt2
-rw-r--r--Documentation/RCU/stallwarn.txt6
-rw-r--r--Documentation/admin-guide/cgroup-v2.rst34
-rw-r--r--Documentation/admin-guide/conf.py10
-rw-r--r--Documentation/admin-guide/hw-vuln/spectre.rst88
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt43
-rw-r--r--Documentation/admin-guide/laptops/thinkpad-acpi.rst23
-rw-r--r--Documentation/admin-guide/mm/transhuge.rst2
-rw-r--r--Documentation/admin-guide/perf/imx-ddr.rst52
-rw-r--r--Documentation/admin-guide/sysctl/net.rst29
-rw-r--r--Documentation/arm64/index.rst1
-rw-r--r--Documentation/arm64/kasan-offsets.sh27
-rw-r--r--Documentation/arm64/memory.rst123
-rw-r--r--Documentation/arm64/silicon-errata.rst2
-rw-r--r--Documentation/arm64/tagged-address-abi.rst156
-rw-r--r--Documentation/arm64/tagged-pointers.rst21
-rw-r--r--Documentation/conf.py30
-rw-r--r--Documentation/core-api/conf.py10
-rw-r--r--Documentation/crypto/conf.py10
-rw-r--r--Documentation/dev-tools/conf.py10
-rw-r--r--Documentation/devicetree/bindings/Makefile4
-rw-r--r--Documentation/devicetree/bindings/arm/amlogic.yaml21
-rw-r--r--Documentation/devicetree/bindings/arm/arm,scmi.txt17
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml26
-rw-r--r--Documentation/devicetree/bindings/arm/idle-states.txt2
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek.yaml4
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml8
-rw-r--r--Documentation/devicetree/bindings/arm/renesas.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/rockchip.yaml45
-rw-r--r--Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/sunxi.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml2
-rw-r--r--Documentation/devicetree/bindings/bus/imx-weim.txt4
-rw-r--r--Documentation/devicetree/bindings/bus/moxtet.txt46
-rw-r--r--Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/imx8mn-clock.yaml112
-rw-r--r--Documentation/devicetree/bindings/cpu/cpu-topology.txt (renamed from Documentation/devicetree/bindings/arm/topology.txt)256
-rw-r--r--Documentation/devicetree/bindings/eeprom/at25.txt1
-rw-r--r--Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt19
-rw-r--r--Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml2
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.txt4
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-aspeed.txt7
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-davinci.txt1
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-moxtet.txt18
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt16
-rw-r--r--Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt45
-rw-r--r--Documentation/devicetree/bindings/hwmon/as370.txt11
-rw-r--r--Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt8
-rw-r--r--Documentation/devicetree/bindings/hwmon/lm75.txt1
-rw-r--r--Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ads1015.txt (renamed from Documentation/devicetree/bindings/hwmon/ads1015.txt)0
-rw-r--r--Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml43
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt16
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml6
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml2
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt30
-rw-r--r--Documentation/devicetree/bindings/iommu/mediatek,iommu.txt30
-rw-r--r--Documentation/devicetree/bindings/media/amlogic,vdec.txt5
-rw-r--r--Documentation/devicetree/bindings/media/renesas,csi2.txt (renamed from Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt)0
-rw-r--r--Documentation/devicetree/bindings/media/renesas,imr.txt (renamed from Documentation/devicetree/bindings/media/rcar_imr.txt)0
-rw-r--r--Documentation/devicetree/bindings/media/renesas,vin.txt (renamed from Documentation/devicetree/bindings/media/rcar_vin.txt)0
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt12
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt4
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt (renamed from Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt)0
-rw-r--r--Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml76
-rw-r--r--Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt59
-rw-r--r--Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml (renamed from Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml)2
-rw-r--r--Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/can/rcar_can.txt6
-rw-r--r--Documentation/devicetree/bindings/net/can/rcar_canfd.txt15
-rw-r--r--Documentation/devicetree/bindings/net/dsa/ksz.txt1
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt30
-rw-r--r--Documentation/devicetree/bindings/net/macb.txt4
-rw-r--r--Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml4
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml45
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem.txt81
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem.yaml93
-rw-r--r--Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml3
-rw-r--r--Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml93
-rw-r--r--Documentation/devicetree/bindings/regulator/act8865-regulator.txt27
-rw-r--r--Documentation/devicetree/bindings/regulator/fixed-regulator.yaml19
-rw-r--r--Documentation/devicetree/bindings/regulator/mt6358-regulator.txt358
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt15
-rw-r--r--Documentation/devicetree/bindings/regulator/sy8824x.txt24
-rw-r--r--Documentation/devicetree/bindings/regulator/twl-regulator.txt7
-rw-r--r--Documentation/devicetree/bindings/regulator/uniphier-regulator.txt5
-rw-r--r--Documentation/devicetree/bindings/reset/fsl,imx7-src.txt6
-rw-r--r--Documentation/devicetree/bindings/reset/snps,dw-reset.txt30
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.txt162
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.yaml16
-rw-r--r--Documentation/devicetree/bindings/riscv/sifive.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.txt5
-rw-r--r--Documentation/devicetree/bindings/serial/mtk-uart.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt13
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt5
-rw-r--r--Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt11
-rw-r--r--Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt47
-rw-r--r--Documentation/devicetree/bindings/spi/spi-controller.yaml3
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt1
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt9
-rw-r--r--Documentation/devicetree/bindings/spi/spi-mt65xx.txt1
-rw-r--r--Documentation/devicetree/bindings/spi/spi-sprd-adi.txt11
-rw-r--r--Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml2
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/usb251xb.txt6
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml14
-rw-r--r--Documentation/doc-guide/conf.py10
-rw-r--r--Documentation/driver-api/80211/conf.py10
-rw-r--r--Documentation/driver-api/conf.py10
-rw-r--r--Documentation/driver-api/generic-counter.rst4
-rw-r--r--Documentation/driver-api/gpio/driver.rst138
-rw-r--r--Documentation/driver-api/phy/phy.rst4
-rw-r--r--Documentation/driver-api/pm/conf.py10
-rw-r--r--Documentation/driver-api/sgi-ioc4.rst49
-rw-r--r--Documentation/features/core/jump-labels/arch-support.txt2
-rw-r--r--Documentation/features/debug/kprobes-on-ftrace/arch-support.txt2
-rw-r--r--Documentation/filesystems/cifs/TODO26
-rw-r--r--Documentation/filesystems/conf.py10
-rw-r--r--Documentation/gpu/conf.py10
-rw-r--r--Documentation/hwmon/ads1015.rst90
-rw-r--r--Documentation/hwmon/index.rst2
-rw-r--r--Documentation/hwmon/inspur-ipsps1.rst79
-rw-r--r--Documentation/hwmon/k8temp.rst2
-rw-r--r--Documentation/hwmon/lm75.rst6
-rw-r--r--Documentation/hwmon/pxe1610.rst (renamed from Documentation/hwmon/pxe1610)33
-rw-r--r--Documentation/hwmon/shtc1.rst19
-rw-r--r--Documentation/hwmon/submitting-patches.rst8
-rw-r--r--Documentation/index.rst3
-rw-r--r--Documentation/input/conf.py10
-rw-r--r--Documentation/kernel-hacking/conf.py10
-rw-r--r--Documentation/locking/spinlocks.rst4
-rw-r--r--Documentation/maintainer/conf.py10
-rw-r--r--Documentation/media/conf.py12
-rw-r--r--Documentation/memory-barriers.txt2
-rw-r--r--Documentation/networking/conf.py10
-rw-r--r--Documentation/networking/tls-offload.rst41
-rw-r--r--Documentation/networking/tuntap.txt4
-rw-r--r--Documentation/power/index.rst2
-rw-r--r--Documentation/powerpc/bootwrapper.rst (renamed from Documentation/powerpc/bootwrapper.txt)28
-rw-r--r--Documentation/powerpc/cpu_families.rst (renamed from Documentation/powerpc/cpu_families.txt)23
-rw-r--r--Documentation/powerpc/cpu_features.rst (renamed from Documentation/powerpc/cpu_features.txt)6
-rw-r--r--Documentation/powerpc/cxl.rst (renamed from Documentation/powerpc/cxl.txt)46
-rw-r--r--Documentation/powerpc/cxlflash.rst (renamed from Documentation/powerpc/cxlflash.txt)10
-rw-r--r--Documentation/powerpc/dawr-power9.rst (renamed from Documentation/powerpc/DAWR-POWER9.txt)15
-rw-r--r--Documentation/powerpc/dscr.rst (renamed from Documentation/powerpc/dscr.txt)18
-rw-r--r--Documentation/powerpc/eeh-pci-error-recovery.rst (renamed from Documentation/powerpc/eeh-pci-error-recovery.txt)108
-rw-r--r--Documentation/powerpc/firmware-assisted-dump.rst (renamed from Documentation/powerpc/firmware-assisted-dump.txt)117
-rw-r--r--Documentation/powerpc/hvcs.rst (renamed from Documentation/powerpc/hvcs.txt)108
-rw-r--r--Documentation/powerpc/index.rst34
-rw-r--r--Documentation/powerpc/isa-versions.rst15
-rw-r--r--Documentation/powerpc/mpc52xx.rst (renamed from Documentation/powerpc/mpc52xx.txt)12
-rw-r--r--Documentation/powerpc/pci_iov_resource_on_powernv.rst (renamed from Documentation/powerpc/pci_iov_resource_on_powernv.txt)15
-rw-r--r--Documentation/powerpc/pmu-ebb.rst (renamed from Documentation/powerpc/pmu-ebb.txt)1
-rw-r--r--Documentation/powerpc/ptrace.rst156
-rw-r--r--Documentation/powerpc/ptrace.txt151
-rw-r--r--Documentation/powerpc/qe_firmware.rst (renamed from Documentation/powerpc/qe_firmware.txt)37
-rw-r--r--Documentation/powerpc/syscall64-abi.rst (renamed from Documentation/powerpc/syscall64-abi.txt)29
-rw-r--r--Documentation/powerpc/transactional_memory.rst (renamed from Documentation/powerpc/transactional_memory.txt)45
-rw-r--r--Documentation/process/conf.py10
-rw-r--r--Documentation/process/deprecated.rst14
-rw-r--r--Documentation/process/embargoed-hardware-issues.rst279
-rw-r--r--Documentation/process/index.rst1
-rw-r--r--Documentation/riscv/boot-image-header.txt13
-rw-r--r--Documentation/s390/vfio-ccw.rst31
-rw-r--r--Documentation/scheduler/sched-bwc.rst74
-rw-r--r--Documentation/security/tpm/index.rst1
-rw-r--r--Documentation/security/tpm/tpm_ftpm_tee.rst27
-rw-r--r--Documentation/sh/conf.py10
-rw-r--r--Documentation/sound/conf.py10
-rw-r--r--Documentation/sphinx/load_config.py27
-rw-r--r--Documentation/translations/it_IT/doc-guide/sphinx.rst19
-rw-r--r--Documentation/translations/it_IT/process/index.rst1
-rw-r--r--Documentation/translations/it_IT/process/kernel-docs.rst11
-rw-r--r--Documentation/translations/it_IT/process/maintainer-pgp-guide.rst25
-rw-r--r--Documentation/translations/it_IT/process/programming-language.rst51
-rw-r--r--Documentation/translations/ko_KR/memory-barriers.txt2
-rw-r--r--Documentation/userspace-api/conf.py10
-rw-r--r--Documentation/virt/index.rst (renamed from Documentation/virtual/index.rst)0
-rw-r--r--Documentation/virt/kvm/amd-memory-encryption.rst (renamed from Documentation/virtual/kvm/amd-memory-encryption.rst)0
-rw-r--r--Documentation/virt/kvm/api.txt (renamed from Documentation/virtual/kvm/api.txt)2
-rw-r--r--Documentation/virt/kvm/arm/hyp-abi.txt (renamed from Documentation/virtual/kvm/arm/hyp-abi.txt)0
-rw-r--r--Documentation/virt/kvm/arm/psci.txt (renamed from Documentation/virtual/kvm/arm/psci.txt)0
-rw-r--r--Documentation/virt/kvm/cpuid.rst (renamed from Documentation/virtual/kvm/cpuid.rst)0
-rw-r--r--Documentation/virt/kvm/devices/README (renamed from Documentation/virtual/kvm/devices/README)0
-rw-r--r--Documentation/virt/kvm/devices/arm-vgic-its.txt (renamed from Documentation/virtual/kvm/devices/arm-vgic-its.txt)0
-rw-r--r--Documentation/virt/kvm/devices/arm-vgic-v3.txt (renamed from Documentation/virtual/kvm/devices/arm-vgic-v3.txt)0
-rw-r--r--Documentation/virt/kvm/devices/arm-vgic.txt (renamed from Documentation/virtual/kvm/devices/arm-vgic.txt)0
-rw-r--r--Documentation/virt/kvm/devices/mpic.txt (renamed from Documentation/virtual/kvm/devices/mpic.txt)0
-rw-r--r--Documentation/virt/kvm/devices/s390_flic.txt (renamed from Documentation/virtual/kvm/devices/s390_flic.txt)0
-rw-r--r--Documentation/virt/kvm/devices/vcpu.txt (renamed from Documentation/virtual/kvm/devices/vcpu.txt)0
-rw-r--r--Documentation/virt/kvm/devices/vfio.txt (renamed from Documentation/virtual/kvm/devices/vfio.txt)0
-rw-r--r--Documentation/virt/kvm/devices/vm.txt (renamed from Documentation/virtual/kvm/devices/vm.txt)0
-rw-r--r--Documentation/virt/kvm/devices/xics.txt (renamed from Documentation/virtual/kvm/devices/xics.txt)0
-rw-r--r--Documentation/virt/kvm/devices/xive.txt (renamed from Documentation/virtual/kvm/devices/xive.txt)0
-rw-r--r--Documentation/virt/kvm/halt-polling.txt (renamed from Documentation/virtual/kvm/halt-polling.txt)0
-rw-r--r--Documentation/virt/kvm/hypercalls.txt (renamed from Documentation/virtual/kvm/hypercalls.txt)4
-rw-r--r--Documentation/virt/kvm/index.rst (renamed from Documentation/virtual/kvm/index.rst)1
-rw-r--r--Documentation/virt/kvm/locking.txt (renamed from Documentation/virtual/kvm/locking.txt)0
-rw-r--r--Documentation/virt/kvm/mmu.txt (renamed from Documentation/virtual/kvm/mmu.txt)2
-rw-r--r--Documentation/virt/kvm/msr.txt (renamed from Documentation/virtual/kvm/msr.txt)0
-rw-r--r--Documentation/virt/kvm/nested-vmx.txt (renamed from Documentation/virtual/kvm/nested-vmx.txt)0
-rw-r--r--Documentation/virt/kvm/ppc-pv.txt (renamed from Documentation/virtual/kvm/ppc-pv.txt)0
-rw-r--r--Documentation/virt/kvm/review-checklist.txt (renamed from Documentation/virtual/kvm/review-checklist.txt)2
-rw-r--r--Documentation/virt/kvm/s390-diag.txt (renamed from Documentation/virtual/kvm/s390-diag.txt)0
-rw-r--r--Documentation/virt/kvm/timekeeping.txt (renamed from Documentation/virtual/kvm/timekeeping.txt)0
-rw-r--r--Documentation/virt/kvm/vcpu-requests.rst (renamed from Documentation/virtual/kvm/vcpu-requests.rst)0
-rw-r--r--Documentation/virt/paravirt_ops.rst (renamed from Documentation/virtual/paravirt_ops.rst)0
-rw-r--r--Documentation/virt/uml/UserModeLinux-HOWTO.txt (renamed from Documentation/virtual/uml/UserModeLinux-HOWTO.txt)0
-rw-r--r--Documentation/vm/conf.py10
-rw-r--r--Documentation/vm/hmm.rst2
-rw-r--r--Documentation/watchdog/hpwdt.rst2
-rw-r--r--Documentation/x86/conf.py10
-rw-r--r--MAINTAINERS308
-rw-r--r--Makefile32
-rw-r--r--arch/Kconfig19
-rw-r--r--arch/arc/boot/dts/Makefile3
-rw-r--r--arch/arc/include/asm/entry-arcv2.h2
-rw-r--r--arch/arc/include/asm/linkage.h8
-rw-r--r--arch/arc/include/asm/mach_desc.h3
-rw-r--r--arch/arc/kernel/mcip.c60
-rw-r--r--arch/arc/kernel/unwind.c5
-rw-r--r--arch/arc/mm/dma.c2
-rw-r--r--arch/arc/plat-hsdk/platform.c87
-rw-r--r--arch/arm/Kconfig102
-rw-r--r--arch/arm/Kconfig.debug46
-rw-r--r--arch/arm/Makefile6
-rw-r--r--arch/arm/boot/dts/Makefile19
-rw-r--r--arch/arm/boot/dts/am335x-boneblue.dts92
-rw-r--r--arch/arm/boot/dts/am335x-cm-t335.dts1
-rw-r--r--arch/arm/boot/dts/am33xx-l4.dtsi16
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi32
-rw-r--r--arch/arm/boot/dts/am4372.dtsi32
-rw-r--r--arch/arm/boot/dts/am437x-l4.dtsi4
-rw-r--r--arch/arm/boot/dts/am571x-idk.dts7
-rw-r--r--arch/arm/boot/dts/am572x-idk.dts7
-rw-r--r--arch/arm/boot/dts/am574x-idk.dts7
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi3
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts7
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15-revc.dts7
-rw-r--r--arch/arm/boot/dts/aspeed-ast2500-evb.dts11
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts429
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts272
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts149
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts141
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts663
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts918
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-swift.dts19
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts10
-rw-r--r--arch/arm/boot/dts/aspeed-g4.dtsi48
-rw-r--r--arch/arm/boot/dts/aspeed-g5.dtsi35
-rw-r--r--arch/arm/boot/dts/at91-ariag25.dts255
-rw-r--r--arch/arm/boot/dts/at91-ariettag25.dts100
-rw-r--r--arch/arm/boot/dts/at91-cosino.dtsi203
-rw-r--r--arch/arm/boot/dts/at91-cosino_mega2560.dts93
-rw-r--r--arch/arm/boot/dts/at91-kizboxmini.dts179
-rw-r--r--arch/arm/boot/dts/at91sam9261ek.dts2
-rw-r--r--arch/arm/boot/dts/at91sam9263ek.dts2
-rw-r--r--arch/arm/boot/dts/at91sam9g15.dtsi28
-rw-r--r--arch/arm/boot/dts/at91sam9g15ek.dts12
-rw-r--r--arch/arm/boot/dts/at91sam9g25ek.dts89
-rw-r--r--arch/arm/boot/dts/at91sam9g35ek.dts22
-rw-r--r--arch/arm/boot/dts/at91sam9m10g45ek.dts2
-rw-r--r--arch/arm/boot/dts/at91sam9rlek.dts2
-rw-r--r--arch/arm/boot/dts/at91sam9x25ek.dts36
-rw-r--r--arch/arm/boot/dts/at91sam9x35ek.dts43
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi2
-rw-r--r--arch/arm/boot/dts/at91sam9x5_lcd.dtsi194
-rw-r--r--arch/arm/boot/dts/at91sam9x5dm.dtsi86
-rw-r--r--arch/arm/boot/dts/at91sam9x5ek.dtsi265
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a-plus.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-plus.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts9
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi5
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-zero-w.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-zero.dts14
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi.dtsi23
-rw-r--r--arch/arm/boot/dts/bcm2836-rpi-2-b.dts10
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts3
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts3
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b.dts3
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts9
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm283x.dtsi6
-rw-r--r--arch/arm/boot/dts/bcm47094-linksys-panamera.dts3
-rw-r--r--arch/arm/boot/dts/da850-evm.dts2
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts2
-rw-r--r--arch/arm/boot/dts/dra7-l4.dtsi6
-rw-r--r--arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi50
-rw-r--r--arch/arm/boot/dts/ep7211-edb7211.dts2
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi3
-rw-r--r--arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi18
-rw-r--r--arch/arm/boot/dts/exynos5250-arndale.dts9
-rw-r--r--arch/arm/boot/dts/exynos5250-snow-common.dtsi5
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi48
-rw-r--r--arch/arm/boot/dts/exynos5420-peach-pit.dts1
-rw-r--r--arch/arm/boot/dts/exynos5420.dtsi13
-rw-r--r--arch/arm/boot/dts/exynos5800-peach-pi.dts1
-rw-r--r--arch/arm/boot/dts/exynos5800.dtsi9
-rw-r--r--arch/arm/boot/dts/gemini-nas4220b.dts37
-rw-r--r--arch/arm/boot/dts/gemini-sl93512r.dts56
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts2
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts2
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts2
-rw-r--r--arch/arm/boot/dts/imx25-pdk.dts2
-rw-r--r--arch/arm/boot/dts/imx27-apf27dev.dts2
-rw-r--r--arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts2
-rw-r--r--arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts2
-rw-r--r--arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts2
-rw-r--r--arch/arm/boot/dts/imx53-m53menlo.dts3
-rw-r--r--arch/arm/boot/dts/imx6qdl-colibri.dtsi11
-rw-r--r--arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi73
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi18
-rw-r--r--arch/arm/boot/dts/imx6sll.dtsi24
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi22
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6ul-geam.dts2
-rw-r--r--arch/arm/boot/dts/imx6ul-isiot.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts102
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts420
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi134
-rw-r--r--arch/arm/boot/dts/imx6ul-opos6uldev.dts37
-rw-r--r--arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi (renamed from arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi)53
-rw-r--r--arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts (renamed from arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts)42
-rw-r--r--arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi (renamed from arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi)16
-rw-r--r--arch/arm/boot/dts/imx6ul-phytec-segin.dtsi (renamed from arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi)31
-rw-r--r--arch/arm/boot/dts/imx6ul-pico-hobbit.dts2
-rw-r--r--arch/arm/boot/dts/imx6ul-pico-pi.dts4
-rw-r--r--arch/arm/boot/dts/imx6ul.dtsi53
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi24
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts93
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts93
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts45
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi19
-rw-r--r--arch/arm/boot/dts/imx6ull-phytec-segin.dtsi38
-rw-r--r--arch/arm/boot/dts/imx7-colibri.dtsi86
-rw-r--r--arch/arm/boot/dts/imx7d-cl-som-imx7.dts6
-rw-r--r--arch/arm/boot/dts/imx7d-zii-rmu2.dts357
-rw-r--r--arch/arm/boot/dts/imx7d-zii-rpu2.dts4
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi4
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi6
-rw-r--r--arch/arm/boot/dts/imx7ulp.dtsi38
-rw-r--r--arch/arm/boot/dts/kirkwood-ts219.dtsi8
-rw-r--r--arch/arm/boot/dts/meson8b-ec100.dts31
-rw-r--r--arch/arm/boot/dts/meson8b-mxq.dts26
-rw-r--r--arch/arm/boot/dts/meson8b-odroidc1.dts36
-rw-r--r--arch/arm/boot/dts/meson8b.dtsi10
-rw-r--r--arch/arm/boot/dts/mt7629-rfb.dts263
-rw-r--r--arch/arm/boot/dts/mt7629.dtsi481
-rw-r--r--arch/arm/boot/dts/nspire-classic.dtsi15
-rw-r--r--arch/arm/boot/dts/nspire-cx.dts15
-rw-r--r--arch/arm/boot/dts/nspire.dtsi10
-rw-r--r--arch/arm/boot/dts/omap3-gta04.dtsi4
-rw-r--r--arch/arm/boot/dts/omap3-n950-n9.dtsi1
-rw-r--r--arch/arm/boot/dts/r8a77470.dtsi7
-rw-r--r--arch/arm/boot/dts/r8a7779.dtsi4
-rw-r--r--arch/arm/boot/dts/rk3036.dtsi2
-rw-r--r--arch/arm/boot/dts/rk3229-xms6.dts283
-rw-r--r--arch/arm/boot/dts/rk3288-evb.dtsi2
-rw-r--r--arch/arm/boot/dts/rk3288-fennec.dts347
-rw-r--r--arch/arm/boot/dts/rk3288-tinker.dtsi12
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi101
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-edp.dtsi172
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-fievel.dts522
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-jaq.dts55
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-jerry.dts207
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-minnie.dts66
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-pinky.dts17
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-speedy.dts58
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-tiger.dts118
-rw-r--r--arch/arm/boot/dts/rk3288-veyron.dtsi4
-rw-r--r--arch/arm/boot/dts/socfpga.dtsi3
-rw-r--r--arch/arm/boot/dts/socfpga_arria10.dtsi7
-rw-r--r--arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts20
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts30
-rw-r--r--arch/arm/boot/dts/ste-ab8500.dtsi228
-rw-r--r--arch/arm/boot/dts/ste-dbx5x0.dtsi251
-rw-r--r--arch/arm/boot/dts/ste-href-ab8500.dtsi2
-rw-r--r--arch/arm/boot/dts/ste-href-family-pinctrl.dtsi1
-rw-r--r--arch/arm/boot/dts/ste-href-stuib.dtsi11
-rw-r--r--arch/arm/boot/dts/ste-href.dtsi4
-rw-r--r--arch/arm/boot/dts/ste-hrefprev60-stuib.dts14
-rw-r--r--arch/arm/boot/dts/ste-hrefv60plus-stuib.dts14
-rw-r--r--arch/arm/boot/dts/ste-nomadik-nhk15.dts8
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts33
-rw-r--r--arch/arm/boot/dts/stm32429i-eval.dts25
-rw-r--r--arch/arm/boot/dts/stm32f429.dtsi12
-rw-r--r--arch/arm/boot/dts/stm32f746.dtsi12
-rw-r--r--arch/arm/boot/dts/stm32h743i-eval.dts1
-rw-r--r--arch/arm/boot/dts/stm32mp157-pinctrl.dtsi70
-rw-r--r--arch/arm/boot/dts/stm32mp157a-dk1.dts135
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ed1.dts46
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ev1.dts17
-rw-r--r--arch/arm/boot/dts/stm32mp157c.dtsi61
-rw-r--r--arch/arm/boot/dts/sun4i-a10-a1000.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-cubieboard.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-hackberry.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-marsboard.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10-pcduino.dts2
-rw-r--r--arch/arm/boot/dts/sun4i-a10.dtsi9
-rw-r--r--arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts2
-rw-r--r--arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts2
-rw-r--r--arch/arm/boot/dts/sun5i-a13-q8-tablet.dts2
-rw-r--r--arch/arm/boot/dts/sun5i.dtsi9
-rw-r--r--arch/arm/boot/dts/sun6i-a31-colombus.dts12
-rw-r--r--arch/arm/boot/dts/sun6i-a31-hummingbird.dts18
-rw-r--r--arch/arm/boot/dts/sun6i-a31-i7.dts12
-rw-r--r--arch/arm/boot/dts/sun6i-a31-m9.dts12
-rw-r--r--arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts12
-rw-r--r--arch/arm/boot/dts/sun6i-a31.dtsi15
-rw-r--r--arch/arm/boot/dts/sun6i-a31s-cs908.dts11
-rw-r--r--arch/arm/boot/dts/sun6i-a31s-sina31s.dts12
-rw-r--r--arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts18
-rw-r--r--arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-bananapi.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-bananapro.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-cubieboard2.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-cubietruck.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-hummingbird.dts21
-rw-r--r--arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-icnova-swac.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-itead-ibox.dts4
-rw-r--r--arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts2
-rw-r--r--arch/arm/boot/dts/sun7i-a20-m3.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts20
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-orangepi.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-pcduino3.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts12
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi35
-rw-r--r--arch/arm/boot/dts/sun8i-a23-a33.dtsi3
-rw-r--r--arch/arm/boot/dts/sun8i-a23-q8-tablet.dts2
-rw-r--r--arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts25
-rw-r--r--arch/arm/boot/dts/sun8i-a83t.dtsi14
-rw-r--r--arch/arm/boot/dts/sun8i-r40.dtsi12
-rw-r--r--arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts53
-rw-r--r--arch/arm/boot/dts/sun8i-v3.dtsi14
-rw-r--r--arch/arm/boot/dts/sun8i-v3s.dtsi14
-rw-r--r--arch/arm/boot/dts/sun9i-a80-cubieboard4.dts12
-rw-r--r--arch/arm/boot/dts/sun9i-a80-optimus.dts4
-rw-r--r--arch/arm/boot/dts/sun9i-a80.dtsi10
-rw-r--r--arch/arm/boot/dts/sunxi-h3-h5.dtsi15
-rw-r--r--arch/arm/boot/dts/vexpress-v2m-rs1.dtsi1
-rw-r--r--arch/arm/boot/dts/vexpress-v2m.dtsi2
-rw-r--r--arch/arm/boot/dts/vf610-bk4.dts4
-rw-r--r--arch/arm/boot/dts/vf610-zii-cfu1.dts21
-rw-r--r--arch/arm/boot/dts/vf610-zii-scu4-aib.dts12
-rw-r--r--arch/arm/boot/dts/vf610-zii-spb4.dts7
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/configs/acs5k_defconfig77
-rw-r--r--arch/arm/configs/acs5k_tiny_defconfig69
-rw-r--r--arch/arm/configs/aspeed_g4_defconfig50
-rw-r--r--arch/arm/configs/aspeed_g5_defconfig68
-rw-r--r--arch/arm/configs/bcm2835_defconfig9
-rw-r--r--arch/arm/configs/davinci_all_defconfig5
-rw-r--r--arch/arm/configs/exynos_defconfig5
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig2
-rw-r--r--arch/arm/configs/iop13xx_defconfig118
-rw-r--r--arch/arm/configs/iop33x_defconfig85
-rw-r--r--arch/arm/configs/ks8695_defconfig67
-rw-r--r--arch/arm/configs/lpc32xx_defconfig2
-rw-r--r--arch/arm/configs/multi_v5_defconfig12
-rw-r--r--arch/arm/configs/multi_v7_defconfig27
-rw-r--r--arch/arm/configs/nuc910_defconfig51
-rw-r--r--arch/arm/configs/nuc950_defconfig67
-rw-r--r--arch/arm/configs/nuc960_defconfig57
-rw-r--r--arch/arm/configs/qcom_defconfig1
-rw-r--r--arch/arm/configs/u8500_defconfig34
-rw-r--r--arch/arm/include/asm/dma-mapping.h4
-rw-r--r--arch/arm/include/asm/topology.h20
-rw-r--r--arch/arm/include/debug/ks8695.S37
-rw-r--r--arch/arm/include/debug/renesas-scif.S6
-rw-r--r--arch/arm/include/debug/ux500.S9
-rw-r--r--arch/arm/kernel/hw_breakpoint.c5
-rw-r--r--arch/arm/kernel/signal.c1
-rw-r--r--arch/arm/kernel/smp.c6
-rw-r--r--arch/arm/kernel/topology.c60
-rw-r--r--arch/arm/kvm/coproc.c23
-rw-r--r--arch/arm/lib/backtrace.S2
-rw-r--r--arch/arm/mach-aspeed/Kconfig17
-rw-r--r--arch/arm/mach-aspeed/Makefile5
-rw-r--r--arch/arm/mach-aspeed/platsmp.c61
-rw-r--r--arch/arm/mach-at91/.gitignore1
-rw-r--r--arch/arm/mach-at91/Makefile5
-rw-r--r--arch/arm/mach-at91/pm_suspend.S2
-rw-r--r--arch/arm/mach-davinci/Kconfig17
-rw-r--r--arch/arm/mach-davinci/Makefile2
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c90
-rw-r--r--arch/arm/mach-davinci/da830.c45
-rw-r--r--arch/arm/mach-davinci/da850.c50
-rw-r--r--arch/arm/mach-davinci/davinci.h3
-rw-r--r--arch/arm/mach-davinci/dm355.c28
-rw-r--r--arch/arm/mach-davinci/dm365.c4
-rw-r--r--arch/arm/mach-davinci/dm644x.c28
-rw-r--r--arch/arm/mach-davinci/dm646x.c30
-rw-r--r--arch/arm/mach-davinci/include/mach/time.h2
-rw-r--r--arch/arm/mach-davinci/sleep.S1
-rw-r--r--arch/arm/mach-davinci/time.c14
-rw-r--r--arch/arm/mach-dove/bridge-regs.h (renamed from arch/arm/mach-dove/include/mach/bridge-regs.h)4
-rw-r--r--arch/arm/mach-dove/cm-a510.c3
-rw-r--r--arch/arm/mach-dove/common.c4
-rw-r--r--arch/arm/mach-dove/dove-db-setup.c2
-rw-r--r--arch/arm/mach-dove/dove.h (renamed from arch/arm/mach-dove/include/mach/dove.h)14
-rw-r--r--arch/arm/mach-dove/include/mach/hardware.h19
-rw-r--r--arch/arm/mach-dove/include/mach/uncompress.h8
-rw-r--r--arch/arm/mach-dove/irq.c5
-rw-r--r--arch/arm/mach-dove/irqs.h (renamed from arch/arm/mach-dove/include/mach/irqs.h)2
-rw-r--r--arch/arm/mach-dove/mpp.c2
-rw-r--r--arch/arm/mach-dove/pcie.c4
-rw-r--r--arch/arm/mach-dove/pm.h (renamed from arch/arm/mach-dove/include/mach/pm.h)4
-rw-r--r--arch/arm/mach-ep93xx/crunch.c1
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c2
-rw-r--r--arch/arm/mach-ep93xx/simone.c2
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c4
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c2
-rw-r--r--arch/arm/mach-exynos/Kconfig1
-rw-r--r--arch/arm/mach-imx/mach-imx7d.c6
-rw-r--r--arch/arm/mach-iop13xx/Kconfig21
-rw-r--r--arch/arm/mach-iop13xx/Makefile9
-rw-r--r--arch/arm/mach-iop13xx/Makefile.boot4
-rw-r--r--arch/arm/mach-iop13xx/include/mach/adma.h608
-rw-r--r--arch/arm/mach-iop13xx/include/mach/entry-macro.S29
-rw-r--r--arch/arm/mach-iop13xx/include/mach/hardware.h22
-rw-r--r--arch/arm/mach-iop13xx/include/mach/iop13xx.h508
-rw-r--r--arch/arm/mach-iop13xx/include/mach/iq81340.h29
-rw-r--r--arch/arm/mach-iop13xx/include/mach/irqs.h195
-rw-r--r--arch/arm/mach-iop13xx/include/mach/memory.h68
-rw-r--r--arch/arm/mach-iop13xx/include/mach/time.h127
-rw-r--r--arch/arm/mach-iop13xx/include/mach/uncompress.h23
-rw-r--r--arch/arm/mach-iop13xx/io.c77
-rw-r--r--arch/arm/mach-iop13xx/iq81340mc.c84
-rw-r--r--arch/arm/mach-iop13xx/iq81340sc.c86
-rw-r--r--arch/arm/mach-iop13xx/irq.c227
-rw-r--r--arch/arm/mach-iop13xx/msi.c152
-rw-r--r--arch/arm/mach-iop13xx/msi.h12
-rw-r--r--arch/arm/mach-iop13xx/pci.c1115
-rw-r--r--arch/arm/mach-iop13xx/pci.h66
-rw-r--r--arch/arm/mach-iop13xx/setup.c595
-rw-r--r--arch/arm/mach-iop13xx/tpmi.c244
-rw-r--r--arch/arm/mach-iop32x/Makefile10
-rw-r--r--arch/arm/mach-iop32x/adma.c (renamed from arch/arm/plat-iop/adma.c)39
-rw-r--r--arch/arm/mach-iop32x/cp6.c (renamed from arch/arm/plat-iop/cp6.c)0
-rw-r--r--arch/arm/mach-iop32x/em7210.c5
-rw-r--r--arch/arm/mach-iop32x/glantank.c5
-rw-r--r--arch/arm/mach-iop32x/glantank.h (renamed from arch/arm/mach-iop32x/include/mach/glantank.h)2
-rw-r--r--arch/arm/mach-iop32x/hardware.h (renamed from arch/arm/mach-iop32x/include/mach/hardware.h)6
-rw-r--r--arch/arm/mach-iop32x/i2c.c (renamed from arch/arm/plat-iop/i2c.c)21
-rw-r--r--arch/arm/mach-iop32x/include/mach/adma.h6
-rw-r--r--arch/arm/mach-iop32x/include/mach/entry-macro.S2
-rw-r--r--arch/arm/mach-iop32x/include/mach/iop32x.h31
-rw-r--r--arch/arm/mach-iop32x/include/mach/irqs.h33
-rw-r--r--arch/arm/mach-iop32x/include/mach/time.h5
-rw-r--r--arch/arm/mach-iop32x/include/mach/uncompress.h18
-rw-r--r--arch/arm/mach-iop32x/iop3xx.h (renamed from arch/arm/include/asm/hardware/iop3xx.h)18
-rw-r--r--arch/arm/mach-iop32x/iq31244.c5
-rw-r--r--arch/arm/mach-iop32x/iq31244.h (renamed from arch/arm/mach-iop32x/include/mach/iq31244.h)2
-rw-r--r--arch/arm/mach-iop32x/iq80321.c5
-rw-r--r--arch/arm/mach-iop32x/iq80321.h (renamed from arch/arm/mach-iop32x/include/mach/iq80321.h)2
-rw-r--r--arch/arm/mach-iop32x/irq.c3
-rw-r--r--arch/arm/mach-iop32x/irqs.h42
-rw-r--r--arch/arm/mach-iop32x/n2100.c5
-rw-r--r--arch/arm/mach-iop32x/n2100.h (renamed from arch/arm/mach-iop32x/include/mach/n2100.h)2
-rw-r--r--arch/arm/mach-iop32x/pci.c (renamed from arch/arm/plat-iop/pci.c)4
-rw-r--r--arch/arm/mach-iop32x/pmu.c (renamed from arch/arm/plat-iop/pmu.c)8
-rw-r--r--arch/arm/mach-iop32x/restart.c (renamed from arch/arm/plat-iop/restart.c)4
-rw-r--r--arch/arm/mach-iop32x/setup.c (renamed from arch/arm/plat-iop/setup.c)2
-rw-r--r--arch/arm/mach-iop32x/time.c (renamed from arch/arm/plat-iop/time.c)7
-rw-r--r--arch/arm/mach-iop33x/Kconfig22
-rw-r--r--arch/arm/mach-iop33x/Makefile9
-rw-r--r--arch/arm/mach-iop33x/Makefile.boot4
-rw-r--r--arch/arm/mach-iop33x/include/mach/adma.h6
-rw-r--r--arch/arm/mach-iop33x/include/mach/entry-macro.S34
-rw-r--r--arch/arm/mach-iop33x/include/mach/hardware.h44
-rw-r--r--arch/arm/mach-iop33x/include/mach/iop33x.h37
-rw-r--r--arch/arm/mach-iop33x/include/mach/iq80331.h17
-rw-r--r--arch/arm/mach-iop33x/include/mach/iq80332.h17
-rw-r--r--arch/arm/mach-iop33x/include/mach/irqs.h57
-rw-r--r--arch/arm/mach-iop33x/include/mach/time.h5
-rw-r--r--arch/arm/mach-iop33x/include/mach/uncompress.h37
-rw-r--r--arch/arm/mach-iop33x/iq80331.c148
-rw-r--r--arch/arm/mach-iop33x/iq80332.c148
-rw-r--r--arch/arm/mach-iop33x/irq.c115
-rw-r--r--arch/arm/mach-iop33x/uart.c100
-rw-r--r--arch/arm/mach-ks8695/Kconfig88
-rw-r--r--arch/arm/mach-ks8695/Makefile23
-rw-r--r--arch/arm/mach-ks8695/Makefile.boot9
-rw-r--r--arch/arm/mach-ks8695/board-acs5k.c238
-rw-r--r--arch/arm/mach-ks8695/board-dsm320.c127
-rw-r--r--arch/arm/mach-ks8695/board-micrel.c59
-rw-r--r--arch/arm/mach-ks8695/board-og.c197
-rw-r--r--arch/arm/mach-ks8695/board-sg.c118
-rw-r--r--arch/arm/mach-ks8695/cpu.c60
-rw-r--r--arch/arm/mach-ks8695/devices.c197
-rw-r--r--arch/arm/mach-ks8695/devices.h29
-rw-r--r--arch/arm/mach-ks8695/generic.h12
-rw-r--r--arch/arm/mach-ks8695/include/mach/entry-macro.S47
-rw-r--r--arch/arm/mach-ks8695/include/mach/gpio-ks8695.h36
-rw-r--r--arch/arm/mach-ks8695/include/mach/hardware.h42
-rw-r--r--arch/arm/mach-ks8695/include/mach/irqs.h51
-rw-r--r--arch/arm/mach-ks8695/include/mach/memory.h51
-rw-r--r--arch/arm/mach-ks8695/include/mach/regs-gpio.h55
-rw-r--r--arch/arm/mach-ks8695/include/mach/regs-irq.h41
-rw-r--r--arch/arm/mach-ks8695/include/mach/regs-misc.h97
-rw-r--r--arch/arm/mach-ks8695/include/mach/regs-switch.h66
-rw-r--r--arch/arm/mach-ks8695/include/mach/regs-uart.h89
-rw-r--r--arch/arm/mach-ks8695/include/mach/uncompress.h33
-rw-r--r--arch/arm/mach-ks8695/irq.c164
-rw-r--r--arch/arm/mach-ks8695/pci.c247
-rw-r--r--arch/arm/mach-ks8695/regs-hpna.h25
-rw-r--r--arch/arm/mach-ks8695/regs-lan.h65
-rw-r--r--arch/arm/mach-ks8695/regs-mem.h89
-rw-r--r--arch/arm/mach-ks8695/regs-pci.h53
-rw-r--r--arch/arm/mach-ks8695/regs-sys.h34
-rw-r--r--arch/arm/mach-ks8695/regs-wan.h65
-rw-r--r--arch/arm/mach-ks8695/time.c159
-rw-r--r--arch/arm/mach-lpc32xx/Kconfig11
-rw-r--r--arch/arm/mach-lpc32xx/common.c24
-rw-r--r--arch/arm/mach-lpc32xx/common.h1
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/board.h15
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/entry-macro.S28
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/hardware.h25
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/uncompress.h50
-rw-r--r--arch/arm/mach-lpc32xx/lpc32xx.h (renamed from arch/arm/mach-lpc32xx/include/mach/platform.h)18
-rw-r--r--arch/arm/mach-lpc32xx/pm.c3
-rw-r--r--arch/arm/mach-lpc32xx/serial.c33
-rw-r--r--arch/arm/mach-lpc32xx/suspend.S3
-rw-r--r--arch/arm/mach-mmp/regs-icu.h3
-rw-r--r--arch/arm/mach-mv78xx0/mv78xx0.h4
-rw-r--r--arch/arm/mach-netx/Kconfig22
-rw-r--r--arch/arm/mach-netx/Makefile13
-rw-r--r--arch/arm/mach-netx/fb.c65
-rw-r--r--arch/arm/mach-netx/fb.h12
-rw-r--r--arch/arm/mach-netx/generic.c182
-rw-r--r--arch/arm/mach-netx/generic.h14
-rw-r--r--arch/arm/mach-netx/include/mach/hardware.h27
-rw-r--r--arch/arm/mach-netx/include/mach/irqs.h58
-rw-r--r--arch/arm/mach-netx/include/mach/netx-regs.h420
-rw-r--r--arch/arm/mach-netx/include/mach/pfifo.h42
-rw-r--r--arch/arm/mach-netx/include/mach/uncompress.h63
-rw-r--r--arch/arm/mach-netx/include/mach/xc.h30
-rw-r--r--arch/arm/mach-netx/nxdb500.c197
-rw-r--r--arch/arm/mach-netx/nxdkn.c90
-rw-r--r--arch/arm/mach-netx/nxeb500hmi.c174
-rw-r--r--arch/arm/mach-netx/pfifo.c56
-rw-r--r--arch/arm/mach-netx/time.c141
-rw-r--r--arch/arm/mach-netx/xc.c246
-rw-r--r--arch/arm/mach-nspire/Makefile1
-rw-r--r--arch/arm/mach-nspire/clcd.c114
-rw-r--r--arch/arm/mach-nspire/clcd.h10
-rw-r--r--arch/arm/mach-nspire/nspire.c25
-rw-r--r--arch/arm/mach-omap1/ams-delta-fiq-handler.S3
-rw-r--r--arch/arm/mach-omap1/ams-delta-fiq.c4
-rw-r--r--arch/arm/mach-omap2/.gitignore1
-rw-r--r--arch/arm/mach-omap2/Makefile7
-rw-r--r--arch/arm/mach-omap2/hsmmc.c4
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c43
-rw-r--r--arch/arm/mach-omap2/omap4-common.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_7xx_data.c3
-rw-r--r--arch/arm/mach-omap2/sleep33xx.S2
-rw-r--r--arch/arm/mach-omap2/sleep43xx.S2
-rw-r--r--arch/arm/mach-orion5x/orion5x.h4
-rw-r--r--arch/arm/mach-rpc/riscpc.c1
-rw-r--r--arch/arm/mach-s3c64xx/setup-usb-phy.c5
-rw-r--r--arch/arm/mach-tegra/reset.c2
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c1
-rw-r--r--arch/arm/mach-vexpress/spc.c4
-rw-r--r--arch/arm/mach-w90x900/Kconfig50
-rw-r--r--arch/arm/mach-w90x900/Makefile20
-rw-r--r--arch/arm/mach-w90x900/Makefile.boot4
-rw-r--r--arch/arm/mach-w90x900/clksel.c88
-rw-r--r--arch/arm/mach-w90x900/clock.c121
-rw-r--r--arch/arm/mach-w90x900/clock.h40
-rw-r--r--arch/arm/mach-w90x900/cpu.c238
-rw-r--r--arch/arm/mach-w90x900/cpu.h56
-rw-r--r--arch/arm/mach-w90x900/dev.c537
-rw-r--r--arch/arm/mach-w90x900/gpio.c150
-rw-r--r--arch/arm/mach-w90x900/include/mach/entry-macro.S26
-rw-r--r--arch/arm/mach-w90x900/include/mach/hardware.h19
-rw-r--r--arch/arm/mach-w90x900/include/mach/irqs.h82
-rw-r--r--arch/arm/mach-w90x900/include/mach/map.h153
-rw-r--r--arch/arm/mach-w90x900/include/mach/mfp.h21
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-clock.h49
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-irq.h46
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-ldm.h248
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-serial.h54
-rw-r--r--arch/arm/mach-w90x900/include/mach/uncompress.h43
-rw-r--r--arch/arm/mach-w90x900/irq.c212
-rw-r--r--arch/arm/mach-w90x900/mach-nuc910evb.c38
-rw-r--r--arch/arm/mach-w90x900/mach-nuc950evb.c42
-rw-r--r--arch/arm/mach-w90x900/mach-nuc960evb.c38
-rw-r--r--arch/arm/mach-w90x900/mfp.c197
-rw-r--r--arch/arm/mach-w90x900/nuc910.c58
-rw-r--r--arch/arm/mach-w90x900/nuc910.h17
-rw-r--r--arch/arm/mach-w90x900/nuc950.c52
-rw-r--r--arch/arm/mach-w90x900/nuc950.h17
-rw-r--r--arch/arm/mach-w90x900/nuc960.c50
-rw-r--r--arch/arm/mach-w90x900/nuc960.h17
-rw-r--r--arch/arm/mach-w90x900/nuc9xx.h22
-rw-r--r--arch/arm/mach-w90x900/regs-ebi.h29
-rw-r--r--arch/arm/mach-w90x900/regs-gcr.h34
-rw-r--r--arch/arm/mach-w90x900/regs-timer.h37
-rw-r--r--arch/arm/mach-w90x900/regs-usb.h31
-rw-r--r--arch/arm/mach-w90x900/time.c168
-rw-r--r--arch/arm/mach-zynq/headsmp.S2
-rw-r--r--arch/arm/mach-zynq/platsmp.c4
-rw-r--r--arch/arm/mm/Kconfig3
-rw-r--r--arch/arm/mm/alignment.c4
-rw-r--r--arch/arm/mm/copypage-xscale.c6
-rw-r--r--arch/arm/mm/dma-mapping.c59
-rw-r--r--arch/arm/mm/init.c13
-rw-r--r--arch/arm/plat-iop/Makefile28
-rw-r--r--arch/arm/plat-omap/dma.c14
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-core.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/usb-phy.h2
-rw-r--r--arch/arm64/Kbuild6
-rw-r--r--arch/arm64/Kconfig43
-rw-r--r--arch/arm64/Kconfig.platforms2
-rw-r--r--arch/arm64/Makefile25
-rw-r--r--arch/arm64/boot/dts/allwinner/Makefile2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts23
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts4
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi29
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts27
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts72
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi4
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts4
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts100
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi135
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi18
-rw-r--r--arch/arm64/boot/dts/amlogic/Makefile4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg.dtsi8
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi2435
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts61
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts54
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts55
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a.dtsi2422
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts16
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi149
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi189
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts104
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts16
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi124
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b.dtsi39
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gx.dtsi35
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi11
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl.dtsi16
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm.dtsi4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi360
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts70
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts383
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1.dtsi147
-rw-r--r--arch/arm64/boot/dts/arm/fvp-base-revc.dts8
-rw-r--r--arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi2
-rw-r--r--arch/arm64/boot/dts/bitmain/bm1880.dtsi15
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile6
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts8
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts13
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi151
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts155
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts33
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi38
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi5
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi21
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-evk.dts68
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm.dtsi61
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts348
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn.dtsi758
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-evk.dts6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts256
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts405
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts413
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi309
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi46
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq.dtsi55
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts249
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-mek.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp.dtsi55
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_agilex.dtsi2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-37xx.dtsi7
-rw-r--r--arch/arm64/boot/dts/marvell/armada-7040-db.dts37
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts22
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-db.dts43
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi38
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi5
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap806.dtsi7
-rw-r--r--arch/arm64/boot/dts/marvell/armada-cp110.dtsi13
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-evb.dts96
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183.dtsi191
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile8
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts228
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi236
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi544
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts47
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi240
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts30
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts30
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi689
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150.dtsi97
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi86
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150l.dtsi80
-rw-r--r--arch/arm64/boot/dts/qcom/pm8998.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pms405.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404-evb.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404.dtsi60
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi12
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi646
-rw-r--r--arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts446
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-mtp.dts375
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi482
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-common.dtsi126
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi22
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774a1.dtsi342
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts37
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0.dtsi100
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts26
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi223
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts26
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts82
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795.dtsi156
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts10
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts10
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796.dtsi152
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965.dtsi50
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-eagle.dts58
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts116
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-condor.dts42
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts12
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts216
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990.dtsi48
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995-draak.dts24
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995.dtsi82
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-common.dtsi72
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf.dtsi226
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb.dtsi10
-rw-r--r--arch/arm64/boot/dts/rockchip/Makefile1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-rock64.dts11
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi17
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts645
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts21
-rw-r--r--arch/arm64/configs/defconfig22
-rw-r--r--arch/arm64/include/asm/arch_gicv3.h6
-rw-r--r--arch/arm64/include/asm/assembler.h28
-rw-r--r--arch/arm64/include/asm/atomic.h99
-rw-r--r--arch/arm64/include/asm/atomic_ll_sc.h217
-rw-r--r--arch/arm64/include/asm/atomic_lse.h395
-rw-r--r--arch/arm64/include/asm/cache.h2
-rw-r--r--arch/arm64/include/asm/cmpxchg.h45
-rw-r--r--arch/arm64/include/asm/compat.h2
-rw-r--r--arch/arm64/include/asm/cpu_ops.h3
-rw-r--r--arch/arm64/include/asm/cpufeature.h35
-rw-r--r--arch/arm64/include/asm/cputype.h21
-rw-r--r--arch/arm64/include/asm/daifflags.h2
-rw-r--r--arch/arm64/include/asm/debug-monitors.h3
-rw-r--r--arch/arm64/include/asm/dma-mapping.h3
-rw-r--r--arch/arm64/include/asm/efi.h10
-rw-r--r--arch/arm64/include/asm/elf.h2
-rw-r--r--arch/arm64/include/asm/esr.h3
-rw-r--r--arch/arm64/include/asm/exception.h2
-rw-r--r--arch/arm64/include/asm/fpsimd.h2
-rw-r--r--arch/arm64/include/asm/futex.h3
-rw-r--r--arch/arm64/include/asm/hw_breakpoint.h3
-rw-r--r--arch/arm64/include/asm/io.h10
-rw-r--r--arch/arm64/include/asm/irqflags.h5
-rw-r--r--arch/arm64/include/asm/kasan.h11
-rw-r--r--arch/arm64/include/asm/kvm_arm.h7
-rw-r--r--arch/arm64/include/asm/lse.h49
-rw-r--r--arch/arm64/include/asm/memory.h139
-rw-r--r--arch/arm64/include/asm/mmu.h2
-rw-r--r--arch/arm64/include/asm/mmu_context.h4
-rw-r--r--arch/arm64/include/asm/pci.h2
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h2
-rw-r--r--arch/arm64/include/asm/pgtable.h35
-rw-r--r--arch/arm64/include/asm/pointer_auth.h2
-rw-r--r--arch/arm64/include/asm/proc-fns.h2
-rw-r--r--arch/arm64/include/asm/processor.h29
-rw-r--r--arch/arm64/include/asm/ptrace.h7
-rw-r--r--arch/arm64/include/asm/signal32.h2
-rw-r--r--arch/arm64/include/asm/stacktrace.h78
-rw-r--r--arch/arm64/include/asm/sysreg.h32
-rw-r--r--arch/arm64/include/asm/thread_info.h29
-rw-r--r--arch/arm64/include/asm/tlbflush.h1
-rw-r--r--arch/arm64/include/asm/topology.h23
-rw-r--r--arch/arm64/include/asm/uaccess.h12
-rw-r--r--arch/arm64/include/asm/vdso.h4
-rw-r--r--arch/arm64/include/asm/vdso/compat_gettimeofday.h40
-rw-r--r--arch/arm64/include/asm/vdso_datapage.h4
-rw-r--r--arch/arm64/include/uapi/asm/bpf_perf_event.h2
-rw-r--r--arch/arm64/include/uapi/asm/stat.h17
-rw-r--r--arch/arm64/kernel/cpufeature.c24
-rw-r--r--arch/arm64/kernel/cpuidle.c50
-rw-r--r--arch/arm64/kernel/cpuinfo.c2
-rw-r--r--arch/arm64/kernel/debug-monitors.c14
-rw-r--r--arch/arm64/kernel/entry.S58
-rw-r--r--arch/arm64/kernel/fpsimd.c29
-rw-r--r--arch/arm64/kernel/ftrace.c22
-rw-r--r--arch/arm64/kernel/head.S116
-rw-r--r--arch/arm64/kernel/hibernate-asm.S8
-rw-r--r--arch/arm64/kernel/hibernate.c2
-rw-r--r--arch/arm64/kernel/hw_breakpoint.c11
-rw-r--r--arch/arm64/kernel/image-vars.h51
-rw-r--r--arch/arm64/kernel/image.h42
-rw-r--r--arch/arm64/kernel/insn.c2
-rw-r--r--arch/arm64/kernel/kaslr.c11
-rw-r--r--arch/arm64/kernel/kexec_image.c2
-rw-r--r--arch/arm64/kernel/machine_kexec_file.c22
-rw-r--r--arch/arm64/kernel/module-plts.c2
-rw-r--r--arch/arm64/kernel/module.c4
-rw-r--r--arch/arm64/kernel/perf_callchain.c7
-rw-r--r--arch/arm64/kernel/perf_event.c2
-rw-r--r--arch/arm64/kernel/probes/kprobes.c40
-rw-r--r--arch/arm64/kernel/process.c112
-rw-r--r--arch/arm64/kernel/psci.c10
-rw-r--r--arch/arm64/kernel/ptrace.c2
-rw-r--r--arch/arm64/kernel/return_address.c12
-rw-r--r--arch/arm64/kernel/setup.c20
-rw-r--r--arch/arm64/kernel/smp.c6
-rw-r--r--arch/arm64/kernel/smp_spin_table.c2
-rw-r--r--arch/arm64/kernel/stacktrace.c62
-rw-r--r--arch/arm64/kernel/time.c7
-rw-r--r--arch/arm64/kernel/topology.c312
-rw-r--r--arch/arm64/kernel/traps.c34
-rw-r--r--arch/arm64/kernel/vdso/Makefile13
-rw-r--r--arch/arm64/kernel/vdso32/Makefile14
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S11
-rw-r--r--arch/arm64/kvm/hyp/debug-sr.c30
-rw-r--r--arch/arm64/kvm/hyp/switch.c2
-rw-r--r--arch/arm64/kvm/regmap.c5
-rw-r--r--arch/arm64/kvm/sys_regs.c32
-rw-r--r--arch/arm64/kvm/va_layout.c14
-rw-r--r--arch/arm64/lib/Makefile21
-rw-r--r--arch/arm64/lib/atomic_ll_sc.c3
-rw-r--r--arch/arm64/lib/error-inject.c18
-rw-r--r--arch/arm64/mm/dma-mapping.c4
-rw-r--r--arch/arm64/mm/dump.c24
-rw-r--r--arch/arm64/mm/fault.c101
-rw-r--r--arch/arm64/mm/init.c35
-rw-r--r--arch/arm64/mm/ioremap.c4
-rw-r--r--arch/arm64/mm/kasan_init.c9
-rw-r--r--arch/arm64/mm/mmu.c32
-rw-r--r--arch/arm64/mm/numa.c2
-rw-r--r--arch/arm64/mm/pageattr.c2
-rw-r--r--arch/arm64/mm/proc.S20
-rw-r--r--arch/csky/include/uapi/asm/byteorder.h2
-rw-r--r--arch/csky/include/uapi/asm/cachectl.h2
-rw-r--r--arch/csky/include/uapi/asm/perf_regs.h2
-rw-r--r--arch/csky/include/uapi/asm/ptrace.h2
-rw-r--r--arch/csky/include/uapi/asm/sigcontext.h2
-rw-r--r--arch/csky/include/uapi/asm/unistd.h2
-rw-r--r--arch/ia64/Kconfig142
-rw-r--r--arch/ia64/Kconfig.debug2
-rw-r--r--arch/ia64/Makefile36
-rw-r--r--arch/ia64/configs/bigsur_defconfig1
-rw-r--r--arch/ia64/configs/generic_defconfig8
-rw-r--r--arch/ia64/configs/gensparse_defconfig10
-rw-r--r--arch/ia64/configs/sim_defconfig52
-rw-r--r--arch/ia64/configs/tiger_defconfig1
-rw-r--r--arch/ia64/configs/zx1_defconfig1
-rw-r--r--arch/ia64/dig/Makefile15
-rw-r--r--arch/ia64/dig/machvec.c3
-rw-r--r--arch/ia64/dig/machvec_vtd.c3
-rw-r--r--arch/ia64/dig/setup.c71
-rw-r--r--arch/ia64/hp/common/Makefile4
-rw-r--r--arch/ia64/hp/common/hwsw_iommu.c60
-rw-r--r--arch/ia64/hp/common/sba_iommu.c105
-rw-r--r--arch/ia64/hp/sim/Kconfig23
-rw-r--r--arch/ia64/hp/sim/Makefile17
-rw-r--r--arch/ia64/hp/sim/boot/Makefile37
-rw-r--r--arch/ia64/hp/sim/boot/boot_head.S165
-rw-r--r--arch/ia64/hp/sim/boot/bootloader.c175
-rw-r--r--arch/ia64/hp/sim/boot/bootloader.lds67
-rw-r--r--arch/ia64/hp/sim/boot/fw-emu.c374
-rw-r--r--arch/ia64/hp/sim/boot/ssc.h36
-rw-r--r--arch/ia64/hp/sim/hpsim.S11
-rw-r--r--arch/ia64/hp/sim/hpsim_console.c77
-rw-r--r--arch/ia64/hp/sim/hpsim_irq.c76
-rw-r--r--arch/ia64/hp/sim/hpsim_machvec.c3
-rw-r--r--arch/ia64/hp/sim/hpsim_setup.c41
-rw-r--r--arch/ia64/hp/sim/hpsim_ssc.h37
-rw-r--r--arch/ia64/hp/sim/simeth.c510
-rw-r--r--arch/ia64/hp/sim/simscsi.c373
-rw-r--r--arch/ia64/hp/sim/simserial.c521
-rw-r--r--arch/ia64/hp/zx1/Makefile9
-rw-r--r--arch/ia64/hp/zx1/hpzx1_machvec.c3
-rw-r--r--arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c3
-rw-r--r--arch/ia64/include/asm/acpi.h28
-rw-r--r--arch/ia64/include/asm/dma-mapping.h8
-rw-r--r--arch/ia64/include/asm/dma.h6
-rw-r--r--arch/ia64/include/asm/hpsim.h17
-rw-r--r--arch/ia64/include/asm/hw_irq.h27
-rw-r--r--arch/ia64/include/asm/io.h222
-rw-r--r--arch/ia64/include/asm/iommu.h3
-rw-r--r--arch/ia64/include/asm/iosapic.h12
-rw-r--r--arch/ia64/include/asm/irq.h3
-rw-r--r--arch/ia64/include/asm/machvec.h347
-rw-r--r--arch/ia64/include/asm/machvec_dig.h17
-rw-r--r--arch/ia64/include/asm/machvec_dig_vtd.h19
-rw-r--r--arch/ia64/include/asm/machvec_hpsim.h19
-rw-r--r--arch/ia64/include/asm/machvec_hpzx1.h19
-rw-r--r--arch/ia64/include/asm/machvec_hpzx1_swiotlb.h20
-rw-r--r--arch/ia64/include/asm/machvec_init.h35
-rw-r--r--arch/ia64/include/asm/machvec_sn2.h114
-rw-r--r--arch/ia64/include/asm/machvec_uv.h26
-rw-r--r--arch/ia64/include/asm/mmiowb.h12
-rw-r--r--arch/ia64/include/asm/mmzone.h13
-rw-r--r--arch/ia64/include/asm/pci.h9
-rw-r--r--arch/ia64/include/asm/processor.h2
-rw-r--r--arch/ia64/include/asm/sal.h1
-rw-r--r--arch/ia64/include/asm/sn/acpi.h15
-rw-r--r--arch/ia64/include/asm/sn/addrs.h299
-rw-r--r--arch/ia64/include/asm/sn/arch.h86
-rw-r--r--arch/ia64/include/asm/sn/bte.h236
-rw-r--r--arch/ia64/include/asm/sn/clksupport.h28
-rw-r--r--arch/ia64/include/asm/sn/geo.h132
-rw-r--r--arch/ia64/include/asm/sn/intr.h53
-rw-r--r--arch/ia64/include/asm/sn/io.h274
-rw-r--r--arch/ia64/include/asm/sn/ioc3.h242
-rw-r--r--arch/ia64/include/asm/sn/klconfig.h246
-rw-r--r--arch/ia64/include/asm/sn/l1.h51
-rw-r--r--arch/ia64/include/asm/sn/leds.h33
-rw-r--r--arch/ia64/include/asm/sn/module.h127
-rw-r--r--arch/ia64/include/asm/sn/mspec.h59
-rw-r--r--arch/ia64/include/asm/sn/nodepda.h82
-rw-r--r--arch/ia64/include/asm/sn/pcibr_provider.h150
-rw-r--r--arch/ia64/include/asm/sn/pcibus_provider_defs.h68
-rw-r--r--arch/ia64/include/asm/sn/pcidev.h85
-rw-r--r--arch/ia64/include/asm/sn/pda.h68
-rw-r--r--arch/ia64/include/asm/sn/pic.h261
-rw-r--r--arch/ia64/include/asm/sn/rw_mmr.h28
-rw-r--r--arch/ia64/include/asm/sn/shub_mmr.h502
-rw-r--r--arch/ia64/include/asm/sn/shubio.h3358
-rw-r--r--arch/ia64/include/asm/sn/simulator.h25
-rw-r--r--arch/ia64/include/asm/sn/sn2/sn_hwperf.h242
-rw-r--r--arch/ia64/include/asm/sn/sn_cpuid.h132
-rw-r--r--arch/ia64/include/asm/sn/sn_feature_sets.h58
-rw-r--r--arch/ia64/include/asm/sn/sn_sal.h1111
-rw-r--r--arch/ia64/include/asm/sn/tioca.h596
-rw-r--r--arch/ia64/include/asm/sn/tioca_provider.h207
-rw-r--r--arch/ia64/include/asm/sn/tioce.h760
-rw-r--r--arch/ia64/include/asm/sn/tioce_provider.h63
-rw-r--r--arch/ia64/include/asm/sn/tiocp.h257
-rw-r--r--arch/ia64/include/asm/sn/tiocx.h72
-rw-r--r--arch/ia64/include/asm/sn/types.h26
-rw-r--r--arch/ia64/include/asm/switch_to.h1
-rw-r--r--arch/ia64/include/asm/tlb.h1
-rw-r--r--arch/ia64/include/asm/uv/uv.h23
-rw-r--r--arch/ia64/kernel/Makefile9
-rw-r--r--arch/ia64/kernel/acpi.c81
-rw-r--r--arch/ia64/kernel/dma-mapping.c14
-rw-r--r--arch/ia64/kernel/efi.c3
-rw-r--r--arch/ia64/kernel/iosapic.c8
-rw-r--r--arch/ia64/kernel/irq.c23
-rw-r--r--arch/ia64/kernel/irq_ia64.c11
-rw-r--r--arch/ia64/kernel/kprobes.c26
-rw-r--r--arch/ia64/kernel/machine_kexec.c1
-rw-r--r--arch/ia64/kernel/machvec.c77
-rw-r--r--arch/ia64/kernel/mca.c29
-rw-r--r--arch/ia64/kernel/mca_drv.c1
-rw-r--r--arch/ia64/kernel/module.c8
-rw-r--r--arch/ia64/kernel/msi_ia64.c21
-rw-r--r--arch/ia64/kernel/pci-dma.c24
-rw-r--r--arch/ia64/kernel/sal.c9
-rw-r--r--arch/ia64/kernel/setup.c98
-rw-r--r--arch/ia64/kernel/signal.c10
-rw-r--r--arch/ia64/kernel/smp.c9
-rw-r--r--arch/ia64/kernel/smpboot.c9
-rw-r--r--arch/ia64/kernel/sys_ia64.c18
-rw-r--r--arch/ia64/kernel/time.c3
-rw-r--r--arch/ia64/kernel/topology.c4
-rw-r--r--arch/ia64/kernel/unaligned.c6
-rw-r--r--arch/ia64/kernel/uncached.c6
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S10
-rw-r--r--arch/ia64/lib/io.c114
-rw-r--r--arch/ia64/mm/discontig.c3
-rw-r--r--arch/ia64/mm/init.c19
-rw-r--r--arch/ia64/mm/tlb.c6
-rw-r--r--arch/ia64/pci/fixup.c6
-rw-r--r--arch/ia64/pci/pci.c14
-rw-r--r--arch/ia64/sn/Makefile12
-rw-r--r--arch/ia64/sn/include/ioerror.h81
-rw-r--r--arch/ia64/sn/include/tio.h41
-rw-r--r--arch/ia64/sn/include/xtalk/hubdev.h91
-rw-r--r--arch/ia64/sn/include/xtalk/xbow.h301
-rw-r--r--arch/ia64/sn/include/xtalk/xwidgetdev.h70
-rw-r--r--arch/ia64/sn/kernel/Makefile18
-rw-r--r--arch/ia64/sn/kernel/bte.c475
-rw-r--r--arch/ia64/sn/kernel/bte_error.c255
-rw-r--r--arch/ia64/sn/kernel/huberror.c220
-rw-r--r--arch/ia64/sn/kernel/idle.c30
-rw-r--r--arch/ia64/sn/kernel/io_acpi_init.c513
-rw-r--r--arch/ia64/sn/kernel/io_common.c561
-rw-r--r--arch/ia64/sn/kernel/io_init.c308
-rw-r--r--arch/ia64/sn/kernel/iomv.c82
-rw-r--r--arch/ia64/sn/kernel/irq.c489
-rw-r--r--arch/ia64/sn/kernel/klconflib.c107
-rw-r--r--arch/ia64/sn/kernel/machvec.c11
-rw-r--r--arch/ia64/sn/kernel/mca.c144
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c238
-rw-r--r--arch/ia64/sn/kernel/pio_phys.S71
-rw-r--r--arch/ia64/sn/kernel/setup.c786
-rw-r--r--arch/ia64/sn/kernel/sn2/Makefile13
-rw-r--r--arch/ia64/sn/kernel/sn2/cache.c41
-rw-r--r--arch/ia64/sn/kernel/sn2/io.c101
-rw-r--r--arch/ia64/sn/kernel/sn2/prominfo_proc.c207
-rw-r--r--arch/ia64/sn/kernel/sn2/ptc_deadlock.S92
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c577
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c1004
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c69
-rw-r--r--arch/ia64/sn/kernel/sn2/timer.c61
-rw-r--r--arch/ia64/sn/kernel/sn2/timer_interrupt.c60
-rw-r--r--arch/ia64/sn/kernel/tiocx.c569
-rw-r--r--arch/ia64/sn/pci/Makefile10
-rw-r--r--arch/ia64/sn/pci/pci_dma.c446
-rw-r--r--arch/ia64/sn/pci/pcibr/Makefile13
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_ate.c177
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c413
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c265
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_reg.c285
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c677
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c1062
-rw-r--r--arch/ia64/uv/kernel/Makefile1
-rw-r--r--arch/ia64/uv/kernel/machvec.c11
-rw-r--r--arch/ia64/uv/kernel/setup.c74
-rw-r--r--arch/m68k/atari/config.c6
-rw-r--r--arch/m68k/configs/amiga_defconfig13
-rw-r--r--arch/m68k/configs/apollo_defconfig13
-rw-r--r--arch/m68k/configs/atari_defconfig13
-rw-r--r--arch/m68k/configs/bvme6000_defconfig13
-rw-r--r--arch/m68k/configs/hp300_defconfig13
-rw-r--r--arch/m68k/configs/mac_defconfig13
-rw-r--r--arch/m68k/configs/multi_defconfig13
-rw-r--r--arch/m68k/configs/mvme147_defconfig13
-rw-r--r--arch/m68k/configs/mvme16x_defconfig13
-rw-r--r--arch/m68k/configs/q40_defconfig13
-rw-r--r--arch/m68k/configs/sun3_defconfig13
-rw-r--r--arch/m68k/configs/sun3x_defconfig13
-rw-r--r--arch/m68k/include/asm/atarihw.h13
-rw-r--r--arch/m68k/include/asm/io_mm.h6
-rw-r--r--arch/m68k/include/asm/kmap.h17
-rw-r--r--arch/m68k/include/asm/macintosh.h11
-rw-r--r--arch/m68k/mac/config.c128
-rw-r--r--arch/mips/cavium-octeon/octeon-usb.c1
-rw-r--r--arch/mips/configs/bigsur_defconfig1
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/markeins_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/sb1250_swarm_defconfig1
-rw-r--r--arch/mips/include/asm/octeon/cvmx-sli-defs.h1
-rw-r--r--arch/mips/kernel/cacheinfo.c2
-rw-r--r--arch/mips/kernel/i8253.c3
-rw-r--r--arch/mips/kvm/emulate.c1
-rw-r--r--arch/mips/kvm/mips.c10
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c13
-rw-r--r--arch/mips/pci/ops-bcm63xx.c1
-rw-r--r--arch/mips/vdso/vdso.h1
-rw-r--r--arch/nds32/include/uapi/asm/auxvec.h2
-rw-r--r--arch/nds32/include/uapi/asm/byteorder.h2
-rw-r--r--arch/nds32/include/uapi/asm/cachectl.h2
-rw-r--r--arch/nds32/include/uapi/asm/fp_udfiex_crtl.h2
-rw-r--r--arch/nds32/include/uapi/asm/param.h2
-rw-r--r--arch/nds32/include/uapi/asm/ptrace.h2
-rw-r--r--arch/nds32/include/uapi/asm/sigcontext.h2
-rw-r--r--arch/nds32/include/uapi/asm/unistd.h2
-rw-r--r--arch/nds32/kernel/signal.c2
-rw-r--r--arch/parisc/Kconfig25
-rw-r--r--arch/parisc/Makefile5
-rw-r--r--arch/parisc/boot/compressed/.gitignore2
-rw-r--r--arch/parisc/boot/compressed/Makefile4
-rw-r--r--arch/parisc/boot/compressed/vmlinux.lds.S4
-rw-r--r--arch/parisc/configs/defconfig (renamed from arch/parisc/configs/default_defconfig)0
-rw-r--r--arch/parisc/include/asm/alternative.h11
-rw-r--r--arch/parisc/include/asm/fixmap.h1
-rw-r--r--arch/parisc/include/asm/ftrace.h1
-rw-r--r--arch/parisc/include/asm/kexec.h37
-rw-r--r--arch/parisc/include/asm/pdc.h1
-rw-r--r--arch/parisc/include/asm/pgtable.h3
-rw-r--r--arch/parisc/include/asm/string.h15
-rw-r--r--arch/parisc/kernel/Makefile2
-rw-r--r--arch/parisc/kernel/alternative.c23
-rw-r--r--arch/parisc/kernel/entry.S99
-rw-r--r--arch/parisc/kernel/firmware.c13
-rw-r--r--arch/parisc/kernel/ftrace.c67
-rw-r--r--arch/parisc/kernel/kexec.c112
-rw-r--r--arch/parisc/kernel/kexec_file.c86
-rw-r--r--arch/parisc/kernel/kprobes.c4
-rw-r--r--arch/parisc/kernel/pacache.S9
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c4
-rw-r--r--arch/parisc/kernel/pci.c11
-rw-r--r--arch/parisc/kernel/relocate_kernel.S149
-rw-r--r--arch/parisc/kernel/smp.c1
-rw-r--r--arch/parisc/kernel/syscalls/syscall.tbl3
-rw-r--r--arch/parisc/kernel/traps.c2
-rw-r--r--arch/parisc/lib/Makefile4
-rw-r--r--arch/parisc/lib/memset.c91
-rw-r--r--arch/parisc/lib/string.S136
-rw-r--r--arch/parisc/math-emu/Makefile1
-rw-r--r--arch/parisc/mm/fault.c1
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/Makefile2
-rw-r--r--arch/powerpc/include/asm/cache.h8
-rw-r--r--arch/powerpc/include/asm/error-injection.h13
-rw-r--r--arch/powerpc/include/asm/hvcall.h11
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h2
-rw-r--r--arch/powerpc/include/asm/pmc.h5
-rw-r--r--arch/powerpc/include/asm/unistd.h1
-rw-r--r--arch/powerpc/include/uapi/asm/bpf_perf_event.h2
-rw-r--r--arch/powerpc/include/uapi/asm/kvm_para.h2
-rw-r--r--arch/powerpc/kernel/align.c4
-rw-r--r--arch/powerpc/kernel/entry_32.S8
-rw-r--r--arch/powerpc/kernel/entry_64.S5
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S2
-rw-r--r--arch/powerpc/kernel/kexec_elf_64.c545
-rw-r--r--arch/powerpc/kernel/process.c21
-rw-r--r--arch/powerpc/kernel/signal_32.c3
-rw-r--r--arch/powerpc/kernel/signal_64.c5
-rw-r--r--arch/powerpc/kernel/syscalls/syscall.tbl2
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu.c1
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c6
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c6
-rw-r--r--arch/powerpc/kvm/book3s_hv.c13
-rw-r--r--arch/powerpc/kvm/book3s_xive.c4
-rw-r--r--arch/powerpc/kvm/book3s_xive_native.c4
-rw-r--r--arch/powerpc/kvm/powerpc.c15
-rw-r--r--arch/powerpc/mm/book3s64/hash_utils.c9
-rw-r--r--arch/powerpc/mm/kasan/kasan_init_32.c7
-rw-r--r--arch/powerpc/mm/mem.c2
-rw-r--r--arch/powerpc/mm/nohash/tlb.c1
-rw-r--r--arch/powerpc/platforms/pseries/papr_scm.c73
-rw-r--r--arch/powerpc/sysdev/xive/common.c7
-rw-r--r--arch/riscv/Kbuild (renamed from arch/arm/mach-netx/Makefile.boot)2
-rw-r--r--arch/riscv/Kconfig24
-rw-r--r--arch/riscv/Makefile5
-rw-r--r--arch/riscv/boot/dts/sifive/fu540-c000.dtsi16
-rw-r--r--arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts9
-rw-r--r--arch/riscv/configs/defconfig12
-rw-r--r--arch/riscv/configs/rv32_defconfig3
-rw-r--r--arch/riscv/include/asm/Kbuild1
-rw-r--r--arch/riscv/include/asm/fixmap.h4
-rw-r--r--arch/riscv/include/asm/image.h12
-rw-r--r--arch/riscv/include/asm/page.h2
-rw-r--r--arch/riscv/include/asm/pgtable.h25
-rw-r--r--arch/riscv/include/asm/smp.h6
-rw-r--r--arch/riscv/include/asm/sparsemem.h11
-rw-r--r--arch/riscv/include/asm/switch_to.h8
-rw-r--r--arch/riscv/include/asm/timex.h44
-rw-r--r--arch/riscv/include/asm/tlbflush.h31
-rw-r--r--arch/riscv/include/uapi/asm/auxvec.h2
-rw-r--r--arch/riscv/include/uapi/asm/bitsperlong.h2
-rw-r--r--arch/riscv/include/uapi/asm/byteorder.h2
-rw-r--r--arch/riscv/include/uapi/asm/hwcap.h2
-rw-r--r--arch/riscv/include/uapi/asm/perf_regs.h42
-rw-r--r--arch/riscv/include/uapi/asm/ptrace.h2
-rw-r--r--arch/riscv/include/uapi/asm/sigcontext.h2
-rw-r--r--arch/riscv/include/uapi/asm/ucontext.h2
-rw-r--r--arch/riscv/include/uapi/asm/unistd.h1
-rw-r--r--arch/riscv/kernel/Makefile4
-rw-r--r--arch/riscv/kernel/entry.S6
-rw-r--r--arch/riscv/kernel/fpu.S8
-rw-r--r--arch/riscv/kernel/head.S6
-rw-r--r--arch/riscv/kernel/perf_callchain.c94
-rw-r--r--arch/riscv/kernel/perf_regs.c44
-rw-r--r--arch/riscv/kernel/process.c11
-rw-r--r--arch/riscv/kernel/smp.c60
-rw-r--r--arch/riscv/kernel/smpboot.c3
-rw-r--r--arch/riscv/kernel/stacktrace.c4
-rw-r--r--arch/riscv/kernel/vdso/Makefile2
-rw-r--r--arch/riscv/lib/Makefile2
-rw-r--r--arch/riscv/lib/delay.c6
-rw-r--r--arch/riscv/lib/uaccess.S12
-rw-r--r--arch/riscv/lib/udivdi3.S32
-rw-r--r--arch/riscv/mm/Makefile3
-rw-r--r--arch/riscv/mm/cacheflush.c1
-rw-r--r--arch/riscv/mm/context.c7
-rw-r--r--arch/riscv/mm/init.c12
-rw-r--r--arch/riscv/mm/tlbflush.c35
-rw-r--r--arch/s390/boot/Makefile2
-rw-r--r--arch/s390/boot/boot.h2
-rw-r--r--arch/s390/boot/head.S1
-rw-r--r--arch/s390/boot/ipl_parm.c2
-rw-r--r--arch/s390/boot/kaslr.c1
-rw-r--r--arch/s390/boot/version.c7
-rw-r--r--arch/s390/configs/debug_defconfig330
-rw-r--r--arch/s390/configs/defconfig233
-rw-r--r--arch/s390/configs/zfcpdump_defconfig31
-rw-r--r--arch/s390/hypfs/hypfs_vm.c4
-rw-r--r--arch/s390/include/asm/bitops.h73
-rw-r--r--arch/s390/include/asm/page.h2
-rw-r--r--arch/s390/include/asm/qdio.h10
-rw-r--r--arch/s390/include/asm/setup.h5
-rw-r--r--arch/s390/include/asm/unistd.h1
-rw-r--r--arch/s390/include/uapi/asm/bpf_perf_event.h2
-rw-r--r--arch/s390/include/uapi/asm/ipl.h2
-rw-r--r--arch/s390/include/uapi/asm/zcrypt.h35
-rw-r--r--arch/s390/kernel/dumpstack.c6
-rw-r--r--arch/s390/kernel/head64.S7
-rw-r--r--arch/s390/kernel/ipl.c9
-rw-r--r--arch/s390/kernel/machine_kexec_reloc.c1
-rw-r--r--arch/s390/kernel/perf_cpum_cf_diag.c2
-rw-r--r--arch/s390/kernel/setup.c3
-rw-r--r--arch/s390/kernel/syscalls/syscall.tbl2
-rw-r--r--arch/s390/kernel/vdso.c5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S10
-rw-r--r--arch/s390/kvm/interrupt.c10
-rw-r--r--arch/s390/kvm/kvm-s390.c14
-rw-r--r--arch/s390/lib/xor.c1
-rw-r--r--arch/s390/mm/dump_pagetables.c12
-rw-r--r--arch/s390/mm/fault.c3
-rw-r--r--arch/s390/mm/gmap.c4
-rw-r--r--arch/s390/mm/pgalloc.c6
-rw-r--r--arch/s390/net/bpf_jit_comp.c12
-rw-r--r--arch/s390/scripts/Makefile.chkbss3
-rw-r--r--arch/sh/include/uapi/asm/setup.h2
-rw-r--r--arch/sh/include/uapi/asm/types.h2
-rw-r--r--arch/sh/kernel/disassemble.c5
-rw-r--r--arch/sh/kernel/hw_breakpoint.c1
-rw-r--r--arch/sparc/include/uapi/asm/oradax.h2
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c33
-rw-r--r--arch/um/include/shared/timer-internal.h14
-rw-r--r--arch/um/kernel/process.c2
-rw-r--r--arch/um/kernel/time.c16
-rw-r--r--arch/unicore32/kernel/irq.c1
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/Kconfig.debug2
-rw-r--r--arch/x86/Makefile1
-rw-r--r--arch/x86/boot/boot.h2
-rw-r--r--arch/x86/boot/compressed/head_32.S4
-rw-r--r--arch/x86/boot/compressed/head_64.S18
-rw-r--r--arch/x86/boot/compressed/pgtable_64.c13
-rw-r--r--arch/x86/boot/main.c1
-rw-r--r--arch/x86/boot/string.c8
-rw-r--r--arch/x86/entry/calling.h17
-rw-r--r--arch/x86/entry/common.c13
-rw-r--r--arch/x86/entry/entry_32.S19
-rw-r--r--arch/x86/entry/entry_64.S29
-rw-r--r--arch/x86/entry/syscall_64.c25
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl4
-rw-r--r--arch/x86/entry/syscalls/syscalltbl.sh35
-rw-r--r--arch/x86/entry/thunk_32.S2
-rw-r--r--arch/x86/entry/thunk_64.S4
-rw-r--r--arch/x86/events/amd/ibs.c13
-rw-r--r--arch/x86/events/core.c38
-rw-r--r--arch/x86/events/intel/core.c107
-rw-r--r--arch/x86/events/intel/cstate.c44
-rw-r--r--arch/x86/events/intel/ds.c53
-rw-r--r--arch/x86/events/intel/lbr.c2
-rw-r--r--arch/x86/events/intel/pt.c336
-rw-r--r--arch/x86/events/intel/pt.h12
-rw-r--r--arch/x86/events/intel/rapl.c30
-rw-r--r--arch/x86/events/intel/uncore.c28
-rw-r--r--arch/x86/events/msr.c28
-rw-r--r--arch/x86/events/perf_event.h17
-rw-r--r--arch/x86/hyperv/hv_init.c14
-rw-r--r--arch/x86/hyperv/mmu.c8
-rw-r--r--arch/x86/include/asm/apic.h11
-rw-r--r--arch/x86/include/asm/apic_flat_64.h8
-rw-r--r--arch/x86/include/asm/barrier.h3
-rw-r--r--arch/x86/include/asm/bitops.h7
-rw-r--r--arch/x86/include/asm/bootparam_utils.h64
-rw-r--r--arch/x86/include/asm/bugs.h2
-rw-r--r--arch/x86/include/asm/cpufeature.h7
-rw-r--r--arch/x86/include/asm/cpufeatures.h7
-rw-r--r--arch/x86/include/asm/div64.h13
-rw-r--r--arch/x86/include/asm/efi.h5
-rw-r--r--arch/x86/include/asm/error-injection.h13
-rw-r--r--arch/x86/include/asm/fixmap.h5
-rw-r--r--arch/x86/include/asm/ftrace.h1
-rw-r--r--arch/x86/include/asm/hw_irq.h4
-rw-r--r--arch/x86/include/asm/hyperv-tlfs.h12
-rw-r--r--arch/x86/include/asm/intel-family.h69
-rw-r--r--arch/x86/include/asm/intel_pt.h2
-rw-r--r--arch/x86/include/asm/iommu.h1
-rw-r--r--arch/x86/include/asm/ipi.h109
-rw-r--r--arch/x86/include/asm/irq.h2
-rw-r--r--arch/x86/include/asm/kvm_host.h12
-rw-r--r--arch/x86/include/asm/mmu_context.h8
-rw-r--r--arch/x86/include/asm/mshyperv.h5
-rw-r--r--arch/x86/include/asm/msr-index.h16
-rw-r--r--arch/x86/include/asm/msr.h3
-rw-r--r--arch/x86/include/asm/nospec-branch.h2
-rw-r--r--arch/x86/include/asm/paravirt.h12
-rw-r--r--arch/x86/include/asm/paravirt_types.h5
-rw-r--r--arch/x86/include/asm/perf_event.h12
-rw-r--r--arch/x86/include/asm/preempt.h2
-rw-r--r--arch/x86/include/asm/qspinlock.h15
-rw-r--r--arch/x86/include/asm/realmode.h1
-rw-r--r--arch/x86/include/asm/set_memory.h8
-rw-r--r--arch/x86/include/asm/smp.h1
-rw-r--r--arch/x86/include/asm/special_insns.h24
-rw-r--r--arch/x86/include/asm/suspend_64.h2
-rw-r--r--arch/x86/include/asm/syscall.h4
-rw-r--r--arch/x86/include/asm/text-patching.h4
-rw-r--r--arch/x86/include/asm/tlbflush.h30
-rw-r--r--arch/x86/include/asm/uaccess.h4
-rw-r--r--arch/x86/include/asm/unistd.h6
-rw-r--r--arch/x86/include/asm/uv/uv.h4
-rw-r--r--arch/x86/include/asm/vdso/gettimeofday.h36
-rw-r--r--arch/x86/include/asm/vmware.h53
-rw-r--r--arch/x86/include/uapi/asm/byteorder.h2
-rw-r--r--arch/x86/include/uapi/asm/errno.h1
-rw-r--r--arch/x86/include/uapi/asm/fcntl.h1
-rw-r--r--arch/x86/include/uapi/asm/hwcap2.h2
-rw-r--r--arch/x86/include/uapi/asm/ioctl.h1
-rw-r--r--arch/x86/include/uapi/asm/ioctls.h1
-rw-r--r--arch/x86/include/uapi/asm/ipcbuf.h1
-rw-r--r--arch/x86/include/uapi/asm/param.h1
-rw-r--r--arch/x86/include/uapi/asm/resource.h1
-rw-r--r--arch/x86/include/uapi/asm/sigcontext32.h2
-rw-r--r--arch/x86/include/uapi/asm/termbits.h1
-rw-r--r--arch/x86/include/uapi/asm/termios.h1
-rw-r--r--arch/x86/include/uapi/asm/types.h7
-rw-r--r--arch/x86/include/uapi/asm/unistd.h2
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S10
-rw-r--r--arch/x86/kernel/alternative.c6
-rw-r--r--arch/x86/kernel/amd_nb.c3
-rw-r--r--arch/x86/kernel/apic/apic.c280
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c66
-rw-r--r--arch/x86/kernel/apic/apic_noop.c18
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c8
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c33
-rw-r--r--arch/x86/kernel/apic/io_apic.c8
-rw-r--r--arch/x86/kernel/apic/ipi.c174
-rw-r--r--arch/x86/kernel/apic/local.h68
-rw-r--r--arch/x86/kernel/apic/probe_32.c44
-rw-r--r--arch/x86/kernel/apic/probe_64.c21
-rw-r--r--arch/x86/kernel/apic/vector.c11
-rw-r--r--arch/x86/kernel/apic/x2apic.h9
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c20
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c23
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c30
-rw-r--r--arch/x86/kernel/asm-offsets_64.c21
-rw-r--r--arch/x86/kernel/cpu/amd.c92
-rw-r--r--arch/x86/kernel/cpu/bugs.c127
-rw-r--r--arch/x86/kernel/cpu/common.c56
-rw-r--r--arch/x86/kernel/cpu/cpuid-deps.c97
-rw-r--r--arch/x86/kernel/cpu/hygon.c21
-rw-r--r--arch/x86/kernel/cpu/intel.c31
-rw-r--r--arch/x86/kernel/cpu/mce/intel.c2
-rw-r--r--arch/x86/kernel/cpu/mce/severity.c4
-rw-r--r--arch/x86/kernel/cpu/mtrr/cyrix.c1
-rw-r--r--arch/x86/kernel/cpu/umwait.c39
-rw-r--r--arch/x86/kernel/cpu/vmware.c94
-rw-r--r--arch/x86/kernel/crash.c2
-rw-r--r--arch/x86/kernel/dumpstack.c7
-rw-r--r--arch/x86/kernel/head_64.S8
-rw-r--r--arch/x86/kernel/hpet.c12
-rw-r--r--arch/x86/kernel/irq.c10
-rw-r--r--arch/x86/kernel/irq_32.c7
-rw-r--r--arch/x86/kernel/irq_64.c9
-rw-r--r--arch/x86/kernel/kgdb.c2
-rw-r--r--arch/x86/kernel/kprobes/core.c2
-rw-r--r--arch/x86/kernel/kprobes/opt.c2
-rw-r--r--arch/x86/kernel/kvm.c10
-rw-r--r--arch/x86/kernel/machine_kexec_32.c4
-rw-r--r--arch/x86/kernel/nmi.c3
-rw-r--r--arch/x86/kernel/paravirt.c4
-rw-r--r--arch/x86/kernel/pci-dma.c20
-rw-r--r--arch/x86/kernel/ptrace.c1
-rw-r--r--arch/x86/kernel/quirks.c4
-rw-r--r--arch/x86/kernel/reboot.c7
-rw-r--r--arch/x86/kernel/smp.c88
-rw-r--r--arch/x86/kernel/smpboot.c12
-rw-r--r--arch/x86/kernel/stacktrace.c2
-rw-r--r--arch/x86/kernel/sysfb_efi.c46
-rw-r--r--arch/x86/kernel/tsc.c2
-rw-r--r--arch/x86/kernel/tsc_msr.c5
-rw-r--r--arch/x86/kernel/umip.c65
-rw-r--r--arch/x86/kernel/uprobes.c17
-rw-r--r--arch/x86/kvm/debugfs.c46
-rw-r--r--arch/x86/kvm/hyperv.c5
-rw-r--r--arch/x86/kvm/lapic.c13
-rw-r--r--arch/x86/kvm/mmu.c120
-rw-r--r--arch/x86/kvm/svm.c28
-rw-r--r--arch/x86/kvm/vmx/nested.c8
-rw-r--r--arch/x86/kvm/vmx/vmx.c20
-rw-r--r--arch/x86/kvm/x86.c48
-rw-r--r--arch/x86/lib/copy_user_64.S14
-rw-r--r--arch/x86/lib/cpu.c1
-rw-r--r--arch/x86/lib/getuser.S16
-rw-r--r--arch/x86/lib/putuser.S22
-rw-r--r--arch/x86/math-emu/errors.c5
-rw-r--r--arch/x86/math-emu/fpu_trig.c2
-rw-r--r--arch/x86/mm/fault.c15
-rw-r--r--arch/x86/mm/init_32.c2
-rw-r--r--arch/x86/mm/ioremap.c1
-rw-r--r--arch/x86/mm/numa.c4
-rw-r--r--arch/x86/mm/pageattr.c136
-rw-r--r--arch/x86/mm/pti.c8
-rw-r--r--arch/x86/mm/tlb.c2
-rw-r--r--arch/x86/net/bpf_jit_comp.c9
-rw-r--r--arch/x86/pci/mmconfig-shared.c5
-rw-r--r--arch/x86/platform/efi/efi.c39
-rw-r--r--arch/x86/platform/intel/iosf_mbi.c100
-rw-r--r--arch/x86/platform/uv/bios_uv.c10
-rw-r--r--arch/x86/platform/uv/tlb_uv.c4
-rw-r--r--arch/x86/power/cpu.c90
-rw-r--r--arch/x86/purgatory/Makefile37
-rw-r--r--arch/x86/purgatory/purgatory.c6
-rw-r--r--arch/x86/purgatory/string.c23
-rw-r--r--arch/x86/realmode/rm/header.S1
-rw-r--r--arch/x86/realmode/rm/trampoline_32.S3
-rw-r--r--arch/x86/realmode/rm/trampoline_64.S3
-rw-r--r--arch/x86/realmode/rm/trampoline_common.S4
-rw-r--r--arch/x86/xen/enlighten_pv.c15
-rw-r--r--arch/xtensa/kernel/coprocessor.S1
-rw-r--r--arch/xtensa/kernel/setup.c1
-rw-r--r--block/bfq-iosched.c135
-rw-r--r--block/blk-cgroup.c9
-rw-r--r--block/blk-iolatency.c3
-rw-r--r--block/blk-mq-sched.h9
-rw-r--r--block/blk-mq.c4
-rw-r--r--block/blk-rq-qos.c7
-rw-r--r--block/blk-settings.c3
-rw-r--r--block/blk-sysfs.c3
-rw-r--r--block/genhd.c2
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/arm64/iort.c10
-rw-r--r--drivers/acpi/device_pm.c4
-rw-r--r--drivers/acpi/nfit/core.c28
-rw-r--r--drivers/acpi/nfit/nfit.h24
-rw-r--r--drivers/acpi/osl.c6
-rw-r--r--drivers/acpi/pptt.c53
-rw-r--r--drivers/acpi/scan.c6
-rw-r--r--drivers/acpi/x86/utils.c4
-rw-r--r--drivers/android/binder.c5
-rw-r--r--drivers/ata/libahci_platform.c4
-rw-r--r--drivers/ata/libata-scsi.c21
-rw-r--r--drivers/ata/libata-sff.c6
-rw-r--r--drivers/ata/libata-zpodd.c2
-rw-r--r--drivers/ata/pata_rb532_cf.c1
-rw-r--r--drivers/atm/Kconfig2
-rw-r--r--drivers/atm/iphase.c8
-rw-r--r--drivers/auxdisplay/Kconfig5
-rw-r--r--drivers/auxdisplay/charlcd.c2
-rw-r--r--drivers/auxdisplay/charlcd.h (renamed from include/misc/charlcd.h)5
-rw-r--r--drivers/auxdisplay/hd44780.c3
-rw-r--r--drivers/auxdisplay/ht16k33.c4
-rw-r--r--drivers/auxdisplay/panel.c4
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/arch_topology.c298
-rw-r--r--drivers/base/base.h1
-rw-r--r--drivers/base/core.c95
-rw-r--r--drivers/base/firmware_loader/firmware.h4
-rw-r--r--drivers/base/platform.c9
-rw-r--r--drivers/base/power/runtime.c15
-rw-r--r--drivers/base/regmap/Kconfig2
-rw-r--r--drivers/base/regmap/regmap-debugfs.c12
-rw-r--r--drivers/base/regmap/regmap-irq.c7
-rw-r--r--drivers/base/soc.c9
-rw-r--r--drivers/block/aoe/aoedev.c13
-rw-r--r--drivers/block/ataflop.c1
-rw-r--r--drivers/block/drbd/drbd_main.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c14
-rw-r--r--drivers/block/loop.c18
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/block/rbd.c11
-rw-r--r--drivers/block/xen-blkback/xenbus.c6
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/btqca.c29
-rw-r--r--drivers/bluetooth/btqca.h7
-rw-r--r--drivers/bluetooth/btusb.c12
-rw-r--r--drivers/bluetooth/hci_ath.c3
-rw-r--r--drivers/bluetooth/hci_bcm.c3
-rw-r--r--drivers/bluetooth/hci_intel.c3
-rw-r--r--drivers/bluetooth/hci_ldisc.c13
-rw-r--r--drivers/bluetooth/hci_mrvl.c3
-rw-r--r--drivers/bluetooth/hci_qca.c22
-rw-r--r--drivers/bluetooth/hci_uart.h1
-rw-r--r--drivers/bus/Kconfig10
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-allocator.c1
-rw-r--r--drivers/bus/fsl-mc/mc-io.c1
-rw-r--r--drivers/bus/hisi_lpc.c47
-rw-r--r--drivers/bus/imx-weim.c34
-rw-r--r--drivers/bus/moxtet.c885
-rw-r--r--drivers/bus/sunxi-rsb.c4
-rw-r--r--drivers/bus/ti-sysc.c24
-rw-r--r--drivers/bus/uniphier-system-bus.c4
-rw-r--r--drivers/char/Kconfig31
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/Kconfig11
-rw-r--r--drivers/char/agp/Makefile1
-rw-r--r--drivers/char/agp/sgi-agp.c338
-rw-r--r--drivers/char/hpet.c3
-rw-r--r--drivers/char/ipmi/ipmb_dev_int.c2
-rw-r--r--drivers/char/mbcs.c831
-rw-r--r--drivers/char/mbcs.h553
-rw-r--r--drivers/char/mspec.c155
-rw-r--r--drivers/char/random.c14
-rw-r--r--drivers/char/snsc.c469
-rw-r--r--drivers/char/snsc.h92
-rw-r--r--drivers/char/snsc_event.c303
-rw-r--r--drivers/char/tpm/Kconfig5
-rw-r--r--drivers/char/tpm/Makefile1
-rw-r--r--drivers/char/tpm/tpm-chip.c50
-rw-r--r--drivers/char/tpm/tpm-sysfs.c7
-rw-r--r--drivers/char/tpm/tpm.h2
-rw-r--r--drivers/char/tpm/tpm1-cmd.c36
-rw-r--r--drivers/char/tpm/tpm2-cmd.c6
-rw-r--r--drivers/char/tpm/tpm_ftpm_tee.c350
-rw-r--r--drivers/char/tpm/tpm_ftpm_tee.h40
-rw-r--r--drivers/char/tpm/tpm_tis_core.c3
-rw-r--r--drivers/clk/at91/clk-generated.c2
-rw-r--r--drivers/clk/clk-scmi.c2
-rw-r--r--drivers/clk/clk.c55
-rw-r--r--drivers/clk/imx/Kconfig6
-rw-r--r--drivers/clk/imx/Makefile1
-rw-r--r--drivers/clk/imx/clk-imx8mm.c17
-rw-r--r--drivers/clk/imx/clk-imx8mn.c636
-rw-r--r--drivers/clk/imx/clk-imx8qxp-lpcg.c5
-rw-r--r--drivers/clk/imx/clk.c8
-rw-r--r--drivers/clk/imx/clk.h18
-rw-r--r--drivers/clk/mediatek/clk-mt8183.c46
-rw-r--r--drivers/clk/meson/Kconfig11
-rw-r--r--drivers/clk/meson/Makefile2
-rw-r--r--drivers/clk/meson/axg-aoclk.c63
-rw-r--r--drivers/clk/meson/axg-audio.c261
-rw-r--r--drivers/clk/meson/axg.c207
-rw-r--r--drivers/clk/meson/clk-cpu-dyndiv.c73
-rw-r--r--drivers/clk/meson/clk-cpu-dyndiv.h20
-rw-r--r--drivers/clk/meson/clk-input.c49
-rw-r--r--drivers/clk/meson/clk-input.h19
-rw-r--r--drivers/clk/meson/clk-regmap.h12
-rw-r--r--drivers/clk/meson/g12a-aoclk.c81
-rw-r--r--drivers/clk/meson/g12a.c1626
-rw-r--r--drivers/clk/meson/g12a.h1
-rw-r--r--drivers/clk/meson/gxbb-aoclk.c55
-rw-r--r--drivers/clk/meson/gxbb.c657
-rw-r--r--drivers/clk/meson/meson-aoclk.c37
-rw-r--r--drivers/clk/meson/meson-aoclk.h8
-rw-r--r--drivers/clk/meson/meson-eeclk.c10
-rw-r--r--drivers/clk/meson/meson-eeclk.h2
-rw-r--r--drivers/clk/meson/meson8b.c710
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c16
-rw-r--r--drivers/clk/samsung/clk-exynos5-subcmu.c16
-rw-r--r--drivers/clk/samsung/clk-exynos5-subcmu.h2
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c7
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c162
-rw-r--r--drivers/clk/socfpga/clk-periph-s10.c2
-rw-r--r--drivers/clk/sprd/Kconfig1
-rw-r--r--drivers/clocksource/timer-riscv.c23
-rw-r--r--drivers/cpufreq/cpufreq.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c26
-rw-r--r--drivers/cpufreq/pasemi-cpufreq.c23
-rw-r--r--drivers/cpuidle/Kconfig.arm10
-rw-r--r--drivers/cpuidle/Makefile1
-rw-r--r--drivers/cpuidle/cpuidle-arm.c13
-rw-r--r--drivers/cpuidle/cpuidle-psci.c236
-rw-r--r--drivers/crypto/ccp/ccp-crypto-aes-galois.c14
-rw-r--r--drivers/crypto/ccp/ccp-dev.c8
-rw-r--r--drivers/crypto/ccp/ccp-ops.c33
-rw-r--r--drivers/crypto/ux500/cryp/cryp.c6
-rw-r--r--drivers/dma/Kconfig4
-rw-r--r--drivers/dma/bcm2835-dma.c38
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.h2
-rw-r--r--drivers/dma/dw-edma/dw-edma-pcie.c18
-rw-r--r--drivers/dma/dw-edma/dw-edma-v0-core.c34
-rw-r--r--drivers/dma/dw-edma/dw-edma-v0-debugfs.c29
-rw-r--r--drivers/dma/fsldma.c1
-rw-r--r--drivers/dma/iop-adma.c22
-rw-r--r--drivers/dma/iop-adma.h (renamed from arch/arm/include/asm/hardware/iop3xx-adma.h)7
-rw-r--r--drivers/dma/sh/rcar-dmac.c28
-rw-r--r--drivers/dma/sprd-dma.c10
-rw-r--r--drivers/dma/ste_dma40.c4
-rw-r--r--drivers/dma/stm32-mdma.c2
-rw-r--r--drivers/dma/tegra210-adma.c4
-rw-r--r--drivers/dma/ti/dma-crossbar.c4
-rw-r--r--drivers/dma/ti/omap-dma.c8
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/altera_edac.c58
-rw-r--r--drivers/edac/altera_edac.h25
-rw-r--r--drivers/edac/amd64_edac.c371
-rw-r--r--drivers/edac/amd64_edac.h15
-rw-r--r--drivers/edac/bluefield_edac.c356
-rw-r--r--drivers/edac/edac_mc.c53
-rw-r--r--drivers/edac/edac_mc.h6
-rw-r--r--drivers/edac/edac_mc_sysfs.c92
-rw-r--r--drivers/edac/ghes_edac.c2
-rw-r--r--drivers/edac/i10nm_base.c4
-rw-r--r--drivers/edac/i5100_edac.c16
-rw-r--r--drivers/edac/pnd2_edac.c9
-rw-r--r--drivers/edac/sb_edac.c2
-rw-r--r--drivers/firewire/core-device.c2
-rw-r--r--drivers/firewire/core-iso.c2
-rw-r--r--drivers/firewire/core-topology.c1
-rw-r--r--drivers/firmware/Kconfig19
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/arm_scmi/Makefile2
-rw-r--r--drivers/firmware/arm_scmi/base.c2
-rw-r--r--drivers/firmware/arm_scmi/clock.c33
-rw-r--r--drivers/firmware/arm_scmi/common.h18
-rw-r--r--drivers/firmware/arm_scmi/driver.c366
-rw-r--r--drivers/firmware/arm_scmi/perf.c264
-rw-r--r--drivers/firmware/arm_scmi/power.c6
-rw-r--r--drivers/firmware/arm_scmi/reset.c231
-rw-r--r--drivers/firmware/arm_scmi/sensors.c57
-rw-r--r--drivers/firmware/efi/Kconfig13
-rw-r--r--drivers/firmware/efi/Makefile1
-rw-r--r--drivers/firmware/efi/cper.c15
-rw-r--r--drivers/firmware/efi/efi.c39
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c38
-rw-r--r--drivers/firmware/efi/rci2-table.c147
-rw-r--r--drivers/firmware/imx/Kconfig11
-rw-r--r--drivers/firmware/imx/Makefile1
-rw-r--r--drivers/firmware/imx/imx-dsp.c155
-rw-r--r--drivers/firmware/imx/scu-pd.c4
-rw-r--r--drivers/firmware/iscsi_ibft.c4
-rw-r--r--drivers/firmware/psci/psci.c167
-rw-r--r--drivers/firmware/psci/psci_checker.c16
-rw-r--r--drivers/firmware/qcom_scm.c47
-rw-r--r--drivers/firmware/ti_sci.c45
-rw-r--r--drivers/firmware/turris-mox-rwtm.c384
-rw-r--r--drivers/fpga/Kconfig1
-rw-r--r--drivers/fpga/altera-ps-spi.c11
-rw-r--r--drivers/fsi/fsi-scom.c8
-rw-r--r--drivers/gpio/Kconfig22
-rw-r--r--drivers/gpio/Makefile4
-rw-r--r--drivers/gpio/gpio-arizona.c4
-rw-r--r--drivers/gpio/gpio-aspeed.c117
-rw-r--r--drivers/gpio/gpio-bd70528.c4
-rw-r--r--drivers/gpio/gpio-brcmstb.c4
-rw-r--r--drivers/gpio/gpio-cadence.c36
-rw-r--r--drivers/gpio/gpio-creg-snps.c4
-rw-r--r--drivers/gpio/gpio-dwapb.c1
-rw-r--r--drivers/gpio/gpio-eic-sprd.c4
-rw-r--r--drivers/gpio/gpio-em.c37
-rw-r--r--drivers/gpio/gpio-ep93xx.c140
-rw-r--r--drivers/gpio/gpio-ftgpio010.c14
-rw-r--r--drivers/gpio/gpio-grgpio.c2
-rw-r--r--drivers/gpio/gpio-hlwd.c58
-rw-r--r--drivers/gpio/gpio-htc-egpio.c14
-rw-r--r--drivers/gpio/gpio-intel-mid.c35
-rw-r--r--drivers/gpio/gpio-ixp4xx.c279
-rw-r--r--drivers/gpio/gpio-ks8695.c284
-rw-r--r--drivers/gpio/gpio-lpc32xx.c118
-rw-r--r--drivers/gpio/gpio-lynxpoint.c35
-rw-r--r--drivers/gpio/gpio-madera.c12
-rw-r--r--drivers/gpio/gpio-max77620.c4
-rw-r--r--drivers/gpio/gpio-max77650.c1
-rw-r--r--drivers/gpio/gpio-mb86s7x.c1
-rw-r--r--drivers/gpio/gpio-merrifield.c28
-rw-r--r--drivers/gpio/gpio-mockup.c1
-rw-r--r--drivers/gpio/gpio-moxtet.c179
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c32
-rw-r--r--drivers/gpio/gpio-mt7621.c33
-rw-r--r--drivers/gpio/gpio-mxc.c9
-rw-r--r--drivers/gpio/gpio-pca953x.c85
-rw-r--r--drivers/gpio/gpio-pch.c6
-rw-r--r--drivers/gpio/gpio-pmic-eic-sprd.c4
-rw-r--r--drivers/gpio/gpio-sprd.c4
-rw-r--r--drivers/gpio/gpio-stmpe.c36
-rw-r--r--drivers/gpio/gpio-tb10x.c4
-rw-r--r--drivers/gpio/gpio-tegra.c4
-rw-r--r--drivers/gpio/gpio-thunderx.c163
-rw-r--r--drivers/gpio/gpio-tqmx86.c50
-rw-r--r--drivers/gpio/gpio-vf610.c26
-rw-r--r--drivers/gpio/gpio-viperboard.c20
-rw-r--r--drivers/gpio/gpio-xgene-sb.c1
-rw-r--r--drivers/gpio/gpio-xlp.c29
-rw-r--r--drivers/gpio/gpio-zx.c35
-rw-r--r--drivers/gpio/gpio-zynq.c41
-rw-r--r--drivers/gpio/gpiolib-acpi.c69
-rw-r--r--drivers/gpio/gpiolib-acpi.h96
-rw-r--r--drivers/gpio/gpiolib-devres.c28
-rw-r--r--drivers/gpio/gpiolib-of.c185
-rw-r--r--drivers/gpio/gpiolib-of.h38
-rw-r--r--drivers/gpio/gpiolib.c743
-rw-r--r--drivers/gpio/gpiolib.h120
-rw-r--r--drivers/gpio/sgpio-aspeed.c533
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c78
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c49
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c47
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c28
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h1
-rw-r--r--drivers/gpu/drm/amd/display/include/dpcd_defs.h2
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/amdgpu_smu.c125
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c9
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c66
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h14
-rw-r--r--drivers/gpu/drm/amd/powerplay/navi10_ppt.c211
-rw-r--r--drivers/gpu/drm/amd/powerplay/navi10_ppt.h4
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c62
-rw-r--r--drivers/gpu/drm/amd/powerplay/vega20_ppt.c65
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_dev.c11
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c19
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h3
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c5
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.c30
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c2
-rw-r--r--drivers/gpu/drm/ast/ast_main.c5
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c2
-rw-r--r--drivers/gpu/drm/ast/ast_post.c2
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c1
-rw-r--r--drivers/gpu/drm/bridge/Kconfig4
-rw-r--r--drivers/gpu/drm/drm_client.c60
-rw-r--r--drivers/gpu/drm/drm_client_modeset.c2
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c51
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c2
-rw-r--r--drivers/gpu/drm/drm_modes.c60
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_scaler.c4
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c15
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_vbt_defs.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c2
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c20
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pages.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pm.c7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.c27
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_pm.c24
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_pm.h12
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h12
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c21
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c58
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ringbuffer.c31
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c43
-rw-r--r--drivers/gpu/drm/i915/gt/mock_engine.c1
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_reset.c5
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_workarounds.c7
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c10
-rw-r--r--drivers/gpu/drm/i915/gvt/fb_decoder.c6
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c9
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c12
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c59
-rw-r--r--drivers/gpu/drm/i915/gvt/trace_points.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c25
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c8
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c7
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c67
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h76
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c3
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c10
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.h15
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm.c5
-rw-r--r--drivers/gpu/drm/lima/lima_gem.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c55
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c1
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c3
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c16
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c47
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c22
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c12
-rw-r--r--drivers/gpu/drm/omapdrm/dss/output.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_mmu.c24
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c20
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c6
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c2
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c4
-rw-r--r--drivers/gpu/drm/selftests/drm_cmdline_selftests.h7
-rw-r--r--drivers/gpu/drm/selftests/test-drm_cmdline_parser.c130
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c1
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c1
-rw-r--r--drivers/gpu/drm/tegra/output.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c6
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_object.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.c27
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.h35
-rw-r--r--drivers/hid/hid-a4tech.c30
-rw-r--r--drivers/hid/hid-cp2112.c8
-rw-r--r--drivers/hid/hid-holtek-kbd.c9
-rw-r--r--drivers/hid/hid-ids.h5
-rw-r--r--drivers/hid/hid-logitech-dj.c10
-rw-r--r--drivers/hid/hid-logitech-hidpp.c14
-rw-r--r--drivers/hid/hid-quirks.c2
-rw-r--r--drivers/hid/hid-sony.c15
-rw-r--r--drivers/hid/hid-tmff.c12
-rw-r--r--drivers/hid/intel-ish-hid/ipc/hw-ish.h1
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c1
-rw-r--r--drivers/hid/usbhid/hiddev.c12
-rw-r--r--drivers/hid/wacom_wac.c19
-rw-r--r--drivers/hv/channel.c2
-rw-r--r--drivers/hv/hv_trace.h2
-rw-r--r--drivers/hv/hyperv_vmbus.h10
-rw-r--r--drivers/hwmon/Kconfig31
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/acpi_power_meter.c4
-rw-r--r--drivers/hwmon/ads1015.c324
-rw-r--r--drivers/hwmon/adt7475.c146
-rw-r--r--drivers/hwmon/as370-hwmon.c145
-rw-r--r--drivers/hwmon/asb100.c12
-rw-r--r--drivers/hwmon/coretemp.c3
-rw-r--r--drivers/hwmon/iio_hwmon.c18
-rw-r--r--drivers/hwmon/k10temp.c1
-rw-r--r--drivers/hwmon/k8temp.c233
-rw-r--r--drivers/hwmon/lm75.c462
-rw-r--r--drivers/hwmon/ltc2990.c10
-rw-r--r--drivers/hwmon/nct6775.c183
-rw-r--r--drivers/hwmon/nct7802.c6
-rw-r--r--drivers/hwmon/nct7904.c476
-rw-r--r--drivers/hwmon/npcm750-pwm-fan.c4
-rw-r--r--drivers/hwmon/occ/common.c6
-rw-r--r--drivers/hwmon/pmbus/Kconfig9
-rw-r--r--drivers/hwmon/pmbus/Makefile1
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c110
-rw-r--r--drivers/hwmon/pmbus/inspur-ipsps.c228
-rw-r--r--drivers/hwmon/pmbus/max31785.c2
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c1
-rw-r--r--drivers/hwmon/raspberrypi-hwmon.c2
-rw-r--r--drivers/hwmon/scmi-hwmon.c2
-rw-r--r--drivers/hwmon/shtc1.c57
-rw-r--r--drivers/hwmon/smm665.c6
-rw-r--r--drivers/hwmon/w83781d.c6
-rw-r--r--drivers/hwmon/w83791d.c32
-rw-r--r--drivers/hwmon/w83792d.c32
-rw-r--r--drivers/hwmon/w83793.c30
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c1
-rw-r--r--drivers/hwtracing/intel_th/msu.h2
-rw-r--r--drivers/hwtracing/intel_th/pci.c10
-rw-r--r--drivers/hwtracing/intel_th/pti.h2
-rw-r--r--drivers/hwtracing/stm/core.c1
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c2
-rw-r--r--drivers/i2c/busses/i2c-at91-master.c9
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c15
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c1
-rw-r--r--drivers/i2c/busses/i2c-emev2.c16
-rw-r--r--drivers/i2c/busses/i2c-i801.c15
-rw-r--r--drivers/i2c/busses/i2c-imx.c18
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c11
-rw-r--r--drivers/i2c/busses/i2c-nvidia-gpu.c2
-rw-r--r--drivers/i2c/busses/i2c-piix4.c12
-rw-r--r--drivers/i2c/busses/i2c-rcar.c11
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c1
-rw-r--r--drivers/i2c/busses/i2c-stm32.h2
-rw-r--r--drivers/i2c/i2c-core-base.c2
-rw-r--r--drivers/i3c/device.c53
-rw-r--r--drivers/i3c/master.c67
-rw-r--r--drivers/i3c/master/dw-i3c-master.c4
-rw-r--r--drivers/i3c/master/i3c-master-cdns.c30
-rw-r--r--drivers/ide/Kconfig9
-rw-r--r--drivers/ide/Makefile1
-rw-r--r--drivers/ide/sgiioc4.c630
-rw-r--r--drivers/idle/intel_idle.c28
-rw-r--r--drivers/iio/accel/cros_ec_accel_legacy.c1
-rw-r--r--drivers/iio/adc/Kconfig2
-rw-r--r--drivers/iio/adc/ingenic-adc.c54
-rw-r--r--drivers/iio/adc/max9611.c4
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c4
-rw-r--r--drivers/iio/frequency/adf4371.c8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c43
-rw-r--r--drivers/infiniband/core/cma.c6
-rw-r--r--drivers/infiniband/core/core_priv.h5
-rw-r--r--drivers/infiniband/core/counters.c27
-rw-r--r--drivers/infiniband/core/device.c102
-rw-r--r--drivers/infiniband/core/mad.c20
-rw-r--r--drivers/infiniband/core/nldev.c11
-rw-r--r--drivers/infiniband/core/restrack.c15
-rw-r--r--drivers/infiniband/core/umem.c7
-rw-r--r--drivers/infiniband/core/umem_odp.c4
-rw-r--r--drivers/infiniband/core/user_mad.c6
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c7
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c8
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.h11
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c13
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h2
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.c14
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.h7
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c11
-rw-r--r--drivers/infiniband/hw/hfi1/fault.c12
-rw-r--r--drivers/infiniband/hw/hfi1/rc.c2
-rw-r--r--drivers/infiniband/hw/hfi1/tid_rdma.c119
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c2
-rw-r--r--drivers/infiniband/hw/hns/Kconfig6
-rw-r--r--drivers/infiniband/hw/hns/Makefile8
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_db.c15
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v1.c4
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c4
-rw-r--r--drivers/infiniband/hw/mlx5/devx.c11
-rw-r--r--drivers/infiniband/hw/mlx5/main.c13
-rw-r--r--drivers/infiniband/hw/mlx5/mem.c5
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h15
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c51
-rw-r--r--drivers/infiniband/hw/mlx5/odp.c48
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c37
-rw-r--r--drivers/infiniband/hw/qedr/main.c10
-rw-r--r--drivers/infiniband/sw/siw/Kconfig2
-rw-r--r--drivers/infiniband/sw/siw/siw.h10
-rw-r--r--drivers/infiniband/sw/siw/siw_cm.c116
-rw-r--r--drivers/infiniband/sw/siw/siw_cq.c5
-rw-r--r--drivers/infiniband/sw/siw/siw_main.c5
-rw-r--r--drivers/infiniband/sw/siw/siw_mem.c14
-rw-r--r--drivers/infiniband/sw/siw/siw_mem.h2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp.c22
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_rx.c26
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_tx.c80
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.c56
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c5
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/applespi.c29
-rw-r--r--drivers/input/mouse/elantech.c55
-rw-r--r--drivers/input/mouse/synaptics.c1
-rw-r--r--drivers/input/mouse/vmmouse.c6
-rw-r--r--drivers/input/serio/hyperv-keyboard.c35
-rw-r--r--drivers/input/tablet/kbtab.c6
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c2
-rw-r--r--drivers/iommu/Kconfig3
-rw-r--r--drivers/iommu/Makefile5
-rw-r--r--drivers/iommu/amd_iommu.c146
-rw-r--r--drivers/iommu/amd_iommu.h14
-rw-r--r--drivers/iommu/amd_iommu_init.c95
-rw-r--r--drivers/iommu/amd_iommu_quirks.c92
-rw-r--r--drivers/iommu/amd_iommu_types.h18
-rw-r--r--drivers/iommu/arm-smmu-impl.c174
-rw-r--r--drivers/iommu/arm-smmu-regs.h210
-rw-r--r--drivers/iommu/arm-smmu-v3.c984
-rw-r--r--drivers/iommu/arm-smmu.c662
-rw-r--r--drivers/iommu/arm-smmu.h402
-rw-r--r--drivers/iommu/dma-iommu.c41
-rw-r--r--drivers/iommu/dmar.c77
-rw-r--r--drivers/iommu/exynos-iommu.c9
-rw-r--r--drivers/iommu/intel-iommu-debugfs.c6
-rw-r--r--drivers/iommu/intel-iommu.c504
-rw-r--r--drivers/iommu/intel-svm.c36
-rw-r--r--drivers/iommu/intel-trace.c14
-rw-r--r--drivers/iommu/intel_irq_remapping.c6
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c145
-rw-r--r--drivers/iommu/io-pgtable-arm.c48
-rw-r--r--drivers/iommu/iommu.c217
-rw-r--r--drivers/iommu/iova.c27
-rw-r--r--drivers/iommu/ipmmu-vmsa.c106
-rw-r--r--drivers/iommu/msm_iommu.c43
-rw-r--r--drivers/iommu/mtk_iommu.c213
-rw-r--r--drivers/iommu/mtk_iommu.h21
-rw-r--r--drivers/iommu/mtk_iommu_v1.c9
-rw-r--r--drivers/iommu/omap-iommu.c324
-rw-r--r--drivers/iommu/omap-iommu.h9
-rw-r--r--drivers/iommu/qcom_iommu.c72
-rw-r--r--drivers/iommu/rockchip-iommu.c2
-rw-r--r--drivers/iommu/s390-iommu.c3
-rw-r--r--drivers/iommu/tegra-gart.c12
-rw-r--r--drivers/iommu/tegra-smmu.c2
-rw-r--r--drivers/iommu/virtio-iommu.c45
-rw-r--r--drivers/irqchip/irq-gic-common.c35
-rw-r--r--drivers/irqchip/irq-gic-common.h2
-rw-r--r--drivers/irqchip/irq-gic-v2m.c2
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c15
-rw-r--r--drivers/irqchip/irq-gic-v3.c388
-rw-r--r--drivers/irqchip/irq-gic.c14
-rw-r--r--drivers/irqchip/irq-hip04.c9
-rw-r--r--drivers/irqchip/irq-imgpdc.c8
-rw-r--r--drivers/irqchip/irq-imx-gpcv2.c1
-rw-r--r--drivers/irqchip/irq-ixp4xx.c2
-rw-r--r--drivers/irqchip/irq-keystone.c4
-rw-r--r--drivers/irqchip/irq-mbigen.c9
-rw-r--r--drivers/irqchip/irq-meson-gpio.c52
-rw-r--r--drivers/irqchip/irq-mmp.c86
-rw-r--r--drivers/irqchip/irq-sifive-plic.c12
-rw-r--r--drivers/irqchip/irq-uniphier-aidet.c4
-rw-r--r--drivers/irqchip/qcom-irq-combiner.c4
-rw-r--r--drivers/isdn/capi/capi.c10
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c13
-rw-r--r--drivers/macintosh/smu.c1
-rw-r--r--drivers/md/bcache/super.c3
-rw-r--r--drivers/md/bcache/sysfs.c20
-rw-r--r--drivers/md/dm-bufio.c4
-rw-r--r--drivers/md/dm-dust.c11
-rw-r--r--drivers/md/dm-integrity.c15
-rw-r--r--drivers/md/dm-kcopyd.c5
-rw-r--r--drivers/md/dm-raid.c2
-rw-r--r--drivers/md/dm-table.c21
-rw-r--r--drivers/md/dm-zoned-metadata.c68
-rw-r--r--drivers/md/dm-zoned-reclaim.c47
-rw-r--r--drivers/md/dm-zoned-target.c68
-rw-r--r--drivers/md/dm-zoned.h11
-rw-r--r--drivers/md/persistent-data/dm-btree.c31
-rw-r--r--drivers/md/persistent-data/dm-space-map-metadata.c2
-rw-r--r--drivers/media/platform/omap/omap_vout_vrfb.c3
-rw-r--r--drivers/media/platform/vivid/vivid-core.c8
-rw-r--r--drivers/memory/mtk-smi.c268
-rw-r--r--drivers/mfd/db8500-prcmu.c2
-rw-r--r--drivers/mfd/omap-usb-host.c4
-rw-r--r--drivers/mfd/rk808.c6
-rw-r--r--drivers/misc/Kconfig18
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/eeprom/Kconfig3
-rw-r--r--drivers/misc/eeprom/at24.c2
-rw-r--r--drivers/misc/habanalabs/command_submission.c2
-rw-r--r--drivers/misc/habanalabs/device.c5
-rw-r--r--drivers/misc/habanalabs/firmware_if.c22
-rw-r--r--drivers/misc/habanalabs/goya/goya.c83
-rw-r--r--drivers/misc/habanalabs/goya/goyaP.h2
-rw-r--r--drivers/misc/habanalabs/habanalabs.h25
-rw-r--r--drivers/misc/habanalabs/hw_queue.c14
-rw-r--r--drivers/misc/habanalabs/include/goya/goya_packets.h13
-rw-r--r--drivers/misc/habanalabs/irq.c27
-rw-r--r--drivers/misc/habanalabs/memory.c2
-rw-r--r--drivers/misc/ioc4.c498
-rw-r--r--drivers/misc/lkdtm/bugs.c4
-rw-r--r--drivers/misc/mei/hw-me-regs.h5
-rw-r--r--drivers/misc/mei/pci-me.c5
-rw-r--r--drivers/misc/sgi-xp/Makefile13
-rw-r--r--drivers/misc/sgi-xp/xp.h19
-rw-r--r--drivers/misc/sgi-xp/xp_main.c8
-rw-r--r--drivers/misc/sgi-xp/xp_nofault.S35
-rw-r--r--drivers/misc/sgi-xp/xp_sn2.c190
-rw-r--r--drivers/misc/sgi-xp/xp_uv.c9
-rw-r--r--drivers/misc/sgi-xp/xpc.h273
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c31
-rw-r--r--drivers/misc/sgi-xp/xpc_partition.c5
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c2459
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c16
-rw-r--r--drivers/misc/sgi-xp/xpnet.c2
-rw-r--r--drivers/misc/vmw_balloon.c10
-rw-r--r--drivers/misc/vmw_vmci/vmci_doorbell.c6
-rw-r--r--drivers/mmc/core/mmc_ops.c2
-rw-r--r--drivers/mmc/core/queue.c5
-rw-r--r--drivers/mmc/core/sd.c6
-rw-r--r--drivers/mmc/host/bcm2835.c2
-rw-r--r--drivers/mmc/host/cavium.c4
-rw-r--r--drivers/mmc/host/dw_mmc.c3
-rw-r--r--drivers/mmc/host/meson-mx-sdio.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c6
-rw-r--r--drivers/mmc/host/sdhci-acpi.c2
-rw-r--r--drivers/mmc/host/sdhci-cadence.c1
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c2
-rw-r--r--drivers/mmc/host/sdhci-of-at91.c5
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c4
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.c2
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c2
-rw-r--r--drivers/mmc/host/sdhci-s3c.c2
-rw-r--r--drivers/mmc/host/sdhci-sprd.c33
-rw-r--r--drivers/mmc/host/sdhci-tegra.c14
-rw-r--r--drivers/mmc/host/sdhci-xenon.c2
-rw-r--r--drivers/mmc/host/sdhci.c4
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/mmc/host/tmio_mmc.c5
-rw-r--r--drivers/mmc/host/tmio_mmc.h1
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c27
-rw-r--r--drivers/mmc/host/uniphier-sd.c3
-rw-r--r--drivers/mtd/hyperbus/Kconfig4
-rw-r--r--drivers/mtd/maps/sa1100-flash.c1
-rw-r--r--drivers/mtd/nand/onenand/onenand_base.c1
-rw-r--r--drivers/mtd/nand/raw/nand_micron.c14
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c5
-rw-r--r--drivers/net/arcnet/arc-rimi.c3
-rw-r--r--drivers/net/arcnet/com20020-isa.c6
-rw-r--r--drivers/net/arcnet/com90io.c2
-rw-r--r--drivers/net/arcnet/com90xx.c3
-rw-r--r--drivers/net/bonding/bond_main.c11
-rw-r--r--drivers/net/can/at91_can.c6
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/flexcan.c39
-rw-r--r--drivers/net/can/peak_canfd/peak_pciefd_main.c2
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c9
-rw-r--r--drivers/net/can/sja1000/peak_pcmcia.c2
-rw-r--r--drivers/net/can/spi/mcp251x.c52
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb.c2
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_core.c10
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_fd.c2
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_pro.c2
-rw-r--r--drivers/net/dsa/bcm_sf2.c10
-rw-r--r--drivers/net/dsa/microchip/ksz9477_spi.c1
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h1
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c29
-rw-r--r--drivers/net/dsa/qca8k.c10
-rw-r--r--drivers/net/dsa/sja1105/sja1105_dynamic_config.c14
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c147
-rw-r--r--drivers/net/dsa/sja1105/sja1105_ptp.c7
-rw-r--r--drivers/net/ethernet/8390/Kconfig4
-rw-r--r--drivers/net/ethernet/Kconfig1
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/agere/et131x.c2
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c4
-rw-r--r--drivers/net/ethernet/amd/Kconfig2
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-main.c10
-rw-r--r--drivers/net/ethernet/apple/Kconfig4
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_filters.c5
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_main.c4
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_nic.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_vec.c3
-rw-r--r--drivers/net/ethernet/atheros/ag71xx.c2
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig6
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c10
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c17
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c38
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c9
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c8
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h6
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c3
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c2
-rw-r--r--drivers/net/ethernet/cavium/common/cavium_ptp.c2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c4
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c18
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c4
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c6
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c2
-rw-r--r--drivers/net/ethernet/ezchip/nps_enet.h4
-rw-r--r--drivers/net/ethernet/freescale/enetc/Kconfig2
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_ptp.c5
-rw-r--r--drivers/net/ethernet/freescale/fman/fman.c3
-rw-r--r--drivers/net/ethernet/google/gve/gve.h8
-rw-r--r--drivers/net/ethernet/google/gve/gve_ethtool.c4
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c2
-rw-r--r--drivers/net/ethernet/google/gve/gve_rx.c34
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_eth.c28
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c2
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c9
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c18
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c12
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c29
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c3
-rw-r--r--drivers/net/ethernet/marvell/mvmdio.c31
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c87
-rw-r--r--drivers/net/ethernet/marvell/sky2.c14
-rw-r--r--drivers/net/ethernet/mediatek/Kconfig1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dev.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h23
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/params.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.c27
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c50
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c97
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c115
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c42
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c76
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c155
-rw-r--r--drivers/net/ethernet/micrel/Kconfig11
-rw-r--r--drivers/net/ethernet/micrel/Makefile1
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.c1632
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.h108
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c1
-rw-r--r--drivers/net/ethernet/mscc/ocelot_ace.c2
-rw-r--r--drivers/net/ethernet/mscc/ocelot_flower.c12
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c2
-rw-r--r--drivers/net/ethernet/natsemi/sonic.c6
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/jit.c17
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/cmsg.c10
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c14
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/qos_conf.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c8
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c4
-rw-r--r--drivers/net/ethernet/ni/Kconfig2
-rw-r--r--drivers/net/ethernet/nuvoton/Kconfig29
-rw-r--r--drivers/net/ethernet/nuvoton/Makefile6
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c1082
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c143
-rw-r--r--drivers/net/ethernet/nxp/Kconfig2
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c45
-rw-r--r--drivers/net/ethernet/packetengines/Kconfig6
-rw-r--r--drivers/net/ethernet/packetengines/Makefile2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_rdma.c2
-rw-r--r--drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c13
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c15
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c8
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c2
-rw-r--r--drivers/net/ethernet/samsung/Kconfig2
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c7
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c87
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c50
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c4
-rw-r--r--drivers/net/ethernet/ti/cpsw.c2
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c1
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c2
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c5
-rw-r--r--drivers/net/ethernet/xscale/Kconfig2
-rw-r--r--drivers/net/hamradio/6pack.c4
-rw-r--r--drivers/net/hamradio/baycom_epp.c3
-rw-r--r--drivers/net/hyperv/netvsc_drv.c9
-rw-r--r--drivers/net/ieee802154/mac802154_hwsim.c8
-rw-r--r--drivers/net/netdevsim/dev.c63
-rw-r--r--drivers/net/netdevsim/fib.c102
-rw-r--r--drivers/net/netdevsim/netdev.c9
-rw-r--r--drivers/net/netdevsim/netdevsim.h10
-rw-r--r--drivers/net/phy/at803x.c32
-rw-r--r--drivers/net/phy/fixed_phy.c6
-rw-r--r--drivers/net/phy/mscc.c16
-rw-r--r--drivers/net/phy/phy-c45.c40
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/phy/phy_device.c18
-rw-r--r--drivers/net/phy/phy_led_triggers.c3
-rw-r--r--drivers/net/phy/phylink.c16
-rw-r--r--drivers/net/ppp/pppoe.c3
-rw-r--r--drivers/net/ppp/pppox.c13
-rw-r--r--drivers/net/ppp/pptp.c3
-rw-r--r--drivers/net/team/team.c2
-rw-r--r--drivers/net/tun.c25
-rw-r--r--drivers/net/usb/cdc_ether.c10
-rw-r--r--drivers/net/usb/cx82310_eth.c3
-rw-r--r--drivers/net/usb/kalmia.c6
-rw-r--r--drivers/net/usb/lan78xx.c8
-rw-r--r--drivers/net/usb/pegasus.c2
-rw-r--r--drivers/net/usb/qmi_wwan.c1
-rw-r--r--drivers/net/usb/r8152.c22
-rw-r--r--drivers/net/virtio_net.c2
-rw-r--r--drivers/net/wan/lmc/lmc_main.c2
-rw-r--r--drivers/net/wan/sdla.c1
-rw-r--r--drivers/net/wimax/i2400m/fw.c4
-rw-r--r--drivers/net/wimax/i2400m/op-rfkill.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c33
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c68
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c539
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c185
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c8
-rw-r--r--drivers/net/wireless/marvell/mwifiex/ie.c3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_cmd.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci.c15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb.c8
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c46
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00dev.c13
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c1
-rw-r--r--drivers/net/xen-netback/netback.c2
-rw-r--r--drivers/nfc/nfcmrvl/main.c4
-rw-r--r--drivers/nfc/nfcmrvl/uart.c4
-rw-r--r--drivers/nfc/nfcmrvl/usb.c1
-rw-r--r--drivers/nfc/st-nci/se.c2
-rw-r--r--drivers/nfc/st21nfca/se.c2
-rw-r--r--drivers/nfc/st95hf/core.c2
-rw-r--r--drivers/ntb/msi.c5
-rw-r--r--drivers/nvdimm/btt_devs.c16
-rw-r--r--drivers/nvdimm/bus.c210
-rw-r--r--drivers/nvdimm/core.c10
-rw-r--r--drivers/nvdimm/dimm_devs.c4
-rw-r--r--drivers/nvdimm/namespace_devs.c36
-rw-r--r--drivers/nvdimm/nd-core.h71
-rw-r--r--drivers/nvdimm/pfn_devs.c29
-rw-r--r--drivers/nvdimm/pmem.c4
-rw-r--r--drivers/nvdimm/region.c24
-rw-r--r--drivers/nvdimm/region_devs.c12
-rw-r--r--drivers/nvme/host/core.c41
-rw-r--r--drivers/nvme/host/multipath.c79
-rw-r--r--drivers/nvme/host/nvme.h32
-rw-r--r--drivers/nvme/host/pci.c23
-rw-r--r--drivers/nvme/host/rdma.c16
-rw-r--r--drivers/nvme/target/configfs.c1
-rw-r--r--drivers/nvme/target/core.c15
-rw-r--r--drivers/nvme/target/loop.c8
-rw-r--r--drivers/nvme/target/nvmet.h3
-rw-r--r--drivers/nvmem/nvmem-sysfs.c15
-rw-r--r--drivers/of/fdt.c14
-rw-r--r--drivers/of/irq.c2
-rw-r--r--drivers/of/resolver.c12
-rw-r--r--drivers/parisc/dino.c30
-rw-r--r--drivers/parisc/eisa_enumerator.c10
-rw-r--r--drivers/parisc/hppb.c11
-rw-r--r--drivers/pci/controller/pci-hyperv.c10
-rw-r--r--drivers/pci/hotplug/Kconfig9
-rw-r--r--drivers/pci/hotplug/Makefile1
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c700
-rw-r--r--drivers/pci/pci.c29
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/pcie/aspm.c20
-rw-r--r--drivers/pci/pcie/portdrv_core.c66
-rw-r--r--drivers/pci/quirks.c2
-rw-r--r--drivers/pcmcia/db1xxx_ss.c4
-rw-r--r--drivers/perf/arm_pmu.c2
-rw-r--r--drivers/perf/arm_smmuv3_pmu.c65
-rw-r--r--drivers/perf/fsl_imx8_ddr_perf.c75
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c4
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_hha_pmu.c4
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c4
-rw-r--r--drivers/perf/qcom_l2_pmu.c6
-rw-r--r--drivers/perf/xgene_pmu.c4
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c2
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c120
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.c12
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.c9
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.h12
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c16
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c42
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c18
-rw-r--r--drivers/pinctrl/qcom/Kconfig1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c23
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c92
-rw-r--r--drivers/platform/chrome/cros_ec_ishtp.c4
-rw-r--r--drivers/platform/chrome/cros_ec_spi.c2
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c5
-rw-r--r--drivers/platform/olpc/olpc-xo175-ec.c6
-rw-r--r--drivers/platform/x86/acer-wmi.c49
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c9
-rw-r--r--drivers/platform/x86/asus-wmi.c534
-rw-r--r--drivers/platform/x86/compal-laptop.c2
-rw-r--r--drivers/platform/x86/dell-wmi.c12
-rw-r--r--drivers/platform/x86/hp_accel.c1
-rw-r--r--drivers/platform/x86/i2c-multi-instantiate.c4
-rw-r--r--drivers/platform/x86/intel_bxtwc_tmu.c5
-rw-r--r--drivers/platform/x86/intel_int0002_vgpio.c26
-rw-r--r--drivers/platform/x86/intel_pmc_core.c21
-rw-r--r--drivers/platform/x86/intel_pmc_core_pltdrv.c20
-rw-r--r--drivers/platform/x86/intel_pmc_ipc.c4
-rw-r--r--drivers/platform/x86/intel_speed_select_if/isst_if_common.c2
-rw-r--r--drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c8
-rw-r--r--drivers/platform/x86/pcengines-apuv2.c19
-rw-r--r--drivers/platform/x86/pmc_atom.c7
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c122
-rw-r--r--drivers/platform/x86/touchscreen_dmi.c58
-rw-r--r--drivers/platform/x86/wmi.c4
-rw-r--r--drivers/power/supply/ab8500_charger.c1
-rw-r--r--drivers/powercap/intel_rapl_common.c34
-rw-r--r--drivers/powercap/powercap_sys.c2
-rw-r--r--drivers/pwm/core.c7
-rw-r--r--drivers/ras/Makefile3
-rw-r--r--drivers/ras/cec.c1
-rw-r--r--drivers/ras/debugfs.c2
-rw-r--r--drivers/regulator/Kconfig17
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/act8865-regulator.c316
-rw-r--r--drivers/regulator/act8945a-regulator.c8
-rw-r--r--drivers/regulator/axp20x-regulator.c10
-rw-r--r--drivers/regulator/core.c58
-rw-r--r--drivers/regulator/da9062-regulator.c4
-rw-r--r--drivers/regulator/da9063-regulator.c4
-rw-r--r--drivers/regulator/da9211-regulator.c2
-rw-r--r--drivers/regulator/fixed.c83
-rw-r--r--drivers/regulator/helpers.c21
-rw-r--r--drivers/regulator/lm363x-regulator.c10
-rw-r--r--drivers/regulator/lp87565-regulator.c13
-rw-r--r--drivers/regulator/lp8788-ldo.c2
-rw-r--r--drivers/regulator/max77686-regulator.c2
-rw-r--r--drivers/regulator/max8660.c1
-rw-r--r--drivers/regulator/mt6358-regulator.c549
-rw-r--r--drivers/regulator/of_regulator.c4
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c193
-rw-r--r--drivers/regulator/rk808-regulator.c2
-rw-r--r--drivers/regulator/s2mps11.c2
-rw-r--r--drivers/regulator/slg51000-regulator.c15
-rw-r--r--drivers/regulator/stm32-booster.c4
-rw-r--r--drivers/regulator/sy8824x.c232
-rw-r--r--drivers/regulator/tps65132-regulator.c4
-rw-r--r--drivers/regulator/twl-regulator.c23
-rw-r--r--drivers/regulator/twl6030-regulator.c21
-rw-r--r--drivers/regulator/uniphier-regulator.c4
-rw-r--r--drivers/reset/Kconfig13
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-imx7.c12
-rw-r--r--drivers/reset/reset-meson.c51
-rw-r--r--drivers/reset/reset-scmi.c124
-rw-r--r--drivers/reset/reset-simple.c3
-rw-r--r--drivers/s390/block/dasd_alias.c22
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/char/tape_core.c3
-rw-r--r--drivers/s390/cio/qdio_main.c24
-rw-r--r--drivers/s390/cio/vfio_ccw_async.c2
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c28
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c2
-rw-r--r--drivers/s390/crypto/ap_queue.c1
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype6.c17
-rw-r--r--drivers/s390/net/ctcm_fsms.c1
-rw-r--r--drivers/s390/net/ctcm_mpc.c3
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c24
-rw-r--r--drivers/s390/net/qeth_l2_main.c2
-rw-r--r--drivers/s390/virtio/virtio_ccw.c4
-rw-r--r--drivers/scsi/Kconfig4
-rw-r--r--drivers/scsi/arm/fas216.c8
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c7
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c140
-rw-r--r--drivers/scsi/hpsa.c18
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c2
-rw-r--r--drivers/scsi/libfc/fc_rport.c5
-rw-r--r--drivers/scsi/libsas/sas_discover.c1
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c15
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h5
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c5
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c27
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c12
-rw-r--r--drivers/scsi/qla1280.c37
-rw-r--r--drivers/scsi/qla1280.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c11
-rw-r--r--drivers/scsi/scsi_lib.c6
-rw-r--r--drivers/scsi/ufs/ufshcd.c3
-rw-r--r--drivers/sn/Kconfig22
-rw-r--r--drivers/sn/Makefile7
-rw-r--r--drivers/sn/ioc3.c844
-rw-r--r--drivers/soc/amlogic/Kconfig11
-rw-r--r--drivers/soc/amlogic/Makefile1
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c148
-rw-r--r--drivers/soc/amlogic/meson-ee-pwrc.c492
-rw-r--r--drivers/soc/amlogic/meson-gx-socinfo.c7
-rw-r--r--drivers/soc/fsl/dpaa2-console.c2
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c2
-rw-r--r--drivers/soc/fsl/guts.c6
-rw-r--r--drivers/soc/fsl/qbman/bman.c17
-rw-r--r--drivers/soc/fsl/qbman/bman_ccsr.c36
-rw-r--r--drivers/soc/fsl/qbman/bman_portal.c22
-rw-r--r--drivers/soc/fsl/qbman/bman_priv.h5
-rw-r--r--drivers/soc/fsl/qbman/dpaa_sys.c63
-rw-r--r--drivers/soc/fsl/qbman/qman.c83
-rw-r--r--drivers/soc/fsl/qbman/qman_ccsr.c68
-rw-r--r--drivers/soc/fsl/qbman/qman_portal.c22
-rw-r--r--drivers/soc/fsl/qbman/qman_priv.h8
-rw-r--r--drivers/soc/fsl/qe/qe.c165
-rw-r--r--drivers/soc/imx/gpcv2.c2
-rw-r--r--drivers/soc/imx/soc-imx-scu.c39
-rw-r--r--drivers/soc/imx/soc-imx8.c45
-rw-r--r--drivers/soc/ixp4xx/Kconfig4
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c10
-rw-r--r--drivers/soc/qcom/Kconfig8
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c6
-rw-r--r--drivers/soc/qcom/qcom_aoss.c133
-rw-r--r--drivers/soc/qcom/smem.c11
-rw-r--r--drivers/soc/qcom/socinfo.c476
-rw-r--r--drivers/soc/renesas/Kconfig11
-rw-r--r--drivers/soc/renesas/rcar-sysc.c7
-rw-r--r--drivers/soc/renesas/rmobile-sysc.c31
-rw-r--r--drivers/soc/samsung/Kconfig6
-rw-r--r--drivers/soc/samsung/Makefile2
-rw-r--r--drivers/soc/samsung/exynos-chipid.c105
-rw-r--r--drivers/soc/ti/pm33xx.c19
-rw-r--r--drivers/soc/ti/ti_sci_pm_domains.c23
-rw-r--r--drivers/soc/ux500/ux500-soc-id.c5
-rw-r--r--drivers/soundwire/Kconfig7
-rw-r--r--drivers/soundwire/Makefile2
-rw-r--r--drivers/soundwire/cadence_master.c8
-rw-r--r--drivers/spi/Kconfig17
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/atmel-quadspi.c1
-rw-r--r--drivers/spi/spi-altera.c4
-rw-r--r--drivers/spi/spi-armada-3700.c5
-rw-r--r--drivers/spi/spi-ath79.c4
-rw-r--r--drivers/spi/spi-atmel.c5
-rw-r--r--drivers/spi/spi-axi-spi-engine.c4
-rw-r--r--drivers/spi/spi-bcm-qspi.c5
-rw-r--r--drivers/spi/spi-bcm2835.c469
-rw-r--r--drivers/spi/spi-bcm2835aux.c5
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c8
-rw-r--r--drivers/spi/spi-bcm63xx.c4
-rw-r--r--drivers/spi/spi-cadence.c5
-rw-r--r--drivers/spi/spi-cavium-octeon.c4
-rw-r--r--drivers/spi/spi-clps711x.c4
-rw-r--r--drivers/spi/spi-coldfire-qspi.c4
-rw-r--r--drivers/spi/spi-dw-mmio.c18
-rw-r--r--drivers/spi/spi-dw-pci.c20
-rw-r--r--drivers/spi/spi-efm32.c4
-rw-r--r--drivers/spi/spi-ep93xx.c4
-rw-r--r--drivers/spi/spi-fsl-cpm.c6
-rw-r--r--drivers/spi/spi-fsl-dspi.c718
-rw-r--r--drivers/spi/spi-fsl-lib.h3
-rw-r--r--drivers/spi/spi-fsl-qspi.c6
-rw-r--r--drivers/spi/spi-fsl-spi.c193
-rw-r--r--drivers/spi/spi-geni-qcom.c8
-rw-r--r--drivers/spi/spi-gpio.c11
-rw-r--r--drivers/spi/spi-lantiq-ssc.c12
-rw-r--r--drivers/spi/spi-lp8841-rtc.c4
-rw-r--r--drivers/spi/spi-meson-spicc.c4
-rw-r--r--drivers/spi/spi-meson-spifc.c4
-rw-r--r--drivers/spi/spi-mt65xx.c54
-rw-r--r--drivers/spi/spi-mt7621.c4
-rw-r--r--drivers/spi/spi-mxs.c4
-rw-r--r--drivers/spi/spi-npcm-fiu.c769
-rw-r--r--drivers/spi/spi-npcm-pspi.c5
-rw-r--r--drivers/spi/spi-nuc900.c429
-rw-r--r--drivers/spi/spi-nxp-fspi.c4
-rw-r--r--drivers/spi/spi-oc-tiny.c4
-rw-r--r--drivers/spi/spi-pic32-sqi.c5
-rw-r--r--drivers/spi/spi-pic32.c12
-rw-r--r--drivers/spi/spi-pxa2xx.c14
-rw-r--r--drivers/spi/spi-qcom-qspi.c8
-rw-r--r--drivers/spi/spi-rb4xx.c4
-rw-r--r--drivers/spi/spi-s3c24xx.c5
-rw-r--r--drivers/spi/spi-sh-msiof.c5
-rw-r--r--drivers/spi/spi-sh.c4
-rw-r--r--drivers/spi/spi-sifive.c5
-rw-r--r--drivers/spi/spi-sirf.c4
-rw-r--r--drivers/spi/spi-slave-mt27xx.c1
-rw-r--r--drivers/spi/spi-sprd-adi.c92
-rw-r--r--drivers/spi/spi-sprd.c4
-rw-r--r--drivers/spi/spi-st-ssc4.c4
-rw-r--r--drivers/spi/spi-stm32-qspi.c5
-rw-r--r--drivers/spi/spi-sun4i.c5
-rw-r--r--drivers/spi/spi-sun6i.c5
-rw-r--r--drivers/spi/spi-synquacer.c2
-rw-r--r--drivers/spi/spi-tegra20-sflash.c4
-rw-r--r--drivers/spi/spi-ti-qspi.c1
-rw-r--r--drivers/spi/spi-uniphier.c90
-rw-r--r--drivers/spi/spi-xlp.c8
-rw-r--r--drivers/spi/spi-zynq-qspi.c7
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c5
-rw-r--r--drivers/spi/spi.c53
-rw-r--r--drivers/staging/android/ion/ion_page_pool.c3
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c8
-rw-r--r--drivers/staging/fbtft/fb_bd663474.c2
-rw-r--r--drivers/staging/fbtft/fb_ili9163.c2
-rw-r--r--drivers/staging/fbtft/fb_ili9325.c2
-rw-r--r--drivers/staging/fbtft/fb_s6d1121.c2
-rw-r--r--drivers/staging/fbtft/fb_ssd1289.c2
-rw-r--r--drivers/staging/fbtft/fb_ssd1331.c4
-rw-r--r--drivers/staging/fbtft/fb_upd161704.c2
-rw-r--r--drivers/staging/fbtft/fbtft-bus.c2
-rw-r--r--drivers/staging/fbtft/fbtft-core.c47
-rw-r--r--drivers/staging/gasket/apex_driver.c2
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c3
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c1
-rw-r--r--drivers/target/iscsi/cxgbit/cxgbit_cm.c8
-rw-r--r--drivers/target/iscsi/cxgbit/cxgbit_main.c3
-rw-r--r--drivers/target/target_core_user.c9
-rw-r--r--drivers/tee/optee/call.c1
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c4
-rw-r--r--drivers/tty/hvc/hvcs.c2
-rw-r--r--drivers/tty/serial/Kconfig49
-rw-r--r--drivers/tty/serial/Makefile4
-rw-r--r--drivers/tty/serial/ioc3_serial.c2195
-rw-r--r--drivers/tty/serial/ioc4_serial.c2955
-rw-r--r--drivers/tty/serial/kgdboc.c4
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c37
-rw-r--r--drivers/tty/serial/netx-serial.c733
-rw-r--r--drivers/tty/serial/sn_console.c1036
-rw-r--r--drivers/tty/tty_ldsem.c5
-rw-r--r--drivers/tty/vt/vt.c6
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c19
-rw-r--r--drivers/usb/chipidea/udc.c32
-rw-r--r--drivers/usb/class/cdc-acm.c12
-rw-r--r--drivers/usb/class/cdc-wdm.c16
-rw-r--r--drivers/usb/class/usbtmc.c3
-rw-r--r--drivers/usb/core/buffer.c10
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/file.c10
-rw-r--r--drivers/usb/core/hcd-pci.c30
-rw-r--r--drivers/usb/core/hcd.c131
-rw-r--r--drivers/usb/core/message.c4
-rw-r--r--drivers/usb/core/sysfs.c121
-rw-r--r--drivers/usb/core/usb.h5
-rw-r--r--drivers/usb/dwc2/hcd.c2
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c28
-rw-r--r--drivers/usb/gadget/udc/Kconfig3
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c5
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c5
-rw-r--r--drivers/usb/host/Kconfig3
-rw-r--r--drivers/usb/host/ehci-pci.c4
-rw-r--r--drivers/usb/host/fotg210-hcd.c4
-rw-r--r--drivers/usb/host/hwa-hc.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c15
-rw-r--r--drivers/usb/host/ohci-nxp.c25
-rw-r--r--drivers/usb/host/ohci-pci.c2
-rw-r--r--drivers/usb/host/pci-quirks.c45
-rw-r--r--drivers/usb/host/pci-quirks.h2
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/host/xhci-rcar.c11
-rw-r--r--drivers/usb/host/xhci-tegra.c10
-rw-r--r--drivers/usb/host/xhci.c10
-rw-r--r--drivers/usb/host/xhci.h3
-rw-r--r--drivers/usb/misc/iowarrior.c7
-rw-r--r--drivers/usb/misc/rio500.c43
-rw-r--r--drivers/usb/misc/usb251xb.c15
-rw-r--r--drivers/usb/misc/yurex.c2
-rw-r--r--drivers/usb/serial/option.c10
-rw-r--r--drivers/usb/storage/realtek_cr.c15
-rw-r--r--drivers/usb/storage/scsiglue.c11
-rw-r--r--drivers/usb/storage/unusual_devs.h2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c60
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c2
-rw-r--r--drivers/vfio/vfio_iommu_type1.c27
-rw-r--r--drivers/vhost/test.c13
-rw-r--r--drivers/vhost/vhost.c524
-rw-r--r--drivers/vhost/vhost.h41
-rw-r--r--drivers/video/fbdev/Kconfig14
-rw-r--r--drivers/video/fbdev/Makefile1
-rw-r--r--drivers/video/fbdev/acornfb.c1
-rw-r--r--drivers/video/fbdev/atafb.c42
-rw-r--r--drivers/video/fbdev/da8xx-fb.c118
-rw-r--r--drivers/video/fbdev/nuc900fb.c760
-rw-r--r--drivers/video/fbdev/nuc900fb.h51
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c8
-rw-r--r--drivers/virtio/virtio_ring.c8
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/ar7_wdt.c1
-rw-r--r--drivers/watchdog/pcwd.c2
-rw-r--r--drivers/watchdog/pnx4008_wdt.c1
-rw-r--r--drivers/watchdog/riowd.c2
-rw-r--r--drivers/watchdog/sb_wdog.c1
-rw-r--r--drivers/watchdog/scx200_wdt.c1
-rw-r--r--drivers/watchdog/wdt.c2
-rw-r--r--drivers/watchdog/wdt285.c2
-rw-r--r--drivers/watchdog/wdt977.c2
-rw-r--r--drivers/xen/gntdev.c2
-rw-r--r--drivers/xen/privcmd.c35
-rw-r--r--drivers/xen/swiotlb-xen.c42
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability.c3
-rw-r--r--drivers/xen/xlate_mmu.c32
-rw-r--r--fs/afs/cell.c4
-rw-r--r--fs/afs/cmservice.c10
-rw-r--r--fs/afs/dir.c92
-rw-r--r--fs/afs/file.c12
-rw-r--r--fs/afs/fsclient.c51
-rw-r--r--fs/afs/vlclient.c11
-rw-r--r--fs/afs/yfsclient.c56
-rw-r--r--fs/block_dev.c86
-rw-r--r--fs/btrfs/backref.c2
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent-tree.c71
-rw-r--r--fs/btrfs/extent_io.c35
-rw-r--r--fs/btrfs/locking.c9
-rw-r--r--fs/btrfs/ordered-data.c11
-rw-r--r--fs/btrfs/send.c77
-rw-r--r--fs/btrfs/transaction.c32
-rw-r--r--fs/btrfs/transaction.h3
-rw-r--r--fs/btrfs/tree-log.c16
-rw-r--r--fs/btrfs/volumes.c13
-rw-r--r--fs/ceph/addr.c5
-rw-r--r--fs/ceph/caps.c5
-rw-r--r--fs/ceph/inode.c7
-rw-r--r--fs/ceph/locks.c3
-rw-r--r--fs/ceph/snap.c4
-rw-r--r--fs/ceph/super.h2
-rw-r--r--fs/ceph/xattr.c19
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c197
-rw-r--r--fs/cifs/connect.c30
-rw-r--r--fs/cifs/dir.c5
-rw-r--r--fs/cifs/misc.c22
-rw-r--r--fs/cifs/sess.c26
-rw-r--r--fs/cifs/smb2ops.c39
-rw-r--r--fs/cifs/smb2pdu.c7
-rw-r--r--fs/compat_ioctl.c3
-rw-r--r--fs/configfs/configfs_internal.h15
-rw-r--r--fs/configfs/dir.c137
-rw-r--r--fs/configfs/file.c280
-rw-r--r--fs/coredump.c44
-rw-r--r--fs/dax.c4
-rw-r--r--fs/exec.c2
-rw-r--r--fs/ext4/inode.c3
-rw-r--r--fs/f2fs/file.c63
-rw-r--r--fs/f2fs/gc.c70
-rw-r--r--fs/f2fs/super.c48
-rw-r--r--fs/gfs2/bmap.c179
-rw-r--r--fs/io_uring.c162
-rw-r--r--fs/iomap/Makefile2
-rw-r--r--fs/namespace.c4
-rw-r--r--fs/nfs/delegation.c25
-rw-r--r--fs/nfs/delegation.h2
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfs/direct.c27
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c28
-rw-r--r--fs/nfs/fscache.c7
-rw-r--r--fs/nfs/fscache.h2
-rw-r--r--fs/nfs/inode.c35
-rw-r--r--fs/nfs/internal.h10
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4client.c5
-rw-r--r--fs/nfs/nfs4file.c12
-rw-r--r--fs/nfs/nfs4proc.c109
-rw-r--r--fs/nfs/nfs4state.c49
-rw-r--r--fs/nfs/pagelist.c19
-rw-r--r--fs/nfs/pnfs.c7
-rw-r--r--fs/nfs/pnfs_nfs.c15
-rw-r--r--fs/nfs/proc.c7
-rw-r--r--fs/nfs/read.c35
-rw-r--r--fs/nfs/super.c1
-rw-r--r--fs/nfs/write.c38
-rw-r--r--fs/nfsd/nfscache.c2
-rw-r--r--fs/nfsd/nfsctl.c19
-rw-r--r--fs/ocfs2/xattr.c3
-rw-r--r--fs/open.c19
-rw-r--r--fs/read_write.c49
-rw-r--r--fs/seq_file.c2
-rw-r--r--fs/super.c5
-rw-r--r--fs/ubifs/budget.c2
-rw-r--r--fs/ubifs/orphan.c2
-rw-r--r--fs/ubifs/super.c4
-rw-r--r--fs/userfaultfd.c25
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c29
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c19
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c3
-rw-r--r--fs/xfs/scrub/dabtree.c6
-rw-r--r--fs/xfs/xfs_ioctl32.c56
-rw-r--r--fs/xfs/xfs_iops.c1
-rw-r--r--fs/xfs/xfs_itable.c3
-rw-r--r--fs/xfs/xfs_log.c5
-rw-r--r--fs/xfs/xfs_pnfs.c2
-rw-r--r--fs/xfs/xfs_reflink.c63
-rw-r--r--include/Kbuild2
-rw-r--r--include/asm-generic/5level-fixup.h21
-rw-r--r--include/asm-generic/div64.h6
-rw-r--r--include/asm-generic/error-injection.h6
-rw-r--r--include/asm-generic/futex.h21
-rw-r--r--include/asm-generic/getorder.h50
-rw-r--r--include/asm-generic/preempt.h4
-rw-r--r--include/drm/drm_client.h2
-rw-r--r--include/drm/drm_mode_config.h7
-rw-r--r--include/dt-bindings/bus/moxtet.h16
-rw-r--r--include/dt-bindings/clock/g12a-clkc.h6
-rw-r--r--include/dt-bindings/clock/imx8-clock.h6
-rw-r--r--include/dt-bindings/clock/imx8mn-clock.h215
-rw-r--r--include/dt-bindings/memory/mt8183-larb-port.h130
-rw-r--r--include/dt-bindings/power/meson-g12a-power.h13
-rw-r--r--include/dt-bindings/power/meson-sm1-power.h18
-rw-r--r--include/dt-bindings/regulator/active-semi,8865-regulator.h28
-rw-r--r--include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h38
-rw-r--r--include/dt-bindings/reset/amlogic,meson-gxbb-reset.h51
-rw-r--r--include/dt-bindings/reset/amlogic,meson8b-reset.h51
-rw-r--r--include/dt-bindings/reset/imx8mq-reset.h34
-rw-r--r--include/dt-bindings/reset/mt7629-resets.h71
-rw-r--r--include/dt-bindings/soc/ti,sci_pm_domain.h9
-rw-r--r--include/kvm/arm_pmu.h2
-rw-r--r--include/kvm/arm_vgic.h1
-rw-r--r--include/linux/acpi.h56
-rw-r--r--include/linux/amd-iommu.h12
-rw-r--r--include/linux/arch_topology.h26
-rw-r--r--include/linux/bitmap.h23
-rw-r--r--include/linux/blk-cgroup.h1
-rw-r--r--include/linux/blk_types.h5
-rw-r--r--include/linux/bug.h5
-rw-r--r--include/linux/ccp.h2
-rw-r--r--include/linux/ceph/buffer.h3
-rw-r--r--include/linux/cgroup.h1
-rw-r--r--include/linux/clk-provider.h1
-rw-r--r--include/linux/clk.h1
-rw-r--r--include/linux/compiler.h8
-rw-r--r--include/linux/cpuidle.h17
-rw-r--r--include/linux/cpumask.h41
-rw-r--r--include/linux/cpuset.h13
-rw-r--r--include/linux/cred.h8
-rw-r--r--include/linux/device.h6
-rw-r--r--include/linux/dim.h56
-rw-r--r--include/linux/dma-contiguous.h5
-rw-r--r--include/linux/dma-mapping.h4
-rw-r--r--include/linux/dma-noncoherent.h13
-rw-r--r--include/linux/edac.h10
-rw-r--r--include/linux/efi.h14
-rw-r--r--include/linux/elevator.h1
-rw-r--r--include/linux/error-injection.h6
-rw-r--r--include/linux/filter.h13
-rw-r--r--include/linux/firmware/imx/dsp.h67
-rw-r--r--include/linux/fs.h6
-rw-r--r--include/linux/gfp.h12
-rw-r--r--include/linux/gpio.h37
-rw-r--r--include/linux/gpio/consumer.h199
-rw-r--r--include/linux/gpio/driver.h178
-rw-r--r--include/linux/hmm.h54
-rw-r--r--include/linux/i3c/device.h4
-rw-r--r--include/linux/i3c/master.h5
-rw-r--r--include/linux/if_pppox.h3
-rw-r--r--include/linux/if_rmnet.h4
-rw-r--r--include/linux/input/elan-i2c-ids.h2
-rw-r--r--include/linux/intel-iommu.h5
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--include/linux/io-pgtable.h66
-rw-r--r--include/linux/ioc4.h184
-rw-r--r--include/linux/iommu.h108
-rw-r--r--include/linux/iova.h6
-rw-r--r--include/linux/irqchip/arm-gic-v3.h30
-rw-r--r--include/linux/irqchip/irq-partition-percpu.h5
-rw-r--r--include/linux/irqdomain.h6
-rw-r--r--include/linux/kexec.h23
-rw-r--r--include/linux/key.h8
-rw-r--r--include/linux/kvm_host.h6
-rw-r--r--include/linux/lockdep.h11
-rw-r--r--include/linux/logic_pio.h1
-rw-r--r--include/linux/memcontrol.h19
-rw-r--r--include/linux/mempolicy.h2
-rw-r--r--include/linux/mlx5/device.h4
-rw-r--r--include/linux/mlx5/fs.h1
-rw-r--r--include/linux/mlx5/mlx5_ifc.h11
-rw-r--r--include/linux/mm_types.h11
-rw-r--r--include/linux/mmzone.h5
-rw-r--r--include/linux/mod_devicetable.h1
-rw-r--r--include/linux/moxtet.h109
-rw-r--r--include/linux/mutex.h25
-rw-r--r--include/linux/netfilter/nf_conntrack_h323_types.h5
-rw-r--r--include/linux/of.h2
-rw-r--r--include/linux/of_gpio.h11
-rw-r--r--include/linux/omap-iommu.h15
-rw-r--r--include/linux/page-flags-layout.h18
-rw-r--r--include/linux/page-flags.h4
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/perf_event.h14
-rw-r--r--include/linux/phy.h1
-rw-r--r--include/linux/phy_fixed.h1
-rw-r--r--include/linux/pid.h4
-rw-r--r--include/linux/platform_data/dma-iop32x.h (renamed from arch/arm/include/asm/hardware/iop_adma.h)4
-rw-r--r--include/linux/platform_data/gpio-htc-egpio.h3
-rw-r--r--include/linux/platform_data/iommu-omap.h4
-rw-r--r--include/linux/platform_data/spi-nuc900.h29
-rw-r--r--include/linux/platform_data/video-nuc900fb.h79
-rw-r--r--include/linux/platform_data/x86/asus-wmi.h8
-rw-r--r--include/linux/preempt.h6
-rw-r--r--include/linux/psci.h4
-rw-r--r--include/linux/qcom_scm.h9
-rw-r--r--include/linux/random.h1
-rw-r--r--include/linux/rcu_segcblist.h9
-rw-r--r--include/linux/rcu_sync.h4
-rw-r--r--include/linux/rculist.h36
-rw-r--r--include/linux/rcupdate.h11
-rw-r--r--include/linux/rcutiny.h2
-rw-r--r--include/linux/rcutree.h2
-rw-r--r--include/linux/regulator/consumer.h13
-rw-r--r--include/linux/regulator/mt6358-regulator.h56
-rw-r--r--include/linux/rwsem.h10
-rw-r--r--include/linux/sched.h21
-rw-r--r--include/linux/sched/deadline.h8
-rw-r--r--include/linux/sched/numa_balancing.h4
-rw-r--r--include/linux/sched/task.h6
-rw-r--r--include/linux/sched/topology.h10
-rw-r--r--include/linux/scmi_protocol.h46
-rw-r--r--include/linux/signal.h15
-rw-r--r--include/linux/skbuff.h8
-rw-r--r--include/linux/skmsg.h8
-rw-r--r--include/linux/soc/mediatek/mtk-cmdq.h14
-rw-r--r--include/linux/soc/nxp/lpc32xx-misc.h33
-rw-r--r--include/linux/soc/samsung/exynos-chipid.h52
-rw-r--r--include/linux/soc/ti/ti_sci_protocol.h3
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/spinlock.h2
-rw-r--r--include/linux/spinlock_api_smp.h2
-rw-r--r--include/linux/stacktrace.h4
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--include/linux/swiotlb.h8
-rw-r--r--include/linux/sys_soc.h1
-rw-r--r--include/linux/syscalls.h19
-rw-r--r--include/linux/timekeeper_internal.h5
-rw-r--r--include/linux/topology.h15
-rw-r--r--include/linux/torture.h2
-rw-r--r--include/linux/trace_events.h1
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/hcd.h3
-rw-r--r--include/linux/usb/samsung_usb_phy.h17
-rw-r--r--include/linux/wait.h13
-rw-r--r--include/math-emu/op-common.h5
-rw-r--r--include/net/act_api.h4
-rw-r--r--include/net/addrconf.h2
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--include/net/cfg80211.h15
-rw-r--r--include/net/inet_frag.h2
-rw-r--r--include/net/ip_fib.h4
-rw-r--r--include/net/net_namespace.h3
-rw-r--r--include/net/netfilter/nf_tables.h9
-rw-r--r--include/net/netfilter/nf_tables_offload.h2
-rw-r--r--include/net/netlink.h5
-rw-r--r--include/net/nexthop.h11
-rw-r--r--include/net/pkt_cls.h2
-rw-r--r--include/net/psample.h1
-rw-r--r--include/net/route.h2
-rw-r--r--include/net/sock.h10
-rw-r--r--include/net/tc_act/tc_police.h4
-rw-r--r--include/net/tc_act/tc_sample.h2
-rw-r--r--include/net/tcp.h3
-rw-r--r--include/net/tls.h13
-rw-r--r--include/net/xfrm.h2
-rw-r--r--include/rdma/ib_verbs.h4
-rw-r--r--include/rdma/rdmavt_qp.h9
-rw-r--r--include/rdma/restrack.h3
-rw-r--r--include/scsi/libfc.h52
-rw-r--r--include/scsi/libfcoe.h3
-rw-r--r--include/soc/arc/mcip.h11
-rw-r--r--include/soc/fsl/qe/qe.h2
-rw-r--r--include/soc/mediatek/smi.h5
-rw-r--r--include/sound/compress_driver.h5
-rw-r--r--include/sound/simple_card_utils.h4
-rw-r--r--include/sound/sof/control.h2
-rw-r--r--include/sound/sof/dai-intel.h2
-rw-r--r--include/sound/sof/dai.h2
-rw-r--r--include/sound/sof/header.h2
-rw-r--r--include/sound/sof/info.h2
-rw-r--r--include/sound/sof/pm.h2
-rw-r--r--include/sound/sof/stream.h2
-rw-r--r--include/sound/sof/topology.h2
-rw-r--r--include/sound/sof/trace.h2
-rw-r--r--include/sound/sof/xtensa.h2
-rw-r--r--include/trace/events/dma_fence.h2
-rw-r--r--include/trace/events/intel_iommu.h106
-rw-r--r--include/trace/events/napi.h4
-rw-r--r--include/trace/events/qdisc.h4
-rw-r--r--include/trace/events/rcu.h4
-rw-r--r--include/trace/events/rxrpc.h65
-rw-r--r--include/trace/events/tegra_apb_dma.h4
-rw-r--r--include/uapi/asm-generic/unistd.h2
-rw-r--r--include/uapi/linux/bpf.h4
-rw-r--r--include/uapi/linux/bpfilter.h2
-rw-r--r--include/uapi/linux/ipmi_bmc.h2
-rw-r--r--include/uapi/linux/isdn/capicmd.h1
-rw-r--r--include/uapi/linux/isst_if.h2
-rw-r--r--include/uapi/linux/jffs2.h5
-rw-r--r--include/uapi/linux/kexec.h1
-rw-r--r--include/uapi/linux/kfd_ioctl.h20
-rw-r--r--include/uapi/linux/kvm.h4
-rw-r--r--include/uapi/linux/netfilter/nf_synproxy.h2
-rw-r--r--include/uapi/linux/netfilter/xt_connlabel.h6
-rw-r--r--include/uapi/linux/netfilter/xt_nfacct.h5
-rw-r--r--include/uapi/linux/perf_event.h3
-rw-r--r--include/uapi/linux/prctl.h7
-rw-r--r--include/uapi/linux/psp-sev.h2
-rw-r--r--include/uapi/linux/rds.h2
-rw-r--r--include/uapi/linux/rxrpc.h2
-rw-r--r--include/uapi/linux/serial_core.h3
-rw-r--r--include/uapi/linux/socket.h19
-rw-r--r--include/uapi/linux/usb/g_uvc.h2
-rw-r--r--include/uapi/linux/vbox_vmmdev_types.h2
-rw-r--r--include/uapi/linux/vboxguest.h2
-rw-r--r--include/uapi/linux/virtio_iommu.h32
-rw-r--r--include/uapi/linux/virtio_pmem.h2
-rw-r--r--include/uapi/linux/vmcore.h2
-rw-r--r--include/uapi/linux/wait.h1
-rw-r--r--include/uapi/linux/wmi.h2
-rw-r--r--include/uapi/misc/fastrpc.h2
-rw-r--r--include/uapi/rdma/rvt-abi.h2
-rw-r--r--include/uapi/rdma/siw-abi.h5
-rw-r--r--include/uapi/scsi/scsi_bsg_ufs.h2
-rw-r--r--include/uapi/sound/skl-tplg-interface.h2
-rw-r--r--include/uapi/sound/sof/fw.h16
-rw-r--r--include/uapi/sound/sof/header.h14
-rw-r--r--include/video/da8xx-fb.h1
-rw-r--r--include/xen/xen-ops.h3
-rw-r--r--init/Kconfig25
-rw-r--r--init/init_task.c2
-rw-r--r--init/main.c2
-rw-r--r--ipc/util.h25
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/bpf/core.c8
-rw-r--r--kernel/bpf/syscall.c30
-rw-r--r--kernel/bpf/verifier.c36
-rw-r--r--kernel/cgroup/cgroup.c12
-rw-r--r--kernel/cgroup/cpuset.c163
-rw-r--r--kernel/configs.c16
-rw-r--r--kernel/cpu.c35
-rw-r--r--kernel/cred.c21
-rw-r--r--kernel/dma/contiguous.c16
-rw-r--r--kernel/dma/direct.c22
-rw-r--r--kernel/dma/mapping.c32
-rw-r--r--kernel/dma/remap.c2
-rw-r--r--kernel/dma/swiotlb.c34
-rw-r--r--kernel/events/core.c104
-rw-r--r--kernel/events/hw_breakpoint.c4
-rw-r--r--kernel/exit.c43
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/irq/affinity.c237
-rw-r--r--kernel/irq/irqdesc.c15
-rw-r--r--kernel/irq/irqdomain.c10
-rw-r--r--kernel/irq/manage.c5
-rw-r--r--kernel/irq/proc.c14
-rw-r--r--kernel/irq/resend.c2
-rw-r--r--kernel/jump_label.c4
-rw-r--r--kernel/kallsyms.c6
-rw-r--r--kernel/kexec_elf.c430
-rw-r--r--kernel/kprobes.c13
-rw-r--r--kernel/locking/lockdep.c174
-rw-r--r--kernel/locking/lockdep_internals.h9
-rw-r--r--kernel/locking/lockdep_proc.c11
-rw-r--r--kernel/locking/mutex.c37
-rw-r--r--kernel/locking/rtmutex.c6
-rw-r--r--kernel/locking/rwsem.c82
-rw-r--r--kernel/module.c4
-rw-r--r--kernel/rcu/Kconfig8
-rw-r--r--kernel/rcu/Kconfig.debug11
-rw-r--r--kernel/rcu/rcu.h1
-rw-r--r--kernel/rcu/rcu_segcblist.c174
-rw-r--r--kernel/rcu/rcu_segcblist.h54
-rw-r--r--kernel/rcu/rcuperf.c10
-rw-r--r--kernel/rcu/rcutorture.c30
-rw-r--r--kernel/rcu/srcutree.c5
-rw-r--r--kernel/rcu/tree.c217
-rw-r--r--kernel/rcu/tree.h81
-rw-r--r--kernel/rcu/tree_exp.h8
-rw-r--r--kernel/rcu/tree_plugin.h1195
-rw-r--r--kernel/rcu/tree_stall.h15
-rw-r--r--kernel/rcu/update.c105
-rw-r--r--kernel/sched/core.c701
-rw-r--r--kernel/sched/cpufreq_schedutil.c20
-rw-r--r--kernel/sched/deadline.c142
-rw-r--r--kernel/sched/fair.c556
-rw-r--r--kernel/sched/idle.c36
-rw-r--r--kernel/sched/isolation.c12
-rw-r--r--kernel/sched/psi.c14
-rw-r--r--kernel/sched/rt.c74
-rw-r--r--kernel/sched/sched.h63
-rw-r--r--kernel/sched/stats.h7
-rw-r--r--kernel/sched/stop_task.c22
-rw-r--r--kernel/sched/topology.c53
-rw-r--r--kernel/signal.c15
-rw-r--r--kernel/stacktrace.c4
-rw-r--r--kernel/stop_machine.c2
-rw-r--r--kernel/sys.c32
-rw-r--r--kernel/time/alarmtimer.c4
-rw-r--r--kernel/time/timekeeping.c5
-rw-r--r--kernel/time/vsyscall.c22
-rw-r--r--kernel/torture.c2
-rw-r--r--kernel/trace/Kconfig6
-rw-r--r--kernel/trace/ftrace.c19
-rw-r--r--kernel/trace/ftrace_internal.h8
-rw-r--r--kernel/trace/ring_buffer_benchmark.c2
-rw-r--r--kernel/trace/trace.c30
-rw-r--r--kernel/trace/trace_events.c6
-rw-r--r--kernel/trace/trace_functions_graph.c17
-rw-r--r--kernel/trace/trace_probe.c3
-rw-r--r--kernel/trace/trace_sched_wakeup.c3
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/Kconfig.kasan11
-rw-r--r--lib/Makefile7
-rw-r--r--lib/bitmap.c20
-rw-r--r--lib/dim/dim.c4
-rw-r--r--lib/dim/net_dim.c56
-rw-r--r--lib/kfifo.c3
-rw-r--r--lib/logic_pio.c73
-rw-r--r--lib/raid6/Makefile2
-rw-r--r--lib/stackdepot.c4
-rw-r--r--lib/test_firmware.c5
-rw-r--r--lib/test_meminit.c2
-rw-r--r--lib/vdso/gettimeofday.c79
-rw-r--r--mm/Makefile1
-rw-r--r--mm/balloon_compaction.c72
-rw-r--r--mm/compaction.c11
-rw-r--r--mm/hmm.c10
-rw-r--r--mm/huge_memory.c55
-rw-r--r--mm/hugetlb.c19
-rw-r--r--mm/kasan/common.c10
-rw-r--r--mm/khugepaged.c2
-rw-r--r--mm/kmemleak.c4
-rw-r--r--mm/memcontrol.c146
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/mempolicy.c134
-rw-r--r--mm/memremap.c (renamed from kernel/memremap.c)30
-rw-r--r--mm/migrate.c21
-rw-r--r--mm/page_alloc.c21
-rw-r--r--mm/rmap.c8
-rw-r--r--mm/shmem.c2
-rw-r--r--mm/slub.c8
-rw-r--r--mm/usercopy.c2
-rw-r--r--mm/vmalloc.c21
-rw-r--r--mm/vmscan.c27
-rw-r--r--mm/workingset.c10
-rw-r--r--mm/z3fold.c104
-rw-r--r--mm/zsmalloc.c80
-rw-r--r--net/batman-adv/bat_iv_ogm.c20
-rw-r--r--net/batman-adv/bat_v_ogm.c18
-rw-r--r--net/batman-adv/multicast.c8
-rw-r--r--net/batman-adv/netlink.c2
-rw-r--r--net/bluetooth/hci_core.c1
-rw-r--r--net/bluetooth/hci_debugfs.c31
-rw-r--r--net/bluetooth/hci_event.c5
-rw-r--r--net/bluetooth/hidp/core.c9
-rw-r--r--net/bluetooth/l2cap_core.c11
-rw-r--r--net/bridge/br.c5
-rw-r--r--net/bridge/br_mdb.c2
-rw-r--r--net/bridge/br_multicast.c3
-rw-r--r--net/bridge/br_netfilter_hooks.c4
-rw-r--r--net/bridge/br_private.h9
-rw-r--r--net/bridge/br_vlan.c29
-rw-r--r--net/bridge/netfilter/ebtables.c40
-rw-r--r--net/bridge/netfilter/nft_meta_bridge.c12
-rw-r--r--net/can/gw.c48
-rw-r--r--net/ceph/crypto.c6
-rw-r--r--net/ceph/osd_client.c9
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/filter.c14
-rw-r--r--net/core/flow_dissector.c2
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/skbuff.c19
-rw-r--r--net/core/skmsg.c4
-rw-r--r--net/core/sock.c50
-rw-r--r--net/core/sock_diag.c3
-rw-r--r--net/core/sock_map.c22
-rw-r--r--net/core/stream.c16
-rw-r--r--net/dsa/switch.c3
-rw-r--r--net/dsa/tag_8021q.c2
-rw-r--r--net/dsa/tag_sja1105.c12
-rw-r--r--net/ieee802154/6lowpan/reassembly.c2
-rw-r--r--net/ieee802154/socket.c2
-rw-r--r--net/ipv4/fib_frontend.c3
-rw-r--r--net/ipv4/fib_semantics.c15
-rw-r--r--net/ipv4/fib_trie.c2
-rw-r--r--net/ipv4/icmp.c10
-rw-r--r--net/ipv4/igmp.c4
-rw-r--r--net/ipv4/inet_fragment.c41
-rw-r--r--net/ipv4/ip_fragment.c8
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv4/route.c17
-rw-r--r--net/ipv4/tcp.c33
-rw-r--r--net/ipv4/tcp_bpf.c6
-rw-r--r--net/ipv4/tcp_input.c2
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/tcp_ulp.c13
-rw-r--r--net/ipv6/addrconf.c19
-rw-r--r--net/ipv6/ip6_gre.c3
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/mcast.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c2
-rw-r--r--net/ipv6/ping.c2
-rw-r--r--net/ipv6/reassembly.c2
-rw-r--r--net/ipv6/route.c23
-rw-r--r--net/iucv/af_iucv.c14
-rw-r--r--net/l2tp/l2tp_ppp.c3
-rw-r--r--net/mac80211/cfg.c23
-rw-r--r--net/mac80211/iface.c1
-rw-r--r--net/mac80211/mlme.c10
-rw-r--r--net/mac80211/rx.c6
-rw-r--r--net/mac80211/sta_info.c4
-rw-r--r--net/mac80211/util.c7
-rw-r--r--net/mpls/mpls_iptunnel.c8
-rw-r--r--net/ncsi/ncsi-cmd.c13
-rw-r--r--net/ncsi/ncsi-rsp.c9
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c2
-rw-r--r--net/netfilter/ipset/ip_set_core.c2
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipmac.c6
-rw-r--r--net/netfilter/nf_conntrack_core.c16
-rw-r--r--net/netfilter/nf_conntrack_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c7
-rw-r--r--net/netfilter/nf_conntrack_standalone.c5
-rw-r--r--net/netfilter/nf_flow_table_core.c45
-rw-r--r--net/netfilter/nf_flow_table_ip.c44
-rw-r--r--net/netfilter/nf_tables_api.c19
-rw-r--r--net/netfilter/nf_tables_offload.c17
-rw-r--r--net/netfilter/nft_fib_netdev.c3
-rw-r--r--net/netfilter/nft_flow_offload.c15
-rw-r--r--net/netfilter/nft_meta.c16
-rw-r--r--net/netfilter/nft_socket.c6
-rw-r--r--net/netfilter/xt_nfacct.c36
-rw-r--r--net/netfilter/xt_physdev.c6
-rw-r--r--net/netrom/af_netrom.c1
-rw-r--r--net/openvswitch/conntrack.c20
-rw-r--r--net/openvswitch/datapath.c15
-rw-r--r--net/openvswitch/flow.c160
-rw-r--r--net/openvswitch/flow.h1
-rw-r--r--net/packet/af_packet.c7
-rw-r--r--net/psample/psample.c2
-rw-r--r--net/qrtr/tun.c5
-rw-r--r--net/rds/bind.c40
-rw-r--r--net/rds/ib.c16
-rw-r--r--net/rds/ib.h1
-rw-r--r--net/rds/ib_cm.c3
-rw-r--r--net/rds/rdma_transport.c15
-rw-r--r--net/rds/recv.c5
-rw-r--r--net/rxrpc/af_rxrpc.c9
-rw-r--r--net/rxrpc/ar-internal.h26
-rw-r--r--net/rxrpc/call_event.c23
-rw-r--r--net/rxrpc/call_object.c33
-rw-r--r--net/rxrpc/conn_client.c44
-rw-r--r--net/rxrpc/conn_event.c6
-rw-r--r--net/rxrpc/conn_object.c2
-rw-r--r--net/rxrpc/input.c359
-rw-r--r--net/rxrpc/local_event.c4
-rw-r--r--net/rxrpc/local_object.c104
-rw-r--r--net/rxrpc/output.c9
-rw-r--r--net/rxrpc/peer_event.c12
-rw-r--r--net/rxrpc/peer_object.c18
-rw-r--r--net/rxrpc/protocol.h9
-rw-r--r--net/rxrpc/recvmsg.c53
-rw-r--r--net/rxrpc/rxkad.c32
-rw-r--r--net/rxrpc/sendmsg.c14
-rw-r--r--net/rxrpc/skbuff.c40
-rw-r--r--net/sched/act_bpf.c11
-rw-r--r--net/sched/act_connmark.c11
-rw-r--r--net/sched/act_csum.c11
-rw-r--r--net/sched/act_ct.c11
-rw-r--r--net/sched/act_ctinfo.c11
-rw-r--r--net/sched/act_gact.c10
-rw-r--r--net/sched/act_ife.c15
-rw-r--r--net/sched/act_ipt.c11
-rw-r--r--net/sched/act_mirred.c15
-rw-r--r--net/sched/act_mpls.c10
-rw-r--r--net/sched/act_nat.c11
-rw-r--r--net/sched/act_pedit.c12
-rw-r--r--net/sched/act_police.c10
-rw-r--r--net/sched/act_sample.c18
-rw-r--r--net/sched/act_simple.c12
-rw-r--r--net/sched/act_skbedit.c25
-rw-r--r--net/sched/act_skbmod.c13
-rw-r--r--net/sched/act_tunnel_key.c10
-rw-r--r--net/sched/act_vlan.c27
-rw-r--r--net/sched/sch_api.c2
-rw-r--r--net/sched/sch_cbs.c19
-rw-r--r--net/sched/sch_codel.c6
-rw-r--r--net/sched/sch_generic.c28
-rw-r--r--net/sched/sch_hhf.c2
-rw-r--r--net/sched/sch_taprio.c34
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/sm_sideeffect.c4
-rw-r--r--net/sctp/socket.c28
-rw-r--r--net/sctp/stream.c1
-rw-r--r--net/smc/af_smc.c15
-rw-r--r--net/smc/smc_tx.c6
-rw-r--r--net/sunrpc/clnt.c47
-rw-r--r--net/sunrpc/xprt.c7
-rw-r--r--net/tipc/addr.c1
-rw-r--r--net/tipc/link.c92
-rw-r--r--net/tipc/msg.h8
-rw-r--r--net/tipc/name_distr.c3
-rw-r--r--net/tipc/netlink_compat.c11
-rw-r--r--net/tipc/socket.c3
-rw-r--r--net/tls/tls_device.c9
-rw-r--r--net/tls/tls_main.c99
-rw-r--r--net/tls/tls_sw.c83
-rw-r--r--net/vmw_vsock/hyperv_transport.c8
-rw-r--r--net/wireless/core.c6
-rw-r--r--net/wireless/nl80211.c4
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/util.c50
-rw-r--r--net/xdp/xdp_umem.c4
-rw-r--r--net/xfrm/xfrm_interface.c56
-rw-r--r--net/xfrm/xfrm_policy.c10
-rw-r--r--samples/auxdisplay/cfag12864b-example.c2
-rw-r--r--samples/vfio-mdev/mdpy-defs.h2
-rw-r--r--scripts/Kbuild.include3
-rw-r--r--scripts/Kconfig.include2
-rw-r--r--scripts/Makefile.build11
-rw-r--r--scripts/Makefile.kasan11
-rw-r--r--scripts/Makefile.lib2
-rw-r--r--scripts/Makefile.modpost86
-rw-r--r--scripts/coccinelle/api/atomic_as_refcounter.cocci1
-rwxr-xr-xscripts/gen_compile_commands.py4
-rwxr-xr-xscripts/headers_install.sh6
-rw-r--r--scripts/kconfig/confdata.c4
-rwxr-xr-xscripts/link-vmlinux.sh2
-rwxr-xr-xscripts/sphinx-pre-install118
-rwxr-xr-xscripts/tools-support-relr.sh16
-rw-r--r--security/Kconfig.hardening7
-rw-r--r--security/keys/request_key.c2
-rw-r--r--security/keys/request_key_auth.c6
-rw-r--r--security/keys/trusted.c13
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/sidtab.c5
-rw-r--r--sound/ac97/bus.c13
-rw-r--r--sound/core/compress_offload.c60
-rw-r--r--sound/core/pcm_native.c12
-rw-r--r--sound/core/seq/seq_clientmgr.c3
-rw-r--r--sound/core/seq/seq_fifo.c17
-rw-r--r--sound/core/seq/seq_fifo.h2
-rw-r--r--sound/firewire/oxfw/oxfw-pcm.c2
-rw-r--r--sound/firewire/packets-buffer.c2
-rw-r--r--sound/hda/hdac_i915.c10
-rw-r--r--sound/pci/hda/hda_auto_parser.c4
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_controller.c13
-rw-r--r--sound/pci/hda/hda_controller.h2
-rw-r--r--sound/pci/hda/hda_generic.c24
-rw-r--r--sound/pci/hda/hda_generic.h2
-rw-r--r--sound/pci/hda/hda_intel.c71
-rw-r--r--sound/pci/hda/patch_ca0132.c1
-rw-r--r--sound/pci/hda/patch_conexant.c33
-rw-r--r--sound/pci/hda/patch_realtek.c29
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c20
-rw-r--r--sound/soc/codecs/cs42xx8.c116
-rw-r--r--sound/soc/codecs/max98357a.c25
-rw-r--r--sound/soc/codecs/max98373.c6
-rw-r--r--sound/soc/codecs/max98373.h2
-rw-r--r--sound/soc/codecs/pcm3060-i2c.c4
-rw-r--r--sound/soc/codecs/pcm3060-spi.c4
-rw-r--r--sound/soc/codecs/pcm3060.c4
-rw-r--r--sound/soc/codecs/pcm3060.h2
-rw-r--r--sound/soc/codecs/rt1011.c4
-rw-r--r--[-rwxr-xr-x]sound/soc/codecs/rt1308.c0
-rw-r--r--[-rwxr-xr-x]sound/soc/codecs/rt1308.h0
-rw-r--r--sound/soc/generic/audio-graph-card.c30
-rw-r--r--sound/soc/generic/simple-card-utils.c7
-rw-r--r--sound/soc/generic/simple-card.c26
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c1
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c8
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c1
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c1
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-bxt-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-byt-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cht-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-glk-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hda-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-icl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-skl-match.c2
-rw-r--r--sound/soc/qcom/apq8016_sbc.c16
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c5
-rw-r--r--sound/soc/rockchip/rockchip_max98090.c32
-rw-r--r--sound/soc/samsung/odroid.c8
-rw-r--r--sound/soc/soc-core.c7
-rw-r--r--sound/soc/soc-dapm.c10
-rw-r--r--sound/soc/sof/intel/cnl.c4
-rw-r--r--sound/soc/sof/intel/hda-ipc.c4
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c4
-rw-r--r--sound/soc/ti/davinci-mcasp.c46
-rw-r--r--sound/sound_core.c3
-rw-r--r--sound/usb/helper.c2
-rw-r--r--sound/usb/hiface/pcm.c11
-rw-r--r--sound/usb/line6/pcm.c18
-rw-r--r--sound/usb/line6/podhd.c2
-rw-r--r--sound/usb/line6/variax.c2
-rw-r--r--sound/usb/mixer.c73
-rw-r--r--sound/usb/mixer_quirks.c8
-rw-r--r--sound/usb/pcm.c1
-rw-r--r--sound/usb/stream.c1
-rw-r--r--tools/Makefile4
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h12
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h10
-rw-r--r--tools/arch/powerpc/include/uapi/asm/mman.h4
-rw-r--r--tools/arch/riscv/include/uapi/asm/perf_regs.h42
-rw-r--r--tools/arch/sparc/include/uapi/asm/mman.h4
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h4
-rw-r--r--tools/arch/x86/include/asm/inat.h (renamed from tools/perf/util/intel-pt-decoder/inat.h)0
-rw-r--r--tools/arch/x86/include/asm/inat_types.h (renamed from tools/objtool/arch/x86/include/asm/inat_types.h)0
-rw-r--r--tools/arch/x86/include/asm/insn.h (renamed from tools/perf/util/intel-pt-decoder/insn.h)0
-rw-r--r--tools/arch/x86/include/asm/orc_types.h (renamed from tools/objtool/arch/x86/include/asm/orc_types.h)0
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h22
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h1
-rw-r--r--tools/arch/x86/lib/inat.c (renamed from tools/objtool/arch/x86/lib/inat.c)2
-rw-r--r--tools/arch/x86/lib/insn.c (renamed from tools/perf/util/intel-pt-decoder/insn.c)4
-rw-r--r--tools/arch/x86/lib/x86-opcode-map.txt (renamed from tools/objtool/arch/x86/lib/x86-opcode-map.txt)0
-rw-r--r--tools/arch/x86/tools/gen-insn-attr-x86.awk (renamed from tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk)0
-rw-r--r--tools/bpf/bpftool/common.c8
-rw-r--r--tools/bpf/bpftool/prog.c4
-rw-r--r--tools/build/Makefile.feature2
-rw-r--r--tools/build/feature/Makefile4
-rw-r--r--tools/build/feature/test-libcap.c20
-rwxr-xr-xtools/hv/hv_get_dhcp_info.sh2
-rw-r--r--tools/hv/hv_kvp_daemon.c10
-rwxr-xr-xtools/hv/hv_set_ifconfig.sh2
-rw-r--r--tools/hv/hv_vss_daemon.c4
-rw-r--r--tools/hv/lsvmbus75
-rw-r--r--tools/include/linux/bitops.h1
-rw-r--r--tools/include/linux/bits.h17
-rw-r--r--tools/include/linux/const.h9
-rw-r--r--tools/include/linux/ring_buffer.h1
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h15
-rw-r--r--tools/include/uapi/asm-generic/mman.h10
-rw-r--r--tools/include/uapi/asm-generic/unistd.h8
-rw-r--r--tools/include/uapi/asm/bitsperlong.h18
-rw-r--r--tools/include/uapi/drm/drm.h1
-rw-r--r--tools/include/uapi/drm/i915_drm.h209
-rw-r--r--tools/include/uapi/linux/bpf.h11
-rw-r--r--tools/include/uapi/linux/const.h31
-rw-r--r--tools/include/uapi/linux/if_link.h5
-rw-r--r--tools/include/uapi/linux/kvm.h7
-rw-r--r--tools/include/uapi/linux/perf_event.h3
-rw-r--r--tools/include/uapi/linux/sched.h30
-rw-r--r--tools/include/uapi/linux/usbdevice_fs.h26
-rw-r--r--tools/lib/bpf/btf.c5
-rw-r--r--tools/lib/bpf/hashmap.h5
-rw-r--r--tools/lib/bpf/libbpf.c67
-rw-r--r--tools/lib/bpf/xsk.c11
-rw-r--r--tools/lib/traceevent/Makefile10
-rw-r--r--tools/lib/traceevent/event-parse-api.c40
-rw-r--r--tools/lib/traceevent/event-parse-local.h6
-rw-r--r--tools/lib/traceevent/event-parse.c391
-rw-r--r--tools/lib/traceevent/event-parse.h30
-rw-r--r--tools/lib/traceevent/event-plugin.c2
-rw-r--r--tools/memory-model/Documentation/explanation.txt53
-rw-r--r--tools/memory-model/README18
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/checkghlitmus.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/checklitmushist.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/cmplitmushist.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/initlitmushist.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/judgelitmus.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/newlitmushist.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/parseargs.sh0
-rwxr-xr-x[-rw-r--r--]tools/memory-model/scripts/runlitmushist.sh0
-rw-r--r--tools/objtool/Makefile6
-rw-r--r--tools/objtool/arch/x86/Build4
-rw-r--r--tools/objtool/arch/x86/decode.c4
-rw-r--r--tools/objtool/arch/x86/include/asm/inat.h230
-rw-r--r--tools/objtool/arch/x86/include/asm/insn.h216
-rw-r--r--tools/objtool/arch/x86/lib/insn.c593
-rw-r--r--tools/objtool/check.c7
-rw-r--r--tools/objtool/check.h3
-rwxr-xr-xtools/objtool/sync-check.sh44
-rw-r--r--tools/perf/.gitignore3
-rw-r--r--tools/perf/Documentation/Makefile2
-rw-r--r--tools/perf/Documentation/intel-pt.txt15
-rw-r--r--tools/perf/Documentation/itrace.txt2
-rw-r--r--tools/perf/Documentation/perf-config.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt13
-rw-r--r--tools/perf/Documentation/perf-report.txt17
-rw-r--r--tools/perf/Documentation/perf-script.txt17
-rw-r--r--tools/perf/Documentation/perf-top.txt38
-rw-r--r--tools/perf/Documentation/perf-trace.txt9
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt27
-rw-r--r--tools/perf/Makefile.config20
-rw-r--r--tools/perf/Makefile.perf33
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c1
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c9
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c107
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c1
-rw-r--r--tools/perf/arch/arm64/util/arm-spe.c30
-rw-r--r--tools/perf/arch/arm64/util/header.c7
-rw-r--r--tools/perf/arch/arm64/util/sym-handling.c8
-rw-r--r--tools/perf/arch/common.c3
-rw-r--r--tools/perf/arch/common.h4
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl146
-rw-r--r--tools/perf/arch/powerpc/util/kvm-stat.c12
-rw-r--r--tools/perf/arch/powerpc/util/mem-events.c1
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c1
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c1
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libdw.c1
-rw-r--r--tools/perf/arch/riscv/Build1
-rw-r--r--tools/perf/arch/riscv/Makefile4
-rw-r--r--tools/perf/arch/riscv/include/perf_regs.h96
-rw-r--r--tools/perf/arch/riscv/util/Build2
-rw-r--r--tools/perf/arch/riscv/util/dwarf-regs.c72
-rw-r--r--tools/perf/arch/riscv/util/unwind-libdw.c57
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c15
-rw-r--r--tools/perf/arch/s390/util/kvm-stat.c9
-rw-r--r--tools/perf/arch/s390/util/machine.c31
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl2
-rw-r--r--tools/perf/arch/x86/tests/bp-modify.c1
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c3
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c9
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c34
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c4
-rw-r--r--tools/perf/arch/x86/util/archinsn.c3
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c10
-rw-r--r--tools/perf/arch/x86/util/header.c1
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c49
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c123
-rw-r--r--tools/perf/arch/x86/util/kvm-stat.c17
-rw-r--r--tools/perf/arch/x86/util/perf_regs.c4
-rw-r--r--tools/perf/arch/x86/util/tsc.c8
-rw-r--r--tools/perf/bench/epoll-ctl.c8
-rw-r--r--tools/perf/bench/epoll-wait.c8
-rw-r--r--tools/perf/bench/futex-hash.c5
-rw-r--r--tools/perf/bench/futex-lock-pi.c7
-rw-r--r--tools/perf/bench/futex-requeue.c7
-rw-r--r--tools/perf/bench/futex-wake-parallel.c6
-rw-r--r--tools/perf/bench/futex-wake.c7
-rw-r--r--tools/perf/bench/mem-functions.c3
-rw-r--r--tools/perf/bench/numa.c7
-rw-r--r--tools/perf/bench/sched-messaging.c1
-rw-r--r--tools/perf/bench/sched-pipe.c1
-rw-r--r--tools/perf/builtin-annotate.c20
-rw-r--r--tools/perf/builtin-bench.c1
-rw-r--r--tools/perf/builtin-buildid-cache.c6
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-c2c.c22
-rw-r--r--tools/perf/builtin-config.c3
-rw-r--r--tools/perf/builtin-data.c2
-rw-r--r--tools/perf/builtin-diff.c24
-rw-r--r--tools/perf/builtin-evlist.c4
-rw-r--r--tools/perf/builtin-ftrace.c37
-rw-r--r--tools/perf/builtin-help.c5
-rw-r--r--tools/perf/builtin-inject.c62
-rw-r--r--tools/perf/builtin-kallsyms.c1
-rw-r--r--tools/perf/builtin-kmem.c29
-rw-r--r--tools/perf/builtin-kvm.c51
-rw-r--r--tools/perf/builtin-list.c5
-rw-r--r--tools/perf/builtin-lock.c34
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-probe.c15
-rw-r--r--tools/perf/builtin-record.c97
-rw-r--r--tools/perf/builtin-report.c55
-rw-r--r--tools/perf/builtin-sched.c101
-rw-r--r--tools/perf/builtin-script.c194
-rw-r--r--tools/perf/builtin-stat.c151
-rw-r--r--tools/perf/builtin-timechart.c56
-rw-r--r--tools/perf/builtin-top.c159
-rw-r--r--tools/perf/builtin-trace.c637
-rw-r--r--tools/perf/builtin-version.c2
-rw-r--r--tools/perf/builtin.h2
-rwxr-xr-xtools/perf/check-headers.sh13
-rw-r--r--tools/perf/examples/bpf/augmented_raw_syscalls.c318
-rw-r--r--tools/perf/include/bpf/bpf.h2
-rw-r--r--tools/perf/lib/Build12
-rw-r--r--tools/perf/lib/Documentation/Makefile7
-rw-r--r--tools/perf/lib/Documentation/man/libperf.rst100
-rw-r--r--tools/perf/lib/Documentation/tutorial/tutorial.rst123
-rw-r--r--tools/perf/lib/Makefile158
-rw-r--r--tools/perf/lib/core.c34
-rw-r--r--tools/perf/lib/cpumap.c262
-rw-r--r--tools/perf/lib/evlist.c159
-rw-r--r--tools/perf/lib/evsel.c232
-rw-r--r--tools/perf/lib/include/internal/cpumap.h19
-rw-r--r--tools/perf/lib/include/internal/evlist.h50
-rw-r--r--tools/perf/lib/include/internal/evsel.h29
-rw-r--r--tools/perf/lib/include/internal/lib.h10
-rw-r--r--tools/perf/lib/include/internal/tests.h19
-rw-r--r--tools/perf/lib/include/internal/threadmap.h23
-rw-r--r--tools/perf/lib/include/internal/xyarray.h (renamed from tools/perf/util/xyarray.h)9
-rw-r--r--tools/perf/lib/include/perf/core.h22
-rw-r--r--tools/perf/lib/include/perf/cpumap.h25
-rw-r--r--tools/perf/lib/include/perf/event.h385
-rw-r--r--tools/perf/lib/include/perf/evlist.h35
-rw-r--r--tools/perf/lib/include/perf/evsel.h39
-rw-r--r--tools/perf/lib/include/perf/threadmap.h20
-rw-r--r--tools/perf/lib/internal.h18
-rw-r--r--tools/perf/lib/lib.c46
-rw-r--r--tools/perf/lib/libperf.map43
-rw-r--r--tools/perf/lib/libperf.pc.template11
-rw-r--r--tools/perf/lib/tests/Makefile38
-rw-r--r--tools/perf/lib/tests/test-cpumap.c21
-rw-r--r--tools/perf/lib/tests/test-evlist.c186
-rw-r--r--tools/perf/lib/tests/test-evsel.c125
-rw-r--r--tools/perf/lib/tests/test-threadmap.c21
-rw-r--r--tools/perf/lib/threadmap.c91
-rw-r--r--tools/perf/lib/xyarray.c33
-rw-r--r--tools/perf/perf-sys.h51
-rw-r--r--tools/perf/perf.c11
-rw-r--r--tools/perf/perf.h82
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/memory.json2
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json8
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/cache.json552
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/floating-point.json102
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/frontend.json424
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/memory.json410
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/other.json121
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/pipeline.json892
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json236
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv3
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/cache.json111
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/memory.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/other.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/pipeline.json111
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/uncore-memory.json73
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/uncore-other.json431
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/uncore-power.json11
-rw-r--r--tools/perf/pmu-events/arch/x86/tremontx/virtual-memory.json86
-rw-r--r--tools/perf/pmu-events/jevents.c1
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c1
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c1
-rw-r--r--tools/perf/tests/attr.c3
-rw-r--r--tools/perf/tests/backward-ring-buffer.c22
-rw-r--r--tools/perf/tests/bitmap.c5
-rw-r--r--tools/perf/tests/bp_account.c3
-rw-r--r--tools/perf/tests/bp_signal.c3
-rw-r--r--tools/perf/tests/bp_signal_overflow.c3
-rw-r--r--tools/perf/tests/bpf.c15
-rw-r--r--tools/perf/tests/builtin-test.c1
-rw-r--r--tools/perf/tests/code-reading.c59
-rw-r--r--tools/perf/tests/cpumap.c33
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/tests/event-times.c83
-rw-r--r--tools/perf/tests/event_update.c32
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c12
-rw-r--r--tools/perf/tests/evsel-tp-sched.c8
-rw-r--r--tools/perf/tests/expr.c1
-rw-r--r--tools/perf/tests/hists_common.c3
-rw-r--r--tools/perf/tests/hists_cumulate.c20
-rw-r--r--tools/perf/tests/hists_filter.c12
-rw-r--r--tools/perf/tests/hists_link.c12
-rw-r--r--tools/perf/tests/hists_output.c22
-rw-r--r--tools/perf/tests/keep-tracking.c47
-rw-r--r--tools/perf/tests/kmod-path.c2
-rw-r--r--tools/perf/tests/llvm.c2
-rw-r--r--tools/perf/tests/make1
-rw-r--r--tools/perf/tests/mem.c1
-rw-r--r--tools/perf/tests/mem2node.c8
-rw-r--r--tools/perf/tests/mmap-basic.c31
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c4
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c20
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c18
-rw-r--r--tools/perf/tests/openat-syscall.c12
-rw-r--r--tools/perf/tests/parse-events.c1221
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c10
-rw-r--r--tools/perf/tests/perf-record.c13
-rw-r--r--tools/perf/tests/sample-parsing.c16
-rw-r--r--tools/perf/tests/sdt.c4
-rwxr-xr-xtools/perf/tests/shell/record+zstd_comp_decomp.sh2
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh4
-rw-r--r--tools/perf/tests/stat.c8
-rw-r--r--tools/perf/tests/sw-clock.c35
-rw-r--r--tools/perf/tests/switch-tracking.c67
-rw-r--r--tools/perf/tests/task-exit.c38
-rw-r--r--tools/perf/tests/thread-map.c43
-rw-r--r--tools/perf/tests/thread-mg-share.c1
-rw-r--r--tools/perf/tests/time-utils-test.c2
-rw-r--r--tools/perf/tests/topology.c9
-rw-r--r--tools/perf/tests/unit_number__scnprintf.c1
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c1
-rw-r--r--tools/perf/tests/wp.c5
-rw-r--r--tools/perf/trace/beauty/ioctl.c2
-rwxr-xr-xtools/perf/trace/beauty/usbdevfs_ioctl.sh9
-rw-r--r--tools/perf/ui/browser.c10
-rw-r--r--tools/perf/ui/browser.h1
-rw-r--r--tools/perf/ui/browsers/annotate.c18
-rw-r--r--tools/perf/ui/browsers/header.c1
-rw-r--r--tools/perf/ui/browsers/hists.c63
-rw-r--r--tools/perf/ui/browsers/map.c1
-rw-r--r--tools/perf/ui/browsers/res_sample.c9
-rw-r--r--tools/perf/ui/browsers/scripts.c18
-rw-r--r--tools/perf/ui/gtk/annotate.c9
-rw-r--r--tools/perf/ui/gtk/browser.c2
-rw-r--r--tools/perf/ui/gtk/gtk.h8
-rw-r--r--tools/perf/ui/gtk/helpline.c1
-rw-r--r--tools/perf/ui/gtk/hists.c7
-rw-r--r--tools/perf/ui/gtk/setup.c1
-rw-r--r--tools/perf/ui/gtk/util.c1
-rw-r--r--tools/perf/ui/helpline.c4
-rw-r--r--tools/perf/ui/helpline.h2
-rw-r--r--tools/perf/ui/hist.c20
-rw-r--r--tools/perf/ui/progress.c1
-rw-r--r--tools/perf/ui/setup.c5
-rw-r--r--tools/perf/ui/stdio/hist.c2
-rw-r--r--tools/perf/ui/tui/helpline.c2
-rw-r--r--tools/perf/ui/tui/progress.c1
-rw-r--r--tools/perf/ui/tui/setup.c3
-rw-r--r--tools/perf/ui/tui/util.c38
-rw-r--r--tools/perf/ui/util.c4
-rw-r--r--tools/perf/ui/util.h2
-rw-r--r--tools/perf/util/Build11
-rw-r--r--tools/perf/util/annotate.c51
-rw-r--r--tools/perf/util/annotate.h28
-rw-r--r--tools/perf/util/arm-spe.c10
-rw-r--r--tools/perf/util/auxtrace.c102
-rw-r--r--tools/perf/util/auxtrace.h89
-rw-r--r--tools/perf/util/bpf-event.c39
-rw-r--r--tools/perf/util/bpf-event.h15
-rw-r--r--tools/perf/util/bpf-loader.c43
-rw-r--r--tools/perf/util/bpf-loader.h30
-rw-r--r--tools/perf/util/bpf-prologue.c2
-rw-r--r--tools/perf/util/branch.c3
-rw-r--r--tools/perf/util/branch.h8
-rw-r--r--tools/perf/util/build-id.c5
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/c++/clang-c.h2
-rw-r--r--tools/perf/util/c++/clang-test.cpp4
-rw-r--r--tools/perf/util/cacheline.c25
-rw-r--r--tools/perf/util/cacheline.h21
-rw-r--r--tools/perf/util/callchain.c6
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/cap.c29
-rw-r--r--tools/perf/util/cap.h32
-rw-r--r--tools/perf/util/cgroup.c25
-rw-r--r--tools/perf/util/cgroup.h6
-rw-r--r--tools/perf/util/cloexec.c4
-rw-r--r--tools/perf/util/color.c3
-rw-r--r--tools/perf/util/color_config.c3
-rw-r--r--tools/perf/util/config.c4
-rw-r--r--tools/perf/util/counts.c17
-rw-r--r--tools/perf/util/counts.h38
-rw-r--r--tools/perf/util/cpumap.c290
-rw-r--r--tools/perf/util/cpumap.h63
-rw-r--r--tools/perf/util/cputopo.c15
-rw-r--r--tools/perf/util/cputopo.h1
-rw-r--r--tools/perf/util/cs-etm.c73
-rw-r--r--tools/perf/util/cs-etm.h3
-rw-r--r--tools/perf/util/data-convert-bt.c38
-rw-r--r--tools/perf/util/data.c2
-rw-r--r--tools/perf/util/db-export.c11
-rw-r--r--tools/perf/util/db-export.h10
-rw-r--r--tools/perf/util/debug.c6
-rw-r--r--tools/perf/util/debug.h6
-rw-r--r--tools/perf/util/dso.c237
-rw-r--r--tools/perf/util/dso.h28
-rw-r--r--tools/perf/util/dsos.c232
-rw-r--r--tools/perf/util/dsos.h44
-rw-r--r--tools/perf/util/dwarf-aux.c1
-rw-r--r--tools/perf/util/dwarf-aux.h2
-rw-r--r--tools/perf/util/env.c4
-rw-r--r--tools/perf/util/env.h2
-rw-r--r--tools/perf/util/event.c121
-rw-r--r--tools/perf/util/event.h469
-rw-r--r--tools/perf/util/events_stats.h51
-rw-r--r--tools/perf/util/evlist.c628
-rw-r--r--tools/perf/util/evlist.h219
-rw-r--r--tools/perf/util/evsel.c541
-rw-r--r--tools/perf/util/evsel.h222
-rw-r--r--tools/perf/util/evsel_fprintf.c16
-rw-r--r--tools/perf/util/evswitch.c61
-rw-r--r--tools/perf/util/evswitch.h31
-rw-r--r--tools/perf/util/expr.y2
-rw-r--r--tools/perf/util/genelf.c3
-rw-r--r--tools/perf/util/genelf_debug.c1
-rw-r--r--tools/perf/util/get_current_dir_name.c1
-rw-r--r--tools/perf/util/header.c326
-rw-r--r--tools/perf/util/header.h24
-rw-r--r--tools/perf/util/hist.c63
-rw-r--r--tools/perf/util/hist.h45
-rw-r--r--tools/perf/util/intel-bts.c32
-rw-r--r--tools/perf/util/intel-pt-decoder/Build22
-rw-r--r--tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk392
-rw-r--r--tools/perf/util/intel-pt-decoder/inat.c82
-rw-r--r--tools/perf/util/intel-pt-decoder/inat_types.h15
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c10
-rw-r--r--tools/perf/util/intel-pt-decoder/x86-opcode-map.txt1072
-rw-r--r--tools/perf/util/intel-pt.c126
-rw-r--r--tools/perf/util/jitdump.c9
-rw-r--r--tools/perf/util/kvm-stat.h24
-rw-r--r--tools/perf/util/llvm-utils.c1
-rw-r--r--tools/perf/util/llvm-utils.h2
-rw-r--r--tools/perf/util/lzma.c1
-rw-r--r--tools/perf/util/machine.c58
-rw-r--r--tools/perf/util/machine.h14
-rw-r--r--tools/perf/util/map.c8
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/map_groups.h4
-rw-r--r--tools/perf/util/mem-events.c2
-rw-r--r--tools/perf/util/mem-events.h9
-rw-r--r--tools/perf/util/mem2node.c3
-rw-r--r--tools/perf/util/mem2node.h3
-rw-r--r--tools/perf/util/metricgroup.c110
-rw-r--r--tools/perf/util/metricgroup.h20
-rw-r--r--tools/perf/util/mmap.c10
-rw-r--r--tools/perf/util/mmap.h1
-rw-r--r--tools/perf/util/namespaces.c2
-rw-r--r--tools/perf/util/namespaces.h4
-rw-r--r--tools/perf/util/ordered-events.c1
-rw-r--r--tools/perf/util/parse-branch-options.c4
-rw-r--r--tools/perf/util/parse-events.c167
-rw-r--r--tools/perf/util/parse-events.h9
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/path.c3
-rw-r--r--tools/perf/util/path.h3
-rw-r--r--tools/perf/util/perf-hooks.c1
-rw-r--r--tools/perf/util/pmu.c25
-rw-r--r--tools/perf/util/pmu.h4
-rw-r--r--tools/perf/util/probe-event.c7
-rw-r--r--tools/perf/util/probe-file.c4
-rw-r--r--tools/perf/util/probe-finder.c1
-rw-r--r--tools/perf/util/pstack.c1
-rw-r--r--tools/perf/util/python-ext-sources3
-rw-r--r--tools/perf/util/python.c139
-rw-r--r--tools/perf/util/record.c78
-rw-r--r--tools/perf/util/record.h74
-rw-r--r--tools/perf/util/s390-cpumsf.c10
-rw-r--r--tools/perf/util/s390-sample-raw.c8
-rw-r--r--tools/perf/util/sample-raw.c2
-rw-r--r--tools/perf/util/sample-raw.h6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c16
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c46
-rw-r--r--tools/perf/util/session.c200
-rw-r--r--tools/perf/util/session.h15
-rw-r--r--tools/perf/util/setup.py5
-rw-r--r--tools/perf/util/sort.c81
-rw-r--r--tools/perf/util/sort.h34
-rw-r--r--tools/perf/util/stat-display.c115
-rw-r--r--tools/perf/util/stat-shadow.c138
-rw-r--r--tools/perf/util/stat.c88
-rw-r--r--tools/perf/util/stat.h42
-rw-r--r--tools/perf/util/strbuf.c5
-rw-r--r--tools/perf/util/svghelper.c62
-rw-r--r--tools/perf/util/svghelper.h4
-rw-r--r--tools/perf/util/symbol-elf.c7
-rw-r--r--tools/perf/util/symbol-minimal.c2
-rw-r--r--tools/perf/util/symbol.c27
-rw-r--r--tools/perf/util/symbol.h64
-rw-r--r--tools/perf/util/symbol_fprintf.c1
-rw-r--r--tools/perf/util/symsrc.h46
-rw-r--r--tools/perf/util/syscalltbl.c1
-rw-r--r--tools/perf/util/syscalltbl.h1
-rw-r--r--tools/perf/util/target.c3
-rw-r--r--tools/perf/util/thread-stack.c1
-rw-r--r--tools/perf/util/thread.c25
-rw-r--r--tools/perf/util/thread.h8
-rw-r--r--tools/perf/util/thread_map.c137
-rw-r--r--tools/perf/util/thread_map.h66
-rw-r--r--tools/perf/util/time-utils.c1
-rw-r--r--tools/perf/util/time-utils.h9
-rw-r--r--tools/perf/util/tool.h10
-rw-r--r--tools/perf/util/top.c13
-rw-r--r--tools/perf/util/top.h12
-rw-r--r--tools/perf/util/trace-event-info.c15
-rw-r--r--tools/perf/util/trace-event-parse.c3
-rw-r--r--tools/perf/util/trace-event-read.c1
-rw-r--r--tools/perf/util/trace-event-scripting.c3
-rw-r--r--tools/perf/util/trace-event.h5
-rw-r--r--tools/perf/util/trigger.h1
-rw-r--r--tools/perf/util/unwind-libdw.c1
-rw-r--r--tools/perf/util/unwind-libunwind-local.c18
-rw-r--r--tools/perf/util/unwind-libunwind.c41
-rw-r--r--tools/perf/util/unwind.h25
-rw-r--r--tools/perf/util/util-cxx.h27
-rw-r--r--tools/perf/util/util.c71
-rw-r--r--tools/perf/util/util.h5
-rw-r--r--tools/perf/util/values.c1
-rw-r--r--tools/perf/util/vdso.c1
-rw-r--r--tools/perf/util/zlib.c1
-rw-r--r--tools/perf/util/zstd.c4
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c21
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c26
-rw-r--r--tools/power/x86/intel-speed-select/isst-display.c126
-rw-r--r--tools/power/x86/intel-speed-select/isst.h1
-rw-r--r--tools/power/x86/turbostat/Makefile3
-rw-r--r--tools/power/x86/turbostat/turbostat.c215
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile3
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.82
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c28
-rw-r--r--tools/scripts/Makefile.include9
-rwxr-xr-xtools/testing/ktest/config-bisect.pl4
-rw-r--r--tools/testing/selftests/arm64/.gitignore1
-rw-r--r--tools/testing/selftests/arm64/Makefile11
-rwxr-xr-xtools/testing/selftests/arm64/run_tags_test.sh12
-rw-r--r--tools/testing/selftests/arm64/tags_test.c31
-rw-r--r--tools/testing/selftests/bpf/Makefile9
-rw-r--r--tools/testing/selftests/bpf/config1
-rw-r--r--tools/testing/selftests/bpf/progs/sendmsg6_prog.c3
-rw-r--r--tools/testing/selftests/bpf/test_btf_dump.c7
-rw-r--r--tools/testing/selftests/bpf/test_cgroup_storage.c6
-rw-r--r--tools/testing/selftests/bpf/test_sock.c7
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_vlan.sh57
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh9
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh9
-rw-r--r--tools/testing/selftests/bpf/verifier/ctx_skb.c11
-rw-r--r--tools/testing/selftests/bpf/verifier/loops1.c28
-rw-r--r--tools/testing/selftests/cgroup/cgroup_util.c3
-rw-r--r--tools/testing/selftests/cgroup/test_freezer.c54
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh4
-rwxr-xr-xtools/testing/selftests/kmod/kmod.sh6
-rw-r--r--tools/testing/selftests/kselftest.h15
-rw-r--r--tools/testing/selftests/kvm/.gitignore3
-rw-r--r--tools/testing/selftests/kvm/config3
-rw-r--r--tools/testing/selftests/kvm/include/evmcs.h2
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/processor.c16
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/vmx.c20
-rw-r--r--tools/testing/selftests/kvm/x86_64/evmcs_test.c15
-rw-r--r--tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c12
-rw-r--r--tools/testing/selftests/kvm/x86_64/platform_info_test.c2
-rw-r--r--tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c32
-rw-r--r--tools/testing/selftests/livepatch/functions.sh46
-rw-r--r--tools/testing/selftests/net/.gitignore4
-rwxr-xr-xtools/testing/selftests/net/fib_nexthops.sh24
-rwxr-xr-xtools/testing/selftests/net/forwarding/gre_multipath.sh28
-rwxr-xr-xtools/testing/selftests/net/tcp_fastopen_backup_key.sh2
-rw-r--r--tools/testing/selftests/net/tls.c223
-rwxr-xr-xtools/testing/selftests/net/xfrm_policy.sh7
-rwxr-xr-xtools/testing/selftests/netfilter/nft_flowtable.sh48
-rw-r--r--tools/testing/selftests/pidfd/.gitignore2
-rw-r--r--tools/testing/selftests/pidfd/Makefile2
-rw-r--r--tools/testing/selftests/pidfd/pidfd.h30
-rw-r--r--tools/testing/selftests/pidfd/pidfd_open_test.c5
-rw-r--r--tools/testing/selftests/pidfd/pidfd_poll_test.c117
-rw-r--r--tools/testing/selftests/pidfd/pidfd_test.c20
-rw-r--r--tools/testing/selftests/pidfd/pidfd_wait.c271
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot1
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py22
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json47
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json94
-rw-r--r--tools/testing/selftests/x86/Makefile4
-rw-r--r--tools/testing/selftests/x86/mpx-debug.h15
-rw-r--r--tools/testing/selftests/x86/mpx-dig.c497
-rw-r--r--tools/testing/selftests/x86/mpx-hw.h124
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c1613
-rw-r--r--tools/testing/selftests/x86/mpx-mm.h10
-rw-r--r--tools/testing/selftests/x86/syscall_numbering.c89
-rw-r--r--tools/testing/selftests/x86/test_vsyscall.c2
-rw-r--r--usr/include/Makefile4
-rw-r--r--virt/kvm/arm/arm.c20
-rw-r--r--virt/kvm/arm/hyp/vgic-v3-sr.c8
-rw-r--r--virt/kvm/arm/mmio.c7
-rw-r--r--virt/kvm/arm/pmu.c18
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c30
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c2
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio.c34
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c14
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c12
-rw-r--r--virt/kvm/arm/vgic/vgic.c18
-rw-r--r--virt/kvm/arm/vgic/vgic.h6
-rw-r--r--virt/kvm/kvm_main.c61
4119 files changed, 92924 insertions, 102510 deletions
diff --git a/.clang-format b/.clang-format
index 2ffd69afc1a8..196ca317bd1f 100644
--- a/.clang-format
+++ b/.clang-format
@@ -107,10 +107,13 @@ ForEachMacros:
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'device_for_each_child_node'
+ - 'dma_fence_chain_for_each'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
+ - 'drm_client_for_each_connector_iter'
+ - 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
@@ -126,6 +129,7 @@ ForEachMacros:
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'flow_action_for_each'
+ - 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_available_child_of_node'
@@ -153,6 +157,8 @@ ForEachMacros:
- 'for_each_cpu_not'
- 'for_each_cpu_wrap'
- 'for_each_dev_addr'
+ - 'for_each_dev_scope'
+ - 'for_each_displayid_db'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
@@ -169,6 +175,8 @@ ForEachMacros:
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
+ - 'for_each_free_mem_pfn_range_in_zone'
+ - 'for_each_free_mem_pfn_range_in_zone_from'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
@@ -178,6 +186,7 @@ ForEachMacros:
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_nr'
- 'for_each_link_codecs'
+ - 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
@@ -302,7 +311,10 @@ ForEachMacros:
- 'ide_port_for_each_present_dev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
+ - 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
+ - 'in_dev_for_each_ifa_rcu'
+ - 'in_dev_for_each_ifa_rtnl'
- 'inet_bind_bucket_for_each'
- 'inet_lhash2_for_each_icsk_rcu'
- 'key_for_each'
@@ -343,8 +355,6 @@ ForEachMacros:
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- - 'mp_bvec_for_each_page'
- - 'mp_bvec_for_each_segment'
- 'nanddev_io_for_each_page'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
@@ -381,18 +391,19 @@ ForEachMacros:
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rbtree_postorder_for_each_entry_safe'
+ - 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- - 'rht_for_each_from'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
+ - 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- '__rq_for_each_bio'
diff --git a/.gitignore b/.gitignore
index 8f5422cba6e2..2030c7a4d2f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -142,3 +142,6 @@ x509.genkey
# Kdevelop4
*.kdev4
+
+# Clang's compilation database file
+/compile_commands.json
diff --git a/.mailmap b/.mailmap
index 0fef932de3db..1ad4fd655619 100644
--- a/.mailmap
+++ b/.mailmap
@@ -64,6 +64,9 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
Dengcheng Zhu <dzhu@wavecomp.com> <dczhu@mips.com>
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com>
Domen Puncer <domen@coderock.org>
Douglas Gilbert <dougg@torque.net>
Ed L. Cashin <ecashin@coraid.com>
@@ -98,6 +101,7 @@ Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com>
Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com>
<javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
Jean Tourrilhes <jt@hpl.hp.com>
+<jean-philippe@linaro.org> <jean-philippe.brucker@arm.com>
Jeff Garzik <jgarzik@pretzel.yyz.us>
Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com>
Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net>
@@ -116,6 +120,7 @@ John Stultz <johnstul@us.ibm.com>
Juha Yrjola <at solidboot.com>
Juha Yrjola <juha.yrjola@nokia.com>
Juha Yrjola <juha.yrjola@solidboot.com>
+Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
Kay Sievers <kay.sievers@vrfy.org>
Kenneth W Chen <kenneth.w.chen@intel.com>
Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
@@ -132,6 +137,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
+Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>
Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
Mark Brown <broonie@sirena.org.uk>
Mark Yao <markyao0591@gmail.com> <mark.yao@rock-chips.com>
@@ -157,6 +163,8 @@ Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.co
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
Matt Redfearn <matt.redfearn@mips.com> <matt.redfearn@imgtec.com>
+Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
+Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
Mayuresh Janorkar <mayur@ti.com>
Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com>
@@ -170,6 +178,7 @@ Morten Welinder <welinder@darter.rentec.com>
Morten Welinder <welinder@troll.com>
Mythri P K <mythripk@ti.com>
Nguyen Anh Quynh <aquynh@gmail.com>
+Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com>
Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org>
Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
diff --git a/Documentation/ABI/testing/debugfs-moxtet b/Documentation/ABI/testing/debugfs-moxtet
new file mode 100644
index 000000000000..67b1717794d8
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-moxtet
@@ -0,0 +1,23 @@
+What: /sys/kernel/debug/moxtet/input
+Date: March 2019
+KernelVersion: 5.3
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Read input from the shift registers, in hexadecimal.
+ Returns N+1 bytes, where N is the number of Moxtet connected
+ modules. The first byte is from the CPU board itself.
+ Example: 101214
+ 10: CPU board with SD card
+ 12: 2 = PCIe module, 1 = IRQ not active
+ 14: 4 = Peridot module, 1 = IRQ not active
+
+What: /sys/kernel/debug/moxtet/output
+Date: March 2019
+KernelVersion: 5.3
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (RW) Read last written value to the shift registers, in
+ hexadecimal, or write values to the shift registers, also
+ in hexadecimal.
+ Example: 0102
+ 01: 01 was last written, or is to be written, to the
+ first module's shift register
+ 02: the same for second module
diff --git a/Documentation/ABI/testing/sysfs-bus-moxtet-devices b/Documentation/ABI/testing/sysfs-bus-moxtet-devices
new file mode 100644
index 000000000000..355958527fa3
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-moxtet-devices
@@ -0,0 +1,17 @@
+What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_description
+Date: March 2019
+KernelVersion: 5.3
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Moxtet module description. Format: string
+
+What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_id
+Date: March 2019
+KernelVersion: 5.3
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Moxtet module ID. Format: %x
+
+What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_name
+Date: March 2019
+KernelVersion: 5.3
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Moxtet module name. Format: string
diff --git a/Documentation/ABI/testing/sysfs-devices-soc b/Documentation/ABI/testing/sysfs-devices-soc
index 6d9cc253f2b2..ba3a3fac0ee1 100644
--- a/Documentation/ABI/testing/sysfs-devices-soc
+++ b/Documentation/ABI/testing/sysfs-devices-soc
@@ -26,6 +26,13 @@ Description:
Read-only attribute common to all SoCs. Contains SoC family name
(e.g. DB8500).
+What: /sys/devices/socX/serial_number
+Date: January 2019
+contact: Bjorn Andersson <bjorn.andersson@linaro.org>
+Description:
+ Read-only attribute supported by most SoCs. Contains the SoC's
+ serial number, if available.
+
What: /sys/devices/socX/soc_id
Date: January 2012
contact: Lee Jones <lee.jones@linaro.org>
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi
index e794eac32a90..5e4d0b27cdfe 100644
--- a/Documentation/ABI/testing/sysfs-firmware-efi
+++ b/Documentation/ABI/testing/sysfs-firmware-efi
@@ -28,3 +28,11 @@ Description: Displays the physical addresses of all EFI Configuration
versions are always printed first, i.e. ACPI20 comes
before ACPI.
Users: dmidecode
+
+What: /sys/firmware/efi/tables/rci2
+Date: July 2019
+Contact: Narendra K <Narendra.K@dell.com>, linux-bugs@dell.com
+Description: Displays the content of the Runtime Configuration Interface
+ Table version 2 on Dell EMC PowerEdge systems in binary format
+Users: It is used by Dell EMC OpenManage Server Administrator tool to
+ populate BIOS setup page.
diff --git a/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm b/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
new file mode 100644
index 000000000000..15595fab88d1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
@@ -0,0 +1,37 @@
+What: /sys/firmware/turris-mox-rwtm/board_version
+Date: August 2019
+KernelVersion: 5.4
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Board version burned into eFuses of this Turris Mox board.
+ Format: %i
+
+What: /sys/firmware/turris-mox-rwtm/mac_address*
+Date: August 2019
+KernelVersion: 5.4
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) MAC addresses burned into eFuses of this Turris Mox board.
+ Format: %pM
+
+What: /sys/firmware/turris-mox-rwtm/pubkey
+Date: August 2019
+KernelVersion: 5.4
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) ECDSA public key (in pubkey hex compressed form) computed
+ as pair to the ECDSA private key burned into eFuses of this
+ Turris Mox Board.
+ Format: string
+
+What: /sys/firmware/turris-mox-rwtm/ram_size
+Date: August 2019
+KernelVersion: 5.4
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) RAM size in MiB of this Turris Mox board as was detected
+ during manufacturing and burned into eFuses. Can be 512 or 1024.
+ Format: %i
+
+What: /sys/firmware/turris-mox-rwtm/serial_number
+Date: August 2019
+KernelVersion: 5.4
+Contact: Marek Behún <marek.behun@nic.cz>
+Description: (R) Serial number burned into eFuses of this Turris Mox device.
+ Format: %016X
diff --git a/Documentation/PCI/index.rst b/Documentation/PCI/index.rst
index f4c6121868c3..6768305e4c26 100644
--- a/Documentation/PCI/index.rst
+++ b/Documentation/PCI/index.rst
@@ -9,7 +9,7 @@ Linux PCI Bus Subsystem
:numbered:
pci
- picebus-howto
+ pciebus-howto
pci-iov-howto
msi-howto
acpi-info
diff --git a/Documentation/PCI/pci-error-recovery.rst b/Documentation/PCI/pci-error-recovery.rst
index 83db42092935..e5d450df06b4 100644
--- a/Documentation/PCI/pci-error-recovery.rst
+++ b/Documentation/PCI/pci-error-recovery.rst
@@ -403,7 +403,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.txt
+ the file Documentation/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
@@ -422,3 +422,6 @@ That is, the recovery API only requires that:
- drivers/net/cxgb3
- drivers/net/s2io.c
- drivers/net/qlge
+
+The End
+-------
diff --git a/Documentation/PCI/picebus-howto.rst b/Documentation/PCI/pciebus-howto.rst
index f882ff62c51f..f882ff62c51f 100644
--- a/Documentation/PCI/picebus-howto.rst
+++ b/Documentation/PCI/pciebus-howto.rst
diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index 5a9238a2883c..467251f7fef6 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -2129,6 +2129,8 @@ Some of the relevant points of interest are as follows:
<li> <a href="#Hotplug CPU">Hotplug CPU</a>.
<li> <a href="#Scheduler and RCU">Scheduler and RCU</a>.
<li> <a href="#Tracing and RCU">Tracing and RCU</a>.
+<li> <a href="#Accesses to User Memory and RCU">
+Accesses to User Memory and RCU</a>.
<li> <a href="#Energy Efficiency">Energy Efficiency</a>.
<li> <a href="#Scheduling-Clock Interrupts and RCU">
Scheduling-Clock Interrupts and RCU</a>.
@@ -2512,7 +2514,7 @@ disabled across the entire RCU read-side critical section.
<p>
It is possible to use tracing on RCU code, but tracing itself
uses RCU.
-For this reason, <tt>rcu_dereference_raw_notrace()</tt>
+For this reason, <tt>rcu_dereference_raw_check()</tt>
is provided for use by tracing, which avoids the destructive
recursion that could otherwise ensue.
This API is also used by virtualization in some architectures,
@@ -2521,6 +2523,75 @@ cannot be used.
The tracing folks both located the requirement and provided the
needed fix, so this surprise requirement was relatively painless.
+<h3><a name="Accesses to User Memory and RCU">
+Accesses to User Memory and RCU</a></h3>
+
+<p>
+The kernel needs to access user-space memory, for example, to access
+data referenced by system-call parameters.
+The <tt>get_user()</tt> macro does this job.
+
+<p>
+However, user-space memory might well be paged out, which means
+that <tt>get_user()</tt> might well page-fault and thus block while
+waiting for the resulting I/O to complete.
+It would be a very bad thing for the compiler to reorder
+a <tt>get_user()</tt> invocation into an RCU read-side critical
+section.
+For example, suppose that the source code looked like this:
+
+<blockquote>
+<pre>
+ 1 rcu_read_lock();
+ 2 p = rcu_dereference(gp);
+ 3 v = p-&gt;value;
+ 4 rcu_read_unlock();
+ 5 get_user(user_v, user_p);
+ 6 do_something_with(v, user_v);
+</pre>
+</blockquote>
+
+<p>
+The compiler must not be permitted to transform this source code into
+the following:
+
+<blockquote>
+<pre>
+ 1 rcu_read_lock();
+ 2 p = rcu_dereference(gp);
+ 3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
+ 4 v = p-&gt;value;
+ 5 rcu_read_unlock();
+ 6 do_something_with(v, user_v);
+</pre>
+</blockquote>
+
+<p>
+If the compiler did make this transformation in a
+<tt>CONFIG_PREEMPT=n</tt> kernel build, and if <tt>get_user()</tt> did
+page fault, the result would be a quiescent state in the middle
+of an RCU read-side critical section.
+This misplaced quiescent state could result in line&nbsp;4 being
+a use-after-free access, which could be bad for your kernel's
+actuarial statistics.
+Similar examples can be constructed with the call to <tt>get_user()</tt>
+preceding the <tt>rcu_read_lock()</tt>.
+
+<p>
+Unfortunately, <tt>get_user()</tt> doesn't have any particular
+ordering properties, and in some architectures the underlying <tt>asm</tt>
+isn't even marked <tt>volatile</tt>.
+And even if it was marked <tt>volatile</tt>, the above access to
+<tt>p-&gt;value</tt> is not volatile, so the compiler would not have any
+reason to keep those two accesses in order.
+
+<p>
+Therefore, the Linux-kernel definitions of <tt>rcu_read_lock()</tt>
+and <tt>rcu_read_unlock()</tt> must act as compiler barriers,
+at least for outermost instances of <tt>rcu_read_lock()</tt> and
+<tt>rcu_read_unlock()</tt> within a nested set of RCU read-side critical
+sections.
+
<h3><a name="Energy Efficiency">Energy Efficiency</a></h3>
<p>
diff --git a/Documentation/RCU/rculist_nulls.txt b/Documentation/RCU/rculist_nulls.txt
index 8151f0195f76..23f115dc87cf 100644
--- a/Documentation/RCU/rculist_nulls.txt
+++ b/Documentation/RCU/rculist_nulls.txt
@@ -1,7 +1,7 @@
Using hlist_nulls to protect read-mostly linked lists and
objects using SLAB_TYPESAFE_BY_RCU allocations.
-Please read the basics in Documentation/RCU/listRCU.txt
+Please read the basics in Documentation/RCU/listRCU.rst
Using special makers (called 'nulls') is a convenient way
to solve following problem :
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 13e88fc00f01..f48f4621ccbc 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -57,6 +57,12 @@ o A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
CONFIG_PREEMPT_RCU case, you might see stall-warning
messages.
+ You can use the rcutree.kthread_prio kernel boot parameter to
+ increase the scheduling priority of RCU's kthreads, which can
+ help avoid this problem. However, please note that doing this
+ can increase your system's context-switch rate and thus degrade
+ performance.
+
o A periodic interrupt whose handler takes longer than the time
interval between successive pairs of interrupts. This can
prevent RCU's kthreads and softirq handlers from running.
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 3b29005aa981..5f1c266131b0 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -951,6 +951,13 @@ controller implements weight and absolute bandwidth limit models for
normal scheduling policy and absolute bandwidth allocation model for
realtime scheduling policy.
+In all the above models, cycles distribution is defined only on a temporal
+base and it does not account for the frequency at which tasks are executed.
+The (optional) utilization clamping support allows to hint the schedutil
+cpufreq governor about the minimum desired frequency which should always be
+provided by a CPU, as well as the maximum desired frequency, which should not
+be exceeded by a CPU.
+
WARNING: cgroup2 doesn't yet support control of realtime processes and
the cpu controller can only be enabled when all RT processes are in
the root cgroup. Be aware that system management software may already
@@ -1016,6 +1023,33 @@ All time durations are in microseconds.
Shows pressure stall information for CPU. See
Documentation/accounting/psi.rst for details.
+ cpu.uclamp.min
+ A read-write single value file which exists on non-root cgroups.
+ The default is "0", i.e. no utilization boosting.
+
+ The requested minimum utilization (protection) as a percentage
+ rational number, e.g. 12.34 for 12.34%.
+
+ This interface allows reading and setting minimum utilization clamp
+ values similar to the sched_setattr(2). This minimum utilization
+ value is used to clamp the task specific minimum utilization clamp.
+
+ The requested minimum utilization (protection) is always capped by
+ the current value for the maximum utilization (limit), i.e.
+ `cpu.uclamp.max`.
+
+ cpu.uclamp.max
+ A read-write single value file which exists on non-root cgroups.
+ The default is "max". i.e. no utilization capping
+
+ The requested maximum utilization (limit) as a percentage rational
+ number, e.g. 98.76 for 98.76%.
+
+ This interface allows reading and setting maximum utilization clamp
+ values similar to the sched_setattr(2). This maximum utilization
+ value is used to clamp the task specific maximum utilization clamp.
+
+
Memory
------
diff --git a/Documentation/admin-guide/conf.py b/Documentation/admin-guide/conf.py
deleted file mode 100644
index 86f738953799..000000000000
--- a/Documentation/admin-guide/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel User Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'linux-user.tex', 'Linux Kernel User Documentation',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
index 25f3b2532198..e05e581af5cf 100644
--- a/Documentation/admin-guide/hw-vuln/spectre.rst
+++ b/Documentation/admin-guide/hw-vuln/spectre.rst
@@ -41,10 +41,11 @@ Related CVEs
The following CVE entries describe Spectre variants:
- ============= ======================= =================
+ ============= ======================= ==========================
CVE-2017-5753 Bounds check bypass Spectre variant 1
CVE-2017-5715 Branch target injection Spectre variant 2
- ============= ======================= =================
+ CVE-2019-1125 Spectre v1 swapgs Spectre variant 1 (swapgs)
+ ============= ======================= ==========================
Problem
-------
@@ -78,6 +79,13 @@ There are some extensions of Spectre variant 1 attacks for reading data
over the network, see :ref:`[12] <spec_ref12>`. However such attacks
are difficult, low bandwidth, fragile, and are considered low risk.
+Note that, despite "Bounds Check Bypass" name, Spectre variant 1 is not
+only about user-controlled array bounds checks. It can affect any
+conditional checks. The kernel entry code interrupt, exception, and NMI
+handlers all have conditional swapgs checks. Those may be problematic
+in the context of Spectre v1, as kernel code can speculatively run with
+a user GS.
+
Spectre variant 2 (Branch Target Injection)
-------------------------------------------
@@ -132,6 +140,9 @@ not cover all possible attack vectors.
1. A user process attacking the kernel
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Spectre variant 1
+~~~~~~~~~~~~~~~~~
+
The attacker passes a parameter to the kernel via a register or
via a known address in memory during a syscall. Such parameter may
be used later by the kernel as an index to an array or to derive
@@ -144,7 +155,40 @@ not cover all possible attack vectors.
potentially be influenced for Spectre attacks, new "nospec" accessor
macros are used to prevent speculative loading of data.
- Spectre variant 2 attacker can :ref:`poison <poison_btb>` the branch
+Spectre variant 1 (swapgs)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ An attacker can train the branch predictor to speculatively skip the
+ swapgs path for an interrupt or exception. If they initialize
+ the GS register to a user-space value, if the swapgs is speculatively
+ skipped, subsequent GS-related percpu accesses in the speculation
+ window will be done with the attacker-controlled GS value. This
+ could cause privileged memory to be accessed and leaked.
+
+ For example:
+
+ ::
+
+ if (coming from user space)
+ swapgs
+ mov %gs:<percpu_offset>, %reg
+ mov (%reg), %reg1
+
+ When coming from user space, the CPU can speculatively skip the
+ swapgs, and then do a speculative percpu load using the user GS
+ value. So the user can speculatively force a read of any kernel
+ value. If a gadget exists which uses the percpu value as an address
+ in another load/store, then the contents of the kernel value may
+ become visible via an L1 side channel attack.
+
+ A similar attack exists when coming from kernel space. The CPU can
+ speculatively do the swapgs, causing the user GS to get used for the
+ rest of the speculative window.
+
+Spectre variant 2
+~~~~~~~~~~~~~~~~~
+
+ A spectre variant 2 attacker can :ref:`poison <poison_btb>` the branch
target buffer (BTB) before issuing syscall to launch an attack.
After entering the kernel, the kernel could use the poisoned branch
target buffer on indirect jump and jump to gadget code in speculative
@@ -280,11 +324,18 @@ The sysfs file showing Spectre variant 1 mitigation status is:
The possible values in this file are:
- ======================================= =================================
- 'Mitigation: __user pointer sanitation' Protection in kernel on a case by
- case base with explicit pointer
- sanitation.
- ======================================= =================================
+ .. list-table::
+
+ * - 'Not affected'
+ - The processor is not vulnerable.
+ * - 'Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers'
+ - The swapgs protections are disabled; otherwise it has
+ protection in the kernel on a case by case base with explicit
+ pointer sanitation and usercopy LFENCE barriers.
+ * - 'Mitigation: usercopy/swapgs barriers and __user pointer sanitization'
+ - Protection in the kernel on a case by case base with explicit
+ pointer sanitation, usercopy LFENCE barriers, and swapgs LFENCE
+ barriers.
However, the protections are put in place on a case by case basis,
and there is no guarantee that all possible attack vectors for Spectre
@@ -366,12 +417,27 @@ Turning on mitigation for Spectre variant 1 and Spectre variant 2
1. Kernel mitigation
^^^^^^^^^^^^^^^^^^^^
+Spectre variant 1
+~~~~~~~~~~~~~~~~~
+
For the Spectre variant 1, vulnerable kernel code (as determined
by code audit or scanning tools) is annotated on a case by case
basis to use nospec accessor macros for bounds clipping :ref:`[2]
<spec_ref2>` to avoid any usable disclosure gadgets. However, it may
not cover all attack vectors for Spectre variant 1.
+ Copy-from-user code has an LFENCE barrier to prevent the access_ok()
+ check from being mis-speculated. The barrier is done by the
+ barrier_nospec() macro.
+
+ For the swapgs variant of Spectre variant 1, LFENCE barriers are
+ added to interrupt, exception and NMI entry where needed. These
+ barriers are done by the FENCE_SWAPGS_KERNEL_ENTRY and
+ FENCE_SWAPGS_USER_ENTRY macros.
+
+Spectre variant 2
+~~~~~~~~~~~~~~~~~
+
For Spectre variant 2 mitigation, the compiler turns indirect calls or
jumps in the kernel into equivalent return trampolines (retpolines)
:ref:`[3] <spec_ref3>` :ref:`[9] <spec_ref9>` to go to the target
@@ -473,6 +539,12 @@ Mitigation control on the kernel command line
Spectre variant 2 mitigation can be disabled or force enabled at the
kernel command line.
+ nospectre_v1
+
+ [X86,PPC] Disable mitigations for Spectre Variant 1
+ (bounds check bypass). With this option data leaks are
+ possible in the system.
+
nospectre_v2
[X86] Disable all mitigations for the Spectre variant 2
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 46b826fcb5ad..520dedae7150 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1732,6 +1732,11 @@
Note that using this option lowers the security
provided by tboot because it makes the system
vulnerable to DMA attacks.
+ nobounce [Default off]
+ Disable bounce buffer for unstrusted devices such as
+ the Thunderbolt devices. This will treat the untrusted
+ devices as the trusted ones, hence might expose security
+ risks of DMA attacks.
intel_idle.max_cstate= [KNL,HW,ACPI,X86]
0 disables intel_idle and fall back on acpi_idle.
@@ -1811,7 +1816,7 @@
synchronously.
iommu.passthrough=
- [ARM64] Configure DMA to bypass the IOMMU by default.
+ [ARM64, X86] Configure DMA to bypass the IOMMU by default.
Format: { "0" | "1" }
0 - Use IOMMU translation for DMA.
1 - Bypass the IOMMU for DMA.
@@ -2373,7 +2378,7 @@
machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel.
- Example: machvec=hpzx1_swiotlb
+ Example: machvec=hpzx1
machtype= [Loongson] Share the same kernel image file between different
yeeloong laptop.
@@ -2545,7 +2550,7 @@
mem_encrypt=on: Activate SME
mem_encrypt=off: Do not activate SME
- Refer to Documentation/virtual/kvm/amd-memory-encryption.rst
+ Refer to Documentation/virt/kvm/amd-memory-encryption.rst
for details on when memory encryption can be activated.
mem_sleep_default= [SUSPEND] Default system suspend mode:
@@ -2604,7 +2609,7 @@
expose users to several CPU vulnerabilities.
Equivalent to: nopti [X86,PPC]
kpti=0 [ARM64]
- nospectre_v1 [PPC]
+ nospectre_v1 [X86,PPC]
nobp=0 [S390]
nospectre_v2 [X86,PPC,S390,ARM64]
spectre_v2_user=off [X86]
@@ -2965,9 +2970,9 @@
nosmt=force: Force disable SMT, cannot be undone
via the sysfs control file.
- nospectre_v1 [PPC] Disable mitigations for Spectre Variant 1 (bounds
- check bypass). With this option data leaks are possible
- in the system.
+ nospectre_v1 [X86,PPC] Disable mitigations for Spectre Variant 1
+ (bounds check bypass). With this option data leaks are
+ possible in the system.
nospectre_v2 [X86,PPC_FSL_BOOK3E,ARM64] Disable all mitigations for
the Spectre variant 2 (indirect branch prediction)
@@ -3837,12 +3842,13 @@
RCU_BOOST is not set, valid values are 0-99 and
the default is zero (non-realtime operation).
- rcutree.rcu_nocb_leader_stride= [KNL]
- Set the number of NOCB kthread groups, which
- defaults to the square root of the number of
- CPUs. Larger numbers reduces the wakeup overhead
- on the per-CPU grace-period kthreads, but increases
- that same overhead on each group's leader.
+ rcutree.rcu_nocb_gp_stride= [KNL]
+ Set the number of NOCB callback kthreads in
+ each group, which defaults to the square root
+ of the number of CPUs. Larger numbers reduce
+ the wakeup overhead on the global grace-period
+ kthread, but increases that same overhead on
+ each group's NOCB grace-period kthread.
rcutree.qhimark= [KNL]
Set threshold of queued RCU callbacks beyond which
@@ -4047,6 +4053,10 @@
rcutorture.verbose= [KNL]
Enable additional printk() statements.
+ rcupdate.rcu_cpu_stall_ftrace_dump= [KNL]
+ Dump ftrace buffer after reporting RCU CPU
+ stall warning.
+
rcupdate.rcu_cpu_stall_suppress= [KNL]
Suppress RCU CPU stall warning messages.
@@ -4090,6 +4100,13 @@
Run specified binary instead of /init from the ramdisk,
used for early userspace startup. See initrd.
+ rdrand= [X86]
+ force - Override the decision by the kernel to hide the
+ advertisement of RDRAND support (this affects
+ certain AMD processors because of buggy BIOS
+ support, specifically around the suspend/resume
+ path).
+
rdt= [HW,X86,RDT]
Turn on/off individual RDT features. List is:
cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index adea0bf2acc5..822907dcc845 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -49,6 +49,7 @@ detailed description):
- Fan control and monitoring: fan speed, fan enable/disable
- WAN enable and disable
- UWB enable and disable
+ - LCD Shadow (PrivacyGuard) enable and disable
A compatibility table by model and feature is maintained on the web
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -1409,6 +1410,28 @@ Sysfs notes
Documentation/driver-api/rfkill.rst for details.
+LCD Shadow control
+------------------
+
+procfs: /proc/acpi/ibm/lcdshadow
+
+Some newer T480s and T490s ThinkPads provide a feature called
+PrivacyGuard. By turning this feature on, the usable vertical and
+horizontal viewing angles of the LCD can be limited (as if some privacy
+screen was applied manually in front of the display).
+
+procfs notes
+^^^^^^^^^^^^
+
+The available commands are::
+
+ echo '0' >/proc/acpi/ibm/lcdshadow
+ echo '1' >/proc/acpi/ibm/lcdshadow
+
+The first command ensures the best viewing angle and the latter one turns
+on the feature, restricting the viewing angles.
+
+
EXPERIMENTAL: UWB
-----------------
diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst
index 7ab93a8404b9..bd5714547cee 100644
--- a/Documentation/admin-guide/mm/transhuge.rst
+++ b/Documentation/admin-guide/mm/transhuge.rst
@@ -53,7 +53,7 @@ disabled, there is ``khugepaged`` daemon that scans memory and
collapses sequences of basic pages into huge pages.
The THP behaviour is controlled via :ref:`sysfs <thp_sysfs>`
-interface and using madivse(2) and prctl(2) system calls.
+interface and using madvise(2) and prctl(2) system calls.
Transparent Hugepage Support maximizes the usefulness of free memory
if compared to the reservation approach of hugetlbfs by allowing all
diff --git a/Documentation/admin-guide/perf/imx-ddr.rst b/Documentation/admin-guide/perf/imx-ddr.rst
new file mode 100644
index 000000000000..517a205abad6
--- /dev/null
+++ b/Documentation/admin-guide/perf/imx-ddr.rst
@@ -0,0 +1,52 @@
+=====================================================
+Freescale i.MX8 DDR Performance Monitoring Unit (PMU)
+=====================================================
+
+There are no performance counters inside the DRAM controller, so performance
+signals are brought out to the edge of the controller where a set of 4 x 32 bit
+counters is implemented. This is controlled by the CSV modes programed in counter
+control register which causes a large number of PERF signals to be generated.
+
+Selection of the value for each counter is done via the config registers. There
+is one register for each counter. Counter 0 is special in that it always counts
+“time†and when expired causes a lock on itself and the other counters and an
+interrupt is raised. If any other counter overflows, it continues counting, and
+no interrupt is raised.
+
+The "format" directory describes format of the config (event ID) and config1
+(AXI filtering) fields of the perf_event_attr structure, see /sys/bus/event_source/
+devices/imx8_ddr0/format/. The "events" directory describes the events types
+hardware supported that can be used with perf tool, see /sys/bus/event_source/
+devices/imx8_ddr0/events/.
+ e.g.::
+ perf stat -a -e imx8_ddr0/cycles/ cmd
+ perf stat -a -e imx8_ddr0/read/,imx8_ddr0/write/ cmd
+
+AXI filtering is only used by CSV modes 0x41 (axid-read) and 0x42 (axid-write)
+to count reading or writing matches filter setting. Filter setting is various
+from different DRAM controller implementations, which is distinguished by quirks
+in the driver.
+
+* With DDR_CAP_AXI_ID_FILTER quirk.
+ Filter is defined with two configuration parts:
+ --AXI_ID defines AxID matching value.
+ --AXI_MASKING defines which bits of AxID are meaningful for the matching.
+ 0:corresponding bit is masked.
+ 1: corresponding bit is not masked, i.e. used to do the matching.
+
+ AXI_ID and AXI_MASKING are mapped on DPCR1 register in performance counter.
+ When non-masked bits are matching corresponding AXI_ID bits then counter is
+ incremented. Perf counter is incremented if
+ AxID && AXI_MASKING == AXI_ID && AXI_MASKING
+
+ This filter doesn't support filter different AXI ID for axid-read and axid-write
+ event at the same time as this filter is shared between counters.
+ e.g.::
+ perf stat -a -e imx8_ddr0/axid-read,axi_mask=0xMMMM,axi_id=0xDDDD/ cmd
+ perf stat -a -e imx8_ddr0/axid-write,axi_mask=0xMMMM,axi_id=0xDDDD/ cmd
+
+ NOTE: axi_mask is inverted in userspace(i.e. set bits are bits to mask), and
+ it will be reverted in driver automatically. so that the user can just specify
+ axi_id to monitor a specific id, rather than having to specify axi_mask.
+ e.g.::
+ perf stat -a -e imx8_ddr0/axid-read,axi_id=0x12/ cmd, which will monitor ARID=0x12
diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
index a7d44e71019d..287b98708a40 100644
--- a/Documentation/admin-guide/sysctl/net.rst
+++ b/Documentation/admin-guide/sysctl/net.rst
@@ -39,7 +39,6 @@ Table : Subdirectories in /proc/sys/net
802 E802 protocol ax25 AX25
ethernet Ethernet protocol rose X.25 PLP layer
ipv4 IP version 4 x25 X.25 protocol
- ipx IPX token-ring IBM token ring
bridge Bridging decnet DEC net
ipv6 IP version 6 tipc TIPC
========= =================== = ========== ==================
@@ -401,33 +400,7 @@ interface.
(network) that the route leads to, the router (may be directly connected), the
route flags, and the device the route is using.
-
-5. IPX
-------
-
-The IPX protocol has no tunable values in proc/sys/net.
-
-The IPX protocol does, however, provide proc/net/ipx. This lists each IPX
-socket giving the local and remote addresses in Novell format (that is
-network:node:port). In accordance with the strange Novell tradition,
-everything but the port is in hex. Not_Connected is displayed for sockets that
-are not tied to a specific remote address. The Tx and Rx queue sizes indicate
-the number of bytes pending for transmission and reception. The state
-indicates the state the socket is in and the uid is the owning uid of the
-socket.
-
-The /proc/net/ipx_interface file lists all IPX interfaces. For each interface
-it gives the network number, the node number, and indicates if the network is
-the primary network. It also indicates which device it is bound to (or
-Internal for internal networks) and the Frame Type if appropriate. Linux
-supports 802.3, 802.2, 802.2 SNAP and DIX (Blue Book) ethernet framing for
-IPX.
-
-The /proc/net/ipx_route table holds a list of IPX routes. For each route it
-gives the destination network, the router node (or Directly) and the network
-address of the router (or Connected) for internal networks.
-
-6. TIPC
+5. TIPC
-------
tipc_rmem
diff --git a/Documentation/arm64/index.rst b/Documentation/arm64/index.rst
index 96b696ba4e6c..5c0c69dc58aa 100644
--- a/Documentation/arm64/index.rst
+++ b/Documentation/arm64/index.rst
@@ -16,6 +16,7 @@ ARM64 Architecture
pointer-authentication
silicon-errata
sve
+ tagged-address-abi
tagged-pointers
.. only:: subproject and html
diff --git a/Documentation/arm64/kasan-offsets.sh b/Documentation/arm64/kasan-offsets.sh
new file mode 100644
index 000000000000..2b7a021db363
--- /dev/null
+++ b/Documentation/arm64/kasan-offsets.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Print out the KASAN_SHADOW_OFFSETS required to place the KASAN SHADOW
+# start address at the mid-point of the kernel VA space
+
+print_kasan_offset () {
+ printf "%02d\t" $1
+ printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \
+ + (1 << ($1 - 32 - $2)) \
+ - (1 << (64 - 32 - $2)) ))
+}
+
+echo KASAN_SHADOW_SCALE_SHIFT = 3
+printf "VABITS\tKASAN_SHADOW_OFFSET\n"
+print_kasan_offset 48 3
+print_kasan_offset 47 3
+print_kasan_offset 42 3
+print_kasan_offset 39 3
+print_kasan_offset 36 3
+echo
+echo KASAN_SHADOW_SCALE_SHIFT = 4
+printf "VABITS\tKASAN_SHADOW_OFFSET\n"
+print_kasan_offset 48 4
+print_kasan_offset 47 4
+print_kasan_offset 42 4
+print_kasan_offset 39 4
+print_kasan_offset 36 4
diff --git a/Documentation/arm64/memory.rst b/Documentation/arm64/memory.rst
index 464b880fc4b7..b040909e45f8 100644
--- a/Documentation/arm64/memory.rst
+++ b/Documentation/arm64/memory.rst
@@ -14,6 +14,10 @@ with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit
64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB)
virtual address, are used but the memory layout is the same.
+ARMv8.2 adds optional support for Large Virtual Address space. This is
+only available when running with a 64KB page size and expands the
+number of descriptors in the first level of translation.
+
User addresses have bits 63:48 set to 0 while the kernel addresses have
the same bits set to 1. TTBRx selection is given by bit 63 of the
virtual address. The swapper_pg_dir contains only kernel (global)
@@ -22,40 +26,43 @@ The swapper_pg_dir address is written to TTBR1 and never written to
TTBR0.
-AArch64 Linux memory layout with 4KB pages + 3 levels::
-
- Start End Size Use
- -----------------------------------------------------------------------
- 0000000000000000 0000007fffffffff 512GB user
- ffffff8000000000 ffffffffffffffff 512GB kernel
-
-
-AArch64 Linux memory layout with 4KB pages + 4 levels::
+AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit)::
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000ffffffffffff 256TB user
- ffff000000000000 ffffffffffffffff 256TB kernel
-
-
-AArch64 Linux memory layout with 64KB pages + 2 levels::
+ ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map
+ ffff800000000000 ffff9fffffffffff 32TB kasan shadow region
+ ffffa00000000000 ffffa00007ffffff 128MB bpf jit region
+ ffffa00008000000 ffffa0000fffffff 128MB modules
+ ffffa00010000000 fffffdffbffeffff ~93TB vmalloc
+ fffffdffbfff0000 fffffdfffe5f8fff ~998MB [guard region]
+ fffffdfffe5f9000 fffffdfffe9fffff 4124KB fixed mappings
+ fffffdfffea00000 fffffdfffebfffff 2MB [guard region]
+ fffffdfffec00000 fffffdffffbfffff 16MB PCI I/O space
+ fffffdffffc00000 fffffdffffdfffff 2MB [guard region]
+ fffffdffffe00000 ffffffffffdfffff 2TB vmemmap
+ ffffffffffe00000 ffffffffffffffff 2MB [guard region]
+
+
+AArch64 Linux memory layout with 64KB pages + 3 levels (52-bit with HW support)::
Start End Size Use
-----------------------------------------------------------------------
- 0000000000000000 000003ffffffffff 4TB user
- fffffc0000000000 ffffffffffffffff 4TB kernel
-
-
-AArch64 Linux memory layout with 64KB pages + 3 levels::
-
- Start End Size Use
- -----------------------------------------------------------------------
- 0000000000000000 0000ffffffffffff 256TB user
- ffff000000000000 ffffffffffffffff 256TB kernel
-
-
-For details of the virtual kernel memory layout please see the kernel
-booting log.
+ 0000000000000000 000fffffffffffff 4PB user
+ fff0000000000000 fff7ffffffffffff 2PB kernel logical memory map
+ fff8000000000000 fffd9fffffffffff 1440TB [gap]
+ fffda00000000000 ffff9fffffffffff 512TB kasan shadow region
+ ffffa00000000000 ffffa00007ffffff 128MB bpf jit region
+ ffffa00008000000 ffffa0000fffffff 128MB modules
+ ffffa00010000000 fffff81ffffeffff ~88TB vmalloc
+ fffff81fffff0000 fffffc1ffe58ffff ~3TB [guard region]
+ fffffc1ffe590000 fffffc1ffe9fffff 4544KB fixed mappings
+ fffffc1ffea00000 fffffc1ffebfffff 2MB [guard region]
+ fffffc1ffec00000 fffffc1fffbfffff 16MB PCI I/O space
+ fffffc1fffc00000 fffffc1fffdfffff 2MB [guard region]
+ fffffc1fffe00000 ffffffffffdfffff 3968GB vmemmap
+ ffffffffffe00000 ffffffffffffffff 2MB [guard region]
Translation table lookup with 4KB pages::
@@ -83,7 +90,8 @@ Translation table lookup with 64KB pages::
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
| | +--------------------------> [41:29] L2 index
- | +-------------------------------> [47:42] L1 index
+ | +-------------------------------> [47:42] L1 index (48-bit)
+ | [51:42] L1 index (52-bit)
+-------------------------------------------------> [63] TTBR0/1
@@ -96,3 +104,62 @@ ARM64_HARDEN_EL2_VECTORS is selected for particular CPUs.
When using KVM with the Virtualization Host Extensions, no additional
mappings are created, since the host kernel runs directly in EL2.
+
+52-bit VA support in the kernel
+-------------------------------
+If the ARMv8.2-LVA optional feature is present, and we are running
+with a 64KB page size; then it is possible to use 52-bits of address
+space for both userspace and kernel addresses. However, any kernel
+binary that supports 52-bit must also be able to fall back to 48-bit
+at early boot time if the hardware feature is not present.
+
+This fallback mechanism necessitates the kernel .text to be in the
+higher addresses such that they are invariant to 48/52-bit VAs. Due
+to the kasan shadow being a fraction of the entire kernel VA space,
+the end of the kasan shadow must also be in the higher half of the
+kernel VA space for both 48/52-bit. (Switching from 48-bit to 52-bit,
+the end of the kasan shadow is invariant and dependent on ~0UL,
+whilst the start address will "grow" towards the lower addresses).
+
+In order to optimise phys_to_virt and virt_to_phys, the PAGE_OFFSET
+is kept constant at 0xFFF0000000000000 (corresponding to 52-bit),
+this obviates the need for an extra variable read. The physvirt
+offset and vmemmap offsets are computed at early boot to enable
+this logic.
+
+As a single binary will need to support both 48-bit and 52-bit VA
+spaces, the VMEMMAP must be sized large enough for 52-bit VAs and
+also must be sized large enought to accommodate a fixed PAGE_OFFSET.
+
+Most code in the kernel should not need to consider the VA_BITS, for
+code that does need to know the VA size the variables are
+defined as follows:
+
+VA_BITS constant the *maximum* VA space size
+
+VA_BITS_MIN constant the *minimum* VA space size
+
+vabits_actual variable the *actual* VA space size
+
+
+Maximum and minimum sizes can be useful to ensure that buffers are
+sized large enough or that addresses are positioned close enough for
+the "worst" case.
+
+52-bit userspace VAs
+--------------------
+To maintain compatibility with software that relies on the ARMv8.0
+VA space maximum size of 48-bits, the kernel will, by default,
+return virtual addresses to userspace from a 48-bit range.
+
+Software can "opt-in" to receiving VAs from a 52-bit space by
+specifying an mmap hint parameter that is larger than 48-bit.
+For example:
+ maybe_high_address = mmap(~0UL, size, prot, flags,...);
+
+It is also possible to build a debug kernel that returns addresses
+from a 52-bit space by enabling the following kernel config options:
+ CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y
+
+Note that this option is only intended for debugging applications
+and should not be used in production.
diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
index 3e57d09246e6..17ea3fecddaa 100644
--- a/Documentation/arm64/silicon-errata.rst
+++ b/Documentation/arm64/silicon-errata.rst
@@ -115,6 +115,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip0{6,7} | #161010701 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
+| Hisilicon | Hip0{6,7} | #161010803 | N/A |
++----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
new file mode 100644
index 000000000000..d4a85d535bf9
--- /dev/null
+++ b/Documentation/arm64/tagged-address-abi.rst
@@ -0,0 +1,156 @@
+==========================
+AArch64 TAGGED ADDRESS ABI
+==========================
+
+Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
+ Catalin Marinas <catalin.marinas@arm.com>
+
+Date: 21 August 2019
+
+This document describes the usage and semantics of the Tagged Address
+ABI on AArch64 Linux.
+
+1. Introduction
+---------------
+
+On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
+userspace (EL0) to perform memory accesses through 64-bit pointers with
+a non-zero top byte. This document describes the relaxation of the
+syscall ABI that allows userspace to pass certain tagged pointers to
+kernel syscalls.
+
+2. AArch64 Tagged Address ABI
+-----------------------------
+
+From the kernel syscall interface perspective and for the purposes of
+this document, a "valid tagged pointer" is a pointer with a potentially
+non-zero top-byte that references an address in the user process address
+space obtained in one of the following ways:
+
+- ``mmap()`` syscall where either:
+
+ - flags have the ``MAP_ANONYMOUS`` bit set or
+ - the file descriptor refers to a regular file (including those
+ returned by ``memfd_create()``) or ``/dev/zero``
+
+- ``brk()`` syscall (i.e. the heap area between the initial location of
+ the program break at process creation and its current location).
+
+- any memory mapped by the kernel in the address space of the process
+ during creation and with the same restrictions as for ``mmap()`` above
+ (e.g. data, bss, stack).
+
+The AArch64 Tagged Address ABI has two stages of relaxation depending
+how the user addresses are used by the kernel:
+
+1. User addresses not accessed by the kernel but used for address space
+ management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
+ of valid tagged pointers in this context is always allowed.
+
+2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
+ relaxation is disabled by default and the application thread needs to
+ explicitly enable it via ``prctl()`` as follows:
+
+ - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
+ Address ABI for the calling thread.
+
+ The ``(unsigned int) arg2`` argument is a bit mask describing the
+ control mode used:
+
+ - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
+ Default status is disabled.
+
+ Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
+
+ - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
+ Address ABI for the calling thread.
+
+ Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
+
+ The ABI properties described above are thread-scoped, inherited on
+ clone() and fork() and cleared on exec().
+
+ Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
+ returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
+ disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
+ ``sysctl abi.tagged_addr_disabled`` configuration is 0.
+
+When the AArch64 Tagged Address ABI is enabled for a thread, the
+following behaviours are guaranteed:
+
+- All syscalls except the cases mentioned in section 3 can accept any
+ valid tagged pointer.
+
+- The syscall behaviour is undefined for invalid tagged pointers: it may
+ result in an error code being returned, a (fatal) signal being raised,
+ or other modes of failure.
+
+- The syscall behaviour for a valid tagged pointer is the same as for
+ the corresponding untagged pointer.
+
+
+A definition of the meaning of tagged pointers on AArch64 can be found
+in Documentation/arm64/tagged-pointers.rst.
+
+3. AArch64 Tagged Address ABI Exceptions
+-----------------------------------------
+
+The following system call parameters must be untagged regardless of the
+ABI relaxation:
+
+- ``prctl()`` other than pointers to user data either passed directly or
+ indirectly as arguments to be accessed by the kernel.
+
+- ``ioctl()`` other than pointers to user data either passed directly or
+ indirectly as arguments to be accessed by the kernel.
+
+- ``shmat()`` and ``shmdt()``.
+
+Any attempt to use non-zero tagged pointers may result in an error code
+being returned, a (fatal) signal being raised, or other modes of
+failure.
+
+4. Example of correct usage
+---------------------------
+.. code-block:: c
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <sys/prctl.h>
+
+ #define PR_SET_TAGGED_ADDR_CTRL 55
+ #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+
+ #define TAG_SHIFT 56
+
+ int main(void)
+ {
+ int tbi_enabled = 0;
+ unsigned long tag = 0;
+ char *ptr;
+
+ /* check/enable the tagged address ABI */
+ if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
+ tbi_enabled = 1;
+
+ /* memory allocation */
+ ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED)
+ return 1;
+
+ /* set a non-zero tag if the ABI is available */
+ if (tbi_enabled)
+ tag = rand() & 0xff;
+ ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
+
+ /* memory access to a tagged address */
+ strcpy(ptr, "tagged pointer\n");
+
+ /* syscall with a tagged pointer */
+ write(1, ptr, strlen(ptr));
+
+ return 0;
+ }
diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index 2acdec3ebbeb..eab4323609b9 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -20,7 +20,9 @@ Passing tagged addresses to the kernel
--------------------------------------
All interpretation of userspace memory addresses by the kernel assumes
-an address tag of 0x00.
+an address tag of 0x00, unless the application enables the AArch64
+Tagged Address ABI explicitly
+(Documentation/arm64/tagged-address-abi.rst).
This includes, but is not limited to, addresses found in:
@@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in:
- the frame pointer (x29) and frame records, e.g. when interpreting
them to generate a backtrace or call graph.
-Using non-zero address tags in any of these locations may result in an
-error code being returned, a (fatal) signal being raised, or other modes
-of failure.
+Using non-zero address tags in any of these locations when the
+userspace application did not enable the AArch64 Tagged Address ABI may
+result in an error code being returned, a (fatal) signal being raised,
+or other modes of failure.
-For these reasons, passing non-zero address tags to the kernel via
-system calls is forbidden, and using a non-zero address tag for sp is
-strongly discouraged.
+For these reasons, when the AArch64 Tagged Address ABI is disabled,
+passing non-zero address tags to the kernel via system calls is
+forbidden, and using a non-zero address tag for sp is strongly
+discouraged.
Programs maintaining a frame pointer and frame records that use non-zero
address tags may suffer impaired or inaccurate debug and profiling
@@ -59,6 +63,9 @@ be preserved.
The architecture prevents the use of a tagged PC, so the upper byte will
be set to a sign-extension of bit 55 on exception return.
+This behaviour is maintained when the AArch64 Tagged Address ABI is
+enabled.
+
Other considerations
--------------------
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 3b2397bcb565..a8fe845832bc 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -16,6 +16,8 @@ import sys
import os
import sphinx
+from subprocess import check_output
+
# Get Sphinx version
major, minor, patch = sphinx.version_info[:3]
@@ -276,10 +278,21 @@ latex_elements = {
\\setsansfont{DejaVu Sans}
\\setromanfont{DejaVu Serif}
\\setmonofont{DejaVu Sans Mono}
-
'''
}
+# At least one book (translations) may have Asian characters
+# with are only displayed if xeCJK is used
+
+cjk_cmd = check_output(['fc-list', '--format="%{family[0]}\n"']).decode('utf-8', 'ignore')
+if cjk_cmd.find("Noto Sans CJK SC") >= 0:
+ print ("enabling CJK for LaTeX builder")
+ latex_elements['preamble'] += '''
+ % This is needed for translations
+ \\usepackage{xeCJK}
+ \\setCJKmainfont{Noto Sans CJK SC}
+ '''
+
# Fix reference escape troubles with Sphinx 1.4.x
if major == 1 and minor > 3:
latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
@@ -410,6 +423,21 @@ latex_documents = [
'The kernel development community', 'manual'),
]
+# Add all other index files from Documentation/ subdirectories
+for fn in os.listdir('.'):
+ doc = os.path.join(fn, "index")
+ if os.path.exists(doc + ".rst"):
+ has = False
+ for l in latex_documents:
+ if l[0] == doc:
+ has = True
+ break
+ if not has:
+ latex_documents.append((doc, fn + '.tex',
+ 'Linux %s Documentation' % fn.capitalize(),
+ 'The kernel development community',
+ 'manual'))
+
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
diff --git a/Documentation/core-api/conf.py b/Documentation/core-api/conf.py
deleted file mode 100644
index db1f7659f3da..000000000000
--- a/Documentation/core-api/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Core-API Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'core-api.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/crypto/conf.py b/Documentation/crypto/conf.py
deleted file mode 100644
index 4335d251ddf3..000000000000
--- a/Documentation/crypto/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Crypto API'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'crypto-api.tex', 'Linux Kernel Crypto API manual',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/dev-tools/conf.py b/Documentation/dev-tools/conf.py
deleted file mode 100644
index 7faafa3f7888..000000000000
--- a/Documentation/dev-tools/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Development tools for the kernel"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'dev-tools.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/devicetree/bindings/Makefile b/Documentation/devicetree/bindings/Makefile
index 6b0dfd5c17ba..5138a2f6232a 100644
--- a/Documentation/devicetree/bindings/Makefile
+++ b/Documentation/devicetree/bindings/Makefile
@@ -19,7 +19,9 @@ quiet_cmd_mk_schema = SCHEMA $@
DT_DOCS = $(shell \
cd $(srctree)/$(src) && \
- find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+ find * \( -name '*.yaml' ! \
+ -name $(DT_TMP_SCHEMA) ! \
+ -name '*.example.dt.yaml' \) \
)
DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 325c6fd3566d..99015cef8bb1 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -91,13 +91,11 @@ properties:
- description: Boards with the Amlogic Meson GXL S905X SoC
items:
- enum:
- - amediatech,x96-max
- amlogic,p212
- hwacom,amazetv
- khadas,vim
- libretech,cc
- nexbox,a95x
- - seirobotics,sei510
- const: amlogic,s905x
- const: amlogic,meson-gxl
@@ -129,16 +127,33 @@ properties:
- const: amlogic,a113d
- const: amlogic,meson-axg
- - description: Boards with the Amlogic Meson G12A S905D2 SoC
+ - description: Boards with the Amlogic Meson G12A S905D2/X2/Y2 SoC
items:
- enum:
+ - amediatech,x96-max
- amlogic,u200
+ - seirobotics,sei510
- const: amlogic,g12a
+ - description: Boards with the Amlogic Meson G12B A311D SoC
+ items:
+ - enum:
+ - khadas,vim3
+ - const: amlogic,a311d
+ - const: amlogic,g12b
+
- description: Boards with the Amlogic Meson G12B S922X SoC
items:
- enum:
- hardkernel,odroid-n2
+ - khadas,vim3
+ - const: amlogic,s922x
- const: amlogic,g12b
+ - description: Boards with the Amlogic Meson SM1 S905X3/D3/Y3 SoC
+ items:
+ - enum:
+ - seirobotics,sei610
+ - khadas,vim3l
+ - const: amlogic,sm1
...
diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt
index 317a2fc3667a..083dbf96ee00 100644
--- a/Documentation/devicetree/bindings/arm/arm,scmi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt
@@ -73,6 +73,16 @@ Required properties:
as used by the firmware. Refer to platform details
for your implementation for the IDs to use.
+Reset signal bindings for the reset domains based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding for the SCMI reset domain providers uses the generic reset
+signal binding[5].
+
+Required properties:
+ - #reset-cells : Should be 1. Contains the reset domain ID value used
+ by SCMI commands.
+
SRAM and Shared Memory for SCMI
-------------------------------
@@ -93,6 +103,7 @@ Required sub-node properties:
[2] Documentation/devicetree/bindings/power/power_domain.txt
[3] Documentation/devicetree/bindings/thermal/thermal.txt
[4] Documentation/devicetree/bindings/sram/sram.txt
+[5] Documentation/devicetree/bindings/reset/reset.txt
Example:
@@ -152,6 +163,11 @@ firmware {
reg = <0x15>;
#thermal-sensor-cells = <1>;
};
+
+ scmi_reset: protocol@16 {
+ reg = <0x16>;
+ #reset-cells = <1>;
+ };
};
};
@@ -166,6 +182,7 @@ hdlcd@7ff60000 {
reg = <0 0x7ff60000 0 0x1000>;
clocks = <&scmi_clk 4>;
power-domains = <&scmi_devpd 1>;
+ resets = <&scmi_reset 10>;
};
thermal-zones {
diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index aa40b074b864..727e0ffc702b 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -175,6 +175,7 @@ properties:
- amlogic,meson8-smp
- amlogic,meson8b-smp
- arm,realview-smp
+ - aspeed,ast2600-smp
- brcm,bcm11351-cpu-method
- brcm,bcm23550
- brcm,bcm2836-smp
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 7294ac36f4c0..1b4b4e6573b5 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -161,6 +161,20 @@ properties:
items:
- enum:
- fsl,imx6ul-14x14-evk # i.MX6 UltraLite 14x14 EVK Board
+ - kontron,imx6ul-n6310-som # Kontron N6310 SOM
+ - const: fsl,imx6ul
+
+ - description: Kontron N6310 S Board
+ items:
+ - const: kontron,imx6ul-n6310-s
+ - const: kontron,imx6ul-n6310-som
+ - const: fsl,imx6ul
+
+ - description: Kontron N6310 S 43 Board
+ items:
+ - const: kontron,imx6ul-n6310-s-43
+ - const: kontron,imx6ul-n6310-s
+ - const: kontron,imx6ul-n6310-som
- const: fsl,imx6ul
- description: i.MX6ULL based Boards
@@ -188,6 +202,7 @@ properties:
- fsl,imx7d-sdb # i.MX7 SabreSD Board
- novtech,imx7d-meerkat96 # i.MX7 Meerkat96 Board
- tq,imx7d-mba7 # i.MX7D TQ MBa7 with TQMa7D SoM
+ - zii,imx7d-rmu2 # ZII RMU2 Board
- zii,imx7d-rpu2 # ZII RPU2 Board
- const: fsl,imx7d
@@ -214,16 +229,26 @@ properties:
- fsl,imx8mm-evk # i.MX8MM EVK Board
- const: fsl,imx8mm
+ - description: i.MX8MN based Boards
+ items:
+ - enum:
+ - fsl,imx8mn-ddr4-evk # i.MX8MN DDR4 EVK Board
+ - const: fsl,imx8mn
+
- description: i.MX8MQ based Boards
items:
- enum:
+ - boundary,imx8mq-nitrogen8m # i.MX8MQ NITROGEN Board
- fsl,imx8mq-evk # i.MX8MQ EVK Board
- purism,librem5-devkit # Purism Librem5 devkit
+ - solidrun,hummingboard-pulse # SolidRun Hummingboard Pulse
+ - technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk
- const: fsl,imx8mq
- description: i.MX8QXP based Boards
items:
- enum:
+ - einfochips,imx8qxp-ai_ml # i.MX8QXP AI_ML Board
- fsl,imx8qxp-mek # i.MX8QXP MEK Board
- const: fsl,imx8qxp
@@ -283,6 +308,7 @@ properties:
- description: LS1046A based Boards
items:
- enum:
+ - fsl,ls1046a-frwy
- fsl,ls1046a-qds
- fsl,ls1046a-rdb
- const: fsl,ls1046a
diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
index 326f29b270ad..2d325bed37e5 100644
--- a/Documentation/devicetree/bindings/arm/idle-states.txt
+++ b/Documentation/devicetree/bindings/arm/idle-states.txt
@@ -703,4 +703,4 @@ cpus {
https://www.devicetree.org/specifications/
[6] ARM Linux Kernel documentation - Booting AArch64 Linux
- Documentation/arm64/booting.txt
+ Documentation/arm64/booting.rst
diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index a4ad2eb926f9..4043c5046441 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -48,6 +48,10 @@ properties:
- const: mediatek,mt6765
- items:
- enum:
+ - mediatek,mt6779-evb
+ - const: mediatek,mt6779
+ - items:
+ - enum:
- mediatek,mt6795-evb
- const: mediatek,mt6795
- items:
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 54ef6b6b9189..e39d8f02e33c 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -45,6 +45,7 @@ description: |
mtp
sbc
hk01
+ qrd
The 'soc_version' and 'board_version' elements take the form of v<Major>.<Minor>
where the minor number may be omitted when it's zero, i.e. v1.0 is the same
@@ -116,6 +117,13 @@ properties:
- const: qcom,msm8916
- items:
+ - enum:
+ - longcheer,l8150
+ - samsung,a3u-eur
+ - samsung,a5u-eur
+ - const: qcom,msm8916
+
+ - items:
- const: qcom,msm8996-mtp
- items:
diff --git a/Documentation/devicetree/bindings/arm/renesas.yaml b/Documentation/devicetree/bindings/arm/renesas.yaml
index 08c923f8c257..28eb458f761a 100644
--- a/Documentation/devicetree/bindings/arm/renesas.yaml
+++ b/Documentation/devicetree/bindings/arm/renesas.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/arm/shmobile.yaml#
+$id: http://devicetree.org/schemas/arm/renesas.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas SH-Mobile, R-Mobile, and R-Car Platform Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index 34865042f4e4..c82c5e57d44c 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -128,6 +128,21 @@ properties:
- const: google,veyron
- const: rockchip,rk3288
+ - description: Google Fievel (AOPEN Chromebox Mini)
+ items:
+ - const: google,veyron-fievel-rev8
+ - const: google,veyron-fievel-rev7
+ - const: google,veyron-fievel-rev6
+ - const: google,veyron-fievel-rev5
+ - const: google,veyron-fievel-rev4
+ - const: google,veyron-fievel-rev3
+ - const: google,veyron-fievel-rev2
+ - const: google,veyron-fievel-rev1
+ - const: google,veyron-fievel-rev0
+ - const: google,veyron-fievel
+ - const: google,veyron
+ - const: rockchip,rk3288
+
- description: Google Gru (dev-board)
items:
- const: google,gru-rev15
@@ -311,6 +326,21 @@ properties:
- const: google,veyron
- const: rockchip,rk3288
+ - description: Google Tiger (AOpen Chromebase Mini)
+ items:
+ - const: google,veyron-tiger-rev8
+ - const: google,veyron-tiger-rev7
+ - const: google,veyron-tiger-rev6
+ - const: google,veyron-tiger-rev5
+ - const: google,veyron-tiger-rev4
+ - const: google,veyron-tiger-rev3
+ - const: google,veyron-tiger-rev2
+ - const: google,veyron-tiger-rev1
+ - const: google,veyron-tiger-rev0
+ - const: google,veyron-tiger
+ - const: google,veyron
+ - const: rockchip,rk3288
+
- description: Haoyu MarsBoard RK3066
items:
- const: haoyu,marsboard-rk3066
@@ -329,6 +359,16 @@ properties:
- khadas,edge-v
- const: rockchip,rk3399
+ - description: Mecer Xtreme Mini S6
+ items:
+ - const: mecer,xms6
+ - const: rockchip,rk3229
+
+ - description: Leez RK3399 P710
+ items:
+ - const: leez,p710
+ - const: rockchip,rk3399
+
- description: mqmaker MiQi
items:
- const: mqmaker,miqi
@@ -424,11 +464,6 @@ properties:
- rockchip,rk3288-evb-rk808
- const: rockchip,rk3288
- - description: Rockchip RK3288 Fennec
- items:
- - const: rockchip,rk3288-fennec
- - const: rockchip,rk3288
-
- description: Rockchip RK3328 Evaluation board
items:
- const: rockchip,rk3328-evb
diff --git a/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml b/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
index aae53fc3cb1e..2bd519d2e855 100644
--- a/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
+++ b/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/arm/milbeaut.yaml#
+$id: http://devicetree.org/schemas/arm/socionext/milbeaut.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Milbeaut platforms device tree bindings
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 000a00d12d6a..972b1e9ee804 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -353,6 +353,12 @@ properties:
- const: licheepi,licheepi-zero
- const: allwinner,sun8i-v3s
+ - description: Lichee Zero Plus (with S3, without eMMC/SPI Flash)
+ items:
+ - const: sipeed,lichee-zero-plus
+ - const: sochip,s3
+ - const: allwinner,sun8i-v3
+
- description: Linksprite PCDuino
items:
- const: linksprite,a10-pcduino
@@ -568,6 +574,11 @@ properties:
- const: olimex,a64-olinuxino
- const: allwinner,sun50i-a64
+ - description: Olimex A64-OlinuXino (with eMMC)
+ items:
+ - const: olimex,a64-olinuxino-emmc
+ - const: allwinner,sun50i-a64
+
- description: Olimex A64 Teres-I
items:
- const: olimex,a64-teres-i
@@ -671,6 +682,11 @@ properties:
- const: sinlinx,sina33
- const: allwinner,sun8i-a33
+ - description: Tanix TX6
+ items:
+ - const: oranth,tanix-tx6
+ - const: allwinner,sun50i-h6
+
- description: TBS A711 Tablet
items:
- const: tbs-biometrics,a711
diff --git a/Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml b/Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
index 4326d2cfa15d..a8765ba29476 100644
--- a/Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
+++ b/Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/arm/ti/davinci.yaml#
+$id: http://devicetree.org/schemas/arm/ti/ti,davinci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments DaVinci Platforms Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt
index dda7d6d66479..1b1d1c5c21ea 100644
--- a/Documentation/devicetree/bindings/bus/imx-weim.txt
+++ b/Documentation/devicetree/bindings/bus/imx-weim.txt
@@ -44,6 +44,10 @@ Optional properties:
what bootloader sets up in IOMUXC_GPR1[11:0] will be
used.
+ - fsl,burst-clk-enable For "fsl,imx50-weim" and "fsl,imx6q-weim" type of
+ devices, the presence of this property indicates that
+ the weim bus should operate in Burst Clock Mode.
+
Timing property for child nodes. It is mandatory, not optional.
- fsl,weim-cs-timing: The timing array, contains timing values for the
diff --git a/Documentation/devicetree/bindings/bus/moxtet.txt b/Documentation/devicetree/bindings/bus/moxtet.txt
new file mode 100644
index 000000000000..fb50fc865336
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/moxtet.txt
@@ -0,0 +1,46 @@
+Turris Mox module status and configuration bus (over SPI)
+
+Required properties:
+ - compatible : Should be "cznic,moxtet"
+ - #address-cells : Has to be 1
+ - #size-cells : Has to be 0
+ - spi-cpol : Required inverted clock polarity
+ - spi-cpha : Required shifted clock phase
+ - interrupts : Must contain reference to the shared interrupt line
+ - interrupt-controller : Required
+ - #interrupt-cells : Has to be 1
+
+For other required and optional properties of SPI slave nodes please refer to
+../spi/spi-bus.txt.
+
+Required properties of subnodes:
+ - reg : Should be position on the Moxtet bus (how many Moxtet
+ modules are between this module and CPU module, so
+ either 0 or a positive integer)
+
+The driver finds the devices connected to the bus by itself, but it may be
+needed to reference some of them from other parts of the device tree. In that
+case the devices can be defined as subnodes of the moxtet node.
+
+Example:
+
+ moxtet@1 {
+ compatible = "cznic,moxtet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ spi-max-frequency = <10000000>;
+ spi-cpol;
+ spi-cpha;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gpiosb>;
+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+
+ moxtet_sfp: gpio@0 {
+ compatible = "cznic,moxtet-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ }
+ };
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index c935405458fe..fa4d143a73de 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/phy/allwinner,sun4i-a10-ccu.yaml#
+$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-ccu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner Clock Control Unit Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
index 0f777749f4f1..b3957d10d241 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
+++ b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
@@ -22,6 +22,7 @@ Required Properties:
components.
- resets : phandle of the internal reset line
- #clock-cells : should be 1.
+- #reset-cells : should be 1 on the g12a (and following) soc family
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
index 6eaa52092313..7ccecd5c02c1 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
+++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
@@ -11,6 +11,7 @@ Required Properties:
"amlogic,axg-clkc" for AXG SoC.
"amlogic,g12a-clkc" for G12A SoC.
"amlogic,g12b-clkc" for G12B SoC.
+ "amlogic,sm1-clkc" for SM1 SoC.
- clocks : list of clock phandle, one for each entry clock-names.
- clock-names : should contain the following:
* "xtal": the platform xtal
diff --git a/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml
new file mode 100644
index 000000000000..622f3658bd9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bindings/clock/imx8mn-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8M Nano Clock Control Module Binding
+
+maintainers:
+ - Anson Huang <Anson.Huang@nxp.com>
+
+description: |
+ NXP i.MX8M Nano clock control module is an integrated clock controller, which
+ generates and supplies to all modules.
+
+properties:
+ compatible:
+ const: fsl,imx8mn-ccm
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: 32k osc
+ - description: 24m osc
+ - description: ext1 clock input
+ - description: ext2 clock input
+ - description: ext3 clock input
+ - description: ext4 clock input
+
+ clock-names:
+ items:
+ - const: osc_32k
+ - const: osc_24m
+ - const: clk_ext1
+ - const: clk_ext2
+ - const: clk_ext3
+ - const: clk_ext4
+
+ '#clock-cells':
+ const: 1
+ description: |
+ The clock consumer should specify the desired clock by having the clock
+ ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mn-clock.h
+ for the full list of i.MX8M Nano clock IDs.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - '#clock-cells'
+
+examples:
+ # Clock Control Module node:
+ - |
+ clk: clock-controller@30380000 {
+ compatible = "fsl,imx8mn-ccm";
+ reg = <0x0 0x30380000 0x0 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>,
+ <&clk_ext2>, <&clk_ext3>, <&clk_ext4>;
+ clock-names = "osc_32k", "osc_24m", "clk_ext1",
+ "clk_ext2", "clk_ext3", "clk_ext4";
+ };
+
+ # Required external clocks for Clock Control Module node:
+ - |
+ osc_32k: clock-osc-32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "osc_32k";
+ };
+
+ osc_24m: clock-osc-24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_24m";
+ };
+
+ clk_ext1: clock-ext1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext1";
+ };
+
+ clk_ext2: clock-ext2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext2";
+ };
+
+ clk_ext3: clock-ext3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext3";
+ };
+
+ clk_ext4: clock-ext4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <133000000>;
+ clock-output-names = "clk_ext4";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/arm/topology.txt b/Documentation/devicetree/bindings/cpu/cpu-topology.txt
index b0d80c0fb265..99918189403c 100644
--- a/Documentation/devicetree/bindings/arm/topology.txt
+++ b/Documentation/devicetree/bindings/cpu/cpu-topology.txt
@@ -1,21 +1,19 @@
===========================================
-ARM topology binding description
+CPU topology binding description
===========================================
===========================================
1 - Introduction
===========================================
-In an ARM system, the hierarchy of CPUs is defined through three entities that
+In a SMP system, the hierarchy of CPUs is defined through three entities that
are used to describe the layout of physical CPUs in the system:
+- socket
- cluster
- core
- thread
-The cpu nodes (bindings defined in [1]) represent the devices that
-correspond to physical CPUs and are to be mapped to the hierarchy levels.
-
The bottom hierarchy level sits at core or thread level depending on whether
symmetric multi-threading (SMT) is supported or not.
@@ -24,33 +22,31 @@ threads existing in the system and map to the hierarchy level "thread" above.
In systems where SMT is not supported "cpu" nodes represent all cores present
in the system and map to the hierarchy level "core" above.
-ARM topology bindings allow one to associate cpu nodes with hierarchical groups
+CPU topology bindings allow one to associate cpu nodes with hierarchical groups
corresponding to the system hierarchy; syntactically they are defined as device
tree nodes.
-The remainder of this document provides the topology bindings for ARM, based
-on the Devicetree Specification, available from:
+Currently, only ARM/RISC-V intend to use this cpu topology binding but it may be
+used for any other architecture as well.
-https://www.devicetree.org/specifications/
+The cpu nodes, as per bindings defined in [4], represent the devices that
+correspond to physical CPUs and are to be mapped to the hierarchy levels.
-If not stated otherwise, whenever a reference to a cpu node phandle is made its
-value must point to a cpu node compliant with the cpu node bindings as
-documented in [1].
A topology description containing phandles to cpu nodes that are not compliant
-with bindings standardized in [1] is therefore considered invalid.
+with bindings standardized in [4] is therefore considered invalid.
===========================================
2 - cpu-map node
===========================================
-The ARM CPU topology is defined within the cpu-map node, which is a direct
+The ARM/RISC-V CPU topology is defined within the cpu-map node, which is a direct
child of the cpus node and provides a container where the actual topology
nodes are listed.
- cpu-map node
- Usage: Optional - On ARM SMP systems provide CPUs topology to the OS.
- ARM uniprocessor systems do not require a topology
+ Usage: Optional - On SMP systems provide CPUs topology to the OS.
+ Uniprocessor systems do not require a topology
description and therefore should not define a
cpu-map node.
@@ -63,21 +59,23 @@ nodes are listed.
The cpu-map node's child nodes can be:
- - one or more cluster nodes
+ - one or more cluster nodes or
+ - one or more socket nodes in a multi-socket system
Any other configuration is considered invalid.
-The cpu-map node can only contain three types of child nodes:
+The cpu-map node can only contain 4 types of child nodes:
+- socket node
- cluster node
- core node
- thread node
whose bindings are described in paragraph 3.
-The nodes describing the CPU topology (cluster/core/thread) can only
-be defined within the cpu-map node and every core/thread in the system
-must be defined within the topology. Any other configuration is
+The nodes describing the CPU topology (socket/cluster/core/thread) can
+only be defined within the cpu-map node and every core/thread in the
+system must be defined within the topology. Any other configuration is
invalid and therefore must be ignored.
===========================================
@@ -85,26 +83,44 @@ invalid and therefore must be ignored.
===========================================
cpu-map child nodes must follow a naming convention where the node name
-must be "clusterN", "coreN", "threadN" depending on the node type (ie
-cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes which
-are siblings within a single common parent node must be given a unique and
+must be "socketN", "clusterN", "coreN", "threadN" depending on the node type
+(ie socket/cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes
+which are siblings within a single common parent node must be given a unique and
sequential N value, starting from 0).
cpu-map child nodes which do not share a common parent node can have the same
name (ie same number N as other cpu-map child nodes at different device tree
levels) since name uniqueness will be guaranteed by the device tree hierarchy.
===========================================
-3 - cluster/core/thread node bindings
+3 - socket/cluster/core/thread node bindings
===========================================
-Bindings for cluster/cpu/thread nodes are defined as follows:
+Bindings for socket/cluster/cpu/thread nodes are defined as follows:
+
+- socket node
+
+ Description: must be declared within a cpu-map node, one node
+ per physical socket in the system. A system can
+ contain single or multiple physical socket.
+ The association of sockets and NUMA nodes is beyond
+ the scope of this bindings, please refer [2] for
+ NUMA bindings.
+
+ This node is optional for a single socket system.
+
+ The socket node name must be "socketN" as described in 2.1 above.
+ A socket node can not be a leaf node.
+
+ A socket node's child nodes must be one or more cluster nodes.
+
+ Any other configuration is considered invalid.
- cluster node
Description: must be declared within a cpu-map node, one node
per cluster. A system can contain several layers of
- clustering and cluster nodes can be contained in parent
- cluster nodes.
+ clustering within a single physical socket and cluster
+ nodes can be contained in parent cluster nodes.
The cluster node name must be "clusterN" as described in 2.1 above.
A cluster node can not be a leaf node.
@@ -164,90 +180,93 @@ Bindings for cluster/cpu/thread nodes are defined as follows:
4 - Example dts
===========================================
-Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters):
+Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters in a single
+physical socket):
cpus {
#size-cells = <0>;
#address-cells = <2>;
cpu-map {
- cluster0 {
+ socket0 {
cluster0 {
- core0 {
- thread0 {
- cpu = <&CPU0>;
+ cluster0 {
+ core0 {
+ thread0 {
+ cpu = <&CPU0>;
+ };
+ thread1 {
+ cpu = <&CPU1>;
+ };
};
- thread1 {
- cpu = <&CPU1>;
- };
- };
- core1 {
- thread0 {
- cpu = <&CPU2>;
- };
- thread1 {
- cpu = <&CPU3>;
+ core1 {
+ thread0 {
+ cpu = <&CPU2>;
+ };
+ thread1 {
+ cpu = <&CPU3>;
+ };
};
};
- };
- cluster1 {
- core0 {
- thread0 {
- cpu = <&CPU4>;
- };
- thread1 {
- cpu = <&CPU5>;
+ cluster1 {
+ core0 {
+ thread0 {
+ cpu = <&CPU4>;
+ };
+ thread1 {
+ cpu = <&CPU5>;
+ };
};
- };
- core1 {
- thread0 {
- cpu = <&CPU6>;
- };
- thread1 {
- cpu = <&CPU7>;
- };
- };
- };
- };
-
- cluster1 {
- cluster0 {
- core0 {
- thread0 {
- cpu = <&CPU8>;
- };
- thread1 {
- cpu = <&CPU9>;
- };
- };
- core1 {
- thread0 {
- cpu = <&CPU10>;
- };
- thread1 {
- cpu = <&CPU11>;
+ core1 {
+ thread0 {
+ cpu = <&CPU6>;
+ };
+ thread1 {
+ cpu = <&CPU7>;
+ };
};
};
};
cluster1 {
- core0 {
- thread0 {
- cpu = <&CPU12>;
+ cluster0 {
+ core0 {
+ thread0 {
+ cpu = <&CPU8>;
+ };
+ thread1 {
+ cpu = <&CPU9>;
+ };
};
- thread1 {
- cpu = <&CPU13>;
+ core1 {
+ thread0 {
+ cpu = <&CPU10>;
+ };
+ thread1 {
+ cpu = <&CPU11>;
+ };
};
};
- core1 {
- thread0 {
- cpu = <&CPU14>;
+
+ cluster1 {
+ core0 {
+ thread0 {
+ cpu = <&CPU12>;
+ };
+ thread1 {
+ cpu = <&CPU13>;
+ };
};
- thread1 {
- cpu = <&CPU15>;
+ core1 {
+ thread0 {
+ cpu = <&CPU14>;
+ };
+ thread1 {
+ cpu = <&CPU15>;
+ };
};
};
};
@@ -470,6 +489,65 @@ cpus {
};
};
+Example 3: HiFive Unleashed (RISC-V 64 bit, 4 core system)
+
+{
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "sifive,fu540g", "sifive,fu500";
+ model = "sifive,hifive-unleashed-a00";
+
+ ...
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu-map {
+ socket0 {
+ cluster0 {
+ core0 {
+ cpu = <&CPU1>;
+ };
+ core1 {
+ cpu = <&CPU2>;
+ };
+ core2 {
+ cpu0 = <&CPU2>;
+ };
+ core3 {
+ cpu0 = <&CPU3>;
+ };
+ };
+ };
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "sifive,rocket0", "riscv";
+ reg = <0x1>;
+ }
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "sifive,rocket0", "riscv";
+ reg = <0x2>;
+ }
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "sifive,rocket0", "riscv";
+ reg = <0x3>;
+ }
+ CPU4: cpu@4 {
+ device_type = "cpu";
+ compatible = "sifive,rocket0", "riscv";
+ reg = <0x4>;
+ }
+ }
+};
===============================================================================
[1] ARM Linux kernel documentation
Documentation/devicetree/bindings/arm/cpus.yaml
+[2] Devicetree NUMA binding description
+ Documentation/devicetree/bindings/numa.txt
+[3] RISC-V Linux kernel documentation
+ Documentation/devicetree/bindings/riscv/cpus.txt
+[4] https://www.devicetree.org/specifications/
diff --git a/Documentation/devicetree/bindings/eeprom/at25.txt b/Documentation/devicetree/bindings/eeprom/at25.txt
index b3bde97dc199..42577dd113dd 100644
--- a/Documentation/devicetree/bindings/eeprom/at25.txt
+++ b/Documentation/devicetree/bindings/eeprom/at25.txt
@@ -3,6 +3,7 @@ EEPROMs (SPI) compatible with Atmel at25.
Required properties:
- compatible : Should be "<vendor>,<type>", and generic value "atmel,at25".
Example "<vendor>,<type>" values:
+ "anvo,anv32e61w"
"microchip,25lc040"
"st,m95m02"
"st,m95256"
diff --git a/Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt b/Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
new file mode 100644
index 000000000000..338169dea7bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
@@ -0,0 +1,19 @@
+Turris Mox rWTM firmware driver
+
+Required properties:
+ - compatible : Should be "cznic,turris-mox-rwtm"
+ - mboxes : Must contain a reference to associated mailbox
+
+This device tree node should be used on Turris Mox, or potentially another A3700
+compatible device running the Mox's rWTM firmware in the secure processor (for
+example it is possible to flash this firmware into EspressoBin).
+
+Example:
+
+ firmware {
+ turris-mox-rwtm {
+ compatible = "cznic,turris-mox-rwtm";
+ mboxes = <&rwtm 0>;
+ status = "okay";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml b/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
index 8cb136c376fb..4f0db8ee226a 100644
--- a/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
+++ b/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
@@ -2,7 +2,7 @@
# Copyright 2019 Linaro Ltd.
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/firmware/intel-ixp4xx-network-processing-engine.yaml#"
+$id: "http://devicetree.org/schemas/firmware/intel,ixp4xx-network-processing-engine.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx Network Processing Engine
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
index 41f133a4e2fa..3f29ea04b5fe 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -9,14 +9,16 @@ Required properties:
- compatible: must contain one of the following:
* "qcom,scm-apq8064"
* "qcom,scm-apq8084"
+ * "qcom,scm-ipq4019"
* "qcom,scm-msm8660"
* "qcom,scm-msm8916"
* "qcom,scm-msm8960"
* "qcom,scm-msm8974"
* "qcom,scm-msm8996"
* "qcom,scm-msm8998"
- * "qcom,scm-ipq4019"
+ * "qcom,scm-sc7180"
* "qcom,scm-sdm845"
+ * "qcom,scm-sm8150"
and:
* "qcom,scm"
- clocks: Specifies clocks needed by the SCM interface, if any:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
index 7e9b586770b0..b2033fc3a71a 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
@@ -2,7 +2,8 @@ Aspeed GPIO controller Device Tree Bindings
-------------------------------------------
Required properties:
-- compatible : Either "aspeed,ast2400-gpio" or "aspeed,ast2500-gpio"
+- compatible : Either "aspeed,ast2400-gpio", "aspeed,ast2500-gpio",
+ or "aspeed,ast2600-gpio".
- #gpio-cells : Should be two
- First cell is the GPIO line number
@@ -17,7 +18,9 @@ Required properties:
Optional properties:
-- clocks : A phandle to the clock to use for debounce timings
+- clocks : A phandle to the clock to use for debounce timings
+- ngpios : Number of GPIOs controlled by this controller. Should be set
+ when there are multiple GPIO controllers on a SoC (ast2600).
The gpio and interrupt properties are further described in their respective
bindings documentation:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt
index bc6b4b62df83..cd91d61eac31 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt
@@ -6,6 +6,7 @@ Required Properties:
66AK2E SoCs
"ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G
"ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654
+ "ti,j721e-gpio", "ti,keystone-gpio": for J721E SoCs
- reg: Physical base address of the controller and the size of memory mapped
registers.
diff --git a/Documentation/devicetree/bindings/gpio/gpio-moxtet.txt b/Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
new file mode 100644
index 000000000000..410759de9f09
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
@@ -0,0 +1,18 @@
+Turris Mox Moxtet GPIO expander via Moxtet bus
+
+Required properties:
+ - compatible : Should be "cznic,moxtet-gpio".
+ - gpio-controller : Marks the device node as a GPIO controller.
+ - #gpio-cells : Should be two. For consumer use see gpio.txt.
+
+Other properties are required for a Moxtet bus device, please refer to
+Documentation/devicetree/bindings/bus/moxtet.txt.
+
+Example:
+
+ moxtet_sfp: gpio@0 {
+ compatible = "cznic,moxtet-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ }
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
index 69d46162d0f5..cd28e932bf50 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
@@ -4,7 +4,7 @@ Required properties:
- compatible : Should be "fsl,<soc>-gpio"
The following <soc>s are known to be supported:
mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq,
- ls1021a, ls1043a, ls2080a.
+ ls1021a, ls1043a, ls2080a, ls1028a, ls1088a.
- reg : Address and length of the register set for the device
- interrupts : Should be the port interrupt shared by all 32 pins.
- #gpio-cells : Should be two. The first cell is the pin number and
@@ -37,3 +37,17 @@ gpio0: gpio@2300000 {
interrupt-controller;
#interrupt-cells = <2>;
};
+
+
+Example of gpio-controller node for a ls1028a/ls1088a SoC:
+
+gpio1: gpio@2300000 {
+ compatible = "fsl,ls1028a-gpio", "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
+ reg = <0x0 0x2300000 0x0 0x10000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ little-endian;
+};
diff --git a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
new file mode 100644
index 000000000000..d4d83916c09d
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
@@ -0,0 +1,45 @@
+Aspeed SGPIO controller Device Tree Bindings
+--------------------------------------------
+
+This SGPIO controller is for ASPEED AST2500 SoC, it supports up to 80 full
+featured Serial GPIOs. Each of the Serial GPIO pins can be programmed to
+support the following options:
+- Support interrupt option for each input port and various interrupt
+ sensitivity option (level-high, level-low, edge-high, edge-low)
+- Support reset tolerance option for each output port
+- Directly connected to APB bus and its shift clock is from APB bus clock
+ divided by a programmable value.
+- Co-work with external signal-chained TTL components (74LV165/74LV595)
+
+Required properties:
+
+- compatible : Should be one of
+ "aspeed,ast2400-sgpio", "aspeed,ast2500-sgpio"
+- #gpio-cells : Should be 2, see gpio.txt
+- reg : Address and length of the register set for the device
+- gpio-controller : Marks the device node as a GPIO controller
+- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
+- interrupt-controller : Mark the GPIO controller as an interrupt-controller
+- ngpios : number of GPIO lines, see gpio.txt
+ (should be multiple of 8, up to 80 pins)
+- clocks : A phandle to the APB clock for SGPM clock division
+- bus-frequency : SGPM CLK frequency
+
+The sgpio and interrupt properties are further described in their respective
+bindings documentation:
+
+- Documentation/devicetree/bindings/gpio/gpio.txt
+- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+ Example:
+ sgpio: sgpio@1e780200 {
+ #gpio-cells = <2>;
+ compatible = "aspeed,ast2500-sgpio";
+ gpio-controller;
+ interrupts = <40>;
+ reg = <0x1e780200 0x0100>;
+ clocks = <&syscon ASPEED_CLK_APB>;
+ interrupt-controller;
+ ngpios = <8>;
+ bus-frequency = <12000000>;
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/as370.txt b/Documentation/devicetree/bindings/hwmon/as370.txt
new file mode 100644
index 000000000000..d102fe765124
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/as370.txt
@@ -0,0 +1,11 @@
+Bindings for Synaptics AS370 PVT sensors
+
+Required properties:
+- compatible : "syna,as370-hwmon"
+- reg : address and length of the register set.
+
+Example:
+ hwmon@ea0810 {
+ compatible = "syna,as370-hwmon";
+ reg = <0xea0810 0xc>;
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt b/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
index f68a0a68fc52..1036f65fb778 100644
--- a/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
+++ b/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
@@ -1,8 +1,10 @@
-Device-tree bindings for IBM Common Form Factor Power Supply Version 1
-----------------------------------------------------------------------
+Device-tree bindings for IBM Common Form Factor Power Supply Versions 1 and 2
+-----------------------------------------------------------------------------
Required properties:
- - compatible = "ibm,cffps1";
+ - compatible : Must be one of the following:
+ "ibm,cffps1"
+ "ibm,cffps2"
- reg = < I2C bus address >; : Address of the power supply on the
I2C bus.
diff --git a/Documentation/devicetree/bindings/hwmon/lm75.txt b/Documentation/devicetree/bindings/hwmon/lm75.txt
index 586b5ed70be7..273616702c51 100644
--- a/Documentation/devicetree/bindings/hwmon/lm75.txt
+++ b/Documentation/devicetree/bindings/hwmon/lm75.txt
@@ -15,6 +15,7 @@ Required properties:
"maxim,max31725",
"maxim,max31726",
"maxim,mcp980x",
+ "nxp,pct2075",
"st,stds75",
"st,stlm75",
"microchip,tcn75",
diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 001f2b7abad0..c779000515d6 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -26,6 +26,9 @@ properties:
- items:
- const: allwinner,sun50i-a64-i2c
- const: allwinner,sun6i-a31-i2c
+ - items:
+ - const: allwinner,sun50i-h6-i2c
+ - const: allwinner,sun6i-a31-i2c
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
index 7ba167e2e1ea..c602b6fe1c0c 100644
--- a/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/iio/accelerometers/adi,adxl345.yaml#
+$id: http://devicetree.org/schemas/iio/accel/adi,adxl345.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers
diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
index a7fafb9bf5c6..e7daffec88d3 100644
--- a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/iio/accelerometers/adi,adxl372.yaml#
+$id: http://devicetree.org/schemas/iio/accel/adi,adxl372.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
diff --git a/Documentation/devicetree/bindings/hwmon/ads1015.txt b/Documentation/devicetree/bindings/iio/adc/ads1015.txt
index 918a507d1159..918a507d1159 100644
--- a/Documentation/devicetree/bindings/hwmon/ads1015.txt
+++ b/Documentation/devicetree/bindings/iio/adc/ads1015.txt
diff --git a/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml b/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml
new file mode 100644
index 000000000000..d74962c0f5ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/allwinner,sun8i-a33-ths.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A33 Thermal Sensor Device Tree Bindings
+
+maintainers:
+ - Chen-Yu Tsai <wens@csie.org>
+ - Maxime Ripard <maxime.ripard@bootlin.com>
+
+properties:
+ "#io-channel-cells":
+ const: 0
+
+ "#thermal-sensor-cells":
+ const: 0
+
+ compatible:
+ const: allwinner,sun8i-a33-ths
+
+ reg:
+ maxItems: 1
+
+required:
+ - "#io-channel-cells"
+ - "#thermal-sensor-cells"
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ ths: ths@1c25000 {
+ compatible = "allwinner,sun8i-a33-ths";
+ reg = <0x01c25000 0x100>;
+ #thermal-sensor-cells = <0>;
+ #io-channel-cells = <0>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt b/Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
index 4e82fd575cec..c676b03c752e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
@@ -5,21 +5,19 @@ Required properties:
- compatible: should be "amazon,al-fic"
- reg: physical base address and size of the registers
- interrupt-controller: identifies the node as an interrupt controller
-- #interrupt-cells: must be 2.
- First cell defines the index of the interrupt within the controller.
- Second cell is used to specify the trigger type and must be one of the
- following:
- - bits[3:0] trigger type and level flags
- 1 = low-to-high edge triggered
- 4 = active high level-sensitive
-- interrupt-parent: specifies the parent interrupt controller.
+- #interrupt-cells : must be 2. Specifies the number of cells needed to encode
+ an interrupt source. Supported trigger types are low-to-high edge
+ triggered and active high level-sensitive.
- interrupts: describes which input line in the interrupt parent, this
fic's output is connected to. This field property depends on the parent's
binding
+Please refer to interrupts.txt in this directory for details of the common
+Interrupt Controllers bindings used by client devices.
+
Example:
-amazon_fic: interrupt-controller@0xfd8a8500 {
+amazon_fic: interrupt-controller@fd8a8500 {
compatible = "amazon,al-fic";
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
index 7d531d5fff29..684bb1cd75ec 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
@@ -16,6 +16,7 @@ Required properties:
"amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912)
"amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X)
"amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2)
+ "amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3)
- reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : Specifies the number of cells needed to encode an
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
index c34df35a25fc..1fe147daca4c 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -44,11 +44,13 @@ properties:
be at least 4.
The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
- interrupts. Other values are reserved for future use.
+ interrupts, 2 for interrupts in the Extended SPI range, 3 for the
+ Extended PPI range. Other values are reserved for future use.
The 2nd cell contains the interrupt number for the interrupt type.
SPI interrupts are in the range [0-987]. PPI interrupts are in the
- range [0-15].
+ range [0-15]. Extented SPI interrupts are in the range [0-1023].
+ Extended PPI interrupts are in the range [0-127].
The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
index bae10e261fa9..507c141ea760 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
@@ -2,7 +2,7 @@
# Copyright 2018 Linaro Ltd.
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/interrupt/intel-ixp4xx-interrupt.yaml#"
+$id: "http://devicetree.org/schemas/interrupt-controller/intel,ixp4xx-interrupt.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx XScale Networking Processors Interrupt Controller
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
index 0e312fea2a5d..84ced3f4179b 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
@@ -15,6 +15,7 @@ Required properties:
"mediatek,mt7629-sysirq", "mediatek,mt6577-sysirq": for MT7629
"mediatek,mt6795-sysirq", "mediatek,mt6577-sysirq": for MT6795
"mediatek,mt6797-sysirq", "mediatek,mt6577-sysirq": for MT6797
+ "mediatek,mt6779-sysirq", "mediatek,mt6577-sysirq": for MT6779
"mediatek,mt6765-sysirq", "mediatek,mt6577-sysirq": for MT6765
"mediatek,mt6755-sysirq", "mediatek,mt6577-sysirq": for MT6755
"mediatek,mt6592-sysirq", "mediatek,mt6577-sysirq": for MT6592
diff --git a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 09fc02b99845..a5c1db95b3ec 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -1,20 +1,30 @@
* ARC-HS Interrupt Distribution Unit
- This optional 2nd level interrupt controller can be used in SMP configurations for
- dynamic IRQ routing, load balancing of common/external IRQs towards core intc.
+ This optional 2nd level interrupt controller can be used in SMP configurations
+ for dynamic IRQ routing, load balancing of common/external IRQs towards core
+ intc.
Properties:
- compatible: "snps,archs-idu-intc"
- interrupt-controller: This is an interrupt controller.
-- #interrupt-cells: Must be <1>.
-
- Value of the cell specifies the "common" IRQ from peripheral to IDU. Number N
- of the particular interrupt line of IDU corresponds to the line N+24 of the
- core interrupt controller.
-
- intc accessed via the special ARC AUX register interface, hence "reg" property
- is not specified.
+- #interrupt-cells: Must be <1> or <2>.
+
+ Value of the first cell specifies the "common" IRQ from peripheral to IDU.
+ Number N of the particular interrupt line of IDU corresponds to the line N+24
+ of the core interrupt controller.
+
+ The (optional) second cell specifies any of the following flags:
+ - bits[3:0] trigger type and level flags
+ 1 = low-to-high edge triggered
+ 2 = NOT SUPPORTED (high-to-low edge triggered)
+ 4 = active high level-sensitive <<< DEFAULT
+ 8 = NOT SUPPORTED (active low level-sensitive)
+ When no second cell is specified, the interrupt is assumed to be level
+ sensitive.
+
+ The interrupt controller is accessed via the special ARC AUX register
+ interface, hence "reg" property is not specified.
Example:
core_intc: core-interrupt-controller {
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index 6922db598def..ce59a505f5a4 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -11,10 +11,23 @@ ARM Short-Descriptor translation table format for address translation.
|
m4u (Multimedia Memory Management Unit)
|
+ +--------+
+ | |
+ gals0-rx gals1-rx (Global Async Local Sync rx)
+ | |
+ | |
+ gals0-tx gals1-tx (Global Async Local Sync tx)
+ | | Some SoCs may have GALS.
+ +--------+
+ |
SMI Common(Smart Multimedia Interface Common)
|
+----------------+-------
| |
+ | gals-rx There may be GALS in some larbs.
+ | |
+ | |
+ | gals-tx
| |
SMI larb0 SMI larb1 ... SoCs have several SMI local arbiter(larb).
(display) (vdec)
@@ -36,6 +49,10 @@ each local arbiter.
like display, video decode, and camera. And there are different ports
in each larb. Take a example, There are many ports like MC, PP, VLD in the
video decode local arbiter, all these ports are according to the video HW.
+ In some SoCs, there may be a GALS(Global Async Local Sync) module between
+smi-common and m4u, and additional GALS module between smi-larb and
+smi-common. GALS can been seen as a "asynchronous fifo" which could help
+synchronize for the modules in different clock frequency.
Required properties:
- compatible : must be one of the following string:
@@ -44,18 +61,25 @@ Required properties:
"mediatek,mt7623-m4u", "mediatek,mt2701-m4u" for mt7623 which uses
generation one m4u HW.
"mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
+ "mediatek,mt8183-m4u" for mt8183 which uses generation two m4u HW.
- reg : m4u register base and size.
- interrupts : the interrupt of m4u.
- clocks : must contain one entry for each clock-names.
-- clock-names : must be "bclk", It is the block clock of m4u.
+- clock-names : Only 1 optional clock:
+ - "bclk": the block clock of m4u.
+ Here is the list which require this "bclk":
+ - mt2701, mt2712, mt7623 and mt8173.
+ Note that m4u use the EMI clock which always has been enabled before kernel
+ if there is no this "bclk".
- mediatek,larbs : List of phandle to the local arbiters in the current Socs.
Refer to bindings/memory-controllers/mediatek,smi-larb.txt. It must sort
according to the local arbiter index, like larb0, larb1, larb2...
- iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
Specifies the mtk_m4u_id as defined in
dt-binding/memory/mt2701-larb-port.h for mt2701, mt7623
- dt-binding/memory/mt2712-larb-port.h for mt2712, and
- dt-binding/memory/mt8173-larb-port.h for mt8173.
+ dt-binding/memory/mt2712-larb-port.h for mt2712,
+ dt-binding/memory/mt8173-larb-port.h for mt8173, and
+ dt-binding/memory/mt8183-larb-port.h for mt8183.
Example:
iommu: iommu@10205000 {
diff --git a/Documentation/devicetree/bindings/media/amlogic,vdec.txt b/Documentation/devicetree/bindings/media/amlogic,vdec.txt
index aabdd01bcf32..9b6aace86ca7 100644
--- a/Documentation/devicetree/bindings/media/amlogic,vdec.txt
+++ b/Documentation/devicetree/bindings/media/amlogic,vdec.txt
@@ -26,6 +26,7 @@ Required properties:
- GXBB (S905) : "amlogic,gxbb-vdec"
- GXL (S905X, S905D) : "amlogic,gxl-vdec"
- GXM (S912) : "amlogic,gxm-vdec"
+ followed by the common "amlogic,gx-vdec"
- reg: base address and size of he following memory-mapped regions :
- dos
- esparser
@@ -47,8 +48,8 @@ Required properties:
Example:
-vdec: video-decoder@c8820000 {
- compatible = "amlogic,gxbb-vdec";
+vdec: video-codec@c8820000 {
+ compatible = "amlogic,gxbb-vdec", "amlogic,gx-vdec";
reg = <0x0 0xc8820000 0x0 0x10000>,
<0x0 0xc110a580 0x0 0xe4>;
reg-names = "dos", "esparser";
diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,csi2.txt
index 331409259752..331409259752 100644
--- a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
+++ b/Documentation/devicetree/bindings/media/renesas,csi2.txt
diff --git a/Documentation/devicetree/bindings/media/rcar_imr.txt b/Documentation/devicetree/bindings/media/renesas,imr.txt
index b0614153ed36..b0614153ed36 100644
--- a/Documentation/devicetree/bindings/media/rcar_imr.txt
+++ b/Documentation/devicetree/bindings/media/renesas,imr.txt
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt
index aa217b096279..aa217b096279 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/renesas,vin.txt
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index e937ddd871a6..b478ade4da65 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,9 +2,10 @@ SMI (Smart Multimedia Interface) Common
The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
-Mediatek SMI have two generations of HW architecture, mt2712 and mt8173 use
-the second generation of SMI HW while mt2701 uses the first generation HW of
-SMI.
+Mediatek SMI have two generations of HW architecture, here is the list
+which generation the SoCs use:
+generation 1: mt2701 and mt7623.
+generation 2: mt2712, mt8173 and mt8183.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
@@ -19,6 +20,7 @@ Required properties:
"mediatek,mt2712-smi-common"
"mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common"
"mediatek,mt8173-smi-common"
+ "mediatek,mt8183-smi-common"
- reg : the register and size of the SMI block.
- power-domains : a phandle to the power domain of this local arbiter.
- clocks : Must contain an entry for each entry in clock-names.
@@ -30,6 +32,10 @@ Required properties:
They may be the same if both source clocks are the same.
- "async" : asynchronous clock, it help transform the smi clock into the emi
clock domain, this clock is only needed by generation 1 smi HW.
+ and these 2 option clocks for generation 2 smi HW:
+ - "gals0": the path0 clock of GALS(Global Async Local Sync).
+ - "gals1": the path1 clock of GALS(Global Async Local Sync).
+ Here is the list which has this GALS: mt8183.
Example:
smi_common: smi@14022000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 94eddcae77ab..4b369b3e1a69 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -8,6 +8,7 @@ Required properties:
"mediatek,mt2712-smi-larb"
"mediatek,mt7623-smi-larb", "mediatek,mt2701-smi-larb"
"mediatek,mt8173-smi-larb"
+ "mediatek,mt8183-smi-larb"
- reg : the register and size of this local arbiter.
- mediatek,smi : a phandle to the smi_common node.
- power-domains : a phandle to the power domain of this local arbiter.
@@ -16,6 +17,9 @@ Required properties:
- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
- "smi" : It's the clock for transfer data and command.
+ and this optional clock name:
+ - "gals": the clock for GALS(Global Async Local Sync).
+ Here is the list which has this GALS: mt8183.
Required property for mt2701, mt2712 and mt7623:
- mediatek,larb-id :the hardware id of this larb.
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt
index 9f78e6c82740..9f78e6c82740 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt
diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml
new file mode 100644
index 000000000000..4b1a09acb98b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/allwinner,sun4i-a10-ts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A10 Resistive Touchscreen Controller Device Tree Bindings
+
+maintainers:
+ - Chen-Yu Tsai <wens@csie.org>
+ - Maxime Ripard <maxime.ripard@bootlin.com>
+
+properties:
+ "#thermal-sensor-cells":
+ const: 0
+
+ compatible:
+ enum:
+ - allwinner,sun4i-a10-ts
+ - allwinner,sun5i-a13-ts
+ - allwinner,sun6i-a31-ts
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ allwinner,ts-attached:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: A touchscreen is attached to the controller
+
+ allwinner,tp-sensitive-adjust:
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32
+ - minimum: 0
+ maximum: 15
+ default: 15
+ description: Sensitivity of pen down detection
+
+ allwinner,filter-type:
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32
+ - minimum: 0
+ maximum: 3
+ default: 1
+ description: |
+ Select median and averaging filter. Sample used for median /
+ averaging filter:
+ 0: 4/2
+ 1: 5/3
+ 2: 8/4
+ 3: 16/8
+
+required:
+ - "#thermal-sensor-cells"
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ rtp: rtp@1c25000 {
+ compatible = "allwinner,sun4i-a10-ts";
+ reg = <0x01c25000 0x100>;
+ interrupts = <29>;
+ allwinner,ts-attached;
+ #thermal-sensor-cells = <0>;
+ /* sensitive/noisy touch panel */
+ allwinner,tp-sensitive-adjust = <0>;
+ allwinner,filter-type = <3>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt
deleted file mode 100644
index 86dd8191b04c..000000000000
--- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-Allwinner SoCs' GPADC Device Tree bindings
-------------------------------------------
-The Allwinner SoCs all have an ADC that can also act as a thermal sensor
-and sometimes as a touchscreen controller.
-
-Required properties:
- - compatible: "allwinner,sun8i-a33-ths",
- - reg: mmio address range of the chip,
- - #thermal-sensor-cells: shall be 0,
- - #io-channel-cells: shall be 0,
-
-Example:
- ths: ths@1c25000 {
- compatible = "allwinner,sun8i-a33-ths";
- reg = <0x01c25000 0x100>;
- #thermal-sensor-cells = <0>;
- #io-channel-cells = <0>;
- };
-
-sun4i, sun5i and sun6i SoCs are also supported via the older binding:
-
-sun4i resistive touchscreen controller
---------------------------------------
-
-Required properties:
- - compatible: "allwinner,sun4i-a10-ts", "allwinner,sun5i-a13-ts" or
- "allwinner,sun6i-a31-ts"
- - reg: mmio address range of the chip
- - interrupts: interrupt to which the chip is connected
- - #thermal-sensor-cells: shall be 0
-
-Optional properties:
- - allwinner,ts-attached : boolean indicating that an actual touchscreen
- is attached to the controller
- - allwinner,tp-sensitive-adjust : integer (4 bits)
- adjust sensitivity of pen down detection
- between 0 (least sensitive) and 15
- (defaults to 15)
- - allwinner,filter-type : integer (2 bits)
- select median and averaging filter
- samples used for median / averaging filter
- 0: 4/2
- 1: 5/3
- 2: 8/4
- 3: 16/8
- (defaults to 1)
-
-Example:
-
- rtp: rtp@1c25000 {
- compatible = "allwinner,sun4i-a10-ts";
- reg = <0x01c25000 0x100>;
- interrupts = <29>;
- allwinner,ts-attached;
- #thermal-sensor-cells = <0>;
- /* sensitive/noisy touch panel */
- allwinner,tp-sensitive-adjust = <0>;
- allwinner,filter-type = <3>;
- };
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
index d2313b1d9405..0ea21a6f70b4 100644
--- a/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml
+++ b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
@@ -2,7 +2,7 @@
# Copyright 2019 Linaro Ltd.
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/misc/intel-ixp4xx-ahb-queue-manager.yaml#"
+$id: "http://devicetree.org/schemas/misc/intel,ixp4xx-ahb-queue-manager.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx AHB Queue Manager
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
index d4084c149768..3fb0714e761e 100644
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/net/allwinner,sun8i-a83t-gmac.yaml#
+$id: http://devicetree.org/schemas/net/allwinner,sun8i-a83t-emac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A83t EMAC Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt
index b463e1268ac4..19e4a7d91511 100644
--- a/Documentation/devicetree/bindings/net/can/rcar_can.txt
+++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt
@@ -5,6 +5,7 @@ Required properties:
- compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
"renesas,can-r8a7744" if CAN controller is a part of R8A7744 SoC.
"renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC.
+ "renesas,can-r8a77470" if CAN controller is a part of R8A77470 SoC.
"renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC.
"renesas,can-r8a774c0" if CAN controller is a part of R8A774C0 SoC.
"renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
@@ -17,6 +18,8 @@ Required properties:
"renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
"renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
"renesas,can-r8a77965" if CAN controller is a part of R8A77965 SoC.
+ "renesas,can-r8a77990" if CAN controller is a part of R8A77990 SoC.
+ "renesas,can-r8a77995" if CAN controller is a part of R8A77995 SoC.
"renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1
compatible device.
@@ -33,7 +36,8 @@ Required properties:
- pinctrl-0: pin control group to be used for this controller.
- pinctrl-names: must be "default".
-Required properties for R8A7795, R8A7796 and R8A77965:
+Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965,
+R8A77990, and R8A77995:
For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can
be used by both CAN and CAN FD controller at the same time. It needs to be
scaled to maximum frequency if any of these controllers use it. This is done
diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
index 32f051f6d338..a901cd9be29e 100644
--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
+++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
@@ -4,6 +4,7 @@ Renesas R-Car CAN FD controller Device Tree Bindings
Required properties:
- compatible: Must contain one or more of the following:
- "renesas,rcar-gen3-canfd" for R-Car Gen3 and RZ/G2 compatible controllers.
+ - "renesas,r8a774a1-canfd" for R8A774A1 (RZ/G2M) compatible controller.
- "renesas,r8a774c0-canfd" for R8A774C0 (RZ/G2E) compatible controller.
- "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller.
- "renesas,r8a7796-canfd" for R8A7796 (R-Car M3-W) compatible controller.
@@ -11,6 +12,7 @@ Required properties:
- "renesas,r8a77970-canfd" for R8A77970 (R-Car V3M) compatible controller.
- "renesas,r8a77980-canfd" for R8A77980 (R-Car V3H) compatible controller.
- "renesas,r8a77990-canfd" for R8A77990 (R-Car E3) compatible controller.
+ - "renesas,r8a77995-canfd" for R8A77995 (R-Car D3) compatible controller.
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first, followed by the
@@ -29,13 +31,12 @@ The name of the child nodes are "channel0" and "channel1" respectively. Each
child node supports the "status" property only, which is used to
enable/disable the respective channel.
-Required properties for "renesas,r8a774c0-canfd", "renesas,r8a7795-canfd",
-"renesas,r8a7796-canfd", "renesas,r8a77965-canfd", and "renesas,r8a77990-canfd"
-compatible:
-In R8A774C0, R8A7795, R8A7796, R8A77965, and R8A77990 SoCs, canfd clock is a
-div6 clock and can be used by both CAN and CAN FD controller at the same time.
-It needs to be scaled to maximum frequency if any of these controllers use it.
-This is done using the below properties:
+Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965,
+R8A77990, and R8A77995:
+In the denoted SoCs, canfd clock is a div6 clock and can be used by both CAN
+and CAN FD controller at the same time. It needs to be scaled to maximum
+frequency if any of these controllers use it. This is done using the below
+properties:
- assigned-clocks: phandle of canfd clock.
- assigned-clock-rates: maximum frequency of this clock.
diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 4ac21cef370e..113e7ac79aad 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -12,6 +12,7 @@ Required properties:
- "microchip,ksz8565"
- "microchip,ksz9893"
- "microchip,ksz9563"
+ - "microchip,ksz8563"
Optional properties:
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 2d41fb96ce0a..5b88fae0307d 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -7,18 +7,6 @@ Required properties:
- phy-mode : See ethernet.txt file in the same directory
Optional properties:
-- phy-reset-gpios : Should specify the gpio for phy reset
-- phy-reset-duration : Reset duration in milliseconds. Should present
- only if property "phy-reset-gpios" is available. Missing the property
- will have the duration be 1 millisecond. Numbers greater than 1000 are
- invalid and 1 millisecond will be used instead.
-- phy-reset-active-high : If present then the reset sequence using the GPIO
- specified in the "phy-reset-gpios" property is reversed (H=reset state,
- L=operation state).
-- phy-reset-post-delay : Post reset delay in milliseconds. If present then
- a delay of phy-reset-post-delay milliseconds will be observed after the
- phy-reset-gpios has been toggled. Can be omitted thus no delay is
- observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
- phy-supply : regulator that powers the Ethernet PHY.
- phy-handle : phandle to the PHY device connected to this device.
- fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
@@ -47,11 +35,27 @@ Optional properties:
For imx6sx, "int0" handles all 3 queues and ENET_MII. "pps" is for the pulse
per second interrupt associated with 1588 precision time protocol(PTP).
-
Optional subnodes:
- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
according to phy.txt in the same directory
+Deprecated optional properties:
+ To avoid these, create a phy node according to phy.txt in the same
+ directory, and point the fec's "phy-handle" property to it. Then use
+ the phy's reset binding, again described by phy.txt.
+- phy-reset-gpios : Should specify the gpio for phy reset
+- phy-reset-duration : Reset duration in milliseconds. Should present
+ only if property "phy-reset-gpios" is available. Missing the property
+ will have the duration be 1 millisecond. Numbers greater than 1000 are
+ invalid and 1 millisecond will be used instead.
+- phy-reset-active-high : If present then the reset sequence using the GPIO
+ specified in the "phy-reset-gpios" property is reversed (H=reset state,
+ L=operation state).
+- phy-reset-post-delay : Post reset delay in milliseconds. If present then
+ a delay of phy-reset-post-delay milliseconds will be observed after the
+ phy-reset-gpios has been toggled. Can be omitted thus no delay is
+ observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
+
Example:
ethernet@83fec000 {
diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt
index 63c73fafe26d..0b61a90f1592 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -15,10 +15,10 @@ Required properties:
Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs.
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
- Use "sifive,fu540-macb" for SiFive FU540-C000 SoC.
+ Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
- For "sifive,fu540-macb", second range is required to specify the
+ For "sifive,fu540-c000-gem", second range is required to specify the
address and length of the registers for GEMGXL Management block.
- interrupts: Should contain macb interrupt
- phy-mode: See ethernet.txt file in the same directory.
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
index c9efd6e2c134..1084e9d2917d 100644
--- a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
@@ -37,13 +37,13 @@ required:
examples:
- |
- sid@1c23800 {
+ efuse@1c23800 {
compatible = "allwinner,sun4i-a10-sid";
reg = <0x01c23800 0x10>;
};
- |
- sid@1c23800 {
+ efuse@1c23800 {
compatible = "allwinner,sun7i-a20-sid";
reg = <0x01c23800 0x200>;
};
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml b/Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml
new file mode 100644
index 000000000000..b7c00ed31085
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem-consumer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM (Non Volatile Memory) Consumer Device Tree Bindings
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+select: true
+
+properties:
+ nvmem:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ List of phandle to the nvmem providers.
+
+ nvmem-cells:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ List of phandle to the nvmem data cells.
+
+ nvmem-names:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description:
+ Names for the each nvmem provider.
+
+ nvmem-cell-names:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description:
+ Names for each nvmem-cells specified.
+
+dependencies:
+ nvmem-names: [ nvmem ]
+ nvmem-cell-names: [ nvmem-cells ]
+
+examples:
+ - |
+ tsens {
+ /* ... */
+ nvmem-cells = <&tsens_calibration>;
+ nvmem-cell-names = "calibration";
+ };
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
index fd06c09b822b..46a7ef485e24 100644
--- a/Documentation/devicetree/bindings/nvmem/nvmem.txt
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
@@ -1,80 +1 @@
-= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
-
-This binding is intended to represent the location of hardware
-configuration data stored in NVMEMs like eeprom, efuses and so on.
-
-On a significant proportion of boards, the manufacturer has stored
-some data on NVMEM, for the OS to be able to retrieve these information
-and act upon it. Obviously, the OS has to know about where to retrieve
-these data from, and where they are stored on the storage device.
-
-This document is here to document this.
-
-= Data providers =
-Contains bindings specific to provider drivers and data cells as children
-of this node.
-
-Optional properties:
- read-only: Mark the provider as read only.
-
-= Data cells =
-These are the child nodes of the provider which contain data cell
-information like offset and size in nvmem provider.
-
-Required properties:
-reg: specifies the offset in byte within the storage device.
-
-Optional properties:
-
-bits: Is pair of bit location and number of bits, which specifies offset
- in bit and number of bits within the address range specified by reg property.
- Offset takes values from 0-7.
-
-For example:
-
- /* Provider */
- qfprom: qfprom@700000 {
- ...
-
- /* Data cells */
- tsens_calibration: calib@404 {
- reg = <0x404 0x10>;
- };
-
- tsens_calibration_bckp: calib_bckp@504 {
- reg = <0x504 0x11>;
- bits = <6 128>
- };
-
- pvs_version: pvs-version@6 {
- reg = <0x6 0x2>
- bits = <7 2>
- };
-
- speed_bin: speed-bin@c{
- reg = <0xc 0x1>;
- bits = <2 3>;
-
- };
- ...
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells/providers.
-
-Required-properties:
-nvmem-cells: list of phandle to the nvmem data cells.
-nvmem-cell-names: names for the each nvmem-cells specified. Required if
- nvmem-cells is used.
-
-Optional-properties:
-nvmem : list of phandles to nvmem providers.
-nvmem-names: names for the each nvmem provider. required if nvmem is used.
-
-For example:
-
- tsens {
- ...
- nvmem-cells = <&tsens_calibration>;
- nvmem-cell-names = "calibration";
- };
+This file has been moved to nvmem.yaml and nvmem-consumer.yaml.
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
new file mode 100644
index 000000000000..1c75a059206c
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM (Non Volatile Memory) Device Tree Bindings
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description: |
+ This binding is intended to represent the location of hardware
+ configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+ On a significant proportion of boards, the manufacturer has stored
+ some data on NVMEM, for the OS to be able to retrieve these
+ information and act upon it. Obviously, the OS has to know about
+ where to retrieve these data from, and where they are stored on the
+ storage device.
+
+properties:
+ $nodename:
+ pattern: "^(eeprom|efuse|nvram)(@.*|-[0-9a-f])*$"
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ read-only:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Mark the provider as read only.
+
+patternProperties:
+ "^.*@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ maxItems: 1
+ description:
+ Offset and size in bytes within the storage device.
+
+ bits:
+ maxItems: 1
+ items:
+ items:
+ - minimum: 0
+ maximum: 7
+ description:
+ Offset in bit within the address range specified by reg.
+ - minimum: 1
+ description:
+ Size in bit within the address range specified by reg.
+
+ required:
+ - reg
+
+ additionalProperties: false
+
+examples:
+ - |
+ qfprom: eeprom@700000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* ... */
+
+ /* Data cells */
+ tsens_calibration: calib@404 {
+ reg = <0x404 0x10>;
+ };
+
+ tsens_calibration_bckp: calib_bckp@504 {
+ reg = <0x504 0x11>;
+ bits = <6 128>;
+ };
+
+ pvs_version: pvs-version@6 {
+ reg = <0x6 0x2>;
+ bits = <7 2>;
+ };
+
+ speed_bin: speed-bin@c{
+ reg = <0xc 0x1>;
+ bits = <2 3>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
index 250f9d5aabdf..fa46670de299 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/display/allwinner,sun6i-a31-mipi-dphy.yaml#
+$id: http://devicetree.org/schemas/phy/allwinner,sun6i-a31-mipi-dphy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A31 MIPI D-PHY Controller Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index 91d3e78b3395..400df2da018a 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -37,7 +37,8 @@ properties:
hwlocks: true
st,syscfg:
- $ref: "/schemas/types.yaml#/definitions/phandle-array"
+ allOf:
+ - $ref: "/schemas/types.yaml#/definitions/phandle-array"
description: Should be phandle/offset/mask
items:
- description: Phandle to the syscon node which includes IRQ mux selection.
diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
new file mode 100644
index 000000000000..aab70e8b681e
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 BayLibre, SAS
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/power/amlogic,meson-ee-pwrc.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic Meson Everything-Else Power Domains
+
+maintainers:
+ - Neil Armstrong <narmstrong@baylibre.com>
+
+description: |+
+ The Everything-Else Power Domains node should be the child of a syscon
+ node with the required property:
+
+ - compatible: Should be the following:
+ "amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon"
+
+ Refer to the the bindings described in
+ Documentation/devicetree/bindings/mfd/syscon.txt
+
+properties:
+ compatible:
+ enum:
+ - amlogic,meson-g12a-pwrc
+ - amlogic,meson-sm1-pwrc
+
+ clocks:
+ minItems: 2
+
+ clock-names:
+ items:
+ - const: vpu
+ - const: vapb
+
+ resets:
+ minItems: 11
+
+ reset-names:
+ items:
+ - const: viu
+ - const: venc
+ - const: vcbus
+ - const: bt656
+ - const: rdma
+ - const: venci
+ - const: vencp
+ - const: vdac
+ - const: vdi6
+ - const: vencl
+ - const: vid_lock
+
+ "#power-domain-cells":
+ const: 1
+
+ amlogic,ao-sysctrl:
+ description: phandle to the AO sysctrl node
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/phandle
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - "#power-domain-cells"
+ - amlogic,ao-sysctrl
+
+examples:
+ - |
+ pwrc: power-controller {
+ compatible = "amlogic,meson-sm1-pwrc";
+ #power-domain-cells = <1>;
+ amlogic,ao-sysctrl = <&rti>;
+ resets = <&reset_viu>,
+ <&reset_venc>,
+ <&reset_vcbus>,
+ <&reset_bt656>,
+ <&reset_rdma>,
+ <&reset_venci>,
+ <&reset_vencp>,
+ <&reset_vdac>,
+ <&reset_vdi6>,
+ <&reset_vencl>,
+ <&reset_vid_lock>;
+ reset-names = "viu", "venc", "vcbus", "bt656",
+ "rdma", "venci", "vencp", "vdac",
+ "vdi6", "vencl", "vid_lock";
+ clocks = <&clk_vpu>, <&clk_vapb>;
+ clock-names = "vpu", "vapb";
+ };
diff --git a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
index 3ae9f1088845..b9f58e480349 100644
--- a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
@@ -34,6 +34,9 @@ Optional input supply properties:
- inl67-supply: The input supply for LDO_REG3 and LDO_REG4
Any standard regulator properties can be used to configure the single regulator.
+regulator-initial-mode, regulator-allowed-modes and regulator-mode could be specified
+for act8865 using mode values from dt-bindings/regulator/active-semi,8865-regulator.h
+file.
The valid names for regulators are:
- for act8846:
@@ -47,6 +50,8 @@ The valid names for regulators are:
Example:
--------
+#include <dt-bindings/regulator/active-semi,8865-regulator.h>
+
i2c1: i2c@f0018000 {
pmic: act8865@5b {
compatible = "active-semi,act8865";
@@ -65,9 +70,19 @@ Example:
regulator-name = "VCC_1V2";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
- regulator-suspend-mem-microvolt = <1150000>;
- regulator-suspend-standby-microvolt = <1150000>;
regulator-always-on;
+
+ regulator-allowed-modes = <ACT8865_REGULATOR_MODE_FIXED>,
+ <ACT8865_REGULATOR_MODE_LOWPOWER>;
+ regulator-initial-mode = <ACT8865_REGULATOR_MODE_FIXED>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-min-microvolt = <1150000>;
+ regulator-suspend-max-microvolt = <1150000>;
+ regulator-changeable-in-suspend;
+ regulator-mode = <ACT8865_REGULATOR_MODE_LOWPOWER>;
+ };
};
vcc_3v3_reg: DCDC_REG3 {
@@ -82,6 +97,14 @@ Example:
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
+
+ regulator-allowed-modes = <ACT8865_REGULATOR_MODE_NORMAL>,
+ <ACT8865_REGULATOR_MODE_LOWPOWER>;
+ regulator-initial-mode = <ACT8865_REGULATOR_MODE_NORMAL>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
};
vddfuse_reg: LDO_REG2 {
diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
index a650b457085d..a78150c47aa2 100644
--- a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
@@ -19,9 +19,19 @@ description:
allOf:
- $ref: "regulator.yaml#"
+if:
+ properties:
+ compatible:
+ contains:
+ const: regulator-fixed-clock
+ required:
+ - clocks
+
properties:
compatible:
- const: regulator-fixed
+ enum:
+ - const: regulator-fixed
+ - const: regulator-fixed-clock
regulator-name: true
@@ -29,6 +39,13 @@ properties:
description: gpio to use for enable control
maxItems: 1
+ clocks:
+ description:
+ clock to use for enable control. This binding is only available if
+ the compatible is chosen to regulator-fixed-clock. The clock binding
+ is mandatory if compatible is chosen to regulator-fixed-clock.
+ maxItems: 1
+
startup-delay-us:
description: startup time in microseconds
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
new file mode 100644
index 000000000000..9a90a92f2d7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
@@ -0,0 +1,358 @@
+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_bt, ldo_vcn33_wifi, 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_bt_reg: ldo_vcn33_bt {
+ regulator-name = "vcn33_bt";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3500000>;
+ regulator-enable-ramp-delay = <270>;
+ };
+
+ mt6358_vcn33_wifi_reg: ldo_vcn33_wifi {
+ regulator-name = "vcn33_wifi";
+ 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/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
index 14d2eee96b3d..bab9f71140b8 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
@@ -22,9 +22,12 @@ RPMh resource.
The names used for regulator nodes must match those supported by a given PMIC.
Supported regulator node names:
+ PM8005: smps1 - smps4
+ PM8009: smps1 - smps2, ldo1 - ldo7
+ PM8150: smps1 - smps10, ldo1 - ldo18
+ PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb
PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
PMI8998: bob
- PM8005: smps1 - smps4
========================
First Level Nodes - PMIC
@@ -33,9 +36,13 @@ First Level Nodes - PMIC
- compatible
Usage: required
Value type: <string>
- Definition: Must be one of: "qcom,pm8998-rpmh-regulators",
- "qcom,pmi8998-rpmh-regulators" or
- "qcom,pm8005-rpmh-regulators".
+ Definition: Must be one of below:
+ "qcom,pm8005-rpmh-regulators"
+ "qcom,pm8009-rpmh-regulators"
+ "qcom,pm8150-rpmh-regulators"
+ "qcom,pm8150l-rpmh-regulators"
+ "qcom,pm8998-rpmh-regulators"
+ "qcom,pmi8998-rpmh-regulators"
- qcom,pmic-id
Usage: required
diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt
new file mode 100644
index 000000000000..c5e95850c427
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sy8824x.txt
@@ -0,0 +1,24 @@
+SY8824C/SY8824E/SY20276 Voltage regulator
+
+Required properties:
+- compatible: Must be one of the following.
+ "silergy,sy8824c"
+ "silergy,sy8824e"
+ "silergy,sy20276"
+ "silergy,sy20278"
+- reg: I2C slave address
+
+Any property defined as part of the core regulator binding, defined in
+./regulator.txt, can also be used.
+
+Example:
+
+ vcore: regulator@00 {
+ compatible = "silergy,sy8824c";
+ reg = <0x66>;
+ regulator-name = "vcore";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt
index 74a91c4f8530..549f80436deb 100644
--- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt
@@ -71,3 +71,10 @@ Example:
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3000000>;
};
+
+For twl6030 regulators/LDOs:
+
+ - ti,retain-on-reset: Does not turn off the supplies during warm
+ reset. Could be needed for VMMC, as TWL6030
+ reset sequence for this signal does not comply
+ with the SD specification.
diff --git a/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt b/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt
index c9919f4b92d2..94fd38b0d163 100644
--- a/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt
@@ -13,6 +13,7 @@ this layer. These clocks and resets should be described in each property.
Required properties:
- compatible: Should be
"socionext,uniphier-pro4-usb3-regulator" - for Pro4 SoC
+ "socionext,uniphier-pro5-usb3-regulator" - for Pro5 SoC
"socionext,uniphier-pxs2-usb3-regulator" - for PXs2 SoC
"socionext,uniphier-ld20-usb3-regulator" - for LD20 SoC
"socionext,uniphier-pxs3-usb3-regulator" - for PXs3 SoC
@@ -20,12 +21,12 @@ Required properties:
- clocks: A list of phandles to the clock gate for USB3 glue layer.
According to the clock-names, appropriate clocks are required.
- clock-names: Should contain
- "gio", "link" - for Pro4 SoC
+ "gio", "link" - for Pro4 and Pro5 SoCs
"link" - for others
- resets: A list of phandles to the reset control for USB3 glue layer.
According to the reset-names, appropriate resets are required.
- reset-names: Should contain
- "gio", "link" - for Pro4 SoC
+ "gio", "link" - for Pro4 and Pro5 SoCs
"link" - for others
See Documentation/devicetree/bindings/regulator/regulator.txt
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
index 13e095182db4..c2489e41a801 100644
--- a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
+++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
@@ -8,6 +8,7 @@ Required properties:
- compatible:
- For i.MX7 SoCs should be "fsl,imx7d-src", "syscon"
- For i.MX8MQ SoCs should be "fsl,imx8mq-src", "syscon"
+ - For i.MX8MM SoCs should be "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon"
- reg: should be register base and length as documented in the
datasheet
- interrupts: Should contain SRC interrupt
@@ -46,5 +47,6 @@ Example:
For list of all valid reset indices see
-<dt-bindings/reset/imx7-reset.h> for i.MX7 and
-<dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ
+<dt-bindings/reset/imx7-reset.h> for i.MX7,
+<dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ and
+<dt-bindings/reset/imx8mq-reset.h> for i.MX8MM
diff --git a/Documentation/devicetree/bindings/reset/snps,dw-reset.txt b/Documentation/devicetree/bindings/reset/snps,dw-reset.txt
new file mode 100644
index 000000000000..f94f911dd98d
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/snps,dw-reset.txt
@@ -0,0 +1,30 @@
+Synopsys DesignWare Reset controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+
+- compatible: should be one of the following.
+ "snps,dw-high-reset" - for active high configuration
+ "snps,dw-low-reset" - for active low configuration
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #reset-cells: must be 1.
+
+example:
+
+ dw_rst_1: reset-controller@0000 {
+ compatible = "snps,dw-high-reset";
+ reg = <0x0000 0x4>;
+ #reset-cells = <1>;
+ };
+
+ dw_rst_2: reset-controller@1000 {i
+ compatible = "snps,dw-low-reset";
+ reg = <0x1000 0x8>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt
deleted file mode 100644
index adf7b7af5dc3..000000000000
--- a/Documentation/devicetree/bindings/riscv/cpus.txt
+++ /dev/null
@@ -1,162 +0,0 @@
-===================
-RISC-V CPU Bindings
-===================
-
-The device tree allows to describe the layout of CPUs in a system through
-the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
-defining properties for every cpu.
-
-Bindings for CPU nodes follow the Devicetree Specification, available from:
-
-https://www.devicetree.org/specifications/
-
-with updates for 32-bit and 64-bit RISC-V systems provided in this document.
-
-===========
-Terminology
-===========
-
-This document uses some terminology common to the RISC-V community that is not
-widely used, the definitions of which are listed here:
-
-* hart: A hardware execution context, which contains all the state mandated by
- the RISC-V ISA: a PC and some registers. This terminology is designed to
- disambiguate software's view of execution contexts from any particular
- microarchitectural implementation strategy. For example, my Intel laptop is
- described as having one socket with two cores, each of which has two hyper
- threads. Therefore this system has four harts.
-
-=====================================
-cpus and cpu node bindings definition
-=====================================
-
-The RISC-V architecture, in accordance with the Devicetree Specification,
-requires the cpus and cpu nodes to be present and contain the properties
-described below.
-
-- cpus node
-
- Description: Container of cpu nodes
-
- The node name must be "cpus".
-
- A cpus node must define the following properties:
-
- - #address-cells
- Usage: required
- Value type: <u32>
- Definition: must be set to 1
- - #size-cells
- Usage: required
- Value type: <u32>
- Definition: must be set to 0
-
-- cpu node
-
- Description: Describes a hart context
-
- PROPERTIES
-
- - device_type
- Usage: required
- Value type: <string>
- Definition: must be "cpu"
- - reg
- Usage: required
- Value type: <u32>
- Definition: The hart ID of this CPU node
- - compatible:
- Usage: required
- Value type: <stringlist>
- Definition: must contain "riscv", may contain one of
- "sifive,rocket0"
- - mmu-type:
- Usage: optional
- Value type: <string>
- Definition: Specifies the CPU's MMU type. Possible values are
- "riscv,sv32"
- "riscv,sv39"
- "riscv,sv48"
- - riscv,isa:
- Usage: required
- Value type: <string>
- Definition: Contains the RISC-V ISA string of this hart. These
- ISA strings are defined by the RISC-V ISA manual.
-
-Example: SiFive Freedom U540G Development Kit
----------------------------------------------
-
-This system contains two harts: a hart marked as disabled that's used for
-low-level system tasks and should be ignored by Linux, and a second hart that
-Linux is allowed to run on.
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
- timebase-frequency = <1000000>;
- cpu@0 {
- clock-frequency = <1600000000>;
- compatible = "sifive,rocket0", "riscv";
- device_type = "cpu";
- i-cache-block-size = <64>;
- i-cache-sets = <128>;
- i-cache-size = <16384>;
- next-level-cache = <&L15 &L0>;
- reg = <0>;
- riscv,isa = "rv64imac";
- status = "disabled";
- L10: interrupt-controller {
- #interrupt-cells = <1>;
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- };
- };
- cpu@1 {
- clock-frequency = <1600000000>;
- compatible = "sifive,rocket0", "riscv";
- d-cache-block-size = <64>;
- d-cache-sets = <64>;
- d-cache-size = <32768>;
- d-tlb-sets = <1>;
- d-tlb-size = <32>;
- device_type = "cpu";
- i-cache-block-size = <64>;
- i-cache-sets = <64>;
- i-cache-size = <32768>;
- i-tlb-sets = <1>;
- i-tlb-size = <32>;
- mmu-type = "riscv,sv39";
- next-level-cache = <&L15 &L0>;
- reg = <1>;
- riscv,isa = "rv64imafdc";
- status = "okay";
- tlb-split;
- L13: interrupt-controller {
- #interrupt-cells = <1>;
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- };
- };
- };
-
-Example: Spike ISA Simulator with 1 Hart
-----------------------------------------
-
-This device tree matches the Spike ISA golden model as run with `spike -p1`.
-
- cpus {
- cpu@0 {
- device_type = "cpu";
- reg = <0x00000000>;
- status = "okay";
- compatible = "riscv";
- riscv,isa = "rv64imafdc";
- mmu-type = "riscv,sv48";
- clock-frequency = <0x3b9aca00>;
- interrupt-controller {
- #interrupt-cells = <0x00000001>;
- interrupt-controller;
- compatible = "riscv,cpu-intc";
- }
- }
- }
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index c899111aa5e3..b261a3015f84 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -10,6 +10,18 @@ maintainers:
- Paul Walmsley <paul.walmsley@sifive.com>
- Palmer Dabbelt <palmer@sifive.com>
+description: |
+ This document uses some terminology common to the RISC-V community
+ that is not widely used, the definitions of which are listed here:
+
+ hart: A hardware execution context, which contains all the state
+ mandated by the RISC-V ISA: a PC and some registers. This
+ terminology is designed to disambiguate software's view of execution
+ contexts from any particular microarchitectural implementation
+ strategy. For example, an Intel laptop containing one socket with
+ two cores, each of which has two hyperthreads, could be described as
+ having four harts.
+
properties:
compatible:
items:
@@ -50,6 +62,10 @@ properties:
User-Level ISA document, available from
https://riscv.org/specifications/
+ While the isa strings in ISA specification are case
+ insensitive, letters in the riscv,isa string must be all
+ lowercase to simplify parsing.
+
timebase-frequency:
type: integer
minimum: 1
diff --git a/Documentation/devicetree/bindings/riscv/sifive.yaml b/Documentation/devicetree/bindings/riscv/sifive.yaml
index 9d17dc2f3f84..3ab532713dc1 100644
--- a/Documentation/devicetree/bindings/riscv/sifive.yaml
+++ b/Documentation/devicetree/bindings/riscv/sifive.yaml
@@ -19,7 +19,7 @@ properties:
compatible:
items:
- enum:
- - sifive,freedom-unleashed-a00
+ - sifive,hifive-unleashed-a00
- const: sifive,fu540-c000
- const: sifive,fu540
...
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index 21483ba820bc..3495eee81d53 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -13,7 +13,10 @@ Required properties:
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
-- clock-names : should contain: "ipg" - the uart clock
+- clock-names : For vf610/ls1021a/imx7ulp, "ipg" clock is for uart bus/baud
+ clock. For imx8qxp lpuart, "ipg" clock is bus clock that is used to access
+ lpuart controller registers, it also requires "baud" clock for module to
+ receive/transmit data.
Optional properties:
- dmas: A list of two dma specifiers, one for each entry in dma-names.
diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 6fdffb735fb9..3a3b57079f0d 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -9,6 +9,7 @@ Required properties:
* "mediatek,mt6589-uart" for MT6589 compatible UARTS
* "mediatek,mt6755-uart" for MT6755 compatible UARTS
* "mediatek,mt6765-uart" for MT6765 compatible UARTS
+ * "mediatek,mt6779-uart" for MT6779 compatible UARTS
* "mediatek,mt6795-uart" for MT6795 compatible UARTS
* "mediatek,mt6797-uart" for MT6797 compatible UARTS
* "mediatek,mt7622-uart" for MT7622 compatible UARTS
diff --git a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
index 6bf6b43f8dd8..3dd563cec794 100644
--- a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
+++ b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
@@ -11,6 +11,7 @@ Required properties:
"amlogic,meson8b-clk-measure" for Meson8b SoCs
"amlogic,meson-axg-clk-measure" for AXG SoCs
"amlogic,meson-g12a-clk-measure" for G12a SoCs
+ "amlogic,meson-sm1-clk-measure" for SM1 SoCs
- reg: base address and size of the Clock Measurer register space.
Example:
diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt
index d7afaff5faff..05ec2a838c54 100644
--- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt
@@ -18,7 +18,8 @@ Required properties:
- reg : offset and length of the device registers.
- bus-frequency : the clock frequency for QUICC Engine.
- fsl,qe-num-riscs: define how many RISC engines the QE has.
-- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
+- fsl,qe-snums: This property has to be specified as '/bits/ 8' value,
+ defining the array of serial number (SNUM) values for the virtual
threads.
Optional properties:
@@ -34,6 +35,11 @@ Recommended properties
- brg-frequency : the internal clock source frequency for baud-rate
generators in Hz.
+Deprecated properties
+- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use
+ for the threads. Use fsl,qe-snums instead to not only specify the
+ number of snums, but also their values.
+
Example:
qe@e0100000 {
#address-cells = <1>;
@@ -44,6 +50,11 @@ Example:
reg = <e0100000 480>;
brg-frequency = <0>;
bus-frequency = <179A7B00>;
+ fsl,qe-snums = /bits/ 8 <
+ 0x04 0x05 0x0C 0x0D 0x14 0x15 0x1C 0x1D
+ 0x24 0x25 0x2C 0x2D 0x34 0x35 0x88 0x89
+ 0x98 0x99 0xA8 0xA9 0xB8 0xB9 0xC8 0xC9
+ 0xD8 0xD9 0xE8 0xE9>;
}
* Multi-User RAM (MURAM)
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt
index 954ffee0a9c4..4fc571e78f01 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt
@@ -15,7 +15,10 @@ power-domains.
- compatible:
Usage: required
Value type: <string>
- Definition: must be "qcom,sdm845-aoss-qmp"
+ Definition: must be one of:
+ "qcom,sc7180-aoss-qmp"
+ "qcom,sdm845-aoss-qmp"
+ "qcom,sm8150-aoss-qmp"
- reg:
Usage: required
diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
index f7b00a7c0f68..f541d1f776a2 100644
--- a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
+++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
@@ -19,8 +19,15 @@ child of the pmmc node.
Required Properties:
--------------------
- compatible: should be "ti,sci-pm-domain"
-- #power-domain-cells: Must be 1 so that an id can be provided in each
- device node.
+- #power-domain-cells: Can be one of the following:
+ 1: Containing the device id of each node
+ 2: First entry should be device id
+ Second entry should be one of the floowing:
+ TI_SCI_PD_EXCLUSIVE: To allow device to be
+ exclusively controlled by
+ the requesting hosts.
+ TI_SCI_PD_SHARED: To allow device to be shared
+ by multiple hosts.
Example (K2G):
-------------
diff --git a/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt
new file mode 100644
index 000000000000..a388005842ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt
@@ -0,0 +1,47 @@
+* Nuvoton FLASH Interface Unit (FIU) SPI Controller
+
+NPCM FIU supports single, dual and quad communication interface.
+
+The NPCM7XX supports three FIU modules,
+FIU0 and FIUx supports two chip selects,
+FIU3 support four chip select.
+
+Required properties:
+ - compatible : "nuvoton,npcm750-fiu" for the NPCM7XX BMC
+ - #address-cells : should be 1.
+ - #size-cells : should be 0.
+ - reg : the first contains the register location and length,
+ the second contains the memory mapping address and length
+ - reg-names: Should contain the reg names "control" and "memory"
+ - clocks : phandle of FIU reference clock.
+
+Required properties in case the pins can be muxed:
+ - pinctrl-names : a pinctrl state named "default" must be defined.
+ - pinctrl-0 : phandle referencing pin configuration of the device.
+
+Optional property:
+ - nuvoton,spix-mode: enable spix-mode for an expansion bus to an ASIC or CPLD.
+
+Aliases:
+- All the FIU controller nodes should be represented in the aliases node using
+ the following format 'fiu{n}' where n is a unique number for the alias.
+ In the NPCM7XX BMC:
+ fiu0 represent fiu 0 controller
+ fiu1 represent fiu 3 controller
+ fiu2 represent fiu x controller
+
+Example:
+fiu3: spi@c00000000 {
+ compatible = "nuvoton,npcm750-fiu";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfb000000 0x1000>, <0x80000000 0x10000000>;
+ reg-names = "control", "memory";
+ clocks = <&clk NPCM7XX_CLK_AHB>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi3_pins>;
+ spi-nor@0 {
+ ...
+ };
+};
+
diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml
index 876c0623f322..732339275848 100644
--- a/Documentation/devicetree/bindings/spi/spi-controller.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml
@@ -31,7 +31,7 @@ properties:
If that property is used, the number of chip selects will be
increased automatically with max(cs-gpios, hardware chip selects).
- So if, for example, the controller has 2 CS lines, and the
+ So if, for example, the controller has 4 CS lines, and the
cs-gpios looks like this
cs-gpios = <&gpio1 0 0>, <0>, <&gpio1 1 0>, <&gpio1 2 0>;
@@ -73,7 +73,6 @@ patternProperties:
Compatible of the SPI device.
reg:
- maxItems: 1
minimum: 0
maximum: 256
description:
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index dcc7eaada511..162e024b95a0 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -6,6 +6,7 @@ Required properties:
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
"fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
+ "fsl,ls1088a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
- reg : Offset and length of the register set for the device
- interrupts : Should contain SPI controller interrupt
- clocks: from common clock binding: handle to dspi clock.
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt
index e8f1d627d288..69dc5d57b1ef 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt
@@ -3,9 +3,8 @@
Required properties:
- compatible : Should be "fsl,vf610-qspi", "fsl,imx6sx-qspi",
"fsl,imx7d-qspi", "fsl,imx6ul-qspi",
- "fsl,ls1021a-qspi"
+ "fsl,ls1021a-qspi", "fsl,ls2080a-qspi"
or
- "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi",
"fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi"
- reg : the first contains the register location and length,
the second contains the memory mapping address and length
@@ -34,7 +33,11 @@ qspi0: quadspi@40044000 {
clock-names = "qspi_en", "qspi";
flash0: s25fl128s@0 {
- ....
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25fl128s", "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
index c0f6c8ecfa2e..3a8079eb18c8 100644
--- a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
@@ -5,6 +5,7 @@ Required properties:
- mediatek,mt2701-spi: for mt2701 platforms
- mediatek,mt2712-spi: for mt2712 platforms
- mediatek,mt6589-spi: for mt6589 platforms
+ - mediatek,mt6765-spi: for mt6765 platforms
- mediatek,mt7622-spi: for mt7622 platforms
- "mediatek,mt7629-spi", "mediatek,mt7622-spi": for mt7629 platforms
- mediatek,mt8135-spi: for mt8135 platforms
diff --git a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt
index 8de589b376ce..2567c829e2dc 100644
--- a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt
@@ -25,18 +25,23 @@ data by ADI software channels at the same time, or two parallel routine of setti
ADI registers will make ADI controller registers chaos to lead incorrect results.
Then we need one hardware spinlock to synchronize between the multiple subsystems.
+The new version ADI controller supplies multiple master channels for different
+subsystem accessing, that means no need to add hardware spinlock to synchronize,
+thus change the hardware spinlock support to be optional to keep backward
+compatibility.
+
Required properties:
- compatible: Should be "sprd,sc9860-adi".
- reg: Offset and length of ADI-SPI controller register space.
-- hwlocks: Reference to a phandle of a hwlock provider node.
-- hwlock-names: Reference to hwlock name strings defined in the same order
- as the hwlocks, should be "adi".
- #address-cells: Number of cells required to define a chip select address
on the ADI-SPI bus. Should be set to 1.
- #size-cells: Size of cells required to define a chip select address size
on the ADI-SPI bus. Should be set to 0.
Optional properties:
+- hwlocks: Reference to a phandle of a hwlock provider node.
+- hwlock-names: Reference to hwlock name strings defined in the same order
+ as the hwlocks, should be "adi".
- sprd,hw-channels: This is an array of channel values up to 49 channels.
The first value specifies the hardware channel id which is used to
transfer data triggered by hardware automatically, and the second
diff --git a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
index a36a0746c056..2807225db902 100644
--- a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
@@ -2,7 +2,7 @@
# Copyright 2018 Linaro Ltd.
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/timer/intel-ixp4xx-timer.yaml#"
+$id: "http://devicetree.org/schemas/timer/intel,ixp4xx-timer.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx XScale Networking Processors Timers
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 2e742d399e87..870ac52d2225 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -104,6 +104,8 @@ properties:
- infineon,slb9645tt
# Infineon TLV493D-A1B6 I2C 3D Magnetic Sensor
- infineon,tlv493d-a1b6
+ # Inspur Power System power supply unit version 1
+ - inspur,ipsps1
# Intersil ISL29028 Ambient Light and Proximity Sensor
- isil,isl29028
# Intersil ISL29030 Ambient Light and Proximity Sensor
diff --git a/Documentation/devicetree/bindings/usb/usb251xb.txt b/Documentation/devicetree/bindings/usb/usb251xb.txt
index bc7945e9dbfe..17915f64b8ee 100644
--- a/Documentation/devicetree/bindings/usb/usb251xb.txt
+++ b/Documentation/devicetree/bindings/usb/usb251xb.txt
@@ -64,10 +64,8 @@ Optional properties :
- power-on-time-ms : Specifies the time it takes from the time the host
initiates the power-on sequence to a port until the port has adequate
power. The value is given in ms in a 0 - 510 range (default is 100ms).
- - swap-dx-lanes : Specifies the downstream ports which will swap the
- differential-pair (D+/D-), default is not-swapped.
- - swap-us-lanes : Selects the upstream port differential-pair (D+/D-)
- swapping (boolean, default is not-swapped)
+ - swap-dx-lanes : Specifies the ports which will swap the differential-pair
+ (D+/D-), default is not-swapped.
Examples:
usb2512b@2c {
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 6992bbbbffab..de4240e0aa82 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -27,6 +27,8 @@ patternProperties:
description: Abilis Systems
"^abracon,.*":
description: Abracon Corporation
+ "^acme,.*":
+ description: Acme Systems srl
"^actions,.*":
description: Actions Semiconductor Co., Ltd.
"^active-semi,.*":
@@ -81,6 +83,8 @@ patternProperties:
description: Analogix Semiconductor, Inc.
"^andestech,.*":
description: Andes Technology Corporation
+ "^anvo,.*":
+ description: Anvo-Systems Dresden GmbH
"^apm,.*":
description: Applied Micro Circuits Corporation (APM)
"^aptina,.*":
@@ -269,6 +273,8 @@ patternProperties:
description: Emerging Display Technologies
"^eeti,.*":
description: eGalax_eMPIA Technology Inc
+ "^einfochips,.*":
+ description: Einfochips
"^elan,.*":
description: Elan Microelectronic Corp.
"^elgin,.*":
@@ -503,6 +509,8 @@ patternProperties:
description: Lantiq Semiconductor
"^lattice,.*":
description: Lattice Semiconductor
+ "^leez,.*":
+ description: Leez
"^lego,.*":
description: LEGO Systems A/S
"^lemaker,.*":
@@ -529,6 +537,8 @@ patternProperties:
description: Linear Technology Corporation
"^logicpd,.*":
description: Logic PD, Inc.
+ "^longcheer,.*":
+ description: Longcheer Technology (Shanghai) Co., Ltd.
"^lsi,.*":
description: LSI Corp. (LSI Logic)
"^lwn,.*":
@@ -549,6 +559,8 @@ patternProperties:
description: mCube
"^meas,.*":
description: Measurement Specialties
+ "^mecer,.*":
+ description: Mustek Limited
"^mediatek,.*":
description: MediaTek Inc.
"^megachips,.*":
@@ -575,6 +587,8 @@ patternProperties:
description: Micro Crystal AG
"^micron,.*":
description: Micron Technology Inc.
+ "^microsoft,.*":
+ description: Microsoft Corporation
"^mikroe,.*":
description: MikroElektronika d.o.o.
"^miniand,.*":
diff --git a/Documentation/doc-guide/conf.py b/Documentation/doc-guide/conf.py
deleted file mode 100644
index fd3731182d5a..000000000000
--- a/Documentation/doc-guide/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Documentation Guide'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/80211/conf.py b/Documentation/driver-api/80211/conf.py
deleted file mode 100644
index 4424b4b0b9c3..000000000000
--- a/Documentation/driver-api/80211/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux 802.11 Driver Developer's Guide"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', '80211.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/conf.py b/Documentation/driver-api/conf.py
deleted file mode 100644
index 202726d20088..000000000000
--- a/Documentation/driver-api/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux driver implementer's API guide"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'driver-api.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/generic-counter.rst b/Documentation/driver-api/generic-counter.rst
index 0c161b1a3be6..8382f01a53e3 100644
--- a/Documentation/driver-api/generic-counter.rst
+++ b/Documentation/driver-api/generic-counter.rst
@@ -233,7 +233,7 @@ Userspace Interface
Several sysfs attributes are generated by the Generic Counter interface,
and reside under the /sys/bus/counter/devices/counterX directory, where
counterX refers to the respective counter device. Please see
-Documentation/ABI/testing/sys-bus-counter-generic-sysfs for detailed
+Documentation/ABI/testing/sysfs-bus-counter for detailed
information on each Generic Counter interface sysfs attribute.
Through these sysfs attributes, programs and scripts may interact with
@@ -325,7 +325,7 @@ sysfs attributes, where Y is the unique ID of the respective Count:
For a more detailed breakdown of the available Generic Counter interface
sysfs attributes, please refer to the
-Documentation/ABI/testing/sys-bus-counter file.
+Documentation/ABI/testing/sysfs-bus-counter file.
The Signals and Counts associated with the Counter device are registered
to the system as well by the counter_register function. The
diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst
index 921c71a3d683..3fdb32422f8a 100644
--- a/Documentation/driver-api/gpio/driver.rst
+++ b/Documentation/driver-api/gpio/driver.rst
@@ -69,9 +69,9 @@ driver code:
The code implementing a gpio_chip should support multiple instances of the
controller, preferably using the driver model. That code will configure each
-gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``.
-Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()``
-when it is unavoidable.
+gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or
+devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use
+gpiochip_remove() when it is unavoidable.
Often a gpio_chip is part of an instance-specific structure with states not
exposed by the GPIO interfaces, such as addressing, power management, and more.
@@ -259,7 +259,7 @@ most often cascaded off a parent interrupt controller, and in some special
cases the GPIO logic is melded with a SoC's primary interrupt controller.
The IRQ portions of the GPIO block are implemented using an irq_chip, using
-the header <linux/irq.h>. So basically such a driver is utilizing two sub-
+the header <linux/irq.h>. So this combined driver is utilizing two sub-
systems simultaneously: gpio and irq.
It is legal for any IRQ consumer to request an IRQ from any irqchip even if it
@@ -391,25 +391,119 @@ Infrastructure helpers for GPIO irqchips
----------------------------------------
To help out in handling the set-up and management of GPIO irqchips and the
-associated irqdomain and resource allocation callbacks, the gpiolib has
-some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
-symbol:
-
-- gpiochip_irqchip_add(): adds a chained cascaded irqchip to a gpiochip. It
- will pass the struct gpio_chip* for the chip to all IRQ callbacks, so the
- callbacks need to embed the gpio_chip in its state container and obtain a
- pointer to the container using container_of().
- (See Documentation/driver-api/driver-model/design-patterns.rst)
+associated irqdomain and resource allocation callbacks. These are activated
+by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol
+IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be
+provided. A big portion of overhead code will be managed by gpiolib,
+under the assumption that your interrupts are 1-to-1-mapped to the
+GPIO line index:
+
+ GPIO line offset Hardware IRQ
+ 0 0
+ 1 1
+ 2 2
+ ... ...
+ ngpio-1 ngpio-1
+
+If some GPIO lines do not have corresponding IRQs, the bitmask valid_mask
+and the flag need_valid_mask in gpio_irq_chip can be used to mask off some
+lines as invalid for associating with IRQs.
+
+The preferred way to set up the helpers is to fill in the
+struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip.
+If you do this, the additional irq_chip will be set up by gpiolib at the
+same time as setting up the rest of the GPIO functionality. The following
+is a typical example of a cascaded interrupt handler using gpio_irq_chip:
+
+ /* Typical state container with dynamic irqchip */
+ struct my_gpio {
+ struct gpio_chip gc;
+ struct irq_chip irq;
+ };
+
+ int irq; /* from platform etc */
+ struct my_gpio *g;
+ struct gpio_irq_chip *girq;
+
+ /* Set up the irqchip dynamically */
+ g->irq.name = "my_gpio_irq";
+ g->irq.irq_ack = my_gpio_ack_irq;
+ g->irq.irq_mask = my_gpio_mask_irq;
+ g->irq.irq_unmask = my_gpio_unmask_irq;
+ g->irq.irq_set_type = my_gpio_set_irq_type;
+
+ /* Get a pointer to the gpio_irq_chip */
+ girq = &g->gc.irq;
+ girq->chip = &g->irq;
+ girq->parent_handler = ftgpio_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+ girq->parents[0] = irq;
+
+ return devm_gpiochip_add_data(dev, &g->gc, g);
+
+The helper support using hierarchical interrupt controllers as well.
+In this case the typical set-up will look like this:
+
+ /* Typical state container with dynamic irqchip */
+ struct my_gpio {
+ struct gpio_chip gc;
+ struct irq_chip irq;
+ struct fwnode_handle *fwnode;
+ };
+
+ int irq; /* from platform etc */
+ struct my_gpio *g;
+ struct gpio_irq_chip *girq;
+
+ /* Set up the irqchip dynamically */
+ g->irq.name = "my_gpio_irq";
+ g->irq.irq_ack = my_gpio_ack_irq;
+ g->irq.irq_mask = my_gpio_mask_irq;
+ g->irq.irq_unmask = my_gpio_unmask_irq;
+ g->irq.irq_set_type = my_gpio_set_irq_type;
+
+ /* Get a pointer to the gpio_irq_chip */
+ girq = &g->gc.irq;
+ girq->chip = &g->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+ girq->fwnode = g->fwnode;
+ girq->parent_domain = parent;
+ girq->child_to_parent_hwirq = my_gpio_child_to_parent_hwirq;
+
+ return devm_gpiochip_add_data(dev, &g->gc, g);
+
+As you can see pretty similar, but you do not supply a parent handler for
+the IRQ, instead a parent irqdomain, an fwnode for the hardware and
+a funcion .child_to_parent_hwirq() that has the purpose of looking up
+the parent hardware irq from a child (i.e. this gpio chip) hardware irq.
+As always it is good to look at examples in the kernel tree for advice
+on how to find the required pieces.
+
+The old way of adding irqchips to gpiochips after registration is also still
+available but we try to move away from this:
+
+- DEPRECATED: gpiochip_irqchip_add(): adds a chained cascaded irqchip to a
+ gpiochip. It will pass the struct gpio_chip* for the chip to all IRQ
+ callbacks, so the callbacks need to embed the gpio_chip in its state
+ container and obtain a pointer to the container using container_of().
+ (See Documentation/driver-model/design-patterns.txt)
- gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip,
as discussed above regarding different types of cascaded irqchips. The
cascaded irq has to be handled by a threaded interrupt handler.
Apart from that it works exactly like the chained irqchip.
-- gpiochip_set_chained_irqchip(): sets up a chained cascaded irq handler for a
- gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
- data. Notice that we pass is as the handler data, since the irqchip data is
- likely used by the parent irqchip.
+- DEPRECATED: gpiochip_set_chained_irqchip(): sets up a chained cascaded irq
+ handler for a gpio_chip from a parent IRQ and passes the struct gpio_chip*
+ as handler data. Notice that we pass is as the handler data, since the
+ irqchip data is likely used by the parent irqchip.
- gpiochip_set_nested_irqchip(): sets up a nested cascaded irq handler for a
gpio_chip from a parent IRQ. As the parent IRQ has usually been
@@ -418,11 +512,11 @@ symbol:
If there is a need to exclude certain GPIO lines from the IRQ domain handled by
these helpers, we can set .irq.need_valid_mask of the gpiochip before
-``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as
-many bits set as there are GPIO lines in the chip, each bit representing line
-0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask
-must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested()
-is called.
+devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an
+.irq.valid_mask with as many bits set as there are GPIO lines in the chip, each
+bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits
+from this mask. The mask must be filled in before gpiochip_irqchip_add() or
+gpiochip_irqchip_add_nested() is called.
To use the helpers please keep the following in mind:
diff --git a/Documentation/driver-api/phy/phy.rst b/Documentation/driver-api/phy/phy.rst
index 457c3e0f86d6..8fc1ce0bb905 100644
--- a/Documentation/driver-api/phy/phy.rst
+++ b/Documentation/driver-api/phy/phy.rst
@@ -179,8 +179,8 @@ PHY Mappings
In order to get reference to a PHY without help from DeviceTree, the framework
offers lookups which can be compared to clkdev that allow clk structures to be
-bound to devices. A lookup can be made be made during runtime when a handle to
-the struct phy already exists.
+bound to devices. A lookup can be made during runtime when a handle to the
+struct phy already exists.
The framework offers the following API for registering and unregistering the
lookups::
diff --git a/Documentation/driver-api/pm/conf.py b/Documentation/driver-api/pm/conf.py
deleted file mode 100644
index a89fac11272f..000000000000
--- a/Documentation/driver-api/pm/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Device Power Management"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'pm.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/sgi-ioc4.rst b/Documentation/driver-api/sgi-ioc4.rst
deleted file mode 100644
index 72709222d3c0..000000000000
--- a/Documentation/driver-api/sgi-ioc4.rst
+++ /dev/null
@@ -1,49 +0,0 @@
-====================================
-SGI IOC4 PCI (multi function) device
-====================================
-
-The SGI IOC4 PCI device is a bit of a strange beast, so some notes on
-it are in order.
-
-First, even though the IOC4 performs multiple functions, such as an
-IDE controller, a serial controller, a PS/2 keyboard/mouse controller,
-and an external interrupt mechanism, it's not implemented as a
-multifunction device. The consequence of this from a software
-standpoint is that all these functions share a single IRQ, and
-they can't all register to own the same PCI device ID. To make
-matters a bit worse, some of the register blocks (and even registers
-themselves) present in IOC4 are mixed-purpose between these several
-functions, meaning that there's no clear "owning" device driver.
-
-The solution is to organize the IOC4 driver into several independent
-drivers, "ioc4", "sgiioc4", and "ioc4_serial". Note that there is no
-PS/2 controller driver as this functionality has never been wired up
-on a shipping IO card.
-
-ioc4
-====
-This is the core (or shim) driver for IOC4. It is responsible for
-initializing the basic functionality of the chip, and allocating
-the PCI resources that are shared between the IOC4 functions.
-
-This driver also provides registration functions that the other
-IOC4 drivers can call to make their presence known. Each driver
-needs to provide a probe and remove function, which are invoked
-by the core driver at appropriate times. The interface of these
-IOC4 function probe and remove operations isn't precisely the same
-as PCI device probe and remove operations, but is logically the
-same operation.
-
-sgiioc4
-=======
-This is the IDE driver for IOC4. Its name isn't very descriptive
-simply for historical reasons (it used to be the only IOC4 driver
-component). There's not much to say about it other than it hooks
-up to the ioc4 driver via the appropriate registration, probe, and
-remove functions.
-
-ioc4_serial
-===========
-This is the serial driver for IOC4. There's not much to say about it
-other than it hooks up to the ioc4 driver via the appropriate registration,
-probe, and remove functions.
diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt
index 7fc2e243dee9..cae7be2f7725 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -21,7 +21,7 @@
| nds32: | TODO |
| nios2: | TODO |
| openrisc: | TODO |
- | parisc: | TODO |
+ | parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| s390: | ok |
diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
index 68f266944d5f..4fae0464ddff 100644
--- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
+++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
@@ -21,7 +21,7 @@
| nds32: | TODO |
| nios2: | TODO |
| openrisc: | TODO |
- | parisc: | TODO |
+ | parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| s390: | TODO |
diff --git a/Documentation/filesystems/cifs/TODO b/Documentation/filesystems/cifs/TODO
index 9267f3fb131f..edbbccda1942 100644
--- a/Documentation/filesystems/cifs/TODO
+++ b/Documentation/filesystems/cifs/TODO
@@ -13,7 +13,8 @@ a) SMB3 (and SMB3.1.1) missing optional features:
- T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
currently the only two server side copy mechanisms supported)
-b) improved sparse file support
+b) improved sparse file support (fiemap and SEEK_HOLE are implemented
+but additional features would be supportable by the protocol).
c) Directory entry caching relies on a 1 second timer, rather than
using Directory Leases, currently only the root file handle is cached longer
@@ -21,9 +22,13 @@ using Directory Leases, currently only the root file handle is cached longer
d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
-e) Additional use cases where we use "compoounding" (e.g. open/query/close
-and open/setinfo/close) to reduce the number of roundtrips, and also
-open to reduce redundant opens (using deferred close and reference counts more).
+e) Additional use cases can be optimized to use "compounding"
+(e.g. open/query/close and open/setinfo/close) to reduce the number
+of roundtrips to the server and improve performance. Various cases
+(stat, statfs, create, unlink, mkdir) already have been improved by
+using compounding but more can be done. In addition we could significantly
+reduce redundant opens by using deferred close (with handle caching leases)
+and better using reference counters on file handles.
f) Finish inotify support so kde and gnome file list windows
will autorefresh (partially complete by Asser). Needs minor kernel
@@ -43,18 +48,17 @@ mount or a per server basis to client UIDs or nobody if no mapping
exists. Also better integration with winbind for resolving SID owners
k) Add tools to take advantage of more smb3 specific ioctls and features
-(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
-is in progress, and a passthrough query_info call is already implemented
-in cifs.ko to allow smb3 info levels queries to be sent from userspace)
+(passthrough ioctl/fsctl is now implemented in cifs.ko to allow sending
+various SMB3 fsctls and query info and set info calls directly from user space)
+Add tools to make setting various non-POSIX metadata attributes easier
+from tools (e.g. extending what was done in smb-info tool).
l) encrypted file support
m) improved stats gathering tools (perhaps integration with nfsometer?)
to extend and make easier to use what is currently in /proc/fs/cifs/Stats
-n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
-file attribute via chflags) and improve user space tools for managing and
-viewing them.
+n) Add support for claims based ACLs ("DAC")
o) mount helper GUI (to simplify the various configuration options on mount)
@@ -82,6 +86,8 @@ so far).
w) Add support for additional strong encryption types, and additional spnego
authentication mechanisms (see MS-SMB2)
+x) Finish support for SMB3.1.1 compression
+
KNOWN BUGS
====================================
See http://bugzilla.samba.org - search on product "CifsVFS" for
diff --git a/Documentation/filesystems/conf.py b/Documentation/filesystems/conf.py
deleted file mode 100644
index ea44172af5c4..000000000000
--- a/Documentation/filesystems/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Filesystems API"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'filesystems.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/gpu/conf.py b/Documentation/gpu/conf.py
deleted file mode 100644
index 1757b040fb32..000000000000
--- a/Documentation/gpu/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux GPU Driver Developer's Guide"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'gpu.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/hwmon/ads1015.rst b/Documentation/hwmon/ads1015.rst
deleted file mode 100644
index e0951c4e57bb..000000000000
--- a/Documentation/hwmon/ads1015.rst
+++ /dev/null
@@ -1,90 +0,0 @@
-Kernel driver ads1015
-=====================
-
-Supported chips:
-
- * Texas Instruments ADS1015
-
- Prefix: 'ads1015'
-
- Datasheet: Publicly available at the Texas Instruments website:
-
- http://focus.ti.com/lit/ds/symlink/ads1015.pdf
-
- * Texas Instruments ADS1115
-
- Prefix: 'ads1115'
-
- Datasheet: Publicly available at the Texas Instruments website:
-
- http://focus.ti.com/lit/ds/symlink/ads1115.pdf
-
-Authors:
- Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
-
-Description
------------
-
-This driver implements support for the Texas Instruments ADS1015/ADS1115.
-
-This device is a 12/16-bit A-D converter with 4 inputs.
-
-The inputs can be used single ended or in certain differential combinations.
-
-The inputs can be made available by 8 sysfs input files in0_input - in7_input:
-
- - in0: Voltage over AIN0 and AIN1.
- - in1: Voltage over AIN0 and AIN3.
- - in2: Voltage over AIN1 and AIN3.
- - in3: Voltage over AIN2 and AIN3.
- - in4: Voltage over AIN0 and GND.
- - in5: Voltage over AIN1 and GND.
- - in6: Voltage over AIN2 and GND.
- - in7: Voltage over AIN3 and GND.
-
-Which inputs are available can be configured using platform data or devicetree.
-
-By default all inputs are exported.
-
-Platform Data
--------------
-
-In linux/platform_data/ads1015.h platform data is defined, channel_data contains
-configuration data for the used input combinations:
-
-- pga is the programmable gain amplifier (values are full scale)
-
- - 0: +/- 6.144 V
- - 1: +/- 4.096 V
- - 2: +/- 2.048 V
- - 3: +/- 1.024 V
- - 4: +/- 0.512 V
- - 5: +/- 0.256 V
-
-- data_rate in samples per second
-
- - 0: 128
- - 1: 250
- - 2: 490
- - 3: 920
- - 4: 1600
- - 5: 2400
- - 6: 3300
-
-Example::
-
- struct ads1015_platform_data data = {
- .channel_data = {
- [2] = { .enabled = true, .pga = 1, .data_rate = 0 },
- [4] = { .enabled = true, .pga = 4, .data_rate = 5 },
- }
- };
-
-In this case only in2_input (FS +/- 4.096 V, 128 SPS) and in4_input
-(FS +/- 0.512 V, 2400 SPS) would be created.
-
-Devicetree
-----------
-
-Configuration is also possible via devicetree:
-Documentation/devicetree/bindings/hwmon/ads1015.txt
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index ee090e51653a..8147c3f218bf 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -30,7 +30,6 @@ Hardware Monitoring Kernel Drivers
adm1031
adm1275
adm9240
- ads1015
ads7828
adt7410
adt7411
@@ -130,6 +129,7 @@ Hardware Monitoring Kernel Drivers
pcf8591
pmbus
powr1220
+ pxe1610
pwm-fan
raspberrypi-hwmon
sch5627
diff --git a/Documentation/hwmon/inspur-ipsps1.rst b/Documentation/hwmon/inspur-ipsps1.rst
new file mode 100644
index 000000000000..2b871ae3448f
--- /dev/null
+++ b/Documentation/hwmon/inspur-ipsps1.rst
@@ -0,0 +1,79 @@
+Kernel driver inspur-ipsps1
+=======================
+
+Supported chips:
+
+ * Inspur Power System power supply unit
+
+Author: John Wang <wangzqbj@inspur.com>
+
+Description
+-----------
+
+This driver supports Inspur Power System power supplies. This driver
+is a client to the core PMBus driver.
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+Sysfs entries
+-------------
+
+The following attributes are supported:
+
+======================= ======================================================
+curr1_input Measured input current
+curr1_label "iin"
+curr1_max Maximum current
+curr1_max_alarm Current high alarm
+curr2_input Measured output current in mA.
+curr2_label "iout1"
+curr2_crit Critical maximum current
+curr2_crit_alarm Current critical high alarm
+curr2_max Maximum current
+curr2_max_alarm Current high alarm
+
+fan1_alarm Fan 1 warning.
+fan1_fault Fan 1 fault.
+fan1_input Fan 1 speed in RPM.
+
+in1_alarm Input voltage under-voltage alarm.
+in1_input Measured input voltage in mV.
+in1_label "vin"
+in2_input Measured output voltage in mV.
+in2_label "vout1"
+in2_lcrit Critical minimum output voltage
+in2_lcrit_alarm Output voltage critical low alarm
+in2_max Maximum output voltage
+in2_max_alarm Output voltage high alarm
+in2_min Minimum output voltage
+in2_min_alarm Output voltage low alarm
+
+power1_alarm Input fault or alarm.
+power1_input Measured input power in uW.
+power1_label "pin"
+power1_max Input power limit
+power2_max_alarm Output power high alarm
+power2_max Output power limit
+power2_input Measured output power in uW.
+power2_label "pout"
+
+temp[1-3]_input Measured temperature
+temp[1-2]_max Maximum temperature
+temp[1-3]_max_alarm Temperature high alarm
+
+vendor Manufacturer name
+model Product model
+part_number Product part number
+serial_number Product serial number
+fw_version Firmware version
+hw_version Hardware version
+mode Work mode. Can be set to active or
+ standby, when set to standby, PSU will
+ automatically switch between standby
+ and redundancy mode.
+======================= ======================================================
diff --git a/Documentation/hwmon/k8temp.rst b/Documentation/hwmon/k8temp.rst
index 72da12aa17e5..fe9109521056 100644
--- a/Documentation/hwmon/k8temp.rst
+++ b/Documentation/hwmon/k8temp.rst
@@ -9,7 +9,7 @@ Supported chips:
Addresses scanned: PCI space
- Datasheet: http://support.amd.com/us/Processor_TechDocs/32559.pdf
+ Datasheet: http://www.amd.com/system/files/TechDocs/32559.pdf
Author: Rudolf Marek
diff --git a/Documentation/hwmon/lm75.rst b/Documentation/hwmon/lm75.rst
index ba8acbd2a6cb..e749f827c002 100644
--- a/Documentation/hwmon/lm75.rst
+++ b/Documentation/hwmon/lm75.rst
@@ -119,9 +119,9 @@ Supported chips:
http://www.ti.com/product/tmp275
- * NXP LM75B
+ * NXP LM75B, PCT2075
- Prefix: 'lm75b'
+ Prefix: 'lm75b', 'pct2075'
Addresses scanned: none
@@ -129,6 +129,8 @@ Supported chips:
http://www.nxp.com/documents/data_sheet/LM75B.pdf
+ http://www.nxp.com/docs/en/data-sheet/PCT2075.pdf
+
Author: Frodo Looijaard <frodol@dds.nl>
Description
diff --git a/Documentation/hwmon/pxe1610 b/Documentation/hwmon/pxe1610.rst
index 211cedeefb44..4f2388840d06 100644
--- a/Documentation/hwmon/pxe1610
+++ b/Documentation/hwmon/pxe1610.rst
@@ -2,19 +2,29 @@ Kernel driver pxe1610
=====================
Supported chips:
+
* Infineon PXE1610
+
Prefix: 'pxe1610'
+
Addresses scanned: -
+
Datasheet: Datasheet is not publicly available.
* Infineon PXE1110
+
Prefix: 'pxe1110'
+
Addresses scanned: -
+
Datasheet: Datasheet is not publicly available.
* Infineon PXM1310
+
Prefix: 'pxm1310'
+
Addresses scanned: -
+
Datasheet: Datasheet is not publicly available.
Author: Vijay Khemka <vijaykhemka@fb.com>
@@ -25,14 +35,19 @@ Description
PXE1610/PXE1110 are Multi-rail/Multiphase Digital Controllers
and compliant to
- -- Intel VR13 DC-DC converter specifications.
- -- Intel SVID protocol.
+
+ - Intel VR13 DC-DC converter specifications.
+ - Intel SVID protocol.
+
Used for Vcore power regulation for Intel VR13 based microprocessors
- -- Servers, Workstations, and High-end desktops
+
+ - Servers, Workstations, and High-end desktops
PXM1310 is a Multi-rail Controller and it is compliant to
- -- Intel VR13 DC-DC converter specifications.
- -- Intel SVID protocol.
+
+ - Intel VR13 DC-DC converter specifications.
+ - Intel SVID protocol.
+
Used for DDR3/DDR4 Memory power regulation for Intel VR13 and
IMVP8 based systems
@@ -44,10 +59,10 @@ This driver does not probe for PMBus devices. You will have
to instantiate devices explicitly.
Example: the following commands will load the driver for an PXE1610
-at address 0x70 on I2C bus #4:
+at address 0x70 on I2C bus #4::
-# modprobe pxe1610
-# echo pxe1610 0x70 > /sys/bus/i2c/devices/i2c-4/new_device
+ # modprobe pxe1610
+ # echo pxe1610 0x70 > /sys/bus/i2c/devices/i2c-4/new_device
It can also be instantiated by declaring in device tree
@@ -55,6 +70,7 @@ It can also be instantiated by declaring in device tree
Sysfs attributes
----------------
+====================== ====================================
curr1_label "iin"
curr1_input Measured input current
curr1_alarm Current high alarm
@@ -88,3 +104,4 @@ temp[1-3]_crit Critical high temperature
temp[1-3]_crit_alarm Chip temperature critical high alarm
temp[1-3]_max Maximum temperature
temp[1-3]_max_alarm Chip temperature high alarm
+====================== ====================================
diff --git a/Documentation/hwmon/shtc1.rst b/Documentation/hwmon/shtc1.rst
index aa116332ba26..9b0f1eee5bf2 100644
--- a/Documentation/hwmon/shtc1.rst
+++ b/Documentation/hwmon/shtc1.rst
@@ -19,7 +19,17 @@ Supported chips:
Addresses scanned: none
- Datasheet: Not publicly available
+ Datasheet: http://www.sensirion.com/file/datasheet_shtw1
+
+
+
+ * Sensirion SHTC3
+
+ Prefix: 'shtc3'
+
+ Addresses scanned: none
+
+ Datasheet: http://www.sensirion.com/file/datasheet_shtc3
@@ -30,10 +40,9 @@ Author:
Description
-----------
-This driver implements support for the Sensirion SHTC1 chip, a humidity and
-temperature sensor. Temperature is measured in degrees celsius, relative
-humidity is expressed as a percentage. Driver can be used as well for SHTW1
-chip, which has the same electrical interface.
+This driver implements support for the Sensirion SHTC1, SHTW1, and SHTC3
+chips, a humidity and temperature sensor. Temperature is measured in degrees
+celsius, relative humidity is expressed as a percentage.
The device communicates with the I2C protocol. All sensors are set to I2C
address 0x70. See Documentation/i2c/instantiating-devices for methods to
diff --git a/Documentation/hwmon/submitting-patches.rst b/Documentation/hwmon/submitting-patches.rst
index 452fc28d8e0b..9a218ea996d8 100644
--- a/Documentation/hwmon/submitting-patches.rst
+++ b/Documentation/hwmon/submitting-patches.rst
@@ -20,6 +20,10 @@ increase the chances of your change being accepted.
errors, no warnings, and few if any check messages. If there are any
messages, please be prepared to explain.
+* Please use the standard multi-line comment style. Do not mix C and C++
+ style comments in a single driver (with the exception of the SPDX license
+ identifier).
+
* If your patch generates checkpatch errors, warnings, or check messages,
please refrain from explanations such as "I prefer that coding style".
Keep in mind that each unnecessary message helps hiding a real problem,
@@ -120,8 +124,8 @@ increase the chances of your change being accepted.
completely initialize your chip and your driver first, then register with
the hwmon subsystem.
-* Use devm_hwmon_device_register_with_groups() or, if your driver needs a remove
- function, hwmon_device_register_with_groups() to register your driver with the
+* Use devm_hwmon_device_register_with_info() or, if your driver needs a remove
+ function, hwmon_device_register_with_info() to register your driver with the
hwmon subsystem. Try using devm_add_action() instead of a remove function if
possible. Do not use hwmon_device_register().
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 70ae148ec980..2df5a3da563c 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -111,9 +111,11 @@ needed).
netlabel/index
networking/index
pcmcia/index
+ power/index
target/index
timers/index
watchdog/index
+ virtual/index
input/index
hwmon/index
gpu/index
@@ -143,6 +145,7 @@ implementation.
arm64/index
ia64/index
m68k/index
+ powerpc/index
riscv/index
s390/index
sh/index
diff --git a/Documentation/input/conf.py b/Documentation/input/conf.py
deleted file mode 100644
index d2352fdc92ed..000000000000
--- a/Documentation/input/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux input driver subsystem"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'linux-input.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/kernel-hacking/conf.py b/Documentation/kernel-hacking/conf.py
deleted file mode 100644
index 3d8acf0f33ad..000000000000
--- a/Documentation/kernel-hacking/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Kernel Hacking Guides"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'kernel-hacking.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/locking/spinlocks.rst b/Documentation/locking/spinlocks.rst
index 098107fb7d86..e93ec6645238 100644
--- a/Documentation/locking/spinlocks.rst
+++ b/Documentation/locking/spinlocks.rst
@@ -82,7 +82,7 @@ itself. The read lock allows many concurrent readers. Anything that
**changes** the list will have to get the write lock.
NOTE! RCU is better for list traversal, but requires careful
- attention to design detail (see Documentation/RCU/listRCU.txt).
+ attention to design detail (see Documentation/RCU/listRCU.rst).
Also, you cannot "upgrade" a read-lock to a write-lock, so if you at _any_
time need to do any changes (even if you don't do it every time), you have
@@ -90,7 +90,7 @@ to get the write-lock at the very beginning.
NOTE! We are working hard to remove reader-writer spinlocks in most
cases, so please don't add a new one without consensus. (Instead, see
- Documentation/RCU/rcu.txt for complete information.)
+ Documentation/RCU/rcu.rst for complete information.)
----
diff --git a/Documentation/maintainer/conf.py b/Documentation/maintainer/conf.py
deleted file mode 100644
index 81e9eb7a7884..000000000000
--- a/Documentation/maintainer/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Development Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'maintainer.tex', 'Linux Kernel Development Documentation',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/media/conf.py b/Documentation/media/conf.py
deleted file mode 100644
index 1f194fcd2cae..000000000000
--- a/Documentation/media/conf.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-# SPDX-License-Identifier: GPL-2.0
-
-project = 'Linux Media Subsystem Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'media.tex', 'Linux Media Subsystem Documentation',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 045bb8148fe9..1adbb8a371c7 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -548,7 +548,7 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
[*] For information on bus mastering DMA and coherency please read:
- Documentation/PCI/pci.rst
+ Documentation/driver-api/pci/pci.rst
Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
diff --git a/Documentation/networking/conf.py b/Documentation/networking/conf.py
deleted file mode 100644
index 40f69e67a883..000000000000
--- a/Documentation/networking/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Networking Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'networking.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/networking/tls-offload.rst b/Documentation/networking/tls-offload.rst
index 048e5ca44824..0dd3f748239f 100644
--- a/Documentation/networking/tls-offload.rst
+++ b/Documentation/networking/tls-offload.rst
@@ -424,13 +424,24 @@ Statistics
Following minimum set of TLS-related statistics should be reported
by the driver:
- * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
- * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
- for encryption
+ * ``rx_tls_decrypted_packets`` - number of successfully decrypted RX packets
+ which were part of a TLS stream.
+ * ``rx_tls_decrypted_bytes`` - number of TLS payload bytes in RX packets
+ which were successfully decrypted.
+ * ``tx_tls_encrypted_packets`` - number of TX packets passed to the device
+ for encryption of their TLS payload.
+ * ``tx_tls_encrypted_bytes`` - number of TLS payload bytes in TX packets
+ passed to the device for encryption.
+ * ``tx_tls_ctx`` - number of TLS TX HW offload contexts added to device for
+ encryption.
* ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
- but did not arrive in the expected order
- * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
- they arrived out of order and associated record could not be found
+ but did not arrive in the expected order.
+ * ``tx_tls_drop_no_sync_data`` - number of TX packets which were part of
+ a TLS stream dropped, because they arrived out of order and associated
+ record could not be found.
+ * ``tx_tls_drop_bypass_req`` - number of TX packets which were part of a TLS
+ stream dropped, because they contain both data that has been encrypted by
+ software and data that expects hardware crypto offload.
Notable corner cases, exceptions and additional requirements
============================================================
@@ -495,21 +506,3 @@ Drivers should ignore the changes to TLS the device feature flags.
These flags will be acted upon accordingly by the core ``ktls`` code.
TLS device feature flags only control adding of new TLS connection
offloads, old connections will remain active after flags are cleared.
-
-Known bugs
-==========
-
-skb_orphan() leaks clear text
------------------------------
-
-Currently drivers depend on the :c:member:`sk` member of
-:c:type:`struct sk_buff <sk_buff>` to identify segments requiring
-encryption. Any operation which removes or does not preserve the socket
-association such as :c:func:`skb_orphan` or :c:func:`skb_clone`
-will cause the driver to miss the packets and lead to clear text leaks.
-
-Redirects leak clear text
--------------------------
-
-In the RX direction, if segment has already been decrypted by the device
-and it gets redirected or mirrored - clear text will be transmitted out.
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index 949d5dcdd9a3..0104830d5075 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -204,8 +204,8 @@ Ethernet device, which instead of receiving packets from a physical
media, receives them from user space program and instead of sending
packets via physical media sends them to the user space program.
-Let's say that you configured IPX on the tap0, then whenever
-the kernel sends an IPX packet to tap0, it is passed to the application
+Let's say that you configured IPv6 on the tap0, then whenever
+the kernel sends an IPv6 packet to tap0, it is passed to the application
(VTun for example). The application encrypts, compresses and sends it to
the other side over TCP or UDP. The application on the other side decompresses
and decrypts the data received and writes the packet to the TAP device,
diff --git a/Documentation/power/index.rst b/Documentation/power/index.rst
index 20415f21e48a..002e42745263 100644
--- a/Documentation/power/index.rst
+++ b/Documentation/power/index.rst
@@ -1,4 +1,4 @@
-:orphan:
+.. SPDX-License-Identifier: GPL-2.0
================
Power Management
diff --git a/Documentation/powerpc/bootwrapper.txt b/Documentation/powerpc/bootwrapper.rst
index d60fced5e1cc..a6292afba573 100644
--- a/Documentation/powerpc/bootwrapper.txt
+++ b/Documentation/powerpc/bootwrapper.rst
@@ -1,5 +1,7 @@
+========================
The PowerPC boot wrapper
-------------------------
+========================
+
Copyright (C) Secret Lab Technologies Ltd.
PowerPC image targets compresses and wraps the kernel image (vmlinux) with
@@ -21,6 +23,7 @@ it uses the wrapper script (arch/powerpc/boot/wrapper) to generate target
image. The details of the build system is discussed in the next section.
Currently, the following image format targets exist:
+ ==================== ========================================================
cuImage.%: Backwards compatible uImage for older version of
U-Boot (for versions that don't understand the device
tree). This image embeds a device tree blob inside
@@ -29,31 +32,36 @@ Currently, the following image format targets exist:
with boot wrapper code that extracts data from the old
bd_info structure and loads the data into the device
tree before jumping into the kernel.
- Because of the series of #ifdefs found in the
+
+ Because of the series of #ifdefs found in the
bd_info structure used in the old U-Boot interfaces,
cuImages are platform specific. Each specific
U-Boot platform has a different platform init file
which populates the embedded device tree with data
from the platform specific bd_info file. The platform
specific cuImage platform init code can be found in
- arch/powerpc/boot/cuboot.*.c. Selection of the correct
+ `arch/powerpc/boot/cuboot.*.c`. Selection of the correct
cuImage init code for a specific board can be found in
the wrapper structure.
+
dtbImage.%: Similar to zImage, except device tree blob is embedded
inside the image instead of provided by firmware. The
output image file can be either an elf file or a flat
binary depending on the platform.
- dtbImages are used on systems which do not have an
+
+ dtbImages are used on systems which do not have an
interface for passing a device tree directly.
dtbImages are similar to simpleImages except that
dtbImages have platform specific code for extracting
data from the board firmware, but simpleImages do not
talk to the firmware at all.
- PlayStation 3 support uses dtbImage. So do Embedded
+
+ PlayStation 3 support uses dtbImage. So do Embedded
Planet boards using the PlanetCore firmware. Board
specific initialization code is typically found in a
file named arch/powerpc/boot/<platform>.c; but this
can be overridden by the wrapper script.
+
simpleImage.%: Firmware independent compressed image that does not
depend on any particular firmware interface and embeds
a device tree blob. This image is a flat binary that
@@ -61,14 +69,16 @@ Currently, the following image format targets exist:
Firmware cannot pass any configuration data to the
kernel with this image type and it depends entirely on
the embedded device tree for all information.
- The simpleImage is useful for booting systems with
+
+ The simpleImage is useful for booting systems with
an unknown firmware interface or for booting from
a debugger when no firmware is present (such as on
the Xilinx Virtex platform). The only assumption that
simpleImage makes is that RAM is correctly initialized
and that the MMU is either off or has RAM mapped to
base address 0.
- simpleImage also supports inserting special platform
+
+ simpleImage also supports inserting special platform
specific initialization code to the start of the bootup
sequence. The virtex405 platform uses this feature to
ensure that the cache is invalidated before caching
@@ -81,9 +91,11 @@ Currently, the following image format targets exist:
named (virtex405-<board>.dts). Search the wrapper
script for 'virtex405' and see the file
arch/powerpc/boot/virtex405-head.S for details.
+
treeImage.%; Image format for used with OpenBIOS firmware found
on some ppc4xx hardware. This image embeds a device
tree blob inside the image.
+
uImage: Native image format used by U-Boot. The uImage target
does not add any boot code. It just wraps a compressed
vmlinux in the uImage data structure. This image
@@ -91,12 +103,14 @@ Currently, the following image format targets exist:
a device tree to the kernel at boot. If using an older
version of U-Boot, then you need to use a cuImage
instead.
+
zImage.%: Image format which does not embed a device tree.
Used by OpenFirmware and other firmware interfaces
which are able to supply a device tree. This image
expects firmware to provide the device tree at boot.
Typically, if you have general purpose PowerPC
hardware then you want this image format.
+ ==================== ========================================================
Image types which embed a device tree blob (simpleImage, dtbImage, treeImage,
and cuImage) all generate the device tree blob from a file in the
diff --git a/Documentation/powerpc/cpu_families.txt b/Documentation/powerpc/cpu_families.rst
index fc08e22feb1a..1e063c5440c3 100644
--- a/Documentation/powerpc/cpu_families.txt
+++ b/Documentation/powerpc/cpu_families.rst
@@ -1,3 +1,4 @@
+============
CPU Families
============
@@ -8,8 +9,8 @@ and are supported by arch/powerpc.
Book3S (aka sPAPR)
------------------
- - Hash MMU
- - Mix of 32 & 64 bit
+- Hash MMU
+- Mix of 32 & 64 bit::
+--------------+ +----------------+
| Old POWER | --------------> | RS64 (threads) |
@@ -108,8 +109,8 @@ Book3S (aka sPAPR)
IBM BookE
---------
- - Software loaded TLB.
- - All 32 bit
+- Software loaded TLB.
+- All 32 bit::
+--------------+
| 401 |
@@ -155,8 +156,8 @@ IBM BookE
Motorola/Freescale 8xx
----------------------
- - Software loaded with hardware assist.
- - All 32 bit
+- Software loaded with hardware assist.
+- All 32 bit::
+-------------+
| MPC8xx Core |
@@ -166,9 +167,9 @@ Motorola/Freescale 8xx
Freescale BookE
---------------
- - Software loaded TLB.
- - e6500 adds HW loaded indirect TLB entries.
- - Mix of 32 & 64 bit
+- Software loaded TLB.
+- e6500 adds HW loaded indirect TLB entries.
+- Mix of 32 & 64 bit::
+--------------+
| e200 |
@@ -207,8 +208,8 @@ Freescale BookE
IBM A2 core
-----------
- - Book3E, software loaded TLB + HW loaded indirect TLB entries.
- - 64 bit
+- Book3E, software loaded TLB + HW loaded indirect TLB entries.
+- 64 bit::
+--------------+ +----------------+
| A2 core | --> | WSP |
diff --git a/Documentation/powerpc/cpu_features.txt b/Documentation/powerpc/cpu_features.rst
index ae09df8722c8..b7bcdd2f41bb 100644
--- a/Documentation/powerpc/cpu_features.txt
+++ b/Documentation/powerpc/cpu_features.rst
@@ -1,3 +1,7 @@
+============
+CPU Features
+============
+
Hollis Blanchard <hollis@austin.ibm.com>
5 Jun 2002
@@ -32,7 +36,7 @@ anyways).
After detecting the processor type, the kernel patches out sections of code
that shouldn't be used by writing nop's over it. Using cpufeatures requires
just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
-transfer_to_handler:
+transfer_to_handler::
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
diff --git a/Documentation/powerpc/cxl.txt b/Documentation/powerpc/cxl.rst
index c5e8d5098ed3..920546d81326 100644
--- a/Documentation/powerpc/cxl.txt
+++ b/Documentation/powerpc/cxl.rst
@@ -1,3 +1,4 @@
+====================================
Coherent Accelerator Interface (CXL)
====================================
@@ -21,6 +22,8 @@ Introduction
Hardware overview
=================
+ ::
+
POWER8/9 FPGA
+----------+ +---------+
| | | |
@@ -59,14 +62,16 @@ Hardware overview
the fault. The context to which this fault is serviced is based on
who owns that acceleration function.
- POWER8 <-----> PSL Version 8 is compliant to the CAIA Version 1.0.
- POWER9 <-----> PSL Version 9 is compliant to the CAIA Version 2.0.
+ - POWER8 and PSL Version 8 are compliant to the CAIA Version 1.0.
+ - POWER9 and PSL Version 9 are compliant to the CAIA Version 2.0.
+
This PSL Version 9 provides new features such as:
+
* Interaction with the nest MMU on the P9 chip.
* Native DMA support.
* Supports sending ASB_Notify messages for host thread wakeup.
* Supports Atomic operations.
- * ....
+ * etc.
Cards with a PSL9 won't work on a POWER8 system and cards with a
PSL8 won't work on a POWER9 system.
@@ -147,7 +152,9 @@ User API
master devices.
A userspace library libcxl is available here:
+
https://github.com/ibm-capi/libcxl
+
This provides a C interface to this kernel API.
open
@@ -165,7 +172,8 @@ open
When all available contexts are allocated the open call will fail
and return -ENOSPC.
- Note: IRQs need to be allocated for each context, which may limit
+ Note:
+ IRQs need to be allocated for each context, which may limit
the number of contexts that can be created, and therefore
how many times the device can be opened. The POWER8 CAPP
supports 2040 IRQs and 3 are used by the kernel, so 2037 are
@@ -186,7 +194,9 @@ ioctl
updated as userspace allocates and frees memory. This ioctl
returns once the AFU context is started.
- Takes a pointer to a struct cxl_ioctl_start_work:
+ Takes a pointer to a struct cxl_ioctl_start_work
+
+ ::
struct cxl_ioctl_start_work {
__u64 flags;
@@ -269,7 +279,7 @@ read
The buffer passed to read() must be at least 4K bytes.
The result of the read will be a buffer of one or more events,
- each event is of type struct cxl_event, of varying size.
+ each event is of type struct cxl_event, of varying size::
struct cxl_event {
struct cxl_event_header header;
@@ -280,7 +290,9 @@ read
};
};
- The struct cxl_event_header is defined as:
+ The struct cxl_event_header is defined as
+
+ ::
struct cxl_event_header {
__u16 type;
@@ -307,7 +319,9 @@ read
For future extensions and padding.
If the event type is CXL_EVENT_AFU_INTERRUPT then the event
- structure is defined as:
+ structure is defined as
+
+ ::
struct cxl_event_afu_interrupt {
__u16 flags;
@@ -326,7 +340,9 @@ read
For future extensions and padding.
If the event type is CXL_EVENT_DATA_STORAGE then the event
- structure is defined as:
+ structure is defined as
+
+ ::
struct cxl_event_data_storage {
__u16 flags;
@@ -356,7 +372,9 @@ read
For future extensions
If the event type is CXL_EVENT_AFU_ERROR then the event structure
- is defined as:
+ is defined as
+
+ ::
struct cxl_event_afu_error {
__u16 flags;
@@ -393,15 +411,15 @@ open
ioctl
-----
-CXL_IOCTL_DOWNLOAD_IMAGE:
-CXL_IOCTL_VALIDATE_IMAGE:
+CXL_IOCTL_DOWNLOAD_IMAGE / CXL_IOCTL_VALIDATE_IMAGE:
Starts and controls flashing a new FPGA image. Partial
reconfiguration is not supported (yet), so the image must contain
a copy of the PSL and AFU(s). Since an image can be quite large,
the caller may have to iterate, splitting the image in smaller
chunks.
- Takes a pointer to a struct cxl_adapter_image:
+ Takes a pointer to a struct cxl_adapter_image::
+
struct cxl_adapter_image {
__u64 flags;
__u64 data;
@@ -442,7 +460,7 @@ Udev rules
The following udev rules could be used to create a symlink to the
most logical chardev to use in any programming mode (afuX.Yd for
dedicated, afuX.Ys for afu directed), since the API is virtually
- identical for each:
+ identical for each::
SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b"
SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \
diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.rst
index a64bdaa0a1cf..cea67931b3b9 100644
--- a/Documentation/powerpc/cxlflash.txt
+++ b/Documentation/powerpc/cxlflash.rst
@@ -1,3 +1,7 @@
+================================
+Coherent Accelerator (CXL) Flash
+================================
+
Introduction
============
@@ -28,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.txt.
+ as described in Documentation/powerpc/cxl.rst.
The cxlflash driver supports two, mutually exclusive, modes of
operation at the device (LUN) level:
@@ -58,7 +62,7 @@ Overview
The CXL Flash Adapter Driver establishes a master context with the
AFU. It uses memory mapped I/O (MMIO) for this control and setup. The
- Adapter Problem Space Memory Map looks like this:
+ Adapter Problem Space Memory Map looks like this::
+-------------------------------+
| 512 * 64 KB User MMIO |
@@ -375,7 +379,7 @@ CXL Flash Driver Host IOCTLs
Each host adapter instance that is supported by the cxlflash driver
has a special character device associated with it to enable a set of
host management function. These character devices are hosted in a
- class dedicated for cxlflash and can be accessed via /dev/cxlflash/*.
+ class dedicated for cxlflash and can be accessed via `/dev/cxlflash/*`.
Applications can be written to perform various functions using the
host ioctl APIs below.
diff --git a/Documentation/powerpc/DAWR-POWER9.txt b/Documentation/powerpc/dawr-power9.rst
index ecdbb076438c..c96ab6befd9c 100644
--- a/Documentation/powerpc/DAWR-POWER9.txt
+++ b/Documentation/powerpc/dawr-power9.rst
@@ -1,10 +1,11 @@
+=====================
DAWR issues on POWER9
-============================
+=====================
On POWER9 the Data Address Watchpoint Register (DAWR) can cause a checkstop
if it points to cache inhibited (CI) memory. Currently Linux has no way to
disinguish CI memory when configuring the DAWR, so (for now) the DAWR is
-disabled by this commit:
+disabled by this commit::
commit 9654153158d3e0684a1bdb76dbababdb7111d5a0
Author: Michael Neuling <mikey@neuling.org>
@@ -12,7 +13,7 @@ disabled by this commit:
powerpc: Disable DAWR in the base POWER9 CPU features
Technical Details:
-============================
+==================
DAWR has 6 different ways of being set.
1) ptrace
@@ -37,7 +38,7 @@ DAWR on the migration.
For xmon, the 'bd' command will return an error on P9.
Consequences for users
-============================
+======================
For GDB watchpoints (ie 'watch' command) on POWER9 bare metal , GDB
will accept the command. Unfortunately since there is no hardware
@@ -57,8 +58,8 @@ trapped in GDB. The watchpoint is remembered, so if the guest is
migrated back to the POWER8 host, it will start working again.
Force enabling the DAWR
-=============================
-Kernels (since ~v5.2) have an option to force enable the DAWR via:
+=======================
+Kernels (since ~v5.2) have an option to force enable the DAWR via::
echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
@@ -86,5 +87,7 @@ dawr_enable_dangerous file will fail if the hypervisor doesn't support
writing the DAWR.
To double check the DAWR is working, run this kernel selftest:
+
tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
+
Any errors/failures/skips mean something is wrong.
diff --git a/Documentation/powerpc/dscr.txt b/Documentation/powerpc/dscr.rst
index ece300c64f76..2ab99006014c 100644
--- a/Documentation/powerpc/dscr.txt
+++ b/Documentation/powerpc/dscr.rst
@@ -1,5 +1,6 @@
- DSCR (Data Stream Control Register)
- ================================================
+===================================
+DSCR (Data Stream Control Register)
+===================================
DSCR register in powerpc allows user to have some control of prefetch of data
stream in the processor. Please refer to the ISA documents or related manual
@@ -10,14 +11,17 @@ user interface.
(A) Data Structures:
- (1) thread_struct:
+ (1) thread_struct::
+
dscr /* Thread DSCR value */
dscr_inherit /* Thread has changed default DSCR */
- (2) PACA:
+ (2) PACA::
+
dscr_default /* per-CPU DSCR default value */
- (3) sysfs.c:
+ (3) sysfs.c::
+
dscr_default /* System DSCR default value */
(B) Scheduler Changes:
@@ -35,8 +39,8 @@ user interface.
(C) SYSFS Interface:
- Global DSCR default: /sys/devices/system/cpu/dscr_default
- CPU specific DSCR default: /sys/devices/system/cpu/cpuN/dscr
+ - Global DSCR default: /sys/devices/system/cpu/dscr_default
+ - CPU specific DSCR default: /sys/devices/system/cpu/cpuN/dscr
Changing the global DSCR default in the sysfs will change all the CPU
specific DSCR defaults immediately in their PACA structures. Again if
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.rst
index 678189280bb4..438a87ebc095 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.txt
+++ b/Documentation/powerpc/eeh-pci-error-recovery.rst
@@ -1,10 +1,10 @@
+==========================
+PCI Bus EEH Error Recovery
+==========================
+Linas Vepstas <linas@austin.ibm.com>
- PCI Bus EEH Error Recovery
- --------------------------
- Linas Vepstas
- <linas@austin.ibm.com>
- 12 January 2005
+12 January 2005
Overview:
@@ -143,17 +143,17 @@ seen in /proc/ppc64/eeh (subject to change). Normally, almost
all of these occur during boot, when the PCI bus is scanned, where
a large number of 0xff reads are part of the bus scan procedure.
-If a frozen slot is detected, code in
-arch/powerpc/platforms/pseries/eeh.c will print a stack trace to
-syslog (/var/log/messages). This stack trace has proven to be very
-useful to device-driver authors for finding out at what point the EEH
-error was detected, as the error itself usually occurs slightly
+If a frozen slot is detected, code in
+arch/powerpc/platforms/pseries/eeh.c will print a stack trace to
+syslog (/var/log/messages). This stack trace has proven to be very
+useful to device-driver authors for finding out at what point the EEH
+error was detected, as the error itself usually occurs slightly
beforehand.
Next, it uses the Linux kernel notifier chain/work queue mechanism to
allow any interested parties to find out about the failure. Device
drivers, or other parts of the kernel, can use
-eeh_register_notifier(struct notifier_block *) to find out about EEH
+`eeh_register_notifier(struct notifier_block *)` to find out about EEH
events. The event will include a pointer to the pci device, the
device node and some state info. Receivers of the event can "do as
they wish"; the default handler will be described further in this
@@ -162,10 +162,13 @@ section.
To assist in the recovery of the device, eeh.c exports the
following functions:
-rtas_set_slot_reset() -- assert the PCI #RST line for 1/8th of a second
-rtas_configure_bridge() -- ask firmware to configure any PCI bridges
+rtas_set_slot_reset()
+ assert the PCI #RST line for 1/8th of a second
+rtas_configure_bridge()
+ ask firmware to configure any PCI bridges
located topologically under the pci slot.
-eeh_save_bars() and eeh_restore_bars(): save and restore the PCI
+eeh_save_bars() and eeh_restore_bars():
+ save and restore the PCI
config-space info for a device and any devices under it.
@@ -191,7 +194,7 @@ events get delivered to user-space scripts.
Following is an example sequence of events that cause a device driver
close function to be called during the first phase of an EEH reset.
-The following sequence is an example of the pcnet32 device driver.
+The following sequence is an example of the pcnet32 device driver::
rpa_php_unconfig_pci_adapter (struct slot *) // in rpaphp_pci.c
{
@@ -241,53 +244,54 @@ The following sequence is an example of the pcnet32 device driver.
}}}}}}
- in drivers/pci/pci_driver.c,
- struct device_driver->remove() is just pci_device_remove()
- which calls struct pci_driver->remove() which is pcnet32_remove_one()
- which calls unregister_netdev() (in net/core/dev.c)
- which calls dev_close() (in net/core/dev.c)
- which calls dev->stop() which is pcnet32_close()
- which then does the appropriate shutdown.
+in drivers/pci/pci_driver.c,
+struct device_driver->remove() is just pci_device_remove()
+which calls struct pci_driver->remove() which is pcnet32_remove_one()
+which calls unregister_netdev() (in net/core/dev.c)
+which calls dev_close() (in net/core/dev.c)
+which calls dev->stop() which is pcnet32_close()
+which then does the appropriate shutdown.
---
+
Following is the analogous stack trace for events sent to user-space
-when the pci device is unconfigured.
+when the pci device is unconfigured::
-rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
- calls
- pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
+ rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
calls
- pci_destroy_dev (struct pci_dev *) {
+ pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
calls
- device_unregister (&dev->dev) { // in /drivers/base/core.c
+ pci_destroy_dev (struct pci_dev *) {
calls
- device_del(struct device * dev) { // in /drivers/base/core.c
+ device_unregister (&dev->dev) { // in /drivers/base/core.c
calls
- kobject_del() { //in /libs/kobject.c
+ device_del(struct device * dev) { // in /drivers/base/core.c
calls
- kobject_uevent() { // in /libs/kobject.c
+ kobject_del() { //in /libs/kobject.c
calls
- kset_uevent() { // in /lib/kobject.c
+ kobject_uevent() { // in /libs/kobject.c
calls
- kset->uevent_ops->uevent() // which is really just
- a call to
- dev_uevent() { // in /drivers/base/core.c
+ kset_uevent() { // in /lib/kobject.c
calls
- dev->bus->uevent() which is really just a call to
- pci_uevent () { // in drivers/pci/hotplug.c
- which prints device name, etc....
+ kset->uevent_ops->uevent() // which is really just
+ a call to
+ dev_uevent() { // in /drivers/base/core.c
+ calls
+ dev->bus->uevent() which is really just a call to
+ pci_uevent () { // in drivers/pci/hotplug.c
+ which prints device name, etc....
+ }
}
- }
- then kobject_uevent() sends a netlink uevent to userspace
- --> userspace uevent
- (during early boot, nobody listens to netlink events and
- kobject_uevent() executes uevent_helper[], which runs the
- event process /sbin/hotplug)
+ then kobject_uevent() sends a netlink uevent to userspace
+ --> userspace uevent
+ (during early boot, nobody listens to netlink events and
+ kobject_uevent() executes uevent_helper[], which runs the
+ event process /sbin/hotplug)
+ }
}
- }
- kobject_del() then calls sysfs_remove_dir(), which would
- trigger any user-space daemon that was watching /sysfs,
- and notice the delete event.
+ kobject_del() then calls sysfs_remove_dir(), which would
+ trigger any user-space daemon that was watching /sysfs,
+ and notice the delete event.
Pro's and Con's of the Current Design
@@ -299,12 +303,12 @@ individual device drivers, so that the current design throws a wide net.
The biggest negative of the design is that it potentially disturbs
network daemons and file systems that didn't need to be disturbed.
--- A minor complaint is that resetting the network card causes
+- A minor complaint is that resetting the network card causes
user-space back-to-back ifdown/ifup burps that potentially disturb
network daemons, that didn't need to even know that the pci
card was being rebooted.
--- A more serious concern is that the same reset, for SCSI devices,
+- A more serious concern is that the same reset, for SCSI devices,
causes havoc to mounted file systems. Scripts cannot post-facto
unmount a file system without flushing pending buffers, but this
is impossible, because I/O has already been stopped. Thus,
@@ -322,7 +326,7 @@ network daemons and file systems that didn't need to be disturbed.
from the block layer. It would be very natural to add an EEH
reset into this chain of events.
--- If a SCSI error occurs for the root device, all is lost unless
+- If a SCSI error occurs for the root device, all is lost unless
the sysadmin had the foresight to run /bin, /sbin, /etc, /var
and so on, out of ramdisk/tmpfs.
@@ -330,5 +334,3 @@ network daemons and file systems that didn't need to be disturbed.
Conclusions
-----------
There's forward progress ...
-
-
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.rst
index 10e7f4d16c14..9ca12830a48e 100644
--- a/Documentation/powerpc/firmware-assisted-dump.txt
+++ b/Documentation/powerpc/firmware-assisted-dump.rst
@@ -1,7 +1,8 @@
+======================
+Firmware-Assisted Dump
+======================
- Firmware-Assisted Dump
- ------------------------
- July 2011
+July 2011
The goal of firmware-assisted dump is to enable the dump of
a crashed system, and to do so from a fully-reset system, and
@@ -27,11 +28,11 @@ in production use.
Comparing with kdump or other strategies, firmware-assisted
dump offers several strong, practical advantages:
--- Unlike kdump, the system has been reset, and loaded
+- Unlike kdump, the system has been reset, and loaded
with a fresh copy of the kernel. In particular,
PCI and I/O devices have been reinitialized and are
in a clean, consistent state.
--- Once the dump is copied out, the memory that held the dump
+- Once the dump is copied out, the memory that held the dump
is immediately available to the running kernel. And therefore,
unlike kdump, fadump doesn't need a 2nd reboot to get back
the system to the production configuration.
@@ -40,17 +41,18 @@ The above can only be accomplished by coordination with,
and assistance from the Power firmware. The procedure is
as follows:
--- The first kernel registers the sections of memory with the
+- The first kernel registers the sections of memory with the
Power firmware for dump preservation during OS initialization.
These registered sections of memory are reserved by the first
kernel during early boot.
--- When a system crashes, the Power firmware will save
+- When a system crashes, the Power firmware will save
the low memory (boot memory of size larger of 5% of system RAM
or 256MB) of RAM to the previous registered region. It will
also save system registers, and hardware PTE's.
- NOTE: The term 'boot memory' means size of the low memory chunk
+ NOTE:
+ The term 'boot memory' means size of the low memory chunk
that is required for a kernel to boot successfully when
booted with restricted memory. By default, the boot memory
size will be the larger of 5% of system RAM or 256MB.
@@ -64,12 +66,12 @@ as follows:
as fadump uses a predefined offset to reserve memory
for boot memory dump preservation in case of a crash.
--- After the low memory (boot memory) area has been saved, the
+- After the low memory (boot memory) area has been saved, the
firmware will reset PCI and other hardware state. It will
*not* clear the RAM. It will then launch the bootloader, as
normal.
--- The freshly booted kernel will notice that there is a new
+- The freshly booted kernel will notice that there is a new
node (ibm,dump-kernel) in the device tree, indicating that
there is crash data available from a previous boot. During
the early boot OS will reserve rest of the memory above
@@ -77,17 +79,18 @@ as follows:
size. This will make sure that the second kernel will not
touch any of the dump memory area.
--- User-space tools will read /proc/vmcore to obtain the contents
+- User-space tools will read /proc/vmcore to obtain the contents
of memory, which holds the previous crashed kernel dump in ELF
format. The userspace tools may copy this info to disk, or
network, nas, san, iscsi, etc. as desired.
--- Once the userspace tool is done saving dump, it will echo
+- Once the userspace tool is done saving dump, it will echo
'1' to /sys/kernel/fadump_release_mem to release the reserved
memory back to general use, except the memory required for
next firmware-assisted dump registration.
- e.g.
+ e.g.::
+
# echo 1 > /sys/kernel/fadump_release_mem
Please note that the firmware-assisted dump feature
@@ -95,7 +98,7 @@ is only available on Power6 and above systems with recent
firmware versions.
Implementation details:
-----------------------
+-----------------------
During boot, a check is made to see if firmware supports
this feature on that particular machine. If it does, then
@@ -121,7 +124,7 @@ Allocator (CMA) for memory reservation if CMA is configured for kernel.
With CMA reservation this memory will be available for applications to
use it, while kernel is prevented from using it. With this fadump will
still be able to capture all of the kernel memory and most of the user
-space memory except the user pages that were present in CMA region.
+space memory except the user pages that were present in CMA region::
o Memory Reservation during first kernel
@@ -166,7 +169,7 @@ The tools to examine the dump will be same as the ones
used for kdump.
How to enable firmware-assisted dump (fadump):
--------------------------------------
+----------------------------------------------
1. Set config option CONFIG_FA_DUMP=y and build kernel.
2. Boot into linux kernel with 'fadump=on' kernel cmdline option.
@@ -177,19 +180,20 @@ How to enable firmware-assisted dump (fadump):
to specify size of the memory to reserve for boot memory dump
preservation.
-NOTE: 1. 'fadump_reserve_mem=' parameter has been deprecated. Instead
- use 'crashkernel=' to specify size of the memory to reserve
- for boot memory dump preservation.
- 2. If firmware-assisted dump fails to reserve memory then it
- will fallback to existing kdump mechanism if 'crashkernel='
- option is set at kernel cmdline.
- 3. if user wants to capture all of user space memory and ok with
- reserved memory not available to production system, then
- 'fadump=nocma' kernel parameter can be used to fallback to
- old behaviour.
+NOTE:
+ 1. 'fadump_reserve_mem=' parameter has been deprecated. Instead
+ use 'crashkernel=' to specify size of the memory to reserve
+ for boot memory dump preservation.
+ 2. If firmware-assisted dump fails to reserve memory then it
+ will fallback to existing kdump mechanism if 'crashkernel='
+ option is set at kernel cmdline.
+ 3. if user wants to capture all of user space memory and ok with
+ reserved memory not available to production system, then
+ 'fadump=nocma' kernel parameter can be used to fallback to
+ old behaviour.
Sysfs/debugfs files:
-------------
+--------------------
Firmware-assisted dump feature uses sysfs file system to hold
the control files and debugfs file to display memory reserved region.
@@ -197,20 +201,20 @@ the control files and debugfs file to display memory reserved region.
Here is the list of files under kernel sysfs:
/sys/kernel/fadump_enabled
-
This is used to display the fadump status.
- 0 = fadump is disabled
- 1 = fadump is enabled
+
+ - 0 = fadump is disabled
+ - 1 = fadump is enabled
This interface can be used by kdump init scripts to identify if
fadump is enabled in the kernel and act accordingly.
/sys/kernel/fadump_registered
-
This is used to display the fadump registration status as well
as to control (start/stop) the fadump registration.
- 0 = fadump is not registered.
- 1 = fadump is registered and ready to handle system crash.
+
+ - 0 = fadump is not registered.
+ - 1 = fadump is registered and ready to handle system crash.
To register fadump echo 1 > /sys/kernel/fadump_registered and
echo 0 > /sys/kernel/fadump_registered for un-register and stop the
@@ -219,13 +223,12 @@ Here is the list of files under kernel sysfs:
easily integrated with kdump service start/stop.
/sys/kernel/fadump_release_mem
-
This file is available only when fadump is active during
second kernel. This is used to release the reserved memory
region that are held for saving crash dump. To release the
- reserved memory echo 1 to it:
+ reserved memory echo 1 to it::
- echo 1 > /sys/kernel/fadump_release_mem
+ echo 1 > /sys/kernel/fadump_release_mem
After echo 1, the content of the /sys/kernel/debug/powerpc/fadump_region
file will change to reflect the new memory reservations.
@@ -238,38 +241,39 @@ Here is the list of files under powerpc debugfs:
(Assuming debugfs is mounted on /sys/kernel/debug directory.)
/sys/kernel/debug/powerpc/fadump_region
-
This file shows the reserved memory regions if fadump is
enabled otherwise this file is empty. The output format
- is:
- <region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>
+ is::
+
+ <region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>
e.g.
- Contents when fadump is registered during first kernel
+ Contents when fadump is registered during first kernel::
- # cat /sys/kernel/debug/powerpc/fadump_region
- CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0
- HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0
- DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0
+ # cat /sys/kernel/debug/powerpc/fadump_region
+ CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0
+ HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0
+ DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0
- Contents when fadump is active during second kernel
+ Contents when fadump is active during second kernel::
- # cat /sys/kernel/debug/powerpc/fadump_region
- CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020
- HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000
- DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000
- : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
+ # cat /sys/kernel/debug/powerpc/fadump_region
+ CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020
+ HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000
+ DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000
+ : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
-NOTE: Please refer to Documentation/filesystems/debugfs.txt on
+NOTE:
+ Please refer to Documentation/filesystems/debugfs.txt on
how to mount the debugfs filesystem.
TODO:
-----
- o Need to come up with the better approach to find out more
+ - Need to come up with the better approach to find out more
accurate boot memory size that is required for a kernel to
boot successfully when booted with restricted memory.
- o The fadump implementation introduces a fadump crash info structure
+ - The fadump implementation introduces a fadump crash info structure
in the scratch area before the ELF core header. The idea of introducing
this structure is to pass some important crash info data to the second
kernel which will help second kernel to populate ELF core header with
@@ -277,7 +281,9 @@ TODO:
design implementation does not address a possibility of introducing
additional fields (in future) to this structure without affecting
compatibility. Need to come up with the better approach to address this.
+
The possible approaches are:
+
1. Introduce version field for version tracking, bump up the version
whenever a new field is added to the structure in future. The version
field can be used to find out what fields are valid for the current
@@ -285,8 +291,11 @@ TODO:
2. Reserve the area of predefined size (say PAGE_SIZE) for this
structure and have unused area as reserved (initialized to zero)
for future field additions.
+
The advantage of approach 1 over 2 is we don't need to reserve extra space.
----
+
Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+
This document is based on the original documentation written for phyp
+
assisted dump by Linas Vepstas and Manish Ahuja.
diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.rst
index a730ca5a07f8..6808acde672f 100644
--- a/Documentation/powerpc/hvcs.txt
+++ b/Documentation/powerpc/hvcs.rst
@@ -1,19 +1,22 @@
-===========================================================================
- HVCS
- IBM "Hypervisor Virtual Console Server" Installation Guide
- for Linux Kernel 2.6.4+
- Copyright (C) 2004 IBM Corporation
+===============================================================
+HVCS IBM "Hypervisor Virtual Console Server" Installation Guide
+===============================================================
-===========================================================================
-NOTE:Eight space tabs are the optimum editor setting for reading this file.
-===========================================================================
+for Linux Kernel 2.6.4+
- Author(s) : Ryan S. Arnold <rsa@us.ibm.com>
- Date Created: March, 02, 2004
- Last Changed: August, 24, 2004
+Copyright (C) 2004 IBM Corporation
----------------------------------------------------------------------------
-Table of contents:
+.. ===========================================================================
+.. NOTE:Eight space tabs are the optimum editor setting for reading this file.
+.. ===========================================================================
+
+
+Author(s): Ryan S. Arnold <rsa@us.ibm.com>
+
+Date Created: March, 02, 2004
+Last Changed: August, 24, 2004
+
+.. Table of contents:
1. Driver Introduction:
2. System Requirements
@@ -27,8 +30,8 @@ Table of contents:
8. Questions & Answers:
9. Reporting Bugs:
----------------------------------------------------------------------------
1. Driver Introduction:
+=======================
This is the device driver for the IBM Hypervisor Virtual Console Server,
"hvcs". The IBM hvcs provides a tty driver interface to allow Linux user
@@ -38,8 +41,8 @@ ppc64 system. Physical hardware consoles per partition are not practical
on this hardware so system consoles are accessed by this driver using
firmware interfaces to virtual terminal devices.
----------------------------------------------------------------------------
2. System Requirements:
+=======================
This device driver was written using 2.6.4 Linux kernel APIs and will only
build and run on kernels of this version or later.
@@ -52,8 +55,8 @@ Sysfs must be mounted on the system so that the user can determine which
major and minor numbers are associated with each vty-server. Directions
for sysfs mounting are outside the scope of this document.
----------------------------------------------------------------------------
3. Build Options:
+=================
The hvcs driver registers itself as a tty driver. The tty layer
dynamically allocates a block of major and minor numbers in a quantity
@@ -65,11 +68,11 @@ If the default number of device entries is adequate then this driver can be
built into the kernel. If not, the default can be over-ridden by inserting
the driver as a module with insmod parameters.
----------------------------------------------------------------------------
3.1 Built-in:
+-------------
The following menuconfig example demonstrates selecting to build this
-driver into the kernel.
+driver into the kernel::
Device Drivers --->
Character devices --->
@@ -77,11 +80,11 @@ driver into the kernel.
Begin the kernel make process.
----------------------------------------------------------------------------
3.2 Module:
+-----------
The following menuconfig example demonstrates selecting to build this
-driver as a kernel module.
+driver as a kernel module::
Device Drivers --->
Character devices --->
@@ -89,11 +92,11 @@ driver as a kernel module.
The make process will build the following kernel modules:
- hvcs.ko
- hvcserver.ko
+ - hvcs.ko
+ - hvcserver.ko
To insert the module with the default allocation execute the following
-commands in the order they appear:
+commands in the order they appear::
insmod hvcserver.ko
insmod hvcs.ko
@@ -103,7 +106,7 @@ be inserted first, otherwise the hvcs module will not find some of the
symbols it expects.
To override the default use an insmod parameter as follows (requesting 4
-tty devices as an example):
+tty devices as an example)::
insmod hvcs.ko hvcs_parm_num_devs=4
@@ -115,31 +118,31 @@ source file before building.
NOTE: The length of time it takes to insmod the driver seems to be related
to the number of tty interfaces the registering driver requests.
-In order to remove the driver module execute the following command:
+In order to remove the driver module execute the following command::
rmmod hvcs.ko
The recommended method for installing hvcs as a module is to use depmod to
build a current modules.dep file in /lib/modules/`uname -r` and then
-execute:
+execute::
-modprobe hvcs hvcs_parm_num_devs=4
+ modprobe hvcs hvcs_parm_num_devs=4
The modules.dep file indicates that hvcserver.ko needs to be inserted
before hvcs.ko and modprobe uses this file to smartly insert the modules in
the proper order.
The following modprobe command is used to remove hvcs and hvcserver in the
-proper order:
+proper order::
-modprobe -r hvcs
+ modprobe -r hvcs
----------------------------------------------------------------------------
4. Installation:
+================
The tty layer creates sysfs entries which contain the major and minor
numbers allocated for the hvcs driver. The following snippet of "tree"
-output of the sysfs directory shows where these numbers are presented:
+output of the sysfs directory shows where these numbers are presented::
sys/
|-- *other sysfs base dirs*
@@ -164,7 +167,7 @@ output of the sysfs directory shows where these numbers are presented:
|-- *other sysfs base dirs*
For the above examples the following output is a result of cat'ing the
-"dev" entry in the hvcs directory:
+"dev" entry in the hvcs directory::
Pow5:/sys/class/tty/hvcs0/ # cat dev
254:0
@@ -184,7 +187,7 @@ systems running hvcs will already have the device entries created or udev
will do it automatically.
Given the example output above, to manually create a /dev/hvcs* node entry
-mknod can be used as follows:
+mknod can be used as follows::
mknod /dev/hvcs0 c 254 0
mknod /dev/hvcs1 c 254 1
@@ -195,15 +198,15 @@ Using mknod to manually create the device entries makes these device nodes
persistent. Once created they will exist prior to the driver insmod.
Attempting to connect an application to /dev/hvcs* prior to insertion of
-the hvcs module will result in an error message similar to the following:
+the hvcs module will result in an error message similar to the following::
"/dev/hvcs*: No such device".
NOTE: Just because there is a device node present doesn't mean that there
is a vty-server device configured for that node.
----------------------------------------------------------------------------
5. Connection
+=============
Since this driver controls devices that provide a tty interface a user can
interact with the device node entries using any standard tty-interactive
@@ -249,7 +252,7 @@ vty-server adapter is associated with which /dev/hvcs* node a special sysfs
attribute has been added to each vty-server sysfs entry. This entry is
called "index" and showing it reveals an integer that refers to the
/dev/hvcs* entry to use to connect to that device. For instance cating the
-index attribute of vty-server adapter 30000004 shows the following.
+index attribute of vty-server adapter 30000004 shows the following::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
2
@@ -262,8 +265,8 @@ system the /dev/hvcs* entry that interacts with a particular vty-server
adapter is not guaranteed to remain the same across system reboots. Look
in the Q & A section for more on this issue.
----------------------------------------------------------------------------
6. Disconnection
+================
As a security feature to prevent the delivery of stale data to an
unintended target the Power5 system firmware disables the fetching of data
@@ -305,7 +308,7 @@ connection between the vty-server and target vty ONLY if the vterm_state
previously read '1'. The write directive is ignored if the vterm_state
read '0' or if any value other than '0' was written to the vterm_state
attribute. The following example will show the method used for verifying
-the vty-server connection status and disconnecting a vty-server connection.
+the vty-server connection status and disconnecting a vty-server connection::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
1
@@ -318,12 +321,12 @@ the vty-server connection status and disconnecting a vty-server connection.
All vty-server connections are automatically terminated when the device is
hotplug removed and when the module is removed.
----------------------------------------------------------------------------
7. Configuration
+================
Each vty-server has a sysfs entry in the /sys/devices/vio directory, which
is symlinked in several other sysfs tree directories, notably under the
-hvcs driver entry, which looks like the following example:
+hvcs driver entry, which looks like the following example::
Pow5:/sys/bus/vio/drivers/hvcs # ls
. .. 30000003 30000004 rescan
@@ -344,7 +347,7 @@ completed or was never executed.
Vty-server entries in this directory are a 32 bit partition unique unit
address that is created by firmware. An example vty-server sysfs entry
-looks like the following:
+looks like the following::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
. current_vty devspec name partner_vtys
@@ -352,21 +355,21 @@ looks like the following:
Each entry is provided, by default with a "name" attribute. Reading the
"name" attribute will reveal the device type as shown in the following
-example:
+example::
Pow5:/sys/bus/vio/drivers/hvcs/30000003 # cat name
vty-server
Each entry is also provided, by default, with a "devspec" attribute which
reveals the full device specification when read, as shown in the following
-example:
+example::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat devspec
/vdevice/vty-server@30000004
Each vty-server sysfs dir is provided with two read-only attributes that
provide lists of easily parsed partner vty data: "partner_vtys" and
-"partner_clcs".
+"partner_clcs"::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_vtys
30000000
@@ -396,7 +399,7 @@ A vty-server can only be connected to a single vty at a time. The entry,
read.
The current_vty can be changed by writing a valid partner clc to the entry
-as in the following example:
+as in the following example::
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo U5112.428.10304
8A-V4-C0 > current_vty
@@ -408,9 +411,9 @@ currently open connection is freed.
Information on the "vterm_state" attribute was covered earlier on the
chapter entitled "disconnection".
----------------------------------------------------------------------------
8. Questions & Answers:
-===========================================================================
+=======================
+
Q: What are the security concerns involving hvcs?
A: There are three main security concerns:
@@ -429,6 +432,7 @@ A: There are three main security concerns:
partition) will experience the previously logged in session.
---------------------------------------------------------------------------
+
Q: How do I multiplex a console that I grab through hvcs so that other
people can see it:
@@ -440,6 +444,7 @@ term type "screen" to others. This means that curses based programs may
not display properly in screen sessions.
---------------------------------------------------------------------------
+
Q: Why are the colors all messed up?
Q: Why are the control characters acting strange or not working?
Q: Why is the console output all strange and unintelligible?
@@ -455,6 +460,7 @@ disconnect from the console. This will ensure that the next user gets
their own TERM type set when they login.
---------------------------------------------------------------------------
+
Q: When I try to CONNECT kermit to an hvcs device I get:
"Sorry, can't open connection: /dev/hvcs*"What is happening?
@@ -490,6 +496,7 @@ A: There is not a corresponding vty-server device that maps to an existing
/dev/hvcs* entry.
---------------------------------------------------------------------------
+
Q: When I try to CONNECT kermit to an hvcs device I get:
"Sorry, write access to UUCP lockfile directory denied."
@@ -497,6 +504,7 @@ A: The /dev/hvcs* entry you have specified doesn't exist where you said it
does? Maybe you haven't inserted the module (on systems with udev).
---------------------------------------------------------------------------
+
Q: If I already have one Linux partition installed can I use hvcs on said
partition to provide the console for the install of a second Linux
partition?
@@ -505,6 +513,7 @@ A: Yes granted that your are connected to the /dev/hvcs* device using
kermit or cu or some other program that doesn't provide terminal emulation.
---------------------------------------------------------------------------
+
Q: Can I connect to more than one partition's console at a time using this
driver?
@@ -512,6 +521,7 @@ A: Yes. Of course this means that there must be more than one vty-server
configured for this partition and each must point to a disconnected vty.
---------------------------------------------------------------------------
+
Q: Does the hvcs driver support dynamic (hotplug) addition of devices?
A: Yes, if you have dlpar and hotplug enabled for your system and it has
@@ -519,6 +529,7 @@ been built into the kernel the hvcs drivers is configured to dynamically
handle additions of new devices and removals of unused devices.
---------------------------------------------------------------------------
+
Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
after a reboot. What happened?
@@ -533,6 +544,7 @@ on how to determine which vty-server goes with which /dev/hvcs* node.
Hint; look at the sysfs "index" attribute for the vty-server.
---------------------------------------------------------------------------
+
Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
device on that partition as the other end of the pipe?
@@ -554,7 +566,9 @@ read or write to /dev/hvcs*. Now you have a tty conduit between two
partitions.
---------------------------------------------------------------------------
+
9. Reporting Bugs:
+==================
The proper channel for reporting bugs is either through the Linux OS
distribution company that provided your OS or by posting issues to the
diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst
new file mode 100644
index 000000000000..549b1cdd77ae
--- /dev/null
+++ b/Documentation/powerpc/index.rst
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+powerpc
+=======
+
+.. toctree::
+ :maxdepth: 1
+
+ bootwrapper
+ cpu_families
+ cpu_features
+ cxl
+ cxlflash
+ dawr-power9
+ dscr
+ eeh-pci-error-recovery
+ firmware-assisted-dump
+ hvcs
+ isa-versions
+ mpc52xx
+ pci_iov_resource_on_powernv
+ pmu-ebb
+ ptrace
+ qe_firmware
+ syscall64-abi
+ transactional_memory
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/powerpc/isa-versions.rst b/Documentation/powerpc/isa-versions.rst
index 66c24140ebf1..a363d8c1603c 100644
--- a/Documentation/powerpc/isa-versions.rst
+++ b/Documentation/powerpc/isa-versions.rst
@@ -1,13 +1,12 @@
-:orphan:
-
+==========================
CPU to ISA Version Mapping
==========================
Mapping of some CPU versions to relevant ISA versions.
-========= ====================
+========= ====================================================================
CPU Architecture version
-========= ====================
+========= ====================================================================
Power9 Power ISA v3.0B
Power8 Power ISA v2.07
Power7 Power ISA v2.06
@@ -24,7 +23,7 @@ PPC970 - PowerPC User Instruction Set Architecture Book I v2.01
- PowerPC Virtual Environment Architecture Book II v2.01
- PowerPC Operating Environment Architecture Book III v2.01
- Plus Altivec/VMX ~= 2.03
-========= ====================
+========= ====================================================================
Key Features
@@ -60,9 +59,9 @@ Power5 No
PPC970 No
========== ====
-========== ====================
+========== ====================================
CPU Transactional Memory
-========== ====================
+========== ====================================
Power9 Yes (* see transactional_memory.txt)
Power8 Yes
Power7 No
@@ -73,4 +72,4 @@ Power5++ No
Power5+ No
Power5 No
PPC970 No
-========== ====================
+========== ====================================
diff --git a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.rst
index 0d540a31ea1a..8676ac63e077 100644
--- a/Documentation/powerpc/mpc52xx.txt
+++ b/Documentation/powerpc/mpc52xx.rst
@@ -1,11 +1,13 @@
+=============================
Linux 2.6.x on MPC52xx family
------------------------------
+=============================
For the latest info, go to http://www.246tNt.com/mpc52xx/
To compile/use :
- - U-Boot:
+ - U-Boot::
+
# <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
if you wish to ).
# make lite5200_defconfig
@@ -16,7 +18,8 @@ To compile/use :
=> tftpboot 400000 pRamdisk
=> bootm 200000 400000
- - DBug:
+ - DBug::
+
# <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
if you wish to ).
# make lite5200_defconfig
@@ -28,7 +31,8 @@ To compile/use :
DBug> dn -i zImage.initrd.lite5200
-Some remarks :
+Some remarks:
+
- The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100
is not supported, and I'm not sure anyone is interesting in working on it
so. I didn't took 5xxx because there's apparently a lot of 5xxx that have
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.txt b/Documentation/powerpc/pci_iov_resource_on_powernv.rst
index b55c5cd83f8d..f5a5793e1613 100644
--- a/Documentation/powerpc/pci_iov_resource_on_powernv.txt
+++ b/Documentation/powerpc/pci_iov_resource_on_powernv.rst
@@ -1,6 +1,13 @@
+===================================================
+PCI Express I/O Virtualization Resource on Powerenv
+===================================================
+
Wei Yang <weiyang@linux.vnet.ibm.com>
+
Benjamin Herrenschmidt <benh@au1.ibm.com>
+
Bjorn Helgaas <bhelgaas@google.com>
+
26 Aug 2014
This document describes the requirement from hardware for PCI MMIO resource
@@ -10,6 +17,7 @@ Endpoints and the implementation on P8 (IODA2). The next two sections talks
about considerations on enabling SRIOV on IODA2.
1. Introduction to Partitionable Endpoints
+==========================================
A Partitionable Endpoint (PE) is a way to group the various resources
associated with a device or a set of devices to provide isolation between
@@ -35,6 +43,7 @@ is a completely separate HW entity that replicates the entire logic, so has
its own set of PEs, etc.
2. Implementation of Partitionable Endpoints on P8 (IODA2)
+==========================================================
P8 supports up to 256 Partitionable Endpoints per PHB.
@@ -149,6 +158,7 @@ P8 supports up to 256 Partitionable Endpoints per PHB.
sense, but we haven't done it yet.
3. Considerations for SR-IOV on PowerKVM
+========================================
* SR-IOV Background
@@ -224,7 +234,7 @@ P8 supports up to 256 Partitionable Endpoints per PHB.
IODA supports 256 PEs, so segmented windows contain 256 segments, so if
total_VFs is less than 256, we have the situation in Figure 1.0, where
segments [total_VFs, 255] of the M64 window may map to some MMIO range on
- other devices:
+ other devices::
0 1 total_VFs - 1
+------+------+- -+------+------+
@@ -243,7 +253,7 @@ P8 supports up to 256 Partitionable Endpoints per PHB.
Figure 1.0 Direct map VF(n) BAR space
Our current solution is to allocate 256 segments even if the VF(n) BAR
- space doesn't need that much, as shown in Figure 1.1:
+ space doesn't need that much, as shown in Figure 1.1::
0 1 total_VFs - 1 255
+------+------+- -+------+------+- -+------+------+
@@ -269,6 +279,7 @@ P8 supports up to 256 Partitionable Endpoints per PHB.
responds to segments [total_VFs, 255].
4. Implications for the Generic PCI Code
+========================================
The PCIe SR-IOV spec requires that the base of the VF(n) BAR space be
aligned to the size of an individual VF BAR.
diff --git a/Documentation/powerpc/pmu-ebb.txt b/Documentation/powerpc/pmu-ebb.rst
index 73cd163dbfb8..4f474758eb55 100644
--- a/Documentation/powerpc/pmu-ebb.txt
+++ b/Documentation/powerpc/pmu-ebb.rst
@@ -1,3 +1,4 @@
+========================
PMU Event Based Branches
========================
diff --git a/Documentation/powerpc/ptrace.rst b/Documentation/powerpc/ptrace.rst
new file mode 100644
index 000000000000..864d4b6dddd1
--- /dev/null
+++ b/Documentation/powerpc/ptrace.rst
@@ -0,0 +1,156 @@
+======
+Ptrace
+======
+
+GDB intends to support the following hardware debug features of BookE
+processors:
+
+4 hardware breakpoints (IAC)
+2 hardware watchpoints (read, write and read-write) (DAC)
+2 value conditions for the hardware watchpoints (DVC)
+
+For that, we need to extend ptrace so that GDB can query and set these
+resources. Since we're extending, we're trying to create an interface
+that's extendable and that covers both BookE and server processors, so
+that GDB doesn't need to special-case each of them. We added the
+following 3 new ptrace requests.
+
+1. PTRACE_PPC_GETHWDEBUGINFO
+============================
+
+Query for GDB to discover the hardware debug features. The main info to
+be returned here is the minimum alignment for the hardware watchpoints.
+BookE processors don't have restrictions here, but server processors have
+an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
+adding special cases to GDB based on what it sees in AUXV.
+
+Since we're at it, we added other useful info that the kernel can return to
+GDB: this query will return the number of hardware breakpoints, hardware
+watchpoints and whether it supports a range of addresses and a condition.
+The query will fill the following structure provided by the requesting process::
+
+ struct ppc_debug_info {
+ unit32_t version;
+ unit32_t num_instruction_bps;
+ unit32_t num_data_bps;
+ unit32_t num_condition_regs;
+ unit32_t data_bp_alignment;
+ unit32_t sizeof_condition; /* size of the DVC register */
+ uint64_t features; /* bitmask of the individual flags */
+ };
+
+features will have bits indicating whether there is support for::
+
+ #define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x1
+ #define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x2
+ #define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x4
+ #define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x8
+ #define PPC_DEBUG_FEATURE_DATA_BP_DAWR 0x10
+
+2. PTRACE_SETHWDEBUG
+
+Sets a hardware breakpoint or watchpoint, according to the provided structure::
+
+ struct ppc_hw_breakpoint {
+ uint32_t version;
+ #define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x1
+ #define PPC_BREAKPOINT_TRIGGER_READ 0x2
+ #define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
+ uint32_t trigger_type; /* only some combinations allowed */
+ #define PPC_BREAKPOINT_MODE_EXACT 0x0
+ #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x1
+ #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x2
+ #define PPC_BREAKPOINT_MODE_MASK 0x3
+ uint32_t addr_mode; /* address match mode */
+
+ #define PPC_BREAKPOINT_CONDITION_MODE 0x3
+ #define PPC_BREAKPOINT_CONDITION_NONE 0x0
+ #define PPC_BREAKPOINT_CONDITION_AND 0x1
+ #define PPC_BREAKPOINT_CONDITION_EXACT 0x1 /* different name for the same thing as above */
+ #define PPC_BREAKPOINT_CONDITION_OR 0x2
+ #define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
+ #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000 /* byte enable bits */
+ #define PPC_BREAKPOINT_CONDITION_BE(n) (1<<((n)+16))
+ uint32_t condition_mode; /* break/watchpoint condition flags */
+
+ uint64_t addr;
+ uint64_t addr2;
+ uint64_t condition_value;
+ };
+
+A request specifies one event, not necessarily just one register to be set.
+For instance, if the request is for a watchpoint with a condition, both the
+DAC and DVC registers will be set in the same request.
+
+With this GDB can ask for all kinds of hardware breakpoints and watchpoints
+that the BookE supports. COMEFROM breakpoints available in server processors
+are not contemplated, but that is out of the scope of this work.
+
+ptrace will return an integer (handle) uniquely identifying the breakpoint or
+watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
+request to ask for its removal. Return -ENOSPC if the requested breakpoint
+can't be allocated on the registers.
+
+Some examples of using the structure to:
+
+- set a breakpoint in the first breakpoint register::
+
+ p.version = PPC_DEBUG_CURRENT_VERSION;
+ p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+ p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
+ p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
+ p.addr = (uint64_t) address;
+ p.addr2 = 0;
+ p.condition_value = 0;
+
+- set a watchpoint which triggers on reads in the second watchpoint register::
+
+ p.version = PPC_DEBUG_CURRENT_VERSION;
+ p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
+ p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
+ p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
+ p.addr = (uint64_t) address;
+ p.addr2 = 0;
+ p.condition_value = 0;
+
+- set a watchpoint which triggers only with a specific value::
+
+ p.version = PPC_DEBUG_CURRENT_VERSION;
+ p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
+ p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
+ p.condition_mode = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
+ p.addr = (uint64_t) address;
+ p.addr2 = 0;
+ p.condition_value = (uint64_t) condition;
+
+- set a ranged hardware breakpoint::
+
+ p.version = PPC_DEBUG_CURRENT_VERSION;
+ p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+ p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+ p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
+ p.addr = (uint64_t) begin_range;
+ p.addr2 = (uint64_t) end_range;
+ p.condition_value = 0;
+
+- set a watchpoint in server processors (BookS)::
+
+ p.version = 1;
+ p.trigger_type = PPC_BREAKPOINT_TRIGGER_RW;
+ p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+ or
+ p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
+
+ p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
+ p.addr = (uint64_t) begin_range;
+ /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
+ * addr2 - addr <= 8 Bytes.
+ */
+ p.addr2 = (uint64_t) end_range;
+ p.condition_value = 0;
+
+3. PTRACE_DELHWDEBUG
+
+Takes an integer which identifies an existing breakpoint or watchpoint
+(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
+corresponding breakpoint or watchpoint..
diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt
deleted file mode 100644
index 99c5ce88d0fe..000000000000
--- a/Documentation/powerpc/ptrace.txt
+++ /dev/null
@@ -1,151 +0,0 @@
-GDB intends to support the following hardware debug features of BookE
-processors:
-
-4 hardware breakpoints (IAC)
-2 hardware watchpoints (read, write and read-write) (DAC)
-2 value conditions for the hardware watchpoints (DVC)
-
-For that, we need to extend ptrace so that GDB can query and set these
-resources. Since we're extending, we're trying to create an interface
-that's extendable and that covers both BookE and server processors, so
-that GDB doesn't need to special-case each of them. We added the
-following 3 new ptrace requests.
-
-1. PTRACE_PPC_GETHWDEBUGINFO
-
-Query for GDB to discover the hardware debug features. The main info to
-be returned here is the minimum alignment for the hardware watchpoints.
-BookE processors don't have restrictions here, but server processors have
-an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
-adding special cases to GDB based on what it sees in AUXV.
-
-Since we're at it, we added other useful info that the kernel can return to
-GDB: this query will return the number of hardware breakpoints, hardware
-watchpoints and whether it supports a range of addresses and a condition.
-The query will fill the following structure provided by the requesting process:
-
-struct ppc_debug_info {
- unit32_t version;
- unit32_t num_instruction_bps;
- unit32_t num_data_bps;
- unit32_t num_condition_regs;
- unit32_t data_bp_alignment;
- unit32_t sizeof_condition; /* size of the DVC register */
- uint64_t features; /* bitmask of the individual flags */
-};
-
-features will have bits indicating whether there is support for:
-
-#define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x1
-#define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x2
-#define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x4
-#define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x8
-#define PPC_DEBUG_FEATURE_DATA_BP_DAWR 0x10
-
-2. PTRACE_SETHWDEBUG
-
-Sets a hardware breakpoint or watchpoint, according to the provided structure:
-
-struct ppc_hw_breakpoint {
- uint32_t version;
-#define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x1
-#define PPC_BREAKPOINT_TRIGGER_READ 0x2
-#define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
- uint32_t trigger_type; /* only some combinations allowed */
-#define PPC_BREAKPOINT_MODE_EXACT 0x0
-#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x1
-#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x2
-#define PPC_BREAKPOINT_MODE_MASK 0x3
- uint32_t addr_mode; /* address match mode */
-
-#define PPC_BREAKPOINT_CONDITION_MODE 0x3
-#define PPC_BREAKPOINT_CONDITION_NONE 0x0
-#define PPC_BREAKPOINT_CONDITION_AND 0x1
-#define PPC_BREAKPOINT_CONDITION_EXACT 0x1 /* different name for the same thing as above */
-#define PPC_BREAKPOINT_CONDITION_OR 0x2
-#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
-#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000 /* byte enable bits */
-#define PPC_BREAKPOINT_CONDITION_BE(n) (1<<((n)+16))
- uint32_t condition_mode; /* break/watchpoint condition flags */
-
- uint64_t addr;
- uint64_t addr2;
- uint64_t condition_value;
-};
-
-A request specifies one event, not necessarily just one register to be set.
-For instance, if the request is for a watchpoint with a condition, both the
-DAC and DVC registers will be set in the same request.
-
-With this GDB can ask for all kinds of hardware breakpoints and watchpoints
-that the BookE supports. COMEFROM breakpoints available in server processors
-are not contemplated, but that is out of the scope of this work.
-
-ptrace will return an integer (handle) uniquely identifying the breakpoint or
-watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
-request to ask for its removal. Return -ENOSPC if the requested breakpoint
-can't be allocated on the registers.
-
-Some examples of using the structure to:
-
-- set a breakpoint in the first breakpoint register
-
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) address;
- p.addr2 = 0;
- p.condition_value = 0;
-
-- set a watchpoint which triggers on reads in the second watchpoint register
-
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) address;
- p.addr2 = 0;
- p.condition_value = 0;
-
-- set a watchpoint which triggers only with a specific value
-
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_READ;
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
- p.addr = (uint64_t) address;
- p.addr2 = 0;
- p.condition_value = (uint64_t) condition;
-
-- set a ranged hardware breakpoint
-
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
- p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) begin_range;
- p.addr2 = (uint64_t) end_range;
- p.condition_value = 0;
-
-- set a watchpoint in server processors (BookS)
-
- p.version = 1;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_RW;
- p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
- or
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
-
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) begin_range;
- /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
- * addr2 - addr <= 8 Bytes.
- */
- p.addr2 = (uint64_t) end_range;
- p.condition_value = 0;
-
-3. PTRACE_DELHWDEBUG
-
-Takes an integer which identifies an existing breakpoint or watchpoint
-(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
-corresponding breakpoint or watchpoint..
diff --git a/Documentation/powerpc/qe_firmware.txt b/Documentation/powerpc/qe_firmware.rst
index e7ac24aec4ff..42f5103140c9 100644
--- a/Documentation/powerpc/qe_firmware.txt
+++ b/Documentation/powerpc/qe_firmware.rst
@@ -1,23 +1,23 @@
- Freescale QUICC Engine Firmware Uploading
- -----------------------------------------
+=========================================
+Freescale QUICC Engine Firmware Uploading
+=========================================
(c) 2007 Timur Tabi <timur at freescale.com>,
Freescale Semiconductor
-Table of Contents
-=================
+.. Table of Contents
- I - Software License for Firmware
+ I - Software License for Firmware
- II - Microcode Availability
+ II - Microcode Availability
- III - Description and Terminology
+ III - Description and Terminology
- IV - Microcode Programming Details
+ IV - Microcode Programming Details
- V - Firmware Structure Layout
+ V - Firmware Structure Layout
- VI - Sample Code for Creating Firmware Files
+ VI - Sample Code for Creating Firmware Files
Revision Information
====================
@@ -39,7 +39,7 @@ http://opensource.freescale.com. For other firmware files, please contact
your Freescale representative or your operating system vendor.
III - Description and Terminology
-================================
+=================================
In this document, the term 'microcode' refers to the sequence of 32-bit
integers that compose the actual QE microcode.
@@ -89,7 +89,7 @@ being fixed in the RAM package utilizing they should be activated. This data
structure signals the microcode which of these virtual traps is active.
This structure contains 6 words that the application should copy to some
-specific been defined. This table describes the structure.
+specific been defined. This table describes the structure::
---------------------------------------------------------------
| Offset in | | Destination Offset | Size of |
@@ -119,7 +119,7 @@ Extended Modes
This is a double word bit array (64 bits) that defines special functionality
which has an impact on the software drivers. Each bit has its own impact
and has special instructions for the s/w associated with it. This structure is
-described in this table:
+described in this table::
-----------------------------------------------------------------------
| Bit # | Name | Description |
@@ -220,7 +220,8 @@ The 'model' field is a 16-bit number that matches the actual SOC. The
'major' and 'minor' fields are the major and minor revision numbers,
respectively, of the SOC.
-For example, to match the 8323, revision 1.0:
+For example, to match the 8323, revision 1.0::
+
soc.model = 8323
soc.major = 1
soc.minor = 0
@@ -273,10 +274,10 @@ library and available to any driver that calles qe_get_firmware_info().
'reserved'.
After the last microcode is a 32-bit CRC. It can be calculated using
-this algorithm:
+this algorithm::
-u32 crc32(const u8 *p, unsigned int len)
-{
+ u32 crc32(const u8 *p, unsigned int len)
+ {
unsigned int i;
u32 crc = 0;
@@ -286,7 +287,7 @@ u32 crc32(const u8 *p, unsigned int len)
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
}
return crc;
-}
+ }
VI - Sample Code for Creating Firmware Files
============================================
diff --git a/Documentation/powerpc/syscall64-abi.txt b/Documentation/powerpc/syscall64-abi.rst
index fa716a0d88bd..e49f69f941b9 100644
--- a/Documentation/powerpc/syscall64-abi.txt
+++ b/Documentation/powerpc/syscall64-abi.rst
@@ -5,12 +5,12 @@ Power Architecture 64-bit Linux system call ABI
syscall
=======
-syscall calling sequence[*] matches the Power Architecture 64-bit ELF ABI
+syscall calling sequence\ [1]_ matches the Power Architecture 64-bit ELF ABI
specification C function calling sequence, including register preservation
rules, with the following differences.
-[*] Some syscalls (typically low-level management functions) may have
- different calling sequences (e.g., rt_sigreturn).
+.. [1] Some syscalls (typically low-level management functions) may have
+ different calling sequences (e.g., rt_sigreturn).
Parameters and return value
---------------------------
@@ -33,12 +33,14 @@ Register preservation rules
Register preservation rules match the ELF ABI calling sequence with the
following differences:
-r0: Volatile. (System call number.)
-r3: Volatile. (Parameter 1, and return value.)
-r4-r8: Volatile. (Parameters 2-6.)
-cr0: Volatile (cr0.SO is the return error condition)
-cr1, cr5-7: Nonvolatile.
-lr: Nonvolatile.
+=========== ============= ========================================
+r0 Volatile (System call number.)
+r3 Volatile (Parameter 1, and return value.)
+r4-r8 Volatile (Parameters 2-6.)
+cr0 Volatile (cr0.SO is the return error condition)
+cr1, cr5-7 Nonvolatile
+lr Nonvolatile
+=========== ============= ========================================
All floating point and vector data registers as well as control and status
registers are nonvolatile.
@@ -90,9 +92,12 @@ The vsyscall may or may not use the caller's stack frame save areas.
Register preservation rules
---------------------------
-r0: Volatile.
-cr1, cr5-7: Volatile.
-lr: Volatile.
+
+=========== ========
+r0 Volatile
+cr1, cr5-7 Volatile
+lr Volatile
+=========== ========
Invocation
----------
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.rst
index 52c023e14f26..09955103acb4 100644
--- a/Documentation/powerpc/transactional_memory.txt
+++ b/Documentation/powerpc/transactional_memory.rst
@@ -1,3 +1,4 @@
+============================
Transactional Memory support
============================
@@ -17,29 +18,29 @@ instructions are presented to delimit transactions; transactions are
guaranteed to either complete atomically or roll back and undo any partial
changes.
-A simple transaction looks like this:
+A simple transaction looks like this::
-begin_move_money:
- tbegin
- beq abort_handler
+ begin_move_money:
+ tbegin
+ beq abort_handler
- ld r4, SAVINGS_ACCT(r3)
- ld r5, CURRENT_ACCT(r3)
- subi r5, r5, 1
- addi r4, r4, 1
- std r4, SAVINGS_ACCT(r3)
- std r5, CURRENT_ACCT(r3)
+ ld r4, SAVINGS_ACCT(r3)
+ ld r5, CURRENT_ACCT(r3)
+ subi r5, r5, 1
+ addi r4, r4, 1
+ std r4, SAVINGS_ACCT(r3)
+ std r5, CURRENT_ACCT(r3)
- tend
+ tend
- b continue
+ b continue
-abort_handler:
- ... test for odd failures ...
+ abort_handler:
+ ... test for odd failures ...
- /* Retry the transaction if it failed because it conflicted with
- * someone else: */
- b begin_move_money
+ /* Retry the transaction if it failed because it conflicted with
+ * someone else: */
+ b begin_move_money
The 'tbegin' instruction denotes the start point, and 'tend' the end point.
@@ -123,7 +124,7 @@ Transaction-aware signal handlers can read the transactional register state
from the second ucontext. This will be necessary for crash handlers to
determine, for example, the address of the instruction causing the SIGSEGV.
-Example signal handler:
+Example signal handler::
void crash_handler(int sig, siginfo_t *si, void *uc)
{
@@ -133,9 +134,9 @@ Example signal handler:
if (ucp_link) {
u64 msr = ucp->uc_mcontext.regs->msr;
/* May have transactional ucontext! */
-#ifndef __powerpc64__
+ #ifndef __powerpc64__
msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
-#endif
+ #endif
if (MSR_TM_ACTIVE(msr)) {
/* Yes, we crashed during a transaction. Oops. */
fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
@@ -176,6 +177,7 @@ Failure cause codes used by kernel
These are defined in <asm/reg.h>, and distinguish different reasons why the
kernel aborted a transaction:
+ ====================== ================================
TM_CAUSE_RESCHED Thread was rescheduled.
TM_CAUSE_TLBI Software TLB invalid.
TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap.
@@ -184,6 +186,7 @@ kernel aborted a transaction:
TM_CAUSE_MISC Currently unused.
TM_CAUSE_ALIGNMENT Alignment fault.
TM_CAUSE_EMULATE Emulation that touched memory.
+ ====================== ================================
These can be checked by the user program's abort handler as TEXASR[0:7]. If
bit 7 is set, it indicates that the error is consider persistent. For example
@@ -203,7 +206,7 @@ POWER9
======
TM on POWER9 has issues with storing the complete register state. This
-is described in this commit:
+is described in this commit::
commit 4bb3c7a0208fc13ca70598efd109901a7cd45ae7
Author: Paul Mackerras <paulus@ozlabs.org>
diff --git a/Documentation/process/conf.py b/Documentation/process/conf.py
deleted file mode 100644
index 1b01a80ad9ce..000000000000
--- a/Documentation/process/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Development Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'process.tex', 'Linux Kernel Development Documentation',
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/process/deprecated.rst b/Documentation/process/deprecated.rst
index 49e0f64a3427..053b24a6dd38 100644
--- a/Documentation/process/deprecated.rst
+++ b/Documentation/process/deprecated.rst
@@ -119,3 +119,17 @@ array may exceed the remaining memory in the stack segment. This could
lead to a crash, possible overwriting sensitive contents at the end of the
stack (when built without `CONFIG_THREAD_INFO_IN_TASK=y`), or overwriting
memory adjacent to the stack (when built without `CONFIG_VMAP_STACK=y`)
+
+Implicit switch case fall-through
+---------------------------------
+The C language allows switch cases to "fall through" when
+a "break" statement is missing at the end of a case. This,
+however, introduces ambiguity in the code, as it's not always
+clear if the missing break is intentional or a bug. As there
+have been a long list of flaws `due to missing "break" statements
+<https://cwe.mitre.org/data/definitions/484.html>`_, we no longer allow
+"implicit fall-through". In order to identify an intentional fall-through
+case, we have adopted the marking used by static analyzers: a comment
+saying `/* Fall through */`. Once the C++17 `__attribute__((fallthrough))`
+is more widely handled by C compilers, static analyzers, and IDEs, we can
+switch to using that instead.
diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..402636356fbe
--- /dev/null
+++ b/Documentation/process/embargoed-hardware-issues.rst
@@ -0,0 +1,279 @@
+Embargoed hardware issues
+=========================
+
+Scope
+-----
+
+Hardware issues which result in security problems are a different category
+of security bugs than pure software bugs which only affect the Linux
+kernel.
+
+Hardware issues like Meltdown, Spectre, L1TF etc. must be treated
+differently because they usually affect all Operating Systems ("OS") and
+therefore need coordination across different OS vendors, distributions,
+hardware vendors and other parties. For some of the issues, software
+mitigations can depend on microcode or firmware updates, which need further
+coordination.
+
+.. _Contact:
+
+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
+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.
+
+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
+certificate. The list's PGP key and S/MIME certificate are available from
+https://www.kernel.org/....
+
+While hardware security issues are often handled by the affected hardware
+vendor, we welcome contact from researchers or individuals who have
+identified a potential hardware flaw.
+
+Hardware security officers
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The current team of hardware security officers:
+
+ - Linus Torvalds (Linux Foundation Fellow)
+ - Greg Kroah-Hartman (Linux Foundation Fellow)
+ - Thomas Gleixner (Linux Foundation Fellow)
+
+Operation of mailing-lists
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The encrypted mailing-lists which are used in our process are hosted on
+Linux Foundation's IT infrastructure. By providing this service Linux
+Foundation's director of IT Infrastructure security technically has the
+ability to access the embargoed information, but is obliged to
+confidentiality by his employment contract. Linux Foundation's director of
+IT Infrastructure security is also responsible for the kernel.org
+infrastructure.
+
+The Linux Foundation's current director of IT Infrastructure security is
+Konstantin Ryabitsev.
+
+
+Non-disclosure agreements
+-------------------------
+
+The Linux kernel hardware security team is not a formal body and therefore
+unable to enter into any non-disclosure agreements. The kernel community
+is aware of the sensitive nature of such issues and offers a Memorandum of
+Understanding instead.
+
+
+Memorandum of Understanding
+---------------------------
+
+The Linux kernel community has a deep understanding of the requirement to
+keep hardware security issues under embargo for coordination between
+different OS vendors, distributors, hardware vendors and other parties.
+
+The Linux kernel community has successfully handled hardware security
+issues in the past and has the necessary mechanisms in place to allow
+community compliant development under embargo restrictions.
+
+The Linux kernel community has a dedicated hardware security team for
+initial contact, which oversees the process of handling such issues under
+embargo rules.
+
+The hardware security team identifies the developers (domain experts) who
+will form the initial response team for a particular issue. The initial
+response team can bring in further developers (domain experts) to address
+the issue in the best technical way.
+
+All involved developers pledge to adhere to the embargo rules and to keep
+the received information confidential. Violation of the pledge will lead to
+immediate exclusion from the current issue and removal from all related
+mailing-lists. In addition, the hardware security team will also exclude
+the offender from future issues. The impact of this consequence is a highly
+effective deterrent in our community. In case a violation happens the
+hardware security team will inform the involved parties immediately. If you
+or anyone becomes aware of a potential violation, please report it
+immediately to the Hardware security officers.
+
+
+Process
+^^^^^^^
+
+Due to the globally distributed nature of Linux kernel development,
+face-to-face meetings are almost impossible to address hardware security
+issues. Phone conferences are hard to coordinate due to time zones and
+other factors and should be only used when absolutely necessary. Encrypted
+email has been proven to be the most effective and secure communication
+method for these types of issues.
+
+Start of Disclosure
+"""""""""""""""""""
+
+Disclosure starts by contacting the Linux kernel hardware security team by
+email. This initial contact should contain a description of the problem and
+a list of any known affected hardware. If your organization builds or
+distributes the affected hardware, we encourage you to also consider what
+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.
+
+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
+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
+response team, but is not necessarily involved in the mitigation
+development process.
+
+While individual developers might be covered by a non-disclosure agreement
+via their employer, they cannot enter individual non-disclosure agreements
+in their role as Linux kernel developers. They will, however, agree to
+adhere to this documented process and the Memorandum of Understanding.
+
+
+Disclosure
+""""""""""
+
+The disclosing party provides detailed information to the initial response
+team via the specific encrypted mailing-list.
+
+From our experience the technical documentation of these issues is usually
+a sufficient starting point and further technical clarification is best
+done via email.
+
+Mitigation development
+""""""""""""""""""""""
+
+The initial response team sets up an encrypted mailing-list or repurposes
+an existing one if appropriate. The disclosing party should provide a list
+of contacts for all other parties who have already been, or should be,
+informed about the issue. The response team contacts these parties so they
+can name experts who should be subscribed to the mailing-list.
+
+Using a mailing-list is close to the normal Linux development process and
+has been successfully used in developing mitigations for various hardware
+security issues in the past.
+
+The mailing-list operates in the same way as normal Linux development.
+Patches are posted, discussed and reviewed and if agreed on applied to a
+non-public git repository which is only accessible to the participating
+developers via a secure connection. The repository contains the main
+development branch against the mainline kernel and backport branches for
+stable kernel versions as necessary.
+
+The initial response team will identify further experts from the Linux
+kernel developer community as needed and inform the disclosing party about
+their participation. Bringing in experts can happen at any time of the
+development process and often needs to be handled in a timely manner.
+
+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.
+
+While we understand that hardware security issues need coordinated embargo
+time, the embargo time should be constrained to the minimum time which is
+required for all involved parties to develop, test and prepare the
+mitigations. Extending embargo time artificially to meet conference talk
+dates or other non-technical reasons is creating more work and burden for
+the involved developers and response teams as the patches need to be kept
+up to date in order to follow the ongoing upstream kernel development,
+which might create conflicting changes.
+
+CVE assignment
+""""""""""""""
+
+Neither the hardware security team nor the initial response team assign
+CVEs, nor are CVEs required for the development process. If CVEs are
+provided by the disclosing party they can be used for documentation
+purposes.
+
+Process ambassadors
+-------------------
+
+For assistance with this process we have established ambassadors in various
+organizations, who can answer questions about or provide guidance on the
+reporting process and further handling. Ambassadors are not involved in the
+disclosure of a particular issue, unless requested by a response team or by
+an involved disclosed party. The current ambassadors list:
+
+ ============= ========================================================
+ ARM
+ AMD
+ IBM
+ Intel
+ Qualcomm Trilok Soni <tsoni@codeaurora.org>
+
+ Microsoft Sasha Levin <sashal@kernel.org>
+ VMware
+ Xen Andrew Cooper <andrew.cooper3@citrix.com>
+
+ Canonical Tyler Hicks <tyhicks@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>
+
+ Amazon
+ Google Kees Cook <keescook@chromium.org>
+ ============= ========================================================
+
+If you want your organization to be added to the ambassadors list, please
+contact the hardware security team. The nominated ambassador has to
+understand and support our process fully and is ideally well connected in
+the Linux kernel community.
+
+Encrypted mailing-lists
+-----------------------
+
+We use encrypted mailing-lists for communication. The operating principle
+of these lists is that email sent to the list is encrypted either with the
+list's PGP key or with the list's S/MIME certificate. The mailing-list
+software decrypts the email and re-encrypts it individually for each
+subscriber with the subscriber's PGP key or S/MIME certificate. Details
+about the mailing-list software and the setup which is used to ensure the
+security of the lists and protection of the data can be found here:
+https://www.kernel.org/....
+
+List keys
+^^^^^^^^^
+
+For initial contact see :ref:`Contact`. For incident specific mailing-lists
+the key and S/MIME certificate are conveyed to the subscribers by email
+sent from the specific list.
+
+Subscription to incident specific lists
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Subscription is handled by the response teams. Disclosed parties who want
+to participate in the communication send a list of potential subscribers to
+the response team so the response team can validate subscription requests.
+
+Each subscriber needs to send a subscription request to the response team
+by email. The email must be signed with the subscriber's PGP key or S/MIME
+certificate. If a PGP key is used, it must be available from a public key
+server and is ideally connected to the Linux kernel's PGP web of trust. See
+also: https://www.kernel.org/signature.html.
+
+The response team verifies that the subscriber request is valid and adds
+the subscriber to the list. After subscription the subscriber will receive
+email from the mailing-list which is signed either with the list's PGP key
+or the list's S/MIME certificate. The subscriber's email client can extract
+the PGP key or the S/MIME certificate from the signature so the subscriber
+can send encrypted email to the list.
+
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
index 878ebfda7eef..e2c9ffc682c5 100644
--- a/Documentation/process/index.rst
+++ b/Documentation/process/index.rst
@@ -45,6 +45,7 @@ Other guides to the community that are of interest to most developers are:
submit-checklist
kernel-docs
deprecated
+ embargoed-hardware-issues
These are some overall technical guides that have been put here for now for
lack of a better place.
diff --git a/Documentation/riscv/boot-image-header.txt b/Documentation/riscv/boot-image-header.txt
index 1b73fea23b39..14b1492f689b 100644
--- a/Documentation/riscv/boot-image-header.txt
+++ b/Documentation/riscv/boot-image-header.txt
@@ -18,7 +18,7 @@ The following 64-byte header is present in decompressed Linux kernel image.
u32 res1 = 0; /* Reserved */
u64 res2 = 0; /* Reserved */
u64 magic = 0x5643534952; /* Magic number, little endian, "RISCV" */
- u32 res3; /* Reserved for additional RISC-V specific header */
+ u32 magic2 = 0x56534905; /* Magic number 2, little endian, "RSC\x05" */
u32 res4; /* Reserved for PE COFF offset */
This header format is compliant with PE/COFF header and largely inspired from
@@ -37,13 +37,14 @@ Notes:
Bits 16:31 - Major version
This preserves compatibility across newer and older version of the header.
- The current version is defined as 0.1.
+ The current version is defined as 0.2.
-- res3 is reserved for offset to any other additional fields. This makes the
- header extendible in future. One example would be to accommodate ISA
- extension for RISC-V in future. For current version, it is set to be zero.
+- The "magic" field is deprecated as of version 0.2. In a future
+ release, it may be removed. This originally should have matched up
+ with the ARM64 header "magic" field, but unfortunately does not.
+ The "magic2" field replaces it, matching up with the ARM64 header.
-- In current header, the flag field has only one field.
+- In current header, the flags field has only one field.
Bit 0: Kernel endianness. 1 if BE, 0 if LE.
- Image size is mandatory for boot loader to load kernel image. Booting will
diff --git a/Documentation/s390/vfio-ccw.rst b/Documentation/s390/vfio-ccw.rst
index 1e210c6afa88..fca9c4f5bd9c 100644
--- a/Documentation/s390/vfio-ccw.rst
+++ b/Documentation/s390/vfio-ccw.rst
@@ -180,6 +180,13 @@ The process of how these work together.
add it to an iommu_group and a vfio_group. Then we could pass through
the mdev to a guest.
+
+VFIO-CCW Regions
+----------------
+
+The vfio-ccw driver exposes MMIO regions to accept requests from and return
+results to userspace.
+
vfio-ccw I/O region
-------------------
@@ -205,6 +212,25 @@ irb_area stores the I/O result.
ret_code stores a return code for each access of the region.
+This region is always available.
+
+vfio-ccw cmd region
+-------------------
+
+The vfio-ccw cmd region is used to accept asynchronous instructions
+from userspace::
+
+ #define VFIO_CCW_ASYNC_CMD_HSCH (1 << 0)
+ #define VFIO_CCW_ASYNC_CMD_CSCH (1 << 1)
+ struct ccw_cmd_region {
+ __u32 command;
+ __u32 ret_code;
+ } __packed;
+
+This region is exposed via region type VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD.
+
+Currently, CLEAR SUBCHANNEL and HALT SUBCHANNEL use this region.
+
vfio-ccw operation details
--------------------------
@@ -306,9 +332,8 @@ Together with the corresponding work in QEMU, we can bring the passed
through DASD/ECKD device online in a guest now and use it as a block
device.
-While the current code allows the guest to start channel programs via
-START SUBCHANNEL, support for HALT SUBCHANNEL or CLEAR SUBCHANNEL is
-not yet implemented.
+The current code allows the guest to start channel programs via
+START SUBCHANNEL, and to issue HALT SUBCHANNEL and CLEAR SUBCHANNEL.
vfio-ccw supports classic (command mode) channel I/O only. Transport
mode (HPF) is not supported.
diff --git a/Documentation/scheduler/sched-bwc.rst b/Documentation/scheduler/sched-bwc.rst
index 3a9064219656..9801d6b284b1 100644
--- a/Documentation/scheduler/sched-bwc.rst
+++ b/Documentation/scheduler/sched-bwc.rst
@@ -9,15 +9,16 @@ CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the
specification of the maximum CPU bandwidth available to a group or hierarchy.
The bandwidth allowed for a group is specified using a quota and period. Within
-each given "period" (microseconds), a group is allowed to consume only up to
-"quota" microseconds of CPU time. When the CPU bandwidth consumption of a
-group exceeds this limit (for that period), the tasks belonging to its
-hierarchy will be throttled and are not allowed to run again until the next
-period.
-
-A group's unused runtime is globally tracked, being refreshed with quota units
-above at each period boundary. As threads consume this bandwidth it is
-transferred to cpu-local "silos" on a demand basis. The amount transferred
+each given "period" (microseconds), a task group is allocated up to "quota"
+microseconds of CPU time. That quota is assigned to per-cpu run queues in
+slices as threads in the cgroup become runnable. Once all quota has been
+assigned any additional requests for quota will result in those threads being
+throttled. Throttled threads will not be able to run again until the next
+period when the quota is replenished.
+
+A group's unassigned quota is globally tracked, being refreshed back to
+cfs_quota units at each period boundary. As threads consume this bandwidth it
+is transferred to cpu-local "silos" on a demand basis. The amount transferred
within each of these updates is tunable and described as the "slice".
Management
@@ -35,12 +36,12 @@ The default values are::
A value of -1 for cpu.cfs_quota_us indicates that the group does not have any
bandwidth restriction in place, such a group is described as an unconstrained
-bandwidth group. This represents the traditional work-conserving behavior for
+bandwidth group. This represents the traditional work-conserving behavior for
CFS.
Writing any (valid) positive value(s) will enact the specified bandwidth limit.
-The minimum quota allowed for the quota or period is 1ms. There is also an
-upper bound on the period length of 1s. Additional restrictions exist when
+The minimum quota allowed for the quota or period is 1ms. There is also an
+upper bound on the period length of 1s. Additional restrictions exist when
bandwidth limits are used in a hierarchical fashion, these are explained in
more detail below.
@@ -53,8 +54,8 @@ unthrottled if it is in a constrained state.
System wide settings
--------------------
For efficiency run-time is transferred between the global pool and CPU local
-"silos" in a batch fashion. This greatly reduces global accounting pressure
-on large systems. The amount transferred each time such an update is required
+"silos" in a batch fashion. This greatly reduces global accounting pressure
+on large systems. The amount transferred each time such an update is required
is described as the "slice".
This is tunable via procfs::
@@ -97,6 +98,51 @@ There are two ways in which a group may become throttled:
In case b) above, even though the child may have runtime remaining it will not
be allowed to until the parent's runtime is refreshed.
+CFS Bandwidth Quota Caveats
+---------------------------
+Once a slice is assigned to a cpu it does not expire. However all but 1ms of
+the slice may be returned to the global pool if all threads on that cpu become
+unrunnable. This is configured at compile time by the min_cfs_rq_runtime
+variable. This is a performance tweak that helps prevent added contention on
+the global lock.
+
+The fact that cpu-local slices do not expire results in some interesting corner
+cases that should be understood.
+
+For cgroup cpu constrained applications that are cpu limited this is a
+relatively moot point because they will naturally consume the entirety of their
+quota as well as the entirety of each cpu-local slice in each period. As a
+result it is expected that nr_periods roughly equal nr_throttled, and that
+cpuacct.usage will increase roughly equal to cfs_quota_us in each period.
+
+For highly-threaded, non-cpu bound applications this non-expiration nuance
+allows applications to briefly burst past their quota limits by the amount of
+unused slice on each cpu that the task group is running on (typically at most
+1ms per cpu or as defined by min_cfs_rq_runtime). This slight burst only
+applies if quota had been assigned to a cpu and then not fully used or returned
+in previous periods. This burst amount will not be transferred between cores.
+As a result, this mechanism still strictly limits the task group to quota
+average usage, albeit over a longer time window than a single period. This
+also limits the burst ability to no more than 1ms per cpu. This provides
+better more predictable user experience for highly threaded applications with
+small quota limits on high core count machines. It also eliminates the
+propensity to throttle these applications while simultanously using less than
+quota amounts of cpu. Another way to say this, is that by allowing the unused
+portion of a slice to remain valid across periods we have decreased the
+possibility of wastefully expiring quota on cpu-local silos that don't need a
+full slice's amount of cpu time.
+
+The interaction between cpu-bound and non-cpu-bound-interactive applications
+should also be considered, especially when single core usage hits 100%. If you
+gave each of these applications half of a cpu-core and they both got scheduled
+on the same CPU it is theoretically possible that the non-cpu bound application
+will use up to 1ms additional quota in some periods, thereby preventing the
+cpu-bound application from fully using its quota by that same amount. In these
+instances it will be up to the CFS algorithm (see sched-design-CFS.rst) to
+decide which application is chosen to run, as they will both be runnable and
+have remaining quota. This runtime discrepancy will be made up in the following
+periods when the interactive application idles.
+
Examples
--------
1. Limit a group to 1 CPU worth of runtime::
diff --git a/Documentation/security/tpm/index.rst b/Documentation/security/tpm/index.rst
index 3296533e54cf..487852fda33e 100644
--- a/Documentation/security/tpm/index.rst
+++ b/Documentation/security/tpm/index.rst
@@ -6,3 +6,4 @@ Trusted Platform Module documentation
tpm_vtpm_proxy
xen-tpmfront
+ tpm_ftpm_tee
diff --git a/Documentation/security/tpm/tpm_ftpm_tee.rst b/Documentation/security/tpm/tpm_ftpm_tee.rst
new file mode 100644
index 000000000000..8c2bae16e3d9
--- /dev/null
+++ b/Documentation/security/tpm/tpm_ftpm_tee.rst
@@ -0,0 +1,27 @@
+=============================================
+Firmware TPM Driver
+=============================================
+
+This document describes the firmware Trusted Platform Module (fTPM)
+device driver.
+
+Introduction
+============
+
+This driver is a shim for firmware implemented in ARM's TrustZone
+environment. The driver allows programs to interact with the TPM in the same
+way they would interact with a hardware TPM.
+
+Design
+======
+
+The driver acts as a thin layer that passes commands to and from a TPM
+implemented in firmware. The driver itself doesn't contain much logic and is
+used more like a dumb pipe between firmware and kernel/userspace.
+
+The firmware itself is based on the following paper:
+https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/ftpm1.pdf
+
+When the driver is loaded it will expose ``/dev/tpmX`` character devices to
+userspace which will enable userspace to communicate with the firmware TPM
+through this device.
diff --git a/Documentation/sh/conf.py b/Documentation/sh/conf.py
deleted file mode 100644
index 1eb684a13ac8..000000000000
--- a/Documentation/sh/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "SuperH architecture implementation manual"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'sh.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/sound/conf.py b/Documentation/sound/conf.py
deleted file mode 100644
index 3f1fc5e74e7b..000000000000
--- a/Documentation/sound/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Sound Subsystem Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'sound.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py
index 301a21aa4f63..eeb394b39e2c 100644
--- a/Documentation/sphinx/load_config.py
+++ b/Documentation/sphinx/load_config.py
@@ -21,6 +21,29 @@ def loadConfig(namespace):
and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
config_file = os.path.abspath(config_file)
+ # Let's avoid one conf.py file just due to latex_documents
+ start = config_file.find('Documentation/')
+ if start >= 0:
+ start = config_file.find('/', start + 1)
+
+ end = config_file.rfind('/')
+ if start >= 0 and end > 0:
+ dir = config_file[start + 1:end]
+
+ print("source directory: %s" % dir)
+ new_latex_docs = []
+ latex_documents = namespace['latex_documents']
+
+ for l in latex_documents:
+ if l[0].find(dir + '/') == 0:
+ has = True
+ fn = l[0][len(dir) + 1:]
+ new_latex_docs.append((fn, l[1], l[2], l[3], l[4]))
+ break
+
+ namespace['latex_documents'] = new_latex_docs
+
+ # If there is an extra conf.py file, load it
if os.path.isfile(config_file):
sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
config = namespace.copy()
@@ -29,4 +52,6 @@ def loadConfig(namespace):
del config['__file__']
namespace.update(config)
else:
- sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
+ config = namespace.copy()
+ config['tags'].add("subproject")
+ namespace.update(config)
diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst
index 1739cba8863e..f1ad4504b734 100644
--- a/Documentation/translations/it_IT/doc-guide/sphinx.rst
+++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst
@@ -242,8 +242,9 @@ del kernel:
* Per inserire blocchi di testo con caratteri a dimensione fissa (codici di
esempio, casi d'uso, eccetera): utilizzate ``::`` quando non è necessario
evidenziare la sintassi, specialmente per piccoli frammenti; invece,
- utilizzate ``.. code-block:: <language>`` per blocchi di più lunghi che
- potranno beneficiare dell'avere la sintassi evidenziata.
+ utilizzate ``.. code-block:: <language>`` per blocchi più lunghi che
+ beneficeranno della sintassi evidenziata. Per un breve pezzo di codice da
+ inserire nel testo, usate \`\`.
Il dominio C
@@ -267,12 +268,14 @@ molto comune come ``open`` o ``ioctl``:
Il nome della funzione (per esempio ioctl) rimane nel testo ma il nome del suo
riferimento cambia da ``ioctl`` a ``VIDIOC_LOG_STATUS``. Anche la voce
-nell'indice cambia in ``VIDIOC_LOG_STATUS`` e si potrà quindi fare riferimento
-a questa funzione scrivendo:
-
-.. code-block:: rst
-
- :c:func:`VIDIOC_LOG_STATUS`
+nell'indice cambia in ``VIDIOC_LOG_STATUS``.
+
+Notate che per una funzione non c'è bisogno di usare ``c:func:`` per generarne
+i riferimenti nella documentazione. Grazie a qualche magica estensione a
+Sphinx, il sistema di generazione della documentazione trasformerà
+automaticamente un riferimento ad una ``funzione()`` in un riferimento
+incrociato quando questa ha una voce nell'indice. Se trovate degli usi di
+``c:func:`` nella documentazione del kernel, sentitevi liberi di rimuoverli.
Tabelle a liste
diff --git a/Documentation/translations/it_IT/process/index.rst b/Documentation/translations/it_IT/process/index.rst
index 2eda85d5cd1e..012de0f3154a 100644
--- a/Documentation/translations/it_IT/process/index.rst
+++ b/Documentation/translations/it_IT/process/index.rst
@@ -27,6 +27,7 @@ Di seguito le guide che ogni sviluppatore dovrebbe leggere.
code-of-conduct
development-process
submitting-patches
+ programming-language
coding-style
maintainer-pgp-guide
email-clients
diff --git a/Documentation/translations/it_IT/process/kernel-docs.rst b/Documentation/translations/it_IT/process/kernel-docs.rst
index 7bd70d661737..38e0a955121a 100644
--- a/Documentation/translations/it_IT/process/kernel-docs.rst
+++ b/Documentation/translations/it_IT/process/kernel-docs.rst
@@ -1,6 +1,7 @@
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_kernel_docs:
@@ -8,6 +9,10 @@
Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
========================================================================================
-.. warning::
-
- TODO ancora da tradurre
+.. note::
+ Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
+ utilizza dai campi *ReStructuredText* di supporto alla ricerca e che per
+ questo motivo è meglio non tradurre al fine di garantirne un corretto
+ utilizzo.
+ Per questi motivi il documento non verrà tradotto. Per favore fate
+ riferimento al documento originale in lingua inglese.
diff --git a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
index 276db0e37f43..118fb4153e8f 100644
--- a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
+++ b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
@@ -248,7 +248,10 @@ possano ricevere la vostra nuova sottochiave::
kernel.
Se per qualche ragione preferite rimanere con sottochiavi RSA, nel comando
- precedente, sostituite "ed25519" con "rsa2048".
+ precedente, sostituite "ed25519" con "rsa2048". In aggiunta, se avete
+ intenzione di usare un dispositivo hardware che non supporta le chiavi
+ ED25519 ECC, come la Nitrokey Pro o la Yubikey, allora dovreste usare
+ "nistp256" al posto di "ed25519".
Copia di riserva della chiave primaria per gestire il recupero da disastro
--------------------------------------------------------------------------
@@ -449,23 +452,27 @@ implementi le funzionalità delle smartcard. Sul mercato ci sono diverse
soluzioni disponibili:
- `Nitrokey Start`_: è Open hardware e Free Software, è basata sul progetto
- `GnuK`_ della FSIJ. Ha il supporto per chiavi ECC, ma meno funzionalità di
- sicurezza (come la resistenza alla manomissione o alcuni attacchi ad un
- canale laterale).
+ `GnuK`_ della FSIJ. Questo è uno dei pochi dispositivi a supportare le chiavi
+ ECC ED25519, ma offre meno funzionalità di sicurezza (come la resistenza
+ alla manomissione o alcuni attacchi ad un canale laterale).
- `Nitrokey Pro`_: è simile alla Nitrokey Start, ma è più resistente alla
- manomissione e offre più funzionalità di sicurezza, ma l'ECC.
-- `Yubikey 4`_: l'hardware e il software sono proprietari, ma è più economica
+ manomissione e offre più funzionalità di sicurezza. La Pro 2 supporta la
+ crittografia ECC (NISTP).
+- `Yubikey 5`_: l'hardware e il software sono proprietari, ma è più economica
della Nitrokey Pro ed è venduta anche con porta USB-C il che è utile con i
computer portatili più recenti. In aggiunta, offre altre funzionalità di
- sicurezza come FIDO, U2F, ma non l'ECC
+ sicurezza come FIDO, U2F, e ora supporta anche le chiavi ECC (NISTP)
`Su LWN c'è una buona recensione`_ dei modelli elencati qui sopra e altri.
+La scelta dipenderà dal costo, dalla disponibilità nella vostra area
+geografica e vostre considerazioni sull'hardware aperto/proprietario.
+
Se volete usare chiavi ECC, la vostra migliore scelta sul mercato è la
Nitrokey Start.
.. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
-.. _`Nitrokey Pro`: https://shop.nitrokey.com/shop/product/nitrokey-pro-3
-.. _`Yubikey 4`: https://www.yubico.com/product/yubikey-4-series/
+.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nitrokey-pro-2-3
+.. _`Yubikey 5`: https://www.yubico.com/product/yubikey-5-overview/
.. _Gnuk: http://www.fsij.org/doc-gnuk/
.. _`Su LWN c'è una buona recensione`: https://lwn.net/Articles/736231/
diff --git a/Documentation/translations/it_IT/process/programming-language.rst b/Documentation/translations/it_IT/process/programming-language.rst
new file mode 100644
index 000000000000..f4b006395849
--- /dev/null
+++ b/Documentation/translations/it_IT/process/programming-language.rst
@@ -0,0 +1,51 @@
+.. include:: ../disclaimer-ita.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
+
+.. _it_programming_language:
+
+Linguaggio di programmazione
+============================
+
+Il kernel è scritto nel linguaggio di programmazione C [c-language]_.
+Più precisamente, il kernel viene compilato con ``gcc`` [gcc]_ usando
+l'opzione ``-std=gnu89`` [gcc-c-dialect-options]_: il dialetto GNU
+dello standard ISO C90 (con l'aggiunta di alcune funzionalità da C99)
+
+Questo dialetto contiene diverse estensioni al linguaggio [gnu-extensions]_,
+e molte di queste vengono usate sistematicamente dal kernel.
+
+Il kernel offre un certo livello di supporto per la compilazione con ``clang``
+[clang]_ e ``icc`` [icc]_ su diverse architetture, tuttavia in questo momento
+il supporto non è completo e richiede delle patch aggiuntive.
+
+Attributi
+---------
+
+Una delle estensioni più comuni e usate nel kernel sono gli attributi
+[gcc-attribute-syntax]_. Gli attributi permettono di aggiungere una semantica,
+definita dell'implementazione, alle entità del linguaggio (come le variabili,
+le funzioni o i tipi) senza dover fare importanti modifiche sintattiche al
+linguaggio stesso (come l'aggiunta di nuove parole chiave) [n2049]_.
+
+In alcuni casi, gli attributi sono opzionali (ovvero un compilatore che non
+dovesse supportarli dovrebbe produrre comunque codice corretto, anche se
+più lento o che non esegue controlli aggiuntivi durante la compilazione).
+
+Il kernel definisce alcune pseudo parole chiave (per esempio ``__pure``)
+in alternativa alla sintassi GNU per gli attributi (per esempio
+``__attribute__((__pure__))``) allo scopo di mostrare quali funzionalità si
+possono usare e/o per accorciare il codice.
+
+Per maggiori informazioni consultate il file d'intestazione
+``include/linux/compiler_attributes.h``.
+
+.. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
+.. [gcc] https://gcc.gnu.org
+.. [clang] https://clang.llvm.org
+.. [icc] https://software.intel.com/en-us/c-compilers
+.. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+.. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+.. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+.. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
diff --git a/Documentation/translations/ko_KR/memory-barriers.txt b/Documentation/translations/ko_KR/memory-barriers.txt
index a33c2a536542..2774624ee843 100644
--- a/Documentation/translations/ko_KR/memory-barriers.txt
+++ b/Documentation/translations/ko_KR/memory-barriers.txt
@@ -569,7 +569,7 @@ ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—만 ì ìš©ë˜ê³  RELEASE ë
[*] 버스 ë§ˆìŠ¤í„°ë§ DMA 와 ì¼ê´€ì„±ì— 대해서는 다ìŒì„ 참고하시기 ë°”ëžë‹ˆë‹¤:
- Documentation/PCI/pci.rst
+ Documentation/driver-api/pci/pci.rst
Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
diff --git a/Documentation/userspace-api/conf.py b/Documentation/userspace-api/conf.py
deleted file mode 100644
index 2eaf59f844e5..000000000000
--- a/Documentation/userspace-api/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux kernel user-space API guide"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'userspace-api.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/virtual/index.rst b/Documentation/virt/index.rst
index 062ffb527043..062ffb527043 100644
--- a/Documentation/virtual/index.rst
+++ b/Documentation/virt/index.rst
diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
index d18c97b4e140..d18c97b4e140 100644
--- a/Documentation/virtual/kvm/amd-memory-encryption.rst
+++ b/Documentation/virt/kvm/amd-memory-encryption.rst
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virt/kvm/api.txt
index e54a3f51ddc5..2d067767b617 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virt/kvm/api.txt
@@ -3781,7 +3781,7 @@ encrypted VMs.
Currently, this ioctl is used for issuing Secure Encrypted Virtualization
(SEV) commands on AMD Processors. The SEV commands are defined in
-Documentation/virtual/kvm/amd-memory-encryption.rst.
+Documentation/virt/kvm/amd-memory-encryption.rst.
4.111 KVM_MEMORY_ENCRYPT_REG_REGION
diff --git a/Documentation/virtual/kvm/arm/hyp-abi.txt b/Documentation/virt/kvm/arm/hyp-abi.txt
index a20a0bee268d..a20a0bee268d 100644
--- a/Documentation/virtual/kvm/arm/hyp-abi.txt
+++ b/Documentation/virt/kvm/arm/hyp-abi.txt
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virt/kvm/arm/psci.txt
index 559586fc9d37..559586fc9d37 100644
--- a/Documentation/virtual/kvm/arm/psci.txt
+++ b/Documentation/virt/kvm/arm/psci.txt
diff --git a/Documentation/virtual/kvm/cpuid.rst b/Documentation/virt/kvm/cpuid.rst
index 01b081f6e7ea..01b081f6e7ea 100644
--- a/Documentation/virtual/kvm/cpuid.rst
+++ b/Documentation/virt/kvm/cpuid.rst
diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virt/kvm/devices/README
index 34a69834124a..34a69834124a 100644
--- a/Documentation/virtual/kvm/devices/README
+++ b/Documentation/virt/kvm/devices/README
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virt/kvm/devices/arm-vgic-its.txt
index eeaa95b893a8..eeaa95b893a8 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
+++ b/Documentation/virt/kvm/devices/arm-vgic-its.txt
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virt/kvm/devices/arm-vgic-v3.txt
index ff290b43c8e5..ff290b43c8e5 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+++ b/Documentation/virt/kvm/devices/arm-vgic-v3.txt
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virt/kvm/devices/arm-vgic.txt
index 97b6518148f8..97b6518148f8 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virt/kvm/devices/arm-vgic.txt
diff --git a/Documentation/virtual/kvm/devices/mpic.txt b/Documentation/virt/kvm/devices/mpic.txt
index 8257397adc3c..8257397adc3c 100644
--- a/Documentation/virtual/kvm/devices/mpic.txt
+++ b/Documentation/virt/kvm/devices/mpic.txt
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virt/kvm/devices/s390_flic.txt
index a4e20a090174..a4e20a090174 100644
--- a/Documentation/virtual/kvm/devices/s390_flic.txt
+++ b/Documentation/virt/kvm/devices/s390_flic.txt
diff --git a/Documentation/virtual/kvm/devices/vcpu.txt b/Documentation/virt/kvm/devices/vcpu.txt
index 2b5dab16c4f2..2b5dab16c4f2 100644
--- a/Documentation/virtual/kvm/devices/vcpu.txt
+++ b/Documentation/virt/kvm/devices/vcpu.txt
diff --git a/Documentation/virtual/kvm/devices/vfio.txt b/Documentation/virt/kvm/devices/vfio.txt
index 528c77c8022c..528c77c8022c 100644
--- a/Documentation/virtual/kvm/devices/vfio.txt
+++ b/Documentation/virt/kvm/devices/vfio.txt
diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virt/kvm/devices/vm.txt
index 4ffb82b02468..4ffb82b02468 100644
--- a/Documentation/virtual/kvm/devices/vm.txt
+++ b/Documentation/virt/kvm/devices/vm.txt
diff --git a/Documentation/virtual/kvm/devices/xics.txt b/Documentation/virt/kvm/devices/xics.txt
index 42864935ac5d..42864935ac5d 100644
--- a/Documentation/virtual/kvm/devices/xics.txt
+++ b/Documentation/virt/kvm/devices/xics.txt
diff --git a/Documentation/virtual/kvm/devices/xive.txt b/Documentation/virt/kvm/devices/xive.txt
index 9a24a4525253..9a24a4525253 100644
--- a/Documentation/virtual/kvm/devices/xive.txt
+++ b/Documentation/virt/kvm/devices/xive.txt
diff --git a/Documentation/virtual/kvm/halt-polling.txt b/Documentation/virt/kvm/halt-polling.txt
index 4f791b128dd2..4f791b128dd2 100644
--- a/Documentation/virtual/kvm/halt-polling.txt
+++ b/Documentation/virt/kvm/halt-polling.txt
diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virt/kvm/hypercalls.txt
index da210651f714..5f6d291bd004 100644
--- a/Documentation/virtual/kvm/hypercalls.txt
+++ b/Documentation/virt/kvm/hypercalls.txt
@@ -18,7 +18,7 @@ S390:
number in R1.
For further information on the S390 diagnose call as supported by KVM,
- refer to Documentation/virtual/kvm/s390-diag.txt.
+ refer to Documentation/virt/kvm/s390-diag.txt.
PowerPC:
It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
@@ -26,7 +26,7 @@ S390:
KVM hypercalls uses 4 byte opcode, that are patched with 'hypercall-instructions'
property inside the device tree's /hypervisor node.
- For more information refer to Documentation/virtual/kvm/ppc-pv.txt
+ For more information refer to Documentation/virt/kvm/ppc-pv.txt
MIPS:
KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
diff --git a/Documentation/virtual/kvm/index.rst b/Documentation/virt/kvm/index.rst
index 0b206a06f5be..ada224a511fe 100644
--- a/Documentation/virtual/kvm/index.rst
+++ b/Documentation/virt/kvm/index.rst
@@ -9,3 +9,4 @@ KVM
amd-memory-encryption
cpuid
+ vcpu-requests
diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virt/kvm/locking.txt
index 635cd6eaf714..635cd6eaf714 100644
--- a/Documentation/virtual/kvm/locking.txt
+++ b/Documentation/virt/kvm/locking.txt
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virt/kvm/mmu.txt
index 2efe0efc516e..1b9880dfba0a 100644
--- a/Documentation/virtual/kvm/mmu.txt
+++ b/Documentation/virt/kvm/mmu.txt
@@ -298,7 +298,7 @@ Handling a page fault is performed as follows:
vcpu->arch.mmio_gfn, and call the emulator
- If both P bit and R/W bit of error code are set, this could possibly
be handled as a "fast page fault" (fixed without taking the MMU lock). See
- the description in Documentation/virtual/kvm/locking.txt.
+ the description in Documentation/virt/kvm/locking.txt.
- if needed, walk the guest page tables to determine the guest translation
(gva->gpa or ngpa->gpa)
- if permissions are insufficient, reflect the fault back to the guest
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virt/kvm/msr.txt
index df1f4338b3ca..df1f4338b3ca 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virt/kvm/msr.txt
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virt/kvm/nested-vmx.txt
index 97eb1353e962..97eb1353e962 100644
--- a/Documentation/virtual/kvm/nested-vmx.txt
+++ b/Documentation/virt/kvm/nested-vmx.txt
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virt/kvm/ppc-pv.txt
index e26115ce4258..e26115ce4258 100644
--- a/Documentation/virtual/kvm/ppc-pv.txt
+++ b/Documentation/virt/kvm/ppc-pv.txt
diff --git a/Documentation/virtual/kvm/review-checklist.txt b/Documentation/virt/kvm/review-checklist.txt
index a83b27635fdd..499af499e296 100644
--- a/Documentation/virtual/kvm/review-checklist.txt
+++ b/Documentation/virt/kvm/review-checklist.txt
@@ -7,7 +7,7 @@ Review checklist for kvm patches
2. Patches should be against kvm.git master branch.
3. If the patch introduces or modifies a new userspace API:
- - the API must be documented in Documentation/virtual/kvm/api.txt
+ - the API must be documented in Documentation/virt/kvm/api.txt
- the API must be discoverable using KVM_CHECK_EXTENSION
4. New state must include support for save/restore.
diff --git a/Documentation/virtual/kvm/s390-diag.txt b/Documentation/virt/kvm/s390-diag.txt
index 7c52e5f8b210..7c52e5f8b210 100644
--- a/Documentation/virtual/kvm/s390-diag.txt
+++ b/Documentation/virt/kvm/s390-diag.txt
diff --git a/Documentation/virtual/kvm/timekeeping.txt b/Documentation/virt/kvm/timekeeping.txt
index 76808a17ad84..76808a17ad84 100644
--- a/Documentation/virtual/kvm/timekeeping.txt
+++ b/Documentation/virt/kvm/timekeeping.txt
diff --git a/Documentation/virtual/kvm/vcpu-requests.rst b/Documentation/virt/kvm/vcpu-requests.rst
index 5feb3706a7ae..5feb3706a7ae 100644
--- a/Documentation/virtual/kvm/vcpu-requests.rst
+++ b/Documentation/virt/kvm/vcpu-requests.rst
diff --git a/Documentation/virtual/paravirt_ops.rst b/Documentation/virt/paravirt_ops.rst
index 6b789d27cead..6b789d27cead 100644
--- a/Documentation/virtual/paravirt_ops.rst
+++ b/Documentation/virt/paravirt_ops.rst
diff --git a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt b/Documentation/virt/uml/UserModeLinux-HOWTO.txt
index 87b80f589e1c..87b80f589e1c 100644
--- a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
+++ b/Documentation/virt/uml/UserModeLinux-HOWTO.txt
diff --git a/Documentation/vm/conf.py b/Documentation/vm/conf.py
deleted file mode 100644
index 3b0b601af558..000000000000
--- a/Documentation/vm/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Memory Management Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'memory-management.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/Documentation/vm/hmm.rst b/Documentation/vm/hmm.rst
index 7d90964abbb0..710ce1c701bf 100644
--- a/Documentation/vm/hmm.rst
+++ b/Documentation/vm/hmm.rst
@@ -237,7 +237,7 @@ The usage pattern is::
ret = hmm_range_snapshot(&range);
if (ret) {
up_read(&mm->mmap_sem);
- if (ret == -EAGAIN) {
+ if (ret == -EBUSY) {
/*
* No need to check hmm_range_wait_until_valid() return value
* on retry we will get proper error with hmm_range_snapshot()
diff --git a/Documentation/watchdog/hpwdt.rst b/Documentation/watchdog/hpwdt.rst
index c165d92cfd12..c824cd7f6e32 100644
--- a/Documentation/watchdog/hpwdt.rst
+++ b/Documentation/watchdog/hpwdt.rst
@@ -63,7 +63,7 @@ Last reviewed: 08/20/2018
and loop forever. This is generally not what a watchdog user wants.
For those wishing to learn more please see:
- Documentation/kdump/kdump.rst
+ Documentation/admin-guide/kdump/kdump.rst
Documentation/admin-guide/kernel-parameters.txt (panic=)
Your Linux Distribution specific documentation.
diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py
deleted file mode 100644
index 33c5c3142e20..000000000000
--- a/Documentation/x86/conf.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "X86 architecture specific documentation"
-
-tags.add("subproject")
-
-latex_documents = [
- ('index', 'x86.tex', project,
- 'The kernel development community', 'manual'),
-]
diff --git a/MAINTAINERS b/MAINTAINERS
index 783569e3c4b4..8147615da48c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -183,7 +183,7 @@ M: Realtek linux nic maintainers <nic_swsd@realtek.com>
M: Heiner Kallweit <hkallweit1@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ethernet/realtek/r8169.c
+F: drivers/net/ethernet/realtek/r8169*
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -517,14 +517,6 @@ W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/video/backlight/adp8860_bl.c
-ADS1015 HARDWARE MONITOR DRIVER
-M: Dirk Eibach <eibach@gdsys.de>
-L: linux-hwmon@vger.kernel.org
-S: Maintained
-F: Documentation/hwmon/ads1015.rst
-F: drivers/hwmon/ads1015.c
-F: include/linux/platform_data/ads1015.h
-
ADT746X FAN DRIVER
M: Colin Leroy <colin@colino.net>
S: Maintained
@@ -683,7 +675,7 @@ S: Maintained
F: drivers/crypto/sunxi-ss/
ALLWINNER VPU DRIVER
-M: Maxime Ripard <maxime.ripard@bootlin.com>
+M: Maxime Ripard <mripard@kernel.org>
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
L: linux-media@vger.kernel.org
S: Maintained
@@ -899,7 +891,7 @@ L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/adc/ad7124.c
-F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
+F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml
ANALOG DEVICES INC AD7606 DRIVER
M: Stefan Popa <stefan.popa@analog.com>
@@ -1194,7 +1186,7 @@ F: include/uapi/linux/if_arcnet.h
ARM ARCHITECTED TIMER DRIVER
M: Mark Rutland <mark.rutland@arm.com>
-M: Marc Zyngier <marc.zyngier@arm.com>
+M: Marc Zyngier <maz@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/include/asm/arch_timer.h
@@ -1350,8 +1342,7 @@ M: Will Deacon <will@kernel.org>
R: Robin Murphy <robin.murphy@arm.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: drivers/iommu/arm-smmu.c
-F: drivers/iommu/arm-smmu-v3.c
+F: drivers/iommu/arm-smmu*
F: drivers/iommu/io-pgtable-arm.c
F: drivers/iommu/io-pgtable-arm-v7s.c
@@ -1408,7 +1399,7 @@ S: Maintained
F: drivers/clk/sunxi/
ARM/Allwinner sunXi SoC support
-M: Maxime Ripard <maxime.ripard@bootlin.com>
+M: Maxime Ripard <mripard@kernel.org>
M: Chen-Yu Tsai <wens@csie.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@@ -1626,6 +1617,21 @@ F: drivers/clocksource/timer-atlas7.c
N: [^a-z]sirf
X: drivers/gnss
+ARM/CZ.NIC TURRIS MOX SUPPORT
+M: Marek Behun <marek.behun@nic.cz>
+W: http://mox.turris.cz
+S: Maintained
+F: Documentation/ABI/testing/debugfs-moxtet
+F: Documentation/ABI/testing/sysfs-bus-moxtet-devices
+F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
+F: Documentation/devicetree/bindings/bus/moxtet.txt
+F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
+F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
+F: include/linux/moxtet.h
+F: drivers/bus/moxtet.c
+F: drivers/firmware/turris-mox-rwtm.c
+F: drivers/gpio/gpio-moxtet.c
+
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@armlinux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1749,20 +1755,11 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-pxa/colibri-pxa270-income.c
-ARM/INTEL IOP13XX ARM ARCHITECTURE
-M: Lennert Buytenhek <kernel@wantstofly.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-
ARM/INTEL IOP32X ARM ARCHITECTURE
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-ARM/INTEL IOP33X ARM ARCHITECTURE
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Orphan
-
ARM/INTEL IQ81342EX MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1921,12 +1918,6 @@ S: Maintained
F: drivers/phy/mediatek/
F: Documentation/devicetree/bindings/phy/phy-mtk-*
-ARM/MICREL KS8695 ARCHITECTURE
-M: Greg Ungerer <gerg@uclinux.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-F: arch/arm/mach-ks8695/
-S: Odd Fixes
-
ARM/Microchip (AT91) SoC support
M: Nicolas Ferre <nicolas.ferre@microchip.com>
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
@@ -1968,6 +1959,7 @@ F: Documentation/devicetree/bindings/i2c/i2c-stu300.txt
F: arch/arm/mach-nomadik/
F: arch/arm/mach-u300/
F: arch/arm/mach-ux500/
+F: drivers/soc/ux500/
F: arch/arm/boot/dts/ste-*
F: drivers/clk/clk-nomadik.c
F: drivers/clk/clk-u300.c
@@ -2011,22 +2003,6 @@ F: drivers/*/*npcm*
F: Documentation/devicetree/bindings/*/*npcm*
F: Documentation/devicetree/bindings/*/*/*npcm*
-ARM/NUVOTON W90X900 ARM ARCHITECTURE
-M: Wan ZongShun <mcuos.com@gmail.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W: http://www.mcuos.com
-S: Maintained
-F: arch/arm/mach-w90x900/
-F: drivers/input/keyboard/w90p910_keypad.c
-F: drivers/input/touchscreen/w90p910_ts.c
-F: drivers/watchdog/nuc900_wdt.c
-F: drivers/net/ethernet/nuvoton/w90p910_ether.c
-F: drivers/mtd/nand/raw/nuc900_nand.c
-F: drivers/rtc/rtc-nuc900.c
-F: drivers/spi/spi-nuc900.c
-F: drivers/usb/host/ehci-w90x900.c
-F: drivers/video/fbdev/nuc900fb.c
-
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
L: openmoko-kernel@lists.openmoko.org (subscribers-only)
W: http://wiki.openmoko.org/wiki/Neo_FreeRunner
@@ -2155,10 +2131,12 @@ F: Documentation/devicetree/bindings/arm/realtek.txt
ARM/RENESAS ARM64 ARCHITECTURE
M: Simon Horman <horms@verge.net.au>
+M: Geert Uytterhoeven <geert+renesas@glider.be>
M: Magnus Damm <magnus.damm@gmail.com>
L: linux-renesas-soc@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
S: Supported
F: arch/arm64/boot/dts/renesas/
F: Documentation/devicetree/bindings/arm/renesas.yaml
@@ -2217,8 +2195,9 @@ F: drivers/*/*s3c24*
F: drivers/*/*/*s3c24*
F: drivers/*/*s3c64xx*
F: drivers/*/*s5pv210*
-F: drivers/memory/samsung/*
-F: drivers/soc/samsung/*
+F: drivers/memory/samsung/
+F: drivers/soc/samsung/
+F: include/linux/soc/samsung/
F: Documentation/arm/samsung/
F: Documentation/devicetree/bindings/arm/samsung/
F: Documentation/devicetree/bindings/sram/samsung-sram.txt
@@ -2269,10 +2248,12 @@ F: drivers/media/platform/s5p-mfc/
ARM/SHMOBILE ARM ARCHITECTURE
M: Simon Horman <horms@verge.net.au>
+M: Geert Uytterhoeven <geert+renesas@glider.be>
M: Magnus Damm <magnus.damm@gmail.com>
L: linux-renesas-soc@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
S: Supported
F: arch/arm/boot/dts/emev2*
F: arch/arm/boot/dts/gr-peach*
@@ -3573,7 +3554,7 @@ F: Documentation/filesystems/caching/cachefiles.txt
F: fs/cachefiles/
CADENCE MIPI-CSI2 BRIDGES
-M: Maxime Ripard <maxime.ripard@bootlin.com>
+M: Maxime Ripard <mripard@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/cdns,*.txt
@@ -4190,7 +4171,7 @@ M: Jens Axboe <axboe@kernel.dk>
L: cgroups@vger.kernel.org
L: linux-block@vger.kernel.org
T: git git://git.kernel.dk/linux-block
-F: Documentation/cgroup-v1/blkio-controller.rst
+F: Documentation/admin-guide/cgroup-v1/blkio-controller.rst
F: block/blk-cgroup.c
F: include/linux/blk-cgroup.h
F: block/blk-throttle.c
@@ -4286,6 +4267,14 @@ S: Supported
F: drivers/cpuidle/cpuidle-exynos.c
F: arch/arm/mach-exynos/pm.c
+CPUIDLE DRIVER - ARM PSCI
+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+M: Sudeep Holla <sudeep.holla@arm.com>
+L: linux-pm@vger.kernel.org
+L: linux-arm-kernel@lists.infradead.org
+S: Supported
+F: drivers/cpuidle/cpuidle-psci.c
+
CPU IDLE TIME MANAGEMENT FRAMEWORK
M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
@@ -4469,7 +4458,7 @@ F: arch/powerpc/platforms/powernv/pci-cxl.c
F: drivers/misc/cxl/
F: include/misc/cxl*
F: include/uapi/misc/cxl.h
-F: Documentation/powerpc/cxl.txt
+F: Documentation/powerpc/cxl.rst
F: Documentation/ABI/testing/sysfs-class-cxl
CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
@@ -4480,7 +4469,7 @@ L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/cxlflash/
F: include/uapi/scsi/cxlflash_ioctl.h
-F: Documentation/powerpc/cxlflash.txt
+F: Documentation/powerpc/cxlflash.rst
CYBERPRO FB DRIVER
M: Russell King <linux@armlinux.org.uk>
@@ -5291,7 +5280,7 @@ F: include/linux/vga*
DRM DRIVERS AND MISC GPU PATCHES
M: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-M: Maxime Ripard <maxime.ripard@bootlin.com>
+M: Maxime Ripard <mripard@kernel.org>
M: Sean Paul <sean@poorly.run>
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
S: Maintained
@@ -5304,7 +5293,7 @@ F: include/uapi/drm/drm*
F: include/linux/vga*
DRM DRIVERS FOR ALLWINNER A10
-M: Maxime Ripard <maxime.ripard@bootlin.com>
+M: Maxime Ripard <mripard@kernel.org>
L: dri-devel@lists.freedesktop.org
S: Supported
F: drivers/gpu/drm/sun4i/
@@ -5757,6 +5746,11 @@ S: Supported
F: drivers/edac/aspeed_edac.c
F: Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt
+EDAC-BLUEFIELD
+M: Shravan Kumar Ramani <sramani@mellanox.com>
+S: Supported
+F: drivers/edac/bluefield_edac.c
+
EDAC-CALXEDA
M: Robert Richter <rric@kernel.org>
L: linux-edac@vger.kernel.org
@@ -5781,10 +5775,11 @@ F: drivers/edac/thunderx_edac*
EDAC-CORE
M: Borislav Petkov <bp@alien8.de>
M: Mauro Carvalho Chehab <mchehab@kernel.org>
+M: Tony Luck <tony.luck@intel.com>
R: James Morse <james.morse@arm.com>
+R: Robert Richter <rrichter@marvell.com>
L: linux-edac@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras.git edac-for-next
S: Supported
F: Documentation/admin-guide/ras.rst
F: Documentation/driver-api/edac.rst
@@ -6061,7 +6056,7 @@ M: Florian Fainelli <f.fainelli@gmail.com>
M: Heiner Kallweit <hkallweit1@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
-F: Documentation/ABI/testing/sysfs-bus-mdio
+F: Documentation/ABI/testing/sysfs-class-net-phydev
F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
F: Documentation/devicetree/bindings/net/mdio*
F: Documentation/networking/phy.rst
@@ -6322,24 +6317,16 @@ F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt
F: drivers/counter/ftm-quaddec.c
FLOPPY DRIVER
-S: Orphan
+M: Denis Efremov <efremov@linux.com>
+S: Odd Fixes
L: linux-block@vger.kernel.org
F: drivers/block/floppy.c
-FMC SUBSYSTEM
-M: Alessandro Rubini <rubini@gnudd.com>
-W: http://www.ohwr.org/projects/fmc-bus
-S: Supported
-F: drivers/fmc/
-F: include/linux/fmc*.h
-F: include/linux/ipmi-fru.h
-K: fmc_d.*register
-
FPGA MANAGER FRAMEWORK
M: Moritz Fischer <mdf@kernel.org>
L: linux-fpga@vger.kernel.org
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
Q: http://patchwork.kernel.org/project/linux-fpga/list/
F: Documentation/fpga/
F: Documentation/driver-api/fpga/
@@ -6372,7 +6359,7 @@ FRAMEBUFFER LAYER
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
L: dri-devel@lists.freedesktop.org
L: linux-fbdev@vger.kernel.org
-T: git git://github.com/bzolnier/linux.git
+T: git git://anongit.freedesktop.org/drm/drm-misc
Q: http://patchwork.kernel.org/project/linux-fbdev/list/
S: Maintained
F: Documentation/fb/
@@ -6434,8 +6421,17 @@ M: Frank Li <Frank.li@nxp.com>
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: drivers/perf/fsl_imx8_ddr_perf.c
+F: Documentation/admin-guide/perf/imx-ddr.rst
F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt
+FREESCALE IMX I2C DRIVER
+M: Oleksij Rempel <o.rempel@pengutronix.de>
+R: Pengutronix Kernel Team <kernel@pengutronix.de>
+L: linux-i2c@vger.kernel.org
+S: Maintained
+F: drivers/i2c/busses/i2c-imx.c
+F: Documentation/devicetree/bindings/i2c/i2c-imx.txt
+
FREESCALE IMX LPI2C DRIVER
M: Dong Aisheng <aisheng.dong@nxp.com>
L: linux-i2c@vger.kernel.org
@@ -6719,6 +6715,13 @@ W: https://linuxtv.org
S: Maintained
F: drivers/media/radio/radio-gemtek*
+GENERIC ARCHITECTURE TOPOLOGY
+M: Sudeep Holla <sudeep.holla@arm.com>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: drivers/base/arch_topology.c
+F: include/linux/arch_topology.h
+
GENERIC GPIO I2C DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
S: Supported
@@ -6822,13 +6825,6 @@ F: Documentation/filesystems/gfs2*.txt
F: fs/gfs2/
F: include/uapi/linux/gfs2_ondisk.h
-GIGASET ISDN DRIVERS
-M: Paul Bolle <pebolle@tiscali.nl>
-L: gigaset307x-common@lists.sourceforge.net
-W: http://gigaset307x.sourceforge.net/
-S: Odd Fixes
-F: drivers/staging/isdn/gigaset/
-
GNSS SUBSYSTEM
M: Johan Hovold <johan@kernel.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss.git
@@ -6856,7 +6852,7 @@ R: Sagi Shahar <sagis@google.com>
R: Jon Olson <jonolson@google.com>
L: netdev@vger.kernel.org
S: Supported
-F: Documentation/networking/device_drivers/google/gve.txt
+F: Documentation/networking/device_drivers/google/gve.rst
F: drivers/net/ethernet/google
GPD POCKET FAN DRIVER
@@ -7454,7 +7450,7 @@ F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
F: drivers/uio/uio_hv_generic.c
F: drivers/video/fbdev/hyperv_fb.c
-F: drivers/iommu/hyperv_iommu.c
+F: drivers/iommu/hyperv-iommu.c
F: net/vmw_vsock/hyperv_transport.c
F: include/clocksource/hyperv_timer.h
F: include/linux/hyperv.h
@@ -7507,7 +7503,7 @@ I2C MV64XXX MARVELL AND ALLWINNER DRIVER
M: Gregory CLEMENT <gregory.clement@bootlin.com>
L: linux-i2c@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
F: drivers/i2c/busses/i2c-mv64xxx.c
I2C OVER PARALLEL PORT
@@ -8044,6 +8040,7 @@ S: Maintained
F: drivers/video/fbdev/i810/
INTEL ASoC DRIVERS
+M: Cezary Rojewski <cezary.rojewski@intel.com>
M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
M: Jie Yang <yang.jie@linux.intel.com>
@@ -8065,6 +8062,13 @@ T: git git://git.code.sf.net/p/intel-sas/isci
S: Supported
F: drivers/scsi/isci/
+INTEL CPU family model numbers
+M: Tony Luck <tony.luck@intel.com>
+M: x86@kernel.org
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: arch/x86/include/asm/intel-family.h
+
INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
M: Jani Nikula <jani.nikula@linux.intel.com>
M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
@@ -8371,12 +8375,6 @@ F: Documentation/x86/intel_txt.rst
F: include/linux/tboot.h
F: arch/x86/kernel/tboot.c
-INTEL-MID GPIO DRIVER
-M: David Cohen <david.a.cohen@linux.intel.com>
-L: linux-gpio@vger.kernel.org
-S: Maintained
-F: drivers/gpio/gpio-intel-mid.c
-
INTERCONNECT API
M: Georgi Djakov <georgi.djakov@linaro.org>
L: linux-pm@vger.kernel.org
@@ -8401,12 +8399,6 @@ L: linux-mips@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/sgi/ioc3-eth.c
-IOC3 SERIAL DRIVER
-M: Pat Gefre <pfg@sgi.com>
-L: linux-serial@vger.kernel.org
-S: Maintained
-F: drivers/tty/serial/ioc3_serial.c
-
IOMAP FILESYSTEM LIBRARY
M: Christoph Hellwig <hch@infradead.org>
M: Darrick J. Wong <darrick.wong@oracle.com>
@@ -8416,7 +8408,6 @@ L: linux-xfs@vger.kernel.org
L: linux-fsdevel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
S: Supported
-F: fs/iomap.c
F: fs/iomap/
F: include/linux/iomap.h
@@ -8441,11 +8432,6 @@ S: Maintained
F: fs/io_uring.c
F: include/uapi/linux/io_uring.h
-IP MASQUERADING
-M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
-S: Maintained
-F: net/ipv4/netfilter/ipt_MASQUERADE.c
-
IPMI SUBSYSTEM
M: Corey Minyard <minyard@acm.org>
L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
@@ -8490,7 +8476,7 @@ S: Obsolete
F: include/uapi/linux/ipx.h
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-M: Marc Zyngier <marc.zyngier@arm.com>
+M: Marc Zyngier <maz@kernel.org>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
F: Documentation/IRQ-domain.txt
@@ -8508,7 +8494,7 @@ F: kernel/irq/
IRQCHIP DRIVERS
M: Thomas Gleixner <tglx@linutronix.de>
M: Jason Cooper <jason@lakedaemon.net>
-M: Marc Zyngier <marc.zyngier@arm.com>
+M: Marc Zyngier <maz@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@ -8808,7 +8794,7 @@ L: kvm@vger.kernel.org
W: http://www.linux-kvm.org
T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
S: Supported
-F: Documentation/virtual/kvm/
+F: Documentation/virt/kvm/
F: include/trace/events/kvm.h
F: include/uapi/asm-generic/kvm*
F: include/uapi/linux/kvm*
@@ -8819,19 +8805,11 @@ F: virt/kvm/*
F: tools/kvm/
F: tools/testing/selftests/kvm/
-KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd)
-M: Joerg Roedel <joro@8bytes.org>
-L: kvm@vger.kernel.org
-W: http://www.linux-kvm.org/
-S: Maintained
-F: arch/x86/include/asm/svm.h
-F: arch/x86/kvm/svm.c
-
KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
-M: Marc Zyngier <marc.zyngier@arm.com>
+M: Marc Zyngier <maz@kernel.org>
R: James Morse <james.morse@arm.com>
-R: Julien Thierry <julien.thierry@arm.com>
-R: Suzuki K Pouloze <suzuki.poulose@arm.com>
+R: Julien Thierry <julien.thierry.kdev@gmail.com>
+R: Suzuki K Poulose <suzuki.poulose@arm.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: kvmarm@lists.cs.columbia.edu
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
@@ -8869,7 +8847,7 @@ M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Janosch Frank <frankja@linux.ibm.com>
R: David Hildenbrand <david@redhat.com>
R: Cornelia Huck <cohuck@redhat.com>
-L: linux-s390@vger.kernel.org
+L: kvm@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
S: Supported
@@ -8884,6 +8862,11 @@ F: tools/testing/selftests/kvm/*/s390x/
KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
M: Paolo Bonzini <pbonzini@redhat.com>
M: Radim KrÄmář <rkrcmar@redhat.com>
+R: Sean Christopherson <sean.j.christopherson@intel.com>
+R: Vitaly Kuznetsov <vkuznets@redhat.com>
+R: Wanpeng Li <wanpengli@tencent.com>
+R: Jim Mattson <jmattson@google.com>
+R: Joerg Roedel <joro@8bytes.org>
L: kvm@vger.kernel.org
W: http://www.linux-kvm.org
T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
@@ -8891,8 +8874,12 @@ S: Supported
F: arch/x86/kvm/
F: arch/x86/kvm/*/
F: arch/x86/include/uapi/asm/kvm*
+F: arch/x86/include/uapi/asm/vmx.h
+F: arch/x86/include/uapi/asm/svm.h
F: arch/x86/include/asm/kvm*
F: arch/x86/include/asm/pvclock-abi.h
+F: arch/x86/include/asm/svm.h
+F: arch/x86/include/asm/vmx.h
F: arch/x86/kernel/kvm.c
F: arch/x86/kernel/kvmclock.c
@@ -8924,7 +8911,7 @@ F: security/keys/encrypted-keys/
KEYS-TRUSTED
M: James Bottomley <jejb@linux.ibm.com>
-M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
M: Mimi Zohar <zohar@linux.ibm.com>
L: linux-integrity@vger.kernel.org
L: keyrings@vger.kernel.org
@@ -9220,6 +9207,18 @@ F: include/linux/nd.h
F: include/linux/libnvdimm.h
F: include/uapi/linux/ndctl.h
+LICENSES and SPDX stuff
+M: Thomas Gleixner <tglx@linutronix.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L: linux-spdx@vger.kernel.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/spdx.git
+F: COPYING
+F: Documentation/process/license-rules.rst
+F: LICENSES/
+F: scripts/spdxcheck-test.sh
+F: scripts/spdxcheck.py
+
LIGHTNVM PLATFORM SUPPORT
M: Matias Bjorling <mb@lightnvm.io>
W: http://github/OpenChannelSSD
@@ -9326,7 +9325,7 @@ F: drivers/misc/lkdtm/*
LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM)
M: Alan Stern <stern@rowland.harvard.edu>
-M: Andrea Parri <andrea.parri@amarulasolutions.com>
+M: Andrea Parri <parri.andrea@gmail.com>
M: Will Deacon <will@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
M: Boqun Feng <boqun.feng@gmail.com>
@@ -9334,7 +9333,7 @@ M: Nicholas Piggin <npiggin@gmail.com>
M: David Howells <dhowells@redhat.com>
M: Jade Alglave <j.alglave@ucl.ac.uk>
M: Luc Maranget <luc.maranget@inria.fr>
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
R: Akira Yokosawa <akiyks@gmail.com>
R: Daniel Lustig <dlustig@nvidia.com>
L: linux-kernel@vger.kernel.org
@@ -10017,8 +10016,8 @@ L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Supported
-F: Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
-F: Documentation/devicetree/bindings/media/rcar_vin.txt
+F: Documentation/devicetree/bindings/media/renesas,csi2.txt
+F: Documentation/devicetree/bindings/media/renesas,vin.txt
F: drivers/media/platform/rcar-vin/
MEDIA DRIVERS FOR RENESAS - VSP1
@@ -10363,7 +10362,7 @@ F: drivers/platform/x86/mlx-platform.c
MEMBARRIER SUPPORT
M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
L: linux-kernel@vger.kernel.org
S: Supported
F: kernel/sched/membarrier.c
@@ -10615,12 +10614,6 @@ M: Nicolas Ferre <nicolas.ferre@microchip.com>
S: Supported
F: drivers/power/reset/at91-sama5d2_shdwc.c
-MICROCHIP SAMA5D2-COMPATIBLE PIOBU GPIO
-M: Andrei Stefanescu <andrei.stefanescu@microchip.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L: linux-gpio@vger.kernel.org
-F: drivers/gpio/gpio-sama5d2-piobu.c
-
MICROCHIP SPI DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com>
S: Supported
@@ -10633,13 +10626,6 @@ S: Supported
F: drivers/misc/atmel-ssc.c
F: include/linux/atmel-ssc.h
-MICROCHIP TIMER COUNTER (TC) AND CLOCKSOURCE DRIVERS
-M: Nicolas Ferre <nicolas.ferre@microchip.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Supported
-F: drivers/misc/atmel_tclib.c
-F: drivers/clocksource/tcb_clksrc.c
-
MICROCHIP USBA UDC DRIVER
M: Cristian Birsan <cristian.birsan@microchip.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -11072,7 +11058,7 @@ NET_FAILOVER MODULE
M: Sridhar Samudrala <sridhar.samudrala@intel.com>
L: netdev@vger.kernel.org
S: Supported
-F: driver/net/net_failover.c
+F: drivers/net/net_failover.c
F: include/net/net_failover.h
F: Documentation/networking/net_failover.rst
@@ -11144,6 +11130,7 @@ L: netdev@vger.kernel.org
S: Maintained
W: https://fedorahosted.org/dropwatch/
F: net/core/drop_monitor.c
+F: include/uapi/linux/net_dropmon.h
NETWORKING DRIVERS
M: "David S. Miller" <davem@davemloft.net>
@@ -11282,6 +11269,7 @@ M: Aviad Yehezkel <aviadye@mellanox.com>
M: Dave Watson <davejwatson@fb.com>
M: John Fastabend <john.fastabend@gmail.com>
M: Daniel Borkmann <daniel@iogearbox.net>
+M: Jakub Kicinski <jakub.kicinski@netronome.com>
L: netdev@vger.kernel.org
S: Maintained
F: net/tls/*
@@ -12137,7 +12125,7 @@ M: Thomas Hellstrom <thellstrom@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
L: virtualization@lists.linux-foundation.org
S: Supported
-F: Documentation/virtual/paravirt_ops.txt
+F: Documentation/virt/paravirt_ops.rst
F: arch/*/kernel/paravirt*
F: arch/*/include/asm/paravirt*.h
F: include/linux/hypervisor.h
@@ -12394,7 +12382,7 @@ F: Documentation/PCI/pci-error-recovery.rst
F: drivers/pci/pcie/aer.c
F: drivers/pci/pcie/dpc.c
F: drivers/pci/pcie/err.c
-F: Documentation/powerpc/eeh-pci-error-recovery.txt
+F: Documentation/powerpc/eeh-pci-error-recovery.rst
F: arch/powerpc/kernel/eeh*.c
F: arch/powerpc/platforms/*/eeh*.c
F: arch/powerpc/include/*/eeh*.h
@@ -12590,6 +12578,7 @@ PERFORMANCE EVENTS SUBSYSTEM
M: Peter Zijlstra <peterz@infradead.org>
M: Ingo Molnar <mingo@redhat.com>
M: Arnaldo Carvalho de Melo <acme@kernel.org>
+R: Mark Rutland <mark.rutland@arm.com>
R: Alexander Shishkin <alexander.shishkin@linux.intel.com>
R: Jiri Olsa <jolsa@redhat.com>
R: Namhyung Kim <namhyung@kernel.org>
@@ -12679,6 +12668,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-gpio@vger.kernel.org
S: Supported
F: drivers/pinctrl/pinctrl-at91*
+F: drivers/gpio/gpio-sama5d2-piobu.c
PIN CONTROLLER - FREESCALE
M: Dong Aisheng <aisheng.dong@nxp.com>
@@ -13476,7 +13466,7 @@ S: Orphan
F: drivers/net/wireless/ray*
RCUTORTURE TEST FRAMEWORK
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
M: Josh Triplett <josh@joshtriplett.org>
R: Steven Rostedt <rostedt@goodmis.org>
R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
@@ -13523,7 +13513,7 @@ F: arch/x86/include/asm/resctrl_sched.h
F: Documentation/x86/resctrl*
READ-COPY UPDATE (RCU)
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
M: Josh Triplett <josh@joshtriplett.org>
R: Steven Rostedt <rostedt@goodmis.org>
R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
@@ -13681,7 +13671,7 @@ F: include/linux/reset-controller.h
RESTARTABLE SEQUENCES SUPPORT
M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
M: Peter Zijlstra <peterz@infradead.org>
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
M: Boqun Feng <boqun.feng@gmail.com>
L: linux-kernel@vger.kernel.org
S: Supported
@@ -13725,6 +13715,7 @@ F: drivers/mtd/nand/raw/r852.c
F: drivers/mtd/nand/raw/r852.h
RISC-V ARCHITECTURE
+M: Paul Walmsley <paul.walmsley@sifive.com>
M: Palmer Dabbelt <palmer@sifive.com>
M: Albert Ou <aou@eecs.berkeley.edu>
L: linux-riscv@lists.infradead.org
@@ -13947,7 +13938,6 @@ F: drivers/pci/hotplug/s390_pci_hpc.c
S390 VFIO-CCW DRIVER
M: Cornelia Huck <cohuck@redhat.com>
-M: Farhan Ali <alifm@linux.ibm.com>
M: Eric Farman <farman@linux.ibm.com>
R: Halil Pasic <pasic@linux.ibm.com>
L: linux-s390@vger.kernel.org
@@ -14016,6 +14006,12 @@ F: drivers/media/common/saa7146/
F: drivers/media/pci/saa7146/
F: include/media/drv-intf/saa7146*
+SAFESETID SECURITY MODULE
+M: Micah Morton <mortonm@chromium.org>
+S: Supported
+F: security/safesetid/
+F: Documentation/admin-guide/LSM/SafeSetID.rst
+
SAMSUNG AUDIO (ASoC) DRIVERS
M: Krzysztof Kozlowski <krzk@kernel.org>
M: Sangbeom Kim <sbkim73@samsung.com>
@@ -14106,6 +14102,8 @@ M: Kamil Konieczny <k.konieczny@partner.samsung.com>
L: linux-crypto@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/crypto/samsung-slimsss.txt
+F: Documentation/devicetree/bindings/crypto/samsung-sss.txt
F: drivers/crypto/s5p-sss.c
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
@@ -14126,6 +14124,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
F: drivers/clk/samsung/
F: include/dt-bindings/clock/exynos*.h
F: Documentation/devicetree/bindings/clock/exynos*.txt
+F: Documentation/devicetree/bindings/clock/samsung,s3c*
+F: Documentation/devicetree/bindings/clock/samsung,s5p*
SAMSUNG SPI DRIVERS
M: Kukjin Kim <kgene@kernel.org>
@@ -14176,6 +14176,12 @@ F: drivers/watchdog/sc1200wdt.c
SCHEDULER
M: Ingo Molnar <mingo@redhat.com>
M: Peter Zijlstra <peterz@infradead.org>
+M: Juri Lelli <juri.lelli@redhat.com> (SCHED_DEADLINE)
+M: Vincent Guittot <vincent.guittot@linaro.org> (SCHED_NORMAL)
+R: Dietmar Eggemann <dietmar.eggemann@arm.com> (SCHED_NORMAL)
+R: Steven Rostedt <rostedt@goodmis.org> (SCHED_FIFO/SCHED_RR)
+R: Ben Segall <bsegall@google.com> (CONFIG_CFS_BANDWIDTH)
+R: Mel Gorman <mgorman@suse.de> (CONFIG_NUMA_BALANCING)
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
S: Maintained
@@ -14456,6 +14462,7 @@ F: drivers/net/phy/phylink.c
F: drivers/net/phy/sfp*
F: include/linux/phylink.h
F: include/linux/sfp.h
+K: phylink
SGI GRU DRIVER
M: Dimitri Sivanich <sivanich@sgi.com>
@@ -14710,7 +14717,7 @@ F: mm/sl?b*
SLEEPABLE READ-COPY UPDATE (SRCU)
M: Lai Jiangshan <jiangshanlai@gmail.com>
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
M: Josh Triplett <josh@joshtriplett.org>
R: Steven Rostedt <rostedt@goodmis.org>
R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
@@ -14861,9 +14868,9 @@ F: include/linux/arm_sdei.h
F: include/uapi/linux/arm_sdei.h
SOFTWARE RAID (Multiple Disks) SUPPORT
-M: Shaohua Li <shli@kernel.org>
+M: Song Liu <song@kernel.org>
L: linux-raid@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/shli/md.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/song/md.git
S: Supported
F: drivers/md/Makefile
F: drivers/md/Kconfig
@@ -15545,6 +15552,7 @@ F: drivers/clk/clk-sc[mp]i.c
F: drivers/cpufreq/sc[mp]i-cpufreq.c
F: drivers/firmware/arm_scpi.c
F: drivers/firmware/arm_scmi/
+F: drivers/reset/reset-scmi.c
F: include/linux/sc[mp]i_protocol.h
SYSTEM RESET/SHUTDOWN DRIVERS
@@ -15853,6 +15861,7 @@ F: drivers/firmware/ti_sci*
F: include/linux/soc/ti/ti_sci_protocol.h
F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
F: drivers/soc/ti/ti_sci_pm_domains.c
+F: include/dt-bindings/soc/ti,sci_pm_domain.h
F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt
F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
F: drivers/clk/keystone/sci-clk.c
@@ -16078,7 +16087,7 @@ S: Maintained
F: drivers/net/ethernet/ti/netcp*
TI PCM3060 ASoC CODEC DRIVER
-M: Kirill Marinushkin <kmarinushkin@birdec.tech>
+M: Kirill Marinushkin <kmarinushkin@birdec.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/pcm3060.txt
@@ -16207,7 +16216,7 @@ F: drivers/platform/x86/topstar-laptop.c
TORTURE-TEST MODULES
M: Davidlohr Bueso <dave@stgolabs.net>
-M: "Paul E. McKenney" <paulmck@linux.ibm.com>
+M: "Paul E. McKenney" <paulmck@kernel.org>
M: Josh Triplett <josh@joshtriplett.org>
L: linux-kernel@vger.kernel.org
S: Supported
@@ -16854,7 +16863,7 @@ W: http://user-mode-linux.sourceforge.net
Q: https://patchwork.ozlabs.org/project/linux-um/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
S: Maintained
-F: Documentation/virtual/uml/
+F: Documentation/virt/uml/
F: arch/um/
F: arch/x86/um/
F: fs/hostfs/
@@ -17123,7 +17132,7 @@ F: drivers/virtio/virtio_input.c
F: include/uapi/linux/virtio_input.h
VIRTIO IOMMU DRIVER
-M: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+M: Jean-Philippe Brucker <jean-philippe@linaro.org>
L: virtualization@lists.linux-foundation.org
S: Maintained
F: drivers/iommu/virtio-iommu.c
@@ -17172,7 +17181,6 @@ F: drivers/vme/
F: include/linux/vme*
VMWARE BALLOON DRIVER
-M: Julien Freche <jfreche@vmware.com>
M: Nadav Amit <namit@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
L: linux-kernel@vger.kernel.org
@@ -17185,6 +17193,7 @@ M: "VMware, Inc." <pv-drivers@vmware.com>
L: virtualization@lists.linux-foundation.org
S: Supported
F: arch/x86/kernel/cpu/vmware.c
+F: arch/x86/include/asm/vmware.h
VMWARE PVRDMA DRIVER
M: Adit Ranadive <aditr@vmware.com>
@@ -17234,6 +17243,7 @@ F: Documentation/power/regulator/
F: drivers/regulator/
F: include/dt-bindings/regulator/
F: include/linux/regulator/
+K: regulator_get_optional
VRF
M: David Ahern <dsa@cumulusnetworks.com>
@@ -17502,7 +17512,7 @@ M: Darren Hart <dvhart@infradead.org>
M: Andy Shevchenko <andy@infradead.org>
L: platform-driver-x86@vger.kernel.org
T: git git://git.infradead.org/linux-platform-drivers-x86.git
-S: Maintained
+S: Odd Fixes
F: drivers/platform/x86/
F: drivers/platform/olpc/
@@ -17555,7 +17565,6 @@ M: Jakub Kicinski <jakub.kicinski@netronome.com>
M: Jesper Dangaard Brouer <hawk@kernel.org>
M: John Fastabend <john.fastabend@gmail.com>
L: netdev@vger.kernel.org
-L: xdp-newbies@vger.kernel.org
L: bpf@vger.kernel.org
S: Supported
F: net/core/xdp.c
@@ -17671,8 +17680,7 @@ F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
XILINX AXI ETHERNET DRIVER
-M: Anirudha Sarangi <anirudh@xilinx.com>
-M: John Linn <John.Linn@xilinx.com>
+M: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
S: Maintained
F: drivers/net/ethernet/xilinx/xilinx_axienet*
diff --git a/Makefile b/Makefile
index 9be5834073f8..4262ef93a294 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 5
PATCHLEVEL = 3
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION =
NAME = Bobtail Squid
# *DOCUMENTATION*
@@ -419,6 +419,7 @@ NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
+OBJSIZE = $(CROSS_COMPILE)size
PAHOLE = pahole
LEX = flex
YACC = bison
@@ -472,11 +473,12 @@ KBUILD_CFLAGS_MODULE := -DMODULE
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
KBUILD_LDFLAGS :=
GCC_PLUGINS_CFLAGS :=
+CLANG_FLAGS :=
export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP PAHOLE KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS
-export MAKE LEX YACC AWK INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE
-export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
+export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
+export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
@@ -519,7 +521,7 @@ endif
ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
ifneq ($(CROSS_COMPILE),)
-CLANG_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%))
+CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)
GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..)
@@ -843,6 +845,9 @@ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
# warn about C99 declaration after statement
KBUILD_CFLAGS += -Wdeclaration-after-statement
+# Warn about unmarked fall-throughs in switch statement.
+KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
+
# Variable Length Arrays (VLAs) should not be used anywhere in the kernel
KBUILD_CFLAGS += -Wvla
@@ -908,6 +913,10 @@ ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
LDFLAGS_vmlinux += $(call ld-option, -X,)
endif
+ifeq ($(CONFIG_RELR),y)
+LDFLAGS_vmlinux += --pack-dyn-relocs=relr
+endif
+
# insure the checker run with the right endianness
CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian)
@@ -998,6 +1007,8 @@ endif
PHONY += prepare0
+export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
+
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -1767,13 +1778,22 @@ build-dir = $(patsubst %/,%,$(dir $(build-target)))
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
%.symtypes: prepare FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
+ifeq ($(KBUILD_EXTMOD),)
+# For the single build of an in-tree module, use a temporary file to avoid
+# the situation of modules_install installing an invalid modules.order.
+%.ko: MODORDER := .modules.tmp
+endif
+%.ko: prepare FORCE
+ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
+ $(Q)echo $(build-target) > $(MODORDER)
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
# Modules
PHONY += /
/: ./
%/: prepare FORCE
- $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir)
+ $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1
# FIXME Should go into a make.lib or something
# ===========================================================================
diff --git a/arch/Kconfig b/arch/Kconfig
index a7b57dd42c26..6baedab10dca 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -18,6 +18,9 @@ config KEXEC_CORE
select CRASH_CORE
bool
+config KEXEC_ELF
+ bool
+
config HAVE_IMA_KEXEC
bool
@@ -103,7 +106,7 @@ config STATIC_KEYS_SELFTEST
config OPTPROBES
def_bool y
depends on KPROBES && HAVE_OPTPROBES
- select TASKS_RCU if PREEMPT
+ select TASKS_RCU if PREEMPTION
config KPROBES_ON_FTRACE
def_bool y
@@ -925,6 +928,20 @@ config LOCK_EVENT_COUNTS
the chance of application behavior change because of timing
differences. The counts are reported via debugfs.
+# Select if the architecture has support for applying RELR relocations.
+config ARCH_HAS_RELR
+ bool
+
+config RELR
+ bool "Use RELR relocation packing"
+ depends on ARCH_HAS_RELR && TOOLS_SUPPORT_RELR
+ default y
+ help
+ Store the kernel's dynamic relocations in the RELR relocation packing
+ format. Requires a compatible linker (LLD supports this feature), as
+ well as compatible NM and OBJCOPY utilities (llvm-nm and llvm-objcopy
+ are compatible).
+
source "kernel/gcov/Kconfig"
source "scripts/gcc-plugins/Kconfig"
diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
index a83c4f5e928b..8483a86c743d 100644
--- a/arch/arc/boot/dts/Makefile
+++ b/arch/arc/boot/dts/Makefile
@@ -12,3 +12,6 @@ dtb-y := $(builtindtb-y).dtb
# for CONFIG_OF_ALL_DTBS test
dtstree := $(srctree)/$(src)
dtb- := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
+
+# board-specific dtc flags
+DTC_FLAGS_hsdk += --pad 20
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index f5ae394ebe06..41b16f21beec 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -256,7 +256,7 @@
.macro FAKE_RET_FROM_EXCPN
lr r9, [status32]
- bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
+ bic r9, r9, STATUS_AE_MASK
or r9, r9, STATUS_IE_MASK
kflag r9
.endm
diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h
index a0eeb9f8f0a9..d9ee43c6b7db 100644
--- a/arch/arc/include/asm/linkage.h
+++ b/arch/arc/include/asm/linkage.h
@@ -62,15 +62,15 @@
#else /* !__ASSEMBLY__ */
#ifdef CONFIG_ARC_HAS_ICCM
-#define __arcfp_code __attribute__((__section__(".text.arcfp")))
+#define __arcfp_code __section(.text.arcfp)
#else
-#define __arcfp_code __attribute__((__section__(".text")))
+#define __arcfp_code __section(.text)
#endif
#ifdef CONFIG_ARC_HAS_DCCM
-#define __arcfp_data __attribute__((__section__(".data.arcfp")))
+#define __arcfp_data __section(.data.arcfp)
#else
-#define __arcfp_data __attribute__((__section__(".data")))
+#define __arcfp_data __section(.data)
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h
index 8ac0e2ac3e70..73746ed5b834 100644
--- a/arch/arc/include/asm/mach_desc.h
+++ b/arch/arc/include/asm/mach_desc.h
@@ -53,8 +53,7 @@ extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
*/
#define MACHINE_START(_type, _name) \
static const struct machine_desc __mach_desc_##_type \
-__used \
-__attribute__((__section__(".arch.info.init"))) = { \
+__used __section(.arch.info.init) = { \
.name = _name,
#define MACHINE_END \
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 18b493dfb3a8..abf9398cc333 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -202,8 +202,8 @@ static void idu_set_dest(unsigned int cmn_irq, unsigned int cpu_mask)
__mcip_cmd_data(CMD_IDU_SET_DEST, cmn_irq, cpu_mask);
}
-static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
- unsigned int distr)
+static void idu_set_mode(unsigned int cmn_irq, bool set_lvl, unsigned int lvl,
+ bool set_distr, unsigned int distr)
{
union {
unsigned int word;
@@ -212,8 +212,11 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
};
} data;
- data.distr = distr;
- data.lvl = lvl;
+ data.word = __mcip_cmd_read(CMD_IDU_READ_MODE, cmn_irq);
+ if (set_distr)
+ data.distr = distr;
+ if (set_lvl)
+ data.lvl = lvl;
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
}
@@ -240,6 +243,25 @@ static void idu_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(&mcip_lock, flags);
}
+static void idu_irq_ack(struct irq_data *data)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&mcip_lock, flags);
+ __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
+static void idu_irq_mask_ack(struct irq_data *data)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&mcip_lock, flags);
+ __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+ __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
static int
idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
bool force)
@@ -263,13 +285,36 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
else
distribution_mode = IDU_M_DISTRI_RR;
- idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
+ idu_set_mode(data->hwirq, false, 0, true, distribution_mode);
raw_spin_unlock_irqrestore(&mcip_lock, flags);
return IRQ_SET_MASK_OK;
}
+static int idu_irq_set_type(struct irq_data *data, u32 type)
+{
+ unsigned long flags;
+
+ /*
+ * ARCv2 IDU HW does not support inverse polarity, so these are the
+ * only interrupt types supported.
+ */
+ if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+ return -EINVAL;
+
+ raw_spin_lock_irqsave(&mcip_lock, flags);
+
+ idu_set_mode(data->hwirq, true,
+ type & IRQ_TYPE_EDGE_RISING ? IDU_M_TRIG_EDGE :
+ IDU_M_TRIG_LEVEL,
+ false, 0);
+
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
+
+ return 0;
+}
+
static void idu_irq_enable(struct irq_data *data)
{
/*
@@ -289,7 +334,10 @@ static struct irq_chip idu_irq_chip = {
.name = "MCIP IDU Intc",
.irq_mask = idu_irq_mask,
.irq_unmask = idu_irq_unmask,
+ .irq_ack = idu_irq_ack,
+ .irq_mask_ack = idu_irq_mask_ack,
.irq_enable = idu_irq_enable,
+ .irq_set_type = idu_irq_set_type,
#ifdef CONFIG_SMP
.irq_set_affinity = idu_irq_set_affinity,
#endif
@@ -317,7 +365,7 @@ static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t
}
static const struct irq_domain_ops idu_irq_ops = {
- .xlate = irq_domain_xlate_onecell,
+ .xlate = irq_domain_xlate_onetwocell,
.map = idu_irq_map,
};
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
index c2663fce7f6c..dc05a63516f5 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -572,6 +572,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end,
#else
BUILD_BUG_ON(sizeof(u32) != sizeof(value));
#endif
+ /* Fall through */
case DW_EH_PE_native:
if (end < (const void *)(ptr.pul + 1))
return 0;
@@ -826,7 +827,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
case DW_CFA_def_cfa:
state->cfa.reg = get_uleb128(&ptr.p8, end);
unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
- /*nobreak*/
+ /* fall through */
case DW_CFA_def_cfa_offset:
state->cfa.offs = get_uleb128(&ptr.p8, end);
unw_debug("cfa_def_cfa_offset: 0x%lx ",
@@ -834,7 +835,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
break;
case DW_CFA_def_cfa_sf:
state->cfa.reg = get_uleb128(&ptr.p8, end);
- /*nobreak */
+ /* fall through */
case DW_CFA_def_cfa_offset_sf:
state->cfa.offs = get_sleb128(&ptr.p8, end)
* state->dataAlign;
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index 62c210e7ee4c..70a3fbe79fba 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -101,7 +101,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
if (is_isa_arcv2() && ioc_enable && coherent)
dev->dma_coherent = true;
- dev_info(dev, "use %sncoherent DMA ops\n",
+ dev_info(dev, "use %scoherent DMA ops\n",
dev->dma_coherent ? "" : "non");
}
diff --git a/arch/arc/plat-hsdk/platform.c b/arch/arc/plat-hsdk/platform.c
index 7dd2dd335cf6..0b961a2a10b8 100644
--- a/arch/arc/plat-hsdk/platform.c
+++ b/arch/arc/plat-hsdk/platform.c
@@ -6,11 +6,15 @@
*/
#include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
#include <linux/smp.h>
#include <asm/arcregs.h>
#include <asm/io.h>
#include <asm/mach_desc.h>
+int arc_hsdk_axi_dmac_coherent __section(.data) = 0;
+
#define ARC_CCM_UNUSED_ADDR 0x60000000
static void __init hsdk_init_per_cpu(unsigned int cpu)
@@ -97,6 +101,42 @@ static void __init hsdk_enable_gpio_intc_wire(void)
iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN);
}
+static int __init hsdk_tweak_node_coherency(const char *path, bool coherent)
+{
+ void *fdt = initial_boot_params;
+ const void *prop;
+ int node, ret;
+ bool dt_coh_set;
+
+ node = fdt_path_offset(fdt, path);
+ if (node < 0)
+ goto tweak_fail;
+
+ prop = fdt_getprop(fdt, node, "dma-coherent", &ret);
+ if (!prop && ret != -FDT_ERR_NOTFOUND)
+ goto tweak_fail;
+
+ dt_coh_set = ret != -FDT_ERR_NOTFOUND;
+ ret = 0;
+
+ /* need to remove "dma-coherent" property */
+ if (dt_coh_set && !coherent)
+ ret = fdt_delprop(fdt, node, "dma-coherent");
+
+ /* need to set "dma-coherent" property */
+ if (!dt_coh_set && coherent)
+ ret = fdt_setprop(fdt, node, "dma-coherent", NULL, 0);
+
+ if (ret < 0)
+ goto tweak_fail;
+
+ return 0;
+
+tweak_fail:
+ pr_err("failed to tweak %s to %scoherent\n", path, coherent ? "" : "non");
+ return -EFAULT;
+}
+
enum hsdk_axi_masters {
M_HS_CORE = 0,
M_HS_RTT,
@@ -162,6 +202,39 @@ enum hsdk_axi_masters {
#define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180))
#define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194))
+static void __init hsdk_init_memory_bridge_axi_dmac(void)
+{
+ bool coherent = !!arc_hsdk_axi_dmac_coherent;
+ u32 axi_m_slv1, axi_m_oft1;
+
+ /*
+ * Don't tweak memory bridge configuration if we failed to tweak DTB
+ * as we will end up in a inconsistent state.
+ */
+ if (hsdk_tweak_node_coherency("/soc/dmac@80000", coherent))
+ return;
+
+ if (coherent) {
+ axi_m_slv1 = 0x77999999;
+ axi_m_oft1 = 0x76DCBA98;
+ } else {
+ axi_m_slv1 = 0x77777777;
+ axi_m_oft1 = 0x76543210;
+ }
+
+ writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
+ writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
+ writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_0));
+ writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_0));
+ writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
+
+ writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
+ writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
+ writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_1));
+ writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_1));
+ writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
+}
+
static void __init hsdk_init_memory_bridge(void)
{
u32 reg;
@@ -227,24 +300,14 @@ static void __init hsdk_init_memory_bridge(void)
writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
- writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
- writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
- writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
- writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
- writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
-
- writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
- writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
- writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
- writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
- writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
-
writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
+ hsdk_init_memory_bridge_axi_dmac();
+
/*
* PAE remapping for DMA clients does not work due to an RTL bug, so
* CREG_PAE register must be programmed to all zeroes, otherwise it
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 33b00579beff..2ae7f8adcac4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -7,6 +7,8 @@ config ARM
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DEVMEM_IS_ALLOWED
+ select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
+ select ARCH_HAS_DMA_MMAP_PGPROT if SWIOTLB
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_KEEPINITRD
@@ -18,6 +20,8 @@ config ARM
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_STRICT_MODULE_RWX if MMU
+ select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB
+ select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
select ARCH_HAS_TEARDOWN_DMA_OPS if MMU
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAVE_CUSTOM_GPIO_H
@@ -263,8 +267,6 @@ config PHYS_OFFSET
default 0x00000000 if ARCH_EBSA110 || \
ARCH_FOOTBRIDGE || \
ARCH_INTEGRATOR || \
- ARCH_IOP13XX || \
- ARCH_KS8695 || \
ARCH_REALVIEW
default 0x10000000 if ARCH_OMAP1 || ARCH_RPC
default 0x20000000 if ARCH_S5PV210
@@ -377,19 +379,6 @@ config ARCH_FOOTBRIDGE
Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
-config ARCH_IOP13XX
- bool "IOP13xx-based"
- depends on MMU
- select CPU_XSC3
- select NEED_MACH_MEMORY_H
- select NEED_RET_TO_USER
- select FORCE_PCI
- select PLAT_IOP
- select VMSPLIT_1G
- select SPARSE_IRQ
- help
- Support for Intel's IOP13XX (XScale) family of processors.
-
config ARCH_IOP32X
bool "IOP32x-based"
depends on MMU
@@ -403,18 +392,6 @@ config ARCH_IOP32X
Support for Intel's 80219 and IOP32X (XScale) family of
processors.
-config ARCH_IOP33X
- bool "IOP33x-based"
- depends on MMU
- select CPU_XSCALE
- select GPIO_IOP
- select GPIOLIB
- select NEED_RET_TO_USER
- select FORCE_PCI
- select PLAT_IOP
- help
- Support for Intel's IOP33X (XScale) family of processors.
-
config ARCH_IXP4XX
bool "IXP4xx-based"
depends on MMU
@@ -451,48 +428,6 @@ config ARCH_DOVE
help
Support for the Marvell Dove SoC 88AP510
-config ARCH_KS8695
- bool "Micrel/Kendin KS8695"
- select CLKSRC_MMIO
- select CPU_ARM922T
- select GENERIC_CLOCKEVENTS
- select GPIOLIB
- select NEED_MACH_MEMORY_H
- help
- Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
- System-on-Chip devices.
-
-config ARCH_W90X900
- bool "Nuvoton W90X900 CPU"
- select CLKDEV_LOOKUP
- select CLKSRC_MMIO
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select GPIOLIB
- help
- Support for Nuvoton (Winbond logic dept.) ARM9 processor,
- At present, the w90x900 has been renamed nuc900, regarding
- the ARM series product line, you can login the following
- link address to know more.
-
- <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
- ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
-
-config ARCH_LPC32XX
- bool "NXP LPC32XX"
- select ARM_AMBA
- select CLKDEV_LOOKUP
- select CLKSRC_LPC32XX
- select COMMON_CLK
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select GENERIC_IRQ_MULTI_HANDLER
- select GPIOLIB
- select SPARSE_IRQ
- select USE_OF
- help
- Support for the NXP LPC32XX family of processors
-
config ARCH_PXA
bool "PXA2xx/PXA3xx-based"
depends on MMU
@@ -578,27 +513,6 @@ config ARCH_S3C24XX
(<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or the
Samsung SMDK2410 development board (and derivatives).
-config ARCH_DAVINCI
- bool "TI DaVinci"
- select ARCH_HAS_HOLES_MEMORYMODEL
- select COMMON_CLK
- select CPU_ARM926T
- select GENERIC_ALLOCATOR
- select GENERIC_CLOCKEVENTS
- select GENERIC_IRQ_CHIP
- select GENERIC_IRQ_MULTI_HANDLER
- select GPIOLIB
- select HAVE_IDE
- select PM_GENERIC_DOMAINS if PM
- select PM_GENERIC_DOMAINS_OF if PM && OF
- select REGMAP_MMIO
- select RESET_CONTROLLER
- select SPARSE_IRQ
- select USE_OF
- select ZONE_DMA
- help
- Support for TI's DaVinci platform.
-
config ARCH_OMAP1
bool "TI OMAP1"
depends on MMU
@@ -734,17 +648,13 @@ source "arch/arm/mach-imx/Kconfig"
source "arch/arm/mach-integrator/Kconfig"
-source "arch/arm/mach-iop13xx/Kconfig"
-
source "arch/arm/mach-iop32x/Kconfig"
-source "arch/arm/mach-iop33x/Kconfig"
-
source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-keystone/Kconfig"
-source "arch/arm/mach-ks8695/Kconfig"
+source "arch/arm/mach-lpc32xx/Kconfig"
source "arch/arm/mach-mediatek/Kconfig"
@@ -830,8 +740,6 @@ source "arch/arm/plat-versatile/Kconfig"
source "arch/arm/mach-vt8500/Kconfig"
-source "arch/arm/mach-w90x900/Kconfig"
-
source "arch/arm/mach-zx/Kconfig"
source "arch/arm/mach-zynq/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index c929bea9a9ff..fe7e9b583e63 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -509,13 +509,6 @@ choice
Say Y here if you want the debug print routines to direct
their output to UART1 serial port on KEYSTONE2 devices.
- config DEBUG_KS8695_UART
- bool "KS8695 Debug UART"
- depends on ARCH_KS8695
- help
- Say Y here if you want kernel low-level debugging support
- on KS8695.
-
config DEBUG_LPC18XX_UART0
bool "Kernel low-level debugging via LPC18xx/43xx UART0"
depends on ARCH_LPC18XX
@@ -924,6 +917,20 @@ choice
Say Y here if you want kernel low-level debugging support
via SCIF2 on Renesas RZ/A1H (R7S72100).
+ config DEBUG_R7S9210_SCIF2
+ bool "Kernel low-level debugging messages via SCIF2 on R7S9210"
+ depends on ARCH_R7S9210
+ help
+ Say Y here if you want kernel low-level debugging support
+ via SCIF2 on Renesas RZ/A2M (R7S9210).
+
+ config DEBUG_R7S9210_SCIF4
+ bool "Kernel low-level debugging messages via SCIF4 on R7S9210"
+ depends on ARCH_R7S9210
+ help
+ Say Y here if you want kernel low-level debugging support
+ via SCIF4 on Renesas RZ/A2M (R7S9210).
+
config DEBUG_RCAR_GEN1_SCIF0
bool "Kernel low-level debugging messages via SCIF0 on R8A7778"
depends on ARCH_R8A7778
@@ -1533,11 +1540,11 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX6SX_UART || \
DEBUG_IMX6UL_UART || \
DEBUG_IMX7D_UART
- default "debug/ks8695.S" if DEBUG_KS8695_UART
default "debug/msm.S" if DEBUG_QCOM_UARTDM
- default "debug/netx.S" if DEBUG_NETX_UART
default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2
+ default "debug/renesas-scif.S" if DEBUG_R7S9210_SCIF2
+ default "debug/renesas-scif.S" if DEBUG_R7S9210_SCIF4
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0
@@ -1569,13 +1576,10 @@ config DEBUG_UART_PL01X
# Compatibility options for 8250
config DEBUG_UART_8250
- def_bool ARCH_EBSA110 || \
- ARCH_IOP13XX || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || \
- ARCH_RPC
+ def_bool ARCH_EBSA110 || ARCH_IOP32X || ARCH_IXP4XX || ARCH_RPC
config DEBUG_UART_PHYS
hex "Physical base address of debug UART"
- default 0x00100a00 if DEBUG_NETX_UART
default 0x01c20000 if DEBUG_DAVINCI_DMx_UART0
default 0x01c28000 if DEBUG_SUNXI_UART0
default 0x01c28400 if DEBUG_SUNXI_UART1
@@ -1668,7 +1672,8 @@ config DEBUG_UART_PHYS
default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0
default 0xe6e68000 if DEBUG_RCAR_GEN2_SCIF1
default 0xe6ee0000 if DEBUG_RCAR_GEN2_SCIF4
- default 0xe8008000 if DEBUG_R7S72100_SCIF2
+ default 0xe8008000 if DEBUG_R7S72100_SCIF2 || DEBUG_R7S9210_SCIF2
+ default 0xe8009000 if DEBUG_R7S9210_SCIF4
default 0xf0000000 if DEBUG_DIGICOLOR_UA0
default 0xf0000be0 if ARCH_EBSA110
default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE
@@ -1685,7 +1690,6 @@ config DEBUG_UART_PHYS
default 0xffc02000 if DEBUG_SOCFPGA_UART0
default 0xffc02100 if DEBUG_SOCFPGA_ARRIA10_UART1
default 0xffc03000 if DEBUG_SOCFPGA_CYCLONE5_UART1
- default 0xffd82340 if ARCH_IOP13XX
default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0
default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2
default 0xfff36000 if DEBUG_HIGHBANK_UART
@@ -1695,13 +1699,12 @@ config DEBUG_UART_PHYS
default 0xfffe8600 if DEBUG_BCM63XX_UART
default 0xffffee00 if DEBUG_AT91_SAM9263_DBGU
default 0xfffff200 if DEBUG_AT91_RM9200_DBGU
- default 0xfffff700 if ARCH_IOP33X
depends on ARCH_EP93XX || \
DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_LL_UART_EFM32 || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
- DEBUG_NETX_UART || \
DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
+ DEBUG_R7S9210_SCIF2 || DEBUG_R7S9210_SCIF4 || \
DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \
DEBUG_RCAR_GEN2_SCIF2 || DEBUG_RCAR_GEN2_SCIF4 || \
@@ -1717,7 +1720,6 @@ config DEBUG_UART_VIRT
default 0xc881f000 if DEBUG_RV1108_UART2
default 0xc8821000 if DEBUG_RV1108_UART1
default 0xc8912000 if DEBUG_RV1108_UART0
- default 0xe0000a00 if DEBUG_NETX_UART
default 0xe0010fe0 if ARCH_RPC
default 0xf0000be0 if ARCH_EBSA110
default 0xf0010000 if DEBUG_ASM9260_UART
@@ -1776,10 +1778,7 @@ config DEBUG_UART_VIRT
default 0xfc705000 if DEBUG_ZTE_ZX
default 0xfcfe8600 if DEBUG_BCM63XX_UART
default 0xfd000000 if DEBUG_SPEAR3XX || DEBUG_SPEAR13XX
- default 0xfd012000 if DEBUG_MVEBU_UART0_ALTERNATE && ARCH_MV78XX0
default 0xfd883000 if DEBUG_ALPINE_UART0
- default 0xfde12000 if DEBUG_MVEBU_UART0_ALTERNATE && ARCH_DOVE
- default 0xfe012000 if DEBUG_MVEBU_UART0_ALTERNATE && ARCH_ORION5X
default 0xfe017000 if DEBUG_MMP_UART2
default 0xfe018000 if DEBUG_MMP_UART3
default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
@@ -1794,7 +1793,7 @@ config DEBUG_UART_VIRT
default 0xfec02000 if DEBUG_SOCFPGA_UART0
default 0xfec02100 if DEBUG_SOCFPGA_ARRIA10_UART1
default 0xfec03000 if DEBUG_SOCFPGA_CYCLONE5_UART1
- default 0xfec12000 if (DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE) && ARCH_MVEBU
+ default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE
default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE
default 0xfec10000 if DEBUG_SIRFATLAS7_UART0
default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
@@ -1809,20 +1808,17 @@ config DEBUG_UART_VIRT
default 0xfedc0000 if DEBUG_EP93XX
default 0xfee003f8 if DEBUG_FOOTBRIDGE_COM1
default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
- default 0xfee82340 if ARCH_IOP13XX
default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfefb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1
default 0xfefb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2
default 0xfefb9800 if DEBUG_OMAP1UART3 || DEBUG_OMAP7XXUART3
- default 0xfefff700 if ARCH_IOP33X
default 0xff003000 if DEBUG_U300_UART
default 0xffd01000 if DEBUG_HIP01_UART
default DEBUG_UART_PHYS if !MMU
depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
- DEBUG_NETX_UART || \
DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c3624ca6c0bc..f9002e44f18f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -155,6 +155,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
machine-$(CONFIG_ARCH_ACTIONS) += actions
machine-$(CONFIG_ARCH_ALPINE) += alpine
machine-$(CONFIG_ARCH_ARTPEC) += artpec
+machine-$(CONFIG_ARCH_ASPEED) += aspeed
machine-$(CONFIG_ARCH_AT91) += at91
machine-$(CONFIG_ARCH_AXXIA) += axxia
machine-$(CONFIG_ARCH_BCM) += bcm
@@ -173,12 +174,9 @@ machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_HISI) += hisi
machine-$(CONFIG_ARCH_INTEGRATOR) += integrator
-machine-$(CONFIG_ARCH_IOP13XX) += iop13xx
machine-$(CONFIG_ARCH_IOP32X) += iop32x
-machine-$(CONFIG_ARCH_IOP33X) += iop33x
machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx
machine-$(CONFIG_ARCH_KEYSTONE) += keystone
-machine-$(CONFIG_ARCH_KS8695) += ks8695
machine-$(CONFIG_ARCH_LPC18XX) += lpc18xx
machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx
machine-$(CONFIG_ARCH_MESON) += meson
@@ -222,7 +220,6 @@ machine-$(CONFIG_ARCH_U8500) += ux500
machine-$(CONFIG_ARCH_VERSATILE) += versatile
machine-$(CONFIG_ARCH_VEXPRESS) += vexpress
machine-$(CONFIG_ARCH_VT8500) += vt8500
-machine-$(CONFIG_ARCH_W90X900) += w90x900
machine-$(CONFIG_ARCH_ZX) += zx
machine-$(CONFIG_ARCH_ZYNQ) += zynq
machine-$(CONFIG_PLAT_SPEAR) += spear
@@ -233,7 +230,6 @@ plat-$(CONFIG_ARCH_EXYNOS) += samsung
plat-$(CONFIG_ARCH_OMAP) += omap
plat-$(CONFIG_ARCH_S3C64XX) += samsung
plat-$(CONFIG_ARCH_S5PV210) += samsung
-plat-$(CONFIG_PLAT_IOP) += iop
plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
plat-$(CONFIG_PLAT_S3C24XX) += samsung
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9159fa2cea90..a24a6a132b07 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -569,17 +569,22 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ul-geam.dtb \
imx6ul-isiot-emmc.dtb \
imx6ul-isiot-nand.dtb \
+ imx6ul-kontron-n6310-s.dtb \
+ imx6ul-kontron-n6310-s-43.dtb \
imx6ul-liteboard.dtb \
imx6ul-opos6uldev.dtb \
imx6ul-pico-hobbit.dtb \
imx6ul-pico-pi.dtb \
- imx6ul-phytec-phyboard-segin-full.dtb \
+ imx6ul-phytec-segin-ff-rdk-nand.dtb \
imx6ul-tx6ul-0010.dtb \
imx6ul-tx6ul-0011.dtb \
imx6ul-tx6ul-mainboard.dtb \
imx6ull-14x14-evk.dtb \
imx6ull-colibri-eval-v3.dtb \
imx6ull-colibri-wifi-eval-v3.dtb \
+ imx6ull-phytec-segin-ff-rdk-nand.dtb \
+ imx6ull-phytec-segin-ff-rdk-emmc.dtb \
+ imx6ull-phytec-segin-lc-rdk-nand.dtb \
imx6ulz-14x14-evk.dtb
dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-cl-som-imx7.dtb \
@@ -594,6 +599,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-sdb.dtb \
imx7d-sdb-reva.dtb \
imx7d-sdb-sht11.dtb \
+ imx7d-zii-rmu2.dtb \
imx7d-zii-rpu2.dtb \
imx7s-colibri-eval-v3.dtb \
imx7s-mba7.dtb \
@@ -905,9 +911,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rk3188-radxarock.dtb \
rk3228-evb.dtb \
rk3229-evb.dtb \
+ rk3229-xms6.dtb \
rk3288-evb-act8846.dtb \
rk3288-evb-rk808.dtb \
- rk3288-fennec.dtb \
rk3288-firefly-beta.dtb \
rk3288-firefly.dtb \
rk3288-firefly-reload.dtb \
@@ -919,6 +925,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rk3288-tinker.dtb \
rk3288-tinker-s.dtb \
rk3288-veyron-brain.dtb \
+ rk3288-veyron-fievel.dtb \
rk3288-veyron-jaq.dtb \
rk3288-veyron-jerry.dtb \
rk3288-veyron-mickey.dtb \
@@ -926,6 +933,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rk3288-veyron-minnie.dtb \
rk3288-veyron-pinky.dtb \
rk3288-veyron-speedy.dtb \
+ rk3288-veyron-tiger.dtb \
rk3288-vyasa.dtb
dtb-$(CONFIG_ARCH_S3C24XX) += \
s3c2416-smdk2416.dtb
@@ -1114,6 +1122,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-r16-nintendo-super-nes-classic.dtb \
sun8i-r16-parrot.dtb \
sun8i-r40-bananapi-m2-ultra.dtb \
+ sun8i-s3-lichee-zero-plus.dtb \
sun8i-t3-cqa3t-bv3.dtb \
sun8i-v3s-licheepi-zero.dtb \
sun8i-v3s-licheepi-zero-dock.dtb \
@@ -1262,6 +1271,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
mt7623a-rfb-nand.dtb \
mt7623n-rfb-emmc.dtb \
mt7623n-bananapi-bpi-r2.dtb \
+ mt7629-rfb.dtb \
mt8127-moose.dtb \
mt8135-evbp1.dtb
dtb-$(CONFIG_ARCH_MILBEAUT) += milbeaut-m10v-evb.dtb
@@ -1271,13 +1281,18 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-arm-centriq2400-rep.dtb \
aspeed-bmc-arm-stardragon4800-rep2.dtb \
aspeed-bmc-facebook-cmm.dtb \
+ aspeed-bmc-facebook-minipack.dtb \
aspeed-bmc-facebook-tiogapass.dtb \
+ aspeed-bmc-facebook-wedge40.dtb \
+ aspeed-bmc-facebook-wedge100.dtb \
aspeed-bmc-facebook-yamp.dtb \
aspeed-bmc-intel-s2600wf.dtb \
aspeed-bmc-inspur-fp5280g2.dtb \
aspeed-bmc-lenovo-hr630.dtb \
+ aspeed-bmc-lenovo-hr855xg2.dtb \
aspeed-bmc-microsoft-olympus.dtb \
aspeed-bmc-opp-lanyang.dtb \
+ aspeed-bmc-opp-mihawk.dtb \
aspeed-bmc-opp-palmetto.dtb \
aspeed-bmc-opp-romulus.dtb \
aspeed-bmc-opp-swift.dtb \
diff --git a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts
index 0257576d5d16..2f6652ef9a15 100644
--- a/arch/arm/boot/dts/am335x-boneblue.dts
+++ b/arch/arm/boot/dts/am335x-boneblue.dts
@@ -5,23 +5,13 @@
/dts-v1/;
#include "am33xx.dtsi"
+#include "am335x-osd335x-common.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "TI AM335x BeagleBone Blue";
compatible = "ti,am335x-bone-blue", "ti,am33xx";
- cpus {
- cpu@0 {
- cpu0-supply = <&dcdc2_reg>;
- };
- };
-
- memory@80000000 {
- device_type = "memory";
- reg = <0x80000000 0x20000000>; /* 512 MB */
- };
-
chosen {
stdout-path = &uart0;
};
@@ -142,13 +132,6 @@
>;
};
- i2c0_pins: pinmux_i2c0_pins {
- pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
- AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
- >;
- };
-
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* (D18) uart1_ctsn.I2C2_SDA */
@@ -328,16 +311,6 @@
};
&i2c0 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins>;
-
- status = "okay";
- clock-frequency = <400000>;
-
- tps: tps@24 {
- reg = <0x24>;
- };
-
baseboard_eeprom: baseboard_eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
@@ -381,66 +354,13 @@
/include/ "tps65217.dtsi"
&tps {
- interrupts = <7>; /* NMI */
- interrupt-parent = <&intc>;
+ /delete-property/ ti,pmic-shutdown-controller;
charger {
interrupts = <0>, <1>;
interrupt-names = "USB", "AC";
status = "okay";
};
-
- pwrbutton {
- interrupts = <2>;
- status = "okay";
- };
-
- regulators {
- dcdc1_reg: regulator@0 {
- regulator-name = "vdds_dpr";
- regulator-always-on;
- };
-
- dcdc2_reg: regulator@1 {
- /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
- regulator-name = "vdd_mpu";
- regulator-min-microvolt = <925000>;
- regulator-max-microvolt = <1351500>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- dcdc3_reg: regulator@2 {
- /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
- regulator-name = "vdd_core";
- regulator-min-microvolt = <925000>;
- regulator-max-microvolt = <1150000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldo1_reg: regulator@3 {
- regulator-name = "vio,vrtc,vdds";
- regulator-always-on;
- };
-
- ldo2_reg: regulator@4 {
- regulator-name = "vdd_3v3aux";
- regulator-always-on;
- };
-
- ldo3_reg: regulator@5 {
- regulator-name = "vdd_1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo4_reg: regulator@6 {
- regulator-name = "vdd_3v3a";
- regulator-always-on;
- };
- };
};
&mmc1 {
@@ -502,14 +422,6 @@
};
};
-&aes {
- status = "okay";
-};
-
-&sham {
- status = "okay";
-};
-
&rtc {
system-power-controller;
clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>;
diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts
index ceecbfd29d2c..1fe3b566ba3d 100644
--- a/arch/arm/boot/dts/am335x-cm-t335.dts
+++ b/arch/arm/boot/dts/am335x-cm-t335.dts
@@ -44,7 +44,6 @@
regulator-name = "vwlan_fixed";
gpio = <&gpio0 20 GPIO_ACTIVE_HIGH>; /* gpio0_20 */
enable-active-high;
- regulator-boot-off;
};
backlight {
diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi
index ced1a19d5f89..46849d6ecb3e 100644
--- a/arch/arm/boot/dts/am33xx-l4.dtsi
+++ b/arch/arm/boot/dts/am33xx-l4.dtsi
@@ -185,7 +185,7 @@
uart0: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <72>;
status = "disabled";
dmas = <&edma 26 0>, <&edma 27 0>;
@@ -934,7 +934,7 @@
uart1: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <73>;
status = "disabled";
dmas = <&edma 28 0>, <&edma 29 0>;
@@ -966,7 +966,7 @@
uart2: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <74>;
status = "disabled";
dmas = <&edma 30 0>, <&edma 31 0>;
@@ -1614,7 +1614,7 @@
uart3: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <44>;
status = "disabled";
};
@@ -1644,7 +1644,7 @@
uart4: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <45>;
status = "disabled";
};
@@ -1674,7 +1674,7 @@
uart5: serial@0 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
clock-frequency = <48000000>;
- reg = <0x0 0x2000>;
+ reg = <0x0 0x1000>;
interrupts = <46>;
status = "disabled";
};
@@ -1758,6 +1758,8 @@
target-module@cc000 { /* 0x481cc000, ap 60 46.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
+ reg = <0xcc020 0x4>;
+ reg-names = "rev";
ti,hwmods = "d_can0";
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>,
@@ -1780,6 +1782,8 @@
target-module@d0000 { /* 0x481d0000, ap 62 42.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
+ reg = <0xd0020 0x4>;
+ reg-names = "rev";
ti,hwmods = "d_can1";
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>,
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index e5c2f71a7c77..fb6b8aa12cc5 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -234,13 +234,33 @@
interrupt-names = "edma3_tcerrint";
};
- mmc3: mmc@47810000 {
- compatible = "ti,omap4-hsmmc";
+ target-module@47810000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
ti,hwmods = "mmc3";
- ti,needs-special-reset;
- interrupts = <29>;
- reg = <0x47810000 0x1000>;
- status = "disabled";
+ reg = <0x478102fc 0x4>,
+ <0x47810110 0x4>,
+ <0x47810114 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+ SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&l3s_clkctrl AM3_L3S_MMC3_CLKCTRL 0>;
+ clock-names = "fck";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x47810000 0x1000>;
+
+ mmc3: mmc@0 {
+ compatible = "ti,omap4-hsmmc";
+ ti,needs-special-reset;
+ interrupts = <29>;
+ reg = <0x0 0x1000>;
+ };
};
usb: usb@47400000 {
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 55aff4db9c7c..848e2a8884e2 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -228,13 +228,33 @@
interrupt-names = "edma3_tcerrint";
};
- mmc3: mmc@47810000 {
- compatible = "ti,omap4-hsmmc";
- reg = <0x47810000 0x1000>;
+ target-module@47810000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
ti,hwmods = "mmc3";
- ti,needs-special-reset;
- interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
- status = "disabled";
+ reg = <0x478102fc 0x4>,
+ <0x47810110 0x4>,
+ <0x47810114 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+ SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&l3s_clkctrl AM4_L3S_MMC3_CLKCTRL 0>;
+ clock-names = "fck";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x47810000 0x1000>;
+
+ mmc3: mmc@0 {
+ compatible = "ti,omap4-hsmmc";
+ ti,needs-special-reset;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x1000>;
+ };
};
sham: sham@53100000 {
diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/am437x-l4.dtsi
index 989cb60b9029..04bee4ff9dcb 100644
--- a/arch/arm/boot/dts/am437x-l4.dtsi
+++ b/arch/arm/boot/dts/am437x-l4.dtsi
@@ -1574,6 +1574,8 @@
target-module@cc000 { /* 0x481cc000, ap 50 46.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
+ reg = <0xcc020 0x4>;
+ reg-names = "rev";
ti,hwmods = "d_can0";
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
@@ -1593,6 +1595,8 @@
target-module@d0000 { /* 0x481d0000, ap 52 3a.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
+ reg = <0xd0020 0x4>;
+ reg-names = "rev";
ti,hwmods = "d_can1";
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/am571x-idk.dts
index 1d5e99964bbf..0aaacea1d887 100644
--- a/arch/arm/boot/dts/am571x-idk.dts
+++ b/arch/arm/boot/dts/am571x-idk.dts
@@ -175,14 +175,9 @@
};
&mmc1 {
- pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-names = "default", "hs";
pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
- pinctrl-2 = <&mmc1_pins_sdr12>;
- pinctrl-3 = <&mmc1_pins_sdr25>;
- pinctrl-4 = <&mmc1_pins_sdr50>;
- pinctrl-5 = <&mmc1_pins_ddr50_rev20 &mmc1_iodelay_ddr50_conf>;
- pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
};
&mmc2 {
diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/am572x-idk.dts
index c65d7f6d3b5a..ea1c119feaa5 100644
--- a/arch/arm/boot/dts/am572x-idk.dts
+++ b/arch/arm/boot/dts/am572x-idk.dts
@@ -16,14 +16,9 @@
};
&mmc1 {
- pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-names = "default", "hs";
pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
- pinctrl-2 = <&mmc1_pins_sdr12>;
- pinctrl-3 = <&mmc1_pins_sdr25>;
- pinctrl-4 = <&mmc1_pins_sdr50>;
- pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
- pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
};
&mmc2 {
diff --git a/arch/arm/boot/dts/am574x-idk.dts b/arch/arm/boot/dts/am574x-idk.dts
index dc5141c35610..7935d70874ce 100644
--- a/arch/arm/boot/dts/am574x-idk.dts
+++ b/arch/arm/boot/dts/am574x-idk.dts
@@ -24,14 +24,9 @@
};
&mmc1 {
- pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-names = "default", "hs";
pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
- pinctrl-2 = <&mmc1_pins_default>;
- pinctrl-3 = <&mmc1_pins_hs>;
- pinctrl-4 = <&mmc1_pins_sdr50>;
- pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_conf>;
- pinctrl-6 = <&mmc1_pins_ddr50 &mmc1_iodelay_sdr104_conf>;
};
&mmc2 {
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
index d02f5fa61e5f..bc76f1705c0f 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -379,7 +379,7 @@
};
};
-&gpio7 {
+&gpio7_target {
ti,no-reset-on-init;
ti,no-idle-on-init;
};
@@ -430,6 +430,7 @@
bus-width = <4>;
cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
+ no-1-8-v;
};
&mmc2 {
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts b/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts
index a374b5cd6db0..7b113b52c3fb 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts
@@ -16,14 +16,9 @@
};
&mmc1 {
- pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-names = "default", "hs";
pinctrl-0 = <&mmc1_pins_default>;
pinctrl-1 = <&mmc1_pins_hs>;
- pinctrl-2 = <&mmc1_pins_sdr12>;
- pinctrl-3 = <&mmc1_pins_sdr25>;
- pinctrl-4 = <&mmc1_pins_sdr50>;
- pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev11_conf>;
- pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev11_conf>;
vmmc-supply = <&vdd_3v3>;
vqmmc-supply = <&ldo1_reg>;
};
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts b/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts
index 4badd2144db9..30c500b15b21 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts
@@ -16,14 +16,9 @@
};
&mmc1 {
- pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-names = "default", "hs";
pinctrl-0 = <&mmc1_pins_default>;
pinctrl-1 = <&mmc1_pins_hs>;
- pinctrl-2 = <&mmc1_pins_sdr12>;
- pinctrl-3 = <&mmc1_pins_sdr25>;
- pinctrl-4 = <&mmc1_pins_sdr50>;
- pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
- pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
vmmc-supply = <&vdd_3v3>;
vqmmc-supply = <&ldo1_reg>;
};
diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
index 556ed469830c..c9d88c90135e 100644
--- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts
+++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
@@ -94,6 +94,17 @@
};
};
+&sdmmc {
+ status = "okay";
+};
+
+&sdhci0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sd1_default>;
+};
+
/*
* Enable port A as device (via the virtual hub) and port B as
* host by default on the eval board. This can be easily changed
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts
new file mode 100644
index 000000000000..c05478296446
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2018 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+ model = "Facebook Minipack 100 BMC";
+ compatible = "facebook,minipack-bmc", "aspeed,ast2500";
+
+ aliases {
+ /*
+ * Override the default serial aliases to avoid breaking
+ * the legacy applications.
+ */
+ serial0 = &uart5;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+
+ /*
+ * i2c switch 2-0070, pca9548, 8 child channels assigned
+ * with bus number 16-23.
+ */
+ i2c16 = &imux16;
+ i2c17 = &imux17;
+ i2c18 = &imux18;
+ i2c19 = &imux19;
+ i2c20 = &imux20;
+ i2c21 = &imux21;
+ i2c22 = &imux22;
+ i2c23 = &imux23;
+
+ /*
+ * i2c switch 8-0070, pca9548, 8 child channels assigned
+ * with bus number 24-31.
+ */
+ i2c24 = &imux24;
+ i2c25 = &imux25;
+ i2c26 = &imux26;
+ i2c27 = &imux27;
+ i2c28 = &imux28;
+ i2c29 = &imux29;
+ i2c30 = &imux30;
+ i2c31 = &imux31;
+
+ /*
+ * i2c switch 9-0070, pca9548, 8 child channels assigned
+ * with bus number 32-39.
+ */
+ i2c32 = &imux32;
+ i2c33 = &imux33;
+ i2c34 = &imux34;
+ i2c35 = &imux35;
+ i2c36 = &imux36;
+ i2c37 = &imux37;
+ i2c38 = &imux38;
+ i2c39 = &imux39;
+
+ /*
+ * i2c switch 11-0070, pca9548, 8 child channels assigned
+ * with bus number 40-47.
+ */
+ i2c40 = &imux40;
+ i2c41 = &imux41;
+ i2c42 = &imux42;
+ i2c43 = &imux43;
+ i2c44 = &imux44;
+ i2c45 = &imux45;
+ i2c46 = &imux46;
+ i2c47 = &imux47;
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ bootargs = "debug console=ttyS1,9600n8 root=/dev/ram rw";
+ };
+
+ memory@80000000 {
+ reg = <0x80000000 0x20000000>;
+ };
+};
+
+&wdt1 {
+ status = "okay";
+ aspeed,reset-type = "system";
+};
+
+&wdt2 {
+ status = "okay";
+ aspeed,reset-type = "system";
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+#include "facebook-bmc-flash-layout.dtsi"
+ };
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default
+ &pinctrl_ncts1_default
+ &pinctrl_ndsr1_default
+ &pinctrl_ndtr1_default
+ &pinctrl_nrts1_default>;
+};
+
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd2_default
+ &pinctrl_rxd2_default>;
+};
+
+&uart3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd3_default
+ &pinctrl_rxd3_default>;
+};
+
+&uart4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd4_default
+ &pinctrl_rxd4_default>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac1 {
+ status = "okay";
+ no-hw-checksum;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "okay";
+ bus-frequency = <400000>;
+ multi-master;
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ imux16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux20: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux21: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux22: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux23: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+ multi-master;
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c8 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ imux24: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux25: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux26: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux27: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux28: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux29: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux30: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux31: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c9 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ imux32: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux33: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux34: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux35: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux36: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux37: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux38: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux39: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ imux40: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux41: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux42: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux43: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux44: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux45: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux46: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux47: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c12 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&vhub {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
index c4521eda787c..682f729ea25e 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
@@ -12,6 +12,27 @@
aliases {
serial0 = &uart1;
serial4 = &uart5;
+
+ /*
+ * Hardcode the bus number of i2c switches' channels to
+ * avoid breaking the legacy applications.
+ */
+ i2c16 = &imux16;
+ i2c17 = &imux17;
+ i2c18 = &imux18;
+ i2c19 = &imux19;
+ i2c20 = &imux20;
+ i2c21 = &imux21;
+ i2c22 = &imux22;
+ i2c23 = &imux23;
+ i2c24 = &imux24;
+ i2c25 = &imux25;
+ i2c26 = &imux26;
+ i2c27 = &imux27;
+ i2c28 = &imux28;
+ i2c29 = &imux29;
+ i2c30 = &imux30;
+ i2c31 = &imux31;
};
chosen {
stdout-path = &uart5;
@@ -25,13 +46,9 @@
iio-hwmon {
compatible = "iio-hwmon";
io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
- <&adc 4>, <&adc 5>, <&adc 6>;
+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>;
};
- iio-hwmon-battery {
- compatible = "iio-hwmon";
- io-channels = <&adc 7>;
- };
};
&fmc {
@@ -124,6 +141,215 @@
&i2c1 {
status = "okay";
//X24 Riser
+ i2c-switch@71 {
+ compatible = "nxp,pca9544";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+
+ imux16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ ina230@45 {
+ compatible = "ti,ina230";
+ reg = <0x45>;
+ };
+
+ tmp75@48 {
+ compatible = "ti,tmp75";
+ reg = <0x48>;
+ };
+
+ tmp421@49 {
+ compatible = "ti,tmp75";
+ reg = <0x49>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-switch@73 {
+ compatible = "nxp,pca9546";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x73>;
+
+ imux20: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux21: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux22: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux23: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ };
+
+ };
+
+ imux17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ ina230@45 {
+ compatible = "ti,ina230";
+ reg = <0x45>;
+ };
+
+ tmp421@48 {
+ compatible = "ti,tmp75";
+ reg = <0x48>;
+ };
+
+ tmp421@49 {
+ compatible = "ti,tmp75";
+ reg = <0x49>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-switch@73 {
+ compatible = "nxp,pca9546";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x73>;
+
+ imux24: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux25: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux26: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux27: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ };
+
+ };
+
+ imux18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ ina230@45 {
+ compatible = "ti,ina230";
+ reg = <0x45>;
+ };
+
+ tmp421@48 {
+ compatible = "ti,tmp75";
+ reg = <0x48>;
+ };
+
+ tmp421@49 {
+ compatible = "ti,tmp75";
+ reg = <0x49>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-switch@73 {
+ compatible = "nxp,pca9546";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x73>;
+
+ imux28: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux29: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux30: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux31: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ };
+
+ };
+
+ imux19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ i2c-switch@40 {
+ compatible = "ti,ina230";
+ reg = <0x40>;
+ };
+
+ i2c-switch@41 {
+ compatible = "ti,ina230";
+ reg = <0x41>;
+ };
+
+ i2c-switch@45 {
+ compatible = "ti,ina230";
+ reg = <0x45>;
+ };
+
+ };
+
+ };
};
&i2c2 {
@@ -144,6 +370,42 @@
&i2c5 {
status = "okay";
// CPU Voltage regulators
+ regulator@48 {
+ compatible = "infineon,pxe1610";
+ reg = <0x48>;
+ };
+ regulator@4a {
+ compatible = "infineon,pxe1610";
+ reg = <0x4a>;
+ };
+ regulator@50 {
+ compatible = "infineon,pxe1610";
+ reg = <0x50>;
+ };
+ regulator@52 {
+ compatible = "infineon,pxe1610";
+ reg = <0x52>;
+ };
+ regulator@58 {
+ compatible = "infineon,pxe1610";
+ reg = <0x58>;
+ };
+ regulator@5a {
+ compatible = "infineon,pxe1610";
+ reg = <0x5a>;
+ };
+ regulator@68 {
+ compatible = "infineon,pxe1610";
+ reg = <0x68>;
+ };
+ regulator@70 {
+ compatible = "infineon,pxe1610";
+ reg = <0x70>;
+ };
+ regulator@72 {
+ compatible = "infineon,pxe1610";
+ reg = <0x72>;
+ };
};
&i2c6 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts
new file mode 100644
index 000000000000..b1e10f0c85c9
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2018 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g4.dtsi"
+
+/ {
+ model = "Facebook Wedge 100 BMC";
+ compatible = "facebook,wedge100-bmc", "aspeed,ast2400";
+
+ aliases {
+ /*
+ * Override the default uart aliases to avoid breaking
+ * the legacy applications.
+ */
+ serial0 = &uart5;
+ serial1 = &uart1;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ };
+
+ chosen {
+ stdout-path = &uart3;
+ bootargs = "console=ttyS2,9600n8 root=/dev/ram rw";
+ };
+
+ memory@40000000 {
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&wdt1 {
+ status = "okay";
+ aspeed,reset-type = "system";
+};
+
+&wdt2 {
+ status = "okay";
+ aspeed,reset-type = "system";
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "fmc0";
+#include "facebook-bmc-flash-layout.dtsi"
+ };
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&uart3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd3_default
+ &pinctrl_rxd3_default>;
+};
+
+&uart4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd4_default
+ &pinctrl_rxd4_default>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac1 {
+ status = "okay";
+ no-hw-checksum;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+};
+
+&i2c9 {
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+};
+
+&i2c12 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&vhub {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts
new file mode 100644
index 000000000000..aaa77a597d1a
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2018 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g4.dtsi"
+
+/ {
+ model = "Facebook Wedge 40 BMC";
+ compatible = "facebook,wedge40-bmc", "aspeed,ast2400";
+
+ aliases {
+ /*
+ * Override the default uart aliases to avoid breaking
+ * the legacy applications.
+ */
+ serial0 = &uart5;
+ serial1 = &uart1;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ };
+
+ chosen {
+ stdout-path = &uart3;
+ bootargs = "console=ttyS2,9600n8 root=/dev/ram rw";
+ };
+
+ memory@40000000 {
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&wdt1 {
+ status = "okay";
+ aspeed,reset-type = "system";
+};
+
+&wdt2 {
+ status = "disabled";
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "fmc0";
+#include "facebook-bmc-flash-layout.dtsi"
+ };
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&uart3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd3_default
+ &pinctrl_rxd3_default>;
+};
+
+&uart4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd4_default
+ &pinctrl_rxd4_default>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac1 {
+ status = "okay";
+ no-hw-checksum;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&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";
+};
+
+&vhub {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts b/arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts
index 628195b66d46..e9d714a46a60 100644
--- a/arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts
@@ -725,9 +725,9 @@
reg = <0x58>;
};
- power-supply@5a {
+ power-supply@59 {
compatible = "pmbus";
- reg = <0x5a>;
+ reg = <0x59>;
};
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts b/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts
new file mode 100644
index 000000000000..118eb8bbbf1b
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts
@@ -0,0 +1,663 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Device Tree file for Lenovo Hr855xg2 platform
+ *
+ * Copyright (C) 2019-present Lenovo
+ */
+
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+ model = "HR855XG2 BMC";
+ compatible = "lenovo,hr855xg2-bmc", "aspeed,ast2500";
+
+ aliases {
+ i2c14 = &i2c_riser1;
+ i2c15 = &i2c_riser2;
+ i2c16 = &i2c_riser3;
+ i2c17 = &i2c_M2;
+ i2c18 = &channel_0;
+ i2c19 = &channel_1;
+ i2c20 = &channel_2;
+ i2c21 = &channel_3;
+ };
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=tty0 console=ttyS4,115200 earlyprintk";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ flash_memory: region@98000000 {
+ no-map;
+ reg = <0x98000000 0x00100000>; /* 1M */
+ };
+
+ gfx_memory: framebuffer {
+ size = <0x01000000>;
+ alignment = <0x01000000>;
+ compatible = "shared-dma-pool";
+ reusable;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ heartbeat {
+ gpios = <&gpio ASPEED_GPIO(C, 7) GPIO_ACTIVE_LOW>;
+ };
+
+ fault {
+ gpios = <&gpio ASPEED_GPIO(G, 3) GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>,
+ <&adc 8>, <&adc 9>, <&adc 10>,<&adc 11>,
+ <&adc 12>,<&adc 13>,<&adc 14>;
+ };
+
+ iio-hwmon-battery {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 15>;
+ };
+
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+ spi-max-frequency = <50000000>;
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&lpc_ctrl {
+ status = "okay";
+ memory-region = <&flash_memory>;
+ flash = <&spi1>;
+};
+
+&lpc_snoop {
+ status = "okay";
+ snoop-ports = <0x80>;
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&uart2 {
+ /* Rear RS-232 connector */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd2_default
+ &pinctrl_rxd2_default
+ &pinctrl_nrts2_default
+ &pinctrl_ndtr2_default
+ &pinctrl_ndsr2_default
+ &pinctrl_ncts2_default
+ &pinctrl_ndcd2_default
+ &pinctrl_nri2_default>;
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&ibt {
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ use-ncsi;
+};
+
+&mac1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&adc{
+ status = "okay";
+ 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
+ &pinctrl_adc8_default
+ &pinctrl_adc9_default
+ &pinctrl_adc10_default
+ &pinctrl_adc11_default
+ &pinctrl_adc12_default
+ &pinctrl_adc13_default
+ &pinctrl_adc14_default
+ &pinctrl_adc15_default>;
+};
+
+&i2c0 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9545";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c_riser1: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c_riser2: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ i2c_riser3: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ i2c_M2: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ bus-frequency = <90000>;
+ HotSwap@10 {
+ compatible = "adm1272";
+ reg = <0x10>;
+ };
+
+ VR@45 {
+ compatible = "pmbus";
+ reg = <0x45>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+ i2c-switch@70 {
+ compatible = "nxp,pca9546";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel_0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ channel_1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ channel_2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ channel_3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+ };
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+ /* temp1 */
+ tmp75@49 {
+ compatible = "national,lm75";
+ reg = <0x49>;
+ };
+
+ /* temp2 */
+ tmp75@4d {
+ compatible = "national,lm75";
+ reg = <0x4d>;
+ };
+
+ eeprom@54 {
+ compatible = "atmel,24c256";
+ reg = <0x54>;
+ pagesize = <16>;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c8 {
+ status = "okay";
+};
+
+&i2c9 {
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&uhci {
+ status = "okay";
+};
+
+&gfx {
+ status = "okay";
+ memory-region = <&gfx_memory>;
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default
+ &pinctrl_pwm1_default
+ &pinctrl_pwm2_default
+ &pinctrl_pwm3_default
+ &pinctrl_pwm4_default
+ &pinctrl_pwm5_default
+ &pinctrl_pwm6_default
+ &pinctrl_pwm7_default>;
+
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
+ };
+
+ fan@1 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
+ };
+
+ fan@2 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x02>;
+ };
+
+ fan@3 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x03>;
+ };
+
+ fan@4 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x04>;
+ };
+
+ fan@5 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x05>;
+ };
+
+ fan@6 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x06>;
+ };
+
+ fan@7 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x07>;
+ };
+
+ fan@8 {
+ reg = <0x04>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x08>;
+ };
+
+ fan@9 {
+ reg = <0x04>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x09>;
+ };
+
+ fan@10 {
+ reg = <0x05>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0a>;
+ };
+
+ fan@11 {
+ reg = <0x05>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0b>;
+ };
+
+ fan@12 {
+ reg = <0x06>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0c>;
+ };
+
+ fan@13 {
+ reg = <0x06>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0d>;
+ };
+
+ fan@14 {
+ reg = <0x07>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0e>;
+ };
+
+ fan@15 {
+ reg = <0x07>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0f>;
+ };
+
+ fan@16 {
+ reg = <0x07>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0f>;
+ };
+};
+
+&gpio {
+
+ pin_gpio_a1 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(A, 1) GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "BMC_EMMC_RST_N";
+ };
+
+ pin_gpio_a3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(A, 3) GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "PCH_PWROK_BMC_FPGA";
+ };
+
+ pin_gpio_b5 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "IRQ_BMC_PCH_SMI_LPC_N";
+ };
+
+ pin_gpio_b7 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(B, 7) GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "CPU_SM_WP";
+ };
+
+ pin_gpio_e0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(E, 0) GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "PDB_PSU_SEL";
+ };
+
+ pin_gpio_e2 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(E, 2) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "LOCATOR_LED_N";
+ };
+
+ pin_gpio_e5 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(E, 5) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_BMC_DBP_PRESENT_R1_N";
+ };
+
+ pin_gpio_e6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(E, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_ME_SECURITY_OVERRIDE_N";
+ };
+
+ pin_gpio_f0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 0) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "IRQ_BMC_PCH_NMI_R";
+ };
+
+ pin_gpio_f1 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 1) GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "CPU2_PROCDIS_BMC_N";
+ };
+
+ pin_gpio_f2 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 2) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "RM_THROTTLE_EN_N";
+ };
+
+ pin_gpio_f3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 3) GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "FM_PMBUS_ALERT_B_EN";
+ };
+
+ pin_gpio_f4 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 4) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_FORCE_NM_THROTTLE_N";
+ };
+
+ pin_gpio_f6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(F, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_BMC_CPU_PWR_DEBUG_N";
+ };
+
+ pin_gpio_g7 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(G, 7) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_PCIE_I2C_MUX_RST_N";
+ };
+
+ pin_gpio_h6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(H, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_BMC_DBP_PRESENT_R2_N";
+ };
+
+ pin_gpio_i3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(I, 3) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "SPI_BMC_BIOS_WP_N";
+ };
+
+ pin_gpio_j1 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(J, 1) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_USB_SEL";
+ };
+
+ pin_gpio_j2 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(J, 2) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "PDB_SMB_RST_N";
+ };
+
+ pin_gpio_j3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(J, 3) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "SPI_BMC_BIOS_HOLD_N";
+ };
+
+ pin_gpio_l0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(L, 0) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "PDB_FAN_TACH_SEL";
+ };
+
+ pin_gpio_l1 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(L, 1) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "SYS_RESET_BMC_FPGA_N";
+ };
+
+ pin_gpio_l4 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_EFUSE_FAN_G1_EN";
+ };
+
+ pin_gpio_l5 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(L, 5) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_EFUSE_FAN_G2_EN";
+ };
+
+ pin_gpio_r6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(R, 6) GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "CPU3_PROCDIS_BMC_N";
+ };
+
+ pin_gpio_r7 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "CPU4_PROCDIS_BMC_N";
+ };
+
+ pin_gpio_s1 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(S, 1) GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "DBP_SYSPWROK_BMC";
+ };
+
+ pin_gpio_s2 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(S, 2) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "PCH_RST_RSMRST_N";
+ };
+
+ pin_gpio_s6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(S, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_HW_STRAP_5";
+ };
+
+ pin_gpio_z3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FM_BMC_PCH_SCI_LPC_N";
+ };
+
+ pin_gpio_aa0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "FW_PSU_ALERT_EN_N";
+ };
+
+ pin_gpio_aa4 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AA, 4) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "DBP_CPU_PREQ_N";
+ };
+
+ pin_gpio_ab3 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AB, 3) GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "BMC_WDTRST";
+ };
+
+ pin_gpio_ac6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AC, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "ESPI_BMC_ALERT_N";
+ };
+
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts b/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts
new file mode 100644
index 000000000000..e55cc454b17f
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts
@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/leds/leds-pca955x.h>
+
+/ {
+ model = "Mihawk BMC";
+ compatible = "ibm,mihawk-bmc", "aspeed,ast2500";
+
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=ttyS4,115200 earlyprintk";
+ };
+
+ memory@80000000 {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ flash_memory: region@98000000 {
+ no-map;
+ reg = <0x98000000 0x04000000>; /* 64M */
+ };
+
+ gfx_memory: framebuffer {
+ size = <0x01000000>;
+ alignment = <0x01000000>;
+ compatible = "shared-dma-pool";
+ reusable;
+ };
+
+ video_engine_memory: jpegbuffer {
+ size = <0x02000000>;
+ alignment = <0x01000000>;
+ compatible = "shared-dma-pool";
+ reusable;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ air-water {
+ label = "air-water";
+ gpios = <&gpio ASPEED_GPIO(F, 6) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(F, 6)>;
+ };
+
+ checkstop {
+ label = "checkstop";
+ gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(J, 2)>;
+ };
+
+ ps0-presence {
+ label = "ps0-presence";
+ gpios = <&gpio ASPEED_GPIO(Z, 2) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(Z, 2)>;
+ };
+
+ ps1-presence {
+ label = "ps1-presence";
+ gpios = <&gpio ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(Z, 0)>;
+ };
+ id-button {
+ label = "id-button";
+ gpios = <&gpio ASPEED_GPIO(F, 1) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(F, 1)>;
+ };
+ };
+
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ poll-interval = <1000>;
+
+ fan0-presence {
+ label = "fan0-presence";
+ gpios = <&pca9552 9 GPIO_ACTIVE_LOW>;
+ linux,code = <9>;
+ };
+
+ fan1-presence {
+ label = "fan1-presence";
+ gpios = <&pca9552 10 GPIO_ACTIVE_LOW>;
+ linux,code = <10>;
+ };
+
+ fan2-presence {
+ label = "fan2-presence";
+ gpios = <&pca9552 11 GPIO_ACTIVE_LOW>;
+ linux,code = <11>;
+ };
+
+ fan3-presence {
+ label = "fan3-presence";
+ gpios = <&pca9552 12 GPIO_ACTIVE_LOW>;
+ linux,code = <12>;
+ };
+
+ fan4-presence {
+ label = "fan4-presence";
+ gpios = <&pca9552 13 GPIO_ACTIVE_LOW>;
+ linux,code = <13>;
+ };
+
+ fan5-presence {
+ label = "fan5-presence";
+ gpios = <&pca9552 14 GPIO_ACTIVE_LOW>;
+ linux,code = <14>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ fault {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_LOW>;
+ };
+
+ power {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&gpio ASPEED_GPIO(AA, 1) GPIO_ACTIVE_LOW>;
+ };
+
+ rear-id {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&gpio ASPEED_GPIO(AA, 2) GPIO_ACTIVE_LOW>;
+ };
+
+ rear-g {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&gpio ASPEED_GPIO(AA, 4) GPIO_ACTIVE_LOW>;
+ };
+
+ rear-ok {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&gpio ASPEED_GPIO(Y, 0) GPIO_ACTIVE_LOW>;
+ };
+
+ fan0 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 0 GPIO_ACTIVE_LOW>;
+ };
+
+ fan1 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 1 GPIO_ACTIVE_LOW>;
+ };
+
+ fan2 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 2 GPIO_ACTIVE_LOW>;
+ };
+
+ fan3 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 3 GPIO_ACTIVE_LOW>;
+ };
+
+ fan4 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 4 GPIO_ACTIVE_LOW>;
+ };
+
+ fan5 {
+ retain-state-shutdown;
+ default-state = "keep";
+ gpios = <&pca9552 5 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ fsi: gpio-fsi {
+ compatible = "fsi-master-gpio", "fsi-master";
+ #address-cells = <2>;
+ #size-cells = <0>;
+ no-gpio-delays;
+
+ clock-gpios = <&gpio ASPEED_GPIO(E, 6) GPIO_ACTIVE_HIGH>;
+ data-gpios = <&gpio ASPEED_GPIO(E, 7) GPIO_ACTIVE_HIGH>;
+ mux-gpios = <&gpio ASPEED_GPIO(E, 5) GPIO_ACTIVE_HIGH>;
+ enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
+ trans-gpios = <&gpio ASPEED_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
+ };
+ iio-hwmon-12v {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>;
+ };
+
+ iio-hwmon-5v {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 1>;
+ };
+
+ iio-hwmon-3v {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 2>;
+ };
+
+ iio-hwmon-vdd0 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 3>;
+ };
+
+ iio-hwmon-vdd1 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 4>;
+ };
+
+ iio-hwmon-vcs0 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 5>;
+ };
+
+ iio-hwmon-vcs1 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 6>;
+ };
+
+ iio-hwmon-vdn0 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 7>;
+ };
+
+ iio-hwmon-vdn1 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 8>;
+ };
+
+ iio-hwmon-vio0 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 9>;
+ };
+
+ iio-hwmon-vio1 {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 10>;
+ };
+
+ iio-hwmon-vddra {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 11>;
+ };
+
+ iio-hwmon-battery {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 12>;
+ };
+
+ iio-hwmon-vddrb {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 13>;
+ };
+
+ iio-hwmon-vddrc {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 14>;
+ };
+
+ iio-hwmon-vddrd {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 15>;
+ };
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+ &pinctrl_pwm2_default &pinctrl_pwm3_default
+ &pinctrl_pwm4_default &pinctrl_pwm5_default>;
+
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
+ };
+
+ fan@1 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
+ };
+
+ fan@2 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x02>;
+ };
+
+ fan@3 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x03>;
+ };
+
+ fan@4 {
+ reg = <0x04>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x04>;
+ };
+
+ fan@5 {
+ reg = <0x05>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x05>;
+ };
+
+ fan@6 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x06>;
+ };
+
+ fan@7 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x07>;
+ };
+
+ fan@8 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x08>;
+ };
+
+ fan@9 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x09>;
+ };
+
+ fan@10 {
+ reg = <0x04>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0a>;
+ };
+
+ fan@11 {
+ reg = <0x05>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0b>;
+ };
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ label = "bmc";
+ m25p,fast-read;
+ spi-max-frequency = <50000000>;
+ partitions {
+ #address-cells = < 1 >;
+ #size-cells = < 1 >;
+ compatible = "fixed-partitions";
+ u-boot@0 {
+ reg = < 0 0x60000 >;
+ label = "u-boot";
+ };
+ u-boot-env@60000 {
+ reg = < 0x60000 0x20000 >;
+ label = "u-boot-env";
+ };
+ obmc-ubi@80000 {
+ reg = < 0x80000 0x1F80000 >;
+ label = "obmc-ubi";
+ };
+ };
+ };
+ flash@1 {
+ status = "okay";
+ label = "alt-bmc";
+ m25p,fast-read;
+ spi-max-frequency = <50000000>;
+ partitions {
+ #address-cells = < 1 >;
+ #size-cells = < 1 >;
+ compatible = "fixed-partitions";
+ u-boot@0 {
+ reg = < 0 0x60000 >;
+ label = "alt-u-boot";
+ };
+ u-boot-env@60000 {
+ reg = < 0x60000 0x20000 >;
+ label = "alt-u-boot-env";
+ };
+ obmc-ubi@80000 {
+ reg = < 0x80000 0x1F80000 >;
+ label = "alt-obmc-ubi";
+ };
+ };
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+
+ flash@0 {
+ status = "okay";
+ label = "pnor";
+ m25p,fast-read;
+ spi-max-frequency = <100000000>;
+ };
+};
+
+&lpc_ctrl {
+ status = "okay";
+ memory-region = <&flash_memory>;
+ flash = <&spi1>;
+};
+
+&uart1 {
+ /* Rear RS-232 connector */
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default
+ &pinctrl_nrts1_default
+ &pinctrl_ndtr1_default
+ &pinctrl_ndsr1_default
+ &pinctrl_ncts1_default
+ &pinctrl_ndcd1_default
+ &pinctrl_nri1_default>;
+};
+
+&uart2 {
+ /* APSS */
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd2_default &pinctrl_rxd2_default>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ use-ncsi;
+};
+
+&mac1 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "disabled";
+};
+
+&i2c1 {
+ status = "disabled";
+};
+
+&i2c2 {
+ status = "okay";
+
+ /* SAMTEC P0 */
+ /* SAMTEC P1 */
+
+};
+
+&i2c3 {
+ status = "okay";
+
+ /* APSS */
+ /* CPLD */
+
+ /* PCA9516 (repeater) ->
+ * CLK Buffer 9FGS9092
+ * CLK Buffer 9DBL0651BKILFT
+ * CLK Buffer 9DBL0651BKILFT
+ * Power Supply 0
+ * Power Supply 1
+ * PCA 9552 LED
+ */
+
+ power-supply@58 {
+ compatible = "ibm,cffps1";
+ reg = <0x58>;
+ };
+
+ power-supply@5b {
+ compatible = "ibm,cffps1";
+ reg = <0x5b>;
+ };
+
+ pca9552: pca9552@60 {
+ compatible = "nxp,pca9552";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@7 {
+ reg = <7>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@8 {
+ reg = <8>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@9 {
+ reg = <9>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@10 {
+ reg = <10>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@11 {
+ reg = <11>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@12 {
+ reg = <12>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@13 {
+ reg = <13>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@14 {
+ reg = <14>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ gpio@15 {
+ reg = <15>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ };
+
+};
+
+&i2c4 {
+ status = "okay";
+
+ /* CP0 VDD & VCS : IR35221 */
+ /* CP0 VDN : IR35221 */
+ /* CP0 VIO : IR38064 */
+ /* CP0 VDDR : PXM1330 */
+
+ ir35221@70 {
+ compatible = "infineon,ir35221";
+ reg = <0x70>;
+ };
+
+ ir35221@72 {
+ compatible = "infineon,ir35221";
+ reg = <0x72>;
+ };
+
+};
+
+&i2c5 {
+ status = "okay";
+
+ /* CP0 VDD & VCS : IR35221 */
+ /* CP0 VDN : IR35221 */
+ /* CP0 VIO : IR38064 */
+ /* CP0 VDDR : PXM1330 */
+
+ ir35221@70 {
+ compatible = "infineon,ir35221";
+ reg = <0x70>;
+ };
+
+ ir35221@72 {
+ compatible = "infineon,ir35221";
+ reg = <0x72>;
+ };
+
+};
+
+&i2c6 {
+ status = "okay";
+
+ /* pca9548 -> NVMe1 to 8 */
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ };
+
+};
+
+&i2c7 {
+ status = "okay";
+
+ /* pca9548 -> NVMe9 to 16 */
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ };
+
+};
+
+&i2c8 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+};
+
+&i2c9 {
+ status = "okay";
+
+ /* pca9545 Riser ->
+ * PCIe x8 Slot3
+ * PCIe x16 slot4
+ * PCIe x8 slot5
+ * I2C BMC RISER PCA9554
+ * BMC SCL/SDA PCA9554
+ * PCA9554
+ */
+
+ /* pca9545 ->
+ * PCIe x16 Slot1
+ * PCIe x8 slot2
+ * PEX8748
+ */
+
+ pca9545riser@70 {
+ compatible = "nxp,pca9545";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ i2c-mux-idle-disconnect;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pca9545@71 {
+ compatible = "nxp,pca9545";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+
+ i2c-mux-idle-disconnect;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
+
+&i2c10 {
+ status = "okay";
+
+ /* pca9545 Riser ->
+ * PCIe x8 Slot8
+ * PCIe x16 slot9
+ * PCIe x8 slot10
+ * I2C BMC RISER PCA9554
+ * BMC SCL/SDA PCA9554
+ * PCA9554
+ */
+
+ /* pca9545 ->
+ * PCIe x16 Slot1
+ * PCIe x8 slot2
+ * PEX8748
+ */
+
+ pca9545riser@70 {
+ compatible = "nxp,pca9545";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ i2c-mux-idle-disconnect;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pca9545@71 {
+ compatible = "nxp,pca9545";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+
+ i2c-mux-idle-disconnect;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
+
+&i2c11 {
+ status = "okay";
+
+ /* TPM */
+ /* RTC RX8900CE */
+ /* FPGA for power sequence */
+ /* TMP275A */
+ /* TMP275A */
+ /* EMC1462 */
+
+ tpm@57 {
+ compatible = "infineon,slb9645tt";
+ reg = <0x57>;
+ };
+
+ rtc@32 {
+ compatible = "epson,rx8900";
+ reg = <0x32>;
+ };
+
+ tmp275@48 {
+ compatible = "ti,tmp275";
+ reg = <0x48>;
+ };
+
+ tmp275@49 {
+ compatible = "ti,tmp275";
+ reg = <0x49>;
+ };
+
+ /* chip emc1462 use emc1403 driver */
+ emc1403@4c {
+ compatible = "smsc,emc1403";
+ reg = <0x4c>;
+ };
+
+};
+
+&i2c12 {
+ status = "okay";
+
+ /* pca9545 ->
+ * SAS BP1
+ * SAS BP2
+ * NVMe BP
+ * M.2 riser
+ */
+
+ pca9545@70 {
+ compatible = "nxp,pca9545";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ tmp275@48 {
+ compatible = "ti,tmp275";
+ reg = <0x48>;
+ };
+ };
+
+ };
+
+};
+
+&i2c13 {
+ status = "okay";
+
+ /* pca9548 ->
+ * NVMe BP
+ * NVMe HDD17 to 24
+ */
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ };
+};
+
+&vuart {
+ status = "okay";
+};
+
+&gfx {
+ status = "okay";
+ memory-region = <&gfx_memory>;
+};
+
+&adc {
+ status = "okay";
+ 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
+ &pinctrl_adc8_default
+ &pinctrl_adc9_default
+ &pinctrl_adc10_default
+ &pinctrl_adc11_default
+ &pinctrl_adc12_default
+ &pinctrl_adc13_default
+ &pinctrl_adc14_default
+ &pinctrl_adc15_default>;
+};
+
+&wdt1 {
+ aspeed,reset-type = "none";
+ aspeed,external-signal;
+ aspeed,ext-push-pull;
+ aspeed,ext-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdtrst1_default>;
+};
+
+&wdt2 {
+ aspeed,alt-boot;
+};
+
+&ibt {
+ status = "okay";
+};
+
+&vhub {
+ status = "okay";
+};
+
+&video {
+ status = "okay";
+ memory-region = <&video_engine_memory>;
+};
+
+#include "ibm-power9-dual.dtsi"
+
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts
index caac895c60b4..f67fef1ac5e1 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts
@@ -207,8 +207,8 @@
#size-cells = <0>;
no-gpio-delays;
- clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
- data-gpios = <&gpio ASPEED_GPIO(E, 0) GPIO_ACTIVE_HIGH>;
+ clock-gpios = <&gpio ASPEED_GPIO(P, 1) GPIO_ACTIVE_HIGH>;
+ data-gpios = <&gpio ASPEED_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
mux-gpios = <&gpio ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
enable-gpios = <&gpio ASPEED_GPIO(P, 0) GPIO_ACTIVE_HIGH>;
trans-gpios = <&gpio ASPEED_GPIO(P, 3) GPIO_ACTIVE_HIGH>;
@@ -494,7 +494,7 @@
};
power-supply@68 {
- compatible = "ibm,cffps1";
+ compatible = "ibm,cffps2";
reg = <0x68>;
};
@@ -504,7 +504,7 @@
};
power-supply@69 {
- compatible = "ibm,cffps1";
+ compatible = "ibm,cffps2";
reg = <0x69>;
};
@@ -963,4 +963,15 @@
status = "okay";
};
+&sdmmc {
+ status = "okay";
+};
+
+&sdhci1 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sd2_default>;
+};
+
#include "ibm-power9-dual.dtsi"
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts b/arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts
index 0b9e29c3212e..a27c88d23056 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts
@@ -81,6 +81,12 @@
label = "bmc";
#include "openbmc-flash-layout.dtsi"
};
+
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "alt";
+ };
};
&spi {
@@ -222,3 +228,7 @@
&vuart {
status = "okay";
};
+
+&wdt2 {
+ aspeed,alt-boot;
+};
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index dd4b0b15afcf..dffb595d30e4 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -67,6 +67,26 @@
compatible = "jedec,spi-nor";
status = "disabled";
};
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor";
+ status = "disabled";
+ };
+ flash@2 {
+ reg = < 2 >;
+ compatible = "jedec,spi-nor";
+ status = "disabled";
+ };
+ flash@3 {
+ reg = < 3 >;
+ compatible = "jedec,spi-nor";
+ status = "disabled";
+ };
+ flash@4 {
+ reg = < 4 >;
+ compatible = "jedec,spi-nor";
+ status = "disabled";
+ };
};
spi: spi@1e630000 {
@@ -192,6 +212,34 @@
reg = <0x1e720000 0x8000>; // 32K
};
+ sdmmc: sd-controller@1e740000 {
+ compatible = "aspeed,ast2400-sd-controller";
+ reg = <0x1e740000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1e740000 0x10000>;
+ clocks = <&syscon ASPEED_CLK_GATE_SDCLK>;
+ status = "disabled";
+
+ sdhci0: sdhci@100 {
+ compatible = "aspeed,ast2400-sdhci";
+ reg = <0x100 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ status = "disabled";
+ };
+
+ sdhci1: sdhci@200 {
+ compatible = "aspeed,ast2400-sdhci";
+ reg = <0x200 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ status = "disabled";
+ };
+ };
+
gpio: gpio@1e780000 {
#gpio-cells = <2>;
gpio-controller;
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 5b1ca265c2ce..e8feb8b66a2f 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -267,13 +267,41 @@
reg = <0x1e720000 0x9000>; // 36K
};
+ sdmmc: sd-controller@1e740000 {
+ compatible = "aspeed,ast2500-sd-controller";
+ reg = <0x1e740000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1e740000 0x10000>;
+ clocks = <&syscon ASPEED_CLK_GATE_SDCLK>;
+ status = "disabled";
+
+ sdhci0: sdhci@100 {
+ compatible = "aspeed,ast2500-sdhci";
+ reg = <0x100 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ status = "disabled";
+ };
+
+ sdhci1: sdhci@200 {
+ compatible = "aspeed,ast2500-sdhci";
+ reg = <0x200 0x100>;
+ interrupts = <26>;
+ sdhci,auto-cmd12;
+ clocks = <&syscon ASPEED_CLK_SDIO>;
+ status = "disabled";
+ };
+ };
+
gpio: gpio@1e780000 {
#gpio-cells = <2>;
gpio-controller;
compatible = "aspeed,ast2500-gpio";
reg = <0x1e780000 0x1000>;
interrupts = <20>;
- gpio-ranges = <&pinctrl 0 0 220>;
+ gpio-ranges = <&pinctrl 0 0 232>;
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -1346,6 +1374,11 @@
groups = "SDA2";
};
+ pinctrl_sgpm_default: sgpm_default {
+ function = "SGPM";
+ groups = "SGPM";
+ };
+
pinctrl_sgps1_default: sgps1_default {
function = "SGPS1";
groups = "SGPS1";
diff --git a/arch/arm/boot/dts/at91-ariag25.dts b/arch/arm/boot/dts/at91-ariag25.dts
index 0d695c762e54..dbfefef2869d 100644
--- a/arch/arm/boot/dts/at91-ariag25.dts
+++ b/arch/arm/boot/dts/at91-ariag25.dts
@@ -14,11 +14,6 @@
"atmel,at91sam9x5", "atmel,at91sam9";
aliases {
- serial0 = &dbgu;
- serial1 = &usart0;
- serial2 = &usart1;
- serial3 = &usart2;
- serial4 = &usart3;
serial5 = &uart0;
serial6 = &uart1;
};
@@ -42,132 +37,6 @@
};
};
- ahb {
- apb {
- mmc0: mmc@f0008000 {
- /* N.B. Aria has no SD card detect (CD), assumed present */
-
- pinctrl-0 = <
- &pinctrl_mmc0_slot0_clk_cmd_dat0
- &pinctrl_mmc0_slot0_dat1_3>;
- status = "okay";
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- };
- };
-
- tcb0: timer@f8008000 {
- timer@0 {
- compatible = "atmel,tcb-timer";
- reg = <0>;
- };
-
- timer@1 {
- compatible = "atmel,tcb-timer";
- reg = <1>;
- };
- };
-
- i2c0: i2c@f8010000 {
- status = "okay";
- };
-
- i2c1: i2c@f8014000 {
- status = "okay";
- };
-
- /* TWD2+TCLK2 hidden behind ethernet, so no i2c2 */
-
- usart0: serial@f801c000 {
- pinctrl-0 = <&pinctrl_usart0
- &pinctrl_usart0_rts
- &pinctrl_usart0_cts>;
- status = "okay";
- };
-
- usart1: serial@f8020000 {
- pinctrl-0 = <&pinctrl_usart1
- /* &pinctrl_usart1_rts */
- /* &pinctrl_usart1_cts */
- >;
- status = "okay";
- };
-
- usart2: serial@f8024000 {
- /* cannot activate RTS2+CTS2, clash with
- * ethernet on PB0 and PB1 */
- pinctrl-0 = <&pinctrl_usart2>;
- status = "okay";
- };
-
- usart3: serial@f8028000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8028000 0x200>;
- interrupts = <8 4 5>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usart3
- /* &pinctrl_usart3_rts */
- /* &pinctrl_usart3_cts */
- >;
- status = "okay";
- };
-
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- /*
- * following can be overwritten by bootloader:
- * for example u-boot 'ftd set' command
- */
- local-mac-address = [00 00 00 00 00 00];
- status = "okay";
- };
-
- /*
- * UART0/1 pins are marked as GPIO on
- * Aria documentation.
- * Change to "okay" if you need additional serial ports
- */
- uart0: serial@f8040000 {
- status = "disabled";
- };
-
- uart1: serial@f8044000 {
- status = "disabled";
- };
-
- adc0: adc@f804c000 {
- status = "okay";
- atmel,adc-channels-used = <0xf>;
- };
-
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- pinctrl@fffff400 {
- w1_0 {
- pinctrl_w1_0: w1_0-0 {
- atmel,pins = <0 21 0x0 0x1>; /* PA21 PIO, pull-up */
- };
- };
- };
-
- rtc@fffffeb0 {
- status = "okay";
- };
- };
-
- usb0: ohci@600000 {
- status = "okay";
- num-ports = <3>;
- };
-
- usb1: ehci@700000 {
- status = "okay";
- };
- };
-
leds {
compatible = "gpio-leds";
@@ -187,3 +56,127 @@
pinctrl-0 = <&pinctrl_w1_0>;
};
};
+
+&adc0 {
+ status = "okay";
+ atmel,adc-channels-used = <0xf>;
+};
+
+&dbgu {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+/* TWD2+TCLK2 hidden behind ethernet, so no i2c2 */
+
+&macb0 {
+ phy-mode = "rmii";
+ /*
+ * following can be overwritten by bootloader:
+ * for example u-boot 'ftd set' command
+ */
+ local-mac-address = [00 00 00 00 00 00];
+ status = "okay";
+};
+
+
+&mmc0 {
+ /* N.B. Aria has no SD card detect (CD), assumed present */
+
+ pinctrl-0 = <
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ };
+};
+
+&pinctrl {
+ w1_0 {
+ pinctrl_w1_0: w1_0-0 {
+ atmel,pins = <0 21 0x0 0x1>; /* PA21 PIO, pull-up */
+ };
+ };
+};
+
+&rtc {
+ status = "okay";
+};
+
+&tcb0 {
+ timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
+ };
+};
+
+/*
+ * UART0/1 pins are marked as GPIO on
+ * Aria documentation.
+ * Change to "okay" if you need additional serial ports
+ */
+&uart0 {
+ status = "disabled";
+};
+
+&uart1 {
+ status = "disabled";
+};
+
+&usart0 {
+ pinctrl-0 = <&pinctrl_usart0
+ &pinctrl_usart0_rts
+ &pinctrl_usart0_cts>;
+ status = "okay";
+};
+
+&usart1 {
+ pinctrl-0 = <&pinctrl_usart1
+ /* &pinctrl_usart1_rts */
+ /* &pinctrl_usart1_cts */
+ >;
+ status = "okay";
+};
+
+&usart2 {
+ /* cannot activate RTS2+CTS2, clash with
+ * ethernet on PB0 and PB1 */
+ pinctrl-0 = <&pinctrl_usart2>;
+ status = "okay";
+};
+
+&usart3 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xf8028000 0x200>;
+ interrupts = <8 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart3
+ /* &pinctrl_usart3_rts */
+ /* &pinctrl_usart3_cts */
+ >;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+ num-ports = <3>;
+};
+
+&usb1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-ariettag25.dts b/arch/arm/boot/dts/at91-ariettag25.dts
index 7a34c4dc05d2..0267e72c074a 100644
--- a/arch/arm/boot/dts/at91-ariettag25.dts
+++ b/arch/arm/boot/dts/at91-ariettag25.dts
@@ -6,14 +6,11 @@
*/
/dts-v1/;
#include "at91sam9g25.dtsi"
+
/ {
model = "Acme Systems Arietta G25";
compatible = "acme,ariettag25", "atmel,at91sam9x5", "atmel,at91sam9";
- aliases {
- serial0 = &dbgu;
- };
-
chosen {
stdout-path = "serial0:115200n8";
};
@@ -32,57 +29,9 @@
};
};
- ahb {
- apb {
- mmc0: mmc@f0008000 {
- pinctrl-0 = <
- &pinctrl_mmc0_slot0_clk_cmd_dat0
- &pinctrl_mmc0_slot0_dat1_3>;
- status = "okay";
-
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- };
- };
-
- tcb0: timer@f8008000 {
- timer@0 {
- compatible = "atmel,tcb-timer";
- reg = <0>;
- };
-
- timer@1 {
- compatible = "atmel,tcb-timer";
- reg = <1>;
- };
- };
-
- usb2: gadget@f803c000 {
- status = "okay";
- };
-
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- rtc@fffffeb0 {
- status = "okay";
- };
- };
-
- usb0: ohci@600000 {
- status = "okay";
- num-ports = <3>;
- };
-
- usb1: ehci@700000 {
- status = "okay";
- };
- };
-
leds {
compatible = "gpio-leds";
+
arietta_led {
label = "arietta_led";
gpios = <&pioB 8 GPIO_ACTIVE_HIGH>; /* PB8 */
@@ -90,3 +39,48 @@
};
};
};
+
+&dbgu {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-0 = <
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ };
+};
+
+&rtc {
+ status = "okay";
+};
+
+&tcb0 {
+ timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
+ };
+};
+
+&usb0 {
+ num-ports = <3>;
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&usb2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-cosino.dtsi b/arch/arm/boot/dts/at91-cosino.dtsi
index 47721c9a2e42..feebd54f670e 100644
--- a/arch/arm/boot/dts/at91-cosino.dtsi
+++ b/arch/arm/boot/dts/at91-cosino.dtsi
@@ -33,122 +33,119 @@
clock-frequency = <12000000>;
};
};
+};
- ahb {
- apb {
- tcb0: timer@f8008000 {
- timer@0 {
- compatible = "atmel,tcb-timer";
- reg = <0>;
- };
+&adc0 {
+ atmel,adc-ts-wires = <4>;
+ atmel,adc-ts-pressure-threshold = <10000>;
+ status = "okay";
+};
+
+&dbgu {
+ status = "okay";
+};
- timer@1 {
- compatible = "atmel,tcb-timer";
- reg = <1>;
+&ebi {
+ pinctrl-0 = <&pinctrl_ebi_addr_nand
+ &pinctrl_ebi_data_0_7>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ nand-controller {
+ pinctrl-0 = <&pinctrl_nand_oe_we
+ &pinctrl_nand_cs
+ &pinctrl_nand_rb>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ nand@3 {
+ reg = <0x3 0x0 0x800000>;
+ rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+ nand-on-flash-bbt;
+ label = "atmel_nand";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x40000>;
};
- };
- mmc0: mmc@f0008000 {
- pinctrl-0 = <
- &pinctrl_board_mmc0
- &pinctrl_mmc0_slot0_clk_cmd_dat0
- &pinctrl_mmc0_slot0_dat1_3>;
- status = "okay";
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>;
+ uboot@40000 {
+ label = "u-boot";
+ reg = <0x40000 0x80000>;
};
- };
- dbgu: serial@fffff200 {
- status = "okay";
- };
+ ubootenv@c0000 {
+ label = "U-Boot Env";
+ reg = <0xc0000 0x140000>;
+ };
- usart0: serial@f801c000 {
- status = "okay";
- };
+ kernel@200000 {
+ label = "kernel";
+ reg = <0x200000 0x600000>;
+ };
- i2c0: i2c@f8010000 {
- status = "okay";
+ rootfs@800000 {
+ label = "rootfs";
+ reg = <0x800000 0x0f800000>;
+ };
};
+ };
+ };
+};
- adc0: adc@f804c000 {
- atmel,adc-ts-wires = <4>;
- atmel,adc-ts-pressure-threshold = <10000>;
- status = "okay";
- };
+&i2c0 {
+ status = "okay";
+};
- pinctrl@fffff400 {
- mmc0 {
- pinctrl_board_mmc0: mmc0-board {
- atmel,pins =
- <AT91_PIOD 15 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD15 gpio CD pin pull up and deglitch */
- };
- };
- };
+&mmc0 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>;
+ };
+};
- watchdog@fffffe40 {
- status = "okay";
- };
+&pinctrl {
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <AT91_PIOD 15 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD15 gpio CD pin pull up and deglitch */
};
+ };
+};
- ebi: ebi@10000000 {
- pinctrl-0 = <&pinctrl_ebi_addr_nand
- &pinctrl_ebi_data_0_7>;
- pinctrl-names = "default";
- status = "okay";
-
- nand_controller: nand-controller {
- status = "okay";
- pinctrl-0 = <&pinctrl_nand_oe_we
- &pinctrl_nand_cs
- &pinctrl_nand_rb>;
- pinctrl-names = "default";
-
- nand@3 {
- reg = <0x3 0x0 0x800000>;
- rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
- cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>;
- nand-bus-width = <8>;
- nand-ecc-mode = "hw";
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
- nand-on-flash-bbt;
- label = "atmel_nand";
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- at91bootstrap@0 {
- label = "at91bootstrap";
- reg = <0x0 0x40000>;
- };
-
- uboot@40000 {
- label = "u-boot";
- reg = <0x40000 0x80000>;
- };
-
- ubootenv@c0000 {
- label = "U-Boot Env";
- reg = <0xc0000 0x140000>;
- };
-
- kernel@200000 {
- label = "kernel";
- reg = <0x200000 0x600000>;
- };
-
- rootfs@800000 {
- label = "rootfs";
- reg = <0x800000 0x0f800000>;
- };
- };
- };
- };
- };
+&tcb0 {
+ timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
};
};
+
+&usart0 {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-cosino_mega2560.dts b/arch/arm/boot/dts/at91-cosino_mega2560.dts
index 8fde06adf7cb..73e88d1ba4ed 100644
--- a/arch/arm/boot/dts/at91-cosino_mega2560.dts
+++ b/arch/arm/boot/dts/at91-cosino_mega2560.dts
@@ -17,61 +17,58 @@
/ {
model = "HCE Cosino Mega 2560";
compatible = "hce,cosino_mega2560", "atmel,at91sam9x5", "atmel,at91sam9";
+};
+
+&adc0 {
+ atmel,adc-ts-wires = <4>;
+ atmel,adc-ts-pressure-threshold = <10000>;
+ status = "okay";
+};
- ahb {
- apb {
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
- adc0: adc@f804c000 {
- atmel,adc-ts-wires = <4>;
- atmel,adc-ts-pressure-threshold = <10000>;
- status = "okay";
- };
+&mmc1 {
+ pinctrl-0 = <
+ &pinctrl_mmc1_slot0_clk_cmd_dat0
+ &pinctrl_mmc1_slot0_dat1_3>;
+ status = "okay";
- rtc@fffffeb0 {
- status = "okay";
- };
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ non-removable;
+ };
+};
- usart1: serial@f8020000 {
- status = "okay";
- };
+&rtc {
+ status = "okay";
+};
- usart2: serial@f8024000 {
- status = "okay";
- };
+&usart1 {
+ status = "okay";
+};
- usb2: gadget@f803c000 {
- atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
- status = "okay";
- };
+&usart2 {
+ status = "okay";
+};
- mmc1: mmc@f000c000 {
- pinctrl-0 = <
- &pinctrl_mmc1_slot0_clk_cmd_dat0
- &pinctrl_mmc1_slot0_dat1_3>;
- status = "okay";
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- non-removable;
- };
- };
- };
+&usb0 {
+ num-ports = <3>;
+ atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW */
+ &pioD 19 GPIO_ACTIVE_LOW
+ &pioD 20 GPIO_ACTIVE_LOW
+ >;
+ status = "okay";
+};
- usb0: ohci@600000 {
- status = "okay";
- num-ports = <3>;
- atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW */
- &pioD 19 GPIO_ACTIVE_LOW
- &pioD 20 GPIO_ACTIVE_LOW
- >;
- };
+&usb1 {
+ status = "okay";
+};
- usb1: ehci@700000 {
- status = "okay";
- };
- };
+&usb2 {
+ atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/at91-kizboxmini.dts b/arch/arm/boot/dts/at91-kizboxmini.dts
index 0620dcdf4dfb..cb22f5fb055f 100644
--- a/arch/arm/boot/dts/at91-kizboxmini.dts
+++ b/arch/arm/boot/dts/at91-kizboxmini.dts
@@ -32,96 +32,6 @@
};
ahb {
- apb {
- tcb0: timer@f8008000 {
- timer@0 {
- compatible = "atmel,tcb-timer";
- reg = <0>;
- };
-
- timer@1 {
- compatible = "atmel,tcb-timer";
- reg = <1>;
- };
- };
-
- usart0: serial@f801c000 {
- status = "okay";
- };
-
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
-
- pwm0: pwm@f8034000 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm0_pwm0_1
- &pinctrl_pwm0_pwm1_1>;
- status = "okay";
- };
-
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- watchdog@fffffe40 {
- status = "okay";
- };
- };
-
- usb0: ohci@600000 {
- num-ports = <1>;
- status = "okay";
- };
-
- usb1: ehci@700000 {
- status = "okay";
- };
-
- ebi: ebi@10000000 {
- pinctrl-0 = <&pinctrl_ebi_addr_nand
- &pinctrl_ebi_data_0_7>;
- pinctrl-names = "default";
- status = "okay";
-
- nand_controller: nand-controller {
- status = "okay";
- pinctrl-0 = <&pinctrl_nand_oe_we
- &pinctrl_nand_cs
- &pinctrl_nand_rb>;
- pinctrl-names = "default";
-
- nand@3 {
- reg = <0x3 0x0 0x800000>;
- rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
- cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>;
- nand-bus-width = <8>;
- nand-ecc-mode = "hw";
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
- nand-on-flash-bbt;
- label = "atmel_nand";
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- bootstrap@0 {
- label = "bootstrap";
- reg = <0x0 0x20000>;
- };
-
- ubi@20000 {
- label = "ubi";
- reg = <0x20000 0x7fe0000>;
- };
- };
- };
- };
- };
-
nand0: nand@40000000 {
nand-bus-width = <8>;
nand-ecc-mode = "hw";
@@ -130,7 +40,6 @@
atmel,pmecc-sector-size = <512>;
nand-on-flash-bbt;
status = "okay";
-
};
};
@@ -172,3 +81,91 @@
};
};
};
+
+&dbgu {
+ status = "okay";
+};
+
+&ebi {
+ pinctrl-0 = <&pinctrl_ebi_addr_nand
+ &pinctrl_ebi_data_0_7>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ nand-controller {
+ pinctrl-0 = <&pinctrl_nand_oe_we
+ &pinctrl_nand_cs
+ &pinctrl_nand_rb>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ nand@3 {
+ reg = <0x3 0x0 0x800000>;
+ rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+ nand-on-flash-bbt;
+ label = "atmel_nand";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bootstrap@0 {
+ label = "bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ ubi@20000 {
+ label = "ubi";
+ reg = <0x20000 0x7fe0000>;
+ };
+ };
+ };
+ };
+};
+
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_pwm0_1
+ &pinctrl_pwm0_pwm1_1>;
+ status = "okay";
+};
+
+&tcb0 {
+ timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
+ };
+};
+
+&usart0 {
+ status = "okay";
+};
+
+&usb0 {
+ num-ports = <1>;
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index 7debdeabcf2f..c4ef74fea97c 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -40,7 +40,7 @@
atmel,power-control-gpio = <&pioA 12 GPIO_ACTIVE_LOW>;
status = "okay";
- display0: display {
+ display0: panel {
bits-per-pixel = <16>;
atmel,lcdcon-backlight;
atmel,dmacon = <0x1>;
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index 45e0c6e88cab..62d218542a48 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -110,7 +110,7 @@
display = <&display0>;
status = "okay";
- display0: display {
+ display0: panel {
bits-per-pixel = <16>;
atmel,lcdcon-backlight;
atmel,dmacon = <0x1>;
diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi
index d77c69ad7f02..dde88276fe52 100644
--- a/arch/arm/boot/dts/at91sam9g15.dtsi
+++ b/arch/arm/boot/dts/at91sam9g15.dtsi
@@ -11,22 +11,18 @@
/ {
model = "Atmel AT91SAM9G15 SoC";
compatible = "atmel,at91sam9g15", "atmel,at91sam9x5";
+};
- ahb {
- apb {
- pinctrl@fffff400 {
- atmel,mux-mask = <
- /* A B C */
- 0xffffffff 0xffe0399f 0x00000000 /* pioA */
- 0x00040000 0x00047e3f 0x00000000 /* pioB */
- 0xfdffffff 0x00000000 0xb83fffff /* pioC */
- 0x003fffff 0x003f8000 0x00000000 /* pioD */
- >;
- };
+&pinctrl {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe0399f 0x00000000 /* pioA */
+ 0x00040000 0x00047e3f 0x00000000 /* pioB */
+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+};
- pmc: pmc@fffffc00 {
- compatible = "atmel,at91sam9g15-pmc", "atmel,at91sam9x5-pmc", "syscon";
- };
- };
- };
+&pmc {
+ compatible = "atmel,at91sam9g15-pmc", "atmel,at91sam9x5-pmc", "syscon";
};
diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts
index 97100d298400..889a5097eb2d 100644
--- a/arch/arm/boot/dts/at91sam9g15ek.dts
+++ b/arch/arm/boot/dts/at91sam9g15ek.dts
@@ -14,14 +14,6 @@
model = "Atmel AT91SAM9G15-EK";
compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
- ahb {
- apb {
- hlcdc: hlcdc@f8038000 {
- status = "okay";
- };
- };
- };
-
backlight: backlight {
status = "okay";
};
@@ -38,3 +30,7 @@
status = "okay";
};
};
+
+&hlcdc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index a02c6c79ce52..61b0bdb615dc 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -12,57 +12,54 @@
/ {
model = "Atmel AT91SAM9G25-EK";
compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
- ahb {
- apb {
- spi0: spi@f0000000 {
- status = "disabled";
- };
-
- mmc1: mmc@f000c000 {
- status = "disabled";
- };
-
- i2c0: i2c@f8010000 {
- ov2640: camera@30 {
- compatible = "ovti,ov2640";
- reg = <0x30>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
- resetb-gpios = <&pioA 7 GPIO_ACTIVE_LOW>;
- pwdn-gpios = <&pioA 13 GPIO_ACTIVE_HIGH>;
- clocks = <&pmc PMC_TYPE_SYSTEM 8>;
- clock-names = "xvclk";
- assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>;
- assigned-clock-rates = <25000000>;
- status = "okay";
+&i2c0 {
+ camera@30 {
+ compatible = "ovti,ov2640";
+ reg = <0x30>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
+ resetb-gpios = <&pioA 7 GPIO_ACTIVE_LOW>;
+ pwdn-gpios = <&pioA 13 GPIO_ACTIVE_HIGH>;
+ clocks = <&pmc PMC_TYPE_SYSTEM 8>;
+ clock-names = "xvclk";
+ assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>;
+ assigned-clock-rates = <25000000>;
+ status = "okay";
- port {
- ov2640_0: endpoint {
- remote-endpoint = <&isi_0>;
- bus-width = <8>;
- };
- };
- };
+ port {
+ ov2640_0: endpoint {
+ remote-endpoint = <&isi_0>;
+ bus-width = <8>;
};
+ };
+ };
+};
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
+&isi {
+ status = "okay";
- isi: isi@f8048000 {
- status = "okay";
- port {
- isi_0: endpoint@0 {
- reg = <0>;
- remote-endpoint = <&ov2640_0>;
- bus-width = <8>;
- vsync-active = <1>;
- hsync-active = <1>;
- };
- };
- };
+ port {
+ isi_0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&ov2640_0>;
+ bus-width = <8>;
+ vsync-active = <1>;
+ hsync-active = <1>;
};
};
};
+
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
+
+&mmc1 {
+ status = "disabled";
+};
+
+&spi0 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
index 449ec712ab52..f966b56de63c 100644
--- a/arch/arm/boot/dts/at91sam9g35ek.dts
+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
@@ -14,19 +14,6 @@
model = "Atmel AT91SAM9G35-EK";
compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
- ahb {
- apb {
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
-
- hlcdc: hlcdc@f8038000 {
- status = "okay";
- };
- };
- };
-
backlight: backlight {
status = "okay";
};
@@ -43,3 +30,12 @@
status = "okay";
};
};
+
+&hlcdc {
+ status = "okay";
+};
+
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 06d74ff1a7d0..84bed6f55fcd 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -235,7 +235,7 @@
display = <&display0>;
status = "okay";
- display0: display {
+ display0: panel {
bits-per-pixel = <32>;
atmel,lcdcon-backlight;
atmel,dmacon = <0x1>;
diff --git a/arch/arm/boot/dts/at91sam9rlek.dts b/arch/arm/boot/dts/at91sam9rlek.dts
index 3a3869444fdc..0de75d3c4f18 100644
--- a/arch/arm/boot/dts/at91sam9rlek.dts
+++ b/arch/arm/boot/dts/at91sam9rlek.dts
@@ -36,7 +36,7 @@
display = <&display0>;
status = "okay";
- display0: display {
+ display0: panel {
bits-per-pixel = <16>;
atmel,lcdcon-backlight;
atmel,dmacon = <0x1>;
diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
index 4e1c3df89a6c..ad7c6b36f0ba 100644
--- a/arch/arm/boot/dts/at91sam9x25ek.dts
+++ b/arch/arm/boot/dts/at91sam9x25ek.dts
@@ -12,28 +12,24 @@
/ {
model = "Atmel AT91SAM9X25-EK";
compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
- ahb {
- apb {
- can1: can@f8004000 {
- status = "okay";
- };
+&can1 {
+ status = "okay";
+};
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
- macb1: ethernet@f8030000 {
- phy-mode = "rmii";
- status = "okay";
- };
+&macb1 {
+ phy-mode = "rmii";
+ status = "okay";
+};
- pwm0: pwm@f8034000 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm0_pwm0_1>;
- status = "okay";
- };
- };
- };
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_pwm0_1>;
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts
index 7646c680fa97..66675c787b97 100644
--- a/arch/arm/boot/dts/at91sam9x35ek.dts
+++ b/arch/arm/boot/dts/at91sam9x35ek.dts
@@ -13,32 +13,29 @@
/ {
model = "Atmel AT91SAM9X35-EK";
compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
- ahb {
- apb {
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
- hlcdc: hlcdc@f8038000 {
- status = "okay";
- };
- };
- };
+&backlight {
+ status = "okay";
+};
- backlight: backlight {
- status = "okay";
- };
+&bl_reg {
+ status = "okay";
+};
- bl_reg: backlight_regulator {
- status = "okay";
- };
+&hlcdc {
+ status = "okay";
+};
- panel: panel {
- status = "okay";
- };
+&macb0 {
+ phy-mode = "rmii";
+ status = "okay";
+};
+
+&panel {
+ status = "okay";
+};
- panel_reg: panel_regulator {
- status = "okay";
- };
+&panel_reg {
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index ef47c005ef03..7c2eb93f8cac 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -941,7 +941,7 @@
status = "disabled";
};
- rtc@fffffeb0 {
+ rtc: rtc@fffffeb0 {
compatible = "atmel,at91sam9x5-rtc";
reg = <0xfffffeb0 0x40>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
diff --git a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
index 584f840cc6a5..f81c9d1691e0 100644
--- a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
@@ -39,109 +39,109 @@
#pwm-cells = <3>;
};
};
+ };
+ };
+};
- pinctrl@fffff400 {
- lcd {
- pinctrl_lcd_base: lcd-base-0 {
- atmel,pins =
- <AT91_PIOC 27 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDVSYNC */
- AT91_PIOC 28 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDHSYNC */
- AT91_PIOC 24 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDDISP */
- AT91_PIOC 29 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDDEN */
- AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPCK */
- };
+&pinctrl {
+ lcd {
+ pinctrl_lcd_base: lcd-base-0 {
+ atmel,pins =
+ <AT91_PIOC 27 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDVSYNC */
+ AT91_PIOC 28 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDHSYNC */
+ AT91_PIOC 24 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDDISP */
+ AT91_PIOC 29 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDDEN */
+ AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPCK */
+ };
- pinctrl_lcd_pwm: lcd-pwm-0 {
- atmel,pins = <AT91_PIOC 26 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPWM */
- };
+ pinctrl_lcd_pwm: lcd-pwm-0 {
+ atmel,pins = <AT91_PIOC 26 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPWM */
+ };
- pinctrl_lcd_rgb444: lcd-rgb-0 {
- atmel,pins =
- <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
- AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
- AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
- AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
- AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
- AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
- AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
- AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
- AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
- AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
- AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
- AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD11 pin */
- };
+ pinctrl_lcd_rgb444: lcd-rgb-0 {
+ atmel,pins =
+ <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
+ AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
+ AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
+ AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
+ AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
+ AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
+ AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
+ AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
+ AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
+ AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
+ AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
+ AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD11 pin */
+ };
- pinctrl_lcd_rgb565: lcd-rgb-1 {
- atmel,pins =
- <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
- AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
- AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
- AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
- AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
- AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
- AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
- AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
- AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
- AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
- AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
- AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
- AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
- AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
- AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
- AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD15 pin */
- };
+ pinctrl_lcd_rgb565: lcd-rgb-1 {
+ atmel,pins =
+ <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
+ AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
+ AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
+ AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
+ AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
+ AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
+ AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
+ AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
+ AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
+ AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
+ AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
+ AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
+ AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
+ AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
+ AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
+ AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD15 pin */
+ };
- pinctrl_lcd_rgb666: lcd-rgb-2 {
- atmel,pins =
- <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
- AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
- AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
- AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
- AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
- AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
- AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
- AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
- AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
- AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
- AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
- AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
- AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
- AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
- AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
- AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD15 pin */
- AT91_PIOC 16 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD16 pin */
- AT91_PIOC 17 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD17 pin */
- };
+ pinctrl_lcd_rgb666: lcd-rgb-2 {
+ atmel,pins =
+ <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
+ AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
+ AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
+ AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
+ AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
+ AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
+ AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
+ AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
+ AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
+ AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
+ AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
+ AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
+ AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
+ AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
+ AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
+ AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD15 pin */
+ AT91_PIOC 16 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD16 pin */
+ AT91_PIOC 17 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD17 pin */
+ };
- pinctrl_lcd_rgb888: lcd-rgb-3 {
- atmel,pins =
- <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
- AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
- AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
- AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
- AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
- AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
- AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
- AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
- AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
- AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
- AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
- AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
- AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
- AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
- AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
- AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD15 pin */
- AT91_PIOC 16 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD16 pin */
- AT91_PIOC 17 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD17 pin */
- AT91_PIOC 18 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD18 pin */
- AT91_PIOC 19 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD19 pin */
- AT91_PIOC 20 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD20 pin */
- AT91_PIOC 21 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD21 pin */
- AT91_PIOC 22 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD22 pin */
- AT91_PIOC 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
- };
- };
- };
+ pinctrl_lcd_rgb888: lcd-rgb-3 {
+ atmel,pins =
+ <AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD0 pin */
+ AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD1 pin */
+ AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD2 pin */
+ AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD3 pin */
+ AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD4 pin */
+ AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD5 pin */
+ AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD6 pin */
+ AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD7 pin */
+ AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD8 pin */
+ AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD9 pin */
+ AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD10 pin */
+ AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD11 pin */
+ AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD12 pin */
+ AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD13 pin */
+ AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD14 pin */
+ AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD15 pin */
+ AT91_PIOC 16 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD16 pin */
+ AT91_PIOC 17 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD17 pin */
+ AT91_PIOC 18 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD18 pin */
+ AT91_PIOC 19 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD19 pin */
+ AT91_PIOC 20 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD20 pin */
+ AT91_PIOC 21 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD21 pin */
+ AT91_PIOC 22 AT91_PERIPH_A AT91_PINCTRL_NONE /* LCDD22 pin */
+ AT91_PIOC 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
};
};
};
diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/at91sam9x5dm.dtsi
index b04ebf1a3131..7f00c1f57b90 100644
--- a/arch/arm/boot/dts/at91sam9x5dm.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5dm.dtsi
@@ -9,51 +9,6 @@
*/
/ {
- ahb {
- apb {
- i2c0: i2c@f8010000 {
- qt1070: keyboard@1b {
- compatible = "qt1070";
- reg = <0x1b>;
- interrupt-parent = <&pioA>;
- interrupts = <7 0x0>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_qt1070_irq>;
- wakeup-source;
- };
- };
-
- hlcdc: hlcdc@f8038000 {
- hlcdc-display-controller {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
-
- port@0 {
- hlcdc_panel_output: endpoint@0 {
- reg = <0>;
- remote-endpoint = <&panel_input>;
- };
- };
- };
- };
-
- adc0: adc@f804c000 {
- atmel,adc-ts-wires = <4>;
- atmel,adc-ts-pressure-threshold = <10000>;
- status = "okay";
- };
-
- pinctrl@fffff400 {
- board {
- pinctrl_qt1070_irq: qt1070_irq {
- atmel,pins =
- <AT91_PIOA 7 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
- };
- };
- };
- };
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&hlcdc_pwm 0 50000 0>;
@@ -98,3 +53,44 @@
status = "disabled";
};
};
+
+&adc0 {
+ atmel,adc-ts-wires = <4>;
+ atmel,adc-ts-pressure-threshold = <10000>;
+ status = "okay";
+};
+
+&i2c0 {
+ keyboard@1b {
+ compatible = "qt1070";
+ reg = <0x1b>;
+ interrupt-parent = <&pioA>;
+ interrupts = <7 0x0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qt1070_irq>;
+ wakeup-source;
+ };
+};
+
+&hlcdc {
+ hlcdc-display-controller {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
+
+ port@0 {
+ hlcdc_panel_output: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&panel_input>;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ board {
+ pinctrl_qt1070_irq: qt1070_irq {
+ atmel,pins =
+ <AT91_PIOA 7 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
index 2ad0a43656e4..c934928742b0 100644
--- a/arch/arm/boot/dts/at91sam9x5ek.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
@@ -16,139 +16,6 @@
stdout-path = "serial0:115200n8";
};
- ahb {
- apb {
- mmc0: mmc@f0008000 {
- pinctrl-0 = <
- &pinctrl_board_mmc0
- &pinctrl_mmc0_slot0_clk_cmd_dat0
- &pinctrl_mmc0_slot0_dat1_3>;
- status = "okay";
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>;
- };
- };
-
- mmc1: mmc@f000c000 {
- pinctrl-0 = <
- &pinctrl_board_mmc1
- &pinctrl_mmc1_slot0_clk_cmd_dat0
- &pinctrl_mmc1_slot0_dat1_3>;
- status = "okay";
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- cd-gpios = <&pioD 14 GPIO_ACTIVE_HIGH>;
- };
- };
-
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- usart0: serial@f801c000 {
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "okay";
- };
-
- usb2: gadget@f803c000 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_board_usb2>;
- atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
- status = "okay";
- };
-
- i2c0: i2c@f8010000 {
- status = "okay";
-
- wm8731: wm8731@1a {
- compatible = "wm8731";
- reg = <0x1a>;
- };
- };
-
- adc0: adc@f804c000 {
- atmel,adc-ts-wires = <4>;
- atmel,adc-ts-pressure-threshold = <10000>;
- status = "okay";
- };
-
- pinctrl@fffff400 {
- camera_sensor {
- pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 {
- atmel,pins =
- <AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* ISI_MCK */
- };
-
- pinctrl_sensor_power: sensor_power-0 {
- atmel,pins =
- <AT91_PIOA 13 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
- };
-
- pinctrl_sensor_reset: sensor_reset-0 {
- atmel,pins =
- <AT91_PIOA 7 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
- };
- };
-
- mmc0 {
- pinctrl_board_mmc0: mmc0-board {
- atmel,pins =
- <AT91_PIOD 15 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD15 gpio CD pin pull up and deglitch */
- };
- };
-
- mmc1 {
- pinctrl_board_mmc1: mmc1-board {
- atmel,pins =
- <AT91_PIOD 14 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD14 gpio CD pin pull up and deglitch */
- };
- };
-
- usb2 {
- pinctrl_board_usb2: usb2-board {
- atmel,pins =
- <AT91_PIOB 16 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>; /* PB16 gpio vbus sense, deglitch */
- };
- };
- };
-
- spi0: spi@f0000000 {
- status = "disabled"; /* conflicts with mmc1 */
- cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
- m25p80@0 {
- compatible = "atmel,at25df321a";
- spi-max-frequency = <50000000>;
- reg = <0>;
- };
- };
-
- watchdog@fffffe40 {
- status = "okay";
- };
-
- ssc0: ssc@f0010000 {
- status = "okay";
- };
- };
-
- usb0: ohci@600000 {
- status = "okay";
- num-ports = <3>;
- atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
- &pioD 19 GPIO_ACTIVE_LOW
- &pioD 20 GPIO_ACTIVE_LOW
- >;
- };
-
- usb1: ehci@700000 {
- status = "okay";
- };
- };
-
sound {
compatible = "atmel,sam9x5-wm8731-audio";
@@ -164,3 +31,135 @@
atmel,audio-codec = <&wm8731>;
};
};
+
+&adc0 {
+ atmel,adc-ts-wires = <4>;
+ atmel,adc-ts-pressure-threshold = <10000>;
+ status = "okay";
+};
+
+&dbgu {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ wm8731: wm8731@1a {
+ compatible = "wm8731";
+ reg = <0x1a>;
+ };
+};
+
+&mmc0 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&mmc1 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc1
+ &pinctrl_mmc1_slot0_clk_cmd_dat0
+ &pinctrl_mmc1_slot0_dat1_3>;
+ status = "okay";
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 14 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&pinctrl {
+ camera_sensor {
+ pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 {
+ atmel,pins =
+ <AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* ISI_MCK */
+ };
+
+ pinctrl_sensor_power: sensor_power-0 {
+ atmel,pins =
+ <AT91_PIOA 13 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+
+ pinctrl_sensor_reset: sensor_reset-0 {
+ atmel,pins =
+ <AT91_PIOA 7 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ };
+
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <AT91_PIOD 15 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD15 gpio CD pin pull up and deglitch */
+ };
+ };
+
+ mmc1 {
+ pinctrl_board_mmc1: mmc1-board {
+ atmel,pins =
+ <AT91_PIOD 14 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PD14 gpio CD pin pull up and deglitch */
+ };
+ };
+
+ usb2 {
+ pinctrl_board_usb2: usb2-board {
+ atmel,pins =
+ <AT91_PIOB 16 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>; /* PB16 gpio vbus sense, deglitch */
+ };
+ };
+};
+
+&spi0 {
+ cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
+ status = "disabled"; /* conflicts with mmc1 */
+
+ m25p80@0 {
+ compatible = "atmel,at25df321a";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ };
+};
+
+&ssc0 {
+ status = "okay";
+};
+
+&usart0 {
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+};
+
+&usb0 {
+ num-ports = <3>;
+ atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
+ &pioD 19 GPIO_ACTIVE_LOW
+ &pioD 20 GPIO_ACTIVE_LOW
+ >;
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&usb2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_board_usb2>;
+ atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
index db8a6017f220..6c8ce39833bf 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
@@ -8,6 +8,11 @@
compatible = "raspberrypi,model-a-plus", "brcm,bcm2835";
model = "Raspberry Pi Model A+";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x10000000>;
+ };
+
leds {
act {
gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
@@ -99,6 +104,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -107,6 +114,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts
index 067d1f07a2d3..17fdd48346ff 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
@@ -8,6 +8,11 @@
compatible = "raspberrypi,model-a", "brcm,bcm2835";
model = "Raspberry Pi Model A";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x10000000>;
+ };
+
leds {
act {
gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
@@ -94,6 +99,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -102,6 +109,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
index 1e40d672b055..b0355c229cdc 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
@@ -9,6 +9,11 @@
compatible = "raspberrypi,model-b-plus", "brcm,bcm2835";
model = "Raspberry Pi Model B+";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x20000000>;
+ };
+
leds {
act {
gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
@@ -101,6 +106,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -109,6 +116,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
index 28e7513ce617..33b3b5c02521 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
@@ -9,6 +9,11 @@
compatible = "raspberrypi,model-b-rev2", "brcm,bcm2835";
model = "Raspberry Pi Model B rev2";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x10000000>;
+ };
+
leds {
act {
gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
@@ -94,6 +99,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -102,6 +109,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 31ff602e2cd3..2b69957e0113 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -9,6 +9,11 @@
compatible = "raspberrypi,model-b", "brcm,bcm2835";
model = "Raspberry Pi Model B";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x10000000>;
+ };
+
leds {
act {
gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
@@ -89,6 +94,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -97,6 +104,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
index 4764a25585ab..a75c882e6575 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
@@ -79,6 +79,15 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
+};
+
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
};
&uart0 {
diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
index ef22c2da783a..58059c2ce129 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
@@ -10,6 +10,11 @@
};
};
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x20000000>;
+ };
+
reg_3v3: fixed-regulator {
compatible = "regulator-fixed";
regulator-name = "3V3";
diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
index ba0167df6c5f..09a088f98566 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
@@ -12,6 +12,11 @@
compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
model = "Raspberry Pi Zero W";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x20000000>;
+ };
+
chosen {
/* 8250 auxiliary UART instead of pl011 */
stdout-path = "serial1:115200n8";
@@ -100,6 +105,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&sdhci {
@@ -116,6 +123,13 @@
};
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio32 &uart0_ctsrts_gpio30>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero.dts b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
index 3b35a8a4a55f..6dd93c6f4966 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
@@ -12,6 +12,11 @@
compatible = "raspberrypi,model-zero", "brcm,bcm2835";
model = "Raspberry Pi Zero";
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0x20000000>;
+ };
+
leds {
act {
gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
@@ -96,6 +101,15 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
+};
+
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
};
&uart0 {
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
index 715d50c64529..6c6a7f620d8b 100644
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
@@ -1,11 +1,6 @@
#include <dt-bindings/power/raspberrypi-power.h>
/ {
- memory@0 {
- device_type = "memory";
- reg = <0 0x10000000>;
- };
-
leds {
compatible = "gpio-leds";
@@ -68,28 +63,10 @@
status = "okay";
};
-&sdhci {
- pinctrl-names = "default";
- pinctrl-0 = <&emmc_gpio48>;
- bus-width = <4>;
-};
-
-&sdhost {
- pinctrl-names = "default";
- pinctrl-0 = <&sdhost_gpio48>;
- status = "okay";
- bus-width = <4>;
-};
-
&usb {
power-domains = <&power RPI_POWER_DOMAIN_USB>;
};
-&hdmi {
- power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
- status = "okay";
-};
-
&vec {
power-domains = <&power RPI_POWER_DOMAIN_VEC>;
status = "okay";
diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
index 7b4e651bafdd..0455a680394a 100644
--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
@@ -10,6 +10,7 @@
model = "Raspberry Pi 2 Model B";
memory@0 {
+ device_type = "memory";
reg = <0 0x40000000>;
};
@@ -105,6 +106,8 @@
&hdmi {
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
@@ -113,6 +116,13 @@
status = "okay";
};
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
index 7f4437a8eedb..66ab35eccba7 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
@@ -14,6 +14,7 @@
};
memory@0 {
+ device_type = "memory";
reg = <0 0x20000000>;
};
@@ -117,6 +118,8 @@
&hdmi {
hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
index c6fa34c24100..74ed6d047807 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
@@ -15,6 +15,7 @@
};
memory@0 {
+ device_type = "memory";
reg = <0 0x40000000>;
};
@@ -124,6 +125,8 @@
&hdmi {
hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
&pwm {
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
index ce71f578c51a..054ecaa355c9 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
@@ -15,6 +15,7 @@
};
memory@0 {
+ device_type = "memory";
reg = <0 0x40000000>;
};
@@ -125,6 +126,8 @@
&hdmi {
hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
};
/* uart0 communicates with the BT module */
diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts
index 6c8233a36d86..588d9411ceb6 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts
@@ -78,6 +78,15 @@
&hdmi {
hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ status = "okay";
+};
+
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ bus-width = <4>;
+ status = "okay";
};
&uart0 {
diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
index 81399b2c5af9..7c3cb7ece6cb 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
+++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
@@ -5,6 +5,7 @@
/ {
memory@0 {
+ device_type = "memory";
reg = <0 0x40000000>;
};
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 4b21ddb26aa5..2d191fcbc2cc 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -397,7 +397,7 @@
uart0: serial@7e201000 {
compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
- reg = <0x7e201000 0x1000>;
+ reg = <0x7e201000 0x200>;
interrupts = <2 25>;
clocks = <&clocks BCM2835_CLOCK_UART>,
<&clocks BCM2835_CLOCK_VPU>;
@@ -428,7 +428,7 @@
spi: spi@7e204000 {
compatible = "brcm,bcm2835-spi";
- reg = <0x7e204000 0x1000>;
+ reg = <0x7e204000 0x200>;
interrupts = <2 22>;
clocks = <&clocks BCM2835_CLOCK_VPU>;
dmas = <&dma 6>, <&dma 7>;
@@ -440,7 +440,7 @@
i2c0: i2c@7e205000 {
compatible = "brcm,bcm2835-i2c";
- reg = <0x7e205000 0x1000>;
+ reg = <0x7e205000 0x200>;
interrupts = <2 21>;
clocks = <&clocks BCM2835_CLOCK_VPU>;
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
index 18d0ae46e76c..0faae8950375 100644
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
@@ -124,6 +124,9 @@
};
mdio-bus-mux {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
/* BIT(9) = 1 => external mdio */
mdio_ext: mdio@200 {
reg = <0x200>;
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 5b2b1ed04d51..f2e7609e5346 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -281,7 +281,7 @@
flash: m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "m25p64";
+ compatible = "jedec,spi-nor";
spi-max-frequency = <30000000>;
m25p,fast-read;
reg = <0>;
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 714e971b912a..de7f85efaa51 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -498,7 +498,7 @@
phy-supply = <&ldousb_reg>;
};
-&gpio7 {
+&gpio7_target {
ti,no-reset-on-init;
ti,no-idle-on-init;
};
diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/dra7-l4.dtsi
index 23faedec08ab..21e5914fdd62 100644
--- a/arch/arm/boot/dts/dra7-l4.dtsi
+++ b/arch/arm/boot/dts/dra7-l4.dtsi
@@ -1261,7 +1261,7 @@
};
};
- target-module@51000 { /* 0x48051000, ap 45 2e.0 */
+ gpio7_target: target-module@51000 { /* 0x48051000, ap 45 2e.0 */
compatible = "ti,sysc-omap2", "ti,sysc";
ti,hwmods = "gpio7";
reg = <0x51000 0x4>,
@@ -3025,7 +3025,7 @@
target-module@80000 { /* 0x48480000, ap 31 16.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
- reg = <0x80000 0x4>;
+ reg = <0x80020 0x4>;
reg-names = "rev";
clocks = <&l4per2_clkctrl DRA7_L4PER2_DCAN2_CLKCTRL 0>;
clock-names = "fck";
@@ -4577,7 +4577,7 @@
target-module@c000 { /* 0x4ae3c000, ap 30 04.0 */
compatible = "ti,sysc-omap4", "ti,sysc";
- reg = <0xc000 0x4>;
+ reg = <0xc020 0x4>;
reg-names = "rev";
clocks = <&wkupaon_clkctrl DRA7_WKUPAON_DCAN1_CLKCTRL 0>;
clock-names = "fck";
diff --git a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi b/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi
index 28ebb4eb884a..214b9e6de2c3 100644
--- a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi
+++ b/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi
@@ -32,7 +32,7 @@
*
* Datamanual Revisions:
*
- * AM572x Silicon Revision 2.0: SPRS953B, Revised November 2016
+ * AM572x Silicon Revision 2.0: SPRS953F, Revised May 2019
* AM572x Silicon Revision 1.1: SPRS915R, Revised November 2016
*
*/
@@ -229,45 +229,45 @@
mmc3_pins_default: mmc3_pins_default {
pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
- DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
- DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
- DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
- DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
- DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+ DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+ DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+ DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+ DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+ DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
>;
};
mmc3_pins_hs: mmc3_pins_hs {
pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
- DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
- DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
- DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
- DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
- DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+ DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+ DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+ DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+ DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+ DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
>;
};
mmc3_pins_sdr12: mmc3_pins_sdr12 {
pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
- DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
- DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
- DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
- DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
- DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+ DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+ DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+ DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+ DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+ DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
>;
};
mmc3_pins_sdr25: mmc3_pins_sdr25 {
pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
- DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
- DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
- DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
- DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
- DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+ DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+ DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+ DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+ DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+ DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
>;
};
diff --git a/arch/arm/boot/dts/ep7211-edb7211.dts b/arch/arm/boot/dts/ep7211-edb7211.dts
index a0c270f63fee..da076479c8e2 100644
--- a/arch/arm/boot/dts/ep7211-edb7211.dts
+++ b/arch/arm/boot/dts/ep7211-edb7211.dts
@@ -25,11 +25,11 @@
display: display {
model = "320x240x4";
- native-mode = <&timing0>;
bits-per-pixel = <4>;
ac-prescale = <17>;
display-timings {
+ native-mode = <&timing0>;
timing0: 320x240 {
hactive = <320>;
hback-porch = <0>;
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 5659c4a10729..784818490376 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -450,8 +450,7 @@
};
adc: adc@126c0000 {
- compatible = "samsung,exynos3250-adc",
- "samsung,exynos-adc-v2";
+ compatible = "samsung,exynos3250-adc";
reg = <0x126C0000 0x100>;
interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "adc", "sclk";
diff --git a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
index 462a5409b1de..dfceb155b3a7 100644
--- a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
+++ b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
@@ -377,7 +377,7 @@
buck1_reg: BUCK1 {
regulator-name = "vdd_mif";
regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -386,7 +386,7 @@
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1456250>;
+ regulator-max-microvolt = <1456250>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -395,7 +395,7 @@
buck3_reg: BUCK3 {
regulator-name = "vdd_int";
regulator-min-microvolt = <875000>;
- regulator-max-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -404,7 +404,7 @@
buck4_reg: BUCK4 {
regulator-name = "vdd_g3d";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -413,7 +413,7 @@
buck5_reg: BUCK5 {
regulator-name = "vdd_m12";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -422,7 +422,7 @@
buck6_reg: BUCK6 {
regulator-name = "vdd12_5m";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
@@ -431,7 +431,7 @@
buck7_reg: BUCK7 {
regulator-name = "pvdd_buck7";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
regulator-boot-on;
regulator-always-on;
op_mode = <1>; /* Normal Mode */
@@ -440,7 +440,7 @@
buck8_reg: BUCK8 {
regulator-name = "pvdd_buck8";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
op_mode = <1>; /* Normal Mode */
@@ -449,7 +449,7 @@
buck9_reg: BUCK9 {
regulator-name = "vddf28_emmc";
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
op_mode = <1>; /* Normal Mode */
};
};
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index dc6fa6fe83f1..6fcb78a354fe 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -461,8 +461,8 @@
buck4_reg: BUCK4 {
regulator-name = "vdd_g3d";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1300000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>;
@@ -543,6 +543,11 @@
status = "okay";
};
+&mali {
+ mali-supply = <&buck4_reg>;
+ status = "okay";
+};
+
&mixer {
status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index fd9226d3b207..c952a615148e 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -529,6 +529,11 @@
status = "okay";
};
+&mali {
+ mali-supply = <&buck4_reg>;
+ status = "okay";
+};
+
&mixer {
status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index d5e0392b409e..81729cf3ad2d 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -328,6 +328,53 @@
iommus = <&sysmmu_rotator>;
};
+ mali: gpu@11800000 {
+ compatible = "samsung,exynos5250-mali", "arm,mali-t604";
+ reg = <0x11800000 0x5000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "job", "mmu", "gpu";
+ clocks = <&clock CLK_G3D>;
+ clock-names = "core";
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&pd_g3d>;
+ status = "disabled";
+
+ gpu_opp_table: gpu-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <925000>;
+ };
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ opp-microvolt = <925000>;
+ };
+ opp-266000000 {
+ opp-hz = /bits/ 64 <266000000>;
+ opp-microvolt = <1025000>;
+ };
+ opp-350000000 {
+ opp-hz = /bits/ 64 <350000000>;
+ opp-microvolt = <1075000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <1125000>;
+ };
+ opp-450000000 {
+ opp-hz = /bits/ 64 <450000000>;
+ opp-microvolt = <1150000>;
+ };
+ opp-533000000 {
+ opp-hz = /bits/ 64 <533000000>;
+ opp-microvolt = <1250000>;
+ };
+ };
+ };
+
tmu: tmu@10060000 {
compatible = "samsung,exynos5250-tmu";
reg = <0x10060000 0x100>;
@@ -346,6 +393,7 @@
clock-names = "sata", "sclk_sata";
phys = <&sata_phy>;
phy-names = "sata-phy";
+ ports-implemented = <0x1>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index f78db6809cca..9eb48cabcca4 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -440,6 +440,7 @@
regulator-name = "vdd_ldo10";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
+ regulator-always-on;
regulator-state-mem {
regulator-off-in-suspend;
};
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 55d4dbf6f83a..7d51e0f4ab79 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -294,11 +294,11 @@
label = "MFC";
};
- msc_pd: power-domain@10044120 {
+ g3d_pd: power-domain@10044080 {
compatible = "samsung,exynos4210-pd";
- reg = <0x10044120 0x20>;
+ reg = <0x10044080 0x20>;
#power-domain-cells = <0>;
- label = "MSC";
+ label = "G3D";
};
disp_pd: power-domain@100440c0 {
@@ -315,6 +315,13 @@
label = "MAU";
};
+ msc_pd: power-domain@10044120 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10044120 0x20>;
+ #power-domain-cells = <0>;
+ label = "MSC";
+ };
+
pinctrl_0: pinctrl@13400000 {
compatible = "samsung,exynos5420-pinctrl";
reg = <0x13400000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index e0f470fe54c8..4398f2d1fe88 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -440,6 +440,7 @@
regulator-name = "vdd_ldo10";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
+ regulator-always-on;
regulator-state-mem {
regulator-off-in-suspend;
};
diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
index 57d3b319fd65..de639eecc5c9 100644
--- a/arch/arm/boot/dts/exynos5800.dtsi
+++ b/arch/arm/boot/dts/exynos5800.dtsi
@@ -131,3 +131,12 @@
&mfc {
compatible = "samsung,mfc-v8";
};
+
+&soc {
+ cam_pd: power-domain@10045100 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10045100 0x20>;
+ #power-domain-cells = <0>;
+ label = "CAM";
+ };
+};
diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts
index f4535d635f3b..521714f38eed 100644
--- a/arch/arm/boot/dts/gemini-nas4220b.dts
+++ b/arch/arm/boot/dts/gemini-nas4220b.dts
@@ -20,7 +20,7 @@
};
chosen {
- bootargs = "console=ttyS0,19200n8";
+ bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait";
stdout-path = &uart0;
};
@@ -81,37 +81,10 @@
/* 16MB of flash */
reg = <0x30000000 0x01000000>;
- partition@0 {
- label = "RedBoot";
- reg = <0x00000000 0x00020000>;
- read-only;
- };
- partition@20000 {
- label = "Kernel";
- reg = <0x00020000 0x00300000>;
- };
- partition@320000 {
- label = "Ramdisk";
- reg = <0x00320000 0x00600000>;
- };
- partition@920000 {
- label = "Application";
- reg = <0x00920000 0x00600000>;
- };
- partition@f20000 {
- label = "VCTL";
- reg = <0x00f20000 0x00020000>;
- read-only;
- };
- partition@f40000 {
- label = "CurConf";
- reg = <0x00f40000 0x000a0000>;
- read-only;
- };
- partition@fe0000 {
- label = "FIS directory";
- reg = <0x00fe0000 0x00020000>;
- read-only;
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0xfe0000 */
+ fis-index-block = <0x1fc>;
};
};
diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini-sl93512r.dts
index 2bb953440793..a98af0351906 100644
--- a/arch/arm/boot/dts/gemini-sl93512r.dts
+++ b/arch/arm/boot/dts/gemini-sl93512r.dts
@@ -24,7 +24,7 @@
};
chosen {
- bootargs = "console=ttyS0,19200n8 root=/dev/sda1 rw rootwait";
+ bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait";
stdout-path = &uart0;
};
@@ -36,8 +36,8 @@
wakeup-source;
linux,code = <KEY_WPS_BUTTON>;
label = "WPS";
- /* Conflict with NAND flash */
- gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+ /* Conflicts with TVC and extended flash */
+ gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
};
button-setup {
@@ -143,54 +143,30 @@
/* 16MB of flash */
reg = <0x30000000 0x01000000>;
- partition@0 {
- label = "BOOT";
- reg = <0x00000000 0x00020000>;
- read-only;
- };
- partition@120000 {
- label = "Kern";
- reg = <0x00020000 0x00300000>;
- };
- partition@320000 {
- label = "Ramdisk";
- reg = <0x00320000 0x00600000>;
- };
- partition@920000 {
- label = "Application";
- reg = <0x00920000 0x00600000>;
- };
- partition@f20000 {
- label = "VCTL";
- reg = <0x00f20000 0x00020000>;
- read-only;
- };
- partition@f40000 {
- label = "CurConf";
- reg = <0x00f40000 0x000a0000>;
- read-only;
- };
- partition@fe0000 {
- label = "FIS directory";
- reg = <0x00fe0000 0x00020000>;
- read-only;
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0xfe0000 */
+ fis-index-block = <0x1fc>;
};
};
syscon: syscon@40000000 {
pinctrl {
/*
- * gpio0egrp cover line 16 used by HD LED
- * gpio0fgrp cover line 17, 18 used by wireless LED and reset button
- * gpio0hgrp cover line 21, 22 used by MDIO for Marvell PHY
- * gpio0kgrp cover line 31 used by USB LED
+ * gpio0agrp cover line 0, used by WPS button
+ * gpio0fgrp cover line 16 used by HD LED
+ * gpio0ggrp cover line 17, 18 used by wireless LAN LED and
+ * reset button OR USB ID select on 17 and USB VBUS select
+ * on 18. (Confusing.)
+ * gpio0igrp cover line 21, 22 used by MDIO for Marvell PHY
*/
gpio0_default_pins: pinctrl-gpio0 {
mux {
function = "gpio0";
- groups = "gpio0egrp",
+ groups = "gpio0agrp",
"gpio0fgrp",
- "gpio0hgrp";
+ "gpio0ggrp",
+ "gpio0igrp";
};
};
/*
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
index dbecd6d2cfc4..7d4301b22b90 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
@@ -14,8 +14,8 @@
bits-per-pixel = <16>;
fsl,pcr = <0xcad08b80>;
bus-width = <18>;
- native-mode = <&qvga_timings>;
display-timings {
+ native-mode = <&qvga_timings>;
qvga_timings: 320x240 {
clock-frequency = <6500000>;
hactive = <320>;
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
index ad2f7e879831..80a7f96de4c6 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
@@ -14,8 +14,8 @@
bits-per-pixel = <16>;
fsl,pcr = <0xfa208b80>;
bus-width = <18>;
- native-mode = <&dvi_svga_timings>;
display-timings {
+ native-mode = <&dvi_svga_timings>;
dvi_svga_timings: 800x600 {
clock-frequency = <40000000>;
hactive = <800>;
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
index d60d8f464ca9..24027a1fb46d 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
@@ -14,8 +14,8 @@
bits-per-pixel = <16>;
fsl,pcr = <0xfa208b80>;
bus-width = <18>;
- native-mode = <&dvi_vga_timings>;
display-timings {
+ native-mode = <&dvi_vga_timings>;
dvi_vga_timings: 640x480 {
clock-frequency = <31250000>;
hactive = <640>;
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
index f8544a9e4633..05cccd12624c 100644
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ b/arch/arm/boot/dts/imx25-pdk.dts
@@ -76,8 +76,8 @@
bits-per-pixel = <16>;
fsl,pcr = <0xfa208b80>;
bus-width = <18>;
- native-mode = <&wvga_timings>;
display-timings {
+ native-mode = <&wvga_timings>;
wvga_timings: 640x480 {
hactive = <640>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts
index 087c6e237af0..6f1e8ce9e76e 100644
--- a/arch/arm/boot/dts/imx27-apf27dev.dts
+++ b/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -12,10 +12,10 @@
display: display {
model = "Chimei-LW700AT9003";
- native-mode = <&timing0>;
bits-per-pixel = <16>; /* non-standard but required */
fsl,pcr = <0xfae80083>; /* non-standard but required */
display-timings {
+ native-mode = <&timing0>;
timing0: 800x480 {
clock-frequency = <33000033>;
hactive = <800>;
diff --git a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
index 84fc8df4be7c..9c3ec82ec7e5 100644
--- a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
+++ b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
@@ -11,11 +11,11 @@
display0: CMO-QVGA {
model = "CMO-QVGA";
- native-mode = <&timing0>;
bits-per-pixel = <16>;
fsl,pcr = <0xfad08b80>;
display-timings {
+ native-mode = <&timing0>;
timing0: 320x240 {
clock-frequency = <6500000>;
hactive = <320>;
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
index 5e5e282ed30e..0cd75dadf292 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
@@ -15,10 +15,10 @@
display: display {
model = "Primeview-PD050VL1";
- native-mode = <&timing0>;
bits-per-pixel = <16>; /* non-standard but required */
fsl,pcr = <0xf0c88080>; /* non-standard but required */
display-timings {
+ native-mode = <&timing0>;
timing0: 640x480 {
hactive = <640>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
index 5606f417e9e8..bf883e45576a 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -14,11 +14,11 @@
display0: LQ035Q7 {
model = "Sharp-LQ035Q7";
- native-mode = <&timing0>;
bits-per-pixel = <16>;
fsl,pcr = <0xf00080c0>;
display-timings {
+ native-mode = <&timing0>;
timing0: 240x320 {
clock-frequency = <5500000>;
hactive = <240>;
diff --git a/arch/arm/boot/dts/imx53-m53menlo.dts b/arch/arm/boot/dts/imx53-m53menlo.dts
index 10acc5331ba6..719ed5ca454a 100644
--- a/arch/arm/boot/dts/imx53-m53menlo.dts
+++ b/arch/arm/boot/dts/imx53-m53menlo.dts
@@ -54,7 +54,8 @@
};
panel {
- compatible = "edt,etm070080dh6";
+ compatible = "edt,etm0700g0dh6";
+ pinctrl-0 = <&pinctrl_display_gpio>;
enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
port {
diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
index 1beac22266ed..019dda6b88ad 100644
--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
@@ -140,7 +140,18 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rmii";
+ phy-handle = <&ethphy>;
status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy: ethernet-phy@0 {
+ reg = <0>;
+ micrel,led-mode = <0>;
+ };
+ };
};
&hdmi {
diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
index 7a85116ef1d2..2418cf8f2317 100644
--- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
@@ -556,8 +556,6 @@
non-removable;
vmmc-supply = <&reg_3p3v>;
vqmmc-supply = <&reg_wlan_vmmc>;
- vqmmc-1-8-v;
- ocr-limit = <0x180>; /* 1.65v - 2.1v */
cap-power-off-card;
keep-power-in-suspend;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
index 82802f8ce7a0..d434868e870a 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
@@ -128,7 +128,7 @@
};
rtc@51 {
- compatible = "nxp,rtc8564";
+ compatible = "epson,rtc8564";
reg = <0x51>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index 50d9a989e06a..2cfb4112a467 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -33,6 +33,30 @@
spdif-out;
};
+ reg_1p5v: regulator-1p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "1P5V";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "1P8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_2p8v: regulator-2p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
reg_2p5v: regulator-2p5v {
compatible = "regulator-fixed";
regulator-name = "2P5V";
@@ -94,6 +118,29 @@
VDDIO-supply = <&reg_3p3v>;
lrclk-strength = <3>;
};
+
+ camera@3c {
+ compatible = "ovti,ov5645";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ov5645>;
+ reg = <0x3c>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "xclk";
+ clock-frequency = <24000000>;
+ vdddo-supply = <&reg_1p8v>;
+ vdda-supply = <&reg_2p8v>;
+ vddd-supply = <&reg_1p5v>;
+ enable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+
+ port {
+ ov5645_to_mipi_csi2: endpoint {
+ remote-endpoint = <&mipi_csi2_in>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
};
&iomuxc {
@@ -128,7 +175,6 @@
MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
>;
};
@@ -152,6 +198,14 @@
>;
};
+ pinctrl_ov5645: ov5645grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
+ >;
+ };
+
pinctrl_spdif: spdifgrp {
fsl,pins = <
MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
@@ -226,12 +280,23 @@
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii-id";
phy-reset-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
- interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- fsl,err006687-workaround-present;
status = "okay";
};
+&mipi_csi {
+ status = "okay";
+
+ port@0 {
+ reg = <0>;
+
+ mipi_csi2_in: endpoint {
+ remote-endpoint = <&ov5645_to_mipi_csi2>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ };
+ };
+};
+
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spdif>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 4b801935cad1..e6b4b8525f98 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -171,8 +171,6 @@
gpmi: gpmi-nand@112000 {
compatible = "fsl,imx6q-gpmi-nand";
- #address-cells = <1>;
- #size-cells = <1>;
reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
reg-names = "gpmi-nand", "bch";
interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
@@ -695,7 +693,7 @@
};
anatop: anatop@20c8000 {
- compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
+ compatible = "fsl,imx6q-anatop", "syscon", "simple-mfd";
reg = <0x020c8000 0x1000>;
interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
<0 54 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index b36fc012ff06..3a96b5538a2a 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -77,15 +77,6 @@
};
};
- intc: interrupt-controller@a01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x00a01000 0x1000>,
- <0x00a00100 0x100>;
- interrupt-parent = <&intc>;
- };
-
clocks {
ckil {
compatible = "fixed-clock";
@@ -133,6 +124,15 @@
clocks = <&clks IMX6SL_CLK_OCRAM>;
};
+ intc: interrupt-controller@a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ interrupt-parent = <&intc>;
+ };
+
L2: l2-cache@a02000 {
compatible = "arm,pl310-cache";
reg = <0x00a02000 0x1000>;
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
index b0a77ff70b67..13c7ba7fa6bc 100644
--- a/arch/arm/boot/dts/imx6sll.dtsi
+++ b/arch/arm/boot/dts/imx6sll.dtsi
@@ -75,15 +75,6 @@
};
};
- intc: interrupt-controller@a01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x00a01000 0x1000>,
- <0x00a00100 0x100>;
- interrupt-parent = <&intc>;
- };
-
ckil: clock-ckil {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -134,6 +125,15 @@
reg = <0x00900000 0x20000>;
};
+ intc: interrupt-controller@a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ interrupt-parent = <&intc>;
+ };
+
L2: l2-cache@a02000 {
compatible = "arm,pl310-cache";
reg = <0x00a02000 0x1000>;
@@ -234,7 +234,7 @@
compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart",
"fsl,imx21-uart";
reg = <0x02018000 0x4000>;
- interrupts =<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
dma-names = "rx", "tx";
clocks = <&clks IMX6SLL_CLK_UART4_IPG>,
@@ -621,7 +621,7 @@
};
sdma: dma-controller@20ec000 {
- compatible = "fsl,imx6sll-sdma", "fsl,imx35-sdma";
+ compatible = "fsl,imx6sll-sdma", "fsl,imx6ul-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_IPG>,
@@ -801,7 +801,7 @@
compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart",
"fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
- interrupts =<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
dma-names = "rx", "tx";
clocks = <&clks IMX6SLL_CLK_UART5_IPG>,
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index bb25add90f19..531a52c1e987 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -90,15 +90,6 @@
};
};
- intc: interrupt-controller@a01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x00a01000 0x1000>,
- <0x00a00100 0x100>;
- interrupt-parent = <&intc>;
- };
-
ckil: clock-ckil {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -181,6 +172,15 @@
clocks = <&clks IMX6SX_CLK_OCRAM>;
};
+ intc: interrupt-controller@a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ interrupt-parent = <&intc>;
+ };
+
L2: l2-cache@a02000 {
compatible = "arm,pl310-cache";
reg = <0x00a02000 0x1000>;
@@ -926,8 +926,8 @@
<&clks IMX6SX_CLK_ENET_PTP>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
- fsl,num-tx-queues=<3>;
- fsl,num-rx-queues=<3>;
+ fsl,num-tx-queues = <3>;
+ fsl,num-rx-queues = <3>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
index cbe61b61a212..c2a9dd57e56a 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
@@ -112,7 +112,7 @@
};
&i2c2 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-geam.dts b/arch/arm/boot/dts/imx6ul-geam.dts
index 21ddd359d3ed..9f63706383a7 100644
--- a/arch/arm/boot/dts/imx6ul-geam.dts
+++ b/arch/arm/boot/dts/imx6ul-geam.dts
@@ -156,7 +156,7 @@
};
&i2c2 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/imx6ul-isiot.dtsi
index b26d4f57c655..cc9adce638f5 100644
--- a/arch/arm/boot/dts/imx6ul-isiot.dtsi
+++ b/arch/arm/boot/dts/imx6ul-isiot.dtsi
@@ -148,7 +148,7 @@
};
&i2c2 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts b/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts
new file mode 100644
index 000000000000..5bad29683cc3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ * Copyright (c) 2019 Krzysztof Kozlowski <krzk@kernel.org>
+ */
+
+#include "imx6ul-kontron-n6310-s.dts"
+
+/ {
+ model = "Kontron N6310 S 43";
+ compatible = "kontron,imx6ul-n6310-s-43", "kontron,imx6ul-n6310-s",
+ "kontron,imx6ul-n6310-som", "fsl,imx6ul";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm7 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+};
+
+&i2c4 {
+ touchscreen@5d {
+ compatible = "goodix,gt928";
+ reg = <0x5d>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cap_touch>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+ irq-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat &pinctrl_lcdif_ctrl>;
+ /* Leave status disabled because of missing display panel node */
+};
+
+&pwm7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm7>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_cap_touch: captouchgrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b0b0 /* Touch Interrupt */
+ MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b0b0 /* Touch Reset */
+ MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b0b0 /* Touch Wake */
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
+ MX6UL_PAD_LCD_RESET__LCDIF_RESET 0x79
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
+ MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
+ MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
+ MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
+ MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
+ MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
+ MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
+ >;
+ };
+
+ pinctrl_pwm7: pwm7grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_VSYNC__PWM7_OUT 0x110b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
new file mode 100644
index 000000000000..0205fd56d975
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ * Copyright (c) 2019 Krzysztof Kozlowski <krzk@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "imx6ul-kontron-n6310-som.dtsi"
+
+/ {
+ model = "Kontron N6310 S";
+ compatible = "kontron,imx6ul-n6310-s", "kontron,imx6ul-n6310-som",
+ "fsl,imx6ul";
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led1 {
+ label = "debug-led1";
+ gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led2 {
+ label = "debug-led2";
+ gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led3 {
+ label = "debug-led3";
+ gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+
+ pwm-beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm8 0 5000>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_vref_adc: regulator-vref-adc {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-adc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&adc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+ num-channels = <3>;
+ vref-supply = <&reg_vref_adc>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ status = "okay";
+
+ eeprom@0 {
+ compatible = "anvo,anv32e61w", "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ spi-cpha;
+ spi-cpol;
+ pagesize = <1>;
+ size = <8192>;
+ address-width = <16>;
+ };
+};
+
+&fec1 {
+ pinctrl-0 = <&pinctrl_enet1>;
+ /delete-node/ mdio;
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy2>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ };
+
+ ethphy2: ethernet-phy@2 {
+ reg = <2>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET2_REF>;
+ clock-names = "rmii-ref";
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ rtc@32 {
+ compatible = "epson,rx8900";
+ reg = <0x32>;
+ };
+};
+
+&pwm8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm8>;
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ linux,rs485-enabled-at-boot-time;
+ rs485-rx-during-tx;
+ rs485-rts-active-low;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbotg1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3>;
+ voltage-ranges = <3300 3300>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ non-removable;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3>;
+ voltage-ranges = <3300 3300>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_reset_out &pinctrl_gpio>;
+
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
+ MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0xb0
+ >;
+ };
+
+ /* FRAM */
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x100b1
+ MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x100b1
+ MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x100b1
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x100b1 /* ECSPI1-CS1 */
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009
+ >;
+ };
+
+ pinctrl_enet2_mdio: enet2mdiogrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_gpio: gpiogrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b0b0 /* DOUT1 */
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b0b0 /* DIN1 */
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0 /* DOUT2 */
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* DIN2 */
+ >;
+ };
+
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x1b0b0 /* LED H14 */
+ MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0b0 /* LED H15 */
+ MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0 /* LED H16 */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_PIXCLK__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_CSI_MCLK__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001f8b0
+ MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001f8b0
+ >;
+ };
+
+ pinctrl_pwm8: pwm8grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__PWM8_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DATA04__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_NAND_DATA05__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_NAND_DATA06__UART2_DCE_CTS 0x1b0b1
+ /*
+ * mux unused RTS to make sure it doesn't cause
+ * any interrupts when it is undefined
+ */
+ MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1
+ MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1 {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10059
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x100b1 /* SD1_CD */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi
new file mode 100644
index 000000000000..a896b2348dd2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ * Copyright (c) 2019 Krzysztof Kozlowski <krzk@kernel.org>
+ */
+
+#include "imx6ul.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Kontron N6310 SOM";
+ compatible = "kontron,imx6ul-n6310-som", "fsl,imx6ul";
+
+ memory@80000000 {
+ reg = <0x80000000 0x10000000>;
+ device_type = "memory";
+ };
+};
+
+&ecspi2 {
+ cs-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+
+ spi-flash@0 {
+ compatible = "mxicy,mx25v8035f", "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ };
+ };
+};
+
+&fec2 {
+ phy-mode = "rmii";
+ status = "disabled";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-max-frequency = <108000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ reg = <0>;
+
+ partition@0 {
+ label = "ubi1";
+ reg = <0x00000000 0x08000000>;
+ };
+
+ partition@8000000 {
+ label = "ubi2";
+ reg = <0x08000000 0x08000000>;
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reset_out>;
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x100b1
+ MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x100b1
+ MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x100b1
+ MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x100b1
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
+ >;
+ };
+
+ pinctrl_enet1_mdio: enet1mdiogrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
+ MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
+ MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
+ MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
+ MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
+ MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
+ >;
+ };
+
+ pinctrl_reset_out: rstoutgrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b0b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-opos6uldev.dts b/arch/arm/boot/dts/imx6ul-opos6uldev.dts
index 0e59ee57fd55..8ecdb9ad2b2e 100644
--- a/arch/arm/boot/dts/imx6ul-opos6uldev.dts
+++ b/arch/arm/boot/dts/imx6ul-opos6uldev.dts
@@ -56,7 +56,7 @@
stdout-path = &uart1;
};
- backlight {
+ backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm3 0 191000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -97,6 +97,18 @@
gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
};
+ panel: panel {
+ compatible = "armadeus,st0700-adapt";
+ power-supply = <&reg_3v3>;
+ backlight = <&backlight>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&lcdif_out>;
+ };
+ };
+ };
+
reg_5v: regulator-5v {
compatible = "regulator-fixed";
regulator-name = "5V";
@@ -182,28 +194,11 @@
&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif>;
- display = <&display0>;
- lcd-supply = <&reg_3v3>;
status = "okay";
- display0: display0 {
- bits-per-pixel = <32>;
- bus-width = <18>;
-
- display-timings {
- timing0: timing0 {
- clock-frequency = <33000033>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <96>;
- hfront-porch = <96>;
- vback-porch = <20>;
- vfront-porch = <21>;
- hsync-len = <64>;
- vsync-len = <4>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
+ port {
+ lcdif_out: endpoint {
+ remote-endpoint = <&panel_in>;
};
};
};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
index fc2997449b49..41f3b7f62bbf 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi
+++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
@@ -7,10 +7,9 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pwm/pwm.h>
-#include "imx6ul.dtsi"
/ {
- model = "Phytec phyCORE i.MX6 UltraLite";
+ model = "PHYTEC phyCORE-i.MX6 UltraLite";
compatible = "phytec,imx6ul-pcl063", "fsl,imx6ul";
chosen {
@@ -31,8 +30,7 @@
pinctrl-0 = <&pinctrl_gpioleds_som>;
compatible = "gpio-leds";
- led_green {
- label = "phycore:green";
+ phycore-green {
gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
@@ -43,20 +41,21 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
phy-mode = "rmii";
- phy-handle = <&ethphy0>;
- status = "okay";
+ phy-handle = <&ethphy1>;
+ status = "disabled";
mdio: mdio {
#address-cells = <1>;
#size-cells = <0>;
- ethphy0: ethernet-phy@1 {
+ ethphy1: ethernet-phy@1 {
reg = <1>;
interrupt-parent = <&gpio1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET_REF>;
clock-names = "rmii-ref";
+ status = "disabled";
};
};
};
@@ -65,12 +64,12 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
nand-on-flash-bbt;
- status = "okay";
+ status = "disabled";
};
&i2c1 {
pinctrl-names = "default";
- pinctrl-0 =<&pinctrl_i2c1>;
+ pinctrl-0 = <&pinctrl_i2c1>;
clock-frequency = <100000>;
status = "okay";
@@ -90,19 +89,28 @@
status = "okay";
};
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <8>;
+ no-1-8-v;
+ non-removable;
+ status = "disabled";
+};
+
&iomuxc {
pinctrl_enet1: enet1grp {
fsl,pins = <
- MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0
- MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0
+ MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x10010
+ MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x10010
MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
- MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
- MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
- MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
- MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b010
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b010
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b010
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b010
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x17059
>;
};
@@ -145,4 +153,19 @@
>;
};
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
+ >;
+ };
+
};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts
index b6a1407a9d44..699dfcbf9a60 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts
+++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts
@@ -5,13 +5,15 @@
*/
/dts-v1/;
-#include "imx6ul-phytec-pcl063.dtsi"
-#include "imx6ul-phytec-phyboard-segin.dtsi"
-#include "imx6ul-phytec-peb-eval-01.dtsi"
+#include "imx6ul.dtsi"
+#include "imx6ul-phytec-phycore-som.dtsi"
+#include "imx6ul-phytec-segin.dtsi"
+#include "imx6ul-phytec-segin-peb-eval-01.dtsi"
/ {
- model = "Phytec phyBOARD-Segin i.MX6 UltraLite Full Featured";
- compatible = "phytec,imx6ul-pbacd10", "phytec,imx6ul-pcl063", "fsl,imx6ul";
+ model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite Full Featured with NAND";
+ compatible = "phytec,imx6ul-pbacd10-nand", "phytec,imx6ul-pbacd10",
+ "phytec,imx6ul-pcl063", "fsl,imx6ul";
};
&adc1 {
@@ -27,9 +29,18 @@
};
&ecspi3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi3>;
- cs-gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&ethphy1 {
+ status = "okay";
+};
+
+&ethphy2 {
+ status = "okay";
+};
+
+&fec1 {
status = "okay";
};
@@ -37,6 +48,10 @@
status = "okay";
};
+&gpmi {
+ status = "okay";
+};
+
&i2c_rtc {
status = "okay";
};
@@ -76,14 +91,3 @@
&usdhc1 {
status = "okay";
};
-
-&iomuxc {
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <
- MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO 0x10b0
- MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0
- MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0
- MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x10b0
- >;
- };
-};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi
index e2f38f39a6ad..2f3fd32a1167 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi
+++ b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi
@@ -21,20 +21,22 @@
};
};
- user_leds: leds {
+ user_leds: user-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_user_leds>;
status = "disabled";
- led_yellow {
- gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "default-on";
+ user-led1 {
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "gpio";
+ default-state = "on";
};
- led_red {
- gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "default-on";
+ user-led2 {
+ gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "gpio";
+ default-state = "on";
};
};
};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi
index 7bf439a77d2c..8d5f8dc6ad58 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi
+++ b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi
@@ -5,7 +5,7 @@
*/
/ {
- model = "Phytec phyBOARD-Segin i.MX6 UltraLite";
+ model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite";
compatible = "phytec,imx6ul-pbacd-10", "phytec,imx6ul-pcl063", "fsl,imx6ul";
aliases {
@@ -103,11 +103,18 @@
assigned-clock-rates = <786432000>;
};
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ cs-gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+};
+
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
phy-mode = "rmii";
- phy-handle = <&ethphy1>;
+ phy-handle = <&ethphy2>;
status = "disabled";
};
@@ -160,11 +167,12 @@
};
&mdio {
- ethphy1: ethernet-phy@2 {
+ ethphy2: ethernet-phy@2 {
reg = <2>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET2_REF>;
clock-names = "rmii-ref";
+ status = "disabled";
};
};
@@ -224,16 +232,25 @@
>;
};
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO 0x10b0
+ MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0
+ MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0
+ MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x10b0
+ >;
+ };
+
pinctrl_enet2: enet2grp {
fsl,pins = <
MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
- MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
- MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
- MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
- MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b010
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b010
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b010
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b010
>;
};
diff --git a/arch/arm/boot/dts/imx6ul-pico-hobbit.dts b/arch/arm/boot/dts/imx6ul-pico-hobbit.dts
index 39eeeddac39e..09f7ffa9ad8c 100644
--- a/arch/arm/boot/dts/imx6ul-pico-hobbit.dts
+++ b/arch/arm/boot/dts/imx6ul-pico-hobbit.dts
@@ -43,7 +43,7 @@
};
&i2c2 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-pico-pi.dts b/arch/arm/boot/dts/imx6ul-pico-pi.dts
index de07357b27fc..6cd7d5877d20 100644
--- a/arch/arm/boot/dts/imx6ul-pico-pi.dts
+++ b/arch/arm/boot/dts/imx6ul-pico-pi.dts
@@ -43,7 +43,7 @@
};
&i2c2 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
@@ -58,7 +58,7 @@
};
&i2c3 {
- clock_frequency = <100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 81d4b4925127..f008036e9294 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -93,18 +93,6 @@
};
};
- intc: interrupt-controller@a01000 {
- compatible = "arm,gic-400", "arm,cortex-a7-gic";
- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
- #interrupt-cells = <3>;
- interrupt-controller;
- interrupt-parent = <&intc>;
- reg = <0x00a01000 0x1000>,
- <0x00a02000 0x2000>,
- <0x00a04000 0x2000>,
- <0x00a06000 0x2000>;
- };
-
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
@@ -171,6 +159,18 @@
reg = <0x00900000 0x20000>;
};
+ intc: interrupt-controller@a01000 {
+ compatible = "arm,gic-400", "arm,cortex-a7-gic";
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ reg = <0x00a01000 0x1000>,
+ <0x00a02000 0x2000>,
+ <0x00a04000 0x2000>,
+ <0x00a06000 0x2000>;
+ };
+
dma_apbh: dma-apbh@1804000 {
compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
reg = <0x01804000 0x2000>;
@@ -227,6 +227,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI1>,
<&clks IMX6UL_CLK_ECSPI1>;
clock-names = "ipg", "per";
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -239,6 +241,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI2>,
<&clks IMX6UL_CLK_ECSPI2>;
clock-names = "ipg", "per";
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -251,6 +255,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI3>,
<&clks IMX6UL_CLK_ECSPI3>;
clock-names = "ipg", "per";
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -263,6 +269,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI4>,
<&clks IMX6UL_CLK_ECSPI4>;
clock-names = "ipg", "per";
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -510,8 +518,8 @@
<&clks IMX6UL_CLK_ENET2_REF_125M>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
- fsl,num-tx-queues=<1>;
- fsl,num-rx-queues=<1>;
+ fsl,num-tx-queues = <1>;
+ fsl,num-rx-queues = <1>;
status = "disabled";
};
@@ -845,8 +853,8 @@
<&clks IMX6UL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
- fsl,num-tx-queues=<1>;
- fsl,num-rx-queues=<1>;
+ fsl,num-tx-queues = <1>;
+ fsl,num-rx-queues = <1>;
status = "disabled";
};
@@ -858,7 +866,7 @@
<&clks IMX6UL_CLK_USDHC1>,
<&clks IMX6UL_CLK_USDHC1>;
clock-names = "ipg", "ahb", "per";
- fsl,tuning-step= <2>;
+ fsl,tuning-step = <2>;
fsl,tuning-start-tap = <20>;
bus-width = <4>;
status = "disabled";
@@ -873,7 +881,7 @@
<&clks IMX6UL_CLK_USDHC2>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
- fsl,tuning-step= <2>;
+ fsl,tuning-step = <2>;
fsl,tuning-start-tap = <20>;
status = "disabled";
};
@@ -957,6 +965,15 @@
};
};
+ csi: csi@21c4000 {
+ compatible = "fsl,imx6ul-csi", "fsl,imx7-csi";
+ reg = <0x021c4000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_CSI>;
+ clock-names = "mclk";
+ status = "disabled";
+ };
+
lcdif: lcdif@21c8000 {
compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
reg = <0x021c8000 0x4000>;
diff --git a/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi
new file mode 100644
index 000000000000..56cd16e5a77f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+#include "imx6ul-phytec-phycore-som.dtsi"
+
+/ {
+ model = "PHYTEC phyCORE-i.MX6 ULL";
+ compatible = "phytec,imx6ull-pcl063", "fsl,imx6ull";
+};
+
+&iomuxc {
+ /delete-node/ gpioledssomgrp;
+};
+
+&iomuxc_snvs {
+ pinctrl_gpioleds_som: gpioledssomgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x0b0b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts
new file mode 100644
index 000000000000..9648d4ecaf58
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6ull.dtsi"
+#include "imx6ull-phytec-phycore-som.dtsi"
+#include "imx6ull-phytec-segin.dtsi"
+#include "imx6ull-phytec-segin-peb-eval-01.dtsi"
+
+/ {
+ model = "PHYTEC phyBOARD-Segin i.MX6 ULL Full Featured with eMMC";
+ compatible = "phytec,imx6ull-pbacd10-emmc", "phytec,imx6ull-pbacd10",
+ "phytec,imx6ull-pcl063","fsl,imx6ull";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&tlv320 {
+ status = "okay";
+};
+
+&ecspi3 {
+ status = "okay";
+};
+
+&ethphy1 {
+ status = "okay";
+};
+
+&ethphy2 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&fec2 {
+ status = "okay";
+};
+
+&i2c_rtc {
+ status = "okay";
+};
+
+&reg_can1_en {
+ status = "okay";
+};
+
+&reg_sound_1v8 {
+ status = "okay";
+};
+
+&reg_sound_3v3 {
+ status = "okay";
+};
+
+&sai2 {
+ status = "okay";
+};
+
+&sound {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usbotg1 {
+ status = "okay";
+};
+
+&usbotg2 {
+ status = "okay";
+};
+
+&usdhc1 {
+ status = "okay";
+};
+
+&usdhc2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts
new file mode 100644
index 000000000000..656baf846453
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6ull.dtsi"
+#include "imx6ull-phytec-phycore-som.dtsi"
+#include "imx6ull-phytec-segin.dtsi"
+#include "imx6ull-phytec-segin-peb-eval-01.dtsi"
+
+/ {
+ model = "PHYTEC phyBOARD-Segin i.MX6 ULL Full Featured with NAND";
+ compatible = "phytec,imx6ull-pbacd10-nand", "phytec,imx6ull-pbacd10",
+ "phytec,imx6ull-pcl063", "fsl,imx6ull";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&tlv320 {
+ status = "okay";
+};
+
+&ecspi3 {
+ status = "okay";
+};
+
+&ethphy1 {
+ status = "okay";
+};
+
+&ethphy2 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&fec2 {
+ status = "okay";
+};
+
+&gpmi {
+ status = "okay";
+};
+
+&i2c_rtc {
+ status = "okay";
+};
+
+&reg_can1_en {
+ status = "okay";
+};
+
+&reg_sound_1v8 {
+ status = "okay";
+};
+
+&reg_sound_3v3 {
+ status = "okay";
+};
+
+&sai2 {
+ status = "okay";
+};
+
+&sound {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usbotg1 {
+ status = "okay";
+};
+
+&usbotg2 {
+ status = "okay";
+};
+
+&usdhc1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts
new file mode 100644
index 000000000000..e168494e0a6d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6ull.dtsi"
+#include "imx6ull-phytec-phycore-som.dtsi"
+#include "imx6ull-phytec-segin.dtsi"
+#include "imx6ull-phytec-segin-peb-eval-01.dtsi"
+
+/ {
+ model = "PHYTEC phyBOARD-Segin i.MX6 ULL Low Cost with NAND";
+ compatible = "phytec,imx6ull-pbacd10-nand", "phytec,imx6ull-pbacd10",
+ "phytec,imx6ull-pcl063", "fsl,imx6ull";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&ethphy1 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&gpmi {
+ status = "okay";
+};
+
+&i2c_rtc {
+ status = "okay";
+};
+
+&usbotg1 {
+ status = "okay";
+};
+
+&usdhc1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi
new file mode 100644
index 000000000000..ff08d95a1aa2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+#include "imx6ul-phytec-segin-peb-eval-01.dtsi"
+
+&iomuxc {
+ /delete-node/ gpio_keysgrp;
+};
+
+&iomuxc_snvs {
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x79
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi
new file mode 100644
index 000000000000..c1595fc785f7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+#include "imx6ul-phytec-segin.dtsi"
+
+/ {
+ model = "PHYTEC phyBOARD-Segin i.MX6 ULL";
+ compatible = "phytec,imx6ull-pbacd-10", "phytec,imx6ull-pcl063","fsl,imx6ull";
+};
+
+&iomuxc {
+ /delete-node/ flexcan1engrp;
+ /delete-node/ rtcintgrp;
+ /delete-node/ stmpegrp;
+};
+
+&iomuxc_snvs {
+ princtrl_flexcan1_en: flexcan1engrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x17059
+ >;
+ };
+
+ pinctrl_rtc_int: rtcintgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x17059
+ >;
+ };
+
+ pinctrl_stmpe: stmpegrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x17059
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index 895fbde4d433..917eb0b58b13 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -54,6 +54,7 @@
regulator-name = "+V3.3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
reg_module_3v3_avdd: regulator-module-3v3-avdd {
@@ -61,6 +62,7 @@
regulator-name = "+V3.3_AVDD_AUDIO";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
sound {
@@ -99,8 +101,9 @@
};
&fec1 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_enet1>;
+ pinctrl-1 = <&pinctrl_enet1_sleep>;
clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>,
@@ -115,6 +118,18 @@
fsl,magic-packet;
};
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "disabled";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "disabled";
+};
+
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
@@ -125,8 +140,12 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1 &pinctrl_i2c1_int>;
+ pinctrl-1 = <&pinctrl_i2c1_recovery &pinctrl_i2c1_int>;
+ scl-gpios = <&gpio1 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio1 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
status = "okay";
codec: sgtl5000@a {
@@ -227,8 +246,11 @@
&i2c4 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_recovery>;
+ scl-gpios = <&gpio7 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio7 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
};
&lcdif {
@@ -267,10 +289,6 @@
status = "okay";
};
-&snvs_pwrkey {
- status = "disabled";
-};
-
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_ctrl1 &pinctrl_uart1_ctrl2>;
@@ -323,16 +341,16 @@
vmmc-supply = <&reg_module_3v3>;
vqmmc-supply = <&reg_DCDC3>;
non-removable;
+ sdhci-caps-mask = <0x80000000 0x0>;
};
&iomuxc {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4>;
+ pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4
+ &pinctrl_gpio7>;
pinctrl_gpio1: gpio1-grp {
fsl,pins = <
- MX7D_PAD_ENET1_RGMII_RD3__GPIO7_IO3 0x74 /* SODIMM 55 */
- MX7D_PAD_ENET1_RGMII_RD2__GPIO7_IO2 0x74 /* SODIMM 63 */
MX7D_PAD_SAI1_RX_SYNC__GPIO6_IO16 0x14 /* SODIMM 77 */
MX7D_PAD_EPDC_DATA09__GPIO2_IO9 0x14 /* SODIMM 89 */
MX7D_PAD_EPDC_DATA08__GPIO2_IO8 0x74 /* SODIMM 91 */
@@ -413,6 +431,13 @@
>;
};
+ pinctrl_gpio7: gpio7-grp { /* Alternatively CAN1 */
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_RD3__GPIO7_IO3 0x14 /* SODIMM 55 */
+ MX7D_PAD_ENET1_RGMII_RD2__GPIO7_IO2 0x14 /* SODIMM 63 */
+ >;
+ };
+
pinctrl_i2c1_int: i2c1-int-grp { /* PMIC / TOUCH */
fsl,pins = <
MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x79
@@ -442,6 +467,22 @@
>;
};
+ pinctrl_enet1_sleep: enet1sleepgrp {
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_RX_CTL__GPIO7_IO4 0x0
+ MX7D_PAD_ENET1_RGMII_RD0__GPIO7_IO0 0x0
+ MX7D_PAD_ENET1_RGMII_RD1__GPIO7_IO1 0x0
+ MX7D_PAD_ENET1_RGMII_RXC__GPIO7_IO5 0x0
+
+ MX7D_PAD_ENET1_RGMII_TX_CTL__GPIO7_IO10 0x0
+ MX7D_PAD_ENET1_RGMII_TD0__GPIO7_IO6 0x0
+ MX7D_PAD_ENET1_RGMII_TD1__GPIO7_IO7 0x0
+ MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x0
+ MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x0
+ MX7D_PAD_SD2_WP__GPIO5_IO10 0x0
+ >;
+ };
+
pinctrl_ecspi3_cs: ecspi3-cs-grp {
fsl,pins = <
MX7D_PAD_I2C2_SDA__GPIO4_IO11 0x14
@@ -456,10 +497,17 @@
>;
};
+ pinctrl_flexcan1: flexcan1-grp {
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_RD3__FLEXCAN1_TX 0x79 /* SODIMM 55 */
+ MX7D_PAD_ENET1_RGMII_RD2__FLEXCAN1_RX 0x79 /* SODIMM 63 */
+ >;
+ };
+
pinctrl_flexcan2: flexcan2-grp {
fsl,pins = <
- MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x59
- MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x59
+ MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x79 /* SODIMM 188 */
+ MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x79 /* SODIMM 178 */
>;
};
@@ -495,6 +543,13 @@
>;
};
+ pinctrl_i2c4_recovery: i2c4-recoverygrp {
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_TD2__GPIO7_IO8 0x4000007f
+ MX7D_PAD_ENET1_RGMII_TD3__GPIO7_IO9 0x4000007f
+ >;
+ };
+
pinctrl_lcdif_dat: lcdif-dat-grp {
fsl,pins = <
MX7D_PAD_LCD_DATA00__LCD_DATA0 0x79
@@ -695,6 +750,13 @@
>;
};
+ pinctrl_i2c1_recovery: i2c1-recoverygrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x4000007f
+ MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5 0x4000007f
+ >;
+ };
+
pinctrl_cd_usdhc1: usdhc1-cd-grp {
fsl,pins = <
MX7D_PAD_LPSR_GPIO1_IO00__GPIO1_IO0 0x59 /* CD */
diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
index e61567437d73..7646284e13a7 100644
--- a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
+++ b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
@@ -44,7 +44,7 @@
<&clks IMX7D_ENET1_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
- phy-mode = "rgmii";
+ phy-mode = "rgmii-id";
phy-handle = <&ethphy0>;
fsl,magic-packet;
status = "okay";
@@ -54,10 +54,12 @@
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
};
ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
@@ -70,7 +72,7 @@
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
- phy-mode = "rgmii";
+ phy-mode = "rgmii-id";
phy-handle = <&ethphy1>;
fsl,magic-packet;
status = "okay";
diff --git a/arch/arm/boot/dts/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/imx7d-zii-rmu2.dts
new file mode 100644
index 000000000000..2b8d6cc45a53
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-zii-rmu2.dts
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device tree file for ZII's RMU2 board
+ *
+ * RMU - Remote Modem Unit
+ *
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+#include <dt-bindings/thermal/thermal.h>
+#include "imx7d.dtsi"
+
+/ {
+ model = "ZII RMU2 Board";
+ compatible = "zii,imx7d-rmu2", "fsl,imx7d";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&pinctrl_leds_debug>;
+ pinctrl-names = "default";
+
+ debug {
+ label = "zii:green:debug1";
+ gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ cs-gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
+ <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+ assigned-clock-rates = <0>, <100000000>;
+ phy-mode = "rgmii";
+ phy-handle = <&fec1_phy>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fec1_phy: ethernet-phy@0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1_phy_reset>,
+ <&pinctrl_enet1_phy_interrupt>;
+ reg = <0>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic@8 {
+ compatible = "fsl,pfuze3000";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1a {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1b {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1475000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1650000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vldo2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vccsd {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: v33 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vldo4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c04";
+ reg = <0x50>;
+ };
+
+ eeprom@52 {
+ compatible = "atmel,24c04";
+ reg = <0x52>;
+ };
+};
+
+&snvs_rtc {
+ status = "disabled";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clks IMX7D_UART4_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+ status = "okay";
+
+ rave-sp {
+ compatible = "zii,rave-sp-rdu2";
+ current-speed = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ watchdog {
+ compatible = "zii,rave-sp-watchdog";
+ };
+
+ eeprom@a3 {
+ compatible = "zii,rave-sp-eeprom";
+ reg = <0xa3 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ zii,eeprom-name = "main-eeprom";
+ };
+ };
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ bus-width = <4>;
+ no-1-8-v;
+ no-sdio;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ bus-width = <8>;
+ no-1-8-v;
+ non-removable;
+ no-sdio;
+ no-sd;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&wdog1 {
+ status = "disabled";
+};
+
+&iomuxc {
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x2
+ MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x2
+ MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO 0x2
+ MX7D_PAD_ECSPI1_SS0__GPIO4_IO19 0x59
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX7D_PAD_SD2_CD_B__ENET1_MDIO 0x3
+ MX7D_PAD_SD2_WP__ENET1_MDC 0x3
+ MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1
+ MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1
+ MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1
+ MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1
+ MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1
+ MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1
+ MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1
+ MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1
+ MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1
+ MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1
+ MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1
+ MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1
+ >;
+ };
+
+ pinctrl_enet1_phy_reset: enet1phyresetgrp {
+ fsl,pins = <
+ MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x14
+
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f
+ MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f
+ >;
+ };
+
+ pinctrl_leds_debug: ledsgrp {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA08__GPIO2_IO8 0x59
+ >;
+ };
+
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x79
+ MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 0x79
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX7D_PAD_SD2_DATA0__UART4_DCE_RX 0x79
+ MX7D_PAD_SD2_DATA1__UART4_DCE_TX 0x79
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX7D_PAD_SD1_CMD__SD1_CMD 0x59
+ MX7D_PAD_SD1_CLK__SD1_CLK 0x19
+ MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59
+ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59
+ MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59
+ MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX7D_PAD_SD3_CMD__SD3_CMD 0x59
+ MX7D_PAD_SD3_CLK__SD3_CLK 0x19
+ MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59
+ MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59
+ MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59
+ MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59
+ MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59
+ MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59
+ MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59
+ MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59
+ MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x59
+ >;
+ };
+};
+
+&iomuxc_lpsr {
+ pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp {
+ fsl,phy = <
+ MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x08
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-zii-rpu2.dts b/arch/arm/boot/dts/imx7d-zii-rpu2.dts
index 4a78ddc7513d..39812c92bf0d 100644
--- a/arch/arm/boot/dts/imx7d-zii-rpu2.dts
+++ b/arch/arm/boot/dts/imx7d-zii-rpu2.dts
@@ -669,10 +669,6 @@
status = "disabled";
};
-&snvs_pwrkey {
- status = "disabled";
-};
-
&iomuxc {
pinctrl_ecspi1: ecspi1grp {
fsl,pins = <
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index 42528d2812a2..9c8dd32cc035 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -147,8 +147,8 @@
<&clks IMX7D_ENET_PHY_REF_ROOT_CLK>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
- fsl,num-tx-queues=<3>;
- fsl,num-rx-queues=<3>;
+ fsl,num-tx-queues = <3>;
+ fsl,num-rx-queues = <3>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index c1a4fff5ceda..710f850e785c 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -151,7 +151,7 @@
compatible = "fsl,imx7d-tempmon";
interrupt-parent = <&gpc>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
- fsl,tempmon =<&anatop>;
+ fsl,tempmon = <&anatop>;
nvmem-cells = <&tempmon_calib>,
<&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
@@ -1184,8 +1184,8 @@
<&clks IMX7D_ENET_PHY_REF_ROOT_CLK>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
- fsl,num-tx-queues=<3>;
- fsl,num-rx-queues=<3>;
+ fsl,num-tx-queues = <3>;
+ fsl,num-rx-queues = <3>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index 992747a57442..6859a3a83750 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -101,6 +101,34 @@
reg = <0x40000000 0x800000>;
ranges;
+ edma1: dma-controller@40080000 {
+ #dma-cells = <2>;
+ compatible = "fsl,imx7ulp-edma";
+ reg = <0x40080000 0x2000>,
+ <0x40210000 0x1000>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <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 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dma", "dmamux0";
+ clocks = <&pcc2 IMX7ULP_CLK_DMA1>,
+ <&pcc2 IMX7ULP_CLK_DMA_MUX1>;
+ };
+
crypto: crypto@40240000 {
compatible = "fsl,sec-v4.0";
#address-cells = <1>;
@@ -186,7 +214,7 @@
reg = <0x40330200 0x200>;
};
- usbphy1: usb-phy@0x40350000 {
+ usbphy1: usb-phy@40350000 {
compatible = "fsl,imx7ulp-usbphy", "fsl,imx6ul-usbphy";
reg = <0x40350000 0x1000>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
@@ -201,12 +229,12 @@
clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>,
<&scg1 IMX7ULP_CLK_NIC1_DIV>,
<&pcc2 IMX7ULP_CLK_USDHC0>;
- clock-names ="ipg", "ahb", "per";
+ clock-names = "ipg", "ahb", "per";
assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC0>;
assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>;
bus-width = <4>;
fsl,tuning-start-tap = <20>;
- fsl,tuning-step= <2>;
+ fsl,tuning-step = <2>;
status = "disabled";
};
@@ -217,12 +245,12 @@
clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>,
<&scg1 IMX7ULP_CLK_NIC1_DIV>,
<&pcc2 IMX7ULP_CLK_USDHC1>;
- clock-names ="ipg", "ahb", "per";
+ clock-names = "ipg", "ahb", "per";
assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC1>;
assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>;
bus-width = <4>;
fsl,tuning-start-tap = <20>;
- fsl,tuning-step= <2>;
+ fsl,tuning-step = <2>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi
index a88eb22070a1..994cabcf4b51 100644
--- a/arch/arm/boot/dts/kirkwood-ts219.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi
@@ -104,3 +104,11 @@
&pcie0 {
status = "okay";
};
+
+&rtc {
+ /*
+ * There is a s35390a available on the i2c bus, the internal rtc isn't
+ * working (probably no crystal assembled).
+ */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/meson8b-ec100.dts
index 96d239d8334e..bed1dfef1985 100644
--- a/arch/arm/boot/dts/meson8b-ec100.dts
+++ b/arch/arm/boot/dts/meson8b-ec100.dts
@@ -219,6 +219,27 @@
*/
vin-supply = <&vcc_3v3>;
};
+
+ vddee: regulator-vddee {
+ /*
+ * Silergy SY8089AAC-GP 2A continuous, 3A peak, 1MHz
+ * Synchronous Step Down Regulator. Also called VDDAO
+ * in a part of the schematics.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDEE";
+ regulator-min-microvolt = <860000>;
+ regulator-max-microvolt = <1140000>;
+
+ vin-supply = <&vcc_5v>;
+
+ pwms = <&pwm_cd 1 1148 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
};
&cpu0 {
@@ -269,6 +290,10 @@
};
};
+&mali {
+ mali-supply = <&vddee>;
+};
+
&saradc {
status = "okay";
vref-supply = <&vcc_1v8>;
@@ -350,10 +375,10 @@
&pwm_cd {
status = "okay";
- pinctrl-0 = <&pwm_c1_pins>;
+ pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>;
pinctrl-names = "default";
- clocks = <&clkc CLKID_XTAL>;
- clock-names = "clkin0";
+ clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>;
+ clock-names = "clkin0", "clkin1";
};
&rtc {
diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts
index bb27b34eb346..6e39ad52e42d 100644
--- a/arch/arm/boot/dts/meson8b-mxq.dts
+++ b/arch/arm/boot/dts/meson8b-mxq.dts
@@ -76,6 +76,22 @@
regulator-boot-on;
regulator-always-on;
};
+
+ vddee: regulator-vddee {
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDEE";
+ regulator-min-microvolt = <860000>;
+ regulator-max-microvolt = <1140000>;
+
+ vin-supply = <&vcc_5v>;
+
+ pwms = <&pwm_cd 1 1148 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
};
&cpu0 {
@@ -112,6 +128,10 @@
};
};
+&mali {
+ mali-supply = <&vddee>;
+};
+
&saradc {
status = "okay";
vref-supply = <&vcc_1v8>;
@@ -143,10 +163,10 @@
&pwm_cd {
status = "okay";
- pinctrl-0 = <&pwm_c1_pins>;
+ pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>;
pinctrl-names = "default";
- clocks = <&clkc CLKID_XTAL>;
- clock-names = "clkin0";
+ clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>;
+ clock-names = "clkin0", "clkin1";
};
&uart_AO {
diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index 86c4614e0a38..a24eccc354b9 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -154,6 +154,23 @@
vin-supply = <&p5v0>;
};
+ vddee: regulator-vddee {
+ /* Monolithic Power Systems MP2161 */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDEE";
+ regulator-min-microvolt = <860000>;
+ regulator-max-microvolt = <1140000>;
+
+ vin-supply = <&p5v0>;
+
+ pwms = <&pwm_cd 1 12218 0>;
+ pwm-dutycycle-range = <91 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
vdd_rtc: regulator-vdd-rtc {
/*
* Torex Semiconductor XC6215 configured for a fixed output of
@@ -173,6 +190,12 @@
cpu-supply = <&vcck>;
};
+&efuse {
+ ethernet_mac_address: mac@1b4 {
+ reg = <0x1b4 0x6>;
+ };
+};
+
&ethmac {
status = "okay";
@@ -183,6 +206,9 @@
phy-handle = <&eth_phy>;
amlogic,tx-delay-ns = <4>;
+ nvmem-cells = <&ethernet_mac_address>;
+ nvmem-cell-names = "mac-address";
+
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
@@ -276,6 +302,10 @@
pinctrl-names = "default";
};
+&mali {
+ mali-supply = <&vddee>;
+};
+
&saradc {
status = "okay";
vref-supply = <&vcc_1v8>;
@@ -308,10 +338,10 @@
&pwm_cd {
status = "okay";
- pinctrl-0 = <&pwm_c1_pins>;
+ pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>;
pinctrl-names = "default";
- clocks = <&clkc CLKID_XTAL>;
- clock-names = "clkin0";
+ clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>;
+ clock-names = "clkin0", "clkin1";
};
&rtc {
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index fba2c70c2fda..099bf8e711c9 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -361,6 +361,14 @@
};
};
+ pwm_d_pins: pwm-d {
+ mux {
+ groups = "pwm_d";
+ function = "pwm_d";
+ bias-disable;
+ };
+ };
+
uart_b0_pins: uart-b0 {
mux {
groups = "uart_tx_b0",
@@ -410,6 +418,8 @@
<&clkc CLKID_MPLL2>,
<&clkc CLKID_MPLL2>;
clock-names = "stmmaceth", "clkin0", "clkin1";
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <2048>;
resets = <&reset RESET_ETHERNET>;
reset-names = "stmmaceth";
diff --git a/arch/arm/boot/dts/mt7629-rfb.dts b/arch/arm/boot/dts/mt7629-rfb.dts
new file mode 100644
index 000000000000..3621b7d2b22a
--- /dev/null
+++ b/arch/arm/boot/dts/mt7629-rfb.dts
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7629.dtsi"
+
+/ {
+ model = "MediaTek MT7629 reference board";
+ compatible = "mediatek,mt7629-rfb", "mediatek,mt7629";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ reset {
+ label = "factory";
+ linux,code = <KEY_RESTART>;
+ gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 58 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x10000000>;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&eth {
+ pinctrl-names = "default";
+ pinctrl-0 = <&eth_pins>;
+ pinctrl-1 = <&ephy_leds_pins>;
+ status = "okay";
+
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ phy-handle = <&phy0>;
+ };
+
+ mdio: mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ phy-mode = "gmii";
+ };
+ };
+};
+
+&i2c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins>;
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qspi_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x00000 0x60000>;
+ read-only;
+ };
+
+ partition@60000 {
+ label = "u-boot-env";
+ reg = <0x60000 0x10000>;
+ read-only;
+ };
+
+ factory: partition@70000 {
+ label = "factory";
+ reg = <0x70000 0x40000>;
+ read-only;
+ };
+
+ partition@b0000 {
+ label = "kernel";
+ reg = <0xb0000 0xb50000>;
+ };
+ };
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins>;
+};
+
+&pciephy1 {
+ status = "okay";
+};
+
+&pio {
+ eth_pins: eth-pins {
+ mux {
+ function = "eth";
+ groups = "mdc_mdio";
+ };
+ };
+
+ ephy_leds_pins: ephy-leds-pins {
+ mux {
+ function = "led";
+ groups = "gphy_leds_0", "ephy_leds";
+ };
+ };
+
+ i2c_pins: i2c-pins {
+ mux {
+ function = "i2c";
+ groups = "i2c_0";
+ };
+
+ conf {
+ pins = "I2C_SDA", "I2C_SCL";
+ drive-strength = <4>;
+ bias-disable;
+ };
+ };
+
+ pcie_pins: pcie-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_clkreq",
+ "pcie_pereset",
+ "pcie_wake";
+ };
+ };
+
+ pwm_pins: pwm-pins {
+ mux {
+ function = "pwm";
+ groups = "pwm_0";
+ };
+ };
+
+ /* SPI-NOR is shared pin with serial NAND */
+ qspi_pins: qspi-pins {
+ mux {
+ function = "flash";
+ groups = "spi_nor";
+ };
+ };
+
+ /* Serial NAND is shared pin with SPI-NOR */
+ serial_nand_pins: serial-nand-pins {
+ mux {
+ function = "flash";
+ groups = "snfi";
+ };
+ };
+
+ spi_pins: spi-pins {
+ mux {
+ function = "spi";
+ groups = "spi_0";
+ };
+ };
+
+ uart0_pins: uart0-pins {
+ mux {
+ function = "uart";
+ groups = "uart0_txd_rxd" ;
+ };
+ };
+
+ uart1_pins: uart1-pins {
+ mux {
+ function = "uart";
+ groups = "uart1_0_tx_rx" ;
+ };
+ };
+
+ uart2_pins: uart2-pins {
+ mux {
+ function = "uart";
+ groups = "uart2_0_txd_rxd" ;
+ };
+ };
+
+ watchdog_pins: watchdog-pins {
+ mux {
+ function = "watchdog";
+ groups = "watchdog";
+ };
+ };
+};
+
+&spi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_pins>;
+ status = "okay";
+};
+
+&ssusb {
+ vusb33-supply = <&reg_3p3v>;
+ vbus-supply = <&reg_5v>;
+ status = "okay";
+};
+
+&u3phy0 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+ status = "okay";
+};
+
+&watchdog {
+ pinctrl-names = "default";
+ pinctrl-0 = <&watchdog_pins>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mt7629.dtsi
new file mode 100644
index 000000000000..9608bc2ccb3f
--- /dev/null
+++ b/arch/arm/boot/dts/mt7629.dtsi
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ *
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mt7629-clk.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/reset/mt7629-resets.h>
+
+/ {
+ compatible = "mediatek,mt7629";
+ interrupt-parent = <&sysirq>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "mediatek,mt6589-smp";
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ clock-frequency = <1250000000>;
+ cci-control-port = <&cci_control2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x1>;
+ clock-frequency = <1250000000>;
+ cci-control-port = <&cci_control2>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
+ clk20m: oscillator-0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "clk20m";
+ };
+
+ clk40m: oscillator-1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <40000000>;
+ clock-output-names = "clkxtal";
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ 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 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ clock-frequency = <20000000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ infracfg: syscon@10000000 {
+ compatible = "mediatek,mt7629-infracfg", "syscon";
+ reg = <0x10000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ pericfg: syscon@10002000 {
+ compatible = "mediatek,mt7629-pericfg", "syscon";
+ reg = <0x10002000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ scpsys: scpsys@10006000 {
+ compatible = "mediatek,mt7629-scpsys",
+ "mediatek,mt7622-scpsys";
+ #power-domain-cells = <1>;
+ reg = <0x10006000 0x1000>;
+ clocks = <&topckgen CLK_TOP_HIF_SEL>;
+ clock-names = "hif_sel";
+ assigned-clocks = <&topckgen CLK_TOP_HIF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>;
+ infracfg = <&infracfg>;
+ };
+
+ timer: timer@10009000 {
+ compatible = "mediatek,mt7629-timer",
+ "mediatek,mt6765-timer";
+ reg = <0x10009000 0x60>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk20m>;
+ clock-names = "clk20m";
+ };
+
+ sysirq: interrupt-controller@10200a80 {
+ compatible = "mediatek,mt7629-sysirq",
+ "mediatek,mt6577-sysirq";
+ reg = <0x10200a80 0x20>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ };
+
+ apmixedsys: syscon@10209000 {
+ compatible = "mediatek,mt7629-apmixedsys", "syscon";
+ reg = <0x10209000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ rng: rng@1020f000 {
+ compatible = "mediatek,mt7629-rng",
+ "mediatek,mt7623-rng";
+ reg = <0x1020f000 0x100>;
+ clocks = <&infracfg CLK_INFRA_TRNG_PD>;
+ clock-names = "rng";
+ };
+
+ topckgen: syscon@10210000 {
+ compatible = "mediatek,mt7629-topckgen", "syscon";
+ reg = <0x10210000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ watchdog: watchdog@10212000 {
+ compatible = "mediatek,mt7629-wdt",
+ "mediatek,mt6589-wdt";
+ reg = <0x10212000 0x100>;
+ };
+
+ pio: pinctrl@10217000 {
+ compatible = "mediatek,mt7629-pinctrl";
+ reg = <0x10217000 0x8000>,
+ <0x10005000 0x1000>;
+ reg-names = "base", "eint";
+ gpio-controller;
+ gpio-ranges = <&pio 0 0 79>;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,gic-400";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0x10310000 0x1000>,
+ <0x10320000 0x1000>,
+ <0x10340000 0x2000>,
+ <0x10360000 0x2000>;
+ };
+
+ cci: cci@10390000 {
+ compatible = "arm,cci-400";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x10390000 0x1000>;
+ ranges = <0 0x10390000 0x10000>;
+
+ cci_control0: slave-if@1000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace-lite";
+ reg = <0x1000 0x1000>;
+ };
+
+ cci_control1: slave-if@4000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x4000 0x1000>;
+ };
+
+ cci_control2: slave-if@5000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x5000 0x1000>;
+ };
+
+ pmu@9000 {
+ compatible = "arm,cci-400-pmu,r1";
+ reg = <0x9000 0x5000>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt7629-uart",
+ "mediatek,mt6577-uart";
+ reg = <0x11002000 0x400>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&pericfg CLK_PERI_UART0_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart1: serial@11003000 {
+ compatible = "mediatek,mt7629-uart",
+ "mediatek,mt6577-uart";
+ reg = <0x11003000 0x400>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&pericfg CLK_PERI_UART1_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart2: serial@11004000 {
+ compatible = "mediatek,mt7629-uart",
+ "mediatek,mt6577-uart";
+ reg = <0x11004000 0x400>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&pericfg CLK_PERI_UART2_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ i2c: i2c@11007000 {
+ compatible = "mediatek,mt7629-i2c",
+ "mediatek,mt2712-i2c";
+ reg = <0x11007000 0x90>,
+ <0x11000100 0x80>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>;
+ clock-div = <4>;
+ clocks = <&pericfg CLK_PERI_I2C0_PD>,
+ <&pericfg CLK_PERI_AP_DMA_PD>;
+ clock-names = "main", "dma";
+ assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi: spi@1100a000 {
+ compatible = "mediatek,mt7629-spi",
+ "mediatek,mt7622-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1100a000 0x100>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+ <&topckgen CLK_TOP_SPI0_SEL>,
+ <&pericfg CLK_PERI_SPI0_PD>;
+ clock-names = "parent-clk", "sel-clk", "spi-clk";
+ status = "disabled";
+ };
+
+ qspi: spi@11014000 {
+ compatible = "mediatek,mt7629-nor",
+ "mediatek,mt8173-nor";
+ reg = <0x11014000 0xe0>;
+ clocks = <&pericfg CLK_PERI_FLASH_PD>,
+ <&topckgen CLK_TOP_FLASH_SEL>;
+ clock-names = "spi", "sf";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ ssusbsys: syscon@1a000000 {
+ compatible = "mediatek,mt7629-ssusbsys", "syscon";
+ reg = <0x1a000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ ssusb: usb@1a0c0000 {
+ compatible = "mediatek,mt7629-xhci",
+ "mediatek,mtk-xhci";
+ reg = <0x1a0c0000 0x01000>,
+ <0x1a0c3e00 0x0100>;
+ reg-names = "mac", "ippc";
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&ssusbsys CLK_SSUSB_SYS_EN>,
+ <&ssusbsys CLK_SSUSB_REF_EN>,
+ <&ssusbsys CLK_SSUSB_MCU_EN>,
+ <&ssusbsys CLK_SSUSB_DMA_EN>;
+ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
+ assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>,
+ <&topckgen CLK_TOP_SATA_SEL>,
+ <&topckgen CLK_TOP_HIF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>,
+ <&topckgen CLK_TOP_UNIVPLL2_D4>,
+ <&topckgen CLK_TOP_UNIVPLL1_D2>;
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>;
+ phys = <&u2port0 PHY_TYPE_USB2>,
+ <&u3port0 PHY_TYPE_USB3>;
+ status = "disabled";
+ };
+
+ u3phy0: usb-phy@1a0c4000 {
+ compatible = "mediatek,generic-tphy-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1a0c4000 0xe00>;
+ status = "disabled";
+
+ u2port0: usb-phy@0 {
+ reg = <0 0x700>;
+ clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+
+ u3port0: usb-phy@700 {
+ reg = <0x700 0x700>;
+ clocks = <&clk20m>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+ };
+
+ pciesys: syscon@1a100800 {
+ compatible = "mediatek,mt7629-pciesys", "syscon";
+ reg = <0x1a100800 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pcie: pcie@1a140000 {
+ compatible = "mediatek,mt7629-pcie";
+ device_type = "pci";
+ reg = <0x1a140000 0x1000>,
+ <0x1a145000 0x1000>;
+ reg-names = "subsys","port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P1_OBFF_EN>,
+ <&pciesys CLK_PCIE_P1_PIPE_EN>;
+ clock-names = "sys_ck1", "ahb_ck1",
+ "aux_ck1", "axi_ck1",
+ "obff_ck1", "pipe_ck1";
+ assigned-clocks = <&topckgen CLK_TOP_SATA_SEL>,
+ <&topckgen CLK_TOP_AXI_SEL>,
+ <&topckgen CLK_TOP_HIF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL2_D4>,
+ <&topckgen CLK_TOP_SYSPLL1_D2>,
+ <&topckgen CLK_TOP_UNIVPLL1_D2>;
+ phys = <&pcieport1 PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy1";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>;
+
+ pcie1: pcie@1,0 {
+ device_type = "pci";
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ pciephy1: pcie-phy@1a14a000 {
+ compatible = "mediatek,generic-tphy-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1a14a000 0x1000>;
+ status = "disabled";
+
+ pcieport1: port1phy@0 {
+ reg = <0 0x1000>;
+ clocks = <&clk20m>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+ };
+
+ ethsys: syscon@1b000000 {
+ compatible = "mediatek,mt7629-ethsys", "syscon";
+ reg = <0x1b000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ eth: ethernet@1b100000 {
+ compatible = "mediatek,mt7629-eth","syscon";
+ reg = <0x1b100000 0x20000>;
+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 225 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_ETH_SEL>,
+ <&topckgen CLK_TOP_F10M_REF_SEL>,
+ <&ethsys CLK_ETH_ESW_EN>,
+ <&ethsys CLK_ETH_GP0_EN>,
+ <&ethsys CLK_ETH_GP1_EN>,
+ <&ethsys CLK_ETH_GP2_EN>,
+ <&ethsys CLK_ETH_FE_EN>,
+ <&sgmiisys0 CLK_SGMII_TX_EN>,
+ <&sgmiisys0 CLK_SGMII_RX_EN>,
+ <&sgmiisys0 CLK_SGMII_CDR_REF>,
+ <&sgmiisys0 CLK_SGMII_CDR_FB>,
+ <&sgmiisys1 CLK_SGMII_TX_EN>,
+ <&sgmiisys1 CLK_SGMII_RX_EN>,
+ <&sgmiisys1 CLK_SGMII_CDR_REF>,
+ <&sgmiisys1 CLK_SGMII_CDR_FB>,
+ <&apmixedsys CLK_APMIXED_SGMIPLL>,
+ <&apmixedsys CLK_APMIXED_ETH2PLL>;
+ clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1",
+ "gp2", "fe", "sgmii_tx250m", "sgmii_rx250m",
+ "sgmii_cdr_ref", "sgmii_cdr_fb",
+ "sgmii2_tx250m", "sgmii2_rx250m",
+ "sgmii2_cdr_ref", "sgmii2_cdr_fb",
+ "sgmii_ck", "eth2pll";
+ assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>,
+ <&topckgen CLK_TOP_F10M_REF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>,
+ <&topckgen CLK_TOP_SGMIIPLL_D2>;
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+ mediatek,ethsys = <&ethsys>;
+ mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
+ mediatek,infracfg = <&infracfg>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ sgmiisys0: syscon@1b128000 {
+ compatible = "mediatek,mt7629-sgmiisys", "syscon";
+ reg = <0x1b128000 0x3000>;
+ #clock-cells = <1>;
+ mediatek,physpeed = "2500";
+ };
+
+ sgmiisys1: syscon@1b130000 {
+ compatible = "mediatek,mt7629-sgmiisys", "syscon";
+ reg = <0x1b130000 0x3000>;
+ #clock-cells = <1>;
+ mediatek,physpeed = "2500";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/nspire-classic.dtsi b/arch/arm/boot/dts/nspire-classic.dtsi
index c53f42777851..41744cc2bc72 100644
--- a/arch/arm/boot/dts/nspire-classic.dtsi
+++ b/arch/arm/boot/dts/nspire-classic.dtsi
@@ -8,7 +8,11 @@
/include/ "nspire.dtsi"
&lcd {
- lcd-type = "classic";
+ port {
+ clcd_pads: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
};
&fast_timer {
@@ -69,6 +73,15 @@
#interrupt-cells = <1>;
};
};
+
+ panel {
+ compatible = "ti,nspire-classic-lcd-panel";
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&clcd_pads>;
+ };
+ };
+ };
chosen {
bootargs = "debug earlyprintk console=tty0 console=ttyS0,115200n8 root=/dev/ram0";
};
diff --git a/arch/arm/boot/dts/nspire-cx.dts b/arch/arm/boot/dts/nspire-cx.dts
index da95c3736651..0c16b04e2744 100644
--- a/arch/arm/boot/dts/nspire-cx.dts
+++ b/arch/arm/boot/dts/nspire-cx.dts
@@ -9,7 +9,11 @@
/include/ "nspire.dtsi"
&lcd {
- lcd-type = "cx";
+ port {
+ clcd_pads: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
};
&fast_timer {
@@ -106,6 +110,15 @@
};
};
};
+
+ panel {
+ compatible = "ti,nspire-cx-lcd-panel";
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&clcd_pads>;
+ };
+ };
+ };
chosen {
bootargs = "debug earlyprintk console=tty0 console=ttyAMA0,115200n8 root=/dev/ram0";
};
diff --git a/arch/arm/boot/dts/nspire.dtsi b/arch/arm/boot/dts/nspire.dtsi
index c35fd6667716..d9a0fd7524dc 100644
--- a/arch/arm/boot/dts/nspire.dtsi
+++ b/arch/arm/boot/dts/nspire.dtsi
@@ -95,8 +95,14 @@
reg = <0xC0000000 0x1000>;
interrupts = <21>;
- clocks = <&apb_pclk>;
- clock-names = "apb_pclk";
+ /*
+ * We assume the same clock is fed to APB and CLCDCLK.
+ * There is some code to scale the clock down by a factor
+ * 48 for the display so likely the frequency to the
+ * display is 1MHz and the CLCDCLK is 48 MHz.
+ */
+ clocks = <&apb_pclk>, <&apb_pclk>;
+ clock-names = "clcdclk", "apb_pclk";
};
adc: adc@C4000000 {
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index b295f6fad2a5..d01fc8744fd7 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -24,6 +24,10 @@
reg = <0x80000000 0x20000000>; /* 512 MB */
};
+ chosen {
+ stdout-path = &uart3;
+ };
+
aliases {
display0 = &lcd;
display1 = &tv0;
diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi
index 5441e9ffdbb4..6681d4519e97 100644
--- a/arch/arm/boot/dts/omap3-n950-n9.dtsi
+++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi
@@ -41,7 +41,6 @@
regulator-name = "VWLAN";
gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>; /* gpio 35 */
enable-active-high;
- regulator-boot-off;
};
leds {
diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi
index 56cb10b42ed9..51806c7f486a 100644
--- a/arch/arm/boot/dts/r8a77470.dtsi
+++ b/arch/arm/boot/dts/r8a77470.dtsi
@@ -63,6 +63,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts-extended = <&gic GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index 3ff259207527..ebf5b7cfe215 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -296,7 +296,7 @@
<&cpg_clocks R8A7779_CLK_S>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- power-domains = <&cpg_clocks>;
+ power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
status = "disabled";
};
@@ -309,7 +309,7 @@
<&cpg_clocks R8A7779_CLK_S>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- power-domains = <&cpg_clocks>;
+ power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index 0290ea4edd32..c776321b2cc4 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -484,7 +484,7 @@
compatible = "rockchip,rockchip-spi";
reg = <0x20074000 0x1000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
+ clocks = <&cru PCLK_SPI>, <&cru SCLK_SPI>;
clock-names = "apb-pclk","spi_pclk";
dmas = <&pdma 8>, <&pdma 9>;
dma-names = "tx", "rx";
diff --git a/arch/arm/boot/dts/rk3229-xms6.dts b/arch/arm/boot/dts/rk3229-xms6.dts
new file mode 100644
index 000000000000..679fc2b00e5a
--- /dev/null
+++ b/arch/arm/boot/dts/rk3229-xms6.dts
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "rk3229.dtsi"
+
+/ {
+ model = "Mecer Xtreme Mini S6";
+ compatible = "mecer,xms6", "rockchip,rk3229";
+
+ memory@60000000 {
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+
+ dc_12v: dc-12v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ ext_gmac: ext_gmac {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "ext_gmac";
+ #clock-cells = <0>;
+ };
+
+ power-led {
+ compatible = "gpio-leds";
+
+ blue {
+ gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ vcc_host: vcc-host-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&host_vbus_drv>;
+ regulator-name = "vcc_host";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_phy: vcc-phy-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ regulator-name = "vcc_phy";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vccio_1v8>;
+ };
+
+ vcc_sys: vcc-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vccio_1v8: vccio-1v8-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vccio_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vccio_3v3: vccio-3v3-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vccio_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vdd_arm: vdd-arm-regulator {
+ compatible = "pwm-regulator";
+ pwms = <&pwm1 0 25000 1>;
+ pwm-supply = <&vcc_sys>;
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_log: vdd-log-regulator {
+ compatible = "pwm-regulator";
+ pwms = <&pwm2 0 25000 1>;
+ pwm-supply = <&vcc_sys>;
+ regulator-name = "vdd_log";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ cap-mmc-highspeed;
+ disable-wp;
+ non-removable;
+ status = "okay";
+};
+
+&gmac {
+ assigned-clocks = <&cru SCLK_MAC_SRC>;
+ assigned-clock-rates = <50000000>;
+ clock_in_out = "output";
+ phy-handle = <&phy>;
+ phy-mode = "rmii";
+ phy-supply = <&vcc_phy>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy: phy@0 {
+ compatible = "ethernet-phy-id1234.d400",
+ "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ clocks = <&cru SCLK_MAC_PHY>;
+ phy-is-integrated;
+ resets = <&cru SRST_MACPHY>;
+ };
+ };
+};
+
+&gpu {
+ mali-supply = <&vdd_log>;
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_phy {
+ status = "okay";
+};
+
+&iep_mmu {
+ status = "okay";
+};
+
+&io_domains {
+ status = "okay";
+
+ vccio1-supply = <&vccio_3v3>;
+ vccio2-supply = <&vccio_1v8>;
+ vccio4-supply = <&vccio_3v3>;
+};
+
+&pinctrl {
+ usb {
+ host_vbus_drv: host-vbus-drv {
+ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&sdmmc {
+ cap-mmc-highspeed;
+ disable-wp;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <0>;
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+
+ u2phy0_host: host-port {
+ phy-supply = <&vcc_host>;
+ status = "okay";
+ };
+
+ u2phy0_otg: otg-port {
+ phy-supply = <&vcc_host>;
+ status = "okay";
+ };
+};
+
+&u2phy1 {
+ status = "okay";
+
+ u2phy1_host: host-port {
+ phy-supply = <&vcc_host>;
+ status = "okay";
+ };
+
+ u2phy1_otg: otg-port {
+ phy-supply = <&vcc_host>;
+ status = "okay";
+ };
+};
+
+&uart2 {
+ pinctrl-0 = <&uart21_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host2_ehci {
+ status = "okay";
+};
+
+&usb_host2_ohci {
+ status = "okay";
+};
+
+&usb_otg {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
index 820440715302..2afd686b2033 100644
--- a/arch/arm/boot/dts/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -97,7 +97,7 @@
};
panel: panel {
- compatible ="lg,lp079qx1-sp0v", "simple-panel";
+ compatible = "lg,lp079qx1-sp0v", "simple-panel";
backlight = <&backlight>;
enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&lcd_cs>;
diff --git a/arch/arm/boot/dts/rk3288-fennec.dts b/arch/arm/boot/dts/rk3288-fennec.dts
deleted file mode 100644
index 4847cf902a15..000000000000
--- a/arch/arm/boot/dts/rk3288-fennec.dts
+++ /dev/null
@@ -1,347 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-
-/dts-v1/;
-
-#include "rk3288.dtsi"
-
-/ {
- model = "Rockchip RK3288 Fennec Board";
- compatible = "rockchip,rk3288-fennec", "rockchip,rk3288";
-
- memory@0 {
- reg = <0x0 0x0 0x0 0x80000000>;
- device_type = "memory";
- };
-
- ext_gmac: external-gmac-clock {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <125000000>;
- clock-output-names = "ext_gmac";
- };
-
- vcc_sys: vsys-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc_sys";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- regulator-boot-on;
- };
-};
-
-&cpu0 {
- cpu0-supply = <&vdd_cpu>;
-};
-
-&emmc {
- bus-width = <8>;
- cap-mmc-highspeed;
- non-removable;
- pinctrl-names = "default";
- pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
- status = "okay";
-};
-
-&gmac {
- assigned-clocks = <&cru SCLK_MAC>;
- assigned-clock-parents = <&ext_gmac>;
- clock_in_out = "input";
- pinctrl-names = "default";
- pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>;
- phy-supply = <&vcc_lan>;
- phy-mode = "rgmii";
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 1000000>;
- snps,reset-gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_LOW>;
- tx_delay = <0x30>;
- rx_delay = <0x10>;
- status = "okay";
-};
-
-&gpu {
- mali-supply = <&vdd_gpu>;
- status = "okay";
-};
-
-&hdmi {
- status = "okay";
-};
-
-&i2c0 {
- status = "okay";
- clock-frequency = <400000>;
-
- rk808: pmic@1b {
- compatible = "rockchip,rk808";
- reg = <0x1b>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PA4 IRQ_TYPE_LEVEL_LOW>;
- #clock-cells = <1>;
- clock-output-names = "xin32k", "rk808-clkout2";
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_int &global_pwroff>;
- rockchip,system-power-controller;
- wakeup-source;
-
- vcc1-supply = <&vcc_sys>;
- vcc2-supply = <&vcc_sys>;
- vcc3-supply = <&vcc_sys>;
- vcc4-supply = <&vcc_sys>;
- vcc6-supply = <&vcc_sys>;
- vcc7-supply = <&vcc_sys>;
- vcc8-supply = <&vcc_io>;
- vcc9-supply = <&vcc_io>;
- vcc10-supply = <&vcc_io>;
- vcc11-supply = <&vcc_io>;
- vcc12-supply = <&vcc_io>;
- vddio-supply = <&vcc_io>;
-
- regulators {
- vdd_cpu: DCDC_REG1 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1350000>;
- regulator-name = "vdd_arm";
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_gpu: DCDC_REG2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1250000>;
- regulator-name = "vdd_gpu";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vcc_ddr: DCDC_REG3 {
- regulator-always-on;
- regulator-boot-on;
- regulator-name = "vcc_ddr";
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
-
- vcc_io: DCDC_REG4 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc_io";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vccio_pmu: LDO_REG1 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vccio_pmu";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vcca_33: LDO_REG2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcca_33";
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_10: LDO_REG3 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-name = "vdd_10";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vcc_wl: LDO_REG4 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vcc_wl";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vccio_sd: LDO_REG5 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vccio_sd";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vdd10_lcd: LDO_REG6 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-name = "vdd10_lcd";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vcc_18: LDO_REG7 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vcc_18";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vcc18_lcd: LDO_REG8 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vcc18_lcd";
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vcc_sd: SWITCH_REG1 {
- regulator-always-on;
- regulator-boot-on;
- regulator-name = "vcc_sd";
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
-
- vcc_lan: SWITCH_REG2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-name = "vcc_lan";
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
- };
- };
-};
-
-&pinctrl {
- pcfg_output_high: pcfg-output-high {
- output-high;
- };
-
- pcfg_output_low: pcfg-output-low {
- output-low;
- };
-
- pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
- drive-strength = <8>;
- };
-
- pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
- bias-pull-up;
- drive-strength = <8>;
- };
-
- gmac {
- phy_int: phy-int {
- rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
- };
-
- phy_pmeb: phy-pmeb {
- rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
-
- phy_rst: phy-rst {
- rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
- };
- };
-
- pmic {
- pmic_int: pmic-int {
- rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- usbphy {
- host_drv: host-drv {
- rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-};
-
-&uart2 {
- status = "okay";
-};
-
-&usbphy {
- pinctrl-names = "default";
- pinctrl-0 = <&host_drv>;
- vbus_drv-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
- status = "okay";
-};
-
-&usb_host0_ehci {
- status = "okay";
-};
-
-&usb_host1 {
- status = "okay";
-};
-
-&usb_otg {
- status = "okay";
-};
-
-&usb_hsic {
- status = "okay";
-};
-
-&vopb {
- status = "okay";
-};
-
-&vopb_mmu {
- status = "okay";
-};
-
-&vopl {
- status = "okay";
-};
-
-&vopl_mmu {
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi
index 293576869546..81e4e953d4a4 100644
--- a/arch/arm/boot/dts/rk3288-tinker.dtsi
+++ b/arch/arm/boot/dts/rk3288-tinker.dtsi
@@ -47,13 +47,13 @@
compatible = "gpio-leds";
act-led {
- gpios=<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
- linux,default-trigger="mmc0";
+ gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc0";
};
heartbeat-led {
- gpios=<&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
- linux,default-trigger="heartbeat";
+ gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
};
pwr-led {
@@ -443,7 +443,7 @@
&saradc {
vref-supply = <&vcc18_ldo1>;
- status ="okay";
+ status = "okay";
};
&sdmmc {
@@ -516,7 +516,7 @@
};
&usb_otg {
- status= "okay";
+ status = "okay";
};
&vopb {
diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
index 1cadb522fd0d..ffb60f880b39 100644
--- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/input/input.h>
#include "rk3288-veyron.dtsi"
#include "rk3288-veyron-analog-audio.dtsi"
+#include "rk3288-veyron-edp.dtsi"
#include "rk3288-veyron-sdmmc.dtsi"
/ {
@@ -18,50 +19,6 @@
i2c20 = &i2c_tunnel;
};
- backlight: backlight {
- compatible = "pwm-backlight";
- brightness-levels = <
- 0 1 2 3 4 5 6 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
- 32 33 34 35 36 37 38 39
- 40 41 42 43 44 45 46 47
- 48 49 50 51 52 53 54 55
- 56 57 58 59 60 61 62 63
- 64 65 66 67 68 69 70 71
- 72 73 74 75 76 77 78 79
- 80 81 82 83 84 85 86 87
- 88 89 90 91 92 93 94 95
- 96 97 98 99 100 101 102 103
- 104 105 106 107 108 109 110 111
- 112 113 114 115 116 117 118 119
- 120 121 122 123 124 125 126 127
- 128 129 130 131 132 133 134 135
- 136 137 138 139 140 141 142 143
- 144 145 146 147 148 149 150 151
- 152 153 154 155 156 157 158 159
- 160 161 162 163 164 165 166 167
- 168 169 170 171 172 173 174 175
- 176 177 178 179 180 181 182 183
- 184 185 186 187 188 189 190 191
- 192 193 194 195 196 197 198 199
- 200 201 202 203 204 205 206 207
- 208 209 210 211 212 213 214 215
- 216 217 218 219 220 221 222 223
- 224 225 226 227 228 229 230 231
- 232 233 234 235 236 237 238 239
- 240 241 242 243 244 245 246 247
- 248 249 250 251 252 253 254 255>;
- default-brightness-level = <128>;
- enable-gpios = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&bl_en>;
- pwms = <&pwm0 0 1000000 0>;
- post-pwm-on-delay-ms = <10>;
- pwm-off-delay-ms = <10>;
- };
-
gpio-charger {
compatible = "gpio-charger";
charger-type = "mains";
@@ -85,21 +42,6 @@
};
};
- panel: panel {
- compatible ="innolux,n116bge", "simple-panel";
- status = "okay";
- power-supply = <&vcc33_lcd>;
- backlight = <&backlight>;
-
- ports {
- panel_in: port {
- panel_in_edp: endpoint {
- remote-endpoint = <&edp_out_panel>;
- };
- };
- };
- };
-
/* A non-regulated voltage from power supply or battery */
vccsys: vccsys {
compatible = "regulator-fixed";
@@ -141,33 +83,6 @@
};
};
-&edp {
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&edp_hpd>;
-
- ports {
- edp_out: port@1 {
- reg = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- edp_out_panel: endpoint@0 {
- reg = <0>;
- remote-endpoint = <&panel_in_edp>;
- };
- };
- };
-};
-
-&edp_phy {
- status = "okay";
-};
-
-&pwm0 {
- status = "okay";
-};
-
&rk808 {
vcc11-supply = <&vcc_5v>;
@@ -220,14 +135,6 @@
};
};
-&vopl {
- status = "okay";
-};
-
-&vopl_mmu {
- status = "okay";
-};
-
&pinctrl {
pinctrl-0 = <
/* Common for sleep and wake, but no owners */
@@ -250,12 +157,6 @@
&bt_dev_wake_sleep
>;
- backlight {
- bl_en: bl-en {
- rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
buttons {
ap_lid_int_l: ap-lid-int-l {
rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi
new file mode 100644
index 000000000000..b12e061c5f7f
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Veyron (and derivatives) fragment for the edp displays
+ *
+ * Copyright 2019 Google LLC
+ */
+
+/ {
+ backlight_regulator: backlight-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bl_pwr_en>;
+ regulator-name = "backlight_regulator";
+ vin-supply = <&vcc33_sys>;
+ startup-delay-us = <15000>;
+ };
+
+ panel_regulator: panel-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_enable_h>;
+ regulator-name = "panel_regulator";
+ vin-supply = <&vcc33_sys>;
+ };
+
+ vcc18_lcd: vcc18-lcd {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&avdd_1v8_disp_en>;
+ regulator-name = "vcc18_lcd";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc18_wl>;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ brightness-levels = <
+ 0 1 2 3 4 5 6 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
+ 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47
+ 48 49 50 51 52 53 54 55
+ 56 57 58 59 60 61 62 63
+ 64 65 66 67 68 69 70 71
+ 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87
+ 88 89 90 91 92 93 94 95
+ 96 97 98 99 100 101 102 103
+ 104 105 106 107 108 109 110 111
+ 112 113 114 115 116 117 118 119
+ 120 121 122 123 124 125 126 127
+ 128 129 130 131 132 133 134 135
+ 136 137 138 139 140 141 142 143
+ 144 145 146 147 148 149 150 151
+ 152 153 154 155 156 157 158 159
+ 160 161 162 163 164 165 166 167
+ 168 169 170 171 172 173 174 175
+ 176 177 178 179 180 181 182 183
+ 184 185 186 187 188 189 190 191
+ 192 193 194 195 196 197 198 199
+ 200 201 202 203 204 205 206 207
+ 208 209 210 211 212 213 214 215
+ 216 217 218 219 220 221 222 223
+ 224 225 226 227 228 229 230 231
+ 232 233 234 235 236 237 238 239
+ 240 241 242 243 244 245 246 247
+ 248 249 250 251 252 253 254 255>;
+ default-brightness-level = <128>;
+ enable-gpios = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bl_en>;
+ pwms = <&pwm0 0 1000000 0>;
+ post-pwm-on-delay-ms = <10>;
+ pwm-off-delay-ms = <10>;
+ power-supply = <&backlight_regulator>;
+ };
+
+ panel: panel {
+ compatible = "innolux,n116bge", "simple-panel";
+ status = "okay";
+ power-supply = <&panel_regulator>;
+ backlight = <&backlight>;
+
+ panel-timing {
+ clock-frequency = <74250000>;
+ hactive = <1366>;
+ hfront-porch = <136>;
+ hback-porch = <60>;
+ hsync-len = <30>;
+ hsync-active = <0>;
+ vactive = <768>;
+ vfront-porch = <8>;
+ vback-porch = <12>;
+ vsync-len = <12>;
+ vsync-active = <0>;
+ };
+
+ ports {
+ panel_in: port {
+ panel_in_edp: endpoint {
+ remote-endpoint = <&edp_out_panel>;
+ };
+ };
+ };
+ };
+};
+
+&edp {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&edp_hpd>;
+
+ ports {
+ edp_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ edp_out_panel: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&panel_in_edp>;
+ };
+ };
+ };
+};
+
+&edp_phy {
+ status = "okay";
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&vopl {
+ status = "okay";
+};
+
+&vopl_mmu {
+ status = "okay";
+};
+
+&pinctrl {
+ backlight {
+ bl_pwr_en: bl_pwr_en {
+ rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bl_en: bl-en {
+ rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ lcd {
+ lcd_enable_h: lcd-en {
+ rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ avdd_1v8_disp_en: avdd-1v8-disp-en {
+ rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rk3288-veyron-fievel.dts
new file mode 100644
index 000000000000..9a0f55085839
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-veyron-fievel.dts
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Veyron Fievel Rev 0+ board device tree source
+ *
+ * Copyright 2016 Google, Inc
+ */
+
+/dts-v1/;
+#include "rk3288-veyron.dtsi"
+#include "rk3288-veyron-analog-audio.dtsi"
+
+/ {
+ model = "Google Fievel";
+ compatible = "google,veyron-fievel-rev8", "google,veyron-fievel-rev7",
+ "google,veyron-fievel-rev6", "google,veyron-fievel-rev5",
+ "google,veyron-fievel-rev4", "google,veyron-fievel-rev3",
+ "google,veyron-fievel-rev2", "google,veyron-fievel-rev1",
+ "google,veyron-fievel-rev0", "google,veyron-fievel",
+ "google,veyron", "rockchip,rk3288";
+
+ /delete-node/ bt-activity;
+
+ vccsys: vccsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vccsys";
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /*
+ * vcc33_pmuio and vcc33_io is sourced directly from vcc33_sys,
+ * enabled by vcc_18
+ */
+ vcc33_io: vcc33-io {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vcc33_io";
+ };
+
+ vcc5_host1: vcc5-host1-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio5 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hub_usb1_pwr_en>;
+ regulator-name = "vcc5_host1";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc5_host2: vcc5-host2-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio5 RK_PB6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hub_usb2_pwr_en>;
+ regulator-name = "vcc5_host2";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc5v_otg: vcc5v-otg-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_otg_pwr_en>;
+ regulator-name = "vcc5_otg";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ext_gmac: external-gmac-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <125000000>;
+ clock-output-names = "ext_gmac";
+ };
+};
+
+&gmac {
+ status = "okay";
+
+ assigned-clocks = <&cru SCLK_MAC>;
+ assigned-clock-parents = <&ext_gmac>;
+ clock_in_out = "input";
+ phy-handle = <&ethphy>;
+ phy-mode = "rgmii";
+ phy-supply = <&vcc33_lan>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>;
+ rx_delay = <0x10>;
+ tx_delay = <0x30>;
+
+ /*
+ * Reset for the RTL8211 PHY which requires a 10-ms reset pulse (low)
+ * with a 30ms settling time.
+ */
+ snps,reset-gpio = <&gpio4 RK_PB0 0>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 30000>;
+ wakeup-source;
+
+ mdio0 {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+};
+
+&rk808 {
+ dvs-gpios = <&gpio7 RK_PB4 GPIO_ACTIVE_HIGH>,
+ <&gpio7 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>;
+
+ vcc6-supply = <&vcc33_sys>;
+ vcc10-supply = <&vcc33_sys>;
+ vcc11-supply = <&vcc_5v>;
+ vcc12-supply = <&vcc33_sys>;
+
+ regulators {
+ /delete-node/ LDO_REG1;
+
+ /*
+ * According to the schematic, vcc18_lcdt is for
+ * HDMI_AVDD_1V8
+ */
+ vcc18_lcdt: LDO_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vdd18_lcdt";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /*
+ * This is not a pwren anymore, but the real power supply,
+ * vdd10_lcd for HDMI_AVDD_1V0
+ */
+ vdd10_lcd: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-name = "vdd10_lcd";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* for usb camera */
+ vcc33_ccd: LDO_REG8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc33_ccd";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc33_lan: SWITCH_REG2 {
+ regulator-name = "vcc33_lan";
+ };
+ };
+};
+
+&sdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ btmrvl: btmrvl@2 {
+ compatible = "marvell,sd8897-bt";
+ reg = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <RK_PD7 IRQ_TYPE_LEVEL_LOW>;
+ marvell,wakeup-pin = /bits/ 16 <13>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_l>;
+ };
+};
+
+&vcc50_hdmi {
+ enable-active-high;
+ gpio = <&gpio5 RK_PC3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc50_hdmi_en>;
+};
+
+&vcc_5v {
+ enable-active-high;
+ gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&drv_5v>;
+};
+
+&gpio0 {
+ gpio-line-names = "PMIC_SLEEP_AP",
+ "DDRIO_PWROFF",
+ "DDRIO_RETEN",
+ "TS3A227E_INT_L",
+ "PMIC_INT_L",
+ "PWR_KEY_L",
+ "HUB_USB1_nFALUT",
+ "PHY_PMEB",
+
+ "PHY_INT",
+ "REC_MODE_L",
+ "OTP_OUT",
+ "",
+ "USB_OTG_POWER_EN",
+ "AP_WARM_RESET_H",
+ "USB_OTG_nFALUT",
+ "I2C0_SDA_PMIC",
+
+ "I2C0_SCL_PMIC",
+ "DEVMODE_L",
+ "USB_INT";
+};
+
+&gpio2 {
+ gpio-line-names = "CONFIG0",
+ "CONFIG1",
+ "CONFIG2",
+ "",
+ "",
+ "",
+ "",
+ "CONFIG3",
+
+ "",
+ "EMMC_RST_L",
+ "",
+ "",
+ "BL_PWR_EN",
+ "",
+ "TOUCH_INT",
+ "TOUCH_RST",
+
+ "I2C3_SCL_TP",
+ "I2C3_SDA_TP";
+};
+
+&gpio3 {
+ gpio-line-names = "FLASH0_D0",
+ "FLASH0_D1",
+ "FLASH0_D2",
+ "FLASH0_D3",
+ "FLASH0_D4",
+ "FLASH0_D5",
+ "FLASH0_D6",
+ "FLASH0_D7",
+
+ "VCC5V_GOOD_H",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+
+ "FLASH0_CS2/EMMC_CMD",
+ "",
+ "FLASH0_DQS/EMMC_CLKO",
+ "",
+ "",
+ "",
+ "",
+ "",
+
+ "PHY_TXD2",
+ "PHY_TXD3",
+ "MAC_RXD2",
+ "MAC_RXD3",
+ "PHY_TXD0",
+ "PHY_TXD1",
+ "MAC_RXD0",
+ "MAC_RXD1";
+};
+
+&gpio4 {
+ gpio-line-names = "MAC_MDC",
+ "MAC_RXDV",
+ "MAC_RXER",
+ "MAC_CLK",
+ "PHY_TXEN",
+ "MAC_MDIO",
+ "MAC_RXCLK",
+ "",
+
+ "PHY_RST",
+ "PHY_TXCLK",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+
+ "UART0_RXD",
+ "UART0_TXD",
+ "UART0_CTS_L",
+ "UART0_RTS_L",
+ "SDIO0_D0",
+ "SDIO0_D1",
+ "SDIO0_D2",
+ "SDIO0_D3",
+
+ "SDIO0_CMD",
+ "SDIO0_CLK",
+ "BT_DEV_WAKE",
+ "",
+ "WIFI_ENABLE_H",
+ "BT_ENABLE_L",
+ "WIFI_HOST_WAKE",
+ "BT_HOST_WAKE";
+};
+
+&gpio5 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+
+ "",
+ "",
+ "",
+ "",
+ "USB_OTG_CTL1",
+ "HUB_USB2_CTL1",
+ "HUB_USB2_PWR_EN",
+ "HUB_USB_ILIM_SEL",
+
+ "USB_OTG_STATUS_L",
+ "HUB_USB1_CTL1",
+ "HUB_USB1_PWR_EN",
+ "VCC50_HDMI_EN";
+};
+
+&gpio6 {
+ gpio-line-names = "I2S0_SCLK",
+ "I2S0_LRCK_RX",
+ "I2S0_LRCK_TX",
+ "I2S0_SDI",
+ "I2S0_SDO0",
+ "HP_DET_H",
+ "",
+ "INT_CODEC",
+
+ "I2S0_CLK",
+ "I2C2_SDA",
+ "I2C2_SCL",
+ "MICDET",
+ "",
+ "",
+ "",
+ "",
+
+ "HUB_USB2_nFALUT",
+ "USB_OTG_ILIM_SEL";
+};
+
+&gpio7 {
+ gpio-line-names = "LCD_BL_PWM",
+ "PWM_LOG",
+ "BL_EN",
+ "PWR_LED1",
+ "TPM_INT_H",
+ "SPK_ON",
+ "FW_WP_AP",
+ "",
+
+ "CPU_NMI",
+ "DVSOK",
+ "",
+ "EDP_HPD",
+ "DVS1",
+ "",
+ "LCD_EN",
+ "DVS2",
+
+ "HDMI_CEC",
+ "I2C4_SDA",
+ "I2C4_SCL",
+ "I2C5_SDA_HDMI",
+ "I2C5_SCL_HDMI",
+ "5V_DRV",
+ "UART2_RXD",
+ "UART2_TXD";
+};
+
+&gpio8 {
+ gpio-line-names = "RAM_ID0",
+ "RAM_ID1",
+ "RAM_ID2",
+ "RAM_ID3",
+ "I2C1_SDA_TPM",
+ "I2C1_SCL_TPM",
+ "SPI2_CLK",
+ "SPI2_CS0",
+
+ "SPI2_RXD",
+ "SPI2_TXD";
+};
+
+&pinctrl {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <
+ /* Common for sleep and wake, but no owners */
+ &ddr0_retention
+ &ddrio_pwroff
+ &global_pwroff
+
+ /* For usb bc1.2 */
+ &usb_otg_ilim_sel
+ &usb_usb_ilim_sel
+
+ /* Wake only */
+ &bt_dev_wake_awake
+ &pwr_led1_on
+ >;
+
+ pinctrl-1 = <
+ /* Common for sleep and wake, but no owners */
+ &ddr0_retention
+ &ddrio_pwroff
+ &global_pwroff
+
+ /* For usb bc1.2 */
+ &usb_otg_ilim_sel
+ &usb_usb_ilim_sel
+
+ /* Sleep only */
+ &bt_dev_wake_sleep
+ &pwr_led1_blink
+ >;
+
+ buck-5v {
+ drv_5v: drv-5v {
+ rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ gmac {
+ phy_rst: phy-rst {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
+ };
+
+ phy_pmeb: phy-pmeb {
+ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ phy_int: phy-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ hdmi {
+ vcc50_hdmi_en: vcc50-hdmi-en {
+ rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ pwr_led1_on: pwr-led1-on {
+ rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+
+ pwr_led1_blink: pwr-led1-blink {
+ rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_output_high>;
+ };
+ };
+
+ pmic {
+ dvs_1: dvs-1 {
+ rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ dvs_2: dvs-2 {
+ rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ usb-bc12 {
+ usb_otg_ilim_sel: usb-otg-ilim-sel {
+ rockchip,pins = <6 RK_PC1 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+
+ usb_usb_ilim_sel: usb-usb-ilim-sel {
+ rockchip,pins = <5 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+ };
+
+ usb-host {
+ hub_usb1_pwr_en: hub_usb1_pwr_en {
+ rockchip,pins = <5 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ hub_usb2_pwr_en: hub_usb2_pwr_en {
+ rockchip,pins = <5 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_otg_pwr_en: usb_otg_pwr_en {
+ rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts
index fcd119168cb6..80386203e85b 100644
--- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts
@@ -16,40 +16,6 @@
"google,veyron-jaq-rev3", "google,veyron-jaq-rev2",
"google,veyron-jaq-rev1", "google,veyron-jaq",
"google,veyron", "rockchip,rk3288";
-
- panel_regulator: panel-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_enable_h>;
- regulator-name = "panel_regulator";
- startup-delay-us = <100000>;
- vin-supply = <&vcc33_sys>;
- };
-
- vcc18_lcd: vcc18-lcd {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&avdd_1v8_disp_en>;
- regulator-name = "vcc18_lcd";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc18_wl>;
- };
-
- backlight_regulator: backlight-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&bl_pwr_en>;
- regulator-name = "backlight_regulator";
- vin-supply = <&vcc33_sys>;
- startup-delay-us = <15000>;
- };
};
&backlight {
@@ -87,11 +53,6 @@
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255>;
- power-supply = <&backlight_regulator>;
-};
-
-&panel {
- power-supply = <&panel_regulator>;
};
&rk808 {
@@ -343,12 +304,6 @@
};
&pinctrl {
- backlight {
- bl_pwr_en: bl_pwr_en {
- rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
buck-5v {
drv_5v: drv-5v {
rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -361,16 +316,6 @@
};
};
- lcd {
- lcd_enable_h: lcd-en {
- rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- avdd_1v8_disp_en: avdd-1v8-disp-en {
- rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
pmic {
dvs_1: dvs-1 {
rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts
index 164561f04c1d..a6ee44f0fe13 100644
--- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts
@@ -18,48 +18,6 @@
"google,veyron-jerry-rev5", "google,veyron-jerry-rev4",
"google,veyron-jerry-rev3", "google,veyron-jerry",
"google,veyron", "rockchip,rk3288";
-
- panel_regulator: panel-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_enable_h>;
- regulator-name = "panel_regulator";
- startup-delay-us = <100000>;
- vin-supply = <&vcc33_sys>;
- };
-
- vcc18_lcd: vcc18-lcd {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&avdd_1v8_disp_en>;
- regulator-name = "vcc18_lcd";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc18_wl>;
- };
-
- backlight_regulator: backlight-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&bl_pwr_en>;
- regulator-name = "backlight_regulator";
- vin-supply = <&vcc33_sys>;
- startup-delay-us = <15000>;
- };
-};
-
-&backlight {
- power-supply = <&backlight_regulator>;
-};
-
-&panel {
- power-supply= <&panel_regulator>;
};
&rk808 {
@@ -82,6 +40,155 @@
};
};
+&sdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mwifiex: wifi@1 {
+ compatible = "marvell,sd8897";
+ reg = <1>;
+
+ marvell,caldata-txpwrlimit-2g = /bits/ 8 <
+0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x01 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x02 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x03 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x04 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x05 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x06 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x07 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x08 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x09 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x0a 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x0b 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x0c 0x00 0x0f
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01
+0x24 0x00 0x67 0x09 0x14 0x0d 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c
+0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c
+0x0d 0x09 0x0e 0x09 0x0f 0x09>;
+
+ marvell,caldata-txpwrlimit-5g-sub0 = /bits/ 8 <
+0x01 0x00 0x06 0x00 0xf0 0x01 0x89 0x01
+0x3a 0x00 0x88 0x13 0x14 0x24 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a
+0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09
+0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05
+0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00
+0x88 0x13 0x14 0x28 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a
+0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09
+0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05
+0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13
+0x14 0x2c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09
+0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09
+0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05
+0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x30
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05
+0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05
+0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x34 0x01 0x0c
+0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09
+0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05
+0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05
+0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x38 0x01 0x0c 0x02 0x0c
+0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a
+0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05
+0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05
+0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x3c 0x01 0x0c 0x02 0x0c 0x03 0x0c
+0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a
+0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05
+0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05
+0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x40 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a
+0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05
+0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05>;
+
+ marvell,caldata-txpwrlimit-5g-sub1 = /bits/ 8 <
+0x01 0x00 0x06 0x00 0xaa 0x02 0x89 0x01
+0x3a 0x00 0x88 0x13 0x14 0x64 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a
+0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09
+0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05
+0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00
+0x88 0x13 0x14 0x68 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a
+0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09
+0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05
+0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13
+0x14 0x6c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09
+0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09
+0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05
+0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x70
+0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09
+0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05
+0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05
+0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x74 0x01 0x0c
+0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09
+0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05
+0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05
+0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x78 0x01 0x0c 0x02 0x0c
+0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a
+0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05
+0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05
+0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x7c 0x01 0x0c 0x02 0x0c 0x03 0x0c
+0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a
+0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05
+0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05
+0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x80 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a
+0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a
+0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05
+0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01
+0x3a 0x00 0x88 0x13 0x14 0x84 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a
+0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09
+0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05
+0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00
+0x88 0x13 0x14 0x88 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a
+0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08
+0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04
+0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13
+0x14 0x8c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08
+0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08
+0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04
+0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05>;
+
+ marvell,caldata-txpwrlimit-5g-sub2 = /bits/ 8 <
+0x01 0x00 0x06 0x00 0x36 0x01 0x89 0x01
+0x3a 0x00 0x88 0x13 0x14 0x95 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a
+0x06 0x0a 0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08
+0x0e 0x08 0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05
+0x16 0x04 0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00
+0x88 0x13 0x14 0x99 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a
+0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08
+0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04
+0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13
+0x14 0x9d 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08
+0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08
+0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04
+0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0xa1
+0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 0x08 0x08
+0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 0x10 0x04
+0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 0x18 0x05
+0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0xa5 0x01 0x0b
+0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 0x08 0x08 0x09 0x08
+0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 0x10 0x04 0x11 0x04
+0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 0x18 0x05 0x19 0x05
+0x1a 0x05 0x1b 0x05>;
+ };
+};
+
&sdmmc {
disable-wp;
pinctrl-names = "default";
@@ -311,12 +418,6 @@
};
&pinctrl {
- backlight {
- bl_pwr_en: bl_pwr_en {
- rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
buck-5v {
drv_5v: drv-5v {
rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -329,16 +430,6 @@
};
};
- lcd {
- lcd_enable_h: lcd-en {
- rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- avdd_1v8_disp_en: avdd-1v8-disp-en {
- rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
pmic {
dvs_1: dvs-1 {
rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts
index 9008e703c07e..55955b082501 100644
--- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts
@@ -15,40 +15,6 @@
"google,veyron-minnie-rev0", "google,veyron-minnie",
"google,veyron", "rockchip,rk3288";
- backlight_regulator: backlight-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&bl_pwr_en>;
- regulator-name = "backlight_regulator";
- vin-supply = <&vcc33_sys>;
- startup-delay-us = <15000>;
- };
-
- panel_regulator: panel-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_enable_h>;
- regulator-name = "panel_regulator";
- startup-delay-us = <100000>;
- vin-supply = <&vcc33_sys>;
- };
-
- vcc18_lcd: vcc18-lcd {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&avdd_1v8_disp_en>;
- regulator-name = "vcc18_lcd";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc18_wl>;
- };
-
volume_buttons: volume-buttons {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -105,7 +71,6 @@
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255>;
- power-supply = <&backlight_regulator>;
};
&i2c_tunnel {
@@ -137,7 +102,20 @@
&panel {
compatible = "auo,b101ean01", "simple-panel";
- power-supply= <&panel_regulator>;
+
+ /delete-node/ panel-timing;
+
+ panel-timing {
+ clock-frequency = <66666667>;
+ hactive = <1280>;
+ hfront-porch = <18>;
+ hback-porch = <21>;
+ hsync-len = <32>;
+ vactive = <800>;
+ vfront-porch = <4>;
+ vback-porch = <8>;
+ vsync-len = <18>;
+ };
};
&rk808 {
@@ -397,12 +375,6 @@
};
&pinctrl {
- backlight {
- bl_pwr_en: bl_pwr_en {
- rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
buck-5v {
drv_5v: drv-5v {
rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -425,16 +397,6 @@
};
};
- lcd {
- lcd_enable_h: lcd-en {
- rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- avdd_1v8_disp_en: avdd-1v8-disp-en {
- rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
pmic {
dvs_1: dvs-1 {
rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rk3288-veyron-pinky.dts
index 9b6f4d9b03b6..f420499f300a 100644
--- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-pinky.dts
@@ -14,7 +14,14 @@
compatible = "google,veyron-pinky-rev2", "google,veyron-pinky",
"google,veyron", "rockchip,rk3288";
+ /delete-node/backlight-regulator;
+ /delete-node/panel-regulator;
/delete-node/emmc-pwrseq;
+ /delete-node/vcc18-lcd;
+};
+
+&backlight {
+ /delete-property/power-supply;
};
&emmc {
@@ -52,7 +59,17 @@
i2c-scl-rising-time-ns = <300>;
};
+&panel {
+ power-supply = <&vcc33_lcd>;
+};
+
&pinctrl {
+ /delete-node/ lcd;
+
+ backlight {
+ /delete-node/ bl_pwr_en;
+ };
+
buttons {
pwr_key_h: pwr-key-h {
rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts
index 9b140db04456..2f2989bc3f9c 100644
--- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts
@@ -16,44 +16,6 @@
"google,veyron-speedy-rev5", "google,veyron-speedy-rev4",
"google,veyron-speedy-rev3", "google,veyron-speedy-rev2",
"google,veyron-speedy", "google,veyron", "rockchip,rk3288";
-
- panel_regulator: panel-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_enable_h>;
- regulator-name = "panel_regulator";
- startup-delay-us = <100000>;
- vin-supply = <&vcc33_sys>;
- };
-
- vcc18_lcd: vcc18-lcd {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&avdd_1v8_disp_en>;
- regulator-name = "vcc18_lcd";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc18_wl>;
- };
-
- backlight_regulator: backlight-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&bl_pwr_en>;
- regulator-name = "backlight_regulator";
- vin-supply = <&vcc33_sys>;
- startup-delay-us = <15000>;
- };
-};
-
-&backlight {
- power-supply = <&backlight_regulator>;
};
&cpu_alert0 {
@@ -83,10 +45,6 @@
temperature = <90000>;
};
-&panel {
- power-supply= <&panel_regulator>;
-};
-
&rk808 {
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
@@ -321,12 +279,6 @@
};
&pinctrl {
- backlight {
- bl_pwr_en: bl_pwr_en {
- rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
buck-5v {
drv_5v: drv-5v {
rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -339,16 +291,6 @@
};
};
- lcd {
- lcd_enable_h: lcd-en {
- rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- avdd_1v8_disp_en: avdd-1v8-disp-en {
- rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
pmic {
dvs_1: dvs-1 {
rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
diff --git a/arch/arm/boot/dts/rk3288-veyron-tiger.dts b/arch/arm/boot/dts/rk3288-veyron-tiger.dts
new file mode 100644
index 000000000000..27557203ae33
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-veyron-tiger.dts
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Veyron Tiger Rev 0+ board device tree source
+ *
+ * Copyright 2016 Google, Inc
+ */
+
+/dts-v1/;
+#include "rk3288-veyron-fievel.dts"
+#include "rk3288-veyron-edp.dtsi"
+
+/ {
+ model = "Google Tiger";
+ compatible = "google,veyron-tiger-rev8", "google,veyron-tiger-rev7",
+ "google,veyron-tiger-rev6", "google,veyron-tiger-rev5",
+ "google,veyron-tiger-rev4", "google,veyron-tiger-rev3",
+ "google,veyron-tiger-rev2", "google,veyron-tiger-rev1",
+ "google,veyron-tiger-rev0", "google,veyron-tiger",
+ "google,veyron", "rockchip,rk3288";
+
+ /delete-node/ vcc18-lcd;
+};
+
+&backlight {
+ /* Tiger panel PWM must be >= 1%, so start non-zero brightness at 3 */
+ brightness-levels = <
+ 0 3 4 5 6 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
+ 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47
+ 48 49 50 51 52 53 54 55
+ 56 57 58 59 60 61 62 63
+ 64 65 66 67 68 69 70 71
+ 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87
+ 88 89 90 91 92 93 94 95
+ 96 97 98 99 100 101 102 103
+ 104 105 106 107 108 109 110 111
+ 112 113 114 115 116 117 118 119
+ 120 121 122 123 124 125 126 127
+ 128 129 130 131 132 133 134 135
+ 136 137 138 139 140 141 142 143
+ 144 145 146 147 148 149 150 151
+ 152 153 154 155 156 157 158 159
+ 160 161 162 163 164 165 166 167
+ 168 169 170 171 172 173 174 175
+ 176 177 178 179 180 181 182 183
+ 184 185 186 187 188 189 190 191
+ 192 193 194 195 196 197 198 199
+ 200 201 202 203 204 205 206 207
+ 208 209 210 211 212 213 214 215
+ 216 217 218 219 220 221 222 223
+ 224 225 226 227 228 229 230 231
+ 232 233 234 235 236 237 238 239
+ 240 241 242 243 244 245 246 247
+ 248 249 250 251 252 253 254 255>;
+};
+
+&backlight_regulator {
+ vin-supply = <&vccsys>;
+};
+
+&i2c3 {
+ status = "okay";
+
+ clock-frequency = <400000>;
+ i2c-scl-falling-time-ns = <50>;
+ i2c-scl-rising-time-ns = <300>;
+
+ touchscreen@10 {
+ compatible = "elan,ekth3500";
+ reg = <0x10>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <RK_PB6 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_int &touch_rst>;
+ reset-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>;
+ vcc33-supply = <&vcc33_io>;
+ vccio-supply = <&vcc33_io>;
+ wakeup-source;
+ };
+};
+
+&panel {
+ compatible = "auo,b101ean01", "simple-panel";
+
+ /delete-node/ panel-timing;
+
+ panel-timing {
+ clock-frequency = <66666667>;
+ hactive = <1280>;
+ hfront-porch = <18>;
+ hback-porch = <21>;
+ hsync-len = <32>;
+ vactive = <800>;
+ vfront-porch = <4>;
+ vback-porch = <8>;
+ vsync-len = <18>;
+ };
+};
+
+&pinctrl {
+ lcd {
+ /delete-node/ avdd-1v8-disp-en;
+ };
+
+ touchscreen {
+ touch_int: touch-int {
+ rockchip,pins = <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ touch_rst: touch-rst {
+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 8fc8eac699bf..7525e3dd1fc1 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -586,6 +586,10 @@
rockchip,pins = <4 RK_PD7 RK_FUNC_GPIO &pcfg_pull_down>;
};
+ bt_host_wake_l: bt-host-wake-l {
+ rockchip,pins = <4 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
/*
* We run sdio0 at max speed; bump up drive strength.
* We also have external pulls, so disable the internal ones.
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index ec1966480f2f..4f3993cc0227 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -85,6 +85,7 @@
clocks = <&l4_main_clk>;
clock-names = "apb_pclk";
resets = <&rst DMA_RESET>;
+ reset-names = "dma";
};
};
@@ -747,7 +748,7 @@
nand0: nand@ff900000 {
#address-cells = <0x1>;
- #size-cells = <0x1>;
+ #size-cells = <0x0>;
compatible = "altr,socfpga-denali-nand";
reg = <0xff900000 0x100000>,
<0xffb80000 0x10000>;
diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
index a0a6d8507265..2a86e72d9791 100644
--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -68,6 +68,8 @@
#dma-requests = <32>;
clocks = <&l4_main_clk>;
clock-names = "apb_pclk";
+ resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>;
+ reset-names = "dma", "dma-ocp";
};
};
@@ -660,7 +662,7 @@
nand: nand@ffb90000 {
#address-cells = <1>;
- #size-cells = <1>;
+ #size-cells = <0>;
compatible = "altr,socfpga-denali-nand";
reg = <0xffb90000 0x72000>,
<0xffb80000 0x10000>;
@@ -753,7 +755,8 @@
cdns,fifo-width = <4>;
cdns,trigger-address = <0x00000000>;
clocks = <&qspi_clk>;
- resets = <&rst QSPI_RESET>;
+ resets = <&rst QSPI_RESET>, <&rst QSPI_OCP_RESET>;
+ reset-names = "qspi", "qspi-ocp";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
index e36e0a0f8aa6..9bd9e04c7361 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
+++ b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
@@ -9,12 +9,18 @@
&nand {
status = "okay";
- partition@nand-boot {
- label = "Boot and fpga data";
- reg = <0x0 0x1C00000>;
- };
- partition@nand-rootfs {
- label = "Root Filesystem - JFFS2";
- reg = <0x1C00000 0x6400000>;
+ nand@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "Boot and fpga data";
+ reg = <0x0 0x1C00000>;
+ };
+ partition@1c00000 {
+ label = "Root Filesystem - JFFS2";
+ reg = <0x1C00000 0x6400000>;
+ };
};
};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
index 355b3dbf438d..a060718758b6 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
@@ -36,21 +36,33 @@
hps_temp0 {
label = "BTN_0"; /* TEMP_OS */
- gpios = <&portc 18 GPIO_ACTIVE_LOW>; /* HPS_GPIO60 */
+ gpios = <&portc 18 GPIO_ACTIVE_LOW>; /* HPS_GPI5 */
linux,code = <BTN_0>;
};
hps_hkey0 {
- label = "BTN_1"; /* DIS_PWR */
- gpios = <&portc 19 GPIO_ACTIVE_LOW>; /* HPS_GPIO61 */
+ label = "GP_SWITCH"; /* GP_SWITCH */
+ gpios = <&portc 19 GPIO_ACTIVE_LOW>; /* HPS_GPI6 */
linux,code = <BTN_1>;
};
hps_hkey1 {
- label = "hps_hkey1"; /* POWER_DOWN */
- gpios = <&portc 20 GPIO_ACTIVE_LOW>; /* HPS_GPIO62 */
+ label = "RESET_SWITCH"; /* RESET_SWITCH */
+ gpios = <&portc 20 GPIO_ACTIVE_LOW>; /* HPS_GPI7 */
+ linux,code = <BTN_2>;
+ };
+
+ hps_hkey2 {
+ label = "POWER_DOWN"; /* POWER_DOWN */
+ gpios = <&portc 4 GPIO_ACTIVE_LOW>; /* HPS_GPIO62 */
linux,code = <KEY_POWER>;
};
+
+ hps_hkey3 {
+ label = "SENSE"; /* SENSE */
+ gpios = <&porta 9 GPIO_ACTIVE_LOW>; /* HPS_GPIO9 */
+ linux,code = <BTN_3>;
+ };
};
regulator-usb-nrst {
@@ -84,10 +96,14 @@
rxd1-skew-ps = <0>;
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
+ txd0-skew-ps = <0>;
+ txd1-skew-ps = <0>;
+ txd2-skew-ps = <0>;
+ txd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1860>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1860>;
};
};
};
diff --git a/arch/arm/boot/dts/ste-ab8500.dtsi b/arch/arm/boot/dts/ste-ab8500.dtsi
new file mode 100644
index 000000000000..55fff4d44277
--- /dev/null
+++ b/arch/arm/boot/dts/ste-ab8500.dtsi
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2012 Linaro Ltd
+ */
+
+#include <dt-bindings/clock/ste-ab8500.h>
+
+/ {
+ soc {
+ prcmu@80157000 {
+ ab8500 {
+ compatible = "stericsson,ab8500";
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ ab8500_clock: clock-controller {
+ compatible = "stericsson,ab8500-clk";
+ #clock-cells = <1>;
+ };
+
+ ab8500_gpio: ab8500-gpio {
+ compatible = "stericsson,ab8500-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ ab8500-rtc {
+ compatible = "stericsson,ab8500-rtc";
+ interrupts = <17 IRQ_TYPE_LEVEL_HIGH
+ 18 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "60S", "ALARM";
+ };
+
+ ab8500-gpadc {
+ compatible = "stericsson,ab8500-gpadc";
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH
+ 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "HW_CONV_END", "SW_CONV_END";
+ vddadc-supply = <&ab8500_ldo_tvout_reg>;
+ };
+
+ ab8500_battery: ab8500_battery {
+ stericsson,battery-type = "LIPO";
+ thermistor-on-batctrl;
+ };
+
+ ab8500_fg {
+ compatible = "stericsson,ab8500-fg";
+ battery = <&ab8500_battery>;
+ };
+
+ ab8500_btemp {
+ compatible = "stericsson,ab8500-btemp";
+ battery = <&ab8500_battery>;
+ };
+
+ ab8500_charger {
+ compatible = "stericsson,ab8500-charger";
+ battery = <&ab8500_battery>;
+ vddadc-supply = <&ab8500_ldo_tvout_reg>;
+ };
+
+ ab8500_chargalg {
+ compatible = "stericsson,ab8500-chargalg";
+ battery = <&ab8500_battery>;
+ };
+
+ ab8500_usb {
+ compatible = "stericsson,ab8500-usb";
+ interrupts = < 90 IRQ_TYPE_LEVEL_HIGH
+ 96 IRQ_TYPE_LEVEL_HIGH
+ 14 IRQ_TYPE_LEVEL_HIGH
+ 15 IRQ_TYPE_LEVEL_HIGH
+ 79 IRQ_TYPE_LEVEL_HIGH
+ 74 IRQ_TYPE_LEVEL_HIGH
+ 75 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ID_WAKEUP_R",
+ "ID_WAKEUP_F",
+ "VBUS_DET_F",
+ "VBUS_DET_R",
+ "USB_LINK_STATUS",
+ "USB_ADP_PROBE_PLUG",
+ "USB_ADP_PROBE_UNPLUG";
+ vddulpivio18-supply = <&ab8500_ldo_intcore_reg>;
+ v-ape-supply = <&db8500_vape_reg>;
+ musb_1v8-supply = <&db8500_vsmps2_reg>;
+ clocks = <&prcmu_clk PRCMU_SYSCLK>;
+ clock-names = "sysclk";
+ };
+
+ ab8500-ponkey {
+ compatible = "stericsson,ab8500-poweron-key";
+ interrupts = <6 IRQ_TYPE_LEVEL_HIGH
+ 7 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
+ };
+
+ ab8500-sysctrl {
+ compatible = "stericsson,ab8500-sysctrl";
+ };
+
+ ab8500-pwm {
+ compatible = "stericsson,ab8500-pwm";
+ clocks = <&ab8500_clock AB8500_SYSCLK_INT>;
+ clock-names = "intclk";
+ };
+
+ ab8500-debugfs {
+ compatible = "stericsson,ab8500-debug";
+ };
+
+ codec: ab8500-codec {
+ compatible = "stericsson,ab8500-codec";
+
+ V-AUD-supply = <&ab8500_ldo_audio_reg>;
+ V-AMIC1-supply = <&ab8500_ldo_anamic1_reg>;
+ V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>;
+ V-DMIC-supply = <&ab8500_ldo_dmic_reg>;
+
+ clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>;
+ clock-names = "audioclk";
+
+ stericsson,earpeice-cmv = <950>; /* Units in mV. */
+ };
+
+ ext_regulators: ab8500-ext-regulators {
+ compatible = "stericsson,ab8500-ext-regulator";
+
+ ab8500_ext1_reg: ab8500_ext1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ab8500_ext2_reg: ab8500_ext2 {
+ regulator-min-microvolt = <1360000>;
+ regulator-max-microvolt = <1360000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ab8500_ext3_reg: ab8500_ext3 {
+ regulator-min-microvolt = <3400000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+ };
+
+ ab8500-regulators {
+ compatible = "stericsson,ab8500-regulator";
+ vin-supply = <&ab8500_ext3_reg>;
+
+ // supplies to the display/camera
+ ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-boot-on;
+ /* BUG: If turned off MMC will be affected. */
+ regulator-always-on;
+ };
+
+ // supplies to the on-board eMMC
+ ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ // supply for VAUX3; SDcard slots
+ ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ // supply for v-intcore12; VINTCORE12 LDO
+ ab8500_ldo_intcore_reg: ab8500_ldo_intcore {
+ };
+
+ // supply for tvout; gpadc; TVOUT LDO
+ ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+ };
+
+ // supply for ab8500-vaudio; VAUDIO LDO
+ ab8500_ldo_audio_reg: ab8500_ldo_audio {
+ };
+
+ // supply for v-anamic1 VAMIC1 LDO
+ ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+ };
+
+ // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
+ ab8500_ldo_anamic2_reg: ab8500_ldo_anamic2 {
+ };
+
+ // supply for v-dmic; VDMIC LDO
+ ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+ };
+
+ // supply for U8500 CSI/DSI; VANA LDO
+ ab8500_ldo_ana_reg: ab8500_ldo_ana {
+ };
+ };
+ };
+ };
+
+ sound {
+ stericsson,audio-codec = <&codec>;
+ clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>;
+ clock-names = "sysclk", "ulpclk", "intclk";
+ };
+
+ mcde@a0350000 {
+ vana-supply = <&ab8500_ldo_ana_reg>;
+
+ dsi@a0351000 {
+ vana-supply = <&ab8500_ldo_ana_reg>;
+ };
+ dsi@a0352000 {
+ vana-supply = <&ab8500_ldo_ana_reg>;
+ };
+ dsi@a0353000 {
+ vana-supply = <&ab8500_ldo_ana_reg>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index b1a31134f860..a53657b83288 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -8,7 +8,6 @@
#include <dt-bindings/mfd/dbx500-prcmu.h>
#include <dt-bindings/arm/ux500_pm_domains.h>
#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/ste-ab8500.h>
/ {
#address-cells = <1>;
@@ -44,6 +43,7 @@
clocks = <&prcmu_clk PRCMU_ARMSS>;
clock-names = "cpu";
clock-latency = <20000>;
+ #cooling-cells = <2>;
};
CPU1: cpu@301 {
device_type = "cpu";
@@ -52,6 +52,39 @@
};
};
+ thermal-zones {
+ /*
+ * Thermal zone for the SoC, using the thermal sensor in the
+ * PRCMU for temperature and the cpufreq driver for passive
+ * cooling.
+ */
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&thermal>;
+
+ trips {
+ cpu_alert: cpu-alert {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu-crit {
+ temperature = <85000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ trip = <&cpu_alert>;
+ cooling-device = <&CPU0 0 2>;
+ contribution = <100>;
+ };
+ };
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -92,7 +125,7 @@
};
funnel@801a6000 {
- compatible = "arm,coresight-funnel", "arm,primecell";
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x801a6000 0x1000>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
@@ -127,7 +160,7 @@
};
replicator {
- compatible = "arm,coresight-replicator";
+ compatible = "arm,coresight-static-replicator";
clocks = <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "atclk";
@@ -502,13 +535,14 @@
reg = <0x80157450 0xC>;
};
- thermal@801573c0 {
+ thermal: thermal@801573c0 {
compatible = "stericsson,db8500-thermal";
reg = <0x801573c0 0x40>;
+ interrupt-parent = <&prcmu>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>,
<22 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "IRQ_HOTMON_LOW", "IRQ_HOTMON_HIGH";
- status = "disabled";
+ #thermal-sensor-cells = <0>;
};
db8500-prcmu-regulators {
@@ -597,206 +631,6 @@
db8500_esram34_ret_reg: db8500_esram34_ret {
};
};
-
- ab8500 {
- compatible = "stericsson,ab8500";
- interrupt-parent = <&intc>;
- interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- ab8500_clock: clock-controller {
- compatible = "stericsson,ab8500-clk";
- #clock-cells = <1>;
- };
-
- ab8500_gpio: ab8500-gpio {
- compatible = "stericsson,ab8500-gpio";
- gpio-controller;
- #gpio-cells = <2>;
- };
-
- ab8500-rtc {
- compatible = "stericsson,ab8500-rtc";
- interrupts = <17 IRQ_TYPE_LEVEL_HIGH
- 18 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "60S", "ALARM";
- };
-
- ab8500-gpadc {
- compatible = "stericsson,ab8500-gpadc";
- interrupts = <32 IRQ_TYPE_LEVEL_HIGH
- 39 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "HW_CONV_END", "SW_CONV_END";
- vddadc-supply = <&ab8500_ldo_tvout_reg>;
- };
-
- ab8500_battery: ab8500_battery {
- stericsson,battery-type = "LIPO";
- thermistor-on-batctrl;
- };
-
- ab8500_fg {
- compatible = "stericsson,ab8500-fg";
- battery = <&ab8500_battery>;
- };
-
- ab8500_btemp {
- compatible = "stericsson,ab8500-btemp";
- battery = <&ab8500_battery>;
- };
-
- ab8500_charger {
- compatible = "stericsson,ab8500-charger";
- battery = <&ab8500_battery>;
- vddadc-supply = <&ab8500_ldo_tvout_reg>;
- };
-
- ab8500_chargalg {
- compatible = "stericsson,ab8500-chargalg";
- battery = <&ab8500_battery>;
- };
-
- ab8500_usb {
- compatible = "stericsson,ab8500-usb";
- interrupts = < 90 IRQ_TYPE_LEVEL_HIGH
- 96 IRQ_TYPE_LEVEL_HIGH
- 14 IRQ_TYPE_LEVEL_HIGH
- 15 IRQ_TYPE_LEVEL_HIGH
- 79 IRQ_TYPE_LEVEL_HIGH
- 74 IRQ_TYPE_LEVEL_HIGH
- 75 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ID_WAKEUP_R",
- "ID_WAKEUP_F",
- "VBUS_DET_F",
- "VBUS_DET_R",
- "USB_LINK_STATUS",
- "USB_ADP_PROBE_PLUG",
- "USB_ADP_PROBE_UNPLUG";
- vddulpivio18-supply = <&ab8500_ldo_intcore_reg>;
- v-ape-supply = <&db8500_vape_reg>;
- musb_1v8-supply = <&db8500_vsmps2_reg>;
- clocks = <&prcmu_clk PRCMU_SYSCLK>;
- clock-names = "sysclk";
- };
-
- ab8500-ponkey {
- compatible = "stericsson,ab8500-poweron-key";
- interrupts = <6 IRQ_TYPE_LEVEL_HIGH
- 7 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
- };
-
- ab8500-sysctrl {
- compatible = "stericsson,ab8500-sysctrl";
- };
-
- ab8500-pwm {
- compatible = "stericsson,ab8500-pwm";
- clocks = <&ab8500_clock AB8500_SYSCLK_INT>;
- clock-names = "intclk";
- };
-
- ab8500-debugfs {
- compatible = "stericsson,ab8500-debug";
- };
-
- codec: ab8500-codec {
- compatible = "stericsson,ab8500-codec";
-
- V-AUD-supply = <&ab8500_ldo_audio_reg>;
- V-AMIC1-supply = <&ab8500_ldo_anamic1_reg>;
- V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>;
- V-DMIC-supply = <&ab8500_ldo_dmic_reg>;
-
- clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>;
- clock-names = "audioclk";
-
- stericsson,earpeice-cmv = <950>; /* Units in mV. */
- };
-
- ext_regulators: ab8500-ext-regulators {
- compatible = "stericsson,ab8500-ext-regulator";
-
- ab8500_ext1_reg: ab8500_ext1 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ab8500_ext2_reg: ab8500_ext2 {
- regulator-min-microvolt = <1360000>;
- regulator-max-microvolt = <1360000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ab8500_ext3_reg: ab8500_ext3 {
- regulator-min-microvolt = <3400000>;
- regulator-max-microvolt = <3400000>;
- regulator-boot-on;
- };
- };
-
- ab8500-regulators {
- compatible = "stericsson,ab8500-regulator";
- vin-supply = <&ab8500_ext3_reg>;
-
- // supplies to the display/camera
- ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2900000>;
- regulator-boot-on;
- /* BUG: If turned off MMC will be affected. */
- regulator-always-on;
- };
-
- // supplies to the on-board eMMC
- ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <3300000>;
- };
-
- // supply for VAUX3; SDcard slots
- ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <3300000>;
- };
-
- // supply for v-intcore12; VINTCORE12 LDO
- ab8500_ldo_intcore_reg: ab8500_ldo_intcore {
- };
-
- // supply for tvout; gpadc; TVOUT LDO
- ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
- };
-
- // supply for ab8500-usb; USB LDO
- ab8500_ldo_usb_reg: ab8500_ldo_usb {
- };
-
- // supply for ab8500-vaudio; VAUDIO LDO
- ab8500_ldo_audio_reg: ab8500_ldo_audio {
- };
-
- // supply for v-anamic1 VAMIC1 LDO
- ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
- };
-
- // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
- ab8500_ldo_anamic2_reg: ab8500_ldo_anamic2 {
- };
-
- // supply for v-dmic; VDMIC LDO
- ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
- };
-
- // supply for U8500 CSI/DSI; VANA LDO
- ab8500_ldo_ana_reg: ab8500_ldo_ana {
- };
- };
- };
};
i2c@80004000 {
@@ -1110,9 +944,6 @@
sound {
compatible = "stericsson,snd-soc-mop500";
stericsson,cpu-dai = <&msp1 &msp3>;
- stericsson,audio-codec = <&codec>;
- clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>;
- clock-names = "sysclk", "ulpclk", "intclk";
};
msp0: msp@80123000 {
@@ -1219,7 +1050,6 @@
reg = <0xa0350000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
epod-supply = <&db8500_b2r2_mcde_reg>;
- vana-supply = <&ab8500_ldo_ana_reg>;
clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
<&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
<&prcmu_clk PRCMU_PLLDSI>; /* HDMI clock */
@@ -1232,7 +1062,6 @@
dsi0: dsi@a0351000 {
compatible = "ste,mcde-dsi";
reg = <0xa0351000 0x1000>;
- vana-supply = <&ab8500_ldo_ana_reg>;
clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>;
clock-names = "hs", "lp";
#address-cells = <1>;
@@ -1241,7 +1070,6 @@
dsi1: dsi@a0352000 {
compatible = "ste,mcde-dsi";
reg = <0xa0352000 0x1000>;
- vana-supply = <&ab8500_ldo_ana_reg>;
clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>;
clock-names = "hs", "lp";
#address-cells = <1>;
@@ -1250,7 +1078,6 @@
dsi2: dsi@a0353000 {
compatible = "ste,mcde-dsi";
reg = <0xa0353000 0x1000>;
- vana-supply = <&ab8500_ldo_ana_reg>;
/* This DSI port only has the Low Power / Energy Save clock */
clocks = <&prcmu_clk PRCMU_DSI2ESCCLK>;
clock-names = "lp";
diff --git a/arch/arm/boot/dts/ste-href-ab8500.dtsi b/arch/arm/boot/dts/ste-href-ab8500.dtsi
index 8e3e947d181f..4946743de7b9 100644
--- a/arch/arm/boot/dts/ste-href-ab8500.dtsi
+++ b/arch/arm/boot/dts/ste-href-ab8500.dtsi
@@ -3,6 +3,8 @@
* Copyright 2014 Linaro Ltd.
*/
+#include "ste-ab8500.dtsi"
+
/ {
soc {
prcmu@80157000 {
diff --git a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi
index 86621196abda..2c382d274ff6 100644
--- a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi
+++ b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi
@@ -607,7 +607,6 @@
groups =
"lcdvsi0_a_1", /* VSI0 for LCD */
"lcd_d0_d7_a_1", /* Data lines */
- "lcd_d8_d11_a_1", /* TV-out */
"lcdvsi1_a_1"; /* VSI1 for HDMI */
};
default_mux2 {
diff --git a/arch/arm/boot/dts/ste-href-stuib.dtsi b/arch/arm/boot/dts/ste-href-stuib.dtsi
index b17998f4f7ca..e32d0c36feb8 100644
--- a/arch/arm/boot/dts/ste-href-stuib.dtsi
+++ b/arch/arm/boot/dts/ste-href-stuib.dtsi
@@ -38,6 +38,8 @@
interrupt-controller;
vcc-supply = <&db8500_vsmps2_reg>;
vio-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&stmpe_stuib_mode>;
wakeup-source;
st,autosleep-timeout = <1024>;
@@ -126,6 +128,15 @@
};
pinctrl {
+ /* Pull up this GPIO pin */
+ stmpe {
+ stmpe_stuib_mode: stmpe_stuib {
+ stuib_cfg {
+ ste,pins = "GPIO218_AH11";
+ ste,config = <&gpio_in_pu>;
+ };
+ };
+ };
prox {
prox_stuib_mode: prox_stuib {
stuib_cfg {
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
index 6422c53f2046..4f6acbd8c040 100644
--- a/arch/arm/boot/dts/ste-href.dtsi
+++ b/arch/arm/boot/dts/ste-href.dtsi
@@ -234,10 +234,6 @@
regulator-name = "V-TVOUT";
};
- ab8500_ldo_usb_reg: ab8500_ldo_usb {
- regulator-name = "dummy";
- };
-
ab8500_ldo_audio_reg: ab8500_ldo_audio {
regulator-name = "V-AUD";
};
diff --git a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts
index aed940bd65a8..b78be5f4c212 100644
--- a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts
+++ b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts
@@ -4,6 +4,8 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
#include "ste-hrefprev60.dtsi"
#include "ste-href-stuib.dtsi"
@@ -23,12 +25,16 @@
i2c@80110000 {
/* Only one of these will be used */
bu21013_tp@5c {
- touch-gpio = <&gpio2 12 0x4>;
- reset-gpio = <&tc3589x_gpio 13 0x4>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>;
};
bu21013_tp@5d {
- touch-gpio = <&gpio2 12 0x4>;
- reset-gpio = <&tc3589x_gpio 13 0x4>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>;
};
};
};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts
index 0f3c3b86bb20..9be513aad549 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts
+++ b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts
@@ -6,6 +6,8 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
#include "ste-hrefv60plus.dtsi"
#include "ste-href-stuib.dtsi"
@@ -25,12 +27,16 @@
i2c@80110000 {
/* Only one of these will be used */
bu21013_tp@5c {
- touch-gpio = <&gpio2 20 0x4>;
- reset-gpio = <&gpio4 17 0x4>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>;
};
bu21013_tp@5d {
- touch-gpio = <&gpio2 20 0x4>;
- reset-gpio = <&gpio4 17 0x4>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>;
};
};
};
diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/ste-nomadik-nhk15.dts
index 04066f9cb8a3..41ed21a4fdc1 100644
--- a/arch/arm/boot/dts/ste-nomadik-nhk15.dts
+++ b/arch/arm/boot/dts/ste-nomadik-nhk15.dts
@@ -212,13 +212,7 @@
*/
gpio-sck = <&gpio0 5 GPIO_ACTIVE_HIGH>;
gpio-mosi = <&gpio0 4 GPIO_ACTIVE_HIGH>;
- /*
- * It's not actually active high, but the frameworks assume
- * the polarity of the passed-in GPIO is "normal" (active
- * high) then actively drives the line low to select the
- * chip.
- */
- cs-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
num-chipselects = <1>;
/*
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 3428290644ba..efbc4467b8b7 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -376,40 +376,11 @@
pinctrl-0 = <&ssp0_snowball_mode>;
};
- cpufreq-cooling {
- status = "okay";
- };
-
prcmu@80157000 {
cpufreq {
status = "okay";
};
- thermal@801573c0 {
- num-trips = <4>;
-
- trip0-temp = <70000>;
- trip0-type = "active";
- trip0-cdev-num = <1>;
- trip0-cdev-name0 = "thermal-cpufreq-0";
-
- trip1-temp = <75000>;
- trip1-type = "active";
- trip1-cdev-num = <1>;
- trip1-cdev-name0 = "thermal-cpufreq-0";
-
- trip2-temp = <80000>;
- trip2-type = "active";
- trip2-cdev-num = <1>;
- trip2-cdev-name0 = "thermal-cpufreq-0";
-
- trip3-temp = <85000>;
- trip3-type = "critical";
- trip3-cdev-num = <0>;
-
- status = "okay";
- };
-
ab8500 {
ab8500-gpio {
/*
@@ -474,10 +445,6 @@
regulator-name = "V-TVOUT";
};
- ab8500_ldo_usb_reg: ab8500_ldo_usb {
- regulator-name = "dummy";
- };
-
ab8500_ldo_audio_reg: ab8500_ldo_audio {
regulator-name = "V-AUD";
};
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 73ea84df7bf4..ba08624c6237 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -81,18 +81,18 @@
dma-ranges = <0xc0000000 0x0 0x10000000>;
};
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
+ vdda: regulator-vdda {
+ compatible = "regulator-fixed";
+ regulator-name = "vdda";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
- reg_vref: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "vref";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
+ vref: regulator-vref {
+ compatible = "regulator-fixed";
+ regulator-name = "vref";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
};
leds {
@@ -157,7 +157,8 @@
&adc {
pinctrl-names = "default";
pinctrl-0 = <&adc3_in8_pin>;
- vref-supply = <&reg_vref>;
+ vdda-supply = <&vdda>;
+ vref-supply = <&vref>;
status = "okay";
adc3: adc@200 {
st,adc-channels = <8>;
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 4a4954492ed1..5c8a826b3195 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -112,6 +112,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -141,6 +142,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -170,6 +172,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -198,6 +201,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -267,6 +271,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -288,6 +293,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -303,6 +309,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -448,6 +455,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -469,6 +477,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -602,6 +611,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -623,6 +633,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -638,6 +649,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi
index a25b7000a3a1..d26f93f8b9c2 100644
--- a/arch/arm/boot/dts/stm32f746.dtsi
+++ b/arch/arm/boot/dts/stm32f746.dtsi
@@ -94,6 +94,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -123,6 +124,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -152,6 +154,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -180,6 +183,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -249,6 +253,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -270,6 +275,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -285,6 +291,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -419,6 +426,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -440,6 +448,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -512,6 +521,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -533,6 +543,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -548,6 +559,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts
index ab78ad532375..e4d3c58f3d97 100644
--- a/arch/arm/boot/dts/stm32h743i-eval.dts
+++ b/arch/arm/boot/dts/stm32h743i-eval.dts
@@ -87,6 +87,7 @@
};
&adc_12 {
+ vdda-supply = <&vdda>;
vref-supply = <&vdda>;
status = "okay";
adc1: adc@0 {
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
index df6470133574..e4a0d51ec3a8 100644
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -24,8 +24,6 @@
reg = <0x0 0x400>;
clocks = <&rcc GPIOA>;
st,bank-name = "GPIOA";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 0 16>;
status = "disabled";
};
@@ -37,8 +35,6 @@
reg = <0x1000 0x400>;
clocks = <&rcc GPIOB>;
st,bank-name = "GPIOB";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 16 16>;
status = "disabled";
};
@@ -50,8 +46,6 @@
reg = <0x2000 0x400>;
clocks = <&rcc GPIOC>;
st,bank-name = "GPIOC";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 32 16>;
status = "disabled";
};
@@ -63,8 +57,6 @@
reg = <0x3000 0x400>;
clocks = <&rcc GPIOD>;
st,bank-name = "GPIOD";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 48 16>;
status = "disabled";
};
@@ -76,8 +68,6 @@
reg = <0x4000 0x400>;
clocks = <&rcc GPIOE>;
st,bank-name = "GPIOE";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 64 16>;
status = "disabled";
};
@@ -89,8 +79,6 @@
reg = <0x5000 0x400>;
clocks = <&rcc GPIOF>;
st,bank-name = "GPIOF";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 80 16>;
status = "disabled";
};
@@ -102,8 +90,6 @@
reg = <0x6000 0x400>;
clocks = <&rcc GPIOG>;
st,bank-name = "GPIOG";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 96 16>;
status = "disabled";
};
@@ -115,8 +101,6 @@
reg = <0x7000 0x400>;
clocks = <&rcc GPIOH>;
st,bank-name = "GPIOH";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 112 16>;
status = "disabled";
};
@@ -128,8 +112,6 @@
reg = <0x8000 0x400>;
clocks = <&rcc GPIOI>;
st,bank-name = "GPIOI";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 128 16>;
status = "disabled";
};
@@ -141,8 +123,6 @@
reg = <0x9000 0x400>;
clocks = <&rcc GPIOJ>;
st,bank-name = "GPIOJ";
- ngpios = <16>;
- gpio-ranges = <&pinctrl 0 144 16>;
status = "disabled";
};
@@ -154,8 +134,6 @@
reg = <0xa000 0x400>;
clocks = <&rcc GPIOK>;
st,bank-name = "GPIOK";
- ngpios = <8>;
- gpio-ranges = <&pinctrl 0 160 8>;
status = "disabled";
};
@@ -276,6 +254,50 @@
};
};
+ fmc_pins_a: fmc-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
+ <STM32_PINMUX('D', 5, AF12)>, /* FMC_NWE */
+ <STM32_PINMUX('D', 11, AF12)>, /* FMC_A16_FMC_CLE */
+ <STM32_PINMUX('D', 12, AF12)>, /* FMC_A17_FMC_ALE */
+ <STM32_PINMUX('D', 14, AF12)>, /* FMC_D0 */
+ <STM32_PINMUX('D', 15, AF12)>, /* FMC_D1 */
+ <STM32_PINMUX('D', 0, AF12)>, /* FMC_D2 */
+ <STM32_PINMUX('D', 1, AF12)>, /* FMC_D3 */
+ <STM32_PINMUX('E', 7, AF12)>, /* FMC_D4 */
+ <STM32_PINMUX('E', 8, AF12)>, /* FMC_D5 */
+ <STM32_PINMUX('E', 9, AF12)>, /* FMC_D6 */
+ <STM32_PINMUX('E', 10, AF12)>, /* FMC_D7 */
+ <STM32_PINMUX('G', 9, AF12)>; /* FMC_NE2_FMC_NCE */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 6, AF12)>; /* FMC_NWAIT */
+ bias-pull-up;
+ };
+ };
+
+ fmc_sleep_pins_a: fmc-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
+ <STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
+ <STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
+ <STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
+ <STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
+ <STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
+ <STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
+ <STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
+ <STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
+ <STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
+ <STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
+ <STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
+ <STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
+ <STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
+ };
+ };
+
i2c1_pins_a: i2c1-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -530,7 +552,7 @@
};
};
- m_can1_sleep_pins_a: m_can1-sleep@0 {
+ m_can1_sleep_pins_a: m_can1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* CAN1_TX */
<STM32_PINMUX('I', 9, ANALOG)>; /* CAN1_RX */
@@ -849,8 +871,6 @@
clocks = <&rcc GPIOZ>;
st,bank-name = "GPIOZ";
st,bank-ioport = <11>;
- ngpios = <8>;
- gpio-ranges = <&pinctrl_z 0 400 8>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
index f3f0e37aad4d..0615d1c8a6fc 100644
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
@@ -33,6 +33,42 @@
#size-cells = <1>;
ranges;
+ mcuram2: mcuram2@10000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10000000 0x40000>;
+ no-map;
+ };
+
+ vdev0vring0: vdev0vring0@10040000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10040000 0x1000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@10041000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10041000 0x1000>;
+ no-map;
+ };
+
+ vdev0buffer: vdev0buffer@10042000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10042000 0x4000>;
+ no-map;
+ };
+
+ mcuram: mcuram@30000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x30000000 0x40000>;
+ no-map;
+ };
+
+ retram: retram@38000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x38000000 0x10000>;
+ no-map;
+ };
+
gpu_reserved: gpu@d4000000 {
reg = <0xd4000000 0x4000000>;
no-map;
@@ -48,6 +84,17 @@
default-state = "off";
};
};
+
+ sound {
+ compatible = "audio-graph-card";
+ label = "STM32MP1-DK";
+ routing =
+ "Playback" , "MCLK",
+ "Capture" , "MCLK",
+ "MICL" , "Mic Bias";
+ dais = <&sai2a_port &sai2b_port>;
+ status = "okay";
+ };
};
&cec {
@@ -116,6 +163,39 @@
};
};
};
+
+ cs42l51: cs42l51@4a {
+ compatible = "cirrus,cs42l51";
+ reg = <0x4a>;
+ #sound-dai-cells = <0>;
+ VL-supply = <&v3v3>;
+ VD-supply = <&v1v8_audio>;
+ VA-supply = <&v1v8_audio>;
+ VAHP-supply = <&v1v8_audio>;
+ reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;
+ clocks = <&sai2a>;
+ clock-names = "MCLK";
+ status = "okay";
+
+ cs42l51_port: port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cs42l51_tx_endpoint: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&sai2a_endpoint>;
+ frame-master;
+ bitclock-master;
+ };
+
+ cs42l51_rx_endpoint: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&sai2b_endpoint>;
+ frame-master;
+ bitclock-master;
+ };
+ };
+ };
};
&i2c4 {
@@ -289,6 +369,16 @@
};
};
+&m4_rproc {
+ memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
+ <&vdev0vring1>, <&vdev0buffer>;
+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
+ mbox-names = "vq0", "vq1", "shutdown";
+ interrupt-parent = <&exti>;
+ interrupts = <68 1>;
+ status = "okay";
+};
+
&rng1 {
status = "okay";
};
@@ -297,6 +387,51 @@
status = "okay";
};
+&sai2 {
+ clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>;
+ clock-names = "pclk", "x8k", "x11k";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>;
+ pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>;
+ status = "okay";
+
+ sai2a: audio-controller@4400b004 {
+ #clock-cells = <0>;
+ dma-names = "tx";
+ clocks = <&rcc SAI2_K>;
+ clock-names = "sai_ck";
+ status = "okay";
+
+ sai2a_port: port {
+ sai2a_endpoint: endpoint {
+ remote-endpoint = <&cs42l51_tx_endpoint>;
+ format = "i2s";
+ mclk-fs = <256>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ };
+ };
+ };
+
+ sai2b: audio-controller@4400b024 {
+ dma-names = "rx";
+ st,sync = <&sai2a 2>;
+ clocks = <&rcc SAI2_K>, <&sai2a>;
+ clock-names = "sai_ck", "MCLK";
+ status = "okay";
+
+ sai2b_port: port {
+ sai2b_endpoint: endpoint {
+ remote-endpoint = <&cs42l51_rx_endpoint>;
+ format = "i2s";
+ mclk-fs = <256>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ };
+ };
+ };
+};
+
&sdmmc1 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index 4fe7f71a74d3..1d426ea8bdaf 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -28,6 +28,42 @@
#size-cells = <1>;
ranges;
+ mcuram2: mcuram2@10000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10000000 0x40000>;
+ no-map;
+ };
+
+ vdev0vring0: vdev0vring0@10040000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10040000 0x1000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@10041000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10041000 0x1000>;
+ no-map;
+ };
+
+ vdev0buffer: vdev0buffer@10042000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10042000 0x4000>;
+ no-map;
+ };
+
+ mcuram: mcuram@30000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x30000000 0x40000>;
+ no-map;
+ };
+
+ retram: retram@38000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x38000000 0x10000>;
+ no-map;
+ };
+
gpu_reserved: gpu@e8000000 {
reg = <0xe8000000 0x8000000>;
no-map;
@@ -233,6 +269,16 @@
status = "okay";
};
+&m4_rproc {
+ memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
+ <&vdev0vring1>, <&vdev0buffer>;
+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
+ mbox-names = "vq0", "vq1", "shutdown";
+ interrupt-parent = <&exti>;
+ interrupts = <68 1>;
+ status = "okay";
+};
+
&rng1 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts
index feb8f7727270..89d29b50c3f4 100644
--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
@@ -101,6 +101,7 @@
&dsi {
#address-cells = <1>;
#size-cells = <0>;
+ phy-dsi-supply = <&reg18>;
status = "okay";
ports {
@@ -157,6 +158,22 @@
};
};
+&fmc {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&fmc_pins_a>;
+ pinctrl-1 = <&fmc_sleep_pins_a>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
&i2c2 {
pinctrl-names = "default";
pinctrl-0 = <&i2c2_pins_a>;
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
index 0c4e6ebc3529..9b11654a0a39 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -109,6 +109,12 @@
};
};
+ booster: regulator-booster {
+ compatible = "st,stm32mp1-booster";
+ st,syscfg = <&syscfg>;
+ status = "disabled";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -133,6 +139,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -161,6 +168,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -187,6 +195,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -215,6 +224,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -272,6 +282,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -293,6 +304,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -314,6 +326,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -567,6 +580,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -597,6 +611,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -670,6 +685,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -694,6 +710,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
timer@15 {
@@ -717,6 +734,7 @@
pwm {
compatible = "st,stm32-pwm";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -983,6 +1001,7 @@
clocks = <&rcc ADC12>, <&rcc ADC12_K>;
clock-names = "bus", "adc";
interrupt-controller;
+ st,syscfg = <&syscfg>;
#interrupt-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1239,11 +1258,33 @@
dma-requests = <48>;
};
+ fmc: nand-controller@58002000 {
+ compatible = "st,stm32mp15-fmc2";
+ reg = <0x58002000 0x1000>,
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
+ <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
+ <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
+ dma-names = "tx", "rx", "ecc";
+ clocks = <&rcc FMC_K>;
+ resets = <&rcc FMC_R>;
+ status = "disabled";
+ };
+
qspi: spi@58003000 {
compatible = "st,stm32f469-qspi";
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
reg-names = "qspi", "qspi_mm";
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>,
+ <&mdma1 22 0x10 0x100008 0x0 0x0>;
+ dma-names = "tx", "rx";
clocks = <&rcc QSPI_K>;
resets = <&rcc QSPI_R>;
status = "disabled";
@@ -1448,4 +1489,24 @@
status = "disabled";
};
};
+
+ mlahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ dma-ranges = <0x00000000 0x38000000 0x10000>,
+ <0x10000000 0x10000000 0x60000>,
+ <0x30000000 0x30000000 0x60000>;
+
+ m4_rproc: m4@10000000 {
+ compatible = "st,stm32mp1-m4";
+ reg = <0x10000000 0x40000>,
+ <0x30000000 0x40000>,
+ <0x38000000 0x10000>;
+ resets = <&rcc MCU_R>;
+ st,syscfg-holdboot = <&rcc 0x10C 0x1>;
+ st,syscfg-tz = <&rcc 0x000 0x1>;
+ status = "disabled";
+ };
+ };
};
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index 6c254ec4c85b..8692b11a83c3 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -125,7 +125,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
index 38a2c4134952..816d534ac093 100644
--- a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
+++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
@@ -68,7 +68,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index 7306c65df88a..6ca02e824acc 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -114,7 +114,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
index cc988ccd5ca7..47dea0922501 100644
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
@@ -80,7 +80,7 @@
};
&emac {
- phy = <&phy0>;
+ phy-handle = <&phy0>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts b/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts
index 80ecd78247ac..d4e319d16aae 100644
--- a/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts
+++ b/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts
@@ -58,7 +58,7 @@
&emac {
pinctrl-names = "default";
pinctrl-0 = <&emac_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
index 247fa27ef717..8a7b4c53d278 100644
--- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
+++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
@@ -94,7 +94,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/sun4i-a10-marsboard.dts
index 58ad2ad9041f..a843e57530ed 100644
--- a/arch/arm/boot/dts/sun4i-a10-marsboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-marsboard.dts
@@ -105,7 +105,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
index a8e537fd4bd6..845f76824d57 100644
--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
@@ -112,7 +112,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
index 0f1e781069e9..83287b6c975e 100644
--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
@@ -110,7 +110,7 @@
};
&emac {
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index e88daa4ef1af..ce823c44e98a 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -803,13 +803,20 @@
timer@1c20c00 {
compatible = "allwinner,sun4i-a10-timer";
reg = <0x01c20c00 0x90>;
- interrupts = <22>;
+ interrupts = <22>,
+ <23>,
+ <24>,
+ <25>,
+ <67>,
+ <68>;
clocks = <&osc24M>;
};
wdt: watchdog@1c20c90 {
compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
+ interrupts = <24>;
+ clocks = <&osc24M>;
};
rtc: rtc@1c20d00 {
diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
index 5340b4164df2..7033a123c9a3 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
@@ -98,7 +98,7 @@
&emac {
pinctrl-names = "default";
pinctrl-0 = <&emac_pa_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
index b5ee8fb13a92..1f74ba1634cc 100644
--- a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
@@ -91,7 +91,7 @@
&emac {
pinctrl-names = "default";
pinctrl-0 = <&emac_pd_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
index fde559a8b61e..f9fc1c8b60b8 100644
--- a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
+++ b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
@@ -49,7 +49,7 @@
compatible = "allwinner,q8-a13", "allwinner,sun5i-a13";
panel: panel {
- compatible = "bananapi,s070wv20-ct16", "simple-panel";
+ compatible = "bananapi,s070wv20-ct16";
power-supply = <&reg_vcc3v3>;
enable-gpios = <&axp_gpio 0 GPIO_ACTIVE_HIGH>; /* AXP GPIO0 */
backlight = <&backlight>;
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 2fb438c4fe9d..cfb1efc8828c 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -588,13 +588,20 @@
timer@1c20c00 {
compatible = "allwinner,sun4i-a10-timer";
reg = <0x01c20c00 0x90>;
- interrupts = <22>;
+ interrupts = <22>,
+ <23>,
+ <24>,
+ <25>,
+ <67>,
+ <68>;
clocks = <&ccu CLK_HOSC>;
};
wdt: watchdog@1c20c90 {
compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
+ interrupts = <24>;
+ clocks = <&osc24M>;
};
ir0: ir@1c21800 {
diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts
index c3d56dc93513..93a15eaaa8cb 100644
--- a/arch/arm/boot/dts/sun6i-a31-colombus.dts
+++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts
@@ -76,13 +76,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -104,6 +100,12 @@
};
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v0>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
index 09832b4e8fc8..049e6ab3cf56 100644
--- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
+++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -153,16 +153,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
- snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 30000>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -199,6 +192,15 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <30000>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_dcdc1>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/sun6i-a31-i7.dts
index 091eb2ac53b3..6cc8ccf53d88 100644
--- a/arch/arm/boot/dts/sun6i-a31-i7.dts
+++ b/arch/arm/boot/dts/sun6i-a31-i7.dts
@@ -117,13 +117,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -142,6 +138,12 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts
index 6eafb6361a26..a645c8f4257c 100644
--- a/arch/arm/boot/dts/sun6i-a31-m9.dts
+++ b/arch/arm/boot/dts/sun6i-a31-m9.dts
@@ -84,14 +84,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
phy-supply = <&reg_dldo1>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&ir {
@@ -100,6 +96,12 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_dcdc1>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts
index ca036f97923a..648f24746234 100644
--- a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts
+++ b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts
@@ -84,14 +84,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
phy-supply = <&reg_dldo1>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&ir {
@@ -100,6 +96,12 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_dcdc1>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index dcddc3392460..bbeb743633c6 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -736,13 +736,16 @@
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc24M>;
};
wdt1: watchdog@1c20ca0 {
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
spdif: spdif@1c21000 {
@@ -939,8 +942,12 @@
snps,fixed-burst;
snps,force_sf_dma_mode;
status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
crypto: crypto-engine@1c15000 {
@@ -1364,7 +1371,7 @@
};
ir: ir@1f02000 {
- compatible = "allwinner,sun5i-a13-ir";
+ compatible = "allwinner,sun6i-a31-ir";
clocks = <&apb0_gates 1>, <&ir_clk>;
clock-names = "apb", "ir";
resets = <&apb0_rst 1>;
diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/sun6i-a31s-cs908.dts
index 72a02c045a38..1d15e15011c6 100644
--- a/arch/arm/boot/dts/sun6i-a31s-cs908.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-cs908.dts
@@ -67,12 +67,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&ir {
@@ -81,6 +78,12 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&ohci1 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts
index 4865c3271ab0..0af48e143b66 100644
--- a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts
@@ -115,14 +115,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
phy-supply = <&reg_dldo1>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -160,6 +156,12 @@
};
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_dcdc1>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts
index 8e724c52feff..708caee52425 100644
--- a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts
@@ -92,17 +92,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_dldo1>;
- snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>; /* PA21 */
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 30000>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&ir {
@@ -111,6 +104,15 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; /* PA21 */
+ reset-assert-us = <10000>;
+ reset-deassert-us = <30000>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_dcdc1>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
index e2bfe0058830..32d5d45a35c0 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -129,14 +129,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -171,6 +167,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts
index 4df921632f7a..bb3987e101c2 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts
@@ -131,14 +131,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -171,6 +167,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/sun7i-a20-bananapro.dts
index 0176e9de0180..01ccff756996 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapro.dts
@@ -109,14 +109,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -143,6 +139,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 08e5a5abf8cc..b8203e4ef21c 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -115,13 +115,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -161,6 +157,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&ohci0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index 99f531b8d2a7..8c8dee6ea461 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -150,13 +150,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -194,6 +190,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts
index fd0153f65685..3def2a330598 100644
--- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts
+++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts
@@ -100,19 +100,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_vdd>;
- /* phy reset config */
- snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>; /* PA17 */
- snps,reset-active-low;
- /* wait 1s after reset, otherwise fail to read phy id */
- snps,reset-delays-us = <0 10000 1000000>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -146,6 +137,16 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */
+ reset-assert-us = <10000>;
+ /* wait 1s after reset, otherwise fail to read phy id */
+ reset-deassert-us = <1000000>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v0>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
index 5f1c4f573d3e..358ed5f1b1c1 100644
--- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
+++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
@@ -115,14 +115,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -145,6 +141,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts
index 7449aac3f43b..413505f45a81 100644
--- a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts
+++ b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts
@@ -76,13 +76,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -99,6 +95,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts
index b90a7607d069..946c27278321 100644
--- a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts
+++ b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts
@@ -97,10 +97,12 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
+};
+&gmac_mdio {
phy1: ethernet-phy@1 {
reg = <1>;
};
diff --git a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
index 3e170cfac86a..17fa8901fc00 100644
--- a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
+++ b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
@@ -123,8 +123,6 @@
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
- /delete-property/#address-cells;
- /delete-property/#size-cells;
fixed-link {
speed = <1000>;
diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts
index b8a1aaaf3976..6bff9e731fc3 100644
--- a/arch/arm/boot/dts/sun7i-a20-m3.dts
+++ b/arch/arm/boot/dts/sun7i-a20-m3.dts
@@ -82,13 +82,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -111,6 +107,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts
index f0e6a96e5785..6f9c54b8e49a 100644
--- a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts
@@ -111,13 +111,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -202,6 +198,12 @@
};
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
index c34a83f666c7..230d62a6b8f1 100644
--- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
@@ -105,18 +105,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy3>;
+ phy-handle = <&phy3>;
phy-mode = "rgmii";
phy-supply = <&reg_vcc3v3>;
-
- snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 1000000>;
status = "okay";
-
- phy3: ethernet-phy@3 {
- reg = <3>;
- };
};
&hdmi {
@@ -161,6 +153,16 @@
status = "okay";
};
+&gmac_mdio {
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */
+ reset-assert-us = <10000>;
+ /* wait 1s after reset, otherwise fail to read phy id */
+ reset-deassert-us = <1000000>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
index e40dd47df8ce..2adbac860119 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
@@ -106,13 +106,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -149,6 +145,12 @@
};
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
index 56f451c07f93..9ba62774e89a 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
@@ -111,13 +111,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -154,6 +150,12 @@
vref-supply = <&reg_vcc3v0>;
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index 0dcba070444a..359bd0d5b3b1 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -118,13 +118,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>, <&gmac_txerr>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -215,6 +211,12 @@
};
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts
index 9628041bb3a3..2e328d2cefc1 100644
--- a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts
+++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts
@@ -120,14 +120,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -158,6 +154,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts
index 7b3532665c28..d75b2e2bab28 100644
--- a/arch/arm/boot/dts/sun7i-a20-orangepi.dts
+++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts
@@ -96,14 +96,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_gmac_3v3>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -124,6 +120,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
index 173b676436e9..fce2f7fcd084 100644
--- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
+++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
@@ -114,13 +114,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&hdmi {
@@ -149,6 +145,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
index 14a88aa16a97..cc8271d777b8 100644
--- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
+++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
@@ -122,13 +122,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_mii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -149,6 +145,12 @@
status = "okay";
};
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts
index f8475a39777b..3bfae98f3cc3 100644
--- a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts
+++ b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts
@@ -81,13 +81,9 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c0 {
@@ -110,6 +106,12 @@
#include "axp209.dtsi"
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 9ad8e445b240..49380de754a9 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -376,6 +376,17 @@
num-cs = <1>;
};
+ csi0: csi@1c09000 {
+ compatible = "allwinner,sun7i-a20-csi0";
+ reg = <0x01c09000 0x1000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>,
+ <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
+ clock-names = "bus", "mod", "isp", "ram";
+ resets = <&ccu RST_CSI0>;
+ status = "disabled";
+ };
+
emac: ethernet@1c0b000 {
compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>;
@@ -775,6 +786,20 @@
};
/omit-if-no-ref/
+ csi0_8bits_pins: csi-8bits-pins {
+ pins = "PE0", "PE2", "PE3", "PE4", "PE5",
+ "PE6", "PE7", "PE8", "PE9", "PE10",
+ "PE11";
+ function = "csi0";
+ };
+
+ /omit-if-no-ref/
+ csi0_clk_pin: csi-clk-pin {
+ pins = "PE1";
+ function = "csi0";
+ };
+
+ /omit-if-no-ref/
emac_pa_pins: emac-pa-pins {
pins = "PA0", "PA1", "PA2",
"PA3", "PA4", "PA5", "PA6",
@@ -1115,6 +1140,8 @@
wdt: watchdog@1c20c90 {
compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
rtc: rtc@1c20d00 {
@@ -1437,8 +1464,12 @@
snps,fixed-burst;
snps,force_sf_dma_mode;
status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
+
+ gmac_mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
hstimer@1c60000 {
diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
index af2fa694a467..52eed0ae3607 100644
--- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
@@ -441,7 +441,7 @@
};
timer@1c20c00 {
- compatible = "allwinner,sun4i-a10-timer";
+ compatible = "allwinner,sun8i-a23-timer";
reg = <0x01c20c00 0xa0>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -452,6 +452,7 @@
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
pwm: pwm@1c21400 {
diff --git a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
index 5659c63d7d77..51097c77a152 100644
--- a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
+++ b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
@@ -63,7 +63,7 @@
};
&panel {
- compatible = "bananapi,s070wv20-ct16", "simple-panel";
+ compatible = "bananapi,s070wv20-ct16";
};
&tcon0_out {
diff --git a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
index ea299d3d84d0..fb928503ad45 100644
--- a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
@@ -60,6 +60,17 @@
stdout-path = "serial0:115200n8";
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -153,6 +164,10 @@
cpu-supply = <&reg_dcdc3>;
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
/* GL830 USB-to-SATA bridge here */
status = "okay";
@@ -172,6 +187,16 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&mdio {
rgmii_phy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index ada6d08bc540..523be6611c50 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -314,10 +314,10 @@
display_clocks: clock@1000000 {
compatible = "allwinner,sun8i-a83t-de2-clk";
reg = <0x01000000 0x100000>;
- clocks = <&ccu CLK_PLL_DE>,
- <&ccu CLK_BUS_DE>;
- clock-names = "mod",
- "bus";
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_PLL_DE>;
+ clock-names = "bus",
+ "mod";
resets = <&ccu RST_BUS_DE>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -806,7 +806,7 @@
};
timer@1c20c00 {
- compatible = "allwinner,sun4i-a10-timer";
+ compatible = "allwinner,sun8i-a23-timer";
reg = <0x01c20c00 0xa0>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -1037,7 +1037,7 @@
resets = <&ccu RST_BUS_HDMI1>;
reset-names = "ctrl";
phys = <&hdmi_phy>;
- phy-names = "hdmi-phy";
+ phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
status = "disabled";
@@ -1096,7 +1096,7 @@
r_cir: ir@1f02000 {
compatible = "allwinner,sun8i-a83t-ir",
- "allwinner,sun5i-a13-ir";
+ "allwinner,sun6i-a31-ir";
clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
clock-names = "apb", "ir";
resets = <&r_ccu RST_APB0_IR>;
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 6007d0cc252d..bde068111b85 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -119,10 +119,10 @@
compatible = "allwinner,sun8i-r40-de2-clk",
"allwinner,sun8i-h3-de2-clk";
reg = <0x01000000 0x100000>;
- clocks = <&ccu CLK_DE>,
- <&ccu CLK_BUS_DE>;
- clock-names = "mod",
- "bus";
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_DE>;
+ clock-names = "bus",
+ "mod";
resets = <&ccu RST_BUS_DE>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -404,6 +404,8 @@
wdt: watchdog@1c20c90 {
compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
uart0: serial@1c28000 {
@@ -808,7 +810,7 @@
resets = <&ccu RST_BUS_HDMI1>;
reset-names = "ctrl";
phys = <&hdmi_phy>;
- phy-names = "hdmi-phy";
+ phy-names = "phy";
status = "disabled";
ports {
diff --git a/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts
new file mode 100644
index 000000000000..d18192d51d1b
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+/dts-v1/;
+#include "sun8i-v3.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Sipeed Lichee Zero Plus";
+ compatible = "sipeed,lichee-zero-plus", "sochip,s3",
+ "allwinner,sun8i-v3";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ vmmc-supply = <&reg_vcc3v3>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/sun8i-v3.dtsi b/arch/arm/boot/dts/sun8i-v3.dtsi
new file mode 100644
index 000000000000..6ae8645ade50
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-v3.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include "sun8i-v3s.dtsi"
+
+&ccu {
+ compatible = "allwinner,sun8i-v3-ccu";
+};
+
+&pio {
+ compatible = "allwinner,sun8i-v3-pinctrl";
+};
diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index d7aef128acb3..23ba56df38f7 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -106,10 +106,10 @@
display_clocks: clock@1000000 {
compatible = "allwinner,sun8i-v3s-de2-clk";
reg = <0x01000000 0x100000>;
- clocks = <&ccu CLK_DE>,
- <&ccu CLK_BUS_DE>;
- clock-names = "mod",
- "bus";
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_DE>;
+ clock-names = "bus",
+ "mod";
resets = <&ccu RST_BUS_DE>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -327,10 +327,11 @@
};
timer@1c20c00 {
- compatible = "allwinner,sun4i-a10-timer";
+ compatible = "allwinner,sun8i-v3s-timer";
reg = <0x01c20c00 0xa0>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc24M>;
};
@@ -338,6 +339,7 @@
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
lradc: lradc@1c22800 {
diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index 18156ffa3ce9..d3b337b043a1 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -128,14 +128,10 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_cldo1>;
status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
};
&i2c3 {
@@ -144,6 +140,12 @@
status = "okay";
};
+&mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index 2ed28d9e2787..bbc6335e5631 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -123,11 +123,13 @@
&gmac {
pinctrl-names = "default";
pinctrl-0 = <&gmac_rgmii_pins>;
- phy = <&phy1>;
+ phy-handle = <&phy1>;
phy-mode = "rgmii";
phy-supply = <&reg_cldo1>;
status = "okay";
+};
+&mdio {
phy1: ethernet-phy@1 {
reg = <1>;
};
diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi
index 0c1eec9000e3..c34d505c7efe 100644
--- a/arch/arm/boot/dts/sun9i-a80.dtsi
+++ b/arch/arm/boot/dts/sun9i-a80.dtsi
@@ -331,8 +331,12 @@
snps,fixed-burst;
snps,force_sf_dma_mode;
status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
ehci0: usb@a00000 {
@@ -1167,7 +1171,7 @@
};
r_ir: ir@8002000 {
- compatible = "allwinner,sun5i-a13-ir";
+ compatible = "allwinner,sun6i-a31-ir";
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&r_ir_pins>;
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 84977d4eb97a..eba190b3f9de 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -114,10 +114,10 @@
display_clocks: clock@1000000 {
/* compatible is in per SoC .dtsi file */
reg = <0x01000000 0x100000>;
- clocks = <&ccu CLK_DE>,
- <&ccu CLK_BUS_DE>;
- clock-names = "mod",
- "bus";
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_DE>;
+ clock-names = "bus",
+ "mod";
resets = <&ccu RST_BUS_DE>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -484,7 +484,7 @@
};
timer@1c20c00 {
- compatible = "allwinner,sun4i-a10-timer";
+ compatible = "allwinner,sun8i-a23-timer";
reg = <0x01c20c00 0xa0>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -574,6 +574,7 @@
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
spdif: spdif@1c21000 {
@@ -765,7 +766,7 @@
resets = <&ccu RST_BUS_HDMI1>;
reset-names = "ctrl";
phys = <&hdmi_phy>;
- phy-names = "hdmi-phy";
+ phy-names = "phy";
status = "disabled";
ports {
@@ -822,7 +823,7 @@
};
ir: ir@1f02000 {
- compatible = "allwinner,sun5i-a13-ir";
+ compatible = "allwinner,sun6i-a31-ir";
clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
clock-names = "apb", "ir";
resets = <&r_ccu RST_APB0_IR>;
diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index d6a1fc269241..dfae90adbb7c 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ARM Ltd. Versatile Express
*
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index 8e57e15307e2..2e29d7790497 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -451,4 +451,4 @@
};
};
};
-}; \ No newline at end of file
+};
diff --git a/arch/arm/boot/dts/vf610-bk4.dts b/arch/arm/boot/dts/vf610-bk4.dts
index 3fa0cbe456db..0f3870d3b099 100644
--- a/arch/arm/boot/dts/vf610-bk4.dts
+++ b/arch/arm/boot/dts/vf610-bk4.dts
@@ -246,13 +246,13 @@
reg = <0>;
};
- n25q128a13_2: flash@1 {
+ n25q128a13_2: flash@2 {
compatible = "n25q128a13", "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <66000000>;
spi-rx-bus-width = <2>;
- reg = <1>;
+ reg = <2>;
};
};
diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/vf610-zii-cfu1.dts
index 9466913693ac..28732249cfc0 100644
--- a/arch/arm/boot/dts/vf610-zii-cfu1.dts
+++ b/arch/arm/boot/dts/vf610-zii-cfu1.dts
@@ -207,7 +207,7 @@
};
&i2c0 {
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c0>;
status = "okay";
@@ -236,6 +236,18 @@
};
};
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ watchdog@38 {
+ compatible = "zii,rave-wdt";
+ reg = <0x38>;
+ };
+};
+
&snvsrtc {
status = "disabled";
};
@@ -304,6 +316,13 @@
>;
};
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ VF610_PAD_PTB16__I2C1_SCL 0x37ff
+ VF610_PAD_PTB17__I2C1_SDA 0x37ff
+ >;
+ };
+
pinctrl_leds_debug: pinctrl-leds-debug {
fsl,pins = <
VF610_PAD_PTD3__GPIO_82 0x31c2
diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts
index d7019e89f588..dc8a5f37a1ef 100644
--- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts
+++ b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts
@@ -565,6 +565,8 @@
#gpio-cells = <2>;
reg = <0x20>;
gpio-controller;
+ interrupt-parent = <&gpio1>;
+ interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
};
lm75@4e {
@@ -777,7 +779,8 @@
VF610_PAD_PTB15__I2C0_SDA 0x37ff
>;
};
- pinctrl_i2c1: i2c1grp {
+
+ pinctrl_i2c1: i2c1grp {
fsl,pins = <
VF610_PAD_PTB16__I2C1_SCL 0x37ff
VF610_PAD_PTB17__I2C1_SDA 0x37ff
@@ -791,13 +794,6 @@
>;
};
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- VF610_PAD_PTA30__I2C3_SCL 0x37ff
- VF610_PAD_PTA31__I2C3_SDA 0x37ff
- >;
- };
-
pinctrl_leds_debug: pinctrl-leds-debug {
fsl,pins = <
VF610_PAD_PTB26__GPIO_96 0x31c2
diff --git a/arch/arm/boot/dts/vf610-zii-spb4.dts b/arch/arm/boot/dts/vf610-zii-spb4.dts
index 9dde83ccb9d1..77e1484211e4 100644
--- a/arch/arm/boot/dts/vf610-zii-spb4.dts
+++ b/arch/arm/boot/dts/vf610-zii-spb4.dts
@@ -316,13 +316,6 @@
>;
};
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- VF610_PAD_PTB16__I2C1_SCL 0x37ff
- VF610_PAD_PTB17__I2C1_SDA 0x37ff
- >;
- };
-
pinctrl_leds_debug: pinctrl-leds-debug {
fsl,pins = <
VF610_PAD_PTD3__GPIO_82 0x31c2
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 60130bd7b182..6edb961bd6c1 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -8,7 +8,7 @@
*/
#include <linux/device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
diff --git a/arch/arm/configs/acs5k_defconfig b/arch/arm/configs/acs5k_defconfig
deleted file mode 100644
index bcb8bda09158..000000000000
--- a/arch/arm/configs/acs5k_defconfig
+++ /dev/null
@@ -1,77 +0,0 @@
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_KS8695=y
-CONFIG_MACH_KS8695=y
-CONFIG_MACH_DSM320=y
-CONFIG_MACH_ACS5K=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCI=y
-CONFIG_PCI_DEBUG=y
-CONFIG_PCCARD=y
-CONFIG_YENTA=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_KS8695_ETHER=y
-CONFIG_PRISM54=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_KS8695=y
-CONFIG_SERIAL_KS8695_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PCA953X=y
-CONFIG_WATCHDOG=y
-CONFIG_KS8695_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_PCF8563=y
-CONFIG_EXT2_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/acs5k_tiny_defconfig b/arch/arm/configs/acs5k_tiny_defconfig
deleted file mode 100644
index e802cdebfd0b..000000000000
--- a/arch/arm/configs/acs5k_tiny_defconfig
+++ /dev/null
@@ -1,69 +0,0 @@
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_KS8695=y
-CONFIG_MACH_ACS5K=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyAM0,115200 init=/bin/sh"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_KS8695_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_KS8695=y
-CONFIG_SERIAL_KS8695_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PCA953X=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_KS8695_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_PCF8563=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_SQUASHFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index 019828d7b251..1857df992484 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -20,20 +20,11 @@ CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_SLAB_FREELIST_RANDOM=y
-CONFIG_JUMP_LABEL=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_GCC_PLUGINS=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEBUG_FS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_MQ_IOSCHED_DEADLINE is not set
-# CONFIG_MQ_IOSCHED_KYBER is not set
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_ASPEED=y
CONFIG_MACH_ASPEED_G4=y
CONFIG_VMSPLIT_2G=y
CONFIG_AEABI=y
-# CONFIG_COMPACTION is not set
CONFIG_UACCESS_WITH_MEMCPY=y
CONFIG_SECCOMP=y
# CONFIG_ATAGS is not set
@@ -42,7 +33,15 @@ CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_KEXEC=y
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_JUMP_LABEL=y
+CONFIG_STRICT_KERNEL_RWX=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
@@ -51,18 +50,11 @@ CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_ADVANCED is not set
CONFIG_VLAN_8021Q=y
CONFIG_NET_NCSI=y
-CONFIG_BPF_STREAM_PARSER=y
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
@@ -140,7 +132,6 @@ CONFIG_ASPEED_BT_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA9541=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_ASPEED=y
@@ -204,6 +195,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_PCF8523=y
@@ -218,13 +210,13 @@ CONFIG_IIO=y
CONFIG_ASPEED_ADC=y
CONFIG_MAX1363=y
CONFIG_BMP280=y
+CONFIG_RAS=y
CONFIG_FSI=y
CONFIG_FSI_MASTER_GPIO=y
CONFIG_FSI_MASTER_HUB=y
CONFIG_FSI_MASTER_AST_CF=y
CONFIG_FSI_SCOM=y
CONFIG_FSI_SBEFIFO=y
-CONFIG_FIRMWARE_MEMMAP=y
CONFIG_FANOTIFY=y
CONFIG_OVERLAY_FS=y
CONFIG_TMPFS=y
@@ -237,6 +229,17 @@ CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
+# CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_USER_API_HASH=y
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
@@ -255,14 +258,3 @@ CONFIG_FUNCTION_TRACER=y
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_DEBUG_WX=y
CONFIG_DEBUG_USER=y
-CONFIG_HARDENED_USERCOPY=y
-CONFIG_FORTIFY_SOURCE=y
-# CONFIG_CRYPTO_ECHAINIV is not set
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_USER_API_HASH=y
-# CONFIG_CRYPTO_HW is not set
-# CONFIG_XZ_DEC_X86 is not set
-# CONFIG_XZ_DEC_POWERPC is not set
-# CONFIG_XZ_DEC_IA64 is not set
-# CONFIG_XZ_DEC_SPARC is not set
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 28fe392c7dfa..597536cc9573 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -20,29 +20,33 @@ CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_SLAB_FREELIST_RANDOM=y
-CONFIG_JUMP_LABEL=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_GCC_PLUGINS=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEBUG_FS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_MQ_IOSCHED_DEADLINE is not set
-# CONFIG_MQ_IOSCHED_KYBER is not set
CONFIG_ARCH_MULTI_V6=y
-# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_ASPEED=y
CONFIG_MACH_ASPEED_G5=y
+CONFIG_MACH_ASPEED_G6=y
# CONFIG_CACHE_L2X0 is not set
+CONFIG_SMP=y
+# CONFIG_ARM_CPU_TOPOLOGY is not set
CONFIG_VMSPLIT_2G=y
-# CONFIG_COMPACTION is not set
+CONFIG_NR_CPUS=2
+CONFIG_HIGHMEM=y
CONFIG_UACCESS_WITH_MEMCPY=y
CONFIG_SECCOMP=y
# CONFIG_ATAGS is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_KEXEC=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_SUSPEND is not set
+# CONFIG_COMPACTION is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
@@ -50,19 +54,20 @@ CONFIG_UNIX=y
CONFIG_UNIX_DIAG=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_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_ADVANCED is not set
CONFIG_VLAN_8021Q=y
CONFIG_NET_NCSI=y
-CONFIG_BPF_STREAM_PARSER=y
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
@@ -145,6 +150,7 @@ CONFIG_I2C_MUX_PCA9541=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_ASPEED=y
CONFIG_I2C_FSI=y
+CONFIG_SPI=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_ASPEED=y
@@ -195,6 +201,10 @@ CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ASPEED=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_CLASS_FLASH=y
@@ -228,7 +238,6 @@ CONFIG_FSI_MASTER_HUB=y
CONFIG_FSI_MASTER_AST_CF=y
CONFIG_FSI_SCOM=y
CONFIG_FSI_SBEFIFO=y
-CONFIG_FIRMWARE_MEMMAP=y
CONFIG_FANOTIFY=y
CONFIG_OVERLAY_FS=y
CONFIG_TMPFS=y
@@ -241,6 +250,16 @@ CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_USER_API_HASH=y
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
@@ -259,14 +278,3 @@ CONFIG_FUNCTION_TRACER=y
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_DEBUG_WX=y
CONFIG_DEBUG_USER=y
-CONFIG_HARDENED_USERCOPY=y
-CONFIG_FORTIFY_SOURCE=y
-# CONFIG_CRYPTO_ECHAINIV is not set
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_USER_API_HASH=y
-# CONFIG_CRYPTO_HW is not set
-# CONFIG_XZ_DEC_X86 is not set
-# CONFIG_XZ_DEC_POWERPC is not set
-# CONFIG_XZ_DEC_IA64 is not set
-# CONFIG_XZ_DEC_SPARC is not set
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index dcf7610cfe55..519ff58e67b3 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -37,6 +37,14 @@ CONFIG_CMA=y
CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
CONFIG_VFP=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SUSPEND is not set
@@ -132,6 +140,7 @@ CONFIG_DMA_BCM2835=y
CONFIG_STAGING=y
CONFIG_SND_BCM2835=m
CONFIG_VIDEO_BCM2835=m
+CONFIG_CLK_RASPBERRYPI=y
CONFIG_MAILBOX=y
CONFIG_BCM2835_MBOX=y
# CONFIG_IOMMU_SUPPORT is not set
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 9a32a8c0f873..b34970ce6b31 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -17,6 +17,9 @@ CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_MULTIPLATFORM=y
+CONFIG_ARCH_MULTI_V7=n
+CONFIG_ARCH_MULTI_V5=y
CONFIG_ARCH_DAVINCI=y
CONFIG_ARCH_DAVINCI_DM644x=y
CONFIG_ARCH_DAVINCI_DM355=y
@@ -129,9 +132,11 @@ CONFIG_SPI=y
CONFIG_SPI_DAVINCI=m
CONFIG_PINCTRL_DA850_PUPD=m
CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_RESET_CONTROLLER=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_SYSCON_REBOOT_MODE=m
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 2e6a863d25aa..08db1c83eb2d 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -92,9 +92,12 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_SCSI=y
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_ATA_SFF is not set
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index a53b29251ed4..9bfffbe22d53 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -60,6 +60,7 @@ CONFIG_ARM_IMX6Q_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_PM_DEBUG=y
@@ -272,6 +273,7 @@ CONFIG_VIDEO_IMX_PXP=y
CONFIG_VIDEO_ADV7180=m
CONFIG_VIDEO_OV2680=m
CONFIG_VIDEO_OV5640=m
+CONFIG_VIDEO_OV5645=m
CONFIG_IMX_IPUV3_CORE=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_LVDS=y
diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig
deleted file mode 100644
index 30cdb287e1b4..000000000000
--- a/arch/arm/configs/iop13xx_defconfig
+++ /dev/null
@@ -1,118 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_IOP13XX=y
-CONFIG_MACH_IQ81340SC=y
-CONFIG_MACH_IQ81340MC=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=bootp root=nfs console=ttyS0,115200 nfsroot=,tcp,v3,wsize=8192,rsize=8192"
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_MTD=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=2
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_ISCSI_ATTRS=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID10=y
-CONFIG_MD_RAID456=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_NETDEVICES=y
-CONFIG_E1000=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_IOP3XX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DMADEVICES=y
-CONFIG_INTEL_IOP_ADMA=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_TMPFS=y
-CONFIG_ECRYPT_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
-CONFIG_DEBUG_USER=y
-CONFIG_KEYS=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRC_CCITT=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/iop33x_defconfig b/arch/arm/configs/iop33x_defconfig
deleted file mode 100644
index 089eca43214a..000000000000
--- a/arch/arm/configs/iop33x_defconfig
+++ /dev/null
@@ -1,85 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_IOP33X=y
-CONFIG_ARCH_IQ80331=y
-CONFIG_MACH_IQ80332=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp cachepolicy=writealloc iop3xx_init_atu=y"
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_MTD=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID456=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_NETDEVICES=y
-CONFIG_E1000=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IOP3XX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DMADEVICES=y
-CONFIG_INTEL_IOP_ADMA=y
-CONFIG_NET_DMA=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_LL_UART_8250=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/ks8695_defconfig b/arch/arm/configs/ks8695_defconfig
deleted file mode 100644
index df62d4dfbbb7..000000000000
--- a/arch/arm/configs/ks8695_defconfig
+++ /dev/null
@@ -1,67 +0,0 @@
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_KS8695=y
-CONFIG_MACH_KS8695=y
-CONFIG_MACH_DSM320=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCI=y
-CONFIG_PCI_DEBUG=y
-CONFIG_PCCARD=y
-CONFIG_YENTA=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_PRISM54=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_KS8695=y
-CONFIG_SERIAL_KS8695_CONSOLE=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_EXT2_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig
index 0cdc6c7974b3..09deb57db942 100644
--- a/arch/arm/configs/lpc32xx_defconfig
+++ b/arch/arm/configs/lpc32xx_defconfig
@@ -12,6 +12,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
+# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_LPC32XX=y
CONFIG_AEABI=y
CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -93,6 +94,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PNX=y
+CONFIG_GPIO_LPC32XX=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
index 201237002c65..bd018873e47a 100644
--- a/arch/arm/configs/multi_v5_defconfig
+++ b/arch/arm/configs/multi_v5_defconfig
@@ -14,6 +14,18 @@ CONFIG_ARCH_ASPEED=y
CONFIG_MACH_ASPEED_G4=y
CONFIG_ARCH_AT91=y
CONFIG_SOC_AT91SAM9=y
+CONFIG_ARCH_DAVINCI=y
+CONFIG_ARCH_DAVINCI_DM644x=y
+CONFIG_ARCH_DAVINCI_DM355=y
+CONFIG_ARCH_DAVINCI_DM646x=y
+CONFIG_ARCH_DAVINCI_DA830=y
+CONFIG_ARCH_DAVINCI_DA850=y
+CONFIG_ARCH_DAVINCI_DM365=y
+CONFIG_MACH_SFFSDR=y
+CONFIG_MACH_NEUROS_OSD2=y
+CONFIG_MACH_DM355_LEOPARD=y
+CONFIG_MACH_MITYOMAPL138=y
+CONFIG_MACH_OMAPL138_HAWKBOARD=y
CONFIG_ARCH_MXC=y
CONFIG_MACH_MX21ADS=y
CONFIG_MACH_MX27ADS=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 6a40bc2ef271..13ba53286901 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -9,6 +9,8 @@ CONFIG_ARCH_VIRT=y
CONFIG_ARCH_ALPINE=y
CONFIG_ARCH_ARTPEC=y
CONFIG_MACH_ARTPEC6=y
+CONFIG_ARCH_ASPEED=y
+CONFIG_MACH_ASPEED_G6=y
CONFIG_ARCH_AT91=y
CONFIG_SOC_SAMA5D2=y
CONFIG_SOC_SAMA5D3=y
@@ -102,6 +104,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_IMX6Q_CPUFREQ=y
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
CONFIG_QORIQ_CPUFREQ=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
@@ -197,7 +200,9 @@ CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_MTD_NAND_BRCMNAND=y
CONFIG_MTD_NAND_VF610_NFC=y
CONFIG_MTD_NAND_DAVINCI=y
+CONFIG_MTD_NAND_STM32_FMC2=y
CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_ASPEED_SMC=m
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
@@ -304,7 +309,11 @@ CONFIG_INPUT_STPMIC1_ONKEY=y
CONFIG_SERIO_AMBAKMI=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_ASPEED_VUART=m
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_DW=y
@@ -349,6 +358,8 @@ CONFIG_SERIAL_STM32=y
CONFIG_SERIAL_STM32_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
+CONFIG_ASPEED_KCS_IPMI_BMC=m
+CONFIG_ASPEED_BT_IPMI_BMC=m
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_ST=y
CONFIG_TCG_TPM=m
@@ -358,6 +369,7 @@ CONFIG_I2C_ARB_GPIO_CHALLENGE=m
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_MUX_PINCTRL=y
CONFIG_I2C_DEMUX_PINCTRL=y
+CONFIG_I2C_ASPEED=m
CONFIG_I2C_AT91=m
CONFIG_I2C_BCM2835=y
CONFIG_I2C_CADENCE=y
@@ -403,6 +415,7 @@ CONFIG_SPI_SH_MSIOF=m
CONFIG_SPI_SH_HSPI=y
CONFIG_SPI_SIRF=y
CONFIG_SPI_STM32=m
+CONFIG_SPI_STM32_QSPI=m
CONFIG_SPI_SUN4I=y
CONFIG_SPI_SUN6I=y
CONFIG_SPI_TEGRA114=y
@@ -461,6 +474,7 @@ CONFIG_CHARGER_MAX77693=m
CONFIG_CHARGER_MAX8997=m
CONFIG_CHARGER_MAX8998=m
CONFIG_CHARGER_TPS65090=y
+CONFIG_SENSORS_ASPEED=m
CONFIG_SENSORS_IIO_HWMON=y
CONFIG_SENSORS_LM90=y
CONFIG_SENSORS_LM95245=y
@@ -559,7 +573,7 @@ CONFIG_REGULATOR_MAX8997=m
CONFIG_REGULATOR_MAX8998=m
CONFIG_REGULATOR_MAX77686=y
CONFIG_REGULATOR_MAX77693=m
-CONFIG_REGULATOR_MAX77802=m
+CONFIG_REGULATOR_MAX77802=y
CONFIG_REGULATOR_PALMAS=y
CONFIG_REGULATOR_PBIAS=y
CONFIG_REGULATOR_PWM=y
@@ -569,6 +583,7 @@ CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_RN5T618=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_S5M8767=y
+CONFIG_REGULATOR_STM32_BOOSTER=m
CONFIG_REGULATOR_STM32_VREFBUF=m
CONFIG_REGULATOR_STPMIC1=y
CONFIG_REGULATOR_TI_ABB=y
@@ -590,6 +605,7 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_ASPEED=m
CONFIG_VIDEO_STM32_DCMI=m
CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS=m
CONFIG_VIDEO_S5P_FIMC=m
@@ -634,6 +650,7 @@ CONFIG_DRM_ATMEL_HLCDC=m
CONFIG_DRM_RCAR_DU=m
CONFIG_DRM_RCAR_LVDS=y
CONFIG_DRM_SUN4I=m
+CONFIG_DRM_MSM=m
CONFIG_DRM_FSL_DCU=m
CONFIG_DRM_TEGRA=y
CONFIG_DRM_STM=m
@@ -659,6 +676,7 @@ CONFIG_DRM_MXSFB=m
CONFIG_DRM_PL111=m
CONFIG_DRM_LIMA=m
CONFIG_DRM_PANFROST=m
+CONFIG_DRM_ASPEED_GFX=m
CONFIG_FB_EFI=y
CONFIG_FB_WM8505=y
CONFIG_FB_SH_MOBILE_LCDC=y
@@ -758,6 +776,7 @@ CONFIG_USB_MXS_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_FSL_USB2=y
CONFIG_USB_RENESAS_USBHS_UDC=m
+CONFIG_USB_ASPEED_VHUB=m
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
@@ -866,6 +885,7 @@ CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_ST_LPC=y
CONFIG_RTC_DRV_STM32=y
CONFIG_RTC_DRV_CPCAP=m
+CONFIG_RTC_DRV_ASPEED=m
CONFIG_DMADEVICES=y
CONFIG_AT_HDMAC=y
CONFIG_AT_XDMAC=y
@@ -902,6 +922,7 @@ CONFIG_STAGING_BOARD=y
CONFIG_COMMON_CLK_MAX77686=y
CONFIG_COMMON_CLK_RK808=m
CONFIG_COMMON_CLK_S2MPS11=m
+CONFIG_CLK_RASPBERRYPI=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_CLK_RPM=y
CONFIG_APQ_MMCC_8084=y
@@ -915,6 +936,9 @@ CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_REMOTEPROC=m
CONFIG_ST_REMOTEPROC=m
CONFIG_RPMSG_VIRTIO=m
+CONFIG_ASPEED_LPC_CTRL=m
+CONFIG_ASPEED_LPC_SNOOP=m
+CONFIG_ASPEED_P2A_CTRL=m
CONFIG_RASPBERRYPI_POWER=y
CONFIG_QCOM_GSBI=y
CONFIG_QCOM_PM=y
@@ -947,6 +971,7 @@ CONFIG_ARM_TEGRA_DEVFREQ=m
CONFIG_TI_AEMIF=y
CONFIG_IIO=y
CONFIG_IIO_SW_TRIGGER=y
+CONFIG_ASPEED_ADC=m
CONFIG_AT91_ADC=m
CONFIG_AT91_SAMA5D2_ADC=m
CONFIG_BERLIN2_ADC=m
diff --git a/arch/arm/configs/nuc910_defconfig b/arch/arm/configs/nuc910_defconfig
deleted file mode 100644
index 63dba62c3326..000000000000
--- a/arch/arm/configs/nuc910_defconfig
+++ /dev/null
@@ -1,51 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_RELAY=y
-CONFIG_USER_NS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_ARCH_W90X900=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 rdinit=/sbin/init mem=64M"
-CONFIG_KEXEC=y
-CONFIG_FPE_NWFPE=y
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_STORAGE=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_ROMFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/nuc950_defconfig b/arch/arm/configs/nuc950_defconfig
deleted file mode 100644
index cb5a8788ebe8..000000000000
--- a/arch/arm/configs/nuc950_defconfig
+++ /dev/null
@@ -1,67 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_RELAY=y
-CONFIG_USER_NS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_ARCH_W90X900=y
-# CONFIG_MACH_W90P910EVB is not set
-CONFIG_MACH_W90P950EVB=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 rdinit=/sbin/init mem=64M"
-CONFIG_KEXEC=y
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=y
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_NUC900=y
-CONFIG_GPM1040A0_320X240=y
-CONFIG_FB_NUC900_DEBUG=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_STORAGE=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_ROMFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_FS=y
diff --git a/arch/arm/configs/nuc960_defconfig b/arch/arm/configs/nuc960_defconfig
deleted file mode 100644
index f7af84e23a05..000000000000
--- a/arch/arm/configs/nuc960_defconfig
+++ /dev/null
@@ -1,57 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_RELAY=y
-CONFIG_USER_NS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_ARCH_W90X900=y
-# CONFIG_MACH_W90P910EVB is not set
-CONFIG_MACH_W90N960EVB=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 rdinit=/sbin/init mem=64M"
-CONFIG_KEXEC=y
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=y
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_STORAGE=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_ROMFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig
index 34433bf5885d..02f1e7b7c8f6 100644
--- a/arch/arm/configs/qcom_defconfig
+++ b/arch/arm/configs/qcom_defconfig
@@ -147,6 +147,7 @@ CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_DRM=y
+CONFIG_DRM_MSM=m
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index e6b98b6eb88d..822cddfbf1af 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -4,17 +4,9 @@ CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_U8500=y
-CONFIG_MACH_HREFV60=y
-CONFIG_MACH_SNOWBALL=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
@@ -25,6 +17,11 @@ CONFIG_CPU_IDLE=y
CONFIG_ARM_U8500_CPUIDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -47,7 +44,6 @@ CONFIG_SMSC911X=y
CONFIG_SMSC_PHY=y
CONFIG_CW1200=y
CONFIG_CW1200_WLAN_SDIO=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
@@ -63,7 +59,6 @@ CONFIG_RMI4_CORE=y
CONFIG_RMI4_I2C=y
CONFIG_RMI4_F11=y
# CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -72,6 +67,7 @@ CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_STMPE=y
CONFIG_GPIO_TC3589X=y
+CONFIG_SENSORS_IIO_HWMON=y
CONFIG_THERMAL=y
CONFIG_CPU_THERMAL=y
CONFIG_WATCHDOG=y
@@ -79,6 +75,13 @@ CONFIG_MFD_STMPE=y
CONFIG_MFD_TC3589X=y
CONFIG_REGULATOR_AB8500=y
CONFIG_REGULATOR_GPIO=y
+CONFIG_DRM=y
+CONFIG_DRM_PANEL_SAMSUNG_S6D16D0=y
+CONFIG_DRM_LIMA=y
+CONFIG_DRM_MCDE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
@@ -87,6 +90,7 @@ CONFIG_SND_SOC_UX500_MACH_MOP500=y
CONFIG_USB=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_UX500=y
+CONFIG_MUSB_PIO_ONLY=y
CONFIG_AB8500_USB=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
@@ -103,6 +107,7 @@ CONFIG_RTC_DRV_AB8500=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
CONFIG_STE_DMA40=y
+CONFIG_HWSPINLOCK=y
CONFIG_HSEM_U8500=y
CONFIG_IIO=y
CONFIG_IIO_SW_TRIGGER=y
@@ -126,20 +131,19 @@ CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
+CONFIG_CRYPTO_DEV_UX500=y
+CONFIG_CRYPTO_DEV_UX500_CRYP=y
+CONFIG_CRYPTO_DEV_UX500_HASH=y
+CONFIG_CRYPTO_DEV_UX500_DEBUG=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_DEBUG_USER=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_SINK_TPIU=y
CONFIG_CORESIGHT_SINK_ETBV10=y
CONFIG_CORESIGHT_SOURCE_ETM3X=y
-CONFIG_CRYPTO_DEV_UX500=y
-CONFIG_CRYPTO_DEV_UX500_CRYP=y
-CONFIG_CRYPTO_DEV_UX500_HASH=y
-CONFIG_CRYPTO_DEV_UX500_DEBUG=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 7e0486ad1318..dba9355e2484 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -18,7 +18,9 @@ extern const struct dma_map_ops arm_coherent_dma_ops;
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
{
- return IS_ENABLED(CONFIG_MMU) ? &arm_dma_ops : NULL;
+ if (IS_ENABLED(CONFIG_MMU) && !IS_ENABLED(CONFIG_ARM_LPAE))
+ return &arm_dma_ops;
+ return NULL;
}
#ifdef __arch_page_to_dma
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h
index 2a786f54d8b8..8a0fae94d45e 100644
--- a/arch/arm/include/asm/topology.h
+++ b/arch/arm/include/asm/topology.h
@@ -5,26 +5,6 @@
#ifdef CONFIG_ARM_CPU_TOPOLOGY
#include <linux/cpumask.h>
-
-struct cputopo_arm {
- int thread_id;
- int core_id;
- int socket_id;
- cpumask_t thread_sibling;
- cpumask_t core_sibling;
-};
-
-extern struct cputopo_arm cpu_topology[NR_CPUS];
-
-#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id)
-#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
-#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
-#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
-
-void init_cpu_topology(void);
-void store_cpu_topology(unsigned int cpuid);
-const struct cpumask *cpu_coregroup_mask(int cpu);
-
#include <linux/arch_topology.h>
/* Replace task scheduler's default frequency-invariant accounting */
diff --git a/arch/arm/include/debug/ks8695.S b/arch/arm/include/debug/ks8695.S
deleted file mode 100644
index eb4d371b5eea..000000000000
--- a/arch/arm/include/debug/ks8695.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/include/debug/ks8695.S
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - Debug macros
- */
-
-#define KS8695_UART_PA 0x03ffe000
-#define KS8695_UART_VA 0xf00fe000
-#define KS8695_URTH (0x04)
-#define KS8695_URLS (0x14)
-#define URLS_URTE (1 << 6)
-#define URLS_URTHRE (1 << 5)
-
- .macro addruart, rp, rv, tmp
- ldr \rp, =KS8695_UART_PA @ physical base address
- ldr \rv, =KS8695_UART_VA @ virtual base address
- .endm
-
- .macro senduart, rd, rx
- str \rd, [\rx, #KS8695_URTH] @ Write to Transmit Holding Register
- .endm
-
- .macro busyuart, rd, rx
-1001: ldr \rd, [\rx, #KS8695_URLS] @ Read Line Status Register
- tst \rd, #URLS_URTE @ Holding & Shift registers empty?
- beq 1001b
- .endm
-
- .macro waituart, rd, rx
-1001: ldr \rd, [\rx, #KS8695_URLS] @ Read Line Status Register
- tst \rd, #URLS_URTHRE @ Holding Register empty?
- beq 1001b
- .endm
diff --git a/arch/arm/include/debug/renesas-scif.S b/arch/arm/include/debug/renesas-scif.S
index 1c5f795587fc..25f06663a9a4 100644
--- a/arch/arm/include/debug/renesas-scif.S
+++ b/arch/arm/include/debug/renesas-scif.S
@@ -11,7 +11,11 @@
#define SCIF_PHYS CONFIG_DEBUG_UART_PHYS
#define SCIF_VIRT ((SCIF_PHYS & 0x00ffffff) | 0xfd000000)
-#if CONFIG_DEBUG_UART_PHYS < 0xe6e00000
+#if defined(CONFIG_DEBUG_R7S9210_SCIF2) || defined(CONFIG_DEBUG_R7S9210_SCIF4)
+/* RZ/A2 SCIFA */
+#define FTDR 0x06
+#define FSR 0x08
+#elif CONFIG_DEBUG_UART_PHYS < 0xe6e00000
/* SCIFA */
#define FTDR 0x20
#define FSR 0x14
diff --git a/arch/arm/include/debug/ux500.S b/arch/arm/include/debug/ux500.S
index c626f89b3e4a..c516900947bb 100644
--- a/arch/arm/include/debug/ux500.S
+++ b/arch/arm/include/debug/ux500.S
@@ -20,21 +20,16 @@
#define U8500_UART0_PHYS_BASE (0x80120000)
#define U8500_UART1_PHYS_BASE (0x80121000)
#define U8500_UART2_PHYS_BASE (0x80007000)
-#define U8500_UART0_VIRT_BASE (0xf8120000)
-#define U8500_UART1_VIRT_BASE (0xf8121000)
-#define U8500_UART2_VIRT_BASE (0xf8007000)
#define __UX500_PHYS_UART(n) U8500_UART##n##_PHYS_BASE
-#define __UX500_VIRT_UART(n) U8500_UART##n##_VIRT_BASE
#endif
-#if !defined(__UX500_PHYS_UART) || !defined(__UX500_VIRT_UART)
+#if !defined(__UX500_PHYS_UART)
#error Unknown SOC
#endif
#define UX500_PHYS_UART(n) __UX500_PHYS_UART(n)
-#define UX500_VIRT_UART(n) __UX500_VIRT_UART(n)
#define UART_PHYS_BASE UX500_PHYS_UART(CONFIG_UX500_DEBUG_UART)
-#define UART_VIRT_BASE UX500_VIRT_UART(CONFIG_UX500_DEBUG_UART)
+#define UART_VIRT_BASE (0xfff07000)
.macro addruart, rp, rv, tmp
ldr \rp, =UART_PHYS_BASE @ no, physical address
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index af8b8e15f589..b0c195e3a06d 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -544,6 +544,7 @@ static int arch_build_bp_info(struct perf_event *bp,
if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE)
&& max_watchpoint_len >= 8)
break;
+ /* Else, fall through */
default:
return -EINVAL;
}
@@ -608,10 +609,12 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
/* Allow halfword watchpoints and breakpoints. */
if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
break;
+ /* Else, fall through */
case 3:
/* Allow single byte watchpoint. */
if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
break;
+ /* Else, fall through */
default:
ret = -EINVAL;
goto out;
@@ -861,6 +864,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
break;
case ARM_ENTRY_ASYNC_WATCHPOINT:
WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
+ /* Fall through */
case ARM_ENTRY_SYNC_WATCHPOINT:
watchpoint_handler(addr, fsr, regs);
break;
@@ -909,6 +913,7 @@ static bool core_has_os_save_restore(void)
ARM_DBG_READ(c1, c1, 4, oslsr);
if (oslsr & ARM_OSLSR_OSLM0)
return true;
+ /* Else, fall through */
default:
return false;
}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 09f6fdd41974..ab2568996ddb 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -596,6 +596,7 @@ static int do_signal(struct pt_regs *regs, int syscall)
switch (retval) {
case -ERESTART_RESTARTBLOCK:
restart -= 2;
+ /* Fall through */
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index aab8ba40ce38..4b0bab2607e4 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -264,15 +264,13 @@ int __cpu_disable(void)
return 0;
}
-static DECLARE_COMPLETION(cpu_died);
-
/*
* called on the thread which is asking for a CPU to be shutdown -
* waits until shutdown has completed, or it is timed out.
*/
void __cpu_die(unsigned int cpu)
{
- if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+ if (!cpu_wait_death(cpu, 5)) {
pr_err("CPU%u: cpu didn't die\n", cpu);
return;
}
@@ -319,7 +317,7 @@ void arch_cpu_idle_dead(void)
* this returns, power and/or clocks can be removed at any point
* from this CPU and its cache by platform_cpu_kill().
*/
- complete(&cpu_died);
+ (void)cpu_report_death();
/*
* Ensure that the cache lines associated with that completion are
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index d17cb1e6d679..5b9faba03afb 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -177,17 +177,6 @@ static inline void parse_dt_topology(void) {}
static inline void update_cpu_capacity(unsigned int cpuid) {}
#endif
- /*
- * cpu topology table
- */
-struct cputopo_arm cpu_topology[NR_CPUS];
-EXPORT_SYMBOL_GPL(cpu_topology);
-
-const struct cpumask *cpu_coregroup_mask(int cpu)
-{
- return &cpu_topology[cpu].core_sibling;
-}
-
/*
* The current assumption is that we can power gate each core independently.
* This will be superseded by DT binding once available.
@@ -197,32 +186,6 @@ const struct cpumask *cpu_corepower_mask(int cpu)
return &cpu_topology[cpu].thread_sibling;
}
-static void update_siblings_masks(unsigned int cpuid)
-{
- struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
- int cpu;
-
- /* update core and thread sibling masks */
- for_each_possible_cpu(cpu) {
- cpu_topo = &cpu_topology[cpu];
-
- if (cpuid_topo->socket_id != cpu_topo->socket_id)
- continue;
-
- cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
- if (cpu != cpuid)
- cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
-
- if (cpuid_topo->core_id != cpu_topo->core_id)
- continue;
-
- cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
- if (cpu != cpuid)
- cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
- }
- smp_wmb();
-}
-
/*
* store_cpu_topology is called at boot when only one cpu is running
* and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
@@ -230,7 +193,7 @@ static void update_siblings_masks(unsigned int cpuid)
*/
void store_cpu_topology(unsigned int cpuid)
{
- struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];
+ struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
unsigned int mpidr;
/* If the cpu topology has been already set, just return */
@@ -250,12 +213,12 @@ void store_cpu_topology(unsigned int cpuid)
/* core performance interdependency */
cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
- cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
+ cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
} else {
/* largely independent cores */
cpuid_topo->thread_id = -1;
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
}
} else {
/*
@@ -265,7 +228,7 @@ void store_cpu_topology(unsigned int cpuid)
*/
cpuid_topo->thread_id = -1;
cpuid_topo->core_id = 0;
- cpuid_topo->socket_id = -1;
+ cpuid_topo->package_id = -1;
}
update_siblings_masks(cpuid);
@@ -275,7 +238,7 @@ void store_cpu_topology(unsigned int cpuid)
pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
cpuid, cpu_topology[cpuid].thread_id,
cpu_topology[cpuid].core_id,
- cpu_topology[cpuid].socket_id, mpidr);
+ cpu_topology[cpuid].package_id, mpidr);
}
static inline int cpu_corepower_flags(void)
@@ -298,18 +261,7 @@ static struct sched_domain_topology_level arm_topology[] = {
*/
void __init init_cpu_topology(void)
{
- unsigned int cpu;
-
- /* init core mask and capacity */
- for_each_possible_cpu(cpu) {
- struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
-
- cpu_topo->thread_id = -1;
- cpu_topo->core_id = -1;
- cpu_topo->socket_id = -1;
- cpumask_clear(&cpu_topo->core_sibling);
- cpumask_clear(&cpu_topo->thread_sibling);
- }
+ reset_cpu_topology();
smp_wmb();
parse_dt_topology();
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index d2806bcff8bb..07745ee022a1 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -651,13 +651,22 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
static void reset_coproc_regs(struct kvm_vcpu *vcpu,
- const struct coproc_reg *table, size_t num)
+ const struct coproc_reg *table, size_t num,
+ unsigned long *bmap)
{
unsigned long i;
for (i = 0; i < num; i++)
- if (table[i].reset)
+ if (table[i].reset) {
+ int reg = table[i].reg;
+
table[i].reset(vcpu, &table[i]);
+ if (reg > 0 && reg < NR_CP15_REGS) {
+ set_bit(reg, bmap);
+ if (table[i].is_64bit)
+ set_bit(reg + 1, bmap);
+ }
+ }
}
static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
@@ -1432,17 +1441,15 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
{
size_t num;
const struct coproc_reg *table;
-
- /* Catch someone adding a register without putting in reset entry. */
- memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
+ DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
/* Generic chip reset first (so target could override). */
- reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
+ reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs), bmap);
table = get_target_table(vcpu->arch.target, &num);
- reset_coproc_regs(vcpu, table, num);
+ reset_coproc_regs(vcpu, table, num, bmap);
for (num = 1; num < NR_CP15_REGS; num++)
- WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+ WARN(!test_bit(num, bmap),
"Didn't reset vcpu_cp15(vcpu, %zi)", num);
}
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 1d5210eb4776..582925238d65 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -66,7 +66,7 @@ for_each_frame: tst frame, mask @ Check for address exceptions
1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
- teq r3, r2, lsr #10 @ instruction
+ teq r3, r2, lsr #11 @ instruction
subne r0, sv_pc, #4 @ allow for mov
subeq r0, sv_pc, #8 @ allow for mov + stmia
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
index a15c3a291386..56007b0b6120 100644
--- a/arch/arm/mach-aspeed/Kconfig
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -1,11 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_ASPEED
bool "Aspeed BMC architectures"
- depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
+ depends on ARCH_MULTI_V5 || ARCH_MULTI_V6 || ARCH_MULTI_V7
select SRAM
select WATCHDOG
select ASPEED_WATCHDOG
- select FTTMR010_TIMER
select MFD_SYSCON
select PINCTRL
help
@@ -18,6 +17,7 @@ config MACH_ASPEED_G4
depends on ARCH_MULTI_V5
select CPU_ARM926T
select PINCTRL_ASPEED_G4
+ select FTTMR010_TIMER
help
Say yes if you intend to run on an Aspeed ast2400 or similar
fourth generation BMCs, such as those used by OpenPower Power8
@@ -28,8 +28,21 @@ config MACH_ASPEED_G5
depends on ARCH_MULTI_V6
select CPU_V6
select PINCTRL_ASPEED_G5
+ select FTTMR010_TIMER
help
Say yes if you intend to run on an Aspeed ast2500 or similar
fifth generation Aspeed BMCs.
+config MACH_ASPEED_G6
+ bool "Aspeed SoC 6th Generation"
+ depends on ARCH_MULTI_V7
+ select CPU_V7
+ select PINCTRL_ASPEED_G6
+ select ARM_GIC
+ select HAVE_ARM_ARCH_TIMER
+ select HAVE_SMP
+ help
+ Say yes if you intend to run on an Aspeed ast2600 or similar
+ sixth generation Aspeed BMCs.
+
endif
diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile
new file mode 100644
index 000000000000..1951b3317a76
--- /dev/null
+++ b/arch/arm/mach-aspeed/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) ASPEED Technology Inc.
+# Copyright IBM Corp.
+
+obj-$(CONFIG_SMP) += platsmp.o
diff --git a/arch/arm/mach-aspeed/platsmp.c b/arch/arm/mach-aspeed/platsmp.c
new file mode 100644
index 000000000000..2324becf7991
--- /dev/null
+++ b/arch/arm/mach-aspeed/platsmp.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (C) ASPEED Technology Inc.
+// Copyright IBM Corp.
+
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+
+#define BOOT_ADDR 0x00
+#define BOOT_SIG 0x04
+
+static struct device_node *secboot_node;
+
+static int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ void __iomem *base;
+
+ base = of_iomap(secboot_node, 0);
+ if (!base) {
+ pr_err("could not map the secondary boot base!");
+ return -ENODEV;
+ }
+
+ writel_relaxed(0, base + BOOT_ADDR);
+ writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR);
+ writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG);
+
+ dsb_sev();
+
+ iounmap(base);
+
+ return 0;
+}
+
+static void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus)
+{
+ void __iomem *base;
+
+ secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem");
+ if (!secboot_node) {
+ pr_err("secboot device node found!!\n");
+ return;
+ }
+
+ base = of_iomap(secboot_node, 0);
+ if (!base) {
+ pr_err("could not map the secondary boot base!");
+ return;
+ }
+ __raw_writel(0xBADABABA, base + BOOT_SIG);
+
+ iounmap(base);
+}
+
+static const struct smp_operations aspeed_smp_ops __initconst = {
+ .smp_prepare_cpus = aspeed_g6_smp_prepare_cpus,
+ .smp_boot_secondary = aspeed_g6_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops);
diff --git a/arch/arm/mach-at91/.gitignore b/arch/arm/mach-at91/.gitignore
new file mode 100644
index 000000000000..2ecd6f51c8a9
--- /dev/null
+++ b/arch/arm/mach-at91/.gitignore
@@ -0,0 +1 @@
+pm_data-offsets.h
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 31b61f0e1c07..de64301dcff2 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -19,9 +19,10 @@ ifeq ($(CONFIG_PM_DEBUG),y)
CFLAGS_pm.o += -DDEBUG
endif
-include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE
+$(obj)/pm_data-offsets.h: $(obj)/pm_data-offsets.s FORCE
$(call filechk,offsets,__PM_DATA_OFFSETS_H__)
-arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h
+$(obj)/pm_suspend.o: $(obj)/pm_data-offsets.h
targets += pm_data-offsets.s
+clean-files += pm_data-offsets.h
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index c751f047b116..ed57c879d4e1 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -10,7 +10,7 @@
#include <linux/linkage.h>
#include <linux/clk/at91_pmc.h>
#include "pm.h"
-#include "generated/at91_pm_data-offsets.h"
+#include "pm_data-offsets.h"
#define SRAMC_SELF_FRESH_ACTIVE 0x01
#define SRAMC_SELF_FRESH_EXIT 0x00
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 5a59cebc7d0a..dd427bd2768c 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -1,11 +1,22 @@
# SPDX-License-Identifier: GPL-2.0
+
+menuconfig ARCH_DAVINCI
+ bool "TI DaVinci"
+ depends on ARCH_MULTI_V5
+ select DAVINCI_TIMER
+ select ZONE_DMA
+ select ARCH_HAS_HOLES_MEMORYMODEL
+ select PM_GENERIC_DOMAINS if PM
+ select PM_GENERIC_DOMAINS_OF if PM && OF
+ select REGMAP_MMIO
+ select HAVE_IDE
+ select PINCTRL_SINGLE
+
if ARCH_DAVINCI
config ARCH_DAVINCI_DMx
bool
-menu "TI DaVinci Implementations"
-
comment "DaVinci Core Type"
config ARCH_DAVINCI_DM644x
@@ -225,6 +236,4 @@ config DAVINCI_MUX_WARNINGS
to change the pin multiplexing setup. When there are no warnings
printed, it's safe to deselect DAVINCI_MUX for your product.
-endmenu
-
endif
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index f76a8482784f..a03d8443ef08 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,6 +4,8 @@
#
#
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
# Common objects
obj-y := time.o serial.o usb.o \
common.o sram.o
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 0628e7d7dcf3..5b3549f1236c 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -36,6 +36,7 @@
#include <linux/platform_data/ti-aemif.h>
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/uio_pruss.h>
+#include <linux/property.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/tps6507x.h>
#include <linux/regulator/fixed.h>
@@ -802,37 +803,79 @@ static const short da850_evm_mmcsd0_pins[] __initconst = {
-1
};
-static void da850_panel_power_ctrl(int val)
-{
- /* lcd backlight */
- gpio_set_value(DA850_LCD_BL_PIN, val);
+static struct property_entry da850_lcd_backlight_props[] = {
+ PROPERTY_ENTRY_BOOL("default-on"),
+ { }
+};
- /* lcd power */
- gpio_set_value(DA850_LCD_PWR_PIN, val);
-}
+static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = {
+ .dev_id = "gpio-backlight",
+ .table = {
+ GPIO_LOOKUP("davinci_gpio", DA850_LCD_BL_PIN, NULL, 0),
+ { }
+ },
+};
+
+static const struct platform_device_info da850_lcd_backlight_info = {
+ .name = "gpio-backlight",
+ .id = PLATFORM_DEVID_NONE,
+ .properties = da850_lcd_backlight_props,
+};
+
+static struct regulator_consumer_supply da850_lcd_supplies[] = {
+ REGULATOR_SUPPLY("lcd", NULL),
+};
+
+static struct regulator_init_data da850_lcd_supply_data = {
+ .consumer_supplies = da850_lcd_supplies,
+ .num_consumer_supplies = ARRAY_SIZE(da850_lcd_supplies),
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct fixed_voltage_config da850_lcd_supply = {
+ .supply_name = "lcd",
+ .microvolts = 33000000,
+ .init_data = &da850_lcd_supply_data,
+};
+
+static struct platform_device da850_lcd_supply_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1, /* Dummy fixed regulator is 0 */
+ .dev = {
+ .platform_data = &da850_lcd_supply,
+ },
+};
+
+static struct gpiod_lookup_table da850_lcd_supply_gpio_table = {
+ .dev_id = "reg-fixed-voltage.1",
+ .table = {
+ GPIO_LOOKUP("davinci_gpio", DA850_LCD_PWR_PIN, NULL, 0),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table *da850_lcd_gpio_lookups[] = {
+ &da850_lcd_backlight_gpio_table,
+ &da850_lcd_supply_gpio_table,
+};
static int da850_lcd_hw_init(void)
{
+ struct platform_device *backlight;
int status;
- status = gpio_request(DA850_LCD_BL_PIN, "lcd bl");
- if (status < 0)
- return status;
-
- status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr");
- if (status < 0) {
- gpio_free(DA850_LCD_BL_PIN);
- return status;
- }
+ gpiod_add_lookup_tables(da850_lcd_gpio_lookups,
+ ARRAY_SIZE(da850_lcd_gpio_lookups));
- gpio_direction_output(DA850_LCD_BL_PIN, 0);
- gpio_direction_output(DA850_LCD_PWR_PIN, 0);
+ backlight = platform_device_register_full(&da850_lcd_backlight_info);
+ if (IS_ERR(backlight))
+ return PTR_ERR(backlight);
- /* Switch off panel power and backlight */
- da850_panel_power_ctrl(0);
-
- /* Switch on panel power and backlight */
- da850_panel_power_ctrl(1);
+ status = platform_device_register(&da850_lcd_supply_device);
+ if (status)
+ return status;
return 0;
}
@@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void)
if (ret)
pr_warn("%s: LCD initialization failed: %d\n", __func__, ret);
- sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl,
ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata);
if (ret)
pr_warn("%s: LCDC registration failed: %d\n", __func__, ret);
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index e6b8ffd934a1..018ab4b549f1 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -21,7 +21,8 @@
#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/da8xx.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
#include "irqs.h"
#include "mux.h"
@@ -676,32 +677,17 @@ int __init da830_register_gpio(void)
return da8xx_register_gpio(&da830_gpio_platform_data);
}
-static struct davinci_timer_instance da830_timer_instance[2] = {
- {
- .base = DA8XX_TIMER64P0_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0),
- .cmp_off = DA830_CMP12_0,
- .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0),
- },
- {
- .base = DA8XX_TIMER64P1_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1),
- .cmp_off = DA830_CMP12_0,
- .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_1),
- },
-};
-
/*
- * T0_BOT: Timer 0, bottom : Used for clock_event & clocksource
- * T0_TOP: Timer 0, top : Used by DSP
- * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer
+ * Bottom half of timer0 is used both for clock even and clocksource.
+ * Top half is used by DSP.
*/
-static struct davinci_timer_info da830_timer_info = {
- .timers = da830_timer_instance,
- .clockevent_id = T0_BOT,
- .clocksource_id = T0_BOT,
+static const struct davinci_timer_cfg da830_timer_cfg = {
+ .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K),
+ .irq = {
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0)),
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)),
+ },
+ .cmp_off = DA830_CMP12_0,
};
static const struct davinci_soc_info davinci_soc_info_da830 = {
@@ -713,7 +699,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = {
.pinmux_base = DA8XX_SYSCFG0_BASE + 0x120,
.pinmux_pins = da830_pins,
.pinmux_pins_num = ARRAY_SIZE(da830_pins),
- .timer_info = &da830_timer_info,
.emac_pdata = &da8xx_emac_pdata,
};
@@ -743,6 +728,7 @@ void __init da830_init_time(void)
{
void __iomem *pll;
struct clk *clk;
+ int rv;
clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA830_REF_FREQ);
@@ -751,8 +737,13 @@ void __init da830_init_time(void)
da830_pll_init(NULL, pll, NULL);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
- davinci_timer_init(clk);
+ rv = davinci_timer_register(clk, &da830_timer_cfg);
+ WARN(rv, "Unable to register the timer: %d\n", rv);
}
static struct resource da830_psc0_resources[] = {
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 77bc64d6e39b..73b7cc53f966 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -35,7 +35,8 @@
#include <mach/cputype.h>
#include <mach/da8xx.h>
#include <mach/pm.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
#include "irqs.h"
#include "mux.h"
@@ -333,38 +334,16 @@ static struct davinci_id da850_ids[] = {
},
};
-static struct davinci_timer_instance da850_timer_instance[4] = {
- {
- .base = DA8XX_TIMER64P0_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0),
- },
- {
- .base = DA8XX_TIMER64P1_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1),
- },
- {
- .base = DA850_TIMER64P2_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_2),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_2),
- },
- {
- .base = DA850_TIMER64P3_BASE,
- .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_3),
- .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_3),
- },
-};
-
/*
- * T0_BOT: Timer 0, bottom : Used for clock_event
- * T0_TOP: Timer 0, top : Used for clocksource
- * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer
+ * Bottom half of timer 0 is used for clock_event, top half for
+ * clocksource.
*/
-static struct davinci_timer_info da850_timer_info = {
- .timers = da850_timer_instance,
- .clockevent_id = T0_BOT,
- .clocksource_id = T0_TOP,
+static const struct davinci_timer_cfg da850_timer_cfg = {
+ .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K),
+ .irq = {
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)),
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0)),
+ },
};
#ifdef CONFIG_CPU_FREQ
@@ -635,7 +614,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
.pinmux_base = DA8XX_SYSCFG0_BASE + 0x120,
.pinmux_pins = da850_pins,
.pinmux_pins_num = ARRAY_SIZE(da850_pins),
- .timer_info = &da850_timer_info,
.emac_pdata = &da8xx_emac_pdata,
.sram_dma = DA8XX_SHARED_RAM_BASE,
.sram_len = SZ_128K,
@@ -672,6 +650,7 @@ void __init da850_init_time(void)
void __iomem *pll0;
struct regmap *cfgchip;
struct clk *clk;
+ int rv;
clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ);
@@ -681,8 +660,13 @@ void __init da850_init_time(void)
da850_pll0_init(NULL, pll0, cfgchip);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
- davinci_timer_init(clk);
+ rv = davinci_timer_register(clk, &da850_timer_cfg);
+ WARN(rv, "Unable to register the timer: %d\n", rv);
}
static struct resource da850_pll1_resources[] = {
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 56c1835c42e5..208d7a4d3597 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -60,6 +60,9 @@ void davinci_map_sysmod(void);
#define DAVINCI_GPIO_BASE 0x01C67000
int davinci_gpio_register(struct resource *res, int size, void *pdata);
+#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
+#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
+
/* DM355 base addresses */
#define DM355_ASYNC_EMIF_CONTROL_BASE 0x01e10000
#define DM355_ASYNC_EMIF_DATA_CE0_BASE 0x02000000
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index c6073326be2e..5de72d2fa8f0 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -30,7 +30,8 @@
#include <mach/cputype.h>
#include <mach/mux.h>
#include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
#include "asp.h"
#include "davinci.h"
@@ -620,15 +621,15 @@ static struct davinci_id dm355_ids[] = {
};
/*
- * T0_BOT: Timer 0, bottom: clockevent source for hrtimers
- * T0_TOP: Timer 0, top : clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top : <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
*/
-static struct davinci_timer_info dm355_timer_info = {
- .timers = davinci_timer_instance,
- .clockevent_id = T0_BOT,
- .clocksource_id = T0_TOP,
+static const struct davinci_timer_cfg dm355_timer_cfg = {
+ .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+ .irq = {
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+ },
};
static struct plat_serial8250_port dm355_serial0_platform_data[] = {
@@ -706,7 +707,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = {
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
.pinmux_pins = dm355_pins,
.pinmux_pins_num = ARRAY_SIZE(dm355_pins),
- .timer_info = &dm355_timer_info,
.sram_dma = 0x00010000,
.sram_len = SZ_32K,
};
@@ -733,6 +733,7 @@ void __init dm355_init_time(void)
{
void __iomem *pll1, *psc;
struct clk *clk;
+ int rv;
clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ);
@@ -743,8 +744,13 @@ void __init dm355_init_time(void)
dm355_psc_init(NULL, psc);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
- davinci_timer_init(clk);
+ rv = davinci_timer_register(clk, &dm355_timer_cfg);
+ WARN(rv, "Unable to register the timer: %d\n", rv);
}
static struct resource dm355_pll2_resources[] = {
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 2f9ae6431bf5..8062412be70f 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -784,6 +784,10 @@ void __init dm365_init_time(void)
dm365_psc_init(NULL, psc);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
davinci_timer_init(clk);
}
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 1b9e9a6192ef..24988939ae46 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -27,7 +27,8 @@
#include <mach/cputype.h>
#include <mach/mux.h>
#include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
#include "asp.h"
#include "davinci.h"
@@ -561,15 +562,15 @@ static struct davinci_id dm644x_ids[] = {
};
/*
- * T0_BOT: Timer 0, bottom: clockevent source for hrtimers
- * T0_TOP: Timer 0, top : clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top : <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
*/
-static struct davinci_timer_info dm644x_timer_info = {
- .timers = davinci_timer_instance,
- .clockevent_id = T0_BOT,
- .clocksource_id = T0_TOP,
+static const struct davinci_timer_cfg dm644x_timer_cfg = {
+ .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+ .irq = {
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+ },
};
static struct plat_serial8250_port dm644x_serial0_platform_data[] = {
@@ -647,7 +648,6 @@ static const struct davinci_soc_info davinci_soc_info_dm644x = {
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
.pinmux_pins = dm644x_pins,
.pinmux_pins_num = ARRAY_SIZE(dm644x_pins),
- .timer_info = &dm644x_timer_info,
.emac_pdata = &dm644x_emac_pdata,
.sram_dma = 0x00008000,
.sram_len = SZ_16K,
@@ -669,6 +669,7 @@ void __init dm644x_init_time(void)
{
void __iomem *pll1, *psc;
struct clk *clk;
+ int rv;
clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM644X_REF_FREQ);
@@ -679,8 +680,13 @@ void __init dm644x_init_time(void)
dm644x_psc_init(NULL, psc);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
- davinci_timer_init(clk);
+ rv = davinci_timer_register(clk, &dm644x_timer_cfg);
+ WARN(rv, "Unable to register the timer: %d\n", rv);
}
static struct resource dm644x_pll2_resources[] = {
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 62ca952fe161..4ffd028ed997 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -1,5 +1,5 @@
/*
- * TI DaVinci DM644x chip specific setup
+ * TI DaVinci DM646x chip specific setup
*
* Author: Kevin Hilman, Deep Root Systems, LLC
*
@@ -28,7 +28,8 @@
#include <mach/cputype.h>
#include <mach/mux.h>
#include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
#include "asp.h"
#include "davinci.h"
@@ -501,15 +502,15 @@ static struct davinci_id dm646x_ids[] = {
};
/*
- * T0_BOT: Timer 0, bottom: clockevent source for hrtimers
- * T0_TOP: Timer 0, top : clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top : <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
*/
-static struct davinci_timer_info dm646x_timer_info = {
- .timers = davinci_timer_instance,
- .clockevent_id = T0_BOT,
- .clocksource_id = T0_TOP,
+static const struct davinci_timer_cfg dm646x_timer_cfg = {
+ .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+ .irq = {
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+ DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+ },
};
static struct plat_serial8250_port dm646x_serial0_platform_data[] = {
@@ -587,7 +588,6 @@ static const struct davinci_soc_info davinci_soc_info_dm646x = {
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
.pinmux_pins = dm646x_pins,
.pinmux_pins_num = ARRAY_SIZE(dm646x_pins),
- .timer_info = &dm646x_timer_info,
.emac_pdata = &dm646x_emac_pdata,
.sram_dma = 0x10010000,
.sram_len = SZ_32K,
@@ -652,6 +652,7 @@ void __init dm646x_init_time(unsigned long ref_clk_rate,
{
void __iomem *pll1, *psc;
struct clk *clk;
+ int rv;
clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, ref_clk_rate);
clk_register_fixed_rate(NULL, "aux_clkin", NULL, 0, aux_clkin_rate);
@@ -663,8 +664,13 @@ void __init dm646x_init_time(unsigned long ref_clk_rate,
dm646x_psc_init(NULL, psc);
clk = clk_get(NULL, "timer0");
+ if (WARN_ON(IS_ERR(clk))) {
+ pr_err("Unable to get the timer clock\n");
+ return;
+ }
- davinci_timer_init(clk);
+ rv = davinci_timer_register(clk, &dm646x_timer_cfg);
+ WARN(rv, "Unable to register the timer: %d\n", rv);
}
static struct resource dm646x_pll2_resources[] = {
diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h
index 1c971d8d8ba8..ba913736990f 100644
--- a/arch/arm/mach-davinci/include/mach/time.h
+++ b/arch/arm/mach-davinci/include/mach/time.h
@@ -11,9 +11,7 @@
#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
#define __ARCH_ARM_MACH_DAVINCI_TIME_H
-#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
-#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
enum {
T0_BOT,
diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S
index 05d03f09ff54..71262dcdbca3 100644
--- a/arch/arm/mach-davinci/sleep.S
+++ b/arch/arm/mach-davinci/sleep.S
@@ -24,6 +24,7 @@
#define DEEPSLEEP_SLEEPENABLE_BIT BIT(31)
.text
+ .arch armv5te
/*
* Move DaVinci into deep sleep state
*
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 5a6de5368ab0..740410a3bb6a 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -398,17 +398,3 @@ void __init davinci_timer_init(struct clk *timer_clk)
for (i=0; i< ARRAY_SIZE(timers); i++)
timer32_config(&timers[i]);
}
-
-static int __init of_davinci_timer_init(struct device_node *np)
-{
- struct clk *clk;
-
- clk = of_clk_get(np, 0);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- davinci_timer_init(clk);
-
- return 0;
-}
-TIMER_OF_DECLARE(davinci_timer, "ti,da830-timer", of_davinci_timer_init);
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/bridge-regs.h
index f4a5b34489b7..ace0b0bfbf11 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/bridge-regs.h
@@ -1,6 +1,4 @@
/*
- * arch/arm/mach-dove/include/mach/bridge-regs.h
- *
* Mbus-L to Mbus Bridge Registers
*
* This file is licensed under the terms of the GNU General Public
@@ -11,7 +9,7 @@
#ifndef __ASM_ARCH_BRIDGE_REGS_H
#define __ASM_ARCH_BRIDGE_REGS_H
-#include <mach/dove.h>
+#include "dove.h"
#define CPU_CONFIG (BRIDGE_VIRT_BASE + 0x0000)
diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
index b9a7c33db29a..9f25c993d863 100644
--- a/arch/arm/mach-dove/cm-a510.c
+++ b/arch/arm/mach-dove/cm-a510.c
@@ -22,8 +22,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <mach/dove.h>
-
+#include "dove.h"
#include "common.h"
static struct mv643xx_eth_platform_data cm_a510_ge00_data = {
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index d7b826d2695c..01b830afcea9 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -22,11 +22,11 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/pm.h>
#include <plat/common.h>
#include <plat/irq.h>
#include <plat/time.h>
+#include "bridge-regs.h"
+#include "pm.h"
#include "common.h"
/* These can go away once Dove uses the mvebu-mbus DT binding */
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index 8971c3c0f0fe..418ab21b9d9b 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -24,7 +24,7 @@
#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <mach/dove.h>
+#include "dove.h"
#include "common.h"
static struct mv643xx_eth_platform_data dove_db_ge00_data = {
diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/dove.h
index 00f45458b3ec..320ed1696abd 100644
--- a/arch/arm/mach-dove/include/mach/dove.h
+++ b/arch/arm/mach-dove/dove.h
@@ -1,6 +1,4 @@
/*
- * arch/arm/mach-dove/include/mach/dove.h
- *
* Generic definitions for Marvell Dove 88AP510 SoC
*
* This file is licensed under the terms of the GNU General Public
@@ -11,7 +9,7 @@
#ifndef __ASM_ARCH_DOVE_H
#define __ASM_ARCH_DOVE_H
-#include <mach/irqs.h>
+#include "irqs.h"
/*
* Marvell Dove address maps.
@@ -20,8 +18,8 @@
* c8000000 fdb00000 1M Cryptographic SRAM
* e0000000 @runtime 128M PCIe-0 Memory space
* e8000000 @runtime 128M PCIe-1 Memory space
- * f1000000 fde00000 8M on-chip south-bridge registers
- * f1800000 fe600000 8M on-chip north-bridge registers
+ * f1000000 fec00000 1M on-chip south-bridge registers
+ * f1800000 fe400000 8M on-chip north-bridge registers
* f2000000 fee00000 1M PCIe-0 I/O space
* f2100000 fef00000 1M PCIe-1 I/O space
*/
@@ -44,11 +42,11 @@
#define DOVE_SCRATCHPAD_SIZE SZ_1M
#define DOVE_SB_REGS_PHYS_BASE 0xf1000000
-#define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfde00000)
-#define DOVE_SB_REGS_SIZE SZ_8M
+#define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfec00000)
+#define DOVE_SB_REGS_SIZE SZ_1M
#define DOVE_NB_REGS_PHYS_BASE 0xf1800000
-#define DOVE_NB_REGS_VIRT_BASE IOMEM(0xfe600000)
+#define DOVE_NB_REGS_VIRT_BASE IOMEM(0xfe400000)
#define DOVE_NB_REGS_SIZE SZ_8M
#define DOVE_PCIE0_IO_PHYS_BASE 0xf2000000
diff --git a/arch/arm/mach-dove/include/mach/hardware.h b/arch/arm/mach-dove/include/mach/hardware.h
deleted file mode 100644
index f1368b9a8ece..000000000000
--- a/arch/arm/mach-dove/include/mach/hardware.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/hardware.h
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include "dove.h"
-
-/* Macros below are required for compatibility with PXA AC'97 driver. */
-#define __REG(x) (*((volatile u32 *)((x) - DOVE_SB_REGS_PHYS_BASE + \
- DOVE_SB_REGS_VIRT_BASE)))
-#define __PREG(x) (((u32)&(x)) - DOVE_SB_REGS_VIRT_BASE + \
- DOVE_SB_REGS_PHYS_BASE)
-#endif
diff --git a/arch/arm/mach-dove/include/mach/uncompress.h b/arch/arm/mach-dove/include/mach/uncompress.h
index 5c8ae9b9d39a..7a4bd8838036 100644
--- a/arch/arm/mach-dove/include/mach/uncompress.h
+++ b/arch/arm/mach-dove/include/mach/uncompress.h
@@ -1,15 +1,13 @@
/*
- * arch/arm/mach-dove/include/mach/uncompress.h
- *
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <mach/dove.h>
+#define UART0_PHYS_BASE (0xf1000000 + 0x12000)
-#define UART_THR ((volatile unsigned char *)(DOVE_UART0_PHYS_BASE + 0x0))
-#define UART_LSR ((volatile unsigned char *)(DOVE_UART0_PHYS_BASE + 0x14))
+#define UART_THR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x0))
+#define UART_LSR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x14))
#define LSR_THRE 0x20
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index d6627c1f7f30..31ccbcee2627 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -11,9 +11,12 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/exception.h>
+
#include <plat/irq.h>
-#include <mach/bridge-regs.h>
#include <plat/orion-gpio.h>
+
+#include "pm.h"
+#include "bridge-regs.h"
#include "common.h"
static int __initdata gpio0_irqs[4] = {
diff --git a/arch/arm/mach-dove/include/mach/irqs.h b/arch/arm/mach-dove/irqs.h
index 8ff0fa8b4fcd..a0742179faff 100644
--- a/arch/arm/mach-dove/include/mach/irqs.h
+++ b/arch/arm/mach-dove/irqs.h
@@ -1,6 +1,4 @@
/*
- * arch/arm/mach-dove/include/mach/irqs.h
- *
* IRQ definitions for Marvell Dove 88AP510 SoC
*
* This file is licensed under the terms of the GNU General Public
diff --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
index 8a433a51289c..6acd8488bb05 100644
--- a/arch/arm/mach-dove/mpp.c
+++ b/arch/arm/mach-dove/mpp.c
@@ -12,8 +12,8 @@
#include <linux/gpio.h>
#include <linux/io.h>
#include <plat/mpp.h>
-#include <mach/dove.h>
#include <plat/orion-gpio.h>
+#include "dove.h"
#include "mpp.h"
struct dove_mpp_grp {
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index dfb62f3f5dcf..ee91ac6b5ebf 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -17,9 +17,9 @@
#include <asm/setup.h>
#include <asm/delay.h>
#include <plat/pcie.h>
-#include <mach/irqs.h>
-#include <mach/bridge-regs.h>
#include <plat/addr-map.h>
+#include "irqs.h"
+#include "bridge-regs.h"
#include "common.h"
struct pcie_port {
diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/pm.h
index d22b9b174007..01267746d707 100644
--- a/arch/arm/mach-dove/include/mach/pm.h
+++ b/arch/arm/mach-dove/pm.h
@@ -1,6 +1,4 @@
/*
- * arch/arm/mach-dove/include/mach/pm.h
- *
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
@@ -10,7 +8,7 @@
#define __ASM_ARCH_PM_H
#include <asm/errno.h>
-#include <mach/irqs.h>
+#include "irqs.h"
#define CLOCK_GATING_CONTROL (DOVE_PMU_VIRT_BASE + 0x38)
#define CLOCK_GATING_BIT_USB0 0
diff --git a/arch/arm/mach-ep93xx/crunch.c b/arch/arm/mach-ep93xx/crunch.c
index 1c9a4be8b503..1c05c5bf7e5c 100644
--- a/arch/arm/mach-ep93xx/crunch.c
+++ b/arch/arm/mach-ep93xx/crunch.c
@@ -49,6 +49,7 @@ static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
* FALLTHROUGH: Ensure we don't try to overwrite our newly
* initialised state information on the first fault.
*/
+ /* Fall through */
case THREAD_NOTIFY_EXIT:
crunch_task_release(thread);
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 1f0da76a39de..7b7280c21ee0 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -103,7 +103,7 @@ static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
};
static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = {
- .dev_id = "ep93xx-spi.0",
+ .dev_id = "spi0",
.table = {
GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW),
{ },
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index e2658e22bba1..8a53b74dc4b2 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -73,7 +73,7 @@ static struct spi_board_info simone_spi_devices[] __initdata = {
* v1.3 parts will still work, since the signal on SFRMOUT is automatic.
*/
static struct gpiod_lookup_table simone_spi_cs_gpio_table = {
- .dev_id = "ep93xx-spi.0",
+ .dev_id = "spi0",
.table = {
GPIO_LOOKUP("A", 1, "cs", GPIO_ACTIVE_LOW),
{ },
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 582e06e104fd..e0e1b11032f1 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -267,7 +267,7 @@ static struct spi_board_info bk3_spi_board_info[] __initdata = {
* goes through CPLD
*/
static struct gpiod_lookup_table bk3_spi_cs_gpio_table = {
- .dev_id = "ep93xx-spi.0",
+ .dev_id = "spi0",
.table = {
GPIO_LOOKUP("F", 3, "cs", GPIO_ACTIVE_LOW),
{ },
@@ -316,7 +316,7 @@ static struct spi_board_info ts72xx_spi_devices[] __initdata = {
};
static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = {
- .dev_id = "ep93xx-spi.0",
+ .dev_id = "spi0",
.table = {
/* DIO_17 */
GPIO_LOOKUP("F", 2, "cs", GPIO_ACTIVE_LOW),
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
index a88a1d807b32..cbcba3136d74 100644
--- a/arch/arm/mach-ep93xx/vision_ep9307.c
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -242,7 +242,7 @@ static struct spi_board_info vision_spi_board_info[] __initdata = {
};
static struct gpiod_lookup_table vision_spi_cs_gpio_table = {
- .dev_id = "ep93xx-spi.0",
+ .dev_id = "spi0",
.table = {
GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW),
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index d7422233a130..f83786640f94 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -13,6 +13,7 @@ menuconfig ARCH_EXYNOS
select ARM_AMBA
select ARM_GIC
select COMMON_CLK_SAMSUNG
+ select EXYNOS_CHIPID
select EXYNOS_THERMAL
select EXYNOS_PMU
select EXYNOS_SROM
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 95713450591a..ebb27592a9f7 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -30,12 +30,6 @@ static int ar8031_phy_fixup(struct phy_device *dev)
val &= ~(0x1 << 8);
phy_write(dev, 0xe, val);
- /* introduce tx clock delay */
- phy_write(dev, 0x1d, 0x5);
- val = phy_read(dev, 0x1e);
- val |= 0x0100;
- phy_write(dev, 0x1e, val);
-
return 0;
}
diff --git a/arch/arm/mach-iop13xx/Kconfig b/arch/arm/mach-iop13xx/Kconfig
deleted file mode 100644
index c4f04070b4c1..000000000000
--- a/arch/arm/mach-iop13xx/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-if ARCH_IOP13XX
-
-menu "IOP13XX Implementation Options"
-
-comment "IOP13XX Platform Support"
-
-config MACH_IQ81340SC
- bool "Enable IQ81340SC Hardware Support"
- help
- Say Y here if you want to support running on the Intel IQ81340SC
- evaluation kit.
-
-config MACH_IQ81340MC
- bool "Enable IQ81340MC Hardware Support"
- help
- Say Y here if you want to support running on the Intel IQ81340MC
- evaluation kit.
-
-endmenu
-endif
diff --git a/arch/arm/mach-iop13xx/Makefile b/arch/arm/mach-iop13xx/Makefile
deleted file mode 100644
index 5757c8f6e371..000000000000
--- a/arch/arm/mach-iop13xx/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ARCH_IOP13XX) += setup.o
-obj-$(CONFIG_ARCH_IOP13XX) += irq.o
-obj-$(CONFIG_ARCH_IOP13XX) += pci.o
-obj-$(CONFIG_ARCH_IOP13XX) += io.o
-obj-$(CONFIG_ARCH_IOP13XX) += tpmi.o
-obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
-obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
-obj-$(CONFIG_PCI_MSI) += msi.o
diff --git a/arch/arm/mach-iop13xx/Makefile.boot b/arch/arm/mach-iop13xx/Makefile.boot
deleted file mode 100644
index 4f29554c8401..000000000000
--- a/arch/arm/mach-iop13xx/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-iop13xx/include/mach/adma.h b/arch/arm/mach-iop13xx/include/mach/adma.h
deleted file mode 100644
index 51d206f5b093..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/adma.h
+++ /dev/null
@@ -1,608 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright(c) 2006, Intel Corporation.
- */
-#ifndef _ADMA_H
-#define _ADMA_H
-#include <linux/types.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop_adma.h>
-
-#define ADMA_ACCR(chan) (chan->mmr_base + 0x0)
-#define ADMA_ACSR(chan) (chan->mmr_base + 0x4)
-#define ADMA_ADAR(chan) (chan->mmr_base + 0x8)
-#define ADMA_IIPCR(chan) (chan->mmr_base + 0x18)
-#define ADMA_IIPAR(chan) (chan->mmr_base + 0x1c)
-#define ADMA_IIPUAR(chan) (chan->mmr_base + 0x20)
-#define ADMA_ANDAR(chan) (chan->mmr_base + 0x24)
-#define ADMA_ADCR(chan) (chan->mmr_base + 0x28)
-#define ADMA_CARMD(chan) (chan->mmr_base + 0x2c)
-#define ADMA_ABCR(chan) (chan->mmr_base + 0x30)
-#define ADMA_DLADR(chan) (chan->mmr_base + 0x34)
-#define ADMA_DUADR(chan) (chan->mmr_base + 0x38)
-#define ADMA_SLAR(src, chan) (chan->mmr_base + (0x3c + (src << 3)))
-#define ADMA_SUAR(src, chan) (chan->mmr_base + (0x40 + (src << 3)))
-
-struct iop13xx_adma_src {
- u32 src_addr;
- union {
- u32 upper_src_addr;
- struct {
- unsigned int pq_upper_src_addr:24;
- unsigned int pq_dmlt:8;
- };
- };
-};
-
-struct iop13xx_adma_desc_ctrl {
- unsigned int int_en:1;
- unsigned int xfer_dir:2;
- unsigned int src_select:4;
- unsigned int zero_result:1;
- unsigned int block_fill_en:1;
- unsigned int crc_gen_en:1;
- unsigned int crc_xfer_dis:1;
- unsigned int crc_seed_fetch_dis:1;
- unsigned int status_write_back_en:1;
- unsigned int endian_swap_en:1;
- unsigned int reserved0:2;
- unsigned int pq_update_xfer_en:1;
- unsigned int dual_xor_en:1;
- unsigned int pq_xfer_en:1;
- unsigned int p_xfer_dis:1;
- unsigned int reserved1:10;
- unsigned int relax_order_en:1;
- unsigned int no_snoop_en:1;
-};
-
-struct iop13xx_adma_byte_count {
- unsigned int byte_count:24;
- unsigned int host_if:3;
- unsigned int reserved:2;
- unsigned int zero_result_err_q:1;
- unsigned int zero_result_err:1;
- unsigned int tx_complete:1;
-};
-
-struct iop13xx_adma_desc_hw {
- u32 next_desc;
- union {
- u32 desc_ctrl;
- struct iop13xx_adma_desc_ctrl desc_ctrl_field;
- };
- union {
- u32 crc_addr;
- u32 block_fill_data;
- u32 q_dest_addr;
- };
- union {
- u32 byte_count;
- struct iop13xx_adma_byte_count byte_count_field;
- };
- union {
- u32 dest_addr;
- u32 p_dest_addr;
- };
- union {
- u32 upper_dest_addr;
- u32 pq_upper_dest_addr;
- };
- struct iop13xx_adma_src src[1];
-};
-
-struct iop13xx_adma_desc_dual_xor {
- u32 next_desc;
- u32 desc_ctrl;
- u32 reserved;
- u32 byte_count;
- u32 h_dest_addr;
- u32 h_upper_dest_addr;
- u32 src0_addr;
- u32 upper_src0_addr;
- u32 src1_addr;
- u32 upper_src1_addr;
- u32 h_src_addr;
- u32 h_upper_src_addr;
- u32 d_src_addr;
- u32 d_upper_src_addr;
- u32 d_dest_addr;
- u32 d_upper_dest_addr;
-};
-
-struct iop13xx_adma_desc_pq_update {
- u32 next_desc;
- u32 desc_ctrl;
- u32 reserved;
- u32 byte_count;
- u32 p_dest_addr;
- u32 p_upper_dest_addr;
- u32 src0_addr;
- u32 upper_src0_addr;
- u32 src1_addr;
- u32 upper_src1_addr;
- u32 p_src_addr;
- u32 p_upper_src_addr;
- u32 q_src_addr;
- struct {
- unsigned int q_upper_src_addr:24;
- unsigned int q_dmlt:8;
- };
- u32 q_dest_addr;
- u32 q_upper_dest_addr;
-};
-
-static inline int iop_adma_get_max_xor(void)
-{
- return 16;
-}
-
-#define iop_adma_get_max_pq iop_adma_get_max_xor
-
-static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
-{
- return __raw_readl(ADMA_ADAR(chan));
-}
-
-static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
- u32 next_desc_addr)
-{
- __raw_writel(next_desc_addr, ADMA_ANDAR(chan));
-}
-
-#define ADMA_STATUS_BUSY (1 << 13)
-
-static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
-{
- if (__raw_readl(ADMA_ACSR(chan)) &
- ADMA_STATUS_BUSY)
- return 1;
- else
- return 0;
-}
-
-static inline int
-iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
-{
- return 1;
-}
-#define iop_desc_is_aligned(x, y) 1
-
-static inline int
-iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
-{
- *slots_per_op = 1;
- return 1;
-}
-
-#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
-
-static inline int
-iop_chan_memset_slot_count(size_t len, int *slots_per_op)
-{
- *slots_per_op = 1;
- return 1;
-}
-
-static inline int
-iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
-{
- static const char slot_count_table[] = { 1, 2, 2, 2,
- 2, 3, 3, 3,
- 3, 4, 4, 4,
- 4, 5, 5, 5,
- };
- *slots_per_op = slot_count_table[src_cnt - 1];
- return *slots_per_op;
-}
-
-#define ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
-#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-#define IOP_ADMA_PQ_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
-#define iop_chan_pq_slot_count iop_chan_xor_slot_count
-#define iop_chan_pq_zero_sum_slot_count iop_chan_xor_slot_count
-
-static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- return hw_desc->byte_count_field.byte_count;
-}
-
-static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan,
- int src_idx)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- return hw_desc->src[src_idx].src_addr;
-}
-
-static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- return hw_desc->desc_ctrl_field.src_select + 1;
-}
-
-static inline void
-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
- hw_desc->crc_addr = 0;
-}
-
-static inline void
-iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.block_fill_en = 1;
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
- hw_desc->crc_addr = 0;
-}
-
-/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
-static inline void
-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,
- unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.src_select = src_cnt - 1;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
- hw_desc->crc_addr = 0;
-
-}
-#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
-
-/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
-static inline int
-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
- unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.src_select = src_cnt - 1;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.zero_result = 1;
- u_desc_ctrl.field.status_write_back_en = 1;
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
- hw_desc->crc_addr = 0;
-
- return 1;
-}
-
-static inline void
-iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt,
- unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.src_select = src_cnt - 1;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.pq_xfer_en = 1;
- u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P);
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
-}
-
-static inline void
-iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
- unsigned long flags)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- union {
- u32 value;
- struct iop13xx_adma_desc_ctrl field;
- } u_desc_ctrl;
-
- u_desc_ctrl.value = 0;
- u_desc_ctrl.field.src_select = src_cnt - 1;
- u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
- u_desc_ctrl.field.zero_result = 1;
- u_desc_ctrl.field.status_write_back_en = 1;
- u_desc_ctrl.field.pq_xfer_en = 1;
- u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P);
- u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
- hw_desc->desc_ctrl = u_desc_ctrl.value;
-}
-
-static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan,
- u32 byte_count)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- hw_desc->byte_count = byte_count;
-}
-
-static inline void
-iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
-{
- int slots_per_op = desc->slots_per_op;
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
- int i = 0;
-
- if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
- hw_desc->byte_count = len;
- } else {
- do {
- iter = iop_hw_desc_slot_idx(hw_desc, i);
- iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
- len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
- i += slots_per_op;
- } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
-
- if (len) {
- iter = iop_hw_desc_slot_idx(hw_desc, i);
- iter->byte_count = len;
- }
- }
-}
-
-#define iop_desc_set_pq_zero_sum_byte_count iop_desc_set_zero_sum_byte_count
-
-static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan,
- dma_addr_t addr)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- hw_desc->dest_addr = addr;
- hw_desc->upper_dest_addr = 0;
-}
-
-static inline void
-iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-
- hw_desc->dest_addr = addr[0];
- hw_desc->q_dest_addr = addr[1];
- hw_desc->upper_dest_addr = 0;
-}
-
-static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
- dma_addr_t addr)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- hw_desc->src[0].src_addr = addr;
- hw_desc->src[0].upper_src_addr = 0;
-}
-
-static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
- int src_idx, dma_addr_t addr)
-{
- int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
- int i = 0;
-
- do {
- iter = iop_hw_desc_slot_idx(hw_desc, i);
- iter->src[src_idx].src_addr = addr;
- iter->src[src_idx].upper_src_addr = 0;
- slot_cnt -= slots_per_op;
- if (slot_cnt) {
- i += slots_per_op;
- addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
- }
- } while (slot_cnt);
-}
-
-static inline void
-iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
- dma_addr_t addr, unsigned char coef)
-{
- int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
- struct iop13xx_adma_src *src;
- int i = 0;
-
- do {
- iter = iop_hw_desc_slot_idx(hw_desc, i);
- src = &iter->src[src_idx];
- src->src_addr = addr;
- src->pq_upper_src_addr = 0;
- src->pq_dmlt = coef;
- slot_cnt -= slots_per_op;
- if (slot_cnt) {
- i += slots_per_op;
- addr += IOP_ADMA_PQ_MAX_BYTE_COUNT;
- }
- } while (slot_cnt);
-}
-
-static inline void
-iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
- struct iop_adma_chan *chan)
-{
- iop_desc_init_memcpy(desc, 1);
- iop_desc_set_byte_count(desc, chan, 0);
- iop_desc_set_dest_addr(desc, chan, 0);
- iop_desc_set_memcpy_src_addr(desc, 0);
-}
-
-#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
-#define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr
-
-static inline void
-iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx,
- dma_addr_t *src)
-{
- iop_desc_set_xor_src_addr(desc, pq_idx, src[pq_idx]);
- iop_desc_set_xor_src_addr(desc, pq_idx+1, src[pq_idx+1]);
-}
-
-static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
- u32 next_desc_addr)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-
- iop_paranoia(hw_desc->next_desc);
- hw_desc->next_desc = next_desc_addr;
-}
-
-static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- return hw_desc->next_desc;
-}
-
-static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- hw_desc->next_desc = 0;
-}
-
-static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
- u32 val)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- hw_desc->block_fill_data = val;
-}
-
-static inline enum sum_check_flags
-iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
-{
- struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
- struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
- enum sum_check_flags flags;
-
- BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
-
- flags = byte_count.zero_result_err_q << SUM_CHECK_Q;
- flags |= byte_count.zero_result_err << SUM_CHECK_P;
-
- return flags;
-}
-
-static inline void iop_chan_append(struct iop_adma_chan *chan)
-{
- u32 adma_accr;
-
- adma_accr = __raw_readl(ADMA_ACCR(chan));
- adma_accr |= 0x2;
- __raw_writel(adma_accr, ADMA_ACCR(chan));
-}
-
-static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
-{
- return __raw_readl(ADMA_ACSR(chan));
-}
-
-static inline void iop_chan_disable(struct iop_adma_chan *chan)
-{
- u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
- adma_chan_ctrl &= ~0x1;
- __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
-}
-
-static inline void iop_chan_enable(struct iop_adma_chan *chan)
-{
- u32 adma_chan_ctrl;
-
- adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
- adma_chan_ctrl |= 0x1;
- __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
-}
-
-static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
-{
- u32 status = __raw_readl(ADMA_ACSR(chan));
- status &= (1 << 12);
- __raw_writel(status, ADMA_ACSR(chan));
-}
-
-static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
-{
- u32 status = __raw_readl(ADMA_ACSR(chan));
- status &= (1 << 11);
- __raw_writel(status, ADMA_ACSR(chan));
-}
-
-static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
-{
- u32 status = __raw_readl(ADMA_ACSR(chan));
- status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
- __raw_writel(status, ADMA_ACSR(chan));
-}
-
-static inline int
-iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
-{
- return test_bit(9, &status);
-}
-
-static inline int
-iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
-{
- return test_bit(5, &status);
-}
-
-static inline int
-iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
-{
- return test_bit(4, &status);
-}
-
-static inline int
-iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
-{
- return test_bit(3, &status);
-}
-
-static inline int
-iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
-{
- return 0;
-}
-
-static inline int
-iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
-{
- return 0;
-}
-
-static inline int
-iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
-{
- return 0;
-}
-
-#endif /* _ADMA_H */
diff --git a/arch/arm/mach-iop13xx/include/mach/entry-macro.S b/arch/arm/mach-iop13xx/include/mach/entry-macro.S
deleted file mode 100644
index 9f4ecb8861bd..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/entry-macro.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * iop13xx low level irq macros
- * Copyright (c) 2005-2006, Intel Corporation.
- */
- .macro get_irqnr_preamble, base, tmp
- mrc p15, 0, \tmp, c15, c1, 0
- orr \tmp, \tmp, #(1 << 6)
- mcr p15, 0, \tmp, c15, c1, 0 @ Enable cp6 access
- .endm
-
- /*
- * Note: a 1-cycle window exists where iintvec will return the value
- * of iintbase, so we explicitly check for "bad zeros"
- */
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mrc p6, 0, \irqnr, c3, c2, 0 @ Read IINTVEC
- cmp \irqnr, #0
- mrceq p6, 0, \irqnr, c3, c2, 0 @ Re-read on potentially bad zero
- adds \irqstat, \irqnr, #1 @ Check for 0xffffffff
- movne \irqnr, \irqnr, lsr #2 @ Convert to irqnr
- .endm
-
- .macro arch_ret_to_user, tmp1, tmp2
- mrc p15, 0, \tmp1, c15, c1, 0
- ands \tmp2, \tmp1, #(1 << 6)
- bicne \tmp1, \tmp1, #(1 << 6)
- mcrne p15, 0, \tmp1, c15, c1, 0 @ Disable cp6 access
- .endm
diff --git a/arch/arm/mach-iop13xx/include/mach/hardware.h b/arch/arm/mach-iop13xx/include/mach/hardware.h
deleted file mode 100644
index 8c943fa6bbd7..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/hardware.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-#include <asm/types.h>
-
-#ifndef __ASSEMBLY__
-extern u16 iop13xx_dev_id(void);
-extern void iop13xx_set_atu_mmr_bases(void);
-#endif
-
-/*
- * Generic chipset bits
- *
- */
-#include "iop13xx.h"
-
-/*
- * Board specific bits
- */
-#include "iq81340.h"
-
-#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-iop13xx/include/mach/iop13xx.h b/arch/arm/mach-iop13xx/include/mach/iop13xx.h
deleted file mode 100644
index 04bb6aca12c5..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/iop13xx.h
+++ /dev/null
@@ -1,508 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP13XX_HW_H_
-#define _IOP13XX_HW_H_
-
-#ifndef __ASSEMBLY__
-
-enum reboot_mode;
-
-/* The ATU offsets can change based on the strapping */
-extern u32 iop13xx_atux_pmmr_offset;
-extern u32 iop13xx_atue_pmmr_offset;
-void iop13xx_init_early(void);
-void iop13xx_init_irq(void);
-void iop13xx_map_io(void);
-void iop13xx_platform_init(void);
-void iop13xx_add_tpmi_devices(void);
-void iop13xx_init_irq(void);
-void iop13xx_restart(enum reboot_mode, const char *);
-
-/* CPUID CP6 R0 Page 0 */
-static inline int iop13xx_cpu_id(void)
-{
- int id;
- asm volatile("mrc p6, 0, %0, c0, c0, 0":"=r" (id));
- return id;
-}
-
-/* WDTCR CP6 R7 Page 9 */
-static inline u32 read_wdtcr(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c7, c9, 0":"=r" (val));
- return val;
-}
-static inline void write_wdtcr(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c7, c9, 0"::"r" (val));
-}
-
-/* WDTSR CP6 R8 Page 9 */
-static inline u32 read_wdtsr(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c8, c9, 0":"=r" (val));
- return val;
-}
-static inline void write_wdtsr(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c8, c9, 0"::"r" (val));
-}
-
-/* RCSR - Reset Cause Status Register */
-static inline u32 read_rcsr(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c0, c1, 0":"=r" (val));
- return val;
-}
-
-extern unsigned long get_iop_tick_rate(void);
-#endif
-
-/*
- * IOP13XX I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP13XX_MAX_RAM_SIZE 0x80000000UL /* 2GB */
-#define IOP13XX_PCI_OFFSET IOP13XX_MAX_RAM_SIZE
-
-/* PCI MAP
- * bus range cpu phys cpu virt note
- * 0x0000.0000 + 2GB (n/a) (n/a) inbound, 1:1 mapping with Physical RAM
- * 0x8000.0000 + 928M 0x1.8000.0000 (ioremap) PCIX outbound memory window
- * 0x8000.0000 + 928M 0x2.8000.0000 (ioremap) PCIE outbound memory window
- *
- * IO MAP
- * 0x00000 + 64K 0x0.fffb.0000 0xfee0.0000 PCIX outbound i/o window
- * 0x10000 + 64K 0x0.fffd.0000 0xfee1.0000 PCIE outbound i/o window
- */
-#define IOP13XX_PCIX_LOWER_IO_PA 0xfffb0000UL
-#define IOP13XX_PCIX_LOWER_IO_BA 0x0UL /* OIOTVR */
-
-#define IOP13XX_PCIX_MEM_PHYS_OFFSET 0x100000000ULL
-#define IOP13XX_PCIX_MEM_WINDOW_SIZE 0x3a000000UL
-#define IOP13XX_PCIX_LOWER_MEM_BA (PHYS_OFFSET + IOP13XX_PCI_OFFSET)
-#define IOP13XX_PCIX_LOWER_MEM_PA (IOP13XX_PCIX_MEM_PHYS_OFFSET +\
- IOP13XX_PCIX_LOWER_MEM_BA)
-#define IOP13XX_PCIX_UPPER_MEM_PA (IOP13XX_PCIX_LOWER_MEM_PA +\
- IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PCIX_UPPER_MEM_BA (IOP13XX_PCIX_LOWER_MEM_BA +\
- IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
-
-#define IOP13XX_PCIX_MEM_COOKIE 0x80000000UL
-#define IOP13XX_PCIX_LOWER_MEM_RA IOP13XX_PCIX_MEM_COOKIE
-#define IOP13XX_PCIX_UPPER_MEM_RA (IOP13XX_PCIX_LOWER_MEM_RA +\
- IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PCIX_MEM_OFFSET (IOP13XX_PCIX_MEM_COOKIE -\
- IOP13XX_PCIX_LOWER_MEM_BA)
-
-/* PCI-E ranges */
-#define IOP13XX_PCIE_LOWER_IO_PA 0xfffd0000UL
-#define IOP13XX_PCIE_LOWER_IO_BA 0x10000UL /* OIOTVR */
-
-#define IOP13XX_PCIE_MEM_PHYS_OFFSET 0x200000000ULL
-#define IOP13XX_PCIE_MEM_WINDOW_SIZE 0x3a000000UL
-#define IOP13XX_PCIE_LOWER_MEM_BA (PHYS_OFFSET + IOP13XX_PCI_OFFSET)
-#define IOP13XX_PCIE_LOWER_MEM_PA (IOP13XX_PCIE_MEM_PHYS_OFFSET +\
- IOP13XX_PCIE_LOWER_MEM_BA)
-#define IOP13XX_PCIE_UPPER_MEM_PA (IOP13XX_PCIE_LOWER_MEM_PA +\
- IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_UPPER_MEM_BA (IOP13XX_PCIE_LOWER_MEM_BA +\
- IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
-
-/* All 0xc000.0000 - 0xfdff.ffff addresses belong to PCIe */
-#define IOP13XX_PCIE_MEM_COOKIE 0xc0000000UL
-#define IOP13XX_PCIE_LOWER_MEM_RA IOP13XX_PCIE_MEM_COOKIE
-#define IOP13XX_PCIE_UPPER_MEM_RA (IOP13XX_PCIE_LOWER_MEM_RA +\
- IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_MEM_OFFSET (IOP13XX_PCIE_MEM_COOKIE -\
- IOP13XX_PCIE_LOWER_MEM_BA)
-
-/* PBI Ranges */
-#define IOP13XX_PBI_LOWER_MEM_PA 0xf0000000UL
-#define IOP13XX_PBI_MEM_WINDOW_SIZE 0x04000000UL
-#define IOP13XX_PBI_MEM_COOKIE 0xfa000000UL
-#define IOP13XX_PBI_LOWER_MEM_RA IOP13XX_PBI_MEM_COOKIE
-#define IOP13XX_PBI_UPPER_MEM_RA (IOP13XX_PBI_LOWER_MEM_RA +\
- IOP13XX_PBI_MEM_WINDOW_SIZE - 1)
-
-/*
- * IOP13XX chipset registers
- */
-#define IOP13XX_PMMR_PHYS_MEM_BASE 0xffd80000UL /* PMMR phys. address */
-#define IOP13XX_PMMR_VIRT_MEM_BASE (void __iomem *)(0xfee80000UL) /* PMMR phys. address */
-#define IOP13XX_PMMR_MEM_WINDOW_SIZE 0x80000
-#define IOP13XX_PMMR_UPPER_MEM_VA (IOP13XX_PMMR_VIRT_MEM_BASE +\
- IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PMMR_UPPER_MEM_PA (IOP13XX_PMMR_PHYS_MEM_BASE +\
- IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PMMR_VIRT_TO_PHYS(addr) (((addr) - IOP13XX_PMMR_VIRT_MEM_BASE)\
- + IOP13XX_PMMR_PHYS_MEM_BASE)
-#define IOP13XX_PMMR_PHYS_TO_VIRT(addr) (((addr) - IOP13XX_PMMR_PHYS_MEM_BASE)\
- + IOP13XX_PMMR_VIRT_MEM_BASE)
-#define IOP13XX_REG_ADDR32(reg) (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
-#define IOP13XX_REG_ADDR16(reg) (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
-#define IOP13XX_REG_ADDR8(reg) (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
-#define IOP13XX_REG_ADDR32_PHYS(reg) (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
-#define IOP13XX_REG_ADDR16_PHYS(reg) (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
-#define IOP13XX_REG_ADDR8_PHYS(reg) (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
-#define IOP13XX_PMMR_SIZE 0x00080000
-
-/*=================== Defines for Platform Devices =====================*/
-#define IOP13XX_UART0_PHYS (IOP13XX_PMMR_PHYS_MEM_BASE + 0x00002300)
-#define IOP13XX_UART1_PHYS (IOP13XX_PMMR_PHYS_MEM_BASE + 0x00002340)
-#define IOP13XX_UART0_VIRT (IOP13XX_PMMR_VIRT_MEM_BASE + 0x00002300)
-#define IOP13XX_UART1_VIRT (IOP13XX_PMMR_VIRT_MEM_BASE + 0x00002340)
-
-#define IOP13XX_I2C0_PHYS (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002500)
-#define IOP13XX_I2C1_PHYS (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002520)
-#define IOP13XX_I2C2_PHYS (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002540)
-#define IOP13XX_I2C0_VIRT (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002500)
-#define IOP13XX_I2C1_VIRT (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002520)
-#define IOP13XX_I2C2_VIRT (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002540)
-
-/* ATU selection flags */
-/* IOP13XX_INIT_ATU_DEFAULT = Rely on CONFIG_IOP13XX_ATU* */
-#define IOP13XX_INIT_ATU_DEFAULT (0)
-#define IOP13XX_INIT_ATU_ATUX (1 << 0)
-#define IOP13XX_INIT_ATU_ATUE (1 << 1)
-#define IOP13XX_INIT_ATU_NONE (1 << 2)
-
-/* UART selection flags */
-/* IOP13XX_INIT_UART_DEFAULT = Rely on CONFIG_IOP13XX_UART* */
-#define IOP13XX_INIT_UART_DEFAULT (0)
-#define IOP13XX_INIT_UART_0 (1 << 0)
-#define IOP13XX_INIT_UART_1 (1 << 1)
-
-/* I2C selection flags */
-/* IOP13XX_INIT_I2C_DEFAULT = Rely on CONFIG_IOP13XX_I2C* */
-#define IOP13XX_INIT_I2C_DEFAULT (0)
-#define IOP13XX_INIT_I2C_0 (1 << 0)
-#define IOP13XX_INIT_I2C_1 (1 << 1)
-#define IOP13XX_INIT_I2C_2 (1 << 2)
-
-/* ADMA selection flags */
-/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
-#define IOP13XX_INIT_ADMA_DEFAULT (0)
-#define IOP13XX_INIT_ADMA_0 (1 << 0)
-#define IOP13XX_INIT_ADMA_1 (1 << 1)
-#define IOP13XX_INIT_ADMA_2 (1 << 2)
-
-/* Platform devices */
-#define IQ81340_NUM_UART 2
-#define IQ81340_NUM_I2C 3
-#define IQ81340_NUM_PHYS_MAP_FLASH 1
-#define IQ81340_NUM_ADMA 3
-#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
- IQ81340_NUM_I2C + \
- IQ81340_NUM_PHYS_MAP_FLASH + \
- IQ81340_NUM_ADMA)
-
-/*========================== PMMR offsets for key registers ============*/
-#define IOP13XX_ATU0_PMMR_OFFSET 0x00048000
-#define IOP13XX_ATU1_PMMR_OFFSET 0x0004c000
-#define IOP13XX_ATU2_PMMR_OFFSET 0x0004d000
-#define IOP13XX_ADMA0_PMMR_OFFSET 0x00000000
-#define IOP13XX_ADMA1_PMMR_OFFSET 0x00000200
-#define IOP13XX_ADMA2_PMMR_OFFSET 0x00000400
-#define IOP13XX_PBI_PMMR_OFFSET 0x00001580
-#define IOP13XX_MU_PMMR_OFFSET 0x00004000
-#define IOP13XX_ESSR0_PMMR_OFFSET 0x00002188
-#define IOP13XX_ESSR0 IOP13XX_REG_ADDR32(0x00002188)
-
-#define IOP13XX_ESSR0_IFACE_MASK 0x00004000 /* Interface PCI-X / PCI-E */
-#define IOP13XX_CONTROLLER_ONLY (1 << 14)
-#define IOP13XX_INTERFACE_SEL_PCIX (1 << 15)
-
-#define IOP13XX_PMON_PMMR_OFFSET 0x0001A000
-#define IOP13XX_PMON_BASE (IOP13XX_PMMR_VIRT_MEM_BASE +\
- IOP13XX_PMON_PMMR_OFFSET)
-#define IOP13XX_PMON_PHYSBASE (IOP13XX_PMMR_PHYS_MEM_BASE +\
- IOP13XX_PMON_PMMR_OFFSET)
-
-#define IOP13XX_PMON_CMD0 (IOP13XX_PMON_BASE + 0x0)
-#define IOP13XX_PMON_EVR0 (IOP13XX_PMON_BASE + 0x4)
-#define IOP13XX_PMON_STS0 (IOP13XX_PMON_BASE + 0x8)
-#define IOP13XX_PMON_DATA0 (IOP13XX_PMON_BASE + 0xC)
-
-#define IOP13XX_PMON_CMD3 (IOP13XX_PMON_BASE + 0x30)
-#define IOP13XX_PMON_EVR3 (IOP13XX_PMON_BASE + 0x34)
-#define IOP13XX_PMON_STS3 (IOP13XX_PMON_BASE + 0x38)
-#define IOP13XX_PMON_DATA3 (IOP13XX_PMON_BASE + 0x3C)
-
-#define IOP13XX_PMON_CMD7 (IOP13XX_PMON_BASE + 0x70)
-#define IOP13XX_PMON_EVR7 (IOP13XX_PMON_BASE + 0x74)
-#define IOP13XX_PMON_STS7 (IOP13XX_PMON_BASE + 0x78)
-#define IOP13XX_PMON_DATA7 (IOP13XX_PMON_BASE + 0x7C)
-
-#define IOP13XX_PMONEN (IOP13XX_PMMR_VIRT_MEM_BASE + 0x4E040)
-#define IOP13XX_PMONSTAT (IOP13XX_PMMR_VIRT_MEM_BASE + 0x4E044)
-
-/*================================ATU===================================*/
-#define IOP13XX_ATUX_OFFSET(ofs) IOP13XX_REG_ADDR32(\
- iop13xx_atux_pmmr_offset + (ofs))
-
-#define IOP13XX_ATUX_DID IOP13XX_REG_ADDR16(\
- iop13xx_atux_pmmr_offset + 0x2)
-
-#define IOP13XX_ATUX_ATUCMD IOP13XX_REG_ADDR16(\
- iop13xx_atux_pmmr_offset + 0x4)
-#define IOP13XX_ATUX_ATUSR IOP13XX_REG_ADDR16(\
- iop13xx_atux_pmmr_offset + 0x6)
-
-#define IOP13XX_ATUX_IABAR0 IOP13XX_ATUX_OFFSET(0x10)
-#define IOP13XX_ATUX_IAUBAR0 IOP13XX_ATUX_OFFSET(0x14)
-#define IOP13XX_ATUX_IABAR1 IOP13XX_ATUX_OFFSET(0x18)
-#define IOP13XX_ATUX_IAUBAR1 IOP13XX_ATUX_OFFSET(0x1c)
-#define IOP13XX_ATUX_IABAR2 IOP13XX_ATUX_OFFSET(0x20)
-#define IOP13XX_ATUX_IAUBAR2 IOP13XX_ATUX_OFFSET(0x24)
-#define IOP13XX_ATUX_IALR0 IOP13XX_ATUX_OFFSET(0x40)
-#define IOP13XX_ATUX_IATVR0 IOP13XX_ATUX_OFFSET(0x44)
-#define IOP13XX_ATUX_IAUTVR0 IOP13XX_ATUX_OFFSET(0x48)
-#define IOP13XX_ATUX_IALR1 IOP13XX_ATUX_OFFSET(0x4c)
-#define IOP13XX_ATUX_IATVR1 IOP13XX_ATUX_OFFSET(0x50)
-#define IOP13XX_ATUX_IAUTVR1 IOP13XX_ATUX_OFFSET(0x54)
-#define IOP13XX_ATUX_IALR2 IOP13XX_ATUX_OFFSET(0x58)
-#define IOP13XX_ATUX_IATVR2 IOP13XX_ATUX_OFFSET(0x5c)
-#define IOP13XX_ATUX_IAUTVR2 IOP13XX_ATUX_OFFSET(0x60)
-#define IOP13XX_ATUX_ATUCR IOP13XX_ATUX_OFFSET(0x70)
-#define IOP13XX_ATUX_PCSR IOP13XX_ATUX_OFFSET(0x74)
-#define IOP13XX_ATUX_ATUISR IOP13XX_ATUX_OFFSET(0x78)
-#define IOP13XX_ATUX_PCIXSR IOP13XX_ATUX_OFFSET(0xD4)
-#define IOP13XX_ATUX_IABAR3 IOP13XX_ATUX_OFFSET(0x200)
-#define IOP13XX_ATUX_IAUBAR3 IOP13XX_ATUX_OFFSET(0x204)
-#define IOP13XX_ATUX_IALR3 IOP13XX_ATUX_OFFSET(0x208)
-#define IOP13XX_ATUX_IATVR3 IOP13XX_ATUX_OFFSET(0x20c)
-#define IOP13XX_ATUX_IAUTVR3 IOP13XX_ATUX_OFFSET(0x210)
-
-#define IOP13XX_ATUX_OIOBAR IOP13XX_ATUX_OFFSET(0x300)
-#define IOP13XX_ATUX_OIOWTVR IOP13XX_ATUX_OFFSET(0x304)
-#define IOP13XX_ATUX_OUMBAR0 IOP13XX_ATUX_OFFSET(0x308)
-#define IOP13XX_ATUX_OUMWTVR0 IOP13XX_ATUX_OFFSET(0x30c)
-#define IOP13XX_ATUX_OUMBAR1 IOP13XX_ATUX_OFFSET(0x310)
-#define IOP13XX_ATUX_OUMWTVR1 IOP13XX_ATUX_OFFSET(0x314)
-#define IOP13XX_ATUX_OUMBAR2 IOP13XX_ATUX_OFFSET(0x318)
-#define IOP13XX_ATUX_OUMWTVR2 IOP13XX_ATUX_OFFSET(0x31c)
-#define IOP13XX_ATUX_OUMBAR3 IOP13XX_ATUX_OFFSET(0x320)
-#define IOP13XX_ATUX_OUMWTVR3 IOP13XX_ATUX_OFFSET(0x324)
-#define IOP13XX_ATUX_OUDMABAR IOP13XX_ATUX_OFFSET(0x328)
-#define IOP13XX_ATUX_OUMSIBAR IOP13XX_ATUX_OFFSET(0x32c)
-#define IOP13XX_ATUX_OCCAR IOP13XX_ATUX_OFFSET(0x330)
-#define IOP13XX_ATUX_OCCDR IOP13XX_ATUX_OFFSET(0x334)
-
-#define IOP13XX_ATUX_ATUCR_OUT_EN (1 << 1)
-#define IOP13XX_ATUX_PCSR_CENTRAL_RES (1 << 25)
-#define IOP13XX_ATUX_PCSR_P_RSTOUT (1 << 21)
-#define IOP13XX_ATUX_PCSR_OUT_Q_BUSY (1 << 15)
-#define IOP13XX_ATUX_PCSR_IN_Q_BUSY (1 << 14)
-#define IOP13XX_ATUX_PCSR_FREQ_OFFSET (16)
-
-#define IOP13XX_ATUX_STAT_PCI_IFACE_ERR (1 << 18)
-#define IOP13XX_ATUX_STAT_VPD_ADDR (1 << 17)
-#define IOP13XX_ATUX_STAT_INT_PAR_ERR (1 << 16)
-#define IOP13XX_ATUX_STAT_CFG_WRITE (1 << 15)
-#define IOP13XX_ATUX_STAT_ERR_COR (1 << 14)
-#define IOP13XX_ATUX_STAT_TX_SCEM (1 << 13)
-#define IOP13XX_ATUX_STAT_REC_SCEM (1 << 12)
-#define IOP13XX_ATUX_STAT_POWER_TRAN (1 << 11)
-#define IOP13XX_ATUX_STAT_TX_SERR (1 << 10)
-#define IOP13XX_ATUX_STAT_DET_PAR_ERR (1 << 9 )
-#define IOP13XX_ATUX_STAT_BIST (1 << 8 )
-#define IOP13XX_ATUX_STAT_INT_REC_MABORT (1 << 7 )
-#define IOP13XX_ATUX_STAT_REC_SERR (1 << 4 )
-#define IOP13XX_ATUX_STAT_EXT_REC_MABORT (1 << 3 )
-#define IOP13XX_ATUX_STAT_EXT_REC_TABORT (1 << 2 )
-#define IOP13XX_ATUX_STAT_EXT_SIG_TABORT (1 << 1 )
-#define IOP13XX_ATUX_STAT_MASTER_DATA_PAR (1 << 0 )
-
-#define IOP13XX_ATUX_PCIXSR_BUS_NUM (8)
-#define IOP13XX_ATUX_PCIXSR_DEV_NUM (3)
-#define IOP13XX_ATUX_PCIXSR_FUNC_NUM (0)
-
-#define IOP13XX_ATUX_IALR_DISABLE 0x00000001
-#define IOP13XX_ATUX_OUMBAR_ENABLE 0x80000000
-
-#define IOP13XX_ATUE_OFFSET(ofs) IOP13XX_REG_ADDR32(\
- iop13xx_atue_pmmr_offset + (ofs))
-
-#define IOP13XX_ATUE_DID IOP13XX_REG_ADDR16(\
- iop13xx_atue_pmmr_offset + 0x2)
-#define IOP13XX_ATUE_ATUCMD IOP13XX_REG_ADDR16(\
- iop13xx_atue_pmmr_offset + 0x4)
-#define IOP13XX_ATUE_ATUSR IOP13XX_REG_ADDR16(\
- iop13xx_atue_pmmr_offset + 0x6)
-
-#define IOP13XX_ATUE_IABAR0 IOP13XX_ATUE_OFFSET(0x10)
-#define IOP13XX_ATUE_IAUBAR0 IOP13XX_ATUE_OFFSET(0x14)
-#define IOP13XX_ATUE_IABAR1 IOP13XX_ATUE_OFFSET(0x18)
-#define IOP13XX_ATUE_IAUBAR1 IOP13XX_ATUE_OFFSET(0x1c)
-#define IOP13XX_ATUE_IABAR2 IOP13XX_ATUE_OFFSET(0x20)
-#define IOP13XX_ATUE_IAUBAR2 IOP13XX_ATUE_OFFSET(0x24)
-#define IOP13XX_ATUE_IALR0 IOP13XX_ATUE_OFFSET(0x40)
-#define IOP13XX_ATUE_IATVR0 IOP13XX_ATUE_OFFSET(0x44)
-#define IOP13XX_ATUE_IAUTVR0 IOP13XX_ATUE_OFFSET(0x48)
-#define IOP13XX_ATUE_IALR1 IOP13XX_ATUE_OFFSET(0x4c)
-#define IOP13XX_ATUE_IATVR1 IOP13XX_ATUE_OFFSET(0x50)
-#define IOP13XX_ATUE_IAUTVR1 IOP13XX_ATUE_OFFSET(0x54)
-#define IOP13XX_ATUE_IALR2 IOP13XX_ATUE_OFFSET(0x58)
-#define IOP13XX_ATUE_IATVR2 IOP13XX_ATUE_OFFSET(0x5c)
-#define IOP13XX_ATUE_IAUTVR2 IOP13XX_ATUE_OFFSET(0x60)
-#define IOP13XX_ATUE_PE_LSTS IOP13XX_REG_ADDR16(\
- iop13xx_atue_pmmr_offset + 0xe2)
-#define IOP13XX_ATUE_OIOWTVR IOP13XX_ATUE_OFFSET(0x304)
-#define IOP13XX_ATUE_OUMBAR0 IOP13XX_ATUE_OFFSET(0x308)
-#define IOP13XX_ATUE_OUMWTVR0 IOP13XX_ATUE_OFFSET(0x30c)
-#define IOP13XX_ATUE_OUMBAR1 IOP13XX_ATUE_OFFSET(0x310)
-#define IOP13XX_ATUE_OUMWTVR1 IOP13XX_ATUE_OFFSET(0x314)
-#define IOP13XX_ATUE_OUMBAR2 IOP13XX_ATUE_OFFSET(0x318)
-#define IOP13XX_ATUE_OUMWTVR2 IOP13XX_ATUE_OFFSET(0x31c)
-#define IOP13XX_ATUE_OUMBAR3 IOP13XX_ATUE_OFFSET(0x320)
-#define IOP13XX_ATUE_OUMWTVR3 IOP13XX_ATUE_OFFSET(0x324)
-
-#define IOP13XX_ATUE_ATUCR IOP13XX_ATUE_OFFSET(0x70)
-#define IOP13XX_ATUE_PCSR IOP13XX_ATUE_OFFSET(0x74)
-#define IOP13XX_ATUE_ATUISR IOP13XX_ATUE_OFFSET(0x78)
-#define IOP13XX_ATUE_OIOBAR IOP13XX_ATUE_OFFSET(0x300)
-#define IOP13XX_ATUE_OCCAR IOP13XX_ATUE_OFFSET(0x32c)
-#define IOP13XX_ATUE_OCCDR IOP13XX_ATUE_OFFSET(0x330)
-
-#define IOP13XX_ATUE_PIE_STS IOP13XX_ATUE_OFFSET(0x384)
-#define IOP13XX_ATUE_PIE_MSK IOP13XX_ATUE_OFFSET(0x388)
-
-#define IOP13XX_ATUE_ATUCR_IVM (1 << 6)
-#define IOP13XX_ATUE_ATUCR_OUT_EN (1 << 1)
-#define IOP13XX_ATUE_OCCAR_BUS_NUM (24)
-#define IOP13XX_ATUE_OCCAR_DEV_NUM (19)
-#define IOP13XX_ATUE_OCCAR_FUNC_NUM (16)
-#define IOP13XX_ATUE_OCCAR_EXT_REG (8)
-#define IOP13XX_ATUE_OCCAR_REG (2)
-
-#define IOP13XX_ATUE_PCSR_BUS_NUM (24)
-#define IOP13XX_ATUE_PCSR_DEV_NUM (19)
-#define IOP13XX_ATUE_PCSR_FUNC_NUM (16)
-#define IOP13XX_ATUE_PCSR_OUT_Q_BUSY (1 << 15)
-#define IOP13XX_ATUE_PCSR_IN_Q_BUSY (1 << 14)
-#define IOP13XX_ATUE_PCSR_END_POINT (1 << 13)
-#define IOP13XX_ATUE_PCSR_LLRB_BUSY (1 << 12)
-
-#define IOP13XX_ATUE_PCSR_BUS_NUM_MASK (0xff)
-#define IOP13XX_ATUE_PCSR_DEV_NUM_MASK (0x1f)
-#define IOP13XX_ATUE_PCSR_FUNC_NUM_MASK (0x7)
-
-#define IOP13XX_ATUE_PCSR_CORE_RESET (8)
-#define IOP13XX_ATUE_PCSR_FUNC_NUM (16)
-
-#define IOP13XX_ATUE_LSTS_TRAINING (1 << 11)
-#define IOP13XX_ATUE_STAT_SLOT_PWR_MSG (1 << 28)
-#define IOP13XX_ATUE_STAT_PME (1 << 27)
-#define IOP13XX_ATUE_STAT_HOT_PLUG_MSG (1 << 26)
-#define IOP13XX_ATUE_STAT_IVM (1 << 25)
-#define IOP13XX_ATUE_STAT_BIST (1 << 24)
-#define IOP13XX_ATUE_STAT_CFG_WRITE (1 << 18)
-#define IOP13XX_ATUE_STAT_VPD_ADDR (1 << 17)
-#define IOP13XX_ATUE_STAT_POWER_TRAN (1 << 16)
-#define IOP13XX_ATUE_STAT_HALT_ON_ERROR (1 << 13)
-#define IOP13XX_ATUE_STAT_ROOT_SYS_ERR (1 << 12)
-#define IOP13XX_ATUE_STAT_ROOT_ERR_MSG (1 << 11)
-#define IOP13XX_ATUE_STAT_PCI_IFACE_ERR (1 << 10)
-#define IOP13XX_ATUE_STAT_ERR_COR (1 << 9 )
-#define IOP13XX_ATUE_STAT_ERR_UNCOR (1 << 8 )
-#define IOP13XX_ATUE_STAT_CRS (1 << 7 )
-#define IOP13XX_ATUE_STAT_LNK_DWN (1 << 6 )
-#define IOP13XX_ATUE_STAT_INT_REC_MABORT (1 << 5 )
-#define IOP13XX_ATUE_STAT_DET_PAR_ERR (1 << 4 )
-#define IOP13XX_ATUE_STAT_EXT_REC_MABORT (1 << 3 )
-#define IOP13XX_ATUE_STAT_SIG_TABORT (1 << 2 )
-#define IOP13XX_ATUE_STAT_EXT_REC_TABORT (1 << 1 )
-#define IOP13XX_ATUE_STAT_MASTER_DATA_PAR (1 << 0 )
-
-#define IOP13XX_ATUE_ESTAT_REC_UNSUPPORTED_COMP_REQ (1 << 31)
-#define IOP13XX_ATUE_ESTAT_REC_COMPLETER_ABORT (1 << 30)
-#define IOP13XX_ATUE_ESTAT_TX_POISONED_TLP (1 << 29)
-#define IOP13XX_ATUE_ESTAT_TX_PAR_ERR (1 << 28)
-#define IOP13XX_ATUE_ESTAT_REC_UNSUPPORTED_REQ (1 << 20)
-#define IOP13XX_ATUE_ESTAT_REC_ECRC_ERR (1 << 19)
-#define IOP13XX_ATUE_ESTAT_REC_MALFORMED_TLP (1 << 18)
-#define IOP13XX_ATUE_ESTAT_TX_RECEIVER_OVERFLOW (1 << 17)
-#define IOP13XX_ATUE_ESTAT_REC_UNEXPECTED_COMP (1 << 16)
-#define IOP13XX_ATUE_ESTAT_INT_COMP_ABORT (1 << 15)
-#define IOP13XX_ATUE_ESTAT_COMP_TIMEOUT (1 << 14)
-#define IOP13XX_ATUE_ESTAT_FLOW_CONTROL_ERR (1 << 13)
-#define IOP13XX_ATUE_ESTAT_REC_POISONED_TLP (1 << 12)
-#define IOP13XX_ATUE_ESTAT_DATA_LNK_ERR (1 << 4 )
-#define IOP13XX_ATUE_ESTAT_TRAINING_ERR (1 << 0 )
-
-#define IOP13XX_ATUE_IALR_DISABLE (0x00000001)
-#define IOP13XX_ATUE_OUMBAR_ENABLE (0x80000000)
-#define IOP13XX_ATU_OUMBAR_FUNC_NUM (28)
-#define IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK (0x7)
-/*=======================================================================*/
-
-/*============================MESSAGING UNIT=============================*/
-#define IOP13XX_MU_OFFSET(ofs) IOP13XX_REG_ADDR32(IOP13XX_MU_PMMR_OFFSET +\
- (ofs))
-
-#define IOP13XX_MU_IMR0 IOP13XX_MU_OFFSET(0x10)
-#define IOP13XX_MU_IMR1 IOP13XX_MU_OFFSET(0x14)
-#define IOP13XX_MU_OMR0 IOP13XX_MU_OFFSET(0x18)
-#define IOP13XX_MU_OMR1 IOP13XX_MU_OFFSET(0x1C)
-#define IOP13XX_MU_IDR IOP13XX_MU_OFFSET(0x20)
-#define IOP13XX_MU_IISR IOP13XX_MU_OFFSET(0x24)
-#define IOP13XX_MU_IIMR IOP13XX_MU_OFFSET(0x28)
-#define IOP13XX_MU_ODR IOP13XX_MU_OFFSET(0x2C)
-#define IOP13XX_MU_OISR IOP13XX_MU_OFFSET(0x30)
-#define IOP13XX_MU_OIMR IOP13XX_MU_OFFSET(0x34)
-#define IOP13XX_MU_IRCSR IOP13XX_MU_OFFSET(0x38)
-#define IOP13XX_MU_ORCSR IOP13XX_MU_OFFSET(0x3C)
-#define IOP13XX_MU_MIMR IOP13XX_MU_OFFSET(0x48)
-#define IOP13XX_MU_MUCR IOP13XX_MU_OFFSET(0x50)
-#define IOP13XX_MU_QBAR IOP13XX_MU_OFFSET(0x54)
-#define IOP13XX_MU_MUBAR IOP13XX_MU_OFFSET(0x84)
-
-#define IOP13XX_MU_WINDOW_SIZE (8 * 1024)
-#define IOP13XX_MU_BASE_PHYS (0xff000000)
-#define IOP13XX_MU_BASE_PCI (0xff000000)
-#define IOP13XX_MU_MIMR_PCI (IOP13XX_MU_BASE_PCI + 0x48)
-#define IOP13XX_MU_MIMR_CORE_SELECT (15)
-/*=======================================================================*/
-
-/*==============================ADMA UNITS===============================*/
-#define IOP13XX_ADMA_PHYS_BASE(chan) IOP13XX_REG_ADDR32_PHYS((chan << 9))
-#define IOP13XX_ADMA_UPPER_PA(chan) (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
-
-/*==============================XSI BRIDGE===============================*/
-#define IOP13XX_XBG_BECSR IOP13XX_REG_ADDR32(0x178c)
-#define IOP13XX_XBG_BERAR IOP13XX_REG_ADDR32(0x1790)
-#define IOP13XX_XBG_BERUAR IOP13XX_REG_ADDR32(0x1794)
-#define is_atue_occdr_error(x) ((__raw_readl(IOP13XX_XBG_BERAR) == \
- IOP13XX_PMMR_VIRT_TO_PHYS(\
- IOP13XX_ATUE_OCCDR))\
- && (__raw_readl(IOP13XX_XBG_BECSR) & 1))
-#define is_atux_occdr_error(x) ((__raw_readl(IOP13XX_XBG_BERAR) == \
- IOP13XX_PMMR_VIRT_TO_PHYS(\
- IOP13XX_ATUX_OCCDR))\
- && (__raw_readl(IOP13XX_XBG_BECSR) & 1))
-/*=======================================================================*/
-
-#define IOP13XX_PBI_OFFSET(ofs) IOP13XX_REG_ADDR32(IOP13XX_PBI_PMMR_OFFSET +\
- (ofs))
-
-#define IOP13XX_PBI_CR IOP13XX_PBI_OFFSET(0x0)
-#define IOP13XX_PBI_SR IOP13XX_PBI_OFFSET(0x4)
-#define IOP13XX_PBI_BAR0 IOP13XX_PBI_OFFSET(0x8)
-#define IOP13XX_PBI_LR0 IOP13XX_PBI_OFFSET(0xc)
-#define IOP13XX_PBI_BAR1 IOP13XX_PBI_OFFSET(0x10)
-#define IOP13XX_PBI_LR1 IOP13XX_PBI_OFFSET(0x14)
-
-#define IOP13XX_PROCESSOR_FREQ IOP13XX_REG_ADDR32(0x2180)
-
-/* Watchdog timer definitions */
-#define IOP_WDTCR_EN_ARM 0x1e1e1e1e
-#define IOP_WDTCR_EN 0xe1e1e1e1
-#define IOP_WDTCR_DIS_ARM 0x1f1f1f1f
-#define IOP_WDTCR_DIS 0xf1f1f1f1
-#define IOP_RCSR_WDT (1 << 5) /* reset caused by watchdog timer */
-#define IOP13XX_WDTSR_WRITE_EN (1 << 31) /* used to speed up reset requests */
-#define IOP13XX_WDTCR_IB_RESET (1 << 0)
-
-#endif /* _IOP13XX_HW_H_ */
diff --git a/arch/arm/mach-iop13xx/include/mach/iq81340.h b/arch/arm/mach-iop13xx/include/mach/iq81340.h
deleted file mode 100644
index d7ad27a95558..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/iq81340.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IQ81340_H_
-#define _IQ81340_H_
-
-#define IQ81340_PCE_BAR0 IOP13XX_PBI_LOWER_MEM_RA
-#define IQ81340_PCE_BAR1 (IQ81340_PCE_BAR0 + 0x02000000)
-
-#define IQ81340_FLASHBASE IQ81340_PCE_BAR0 /* Flash */
-
-#define IQ81340_PCE_BAR1_OFFSET(a) (IQ81340_PCE_BAR1 + (a))
-
-#define IQ81340_PRD_CODE IQ81340_PCE_BAR1_OFFSET(0)
-#define IQ81340_BRD_STEP IQ81340_PCE_BAR1_OFFSET(0x10000)
-#define IQ81340_CPLD_REV IQ81340_PCE_BAR1_OFFSET(0x20000)
-#define IQ81340_LED IQ81340_PCE_BAR1_OFFSET(0x30000)
-#define IQ81340_LHEX IQ81340_PCE_BAR1_OFFSET(0x40000)
-#define IQ81340_RHEX IQ81340_PCE_BAR1_OFFSET(0x50000)
-#define IQ81340_BUZZER IQ81340_PCE_BAR1_OFFSET(0x60000)
-#define IQ81340_32K_NVRAM IQ81340_PCE_BAR1_OFFSET(0x70000)
-#define IQ81340_256K_NVRAM IQ81340_PCE_BAR1_OFFSET(0x80000)
-#define IQ81340_ROTARY_SW IQ81340_PCE_BAR1_OFFSET(0xd0000)
-#define IQ81340_BATT_STAT IQ81340_PCE_BAR1_OFFSET(0xf0000)
-#define IQ81340_CMP_FLSH IQ81340_PCE_BAR1_OFFSET(0x1000000) /* 16MB */
-
-#define PBI_CF_IDE_BASE (IQ81340_CMP_FLSH)
-#define PBI_CF_BAR_ADDR (IOP13XX_PBI_BAR1)
-
-
-#endif /* _IQ81340_H_ */
diff --git a/arch/arm/mach-iop13xx/include/mach/irqs.h b/arch/arm/mach-iop13xx/include/mach/irqs.h
deleted file mode 100644
index cd6b6375c050..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/irqs.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP13XX_IRQS_H_
-#define _IOP13XX_IRQS_H_
-
-#ifndef __ASSEMBLER__
-#include <linux/types.h>
-
-/* INTPND0 CP6 R0 Page 3
- */
-static inline u32 read_intpnd_0(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c0, c3, 0":"=r" (val));
- return val;
-}
-
-/* INTPND1 CP6 R1 Page 3
- */
-static inline u32 read_intpnd_1(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c1, c3, 0":"=r" (val));
- return val;
-}
-
-/* INTPND2 CP6 R2 Page 3
- */
-static inline u32 read_intpnd_2(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c2, c3, 0":"=r" (val));
- return val;
-}
-
-/* INTPND3 CP6 R3 Page 3
- */
-static inline u32 read_intpnd_3(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c3, c3, 0":"=r" (val));
- return val;
-}
-#endif
-
-#define INTBASE 0
-#define INTSIZE_4 1
-
-/*
- * iop34x chipset interrupts
- */
-#define IOP13XX_IRQ(x) (IOP13XX_IRQ_OFS + (x))
-
-/*
- * On IRQ or FIQ register
- */
-#define IRQ_IOP13XX_ADMA0_EOT (0)
-#define IRQ_IOP13XX_ADMA0_EOC (1)
-#define IRQ_IOP13XX_ADMA1_EOT (2)
-#define IRQ_IOP13XX_ADMA1_EOC (3)
-#define IRQ_IOP13XX_ADMA2_EOT (4)
-#define IRQ_IOP13XX_ADMA2_EOC (5)
-#define IRQ_IOP134_WATCHDOG (6)
-#define IRQ_IOP13XX_RSVD_7 (7)
-#define IRQ_IOP13XX_TIMER0 (8)
-#define IRQ_IOP13XX_TIMER1 (9)
-#define IRQ_IOP13XX_I2C_0 (10)
-#define IRQ_IOP13XX_I2C_1 (11)
-#define IRQ_IOP13XX_MSG (12)
-#define IRQ_IOP13XX_MSGIBQ (13)
-#define IRQ_IOP13XX_ATU_IM (14)
-#define IRQ_IOP13XX_ATU_BIST (15)
-#define IRQ_IOP13XX_PPMU (16)
-#define IRQ_IOP13XX_COREPMU (17)
-#define IRQ_IOP13XX_CORECACHE (18)
-#define IRQ_IOP13XX_RSVD_19 (19)
-#define IRQ_IOP13XX_RSVD_20 (20)
-#define IRQ_IOP13XX_RSVD_21 (21)
-#define IRQ_IOP13XX_RSVD_22 (22)
-#define IRQ_IOP13XX_RSVD_23 (23)
-#define IRQ_IOP13XX_XINT0 (24)
-#define IRQ_IOP13XX_XINT1 (25)
-#define IRQ_IOP13XX_XINT2 (26)
-#define IRQ_IOP13XX_XINT3 (27)
-#define IRQ_IOP13XX_XINT4 (28)
-#define IRQ_IOP13XX_XINT5 (29)
-#define IRQ_IOP13XX_XINT6 (30)
-#define IRQ_IOP13XX_XINT7 (31)
- /* IINTSRC1 bit */
-#define IRQ_IOP13XX_XINT8 (32) /* 0 */
-#define IRQ_IOP13XX_XINT9 (33) /* 1 */
-#define IRQ_IOP13XX_XINT10 (34) /* 2 */
-#define IRQ_IOP13XX_XINT11 (35) /* 3 */
-#define IRQ_IOP13XX_XINT12 (36) /* 4 */
-#define IRQ_IOP13XX_XINT13 (37) /* 5 */
-#define IRQ_IOP13XX_XINT14 (38) /* 6 */
-#define IRQ_IOP13XX_XINT15 (39) /* 7 */
-#define IRQ_IOP13XX_RSVD_40 (40) /* 8 */
-#define IRQ_IOP13XX_RSVD_41 (41) /* 9 */
-#define IRQ_IOP13XX_RSVD_42 (42) /* 10 */
-#define IRQ_IOP13XX_RSVD_43 (43) /* 11 */
-#define IRQ_IOP13XX_RSVD_44 (44) /* 12 */
-#define IRQ_IOP13XX_RSVD_45 (45) /* 13 */
-#define IRQ_IOP13XX_RSVD_46 (46) /* 14 */
-#define IRQ_IOP13XX_RSVD_47 (47) /* 15 */
-#define IRQ_IOP13XX_RSVD_48 (48) /* 16 */
-#define IRQ_IOP13XX_RSVD_49 (49) /* 17 */
-#define IRQ_IOP13XX_RSVD_50 (50) /* 18 */
-#define IRQ_IOP13XX_UART0 (51) /* 19 */
-#define IRQ_IOP13XX_UART1 (52) /* 20 */
-#define IRQ_IOP13XX_PBIE (53) /* 21 */
-#define IRQ_IOP13XX_ATU_CRW (54) /* 22 */
-#define IRQ_IOP13XX_ATU_ERR (55) /* 23 */
-#define IRQ_IOP13XX_MCU_ERR (56) /* 24 */
-#define IRQ_IOP13XX_ADMA0_ERR (57) /* 25 */
-#define IRQ_IOP13XX_ADMA1_ERR (58) /* 26 */
-#define IRQ_IOP13XX_ADMA2_ERR (59) /* 27 */
-#define IRQ_IOP13XX_RSVD_60 (60) /* 28 */
-#define IRQ_IOP13XX_RSVD_61 (61) /* 29 */
-#define IRQ_IOP13XX_MSG_ERR (62) /* 30 */
-#define IRQ_IOP13XX_RSVD_63 (63) /* 31 */
- /* IINTSRC2 bit */
-#define IRQ_IOP13XX_INTERPROC (64) /* 0 */
-#define IRQ_IOP13XX_RSVD_65 (65) /* 1 */
-#define IRQ_IOP13XX_RSVD_66 (66) /* 2 */
-#define IRQ_IOP13XX_RSVD_67 (67) /* 3 */
-#define IRQ_IOP13XX_RSVD_68 (68) /* 4 */
-#define IRQ_IOP13XX_RSVD_69 (69) /* 5 */
-#define IRQ_IOP13XX_RSVD_70 (70) /* 6 */
-#define IRQ_IOP13XX_RSVD_71 (71) /* 7 */
-#define IRQ_IOP13XX_RSVD_72 (72) /* 8 */
-#define IRQ_IOP13XX_RSVD_73 (73) /* 9 */
-#define IRQ_IOP13XX_RSVD_74 (74) /* 10 */
-#define IRQ_IOP13XX_RSVD_75 (75) /* 11 */
-#define IRQ_IOP13XX_RSVD_76 (76) /* 12 */
-#define IRQ_IOP13XX_RSVD_77 (77) /* 13 */
-#define IRQ_IOP13XX_RSVD_78 (78) /* 14 */
-#define IRQ_IOP13XX_RSVD_79 (79) /* 15 */
-#define IRQ_IOP13XX_RSVD_80 (80) /* 16 */
-#define IRQ_IOP13XX_RSVD_81 (81) /* 17 */
-#define IRQ_IOP13XX_RSVD_82 (82) /* 18 */
-#define IRQ_IOP13XX_RSVD_83 (83) /* 19 */
-#define IRQ_IOP13XX_RSVD_84 (84) /* 20 */
-#define IRQ_IOP13XX_RSVD_85 (85) /* 21 */
-#define IRQ_IOP13XX_RSVD_86 (86) /* 22 */
-#define IRQ_IOP13XX_RSVD_87 (87) /* 23 */
-#define IRQ_IOP13XX_RSVD_88 (88) /* 24 */
-#define IRQ_IOP13XX_RSVD_89 (89) /* 25 */
-#define IRQ_IOP13XX_RSVD_90 (90) /* 26 */
-#define IRQ_IOP13XX_RSVD_91 (91) /* 27 */
-#define IRQ_IOP13XX_RSVD_92 (92) /* 28 */
-#define IRQ_IOP13XX_RSVD_93 (93) /* 29 */
-#define IRQ_IOP13XX_SIB_ERR (94) /* 30 */
-#define IRQ_IOP13XX_SRAM_ERR (95) /* 31 */
- /* IINTSRC3 bit */
-#define IRQ_IOP13XX_I2C_2 (96) /* 0 */
-#define IRQ_IOP13XX_ATUE_BIST (97) /* 1 */
-#define IRQ_IOP13XX_ATUE_CRW (98) /* 2 */
-#define IRQ_IOP13XX_ATUE_ERR (99) /* 3 */
-#define IRQ_IOP13XX_IMU (100) /* 4 */
-#define IRQ_IOP13XX_RSVD_101 (101) /* 5 */
-#define IRQ_IOP13XX_RSVD_102 (102) /* 6 */
-#define IRQ_IOP13XX_TPMI0_OUT (103) /* 7 */
-#define IRQ_IOP13XX_TPMI1_OUT (104) /* 8 */
-#define IRQ_IOP13XX_TPMI2_OUT (105) /* 9 */
-#define IRQ_IOP13XX_TPMI3_OUT (106) /* 10 */
-#define IRQ_IOP13XX_ATUE_IMA (107) /* 11 */
-#define IRQ_IOP13XX_ATUE_IMB (108) /* 12 */
-#define IRQ_IOP13XX_ATUE_IMC (109) /* 13 */
-#define IRQ_IOP13XX_ATUE_IMD (110) /* 14 */
-#define IRQ_IOP13XX_MU_MSI_TB (111) /* 15 */
-#define IRQ_IOP13XX_RSVD_112 (112) /* 16 */
-#define IRQ_IOP13XX_INBD_MSI (113) /* 17 */
-#define IRQ_IOP13XX_RSVD_114 (114) /* 18 */
-#define IRQ_IOP13XX_RSVD_115 (115) /* 19 */
-#define IRQ_IOP13XX_RSVD_116 (116) /* 20 */
-#define IRQ_IOP13XX_RSVD_117 (117) /* 21 */
-#define IRQ_IOP13XX_RSVD_118 (118) /* 22 */
-#define IRQ_IOP13XX_RSVD_119 (119) /* 23 */
-#define IRQ_IOP13XX_RSVD_120 (120) /* 24 */
-#define IRQ_IOP13XX_RSVD_121 (121) /* 25 */
-#define IRQ_IOP13XX_RSVD_122 (122) /* 26 */
-#define IRQ_IOP13XX_RSVD_123 (123) /* 27 */
-#define IRQ_IOP13XX_RSVD_124 (124) /* 28 */
-#define IRQ_IOP13XX_RSVD_125 (125) /* 29 */
-#define IRQ_IOP13XX_RSVD_126 (126) /* 30 */
-#define IRQ_IOP13XX_HPI (127) /* 31 */
-
-#ifdef CONFIG_PCI_MSI
-#define IRQ_IOP13XX_MSI_0 (IRQ_IOP13XX_HPI + 1)
-#define NR_IOP13XX_IRQS (IRQ_IOP13XX_MSI_0 + 128)
-#else
-#define NR_IOP13XX_IRQS (IRQ_IOP13XX_HPI + 1)
-#endif
-
-#endif /* _IOP13XX_IRQ_H_ */
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
deleted file mode 100644
index 32da0e09c6a3..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <mach/hardware.h>
-
-#ifndef __ASSEMBLY__
-
-#if defined(CONFIG_ARCH_IOP13XX)
-#define IOP13XX_PMMR_V_START (IOP13XX_PMMR_VIRT_MEM_BASE)
-#define IOP13XX_PMMR_V_END (IOP13XX_PMMR_VIRT_MEM_BASE + IOP13XX_PMMR_SIZE)
-#define IOP13XX_PMMR_P_START (IOP13XX_PMMR_PHYS_MEM_BASE)
-#define IOP13XX_PMMR_P_END (IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_SIZE)
-
-static inline dma_addr_t __virt_to_lbus(void __iomem *x)
-{
- return x + IOP13XX_PMMR_PHYS_MEM_BASE - IOP13XX_PMMR_VIRT_MEM_BASE;
-}
-
-static inline void __iomem *__lbus_to_virt(dma_addr_t x)
-{
- return x + IOP13XX_PMMR_VIRT_MEM_BASE - IOP13XX_PMMR_PHYS_MEM_BASE;
-}
-
-#define __is_lbus_dma(a) \
- ((a) >= IOP13XX_PMMR_P_START && (a) < IOP13XX_PMMR_P_END)
-
-#define __is_lbus_virt(a) \
- ((a) >= IOP13XX_PMMR_V_START && (a) < IOP13XX_PMMR_V_END)
-
-/* Device is an lbus device if it is on the platform bus of the IOP13XX */
-#define is_lbus_device(dev) \
- (dev && strncmp(dev->bus->name, "platform", 8) == 0)
-
-#define __arch_dma_to_virt(dev, addr) \
- ({ \
- void * __virt; \
- dma_addr_t __dma = addr; \
- if (is_lbus_device(dev) && __is_lbus_dma(__dma)) \
- __virt = __lbus_to_virt(__dma); \
- else \
- __virt = (void *)__phys_to_virt(__dma); \
- __virt; \
- })
-
-#define __arch_virt_to_dma(dev, addr) \
- ({ \
- void * __virt = addr; \
- dma_addr_t __dma; \
- if (is_lbus_device(dev) && __is_lbus_virt(__virt)) \
- __dma = __virt_to_lbus(__virt); \
- else \
- __dma = __virt_to_phys((unsigned long)__virt); \
- __dma; \
- })
-
-#define __arch_pfn_to_dma(dev, pfn) \
- ({ \
- /* __is_lbus_virt() can never be true for RAM pages */ \
- (dma_addr_t)__pfn_to_phys(pfn); \
- })
-
-#define __arch_dma_to_pfn(dev, addr) __phys_to_pfn(addr)
-
-#endif /* CONFIG_ARCH_IOP13XX */
-#endif /* !ASSEMBLY */
-
-#endif
diff --git a/arch/arm/mach-iop13xx/include/mach/time.h b/arch/arm/mach-iop13xx/include/mach/time.h
deleted file mode 100644
index 2c2d7532d5c3..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/time.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP13XX_TIME_H_
-#define _IOP13XX_TIME_H_
-
-#include <mach/irqs.h>
-
-#define IRQ_IOP_TIMER0 IRQ_IOP13XX_TIMER0
-
-#define IOP_TMR_EN 0x02
-#define IOP_TMR_RELOAD 0x04
-#define IOP_TMR_PRIVILEGED 0x08
-#define IOP_TMR_RATIO_1_1 0x00
-
-#define IOP13XX_XSI_FREQ_RATIO_MASK (3 << 19)
-#define IOP13XX_XSI_FREQ_RATIO_2 (0 << 19)
-#define IOP13XX_XSI_FREQ_RATIO_3 (1 << 19)
-#define IOP13XX_XSI_FREQ_RATIO_4 (2 << 19)
-#define IOP13XX_CORE_FREQ_MASK (7 << 16)
-#define IOP13XX_CORE_FREQ_600 (0 << 16)
-#define IOP13XX_CORE_FREQ_667 (1 << 16)
-#define IOP13XX_CORE_FREQ_800 (2 << 16)
-#define IOP13XX_CORE_FREQ_933 (3 << 16)
-#define IOP13XX_CORE_FREQ_1000 (4 << 16)
-#define IOP13XX_CORE_FREQ_1200 (5 << 16)
-
-void iop_init_time(unsigned long tickrate);
-
-static inline unsigned long iop13xx_core_freq(void)
-{
- unsigned long freq = __raw_readl(IOP13XX_PROCESSOR_FREQ);
- freq &= IOP13XX_CORE_FREQ_MASK;
- switch (freq) {
- case IOP13XX_CORE_FREQ_600:
- return 600000000;
- case IOP13XX_CORE_FREQ_667:
- return 667000000;
- case IOP13XX_CORE_FREQ_800:
- return 800000000;
- case IOP13XX_CORE_FREQ_933:
- return 933000000;
- case IOP13XX_CORE_FREQ_1000:
- return 1000000000;
- case IOP13XX_CORE_FREQ_1200:
- return 1200000000;
- default:
- printk("%s: warning unknown frequency, defaulting to 800MHz\n",
- __func__);
- }
-
- return 800000000;
-}
-
-static inline unsigned long iop13xx_xsi_bus_ratio(void)
-{
- unsigned long ratio = __raw_readl(IOP13XX_PROCESSOR_FREQ);
- ratio &= IOP13XX_XSI_FREQ_RATIO_MASK;
- switch (ratio) {
- case IOP13XX_XSI_FREQ_RATIO_2:
- return 2;
- case IOP13XX_XSI_FREQ_RATIO_3:
- return 3;
- case IOP13XX_XSI_FREQ_RATIO_4:
- return 4;
- default:
- printk("%s: warning unknown ratio, defaulting to 2\n",
- __func__);
- }
-
- return 2;
-}
-
-static inline u32 read_tmr0(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c0, c9, 0" : "=r" (val));
- return val;
-}
-
-static inline void write_tmr0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val));
-}
-
-static inline void write_tmr1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (val));
-}
-
-static inline u32 read_tcr0(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c2, c9, 0" : "=r" (val));
- return val;
-}
-
-static inline void write_tcr0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c2, c9, 0" : : "r" (val));
-}
-
-static inline u32 read_tcr1(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
- return val;
-}
-
-static inline void write_tcr1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c3, c9, 0" : : "r" (val));
-}
-
-static inline void write_trr0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (val));
-}
-
-static inline void write_trr1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (val));
-}
-
-static inline void write_tisr(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (val));
-}
-#endif
diff --git a/arch/arm/mach-iop13xx/include/mach/uncompress.h b/arch/arm/mach-iop13xx/include/mach/uncompress.h
deleted file mode 100644
index c62903041d11..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/types.h>
-#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-
-#define UART_BASE ((volatile u32 *)IOP13XX_UART1_PHYS)
-#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
-
-static inline void putc(char c)
-{
- while ((UART_BASE[UART_LSR] & TX_DONE) != TX_DONE)
- barrier();
- UART_BASE[UART_TX] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c
deleted file mode 100644
index 253d446b1f3f..000000000000
--- a/arch/arm/mach-iop13xx/io.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iop13xx custom ioremap implementation
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-
-#include "pci.h"
-
-static void __iomem *__iop13xx_ioremap_caller(phys_addr_t cookie,
- size_t size, unsigned int mtype, void *caller)
-{
- void __iomem * retval;
-
- switch (cookie) {
- case IOP13XX_PCIX_LOWER_MEM_RA ... IOP13XX_PCIX_UPPER_MEM_RA:
- if (unlikely(!iop13xx_atux_mem_base))
- retval = NULL;
- else
- retval = (iop13xx_atux_mem_base +
- (cookie - IOP13XX_PCIX_LOWER_MEM_RA));
- break;
- case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA:
- if (unlikely(!iop13xx_atue_mem_base))
- retval = NULL;
- else
- retval = (iop13xx_atue_mem_base +
- (cookie - IOP13XX_PCIE_LOWER_MEM_RA));
- break;
- case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
- retval = __arm_ioremap_caller(IOP13XX_PBI_LOWER_MEM_PA +
- (cookie - IOP13XX_PBI_LOWER_MEM_RA),
- size, mtype, __builtin_return_address(0));
- break;
- case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA:
- retval = IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
- break;
- default:
- retval = __arm_ioremap_caller(cookie, size, mtype,
- caller);
- }
-
- return retval;
-}
-
-static void __iop13xx_iounmap(volatile void __iomem *addr)
-{
- if (iop13xx_atue_mem_base)
- if (addr >= (void __iomem *) iop13xx_atue_mem_base &&
- addr < (void __iomem *) (iop13xx_atue_mem_base +
- iop13xx_atue_mem_size))
- goto skip;
-
- if (iop13xx_atux_mem_base)
- if (addr >= (void __iomem *) iop13xx_atux_mem_base &&
- addr < (void __iomem *) (iop13xx_atux_mem_base +
- iop13xx_atux_mem_size))
- goto skip;
-
- switch ((u32) addr) {
- case (u32)IOP13XX_PMMR_VIRT_MEM_BASE ... (u32)IOP13XX_PMMR_UPPER_MEM_VA:
- goto skip;
- }
- __iounmap(addr);
-
-skip:
- return;
-}
-
-void __init iop13xx_init_early(void)
-{
- arch_ioremap_caller = __iop13xx_ioremap_caller;
- arch_iounmap = __iop13xx_iounmap;
-}
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
deleted file mode 100644
index b3ce5cb228cc..000000000000
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iq81340mc board support
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-#include <linux/pci.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include "pci.h"
-#include <asm/mach/time.h>
-#include <mach/time.h>
-
-extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
-
-static int __init
-iq81340mc_pcix_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
-{
- switch (idsel) {
- case 1:
- switch (pin) {
- case 1: return ATUX_INTB;
- case 2: return ATUX_INTC;
- case 3: return ATUX_INTD;
- case 4: return ATUX_INTA;
- default: return -1;
- }
- case 2:
- switch (pin) {
- case 1: return ATUX_INTC;
- case 2: return ATUX_INTD;
- case 3: return ATUX_INTC;
- case 4: return ATUX_INTD;
- default: return -1;
- }
- default: return -1;
- }
-}
-
-static struct hw_pci iq81340mc_pci __initdata = {
- .nr_controllers = 0,
- .setup = iop13xx_pci_setup,
- .map_irq = iq81340mc_pcix_map_irq,
- .scan = iop13xx_scan_bus,
- .preinit = iop13xx_pci_init,
-};
-
-static int __init iq81340mc_pci_init(void)
-{
- iop13xx_atu_select(&iq81340mc_pci);
- pci_common_init(&iq81340mc_pci);
- iop13xx_map_pci_memory();
-
- return 0;
-}
-
-static void __init iq81340mc_init(void)
-{
- iop13xx_platform_init();
- iq81340mc_pci_init();
- iop13xx_add_tpmi_devices();
-}
-
-static void __init iq81340mc_timer_init(void)
-{
- unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
- printk(KERN_DEBUG "%s: bus frequency: %lu\n", __func__, bus_freq);
- iop_init_time(bus_freq);
-}
-
-MACHINE_START(IQ81340MC, "Intel IQ81340MC")
- /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .atag_offset = 0x100,
- .init_early = iop13xx_init_early,
- .map_io = iop13xx_map_io,
- .init_irq = iop13xx_init_irq,
- .init_time = iq81340mc_timer_init,
- .init_machine = iq81340mc_init,
- .restart = iop13xx_restart,
- .nr_irqs = NR_IOP13XX_IRQS,
-MACHINE_END
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
deleted file mode 100644
index 123845dcf2d3..000000000000
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iq81340sc board support
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-#include <linux/pci.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include "pci.h"
-#include <asm/mach/time.h>
-#include <mach/time.h>
-
-extern int init_atu;
-
-static int __init
-iq81340sc_atux_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
-{
- WARN_ON(idsel < 1 || idsel > 2);
-
- switch (idsel) {
- case 1:
- switch (pin) {
- case 1: return ATUX_INTB;
- case 2: return ATUX_INTC;
- case 3: return ATUX_INTD;
- case 4: return ATUX_INTA;
- default: return -1;
- }
- case 2:
- switch (pin) {
- case 1: return ATUX_INTC;
- case 2: return ATUX_INTC;
- case 3: return ATUX_INTC;
- case 4: return ATUX_INTC;
- default: return -1;
- }
- default: return -1;
- }
-}
-
-static struct hw_pci iq81340sc_pci __initdata = {
- .nr_controllers = 0,
- .setup = iop13xx_pci_setup,
- .scan = iop13xx_scan_bus,
- .map_irq = iq81340sc_atux_map_irq,
- .preinit = iop13xx_pci_init
-};
-
-static int __init iq81340sc_pci_init(void)
-{
- iop13xx_atu_select(&iq81340sc_pci);
- pci_common_init(&iq81340sc_pci);
- iop13xx_map_pci_memory();
-
- return 0;
-}
-
-static void __init iq81340sc_init(void)
-{
- iop13xx_platform_init();
- iq81340sc_pci_init();
- iop13xx_add_tpmi_devices();
-}
-
-static void __init iq81340sc_timer_init(void)
-{
- unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
- printk(KERN_DEBUG "%s: bus frequency: %lu\n", __func__, bus_freq);
- iop_init_time(bus_freq);
-}
-
-MACHINE_START(IQ81340SC, "Intel IQ81340SC")
- /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .atag_offset = 0x100,
- .init_early = iop13xx_init_early,
- .map_io = iop13xx_map_io,
- .init_irq = iop13xx_init_irq,
- .init_time = iq81340sc_timer_init,
- .init_machine = iq81340sc_init,
- .restart = iop13xx_restart,
- .nr_irqs = NR_IOP13XX_IRQS,
-MACHINE_END
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
deleted file mode 100644
index 0e24ba7a1309..000000000000
--- a/arch/arm/mach-iop13xx/irq.c
+++ /dev/null
@@ -1,227 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iop13xx IRQ handling / support functions
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/sysctl.h>
-#include <linux/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include "msi.h"
-
-/* INTCTL0 CP6 R0 Page 4
- */
-static u32 read_intctl_0(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val));
- return val;
-}
-static void write_intctl_0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val));
-}
-
-/* INTCTL1 CP6 R1 Page 4
- */
-static u32 read_intctl_1(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val));
- return val;
-}
-static void write_intctl_1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val));
-}
-
-/* INTCTL2 CP6 R2 Page 4
- */
-static u32 read_intctl_2(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val));
- return val;
-}
-static void write_intctl_2(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val));
-}
-
-/* INTCTL3 CP6 R3 Page 4
- */
-static u32 read_intctl_3(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val));
- return val;
-}
-static void write_intctl_3(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val));
-}
-
-/* INTSTR0 CP6 R0 Page 5
- */
-static void write_intstr_0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val));
-}
-
-/* INTSTR1 CP6 R1 Page 5
- */
-static void write_intstr_1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val));
-}
-
-/* INTSTR2 CP6 R2 Page 5
- */
-static void write_intstr_2(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val));
-}
-
-/* INTSTR3 CP6 R3 Page 5
- */
-static void write_intstr_3(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val));
-}
-
-/* INTBASE CP6 R0 Page 2
- */
-static void write_intbase(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val));
-}
-
-/* INTSIZE CP6 R2 Page 2
- */
-static void write_intsize(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val));
-}
-
-/* 0 = Interrupt Masked and 1 = Interrupt not masked */
-static void
-iop13xx_irq_mask0 (struct irq_data *d)
-{
- write_intctl_0(read_intctl_0() & ~(1 << (d->irq - 0)));
-}
-
-static void
-iop13xx_irq_mask1 (struct irq_data *d)
-{
- write_intctl_1(read_intctl_1() & ~(1 << (d->irq - 32)));
-}
-
-static void
-iop13xx_irq_mask2 (struct irq_data *d)
-{
- write_intctl_2(read_intctl_2() & ~(1 << (d->irq - 64)));
-}
-
-static void
-iop13xx_irq_mask3 (struct irq_data *d)
-{
- write_intctl_3(read_intctl_3() & ~(1 << (d->irq - 96)));
-}
-
-static void
-iop13xx_irq_unmask0(struct irq_data *d)
-{
- write_intctl_0(read_intctl_0() | (1 << (d->irq - 0)));
-}
-
-static void
-iop13xx_irq_unmask1(struct irq_data *d)
-{
- write_intctl_1(read_intctl_1() | (1 << (d->irq - 32)));
-}
-
-static void
-iop13xx_irq_unmask2(struct irq_data *d)
-{
- write_intctl_2(read_intctl_2() | (1 << (d->irq - 64)));
-}
-
-static void
-iop13xx_irq_unmask3(struct irq_data *d)
-{
- write_intctl_3(read_intctl_3() | (1 << (d->irq - 96)));
-}
-
-static struct irq_chip iop13xx_irqchip1 = {
- .name = "IOP13xx-1",
- .irq_ack = iop13xx_irq_mask0,
- .irq_mask = iop13xx_irq_mask0,
- .irq_unmask = iop13xx_irq_unmask0,
-};
-
-static struct irq_chip iop13xx_irqchip2 = {
- .name = "IOP13xx-2",
- .irq_ack = iop13xx_irq_mask1,
- .irq_mask = iop13xx_irq_mask1,
- .irq_unmask = iop13xx_irq_unmask1,
-};
-
-static struct irq_chip iop13xx_irqchip3 = {
- .name = "IOP13xx-3",
- .irq_ack = iop13xx_irq_mask2,
- .irq_mask = iop13xx_irq_mask2,
- .irq_unmask = iop13xx_irq_unmask2,
-};
-
-static struct irq_chip iop13xx_irqchip4 = {
- .name = "IOP13xx-4",
- .irq_ack = iop13xx_irq_mask3,
- .irq_mask = iop13xx_irq_mask3,
- .irq_unmask = iop13xx_irq_unmask3,
-};
-
-extern void iop_init_cp6_handler(void);
-
-void __init iop13xx_init_irq(void)
-{
- unsigned int i;
-
- iop_init_cp6_handler();
-
- /* disable all interrupts */
- write_intctl_0(0);
- write_intctl_1(0);
- write_intctl_2(0);
- write_intctl_3(0);
-
- /* treat all as IRQ */
- write_intstr_0(0);
- write_intstr_1(0);
- write_intstr_2(0);
- write_intstr_3(0);
-
- /* initialize the interrupt vector generator */
- write_intbase(INTBASE);
- write_intsize(INTSIZE_4);
-
- for(i = 0; i <= IRQ_IOP13XX_HPI; i++) {
- if (i < 32)
- irq_set_chip(i, &iop13xx_irqchip1);
- else if (i < 64)
- irq_set_chip(i, &iop13xx_irqchip2);
- else if (i < 96)
- irq_set_chip(i, &iop13xx_irqchip3);
- else
- irq_set_chip(i, &iop13xx_irqchip4);
-
- irq_set_handler(i, handle_level_irq);
- irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
- }
-
- iop13xx_msi_init();
-}
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
deleted file mode 100644
index f4d70cba1dd1..000000000000
--- a/arch/arm/mach-iop13xx/msi.c
+++ /dev/null
@@ -1,152 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-iop13xx/msi.c
- *
- * PCI MSI support for the iop13xx processor
- *
- * Copyright (c) 2006, Intel Corporation.
- */
-#include <linux/pci.h>
-#include <linux/msi.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <mach/irqs.h>
-
-/* IMIPR0 CP6 R8 Page 1
- */
-static u32 read_imipr_0(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c8, c1, 0":"=r" (val));
- return val;
-}
-static void write_imipr_0(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c8, c1, 0"::"r" (val));
-}
-
-/* IMIPR1 CP6 R9 Page 1
- */
-static u32 read_imipr_1(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c9, c1, 0":"=r" (val));
- return val;
-}
-static void write_imipr_1(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c9, c1, 0"::"r" (val));
-}
-
-/* IMIPR2 CP6 R10 Page 1
- */
-static u32 read_imipr_2(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c10, c1, 0":"=r" (val));
- return val;
-}
-static void write_imipr_2(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c10, c1, 0"::"r" (val));
-}
-
-/* IMIPR3 CP6 R11 Page 1
- */
-static u32 read_imipr_3(void)
-{
- u32 val;
- asm volatile("mrc p6, 0, %0, c11, c1, 0":"=r" (val));
- return val;
-}
-static void write_imipr_3(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c11, c1, 0"::"r" (val));
-}
-
-static u32 (*read_imipr[])(void) = {
- read_imipr_0,
- read_imipr_1,
- read_imipr_2,
- read_imipr_3,
-};
-
-static void (*write_imipr[])(u32) = {
- write_imipr_0,
- write_imipr_1,
- write_imipr_2,
- write_imipr_3,
-};
-
-static void iop13xx_msi_handler(struct irq_desc *desc)
-{
- int i, j;
- unsigned long status;
-
- /* read IMIPR registers and find any active interrupts,
- * then call ISR for each active interrupt
- */
- for (i = 0; i < ARRAY_SIZE(read_imipr); i++) {
- status = (read_imipr[i])();
- if (!status)
- continue;
-
- do {
- j = find_first_bit(&status, 32);
- (write_imipr[i])(1 << j); /* write back to clear bit */
- generic_handle_irq(IRQ_IOP13XX_MSI_0 + j + (32*i));
- status = (read_imipr[i])();
- } while (status);
- }
-}
-
-void __init iop13xx_msi_init(void)
-{
- irq_set_chained_handler(IRQ_IOP13XX_INBD_MSI, iop13xx_msi_handler);
-}
-
-static void iop13xx_msi_nop(struct irq_data *d)
-{
- return;
-}
-
-static struct irq_chip iop13xx_msi_chip = {
- .name = "PCI-MSI",
- .irq_ack = iop13xx_msi_nop,
- .irq_enable = pci_msi_unmask_irq,
- .irq_disable = pci_msi_mask_irq,
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
-};
-
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
-{
- int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1);
- struct msi_msg msg;
-
- if (irq < 0)
- return irq;
-
- if (irq >= NR_IOP13XX_IRQS) {
- irq_free_desc(irq);
- return -ENOSPC;
- }
-
- irq_set_msi_desc(irq, desc);
-
- msg.address_hi = 0x0;
- msg.address_lo = IOP13XX_MU_MIMR_PCI;
-
- id = iop13xx_cpu_id();
- msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f);
-
- pci_write_msi_msg(irq, &msg);
- irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
-
- return 0;
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
- irq_free_desc(irq);
-}
diff --git a/arch/arm/mach-iop13xx/msi.h b/arch/arm/mach-iop13xx/msi.h
deleted file mode 100644
index 766dcfaaa353..000000000000
--- a/arch/arm/mach-iop13xx/msi.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP13XX_MSI_H_
-#define _IOP13XX_MSI_H_
-#ifdef CONFIG_PCI_MSI
-void iop13xx_msi_init(void);
-#else
-static inline void iop13xx_msi_init(void)
-{
- return;
-}
-#endif
-#endif
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
deleted file mode 100644
index 46ea06e906cc..000000000000
--- a/arch/arm/mach-iop13xx/pci.c
+++ /dev/null
@@ -1,1115 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iop13xx PCI support
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <linux/export.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <linux/sizes.h>
-#include <asm/signal.h>
-#include <asm/mach/pci.h>
-#include "pci.h"
-
-#define IOP13XX_PCI_DEBUG 0
-#define PRINTK(x...) ((void)(IOP13XX_PCI_DEBUG && printk(x)))
-
-u32 iop13xx_atux_pmmr_offset; /* This offset can change based on strapping */
-u32 iop13xx_atue_pmmr_offset; /* This offset can change based on strapping */
-static struct pci_bus *pci_bus_atux = 0;
-static struct pci_bus *pci_bus_atue = 0;
-void __iomem *iop13xx_atue_mem_base;
-void __iomem *iop13xx_atux_mem_base;
-size_t iop13xx_atue_mem_size;
-size_t iop13xx_atux_mem_size;
-
-EXPORT_SYMBOL(iop13xx_atue_mem_base);
-EXPORT_SYMBOL(iop13xx_atux_mem_base);
-EXPORT_SYMBOL(iop13xx_atue_mem_size);
-EXPORT_SYMBOL(iop13xx_atux_mem_size);
-
-int init_atu = 0; /* Flag to select which ATU(s) to initialize / disable */
-static unsigned long atux_trhfa_timeout = 0; /* Trhfa = RST# high to first
- access */
-
-/* Scan the initialized busses and ioremap the requested memory range
- */
-void iop13xx_map_pci_memory(void)
-{
- int atu;
- struct pci_bus *bus;
- struct pci_dev *dev;
- resource_size_t end = 0;
-
- for (atu = 0; atu < 2; atu++) {
- bus = atu ? pci_bus_atue : pci_bus_atux;
- if (bus) {
- list_for_each_entry(dev, &bus->devices, bus_list) {
- int i;
- int max = 7;
-
- if (dev->subordinate)
- max = DEVICE_COUNT_RESOURCE;
-
- for (i = 0; i < max; i++) {
- struct resource *res = &dev->resource[i];
- if (res->flags & IORESOURCE_MEM)
- end = max(res->end, end);
- }
- }
-
- switch(atu) {
- case 0:
- iop13xx_atux_mem_size =
- (end - IOP13XX_PCIX_LOWER_MEM_RA) + 1;
-
- /* 16MB align the request */
- if (iop13xx_atux_mem_size & (SZ_16M - 1)) {
- iop13xx_atux_mem_size &= ~(SZ_16M - 1);
- iop13xx_atux_mem_size += SZ_16M;
- }
-
- if (end) {
- iop13xx_atux_mem_base = __arm_ioremap_pfn(
- __phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA)
- , 0, iop13xx_atux_mem_size, MT_DEVICE);
- if (!iop13xx_atux_mem_base) {
- printk("%s: atux allocation "
- "failed\n", __func__);
- BUG();
- }
- } else
- iop13xx_atux_mem_size = 0;
- PRINTK("%s: atu: %d bus_size: %d mem_base: %p\n",
- __func__, atu, iop13xx_atux_mem_size,
- iop13xx_atux_mem_base);
- break;
- case 1:
- iop13xx_atue_mem_size =
- (end - IOP13XX_PCIE_LOWER_MEM_RA) + 1;
-
- /* 16MB align the request */
- if (iop13xx_atue_mem_size & (SZ_16M - 1)) {
- iop13xx_atue_mem_size &= ~(SZ_16M - 1);
- iop13xx_atue_mem_size += SZ_16M;
- }
-
- if (end) {
- iop13xx_atue_mem_base = __arm_ioremap_pfn(
- __phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA)
- , 0, iop13xx_atue_mem_size, MT_DEVICE);
- if (!iop13xx_atue_mem_base) {
- printk("%s: atue allocation "
- "failed\n", __func__);
- BUG();
- }
- } else
- iop13xx_atue_mem_size = 0;
- PRINTK("%s: atu: %d bus_size: %d mem_base: %p\n",
- __func__, atu, iop13xx_atue_mem_size,
- iop13xx_atue_mem_base);
- break;
- }
-
- printk("%s: Initialized (%uM @ resource/virtual: %08lx/%p)\n",
- atu ? "ATUE" : "ATUX",
- (atu ? iop13xx_atue_mem_size : iop13xx_atux_mem_size) /
- SZ_1M,
- atu ? IOP13XX_PCIE_LOWER_MEM_RA :
- IOP13XX_PCIX_LOWER_MEM_RA,
- atu ? iop13xx_atue_mem_base :
- iop13xx_atux_mem_base);
- end = 0;
- }
-
- }
-}
-
-static int iop13xx_atu_function(int atu)
-{
- int func = 0;
- /* the function number depends on the value of the
- * IOP13XX_INTERFACE_SEL_PCIX reset strap
- * see C-Spec section 3.17
- */
- switch(atu) {
- case IOP13XX_INIT_ATU_ATUX:
- if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
- func = 5;
- else
- func = 0;
- break;
- case IOP13XX_INIT_ATU_ATUE:
- if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
- func = 0;
- else
- func = 5;
- break;
- default:
- BUG();
- }
-
- return func;
-}
-
-/* iop13xx_atux_cfg_address - format a configuration address for atux
- * @bus: Target bus to access
- * @devfn: Combined device number and function number
- * @where: Desired register's address offset
- *
- * Convert the parameters to a configuration address formatted
- * according the PCI-X 2.0 specification
- */
-static u32 iop13xx_atux_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
- struct pci_sys_data *sys = bus->sysdata;
- u32 addr;
-
- if (sys->busnr == bus->number)
- addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
- else
- addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
- addr |= PCI_FUNC(devfn) << 8 | ((where & 0xff) & ~3);
- addr |= ((where & 0xf00) >> 8) << 24; /* upper register number */
-
- return addr;
-}
-
-/* iop13xx_atue_cfg_address - format a configuration address for atue
- * @bus: Target bus to access
- * @devfn: Combined device number and function number
- * @where: Desired register's address offset
- *
- * Convert the parameters to an address usable by the ATUE_OCCAR
- */
-static u32 iop13xx_atue_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
- struct pci_sys_data *sys = bus->sysdata;
- u32 addr;
-
- PRINTK("iop13xx_atue_cfg_address: bus: %d dev: %d func: %d",
- bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
- addr = ((u32) bus->number) << IOP13XX_ATUE_OCCAR_BUS_NUM |
- ((u32) PCI_SLOT(devfn)) << IOP13XX_ATUE_OCCAR_DEV_NUM |
- ((u32) PCI_FUNC(devfn)) << IOP13XX_ATUE_OCCAR_FUNC_NUM |
- (where & ~0x3);
-
- if (sys->busnr != bus->number)
- addr |= 1; /* type 1 access */
-
- return addr;
-}
-
-/* This routine checks the status of the last configuration cycle. If an error
- * was detected it returns >0, else it returns a 0. The errors being checked
- * are parity, master abort, target abort (master and target). These types of
- * errors occur during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop13xx_atux_pci_status(int clear)
-{
- unsigned int status;
- int err = 0;
-
- /*
- * Check the status registers.
- */
- status = __raw_readw(IOP13XX_ATUX_ATUSR);
- if (status & IOP_PCI_STATUS_ERROR)
- {
- PRINTK("\t\t\tPCI error: ATUSR %#08x", status);
- if(clear)
- __raw_writew(status & IOP_PCI_STATUS_ERROR,
- IOP13XX_ATUX_ATUSR);
- err = 1;
- }
- status = __raw_readl(IOP13XX_ATUX_ATUISR);
- if (status & IOP13XX_ATUX_ATUISR_ERROR)
- {
- PRINTK("\t\t\tPCI error interrupt: ATUISR %#08x", status);
- if(clear)
- __raw_writel(status & IOP13XX_ATUX_ATUISR_ERROR,
- IOP13XX_ATUX_ATUISR);
- err = 1;
- }
- return err;
-}
-
-/* Simply write the address register and read the configuration
- * data. Note that the data dependency on %0 encourages an abort
- * to be detected before we return.
- */
-static u32 iop13xx_atux_read(unsigned long addr)
-{
- u32 val;
-
- __asm__ __volatile__(
- "str %1, [%2]\n\t"
- "ldr %0, [%3]\n\t"
- "mov %0, %0\n\t"
- : "=r" (val)
- : "r" (addr), "r" (IOP13XX_ATUX_OCCAR), "r" (IOP13XX_ATUX_OCCDR));
-
- return val;
-}
-
-/* The read routines must check the error status of the last configuration
- * cycle. If there was an error, the routine returns all hex f's.
- */
-static int
-iop13xx_atux_read_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 *value)
-{
- unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where);
- u32 val = iop13xx_atux_read(addr) >> ((where & 3) * 8);
-
- if (iop13xx_atux_pci_status(1) || is_atux_occdr_error()) {
- __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3,
- IOP13XX_XBG_BECSR);
- val = 0xffffffff;
- }
-
- *value = val;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop13xx_atux_write_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 value)
-{
- unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where);
- u32 val;
-
- if (size != 4) {
- val = iop13xx_atux_read(addr);
- if (!iop13xx_atux_pci_status(1) == 0)
- return PCIBIOS_SUCCESSFUL;
-
- where = (where & 3) * 8;
-
- if (size == 1)
- val &= ~(0xff << where);
- else
- val &= ~(0xffff << where);
-
- __raw_writel(val | value << where, IOP13XX_ATUX_OCCDR);
- } else {
- __raw_writel(addr, IOP13XX_ATUX_OCCAR);
- __raw_writel(value, IOP13XX_ATUX_OCCDR);
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop13xx_atux_ops = {
- .read = iop13xx_atux_read_config,
- .write = iop13xx_atux_write_config,
-};
-
-/* This routine checks the status of the last configuration cycle. If an error
- * was detected it returns >0, else it returns a 0. The errors being checked
- * are parity, master abort, target abort (master and target). These types of
- * errors occur during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop13xx_atue_pci_status(int clear)
-{
- unsigned int status;
- int err = 0;
-
- /*
- * Check the status registers.
- */
-
- /* standard pci status register */
- status = __raw_readw(IOP13XX_ATUE_ATUSR);
- if (status & IOP_PCI_STATUS_ERROR) {
- PRINTK("\t\t\tPCI error: ATUSR %#08x", status);
- if(clear)
- __raw_writew(status & IOP_PCI_STATUS_ERROR,
- IOP13XX_ATUE_ATUSR);
- err++;
- }
-
- /* check the normal status bits in the ATUISR */
- status = __raw_readl(IOP13XX_ATUE_ATUISR);
- if (status & IOP13XX_ATUE_ATUISR_ERROR) {
- PRINTK("\t\t\tPCI error: ATUISR %#08x", status);
- if (clear)
- __raw_writew(status & IOP13XX_ATUE_ATUISR_ERROR,
- IOP13XX_ATUE_ATUISR);
- err++;
-
- /* check the PCI-E status if the ATUISR reports an interface error */
- if (status & IOP13XX_ATUE_STAT_PCI_IFACE_ERR) {
- /* get the unmasked errors */
- status = __raw_readl(IOP13XX_ATUE_PIE_STS) &
- ~(__raw_readl(IOP13XX_ATUE_PIE_MSK));
-
- if (status) {
- PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x",
- __raw_readl(IOP13XX_ATUE_PIE_STS));
- err++;
- } else {
- PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x",
- __raw_readl(IOP13XX_ATUE_PIE_STS));
- PRINTK("\t\t\tPCI-E error: ATUE_PIE_MSK %#08x",
- __raw_readl(IOP13XX_ATUE_PIE_MSK));
- BUG();
- }
-
- if(clear)
- __raw_writel(status, IOP13XX_ATUE_PIE_STS);
- }
- }
-
- return err;
-}
-
-static int
-iop13xx_pcie_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
-{
- WARN_ON(idsel != 0);
-
- switch (pin) {
- case 1: return ATUE_INTA;
- case 2: return ATUE_INTB;
- case 3: return ATUE_INTC;
- case 4: return ATUE_INTD;
- default: return -1;
- }
-}
-
-static u32 iop13xx_atue_read(unsigned long addr)
-{
- u32 val;
-
- __raw_writel(addr, IOP13XX_ATUE_OCCAR);
- val = __raw_readl(IOP13XX_ATUE_OCCDR);
-
- rmb();
-
- return val;
-}
-
-/* The read routines must check the error status of the last configuration
- * cycle. If there was an error, the routine returns all hex f's.
- */
-static int
-iop13xx_atue_read_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 *value)
-{
- u32 val;
- unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where);
-
- /* Hide device numbers > 0 on the local PCI-E bus (Type 0 access) */
- if (!PCI_SLOT(devfn) || (addr & 1)) {
- val = iop13xx_atue_read(addr) >> ((where & 3) * 8);
- if( iop13xx_atue_pci_status(1) || is_atue_occdr_error() ) {
- __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3,
- IOP13XX_XBG_BECSR);
- val = 0xffffffff;
- }
-
- PRINTK("addr=%#0lx, val=%#010x", addr, val);
- } else
- val = 0xffffffff;
-
- *value = val;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop13xx_atue_write_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 value)
-{
- unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where);
- u32 val;
-
- if (size != 4) {
- val = iop13xx_atue_read(addr);
- if (!iop13xx_atue_pci_status(1) == 0)
- return PCIBIOS_SUCCESSFUL;
-
- where = (where & 3) * 8;
-
- if (size == 1)
- val &= ~(0xff << where);
- else
- val &= ~(0xffff << where);
-
- __raw_writel(val | value << where, IOP13XX_ATUE_OCCDR);
- } else {
- __raw_writel(addr, IOP13XX_ATUE_OCCAR);
- __raw_writel(value, IOP13XX_ATUE_OCCDR);
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop13xx_atue_ops = {
- .read = iop13xx_atue_read_config,
- .write = iop13xx_atue_write_config,
-};
-
-/* When a PCI device does not exist during config cycles, the XScale gets a
- * bus error instead of returning 0xffffffff. We can't rely on the ATU status
- * bits to tell us that it was indeed a configuration cycle that caused this
- * error especially in the case when the ATUE link is down. Instead we rely
- * on data from the south XSI bridge to validate the abort
- */
-int
-iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- PRINTK("Data abort: address = 0x%08lx "
- "fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx",
- addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
- PRINTK("IOP13XX_XBG_BECSR: %#10x", __raw_readl(IOP13XX_XBG_BECSR));
- PRINTK("IOP13XX_XBG_BERAR: %#10x", __raw_readl(IOP13XX_XBG_BERAR));
- PRINTK("IOP13XX_XBG_BERUAR: %#10x", __raw_readl(IOP13XX_XBG_BERUAR));
-
- /* If it was an imprecise abort, then we need to correct the
- * return address to be _after_ the instruction.
- */
- if (fsr & (1 << 10))
- regs->ARM_pc += 4;
-
- if (is_atue_occdr_error() || is_atux_occdr_error())
- return 0;
- else
- return 1;
-}
-
-/* Scan an IOP13XX PCI bus. nr selects which ATU we use.
- */
-int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge)
-{
- int which_atu, ret;
- struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
-
- switch (init_atu) {
- case IOP13XX_INIT_ATU_ATUX:
- which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX;
- break;
- case IOP13XX_INIT_ATU_ATUE:
- which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE;
- break;
- case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE):
- which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX;
- break;
- default:
- which_atu = 0;
- }
-
- if (!which_atu) {
- BUG();
- return -ENODEV;
- }
-
- list_splice_init(&sys->resources, &bridge->windows);
- bridge->dev.parent = NULL;
- bridge->sysdata = sys;
- bridge->busnr = sys->busnr;
-
- switch (which_atu) {
- case IOP13XX_INIT_ATU_ATUX:
- if (time_after_eq(jiffies + msecs_to_jiffies(1000),
- atux_trhfa_timeout)) /* ensure not wrap */
- while(time_before(jiffies, atux_trhfa_timeout))
- udelay(100);
-
- bridge->ops = &iop13xx_atux_ops;
- ret = pci_scan_root_bus_bridge(bridge);
- if (!ret)
- pci_bus_atux = bridge->bus;
- break;
- case IOP13XX_INIT_ATU_ATUE:
- bridge->ops = &iop13xx_atue_ops;
- ret = pci_scan_root_bus_bridge(bridge);
- if (!ret)
- pci_bus_atue = bridge->bus;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/* This function is called from iop13xx_pci_init() after assigning valid
- * values to iop13xx_atue_pmmr_offset. This is the location for common
- * setup of ATUE for all IOP13XX implementations.
- */
-void __init iop13xx_atue_setup(void)
-{
- int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUE);
- u32 reg_val;
-
-#ifdef CONFIG_PCI_MSI
- /* BAR 0 (inbound msi window) */
- __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_MU_MUBAR);
- __raw_writel(~(IOP13XX_MU_WINDOW_SIZE - 1), IOP13XX_ATUE_IALR0);
- __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_ATUE_IATVR0);
- __raw_writel(IOP13XX_MU_BASE_PCI, IOP13XX_ATUE_IABAR0);
-#endif
-
- /* BAR 1 (1:1 mapping with Physical RAM) */
- /* Set limit and enable */
- __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1,
- IOP13XX_ATUE_IALR1);
- __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1);
-
- /* Set base at the top of the reserved address space */
- __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 |
- PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUE_IABAR1);
-
- /* 1:1 mapping with physical ram
- * (leave big endian byte swap disabled)
- */
- __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1);
- __raw_writel(PHYS_OFFSET, IOP13XX_ATUE_IATVR1);
-
- /* Outbound window 1 (PCIX/PCIE memory window) */
- /* 32 bit Address Space */
- __raw_writel(0x0, IOP13XX_ATUE_OUMWTVR1);
- /* PA[35:32] */
- __raw_writel(IOP13XX_ATUE_OUMBAR_ENABLE |
- (IOP13XX_PCIE_MEM_PHYS_OFFSET >> 32),
- IOP13XX_ATUE_OUMBAR1);
-
- /* Setup the I/O Bar
- * A[35-16] in 31-12
- */
- __raw_writel(((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000),
- IOP13XX_ATUE_OIOBAR);
- __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR);
-
- /* clear startup errors */
- iop13xx_atue_pci_status(1);
-
- /* OIOBAR function number
- */
- reg_val = __raw_readl(IOP13XX_ATUE_OIOBAR);
- reg_val &= ~0x7;
- reg_val |= func;
- __raw_writel(reg_val, IOP13XX_ATUE_OIOBAR);
-
- /* OUMBAR function numbers
- */
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0);
-
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1);
-
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2);
-
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3);
-
- /* Enable inbound and outbound cycles
- */
- reg_val = __raw_readw(IOP13XX_ATUE_ATUCMD);
- reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
- __raw_writew(reg_val, IOP13XX_ATUE_ATUCMD);
-
- reg_val = __raw_readl(IOP13XX_ATUE_ATUCR);
- reg_val |= IOP13XX_ATUE_ATUCR_OUT_EN |
- IOP13XX_ATUE_ATUCR_IVM;
- __raw_writel(reg_val, IOP13XX_ATUE_ATUCR);
-}
-
-void __init iop13xx_atue_disable(void)
-{
- u32 reg_val;
-
- __raw_writew(0x0, IOP13XX_ATUE_ATUCMD);
- __raw_writel(IOP13XX_ATUE_ATUCR_IVM, IOP13XX_ATUE_ATUCR);
-
- /* wait for cycles to quiesce */
- while (__raw_readl(IOP13XX_ATUE_PCSR) & (IOP13XX_ATUE_PCSR_OUT_Q_BUSY |
- IOP13XX_ATUE_PCSR_IN_Q_BUSY |
- IOP13XX_ATUE_PCSR_LLRB_BUSY))
- cpu_relax();
-
- /* BAR 0 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUE_IAUBAR0);
- __raw_writel(0x0, IOP13XX_ATUE_IABAR0);
- __raw_writel(0x0, IOP13XX_ATUE_IAUTVR0);
- __raw_writel(0x0, IOP13XX_ATUE_IATVR0);
- __raw_writel(0x0, IOP13XX_ATUE_IALR0);
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0);
- reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0);
-
- /* BAR 1 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1);
- __raw_writel(0x0, IOP13XX_ATUE_IABAR1);
- __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1);
- __raw_writel(0x0, IOP13XX_ATUE_IATVR1);
- __raw_writel(0x0, IOP13XX_ATUE_IALR1);
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1);
- reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1);
-
- /* BAR 2 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUE_IAUBAR2);
- __raw_writel(0x0, IOP13XX_ATUE_IABAR2);
- __raw_writel(0x0, IOP13XX_ATUE_IAUTVR2);
- __raw_writel(0x0, IOP13XX_ATUE_IATVR2);
- __raw_writel(0x0, IOP13XX_ATUE_IALR2);
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2);
- reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2);
-
- /* BAR 3 ( Disabled ) */
- reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3);
- reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3);
-
- /* Setup the I/O Bar
- * A[35-16] in 31-12
- */
- __raw_writel((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000,
- IOP13XX_ATUE_OIOBAR);
- __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR);
-}
-
-/* This function is called from iop13xx_pci_init() after assigning valid
- * values to iop13xx_atux_pmmr_offset. This is the location for common
- * setup of ATUX for all IOP13XX implementations.
- */
-void __init iop13xx_atux_setup(void)
-{
- u32 reg_val;
- int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX);
-
- /* Take PCI-X bus out of reset if bootloader hasn't already.
- * According to spec, we should wait for 2^25 PCI clocks to meet
- * the PCI timing parameter Trhfa (RST# high to first access).
- * This is rarely necessary and often ignored.
- */
- reg_val = __raw_readl(IOP13XX_ATUX_PCSR);
- if (reg_val & IOP13XX_ATUX_PCSR_P_RSTOUT) {
- int msec = (reg_val >> IOP13XX_ATUX_PCSR_FREQ_OFFSET) & 0x7;
- msec = 1000 / (8-msec); /* bits 100=133MHz, 111=>33MHz */
- __raw_writel(reg_val & ~IOP13XX_ATUX_PCSR_P_RSTOUT,
- IOP13XX_ATUX_PCSR);
- atux_trhfa_timeout = jiffies + msecs_to_jiffies(msec);
- }
- else
- atux_trhfa_timeout = jiffies;
-
-#ifdef CONFIG_PCI_MSI
- /* BAR 0 (inbound msi window) */
- __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_MU_MUBAR);
- __raw_writel(~(IOP13XX_MU_WINDOW_SIZE - 1), IOP13XX_ATUX_IALR0);
- __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_ATUX_IATVR0);
- __raw_writel(IOP13XX_MU_BASE_PCI, IOP13XX_ATUX_IABAR0);
-#endif
-
- /* BAR 1 (1:1 mapping with Physical RAM) */
- /* Set limit and enable */
- __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1,
- IOP13XX_ATUX_IALR1);
- __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1);
-
- /* Set base at the top of the reserved address space */
- __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 |
- PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUX_IABAR1);
-
- /* 1:1 mapping with physical ram
- * (leave big endian byte swap disabled)
- */
- __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1);
- __raw_writel(PHYS_OFFSET, IOP13XX_ATUX_IATVR1);
-
- /* Outbound window 1 (PCIX/PCIE memory window) */
- /* 32 bit Address Space */
- __raw_writel(0x0, IOP13XX_ATUX_OUMWTVR1);
- /* PA[35:32] */
- __raw_writel(IOP13XX_ATUX_OUMBAR_ENABLE |
- IOP13XX_PCIX_MEM_PHYS_OFFSET >> 32,
- IOP13XX_ATUX_OUMBAR1);
-
- /* Setup the I/O Bar
- * A[35-16] in 31-12
- */
- __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000,
- IOP13XX_ATUX_OIOBAR);
- __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR);
-
- /* clear startup errors */
- iop13xx_atux_pci_status(1);
-
- /* OIOBAR function number
- */
- reg_val = __raw_readl(IOP13XX_ATUX_OIOBAR);
- reg_val &= ~0x7;
- reg_val |= func;
- __raw_writel(reg_val, IOP13XX_ATUX_OIOBAR);
-
- /* OUMBAR function numbers
- */
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0);
-
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1);
-
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2);
-
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3);
- reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
- IOP13XX_ATU_OUMBAR_FUNC_NUM);
- reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3);
-
- /* Enable inbound and outbound cycles
- */
- reg_val = __raw_readw(IOP13XX_ATUX_ATUCMD);
- reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
- __raw_writew(reg_val, IOP13XX_ATUX_ATUCMD);
-
- reg_val = __raw_readl(IOP13XX_ATUX_ATUCR);
- reg_val |= IOP13XX_ATUX_ATUCR_OUT_EN;
- __raw_writel(reg_val, IOP13XX_ATUX_ATUCR);
-}
-
-void __init iop13xx_atux_disable(void)
-{
- u32 reg_val;
-
- __raw_writew(0x0, IOP13XX_ATUX_ATUCMD);
- __raw_writel(0x0, IOP13XX_ATUX_ATUCR);
-
- /* wait for cycles to quiesce */
- while (__raw_readl(IOP13XX_ATUX_PCSR) & (IOP13XX_ATUX_PCSR_OUT_Q_BUSY |
- IOP13XX_ATUX_PCSR_IN_Q_BUSY))
- cpu_relax();
-
- /* BAR 0 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUX_IAUBAR0);
- __raw_writel(0x0, IOP13XX_ATUX_IABAR0);
- __raw_writel(0x0, IOP13XX_ATUX_IAUTVR0);
- __raw_writel(0x0, IOP13XX_ATUX_IATVR0);
- __raw_writel(0x0, IOP13XX_ATUX_IALR0);
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0);
- reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0);
-
- /* BAR 1 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1);
- __raw_writel(0x0, IOP13XX_ATUX_IABAR1);
- __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1);
- __raw_writel(0x0, IOP13XX_ATUX_IATVR1);
- __raw_writel(0x0, IOP13XX_ATUX_IALR1);
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1);
- reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1);
-
- /* BAR 2 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUX_IAUBAR2);
- __raw_writel(0x0, IOP13XX_ATUX_IABAR2);
- __raw_writel(0x0, IOP13XX_ATUX_IAUTVR2);
- __raw_writel(0x0, IOP13XX_ATUX_IATVR2);
- __raw_writel(0x0, IOP13XX_ATUX_IALR2);
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2);
- reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2);
-
- /* BAR 3 ( Disabled ) */
- __raw_writel(0x0, IOP13XX_ATUX_IAUBAR3);
- __raw_writel(0x0, IOP13XX_ATUX_IABAR3);
- __raw_writel(0x0, IOP13XX_ATUX_IAUTVR3);
- __raw_writel(0x0, IOP13XX_ATUX_IATVR3);
- __raw_writel(0x0, IOP13XX_ATUX_IALR3);
- reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3);
- reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
- __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3);
-
- /* Setup the I/O Bar
- * A[35-16] in 31-12
- */
- __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000,
- IOP13XX_ATUX_OIOBAR);
- __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR);
-}
-
-void __init iop13xx_set_atu_mmr_bases(void)
-{
- /* Based on ESSR0, determine the ATU X/E offsets */
- switch(__raw_readl(IOP13XX_ESSR0) &
- (IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX)) {
- /* both asserted */
- case 0:
- iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET;
- iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
- break;
- /* IOP13XX_CONTROLLER_ONLY = deasserted
- * IOP13XX_INTERFACE_SEL_PCIX = asserted
- */
- case IOP13XX_CONTROLLER_ONLY:
- iop13xx_atux_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET;
- iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
- break;
- /* IOP13XX_CONTROLLER_ONLY = asserted
- * IOP13XX_INTERFACE_SEL_PCIX = deasserted
- */
- case IOP13XX_INTERFACE_SEL_PCIX:
- iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET;
- iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
- break;
- /* both deasserted */
- case IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX:
- iop13xx_atux_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
- iop13xx_atue_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET;
- break;
- default:
- BUG();
- }
-}
-
-void __init iop13xx_atu_select(struct hw_pci *plat_pci)
-{
- int i;
-
- /* set system defaults
- * note: if "iop13xx_init_atu=" is specified this autodetect
- * sequence will be bypassed
- */
- if (init_atu == IOP13XX_INIT_ATU_DEFAULT) {
- /* check for single/dual interface */
- if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) {
- /* ATUE must be present check the device id
- * to see if ATUX is present.
- */
- init_atu |= IOP13XX_INIT_ATU_ATUE;
- switch (__raw_readw(IOP13XX_ATUE_DID) & 0xf0) {
- case 0x70:
- case 0x80:
- case 0xc0:
- init_atu |= IOP13XX_INIT_ATU_ATUX;
- break;
- }
- } else {
- /* ATUX must be present check the device id
- * to see if ATUE is present.
- */
- init_atu |= IOP13XX_INIT_ATU_ATUX;
- switch (__raw_readw(IOP13XX_ATUX_DID) & 0xf0) {
- case 0x70:
- case 0x80:
- case 0xc0:
- init_atu |= IOP13XX_INIT_ATU_ATUE;
- break;
- }
- }
-
- /* check central resource and root complex capability */
- if (init_atu & IOP13XX_INIT_ATU_ATUX)
- if (!(__raw_readl(IOP13XX_ATUX_PCSR) &
- IOP13XX_ATUX_PCSR_CENTRAL_RES))
- init_atu &= ~IOP13XX_INIT_ATU_ATUX;
-
- if (init_atu & IOP13XX_INIT_ATU_ATUE)
- if (__raw_readl(IOP13XX_ATUE_PCSR) &
- IOP13XX_ATUE_PCSR_END_POINT)
- init_atu &= ~IOP13XX_INIT_ATU_ATUE;
- }
-
- for (i = 0; i < 2; i++) {
- if((init_atu & (1 << i)) == (1 << i))
- plat_pci->nr_controllers++;
- }
-}
-
-void __init iop13xx_pci_init(void)
-{
- /* clear pre-existing south bridge errors */
- __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
-
- /* Setup the Min Address for PCI memory... */
- pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
-
- /* if Linux is given control of an ATU
- * clear out its prior configuration,
- * otherwise do not touch the registers
- */
- if (init_atu & IOP13XX_INIT_ATU_ATUE) {
- iop13xx_atue_disable();
- iop13xx_atue_setup();
- }
-
- if (init_atu & IOP13XX_INIT_ATU_ATUX) {
- iop13xx_atux_disable();
- iop13xx_atux_setup();
- }
-
- hook_fault_code(16+6, iop13xx_pci_abort, SIGBUS, 0,
- "imprecise external abort");
-}
-
-/* initialize the pci memory space. handle any combination of
- * atue and atux enabled/disabled
- */
-int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
-{
- struct resource *res;
- int which_atu;
- u32 pcixsr, pcsr;
-
- if (nr > 1)
- return 0;
-
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
- if (!res)
- panic("PCI: unable to alloc resources");
-
-
- /* 'nr' assumptions:
- * ATUX is always 0
- * ATUE is 1 when ATUX is also enabled
- * ATUE is 0 when ATUX is disabled
- */
- switch(init_atu) {
- case IOP13XX_INIT_ATU_ATUX:
- which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX;
- break;
- case IOP13XX_INIT_ATU_ATUE:
- which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE;
- break;
- case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE):
- which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX;
- break;
- default:
- which_atu = 0;
- }
-
- if (!which_atu) {
- kfree(res);
- return 0;
- }
-
- switch(which_atu) {
- case IOP13XX_INIT_ATU_ATUX:
- pcixsr = __raw_readl(IOP13XX_ATUX_PCIXSR);
- pcixsr &= ~0xffff;
- pcixsr |= sys->busnr << IOP13XX_ATUX_PCIXSR_BUS_NUM |
- 0 << IOP13XX_ATUX_PCIXSR_DEV_NUM |
- iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX)
- << IOP13XX_ATUX_PCIXSR_FUNC_NUM;
- __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
-
- pci_ioremap_io(0, IOP13XX_PCIX_LOWER_IO_PA);
-
- res->start = IOP13XX_PCIX_LOWER_MEM_RA;
- res->end = IOP13XX_PCIX_UPPER_MEM_RA;
- res->name = "IQ81340 ATUX PCI Memory Space";
- res->flags = IORESOURCE_MEM;
- sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
- break;
- case IOP13XX_INIT_ATU_ATUE:
- /* Note: the function number field in the PCSR is ro */
- pcsr = __raw_readl(IOP13XX_ATUE_PCSR);
- pcsr &= ~(0xfff8 << 16);
- pcsr |= sys->busnr << IOP13XX_ATUE_PCSR_BUS_NUM |
- 0 << IOP13XX_ATUE_PCSR_DEV_NUM;
-
- __raw_writel(pcsr, IOP13XX_ATUE_PCSR);
-
- pci_ioremap_io(SZ_64K, IOP13XX_PCIE_LOWER_IO_PA);
-
- res->start = IOP13XX_PCIE_LOWER_MEM_RA;
- res->end = IOP13XX_PCIE_UPPER_MEM_RA;
- res->name = "IQ81340 ATUE PCI Memory Space";
- res->flags = IORESOURCE_MEM;
- sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
- sys->map_irq = iop13xx_pcie_map_irq;
- break;
- default:
- kfree(res);
- return 0;
- }
-
- request_resource(&iomem_resource, res);
-
- pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
-
- return 1;
-}
-
-u16 iop13xx_dev_id(void)
-{
- if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
- return __raw_readw(IOP13XX_ATUE_DID);
- else
- return __raw_readw(IOP13XX_ATUX_DID);
-}
-
-static int __init iop13xx_init_atu_setup(char *str)
-{
- init_atu = IOP13XX_INIT_ATU_NONE;
- if (str) {
- while (*str != '\0') {
- switch (*str) {
- case 'x':
- case 'X':
- init_atu |= IOP13XX_INIT_ATU_ATUX;
- init_atu &= ~IOP13XX_INIT_ATU_NONE;
- break;
- case 'e':
- case 'E':
- init_atu |= IOP13XX_INIT_ATU_ATUE;
- init_atu &= ~IOP13XX_INIT_ATU_NONE;
- break;
- case ',':
- case '=':
- break;
- default:
- PRINTK("\"iop13xx_init_atu\" malformed at "
- "character: \'%c\'", *str);
- *(str + 1) = '\0';
- init_atu = IOP13XX_INIT_ATU_DEFAULT;
- }
- str++;
- }
- }
- return 1;
-}
-
-__setup("iop13xx_init_atu", iop13xx_init_atu_setup);
diff --git a/arch/arm/mach-iop13xx/pci.h b/arch/arm/mach-iop13xx/pci.h
deleted file mode 100644
index 736168d8c7ac..000000000000
--- a/arch/arm/mach-iop13xx/pci.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP13XX_PCI_H_
-#define _IOP13XX_PCI_H_
-#include <linux/io.h>
-#include <mach/irqs.h>
-
-#include <linux/types.h>
-
-extern void __iomem *iop13xx_atue_mem_base;
-extern void __iomem *iop13xx_atux_mem_base;
-extern size_t iop13xx_atue_mem_size;
-extern size_t iop13xx_atux_mem_size;
-
-struct pci_sys_data;
-struct pci_host_bridge;
-struct hw_pci;
-int iop13xx_pci_setup(int nr, struct pci_sys_data *sys);
-int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge);
-void iop13xx_atu_select(struct hw_pci *plat_pci);
-void iop13xx_pci_init(void);
-void iop13xx_map_pci_memory(void);
-
-#define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY | \
- PCI_STATUS_SIG_TARGET_ABORT | \
- PCI_STATUS_REC_TARGET_ABORT | \
- PCI_STATUS_REC_TARGET_ABORT | \
- PCI_STATUS_REC_MASTER_ABORT | \
- PCI_STATUS_SIG_SYSTEM_ERROR | \
- PCI_STATUS_DETECTED_PARITY)
-
-#define IOP13XX_ATUE_ATUISR_ERROR (IOP13XX_ATUE_STAT_HALT_ON_ERROR | \
- IOP13XX_ATUE_STAT_ROOT_SYS_ERR | \
- IOP13XX_ATUE_STAT_PCI_IFACE_ERR | \
- IOP13XX_ATUE_STAT_ERR_COR | \
- IOP13XX_ATUE_STAT_ERR_UNCOR | \
- IOP13XX_ATUE_STAT_CRS | \
- IOP13XX_ATUE_STAT_DET_PAR_ERR | \
- IOP13XX_ATUE_STAT_EXT_REC_MABORT | \
- IOP13XX_ATUE_STAT_SIG_TABORT | \
- IOP13XX_ATUE_STAT_EXT_REC_TABORT | \
- IOP13XX_ATUE_STAT_MASTER_DATA_PAR)
-
-#define IOP13XX_ATUX_ATUISR_ERROR (IOP13XX_ATUX_STAT_TX_SCEM | \
- IOP13XX_ATUX_STAT_REC_SCEM | \
- IOP13XX_ATUX_STAT_TX_SERR | \
- IOP13XX_ATUX_STAT_DET_PAR_ERR | \
- IOP13XX_ATUX_STAT_INT_REC_MABORT | \
- IOP13XX_ATUX_STAT_REC_SERR | \
- IOP13XX_ATUX_STAT_EXT_REC_MABORT | \
- IOP13XX_ATUX_STAT_EXT_REC_TABORT | \
- IOP13XX_ATUX_STAT_EXT_SIG_TABORT | \
- IOP13XX_ATUX_STAT_MASTER_DATA_PAR)
-
-/* PCI interrupts
- */
-#define ATUX_INTA IRQ_IOP13XX_XINT0
-#define ATUX_INTB IRQ_IOP13XX_XINT1
-#define ATUX_INTC IRQ_IOP13XX_XINT2
-#define ATUX_INTD IRQ_IOP13XX_XINT3
-
-#define ATUE_INTA IRQ_IOP13XX_ATUE_IMA
-#define ATUE_INTB IRQ_IOP13XX_ATUE_IMB
-#define ATUE_INTC IRQ_IOP13XX_ATUE_IMC
-#define ATUE_INTD IRQ_IOP13XX_ATUE_IMD
-
-#endif /* _IOP13XX_PCI_H_ */
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
deleted file mode 100644
index c5c84c9ec9ee..000000000000
--- a/arch/arm/mach-iop13xx/setup.c
+++ /dev/null
@@ -1,595 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iop13xx platform Initialization
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-#include <linux/reboot.h>
-#ifdef CONFIG_MTD_PHYSMAP
-#include <linux/mtd/physmap.h>
-#endif
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/hardware/iop_adma.h>
-#include <mach/irqs.h>
-
-#define IOP13XX_UART_XTAL 33334000
-#define IOP13XX_SETUP_DEBUG 0
-#define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x)))
-
-/* Standard IO mapping for all IOP13XX based systems
- */
-static struct map_desc iop13xx_std_desc[] __initdata = {
- { /* mem mapped registers */
- .virtual = (unsigned long)IOP13XX_PMMR_VIRT_MEM_BASE,
- .pfn = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE),
- .length = IOP13XX_PMMR_SIZE,
- .type = MT_DEVICE,
- },
-};
-
-static struct resource iop13xx_uart0_resources[] = {
- [0] = {
- .start = IOP13XX_UART0_PHYS,
- .end = IOP13XX_UART0_PHYS + 0x3f,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_UART0,
- .end = IRQ_IOP13XX_UART0,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_uart1_resources[] = {
- [0] = {
- .start = IOP13XX_UART1_PHYS,
- .end = IOP13XX_UART1_PHYS + 0x3f,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_UART1,
- .end = IRQ_IOP13XX_UART1,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct plat_serial8250_port iop13xx_uart0_data[] = {
- {
- .membase = IOP13XX_UART0_VIRT,
- .mapbase = IOP13XX_UART0_PHYS,
- .irq = IRQ_IOP13XX_UART0,
- .uartclk = IOP13XX_UART_XTAL,
- .regshift = 2,
- .iotype = UPIO_MEM,
- .flags = UPF_SKIP_TEST,
- },
- { },
-};
-
-static struct plat_serial8250_port iop13xx_uart1_data[] = {
- {
- .membase = IOP13XX_UART1_VIRT,
- .mapbase = IOP13XX_UART1_PHYS,
- .irq = IRQ_IOP13XX_UART1,
- .uartclk = IOP13XX_UART_XTAL,
- .regshift = 2,
- .iotype = UPIO_MEM,
- .flags = UPF_SKIP_TEST,
- },
- { },
-};
-
-/* The ids are fixed up later in iop13xx_platform_init */
-static struct platform_device iop13xx_uart0 = {
- .name = "serial8250",
- .id = 0,
- .dev.platform_data = iop13xx_uart0_data,
- .num_resources = 2,
- .resource = iop13xx_uart0_resources,
-};
-
-static struct platform_device iop13xx_uart1 = {
- .name = "serial8250",
- .id = 0,
- .dev.platform_data = iop13xx_uart1_data,
- .num_resources = 2,
- .resource = iop13xx_uart1_resources
-};
-
-static struct resource iop13xx_i2c_0_resources[] = {
- [0] = {
- .start = IOP13XX_I2C0_PHYS,
- .end = IOP13XX_I2C0_PHYS + 0x18,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_I2C_0,
- .end = IRQ_IOP13XX_I2C_0,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_i2c_1_resources[] = {
- [0] = {
- .start = IOP13XX_I2C1_PHYS,
- .end = IOP13XX_I2C1_PHYS + 0x18,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_I2C_1,
- .end = IRQ_IOP13XX_I2C_1,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_i2c_2_resources[] = {
- [0] = {
- .start = IOP13XX_I2C2_PHYS,
- .end = IOP13XX_I2C2_PHYS + 0x18,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_I2C_2,
- .end = IRQ_IOP13XX_I2C_2,
- .flags = IORESOURCE_IRQ
- }
-};
-
-/* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so
- * we just use the same device name.
- */
-
-/* The ids are fixed up later in iop13xx_platform_init */
-static struct platform_device iop13xx_i2c_0_controller = {
- .name = "IOP3xx-I2C",
- .id = 0,
- .num_resources = 2,
- .resource = iop13xx_i2c_0_resources
-};
-
-static struct platform_device iop13xx_i2c_1_controller = {
- .name = "IOP3xx-I2C",
- .id = 0,
- .num_resources = 2,
- .resource = iop13xx_i2c_1_resources
-};
-
-static struct platform_device iop13xx_i2c_2_controller = {
- .name = "IOP3xx-I2C",
- .id = 0,
- .num_resources = 2,
- .resource = iop13xx_i2c_2_resources
-};
-
-#ifdef CONFIG_MTD_PHYSMAP
-/* PBI Flash Device
- */
-static struct physmap_flash_data iq8134x_flash_data = {
- .width = 2,
-};
-
-static struct resource iq8134x_flash_resource = {
- .start = IQ81340_FLASHBASE,
- .end = 0,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device iq8134x_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = { .platform_data = &iq8134x_flash_data, },
- .num_resources = 1,
- .resource = &iq8134x_flash_resource,
-};
-
-static unsigned long iq8134x_probe_flash_size(void)
-{
- uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE);
- int i;
- char query[3];
- unsigned long size = 0;
- int width = iq8134x_flash_data.width;
-
- if (flash_addr) {
- /* send CFI 'query' command */
- writew(0x98, flash_addr);
-
- /* check for CFI compliance */
- for (i = 0; i < 3 * width; i += width)
- query[i / width] = readb(flash_addr + (0x10 * width) + i);
-
- /* read the size */
- if (memcmp(query, "QRY", 3) == 0)
- size = 1 << readb(flash_addr + (0x27 * width));
-
- /* send CFI 'read array' command */
- writew(0xff, flash_addr);
-
- iounmap(flash_addr);
- }
-
- return size;
-}
-#endif
-
-/* ADMA Channels */
-static struct resource iop13xx_adma_0_resources[] = {
- [0] = {
- .start = IOP13XX_ADMA_PHYS_BASE(0),
- .end = IOP13XX_ADMA_UPPER_PA(0),
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_ADMA0_EOT,
- .end = IRQ_IOP13XX_ADMA0_EOT,
- .flags = IORESOURCE_IRQ
- },
- [2] = {
- .start = IRQ_IOP13XX_ADMA0_EOC,
- .end = IRQ_IOP13XX_ADMA0_EOC,
- .flags = IORESOURCE_IRQ
- },
- [3] = {
- .start = IRQ_IOP13XX_ADMA0_ERR,
- .end = IRQ_IOP13XX_ADMA0_ERR,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_adma_1_resources[] = {
- [0] = {
- .start = IOP13XX_ADMA_PHYS_BASE(1),
- .end = IOP13XX_ADMA_UPPER_PA(1),
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_ADMA1_EOT,
- .end = IRQ_IOP13XX_ADMA1_EOT,
- .flags = IORESOURCE_IRQ
- },
- [2] = {
- .start = IRQ_IOP13XX_ADMA1_EOC,
- .end = IRQ_IOP13XX_ADMA1_EOC,
- .flags = IORESOURCE_IRQ
- },
- [3] = {
- .start = IRQ_IOP13XX_ADMA1_ERR,
- .end = IRQ_IOP13XX_ADMA1_ERR,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_adma_2_resources[] = {
- [0] = {
- .start = IOP13XX_ADMA_PHYS_BASE(2),
- .end = IOP13XX_ADMA_UPPER_PA(2),
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP13XX_ADMA2_EOT,
- .end = IRQ_IOP13XX_ADMA2_EOT,
- .flags = IORESOURCE_IRQ
- },
- [2] = {
- .start = IRQ_IOP13XX_ADMA2_EOC,
- .end = IRQ_IOP13XX_ADMA2_EOC,
- .flags = IORESOURCE_IRQ
- },
- [3] = {
- .start = IRQ_IOP13XX_ADMA2_ERR,
- .end = IRQ_IOP13XX_ADMA2_ERR,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static u64 iop13xx_adma_dmamask = DMA_BIT_MASK(32);
-static struct iop_adma_platform_data iop13xx_adma_0_data = {
- .hw_id = 0,
- .pool_size = PAGE_SIZE,
-};
-
-static struct iop_adma_platform_data iop13xx_adma_1_data = {
- .hw_id = 1,
- .pool_size = PAGE_SIZE,
-};
-
-static struct iop_adma_platform_data iop13xx_adma_2_data = {
- .hw_id = 2,
- .pool_size = PAGE_SIZE,
-};
-
-/* The ids are fixed up later in iop13xx_platform_init */
-static struct platform_device iop13xx_adma_0_channel = {
- .name = "iop-adma",
- .id = 0,
- .num_resources = 4,
- .resource = iop13xx_adma_0_resources,
- .dev = {
- .dma_mask = &iop13xx_adma_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = (void *) &iop13xx_adma_0_data,
- },
-};
-
-static struct platform_device iop13xx_adma_1_channel = {
- .name = "iop-adma",
- .id = 0,
- .num_resources = 4,
- .resource = iop13xx_adma_1_resources,
- .dev = {
- .dma_mask = &iop13xx_adma_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = (void *) &iop13xx_adma_1_data,
- },
-};
-
-static struct platform_device iop13xx_adma_2_channel = {
- .name = "iop-adma",
- .id = 0,
- .num_resources = 4,
- .resource = iop13xx_adma_2_resources,
- .dev = {
- .dma_mask = &iop13xx_adma_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = (void *) &iop13xx_adma_2_data,
- },
-};
-
-void __init iop13xx_map_io(void)
-{
- /* Initialize the Static Page Table maps */
- iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
-}
-
-static int init_uart;
-static int init_i2c;
-static int init_adma;
-
-void __init iop13xx_platform_init(void)
-{
- int i;
- u32 uart_idx, i2c_idx, adma_idx, plat_idx;
- struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
-
- /* set the bases so we can read the device id */
- iop13xx_set_atu_mmr_bases();
-
- memset(iop13xx_devices, 0, sizeof(iop13xx_devices));
-
- if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
- switch (iop13xx_dev_id()) {
- /* enable both uarts on iop341 */
- case 0x3380:
- case 0x3384:
- case 0x3388:
- case 0x338c:
- init_uart |= IOP13XX_INIT_UART_0;
- init_uart |= IOP13XX_INIT_UART_1;
- break;
- /* only enable uart 1 */
- default:
- init_uart |= IOP13XX_INIT_UART_1;
- }
- }
-
- if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) {
- switch (iop13xx_dev_id()) {
- /* enable all i2c units on iop341 and iop342 */
- case 0x3380:
- case 0x3384:
- case 0x3388:
- case 0x338c:
- case 0x3382:
- case 0x3386:
- case 0x338a:
- case 0x338e:
- init_i2c |= IOP13XX_INIT_I2C_0;
- init_i2c |= IOP13XX_INIT_I2C_1;
- init_i2c |= IOP13XX_INIT_I2C_2;
- break;
- /* only enable i2c 1 and 2 */
- default:
- init_i2c |= IOP13XX_INIT_I2C_1;
- init_i2c |= IOP13XX_INIT_I2C_2;
- }
- }
-
- if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
- init_adma |= IOP13XX_INIT_ADMA_0;
- init_adma |= IOP13XX_INIT_ADMA_1;
- init_adma |= IOP13XX_INIT_ADMA_2;
- }
-
- plat_idx = 0;
- uart_idx = 0;
- i2c_idx = 0;
-
- /* uart 1 (if enabled) is ttyS0 */
- if (init_uart & IOP13XX_INIT_UART_1) {
- PRINTK("Adding uart1 to platform device list\n");
- iop13xx_uart1.id = uart_idx++;
- iop13xx_devices[plat_idx++] = &iop13xx_uart1;
- }
- if (init_uart & IOP13XX_INIT_UART_0) {
- PRINTK("Adding uart0 to platform device list\n");
- iop13xx_uart0.id = uart_idx++;
- iop13xx_devices[plat_idx++] = &iop13xx_uart0;
- }
-
- for(i = 0; i < IQ81340_NUM_I2C; i++) {
- if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG)
- printk("Adding i2c%d to platform device list\n", i);
- switch(init_i2c & (1 << i)) {
- case IOP13XX_INIT_I2C_0:
- iop13xx_i2c_0_controller.id = i2c_idx++;
- iop13xx_devices[plat_idx++] =
- &iop13xx_i2c_0_controller;
- break;
- case IOP13XX_INIT_I2C_1:
- iop13xx_i2c_1_controller.id = i2c_idx++;
- iop13xx_devices[plat_idx++] =
- &iop13xx_i2c_1_controller;
- break;
- case IOP13XX_INIT_I2C_2:
- iop13xx_i2c_2_controller.id = i2c_idx++;
- iop13xx_devices[plat_idx++] =
- &iop13xx_i2c_2_controller;
- break;
- }
- }
-
- /* initialize adma channel ids and capabilities */
- adma_idx = 0;
- for (i = 0; i < IQ81340_NUM_ADMA; i++) {
- struct iop_adma_platform_data *plat_data;
- if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
- printk(KERN_INFO
- "Adding adma%d to platform device list\n", i);
- switch (init_adma & (1 << i)) {
- case IOP13XX_INIT_ADMA_0:
- iop13xx_adma_0_channel.id = adma_idx++;
- iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
- plat_data = &iop13xx_adma_0_data;
- dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
- dma_cap_set(DMA_XOR, plat_data->cap_mask);
- dma_cap_set(DMA_XOR_VAL, plat_data->cap_mask);
- dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
- break;
- case IOP13XX_INIT_ADMA_1:
- iop13xx_adma_1_channel.id = adma_idx++;
- iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
- plat_data = &iop13xx_adma_1_data;
- dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
- dma_cap_set(DMA_XOR, plat_data->cap_mask);
- dma_cap_set(DMA_XOR_VAL, plat_data->cap_mask);
- dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
- break;
- case IOP13XX_INIT_ADMA_2:
- iop13xx_adma_2_channel.id = adma_idx++;
- iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
- plat_data = &iop13xx_adma_2_data;
- dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
- dma_cap_set(DMA_XOR, plat_data->cap_mask);
- dma_cap_set(DMA_XOR_VAL, plat_data->cap_mask);
- dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
- dma_cap_set(DMA_PQ, plat_data->cap_mask);
- dma_cap_set(DMA_PQ_VAL, plat_data->cap_mask);
- break;
- }
- }
-
-#ifdef CONFIG_MTD_PHYSMAP
- iq8134x_flash_resource.end = iq8134x_flash_resource.start +
- iq8134x_probe_flash_size() - 1;
- if (iq8134x_flash_resource.end > iq8134x_flash_resource.start)
- iop13xx_devices[plat_idx++] = &iq8134x_flash;
- else
- printk(KERN_ERR "%s: Failed to probe flash size\n", __func__);
-#endif
-
- platform_add_devices(iop13xx_devices, plat_idx);
-}
-
-static int __init iop13xx_init_uart_setup(char *str)
-{
- if (str) {
- while (*str != '\0') {
- switch(*str) {
- case '0':
- init_uart |= IOP13XX_INIT_UART_0;
- break;
- case '1':
- init_uart |= IOP13XX_INIT_UART_1;
- break;
- case ',':
- case '=':
- break;
- default:
- PRINTK("\"iop13xx_init_uart\" malformed"
- " at character: \'%c\'", *str);
- *(str + 1) = '\0';
- init_uart = IOP13XX_INIT_UART_DEFAULT;
- }
- str++;
- }
- }
- return 1;
-}
-
-static int __init iop13xx_init_i2c_setup(char *str)
-{
- if (str) {
- while (*str != '\0') {
- switch(*str) {
- case '0':
- init_i2c |= IOP13XX_INIT_I2C_0;
- break;
- case '1':
- init_i2c |= IOP13XX_INIT_I2C_1;
- break;
- case '2':
- init_i2c |= IOP13XX_INIT_I2C_2;
- break;
- case ',':
- case '=':
- break;
- default:
- PRINTK("\"iop13xx_init_i2c\" malformed"
- " at character: \'%c\'", *str);
- *(str + 1) = '\0';
- init_i2c = IOP13XX_INIT_I2C_DEFAULT;
- }
- str++;
- }
- }
- return 1;
-}
-
-static int __init iop13xx_init_adma_setup(char *str)
-{
- if (str) {
- while (*str != '\0') {
- switch (*str) {
- case '0':
- init_adma |= IOP13XX_INIT_ADMA_0;
- break;
- case '1':
- init_adma |= IOP13XX_INIT_ADMA_1;
- break;
- case '2':
- init_adma |= IOP13XX_INIT_ADMA_2;
- break;
- case ',':
- case '=':
- break;
- default:
- PRINTK("\"iop13xx_init_adma\" malformed"
- " at character: \'%c\'", *str);
- *(str + 1) = '\0';
- init_adma = IOP13XX_INIT_ADMA_DEFAULT;
- }
- str++;
- }
- }
- return 1;
-}
-
-__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
-__setup("iop13xx_init_uart", iop13xx_init_uart_setup);
-__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
-
-void iop13xx_restart(enum reboot_mode mode, const char *cmd)
-{
- /*
- * Reset the internal bus (warning both cores are reset)
- */
- write_wdtcr(IOP_WDTCR_EN_ARM);
- write_wdtcr(IOP_WDTCR_EN);
- write_wdtsr(IOP13XX_WDTSR_WRITE_EN | IOP13XX_WDTCR_IB_RESET);
- write_wdtcr(0x1000);
-}
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
deleted file mode 100644
index 4f916549e381..000000000000
--- a/arch/arm/mach-iop13xx/tpmi.c
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * iop13xx tpmi device resources
- * Copyright (c) 2005-2006, Intel Corporation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <asm/irq.h>
-#include <linux/sizes.h>
-#include <mach/irqs.h>
-
-/* assumes CONTROLLER_ONLY# is never asserted in the ESSR register */
-#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
-#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
-#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
-#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
-#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1)
-#define IOP13XX_TPMI_MEM_SIZE (255)
-#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1)
-#define IOP13XX_TPMI_RESOURCE_MMR 0
-#define IOP13XX_TPMI_RESOURCE_MEM 1
-#define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
-#define IOP13XX_TPMI_RESOURCE_IRQ 4
-
-static struct resource iop13xx_tpmi_0_resources[] = {
- [IOP13XX_TPMI_RESOURCE_MMR] = {
- .start = IOP13XX_TPMI_MMR(4), /* tpmi0 starts at dev == 4 */
- .end = IOP13XX_TPMI_MMR(4) + IOP13XX_TPMI_MMR_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_MEM] = {
- .start = IOP13XX_TPMI_MEM(0),
- .end = IOP13XX_TPMI_MEM(0) + IOP13XX_TPMI_MEM_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_CTRL] = {
- .start = IOP13XX_TPMI_CTRL(0),
- .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
- .start = IOP13XX_TPMI_IOP_CTRL(0),
- .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IRQ] = {
- .start = IRQ_IOP13XX_TPMI0_OUT,
- .end = IRQ_IOP13XX_TPMI0_OUT,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_tpmi_1_resources[] = {
- [IOP13XX_TPMI_RESOURCE_MMR] = {
- .start = IOP13XX_TPMI_MMR(1),
- .end = IOP13XX_TPMI_MMR(1) + IOP13XX_TPMI_MMR_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_MEM] = {
- .start = IOP13XX_TPMI_MEM(1),
- .end = IOP13XX_TPMI_MEM(1) + IOP13XX_TPMI_MEM_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_CTRL] = {
- .start = IOP13XX_TPMI_CTRL(1),
- .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
- .start = IOP13XX_TPMI_IOP_CTRL(1),
- .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IRQ] = {
- .start = IRQ_IOP13XX_TPMI1_OUT,
- .end = IRQ_IOP13XX_TPMI1_OUT,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_tpmi_2_resources[] = {
- [IOP13XX_TPMI_RESOURCE_MMR] = {
- .start = IOP13XX_TPMI_MMR(2),
- .end = IOP13XX_TPMI_MMR(2) + IOP13XX_TPMI_MMR_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_MEM] = {
- .start = IOP13XX_TPMI_MEM(2),
- .end = IOP13XX_TPMI_MEM(2) + IOP13XX_TPMI_MEM_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_CTRL] = {
- .start = IOP13XX_TPMI_CTRL(2),
- .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
- .start = IOP13XX_TPMI_IOP_CTRL(2),
- .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IRQ] = {
- .start = IRQ_IOP13XX_TPMI2_OUT,
- .end = IRQ_IOP13XX_TPMI2_OUT,
- .flags = IORESOURCE_IRQ
- }
-};
-
-static struct resource iop13xx_tpmi_3_resources[] = {
- [IOP13XX_TPMI_RESOURCE_MMR] = {
- .start = IOP13XX_TPMI_MMR(3),
- .end = IOP13XX_TPMI_MMR(3) + IOP13XX_TPMI_MMR_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_MEM] = {
- .start = IOP13XX_TPMI_MEM(3),
- .end = IOP13XX_TPMI_MEM(3) + IOP13XX_TPMI_MEM_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_CTRL] = {
- .start = IOP13XX_TPMI_CTRL(3),
- .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
- .start = IOP13XX_TPMI_IOP_CTRL(3),
- .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
- .flags = IORESOURCE_MEM,
- },
- [IOP13XX_TPMI_RESOURCE_IRQ] = {
- .start = IRQ_IOP13XX_TPMI3_OUT,
- .end = IRQ_IOP13XX_TPMI3_OUT,
- .flags = IORESOURCE_IRQ
- }
-};
-
-u64 iop13xx_tpmi_mask = DMA_BIT_MASK(32);
-static struct platform_device iop13xx_tpmi_0_device = {
- .name = "iop-tpmi",
- .id = 0,
- .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
- .resource = iop13xx_tpmi_0_resources,
- .dev = {
- .dma_mask = &iop13xx_tpmi_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-static struct platform_device iop13xx_tpmi_1_device = {
- .name = "iop-tpmi",
- .id = 1,
- .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
- .resource = iop13xx_tpmi_1_resources,
- .dev = {
- .dma_mask = &iop13xx_tpmi_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-static struct platform_device iop13xx_tpmi_2_device = {
- .name = "iop-tpmi",
- .id = 2,
- .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
- .resource = iop13xx_tpmi_2_resources,
- .dev = {
- .dma_mask = &iop13xx_tpmi_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-static struct platform_device iop13xx_tpmi_3_device = {
- .name = "iop-tpmi",
- .id = 3,
- .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
- .resource = iop13xx_tpmi_3_resources,
- .dev = {
- .dma_mask = &iop13xx_tpmi_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-__init void iop13xx_add_tpmi_devices(void)
-{
- unsigned short device_id;
-
- /* tpmi's not present on iop341 or iop342 */
- if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
- /* ATUE must be present */
- device_id = __raw_readw(IOP13XX_ATUE_DID);
- else
- /* ATUX must be present */
- device_id = __raw_readw(IOP13XX_ATUX_DID);
-
- switch (device_id) {
- /* iop34[1|2] 0-tpmi */
- case 0x3380:
- case 0x3384:
- case 0x3388:
- case 0x338c:
- case 0x3382:
- case 0x3386:
- case 0x338a:
- case 0x338e:
- return;
- /* iop348 1-tpmi */
- case 0x3310:
- case 0x3312:
- case 0x3314:
- case 0x3318:
- case 0x331a:
- case 0x331c:
- case 0x33c0:
- case 0x33c2:
- case 0x33c4:
- case 0x33c8:
- case 0x33ca:
- case 0x33cc:
- case 0x33b0:
- case 0x33b2:
- case 0x33b4:
- case 0x33b8:
- case 0x33ba:
- case 0x33bc:
- case 0x3320:
- case 0x3322:
- case 0x3324:
- case 0x3328:
- case 0x332a:
- case 0x332c:
- platform_device_register(&iop13xx_tpmi_0_device);
- return;
- default:
- platform_device_register(&iop13xx_tpmi_0_device);
- platform_device_register(&iop13xx_tpmi_1_device);
- platform_device_register(&iop13xx_tpmi_2_device);
- platform_device_register(&iop13xx_tpmi_3_device);
- return;
- }
-}
diff --git a/arch/arm/mach-iop32x/Makefile b/arch/arm/mach-iop32x/Makefile
index 71d62447d4d5..c8018ef5c6a9 100644
--- a/arch/arm/mach-iop32x/Makefile
+++ b/arch/arm/mach-iop32x/Makefile
@@ -3,7 +3,15 @@
# Makefile for the linux kernel.
#
-obj-y := irq.o
+obj-$(CONFIG_ARCH_IOP32X) += irq.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+obj-$(CONFIG_ARCH_IOP32X) += adma.o
+obj-$(CONFIG_ARCH_IOP32X) += pmu.o
+obj-$(CONFIG_ARCH_IOP32X) += restart.o
obj-$(CONFIG_MACH_GLANTANK) += glantank.o
obj-$(CONFIG_ARCH_IQ80321) += iq80321.o
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/mach-iop32x/adma.c
index b8e360299293..764bcbff98df 100644
--- a/arch/arm/plat-iop/adma.c
+++ b/arch/arm/mach-iop32x/adma.c
@@ -4,12 +4,12 @@
* Copyright © 2006, Intel Corporation.
*/
#include <linux/platform_device.h>
-#include <asm/hardware/iop3xx.h>
#include <linux/dma-mapping.h>
-#include <mach/adma.h>
-#include <asm/hardware/iop_adma.h>
+#include <linux/platform_data/dma-iop32x.h>
+
+#include "iop3xx.h"
+#include "irqs.h"
-#ifdef CONFIG_ARCH_IOP32X
#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
@@ -21,20 +21,7 @@
#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
-#endif
-#ifdef CONFIG_ARCH_IOP33X
-#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
-#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
-#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
-
-#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
-#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
-#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
-
-#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
-#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
-#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
-#endif
+
/* AAU and DMA Channels */
static struct resource iop3xx_dma_0_resources[] = {
[0] = {
@@ -161,30 +148,14 @@ struct platform_device iop3xx_aau_channel = {
static int __init iop3xx_adma_cap_init(void)
{
- #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
- dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
- dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
- #else
dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
- #endif
- #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
- #else
- dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
- dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
- #endif
- #ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
- dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
- dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
- #else
dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
- dma_cap_set(DMA_XOR_VAL, iop3xx_aau_data.cap_mask);
dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
- #endif
return 0;
}
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/mach-iop32x/cp6.c
index ec74b07fb7e3..ec74b07fb7e3 100644
--- a/arch/arm/plat-iop/cp6.c
+++ b/arch/arm/mach-iop32x/cp6.c
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 61a1e593f9ec..d43ced3cd4e7 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -21,7 +21,6 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <asm/mach/arch.h>
@@ -29,8 +28,10 @@
#include <asm/mach/pci.h>
#include <asm/mach/time.h>
#include <asm/mach-types.h>
-#include <mach/time.h>
+
+#include "hardware.h"
#include "gpio-iop32x.h"
+#include "irqs.h"
static void __init em7210_timer_init(void)
{
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 5a45d616d9ac..2fe0f77d1f1d 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -30,8 +29,10 @@
#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/page.h>
-#include <mach/time.h>
+
+#include "hardware.h"
#include "gpio-iop32x.h"
+#include "irqs.h"
/*
* GLAN Tank timer tick configuration.
diff --git a/arch/arm/mach-iop32x/include/mach/glantank.h b/arch/arm/mach-iop32x/glantank.h
index b9df2e4614cf..f38e86b82c3d 100644
--- a/arch/arm/mach-iop32x/include/mach/glantank.h
+++ b/arch/arm/mach-iop32x/glantank.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/glantank.h
- *
* IO-Data GLAN Tank board registers
*/
diff --git a/arch/arm/mach-iop32x/include/mach/hardware.h b/arch/arm/mach-iop32x/hardware.h
index 6e5303e60226..43ab4fb8f9b0 100644
--- a/arch/arm/mach-iop32x/include/mach/hardware.h
+++ b/arch/arm/mach-iop32x/hardware.h
@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop32x/include/mach/hardware.h
- */
-
#ifndef __HARDWARE_H
#define __HARDWARE_H
@@ -28,7 +24,7 @@ void iop32x_init_irq(void);
/*
* Generic chipset bits
*/
-#include "iop32x.h"
+#include "iop3xx.h"
/*
* Board specific bits
diff --git a/arch/arm/plat-iop/i2c.c b/arch/arm/mach-iop32x/i2c.c
index dfbd7c332866..dc9f6a14ab1b 100644
--- a/arch/arm/plat-iop/i2c.c
+++ b/arch/arm/mach-iop32x/i2c.c
@@ -22,18 +22,11 @@
#include <asm/mach/map.h>
#include <asm/setup.h>
#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop3xx.h>
#include <asm/mach/arch.h>
-#ifdef CONFIG_ARCH_IOP32X
-#define IRQ_IOP3XX_I2C_0 IRQ_IOP32X_I2C_0
-#define IRQ_IOP3XX_I2C_1 IRQ_IOP32X_I2C_1
-#endif
-#ifdef CONFIG_ARCH_IOP33X
-#define IRQ_IOP3XX_I2C_0 IRQ_IOP33X_I2C_0
-#define IRQ_IOP3XX_I2C_1 IRQ_IOP33X_I2C_1
-#endif
+#include "hardware.h"
+#include "iop3xx.h"
+#include "irqs.h"
/*
* Each of the I2C busses have corresponding GPIO lines, and the driver
@@ -65,8 +58,8 @@ static struct resource iop3xx_i2c0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_IOP3XX_I2C_0,
- .end = IRQ_IOP3XX_I2C_0,
+ .start = IRQ_IOP32X_I2C_0,
+ .end = IRQ_IOP32X_I2C_0,
.flags = IORESOURCE_IRQ,
},
};
@@ -86,8 +79,8 @@ static struct resource iop3xx_i2c1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_IOP3XX_I2C_1,
- .end = IRQ_IOP3XX_I2C_1,
+ .start = IRQ_IOP32X_I2C_1,
+ .end = IRQ_IOP32X_I2C_1,
.flags = IORESOURCE_IRQ,
}
};
diff --git a/arch/arm/mach-iop32x/include/mach/adma.h b/arch/arm/mach-iop32x/include/mach/adma.h
deleted file mode 100644
index 2b20063123ad..000000000000
--- a/arch/arm/mach-iop32x/include/mach/adma.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef IOP32X_ADMA_H
-#define IOP32X_ADMA_H
-#include <asm/hardware/iop3xx-adma.h>
-#endif
-
diff --git a/arch/arm/mach-iop32x/include/mach/entry-macro.S b/arch/arm/mach-iop32x/include/mach/entry-macro.S
index ea13ae02d9b1..8e6766d4621e 100644
--- a/arch/arm/mach-iop32x/include/mach/entry-macro.S
+++ b/arch/arm/mach-iop32x/include/mach/entry-macro.S
@@ -7,8 +7,6 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <mach/iop32x.h>
-
.macro get_irqnr_preamble, base, tmp
mrc p15, 0, \tmp, c15, c1, 0
orr \tmp, \tmp, #(1 << 6)
diff --git a/arch/arm/mach-iop32x/include/mach/iop32x.h b/arch/arm/mach-iop32x/include/mach/iop32x.h
deleted file mode 100644
index 84223f86552f..000000000000
--- a/arch/arm/mach-iop32x/include/mach/iop32x.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-iop32x/include/mach/iop32x.h
- *
- * Intel IOP32X Chip definitions
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- */
-
-#ifndef __IOP32X_H
-#define __IOP32X_H
-
-/*
- * Peripherals that are shared between the iop32x and iop33x but
- * located at different addresses.
- */
-#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
-
-#include <asm/hardware/iop3xx.h>
-
-/* ATU Parameters
- * set up a 1:1 bus to physical ram relationship
- * w/ physical ram on top of pci in the memory map
- */
-#define IOP32X_MAX_RAM_SIZE 0x40000000UL
-#define IOP3XX_MAX_RAM_SIZE IOP32X_MAX_RAM_SIZE
-#define IOP3XX_PCI_LOWER_MEM_BA 0x80000000
-
-#endif
diff --git a/arch/arm/mach-iop32x/include/mach/irqs.h b/arch/arm/mach-iop32x/include/mach/irqs.h
index 82b11743e91c..c4e78df428e8 100644
--- a/arch/arm/mach-iop32x/include/mach/irqs.h
+++ b/arch/arm/mach-iop32x/include/mach/irqs.h
@@ -9,39 +9,6 @@
#ifndef __IRQS_H
#define __IRQS_H
-/*
- * IOP80321 chipset interrupts
- */
-#define IRQ_IOP32X_DMA0_EOT 0
-#define IRQ_IOP32X_DMA0_EOC 1
-#define IRQ_IOP32X_DMA1_EOT 2
-#define IRQ_IOP32X_DMA1_EOC 3
-#define IRQ_IOP32X_AA_EOT 6
-#define IRQ_IOP32X_AA_EOC 7
-#define IRQ_IOP32X_CORE_PMON 8
-#define IRQ_IOP32X_TIMER0 9
-#define IRQ_IOP32X_TIMER1 10
-#define IRQ_IOP32X_I2C_0 11
-#define IRQ_IOP32X_I2C_1 12
-#define IRQ_IOP32X_MESSAGING 13
-#define IRQ_IOP32X_ATU_BIST 14
-#define IRQ_IOP32X_PERFMON 15
-#define IRQ_IOP32X_CORE_PMU 16
-#define IRQ_IOP32X_BIU_ERR 17
-#define IRQ_IOP32X_ATU_ERR 18
-#define IRQ_IOP32X_MCU_ERR 19
-#define IRQ_IOP32X_DMA0_ERR 20
-#define IRQ_IOP32X_DMA1_ERR 21
-#define IRQ_IOP32X_AA_ERR 23
-#define IRQ_IOP32X_MSG_ERR 24
-#define IRQ_IOP32X_SSP 25
-#define IRQ_IOP32X_XINT0 27
-#define IRQ_IOP32X_XINT1 28
-#define IRQ_IOP32X_XINT2 29
-#define IRQ_IOP32X_XINT3 30
-#define IRQ_IOP32X_HPI 31
-
#define NR_IRQS 32
-
#endif
diff --git a/arch/arm/mach-iop32x/include/mach/time.h b/arch/arm/mach-iop32x/include/mach/time.h
deleted file mode 100644
index d08950ccebc4..000000000000
--- a/arch/arm/mach-iop32x/include/mach/time.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP32X_TIME_H_
-#define _IOP32X_TIME_H_
-#define IRQ_IOP_TIMER0 IRQ_IOP32X_TIMER0
-#endif
diff --git a/arch/arm/mach-iop32x/include/mach/uncompress.h b/arch/arm/mach-iop32x/include/mach/uncompress.h
index ed4ac3e28fa1..c8548875d942 100644
--- a/arch/arm/mach-iop32x/include/mach/uncompress.h
+++ b/arch/arm/mach-iop32x/include/mach/uncompress.h
@@ -6,9 +6,8 @@
#include <asm/types.h>
#include <asm/mach-types.h>
#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-volatile u8 *uart_base;
+#define uart_base ((volatile u8 *)0xfe800000)
#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
@@ -23,17 +22,4 @@ static inline void flush(void)
{
}
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
- if (machine_is_iq80321())
- uart_base = (volatile u8 *)IQ80321_UART;
- else if (machine_is_iq31244() || machine_is_em7210())
- uart_base = (volatile u8 *)IQ31244_UART;
- else
- uart_base = (volatile u8 *)0xfe800000;
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup() __arch_decomp_setup(arch_id)
+#define arch_decomp_setup() do { } while (0)
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/mach-iop32x/iop3xx.h
index 3cb6f22f510b..46b4b34a4ad2 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/mach-iop32x/iop3xx.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * arch/arm/include/asm/hardware/iop3xx.h
- *
* Intel IOP32X and IOP33X register definitions
*
* Author: Rory Bolt <rorybolt@pacbell.net>
@@ -13,6 +11,22 @@
#define __IOP3XX_H
/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
+
+#include "iop3xx.h"
+
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ physical ram on top of pci in the memory map
+ */
+#define IOP32X_MAX_RAM_SIZE 0x40000000UL
+#define IOP3XX_MAX_RAM_SIZE IOP32X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA 0x80000000
+
+/*
* IOP3XX GPIO handling
*/
#define IOP3XX_GPIO_LINE(x) (x)
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 8755aa87e591..04a7d389d365 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -23,7 +23,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/cputype.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -33,7 +32,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/iq31244.h b/arch/arm/mach-iop32x/iq31244.h
index e62da5da6ed4..a7ac691e48d3 100644
--- a/arch/arm/mach-iop32x/include/mach/iq31244.h
+++ b/arch/arm/mach-iop32x/iq31244.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/iq31244.h
- *
* Intel IQ31244 evaluation board registers
*/
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index e12699d1c540..4bd596d6c9c1 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -20,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -29,7 +28,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/iq80321.h b/arch/arm/mach-iop32x/iq80321.h
index faf62c26f6f8..3a5d10626ea6 100644
--- a/arch/arm/mach-iop32x/include/mach/iq80321.h
+++ b/arch/arm/mach-iop32x/iq80321.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/iq80321.h
- *
* Intel IQ80321 evaluation board registers
*/
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
index 2f5d4ec94f9c..2d48bf1398c1 100644
--- a/arch/arm/mach-iop32x/irq.c
+++ b/arch/arm/mach-iop32x/irq.c
@@ -13,9 +13,10 @@
#include <linux/list.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
+#include "hardware.h"
+
static u32 iop32x_mask;
static void intctl_write(u32 val)
diff --git a/arch/arm/mach-iop32x/irqs.h b/arch/arm/mach-iop32x/irqs.h
new file mode 100644
index 000000000000..69858e4e905d
--- /dev/null
+++ b/arch/arm/mach-iop32x/irqs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright: (C) 2002 Rory Bolt
+ */
+
+#ifndef __IOP32X_IRQS_H
+#define __IOP32X_IRQS_H
+
+/*
+ * IOP80321 chipset interrupts
+ */
+#define IRQ_IOP32X_DMA0_EOT 0
+#define IRQ_IOP32X_DMA0_EOC 1
+#define IRQ_IOP32X_DMA1_EOT 2
+#define IRQ_IOP32X_DMA1_EOC 3
+#define IRQ_IOP32X_AA_EOT 6
+#define IRQ_IOP32X_AA_EOC 7
+#define IRQ_IOP32X_CORE_PMON 8
+#define IRQ_IOP32X_TIMER0 9
+#define IRQ_IOP32X_TIMER1 10
+#define IRQ_IOP32X_I2C_0 11
+#define IRQ_IOP32X_I2C_1 12
+#define IRQ_IOP32X_MESSAGING 13
+#define IRQ_IOP32X_ATU_BIST 14
+#define IRQ_IOP32X_PERFMON 15
+#define IRQ_IOP32X_CORE_PMU 16
+#define IRQ_IOP32X_BIU_ERR 17
+#define IRQ_IOP32X_ATU_ERR 18
+#define IRQ_IOP32X_MCU_ERR 19
+#define IRQ_IOP32X_DMA0_ERR 20
+#define IRQ_IOP32X_DMA1_ERR 21
+#define IRQ_IOP32X_AA_ERR 23
+#define IRQ_IOP32X_MSG_ERR 24
+#define IRQ_IOP32X_SSP 25
+#define IRQ_IOP32X_XINT0 27
+#define IRQ_IOP32X_XINT1 28
+#define IRQ_IOP32X_XINT2 29
+#define IRQ_IOP32X_XINT3 30
+#define IRQ_IOP32X_HPI 31
+
+#endif
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 26d76b377e79..5382a93ad0f8 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -28,7 +28,6 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -37,7 +36,9 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
#include "gpio-iop32x.h"
/*
diff --git a/arch/arm/mach-iop32x/include/mach/n2100.h b/arch/arm/mach-iop32x/n2100.h
index 70bb660b643a..0b97b940d3e7 100644
--- a/arch/arm/mach-iop32x/include/mach/n2100.h
+++ b/arch/arm/mach-iop32x/n2100.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * arch/arm/mach-iop32x/include/mach/n2100.h
- *
* Thecus N2100 board registers
*/
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/mach-iop32x/pci.c
index 4c42c95e4bf5..ab0010dc3145 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/mach-iop32x/pci.c
@@ -17,9 +17,9 @@
#include <linux/io.h>
#include <asm/irq.h>
#include <asm/signal.h>
-#include <mach/hardware.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/iop3xx.h>
+#include "hardware.h"
+#include "iop3xx.h"
// #define DEBUG
diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/mach-iop32x/pmu.c
index 04c44a809b32..bdbc7a3cb8a3 100644
--- a/arch/arm/plat-iop/pmu.c
+++ b/arch/arm/mach-iop32x/pmu.c
@@ -5,17 +5,11 @@
*/
#include <linux/platform_device.h>
-#include <mach/irqs.h>
+#include "irqs.h"
static struct resource pmu_resource = {
-#ifdef CONFIG_ARCH_IOP32X
.start = IRQ_IOP32X_CORE_PMU,
.end = IRQ_IOP32X_CORE_PMU,
-#endif
-#ifdef CONFIG_ARCH_IOP33X
- .start = IRQ_IOP33X_CORE_PMU,
- .end = IRQ_IOP33X_CORE_PMU,
-#endif
.flags = IORESOURCE_IRQ,
};
diff --git a/arch/arm/plat-iop/restart.c b/arch/arm/mach-iop32x/restart.c
index cf6d3d9a2112..3dfa54d3a7a8 100644
--- a/arch/arm/plat-iop/restart.c
+++ b/arch/arm/mach-iop32x/restart.c
@@ -4,9 +4,9 @@
*
* Copyright (C) 2001 MontaVista Software, Inc.
*/
-#include <asm/hardware/iop3xx.h>
#include <asm/system_misc.h>
-#include <mach/hardware.h>
+#include "hardware.h"
+#include "iop3xx.h"
void iop3xx_restart(enum reboot_mode mode, const char *cmd)
{
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/mach-iop32x/setup.c
index d10e0102d82c..a0a81c28a632 100644
--- a/arch/arm/plat-iop/setup.c
+++ b/arch/arm/mach-iop32x/setup.c
@@ -10,7 +10,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <asm/mach/map.h>
-#include <asm/hardware/iop3xx.h>
+#include "iop3xx.h"
/*
* Standard IO mapping for all IOP3xx based systems. Note that
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/mach-iop32x/time.c
index f9dd1f50cfe5..18a4df5c1baa 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/mach-iop32x/time.c
@@ -19,12 +19,13 @@
#include <linux/clockchips.h>
#include <linux/export.h>
#include <linux/sched_clock.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <linux/uaccess.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-#include <mach/time.h>
+
+#include "hardware.h"
+#include "irqs.h"
/*
* Minimum clocksource/clockevent timer range in seconds
@@ -167,7 +168,7 @@ void __init iop_init_time(unsigned long tick_rate)
*/
write_tmr0(timer_ctl & ~IOP_TMR_EN);
write_tisr(1);
- setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
+ setup_irq(IRQ_IOP32X_TIMER0, &iop_timer_irq);
iop_clockevent.cpumask = cpumask_of(0);
clockevents_config_and_register(&iop_clockevent, tick_rate,
0xf, 0xfffffffe);
diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
deleted file mode 100644
index cd6069c7c568..000000000000
--- a/arch/arm/mach-iop33x/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-if ARCH_IOP33X
-
-menu "IOP33x Implementation Options"
-
-comment "IOP33x Platform Types"
-
-config ARCH_IQ80331
- bool "Enable support for IQ80331"
- help
- Say Y here if you want to run your kernel on the Intel IQ80331
- evaluation kit for the IOP331 chipset.
-
-config MACH_IQ80332
- bool "Enable support for IQ80332"
- help
- Say Y here if you want to run your kernel on the Intel IQ80332
- evaluation kit for the IOP332 chipset.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-iop33x/Makefile b/arch/arm/mach-iop33x/Makefile
deleted file mode 100644
index 320ecde1f907..000000000000
--- a/arch/arm/mach-iop33x/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the linux kernel.
-#
-
-obj-y := irq.o uart.o
-
-obj-$(CONFIG_ARCH_IQ80331) += iq80331.o
-obj-$(CONFIG_MACH_IQ80332) += iq80332.o
diff --git a/arch/arm/mach-iop33x/Makefile.boot b/arch/arm/mach-iop33x/Makefile.boot
deleted file mode 100644
index e4dd1d26038f..000000000000
--- a/arch/arm/mach-iop33x/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-iop33x/include/mach/adma.h b/arch/arm/mach-iop33x/include/mach/adma.h
deleted file mode 100644
index 8aa7159ab6d8..000000000000
--- a/arch/arm/mach-iop33x/include/mach/adma.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef IOP33X_ADMA_H
-#define IOP33X_ADMA_H
-#include <asm/hardware/iop3xx-adma.h>
-#endif
-
diff --git a/arch/arm/mach-iop33x/include/mach/entry-macro.S b/arch/arm/mach-iop33x/include/mach/entry-macro.S
deleted file mode 100644
index 0a398fe1fba4..000000000000
--- a/arch/arm/mach-iop33x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for IOP33x-based platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/iop33x.h>
-
- .macro get_irqnr_preamble, base, tmp
- mrc p15, 0, \tmp, c15, c1, 0
- orr \tmp, \tmp, #(1 << 6)
- mcr p15, 0, \tmp, c15, c1, 0 @ Enable cp6 access
- mrc p15, 0, \tmp, c15, c1, 0
- mov \tmp, \tmp
- sub pc, pc, #4 @ cp_wait
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mrc p6, 0, \irqstat, c14, c0, 0 @ Read IINTVEC
- cmp \irqstat, #0
- mrceq p6, 0, \irqstat, c14, c0, 0 @ erratum 63 workaround
- adds \irqnr, \irqstat, #1
- movne \irqnr, \irqstat, lsr #2
- .endm
-
- .macro arch_ret_to_user, tmp1, tmp2
- mrc p15, 0, \tmp1, c15, c1, 0
- ands \tmp2, \tmp1, #(1 << 6)
- bicne \tmp1, \tmp1, #(1 << 6)
- mcrne p15, 0, \tmp1, c15, c1, 0 @ Disable cp6 access
- .endm
diff --git a/arch/arm/mach-iop33x/include/mach/hardware.h b/arch/arm/mach-iop33x/include/mach/hardware.h
deleted file mode 100644
index 020bafbc36a5..000000000000
--- a/arch/arm/mach-iop33x/include/mach/hardware.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop33x/include/mach/hardware.h
- */
-
-#ifndef __HARDWARE_H
-#define __HARDWARE_H
-
-#include <asm/types.h>
-
-/*
- * Note about PCI IO space mappings
- *
- * To make IO space accesses efficient, we store virtual addresses in
- * the IO resources.
- *
- * The PCI IO space is located at virtual 0xfe000000 from physical
- * 0x90000000. The PCI BARs must be programmed with physical addresses,
- * but when we read them, we convert them to virtual addresses. See
- * arch/arm/mach-iop3xx/iop3xx-pci.c
- */
-
-#ifndef __ASSEMBLY__
-void iop33x_init_irq(void);
-
-extern struct platform_device iop33x_uart0_device;
-extern struct platform_device iop33x_uart1_device;
-#endif
-
-
-/*
- * Generic chipset bits
- *
- */
-#include "iop33x.h"
-
-/*
- * Board specific bits
- */
-#include "iq80331.h"
-#include "iq80332.h"
-
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/iop33x.h b/arch/arm/mach-iop33x/include/mach/iop33x.h
deleted file mode 100644
index 0c7041ed7a60..000000000000
--- a/arch/arm/mach-iop33x/include/mach/iop33x.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-iop33x/include/mach/iop33x.h
- *
- * Intel IOP33X Chip definitions
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2003, 2004 Intel Corp.
- */
-
-#ifndef __IOP33X_H
-#define __IOP33X_H
-
-/*
- * Peripherals that are shared between the iop32x and iop33x but
- * located at different addresses.
- */
-#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07d0 + (reg))
-
-#include <asm/hardware/iop3xx.h>
-
-/* UARTs */
-#define IOP33X_UART0_PHYS (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1700)
-#define IOP33X_UART0_VIRT (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1700)
-#define IOP33X_UART1_PHYS (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1740)
-#define IOP33X_UART1_VIRT (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1740)
-
-/* ATU Parameters
- * set up a 1:1 bus to physical ram relationship
- * w/ pci on top of physical ram in memory map
- */
-#define IOP33X_MAX_RAM_SIZE 0x80000000UL
-#define IOP3XX_MAX_RAM_SIZE IOP33X_MAX_RAM_SIZE
-#define IOP3XX_PCI_LOWER_MEM_BA (PHYS_OFFSET + IOP33X_MAX_RAM_SIZE)
-
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/iq80331.h b/arch/arm/mach-iop33x/include/mach/iq80331.h
deleted file mode 100644
index c7e68d863e44..000000000000
--- a/arch/arm/mach-iop33x/include/mach/iq80331.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop33x/include/mach/iq80331.h
- *
- * Intel IQ80331 evaluation board registers
- */
-
-#ifndef __IQ80331_H
-#define __IQ80331_H
-
-#define IQ80331_7SEG_1 0xce840000 /* 7-Segment MSB */
-#define IQ80331_7SEG_0 0xce850000 /* 7-Segment LSB (WO) */
-#define IQ80331_ROTARY_SW 0xce8d0000 /* Rotary Switch */
-#define IQ80331_BATT_STAT 0xce8f0000 /* Battery Status */
-
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/iq80332.h b/arch/arm/mach-iop33x/include/mach/iq80332.h
deleted file mode 100644
index 749b44bf7f62..000000000000
--- a/arch/arm/mach-iop33x/include/mach/iq80332.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop33x/include/mach/iq80332.h
- *
- * Intel IQ80332 evaluation board registers
- */
-
-#ifndef __IQ80332_H
-#define __IQ80332_H
-
-#define IQ80332_7SEG_1 0xce840000 /* 7-Segment MSB */
-#define IQ80332_7SEG_0 0xce850000 /* 7-Segment LSB (WO) */
-#define IQ80332_ROTARY_SW 0xce8d0000 /* Rotary Switch */
-#define IQ80332_BATT_STAT 0xce8f0000 /* Battery Status */
-
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/irqs.h b/arch/arm/mach-iop33x/include/mach/irqs.h
deleted file mode 100644
index cc3dce0ad4a1..000000000000
--- a/arch/arm/mach-iop33x/include/mach/irqs.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-iop33x/include/mach/irqs.h
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright: (C) 2003 Intel Corp.
- */
-
-#ifndef __IRQS_H
-#define __IRQS_H
-
-/*
- * IOP80331 chipset interrupts
- */
-#define IRQ_IOP33X_DMA0_EOT 0
-#define IRQ_IOP33X_DMA0_EOC 1
-#define IRQ_IOP33X_DMA1_EOT 2
-#define IRQ_IOP33X_DMA1_EOC 3
-#define IRQ_IOP33X_AA_EOT 6
-#define IRQ_IOP33X_AA_EOC 7
-#define IRQ_IOP33X_TIMER0 8
-#define IRQ_IOP33X_TIMER1 9
-#define IRQ_IOP33X_I2C_0 10
-#define IRQ_IOP33X_I2C_1 11
-#define IRQ_IOP33X_MSG 12
-#define IRQ_IOP33X_MSGIBQ 13
-#define IRQ_IOP33X_ATU_BIST 14
-#define IRQ_IOP33X_PERFMON 15
-#define IRQ_IOP33X_CORE_PMU 16
-#define IRQ_IOP33X_XINT0 24
-#define IRQ_IOP33X_XINT1 25
-#define IRQ_IOP33X_XINT2 26
-#define IRQ_IOP33X_XINT3 27
-#define IRQ_IOP33X_XINT8 32
-#define IRQ_IOP33X_XINT9 33
-#define IRQ_IOP33X_XINT10 34
-#define IRQ_IOP33X_XINT11 35
-#define IRQ_IOP33X_XINT12 36
-#define IRQ_IOP33X_XINT13 37
-#define IRQ_IOP33X_XINT14 38
-#define IRQ_IOP33X_XINT15 39
-#define IRQ_IOP33X_UART0 51
-#define IRQ_IOP33X_UART1 52
-#define IRQ_IOP33X_PBIE 53
-#define IRQ_IOP33X_ATU_CRW 54
-#define IRQ_IOP33X_ATU_ERR 55
-#define IRQ_IOP33X_MCU_ERR 56
-#define IRQ_IOP33X_DMA0_ERR 57
-#define IRQ_IOP33X_DMA1_ERR 58
-#define IRQ_IOP33X_AA_ERR 60
-#define IRQ_IOP33X_MSG_ERR 62
-#define IRQ_IOP33X_HPI 63
-
-#define NR_IRQS 64
-
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/time.h b/arch/arm/mach-iop33x/include/mach/time.h
deleted file mode 100644
index 801f8fd644ad..000000000000
--- a/arch/arm/mach-iop33x/include/mach/time.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IOP33X_TIME_H_
-#define _IOP33X_TIME_H_
-#define IRQ_IOP_TIMER0 IRQ_IOP33X_TIMER0
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/uncompress.h b/arch/arm/mach-iop33x/include/mach/uncompress.h
deleted file mode 100644
index 62b71cde1f79..000000000000
--- a/arch/arm/mach-iop33x/include/mach/uncompress.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-iop33x/include/mach/uncompress.h
- */
-
-#include <asm/types.h>
-#include <asm/mach-types.h>
-#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-
-volatile u32 *uart_base;
-
-#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
-
-static inline void putc(char c)
-{
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
- barrier();
- uart_base[UART_TX] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
- if (machine_is_iq80331() || machine_is_iq80332())
- uart_base = (volatile u32 *)IOP33X_UART0_PHYS;
- else
- uart_base = (volatile u32 *)0xfe800000;
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup() __arch_decomp_setup(arch_id)
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
deleted file mode 100644
index ab74fbabc749..000000000000
--- a/arch/arm/mach-iop33x/iq80331.c
+++ /dev/null
@@ -1,148 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-iop33x/iq80331.c
- *
- * Board support code for the Intel IQ80331 platform.
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/pci.h>
-#include <asm/mach/time.h>
-#include <asm/mach-types.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <mach/time.h>
-
-/*
- * IQ80331 timer tick configuration.
- */
-static void __init iq80331_timer_init(void)
-{
- /* D-Step parts run at a higher internal bus frequency */
- if (*IOP3XX_ATURID >= 0xa)
- iop_init_time(333000000);
- else
- iop_init_time(266000000);
-}
-
-
-/*
- * IQ80331 PCI.
- */
-static int __init
-iq80331_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq;
-
- if (slot == 1 && pin == 1) {
- /* PCI-X Slot INTA */
- irq = IRQ_IOP33X_XINT1;
- } else if (slot == 1 && pin == 2) {
- /* PCI-X Slot INTB */
- irq = IRQ_IOP33X_XINT2;
- } else if (slot == 1 && pin == 3) {
- /* PCI-X Slot INTC */
- irq = IRQ_IOP33X_XINT3;
- } else if (slot == 1 && pin == 4) {
- /* PCI-X Slot INTD */
- irq = IRQ_IOP33X_XINT0;
- } else if (slot == 2) {
- /* GigE */
- irq = IRQ_IOP33X_XINT2;
- } else {
- printk(KERN_ERR "iq80331_pci_map_irq() called for unknown "
- "device PCI:%d:%d:%d\n", dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- irq = -1;
- }
-
- return irq;
-}
-
-static struct hw_pci iq80331_pci __initdata = {
- .nr_controllers = 1,
- .ops = &iop3xx_ops,
- .setup = iop3xx_pci_setup,
- .preinit = iop3xx_pci_preinit_cond,
- .map_irq = iq80331_pci_map_irq,
-};
-
-static int __init iq80331_pci_init(void)
-{
- if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
- machine_is_iq80331())
- pci_common_init(&iq80331_pci);
-
- return 0;
-}
-
-subsys_initcall(iq80331_pci_init);
-
-
-/*
- * IQ80331 machine initialisation.
- */
-static struct physmap_flash_data iq80331_flash_data = {
- .width = 1,
-};
-
-static struct resource iq80331_flash_resource = {
- .start = 0xc0000000,
- .end = 0xc07fffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device iq80331_flash_device = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &iq80331_flash_data,
- },
- .num_resources = 1,
- .resource = &iq80331_flash_resource,
-};
-
-static struct resource iq80331_gpio_res[] = {
- DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
-};
-
-static void __init iq80331_init_machine(void)
-{
- platform_device_register_simple("gpio-iop", 0,
- iq80331_gpio_res,
- ARRAY_SIZE(iq80331_gpio_res));
- platform_device_register(&iop3xx_i2c0_device);
- platform_device_register(&iop3xx_i2c1_device);
- platform_device_register(&iop33x_uart0_device);
- platform_device_register(&iop33x_uart1_device);
- platform_device_register(&iq80331_flash_device);
- platform_device_register(&iop3xx_dma_0_channel);
- platform_device_register(&iop3xx_dma_1_channel);
- platform_device_register(&iop3xx_aau_channel);
-}
-
-MACHINE_START(IQ80331, "Intel IQ80331")
- /* Maintainer: Intel Corp. */
- .atag_offset = 0x100,
- .map_io = iop3xx_map_io,
- .init_irq = iop33x_init_irq,
- .init_time = iq80331_timer_init,
- .init_machine = iq80331_init_machine,
- .restart = iop3xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
deleted file mode 100644
index 2e309b197aa4..000000000000
--- a/arch/arm/mach-iop33x/iq80332.c
+++ /dev/null
@@ -1,148 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-iop33x/iq80332.c
- *
- * Board support code for the Intel IQ80332 platform.
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2004 Intel Corp.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/pci.h>
-#include <asm/mach/time.h>
-#include <asm/mach-types.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <mach/time.h>
-
-/*
- * IQ80332 timer tick configuration.
- */
-static void __init iq80332_timer_init(void)
-{
- /* D-Step parts and the iop333 run at a higher internal bus frequency */
- if (*IOP3XX_ATURID >= 0xa || *IOP3XX_ATUDID == 0x374)
- iop_init_time(333000000);
- else
- iop_init_time(266000000);
-}
-
-
-/*
- * IQ80332 PCI.
- */
-static int __init
-iq80332_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq;
-
- if (slot == 4 && pin == 1) {
- /* PCI-X Slot INTA */
- irq = IRQ_IOP33X_XINT0;
- } else if (slot == 4 && pin == 2) {
- /* PCI-X Slot INTB */
- irq = IRQ_IOP33X_XINT1;
- } else if (slot == 4 && pin == 3) {
- /* PCI-X Slot INTC */
- irq = IRQ_IOP33X_XINT2;
- } else if (slot == 4 && pin == 4) {
- /* PCI-X Slot INTD */
- irq = IRQ_IOP33X_XINT3;
- } else if (slot == 6) {
- /* GigE */
- irq = IRQ_IOP33X_XINT2;
- } else {
- printk(KERN_ERR "iq80332_pci_map_irq() called for unknown "
- "device PCI:%d:%d:%d\n", dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- irq = -1;
- }
-
- return irq;
-}
-
-static struct hw_pci iq80332_pci __initdata = {
- .nr_controllers = 1,
- .ops = &iop3xx_ops,
- .setup = iop3xx_pci_setup,
- .preinit = iop3xx_pci_preinit_cond,
- .map_irq = iq80332_pci_map_irq,
-};
-
-static int __init iq80332_pci_init(void)
-{
- if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
- machine_is_iq80332())
- pci_common_init(&iq80332_pci);
-
- return 0;
-}
-
-subsys_initcall(iq80332_pci_init);
-
-
-/*
- * IQ80332 machine initialisation.
- */
-static struct physmap_flash_data iq80332_flash_data = {
- .width = 1,
-};
-
-static struct resource iq80332_flash_resource = {
- .start = 0xc0000000,
- .end = 0xc07fffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device iq80332_flash_device = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &iq80332_flash_data,
- },
- .num_resources = 1,
- .resource = &iq80332_flash_resource,
-};
-
-static struct resource iq80332_gpio_res[] = {
- DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
-};
-
-static void __init iq80332_init_machine(void)
-{
- platform_device_register_simple("gpio-iop", 0,
- iq80332_gpio_res,
- ARRAY_SIZE(iq80332_gpio_res));
- platform_device_register(&iop3xx_i2c0_device);
- platform_device_register(&iop3xx_i2c1_device);
- platform_device_register(&iop33x_uart0_device);
- platform_device_register(&iop33x_uart1_device);
- platform_device_register(&iq80332_flash_device);
- platform_device_register(&iop3xx_dma_0_channel);
- platform_device_register(&iop3xx_dma_1_channel);
- platform_device_register(&iop3xx_aau_channel);
-}
-
-MACHINE_START(IQ80332, "Intel IQ80332")
- /* Maintainer: Intel Corp. */
- .atag_offset = 0x100,
- .map_io = iop3xx_map_io,
- .init_irq = iop33x_init_irq,
- .init_time = iq80332_timer_init,
- .init_machine = iq80332_init_machine,
- .restart = iop3xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
deleted file mode 100644
index 03ad7d3a8f49..000000000000
--- a/arch/arm/mach-iop33x/irq.c
+++ /dev/null
@@ -1,115 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-iop33x/irq.c
- *
- * Generic IOP331 IRQ handling functionality
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-static u32 iop33x_mask0;
-static u32 iop33x_mask1;
-
-static void intctl0_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
-}
-
-static void intctl1_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
-}
-
-static void intstr0_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
-}
-
-static void intstr1_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
-}
-
-static void intbase_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
-}
-
-static void intsize_write(u32 val)
-{
- asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
-}
-
-static void
-iop33x_irq_mask1 (struct irq_data *d)
-{
- iop33x_mask0 &= ~(1 << d->irq);
- intctl0_write(iop33x_mask0);
-}
-
-static void
-iop33x_irq_mask2 (struct irq_data *d)
-{
- iop33x_mask1 &= ~(1 << (d->irq - 32));
- intctl1_write(iop33x_mask1);
-}
-
-static void
-iop33x_irq_unmask1(struct irq_data *d)
-{
- iop33x_mask0 |= 1 << d->irq;
- intctl0_write(iop33x_mask0);
-}
-
-static void
-iop33x_irq_unmask2(struct irq_data *d)
-{
- iop33x_mask1 |= (1 << (d->irq - 32));
- intctl1_write(iop33x_mask1);
-}
-
-struct irq_chip iop33x_irqchip1 = {
- .name = "IOP33x-1",
- .irq_ack = iop33x_irq_mask1,
- .irq_mask = iop33x_irq_mask1,
- .irq_unmask = iop33x_irq_unmask1,
-};
-
-struct irq_chip iop33x_irqchip2 = {
- .name = "IOP33x-2",
- .irq_ack = iop33x_irq_mask2,
- .irq_mask = iop33x_irq_mask2,
- .irq_unmask = iop33x_irq_unmask2,
-};
-
-void __init iop33x_init_irq(void)
-{
- int i;
-
- iop_init_cp6_handler();
-
- intctl0_write(0);
- intctl1_write(0);
- intstr0_write(0);
- intstr1_write(0);
- intbase_write(0);
- intsize_write(1);
- if (machine_is_iq80331())
- *IOP3XX_PCIIRSR = 0x0f;
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_set_chip_and_handler(i,
- (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2,
- handle_level_irq);
- irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
- }
-}
diff --git a/arch/arm/mach-iop33x/uart.c b/arch/arm/mach-iop33x/uart.c
deleted file mode 100644
index 8fa079d2e3c3..000000000000
--- a/arch/arm/mach-iop33x/uart.c
+++ /dev/null
@@ -1,100 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-iop33x/uart.c
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2004 Intel Corporation.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop3xx.h>
-#include <asm/mach/arch.h>
-
-#define IOP33X_UART_XTAL 33334000
-
-static struct plat_serial8250_port iop33x_uart0_data[] = {
- {
- .membase = (char *)IOP33X_UART0_VIRT,
- .mapbase = IOP33X_UART0_PHYS,
- .irq = IRQ_IOP33X_UART0,
- .uartclk = IOP33X_UART_XTAL,
- .regshift = 2,
- .iotype = UPIO_MEM,
- .flags = UPF_SKIP_TEST,
- },
- { },
-};
-
-static struct resource iop33x_uart0_resources[] = {
- [0] = {
- .start = IOP33X_UART0_PHYS,
- .end = IOP33X_UART0_PHYS + 0x3f,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP33X_UART0,
- .end = IRQ_IOP33X_UART0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device iop33x_uart0_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = iop33x_uart0_data,
- },
- .num_resources = 2,
- .resource = iop33x_uart0_resources,
-};
-
-
-static struct resource iop33x_uart1_resources[] = {
- [0] = {
- .start = IOP33X_UART1_PHYS,
- .end = IOP33X_UART1_PHYS + 0x3f,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_IOP33X_UART1,
- .end = IRQ_IOP33X_UART1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct plat_serial8250_port iop33x_uart1_data[] = {
- {
- .membase = (char *)IOP33X_UART1_VIRT,
- .mapbase = IOP33X_UART1_PHYS,
- .irq = IRQ_IOP33X_UART1,
- .uartclk = IOP33X_UART_XTAL,
- .regshift = 2,
- .iotype = UPIO_MEM,
- .flags = UPF_SKIP_TEST,
- },
- { },
-};
-
-struct platform_device iop33x_uart1_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM1,
- .dev = {
- .platform_data = iop33x_uart1_data,
- },
- .num_resources = 2,
- .resource = iop33x_uart1_resources,
-};
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
deleted file mode 100644
index 724d7d039f74..000000000000
--- a/arch/arm/mach-ks8695/Kconfig
+++ /dev/null
@@ -1,88 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-if ARCH_KS8695
-
-menu "Kendin/Micrel KS8695 Implementations"
-
-config MACH_KS8695
- bool "KS8695 development board"
- select HAVE_PCI
- help
- Say 'Y' here if you want your kernel to run on the original
- Kendin-Micrel KS8695 development board.
-
-config MACH_DSM320
- bool "DSM-320 Wireless Media Player"
- help
- Say 'Y' here if you want your kernel to run on the D-Link
- DSM-320 Wireless Media Player.
-
-config MACH_ACS5K
- bool "Brivo Systems LLC, ACS-5000 Master board"
- help
- say 'Y' here if you want your kernel to run on the Brivo
- Systems LLC, ACS-5000 Master board.
-
-config MACH_LITE300
- bool "SecureComputing SG300"
- help
- Say 'Y' here if you want your kernel to support the
- SecureComputing / SnapGear SG300 VPN Internet Router.
- See http://www.securecomputing.com for more details.
-
-config MACH_SG310
- bool "McAfee SG310"
- help
- Say 'Y' here if you want your kernel to support the
- McAfee / SnapGear SG310 VPN Internet Router.
- See http://www.mcafee.com for more details.
-
-config MACH_SE4200
- bool "SecureComputing SE4200"
- help
- Say 'Y' here if you want your kernel to support the
- SecureComputing / SnapGear SE4200 Secure Wireless VPN
- Internet Router.
- See http://www.securecomputing.com for more details.
-
-config MACH_CM4002
- bool "OpenGear CM4002"
- help
- Say 'Y' here if you want your kernel to support the OpenGear
- CM4002 Secure Access Server. See http://www.opengear.com for
- more details.
-
-config MACH_CM4008
- bool "OpenGear CM4008"
- select HAVE_PCI
- help
- Say 'Y' here if you want your kernel to support the OpenGear
- CM4008 Console Server. See http://www.opengear.com for more
- details.
-
-config MACH_CM41xx
- bool "OpenGear CM41xx"
- select HAVE_PCI
- help
- Say 'Y' here if you want your kernel to support the OpenGear
- CM4016 or CM4048 Console Servers. See http://www.opengear.com for
- more details.
-
-config MACH_IM4004
- bool "OpenGear IM4004"
- select HAVE_PCI
- help
- Say 'Y' here if you want your kernel to support the OpenGear
- IM4004 Secure Access Server. See http://www.opengear.com for
- more details.
-
-config MACH_IM42xx
- bool "OpenGear IM42xx"
- select HAVE_PCI
- help
- Say 'Y' here if you want your kernel to support the OpenGear
- IM4216 or IM4248 Console Servers. See http://www.opengear.com for
- more details.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
deleted file mode 100644
index 439b22255a32..000000000000
--- a/arch/arm/mach-ks8695/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# arch/arm/mach-ks8695/Makefile
-#
-# Makefile for KS8695 architecture support
-#
-
-obj-y := cpu.o irq.o time.o devices.o
-
-# PCI support is optional
-obj-$(CONFIG_PCI) += pci.o
-
-# Board-specific support
-obj-$(CONFIG_MACH_KS8695) += board-micrel.o
-obj-$(CONFIG_MACH_DSM320) += board-dsm320.o
-obj-$(CONFIG_MACH_ACS5K) += board-acs5k.o
-obj-$(CONFIG_MACH_LITE300) += board-sg.o
-obj-$(CONFIG_MACH_SG310) += board-sg.o
-obj-$(CONFIG_MACH_SE4200) += board-sg.o
-obj-$(CONFIG_MACH_CM4002) += board-og.o
-obj-$(CONFIG_MACH_CM4008) += board-og.o
-obj-$(CONFIG_MACH_CM41xx) += board-og.o
-obj-$(CONFIG_MACH_IM4004) += board-og.o
-obj-$(CONFIG_MACH_IM42xx) += board-og.o
diff --git a/arch/arm/mach-ks8695/Makefile.boot b/arch/arm/mach-ks8695/Makefile.boot
deleted file mode 100644
index cf32eb605bd8..000000000000
--- a/arch/arm/mach-ks8695/Makefile.boot
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-# Note: the following conditions must always be true:
-# ZRELADDR == virt_to_phys(TEXTADDR)
-# PARAMS_PHYS must be within 4MB of ZRELADDR
-# INITRD_PHYS must be in RAM
-
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
deleted file mode 100644
index f319258d1226..000000000000
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ks8695/board-acs5k.c
- *
- * Brivo Systems LLC, ACS-5000 Master Board
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/machine.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/platform_data/i2c-gpio.h>
-#include <linux/platform_data/pca953x.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "devices.h"
-#include <mach/gpio-ks8695.h>
-
-#include "generic.h"
-
-static struct gpiod_lookup_table acs5k_i2c_gpiod_table = {
- .dev_id = "i2c-gpio",
- .table = {
- GPIO_LOOKUP_IDX("KS8695", 4, NULL, 0,
- GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("KS8695", 5, NULL, 1,
- GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = {
- .udelay = 10,
-};
-
-static struct platform_device acs5k_i2c_device = {
- .name = "i2c-gpio",
- .id = -1,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &acs5k_i2c_device_platdata,
- },
-};
-
-static int acs5k_pca9555_setup(struct i2c_client *client,
- unsigned gpio_base, unsigned ngpio,
- void *context)
-{
- static int acs5k_gpio_value[] = {
- -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, -1, 0, 1, 0, -1, -1
- };
- int n;
-
- for (n = 0; n < ARRAY_SIZE(acs5k_gpio_value); ++n) {
- gpio_request(gpio_base + n, "ACS-5000 GPIO Expander");
- if (acs5k_gpio_value[n] < 0)
- gpio_direction_input(gpio_base + n);
- else
- gpio_direction_output(gpio_base + n,
- acs5k_gpio_value[n]);
- gpio_export(gpio_base + n, 0); /* Export, direction locked down */
- }
-
- return 0;
-}
-
-static struct pca953x_platform_data acs5k_i2c_pca9555_platdata = {
- .gpio_base = 16, /* Start directly after the CPU's GPIO */
- .invert = 0, /* Do not invert */
- .setup = acs5k_pca9555_setup,
-};
-
-static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
- {
- I2C_BOARD_INFO("pca9555", 0x20),
- .platform_data = &acs5k_i2c_pca9555_platdata,
- },
-};
-
-static void __init acs5k_i2c_init(void)
-{
- /* The gpio interface */
- gpiod_add_lookup_table(&acs5k_i2c_gpiod_table);
- platform_device_register(&acs5k_i2c_device);
- /* I2C devices */
- i2c_register_board_info(0, acs5k_i2c_devs,
- ARRAY_SIZE(acs5k_i2c_devs));
-}
-
-static struct mtd_partition acs5k_nor_partitions[] = {
- [0] = {
- .name = "Boot Agent and config",
- .size = SZ_256K,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE,
- },
- [1] = {
- .name = "Kernel",
- .size = SZ_1M,
- .offset = SZ_256K,
- },
- [2] = {
- .name = "SquashFS1",
- .size = SZ_2M,
- .offset = SZ_256K + SZ_1M,
- },
- [3] = {
- .name = "SquashFS2",
- .size = SZ_4M + SZ_2M,
- .offset = SZ_256K + SZ_1M + SZ_2M,
- },
- [4] = {
- .name = "Data",
- .size = SZ_16M + SZ_4M + SZ_2M + SZ_512K, /* 22.5 MB */
- .offset = SZ_256K + SZ_8M + SZ_1M,
- }
-};
-
-static struct physmap_flash_data acs5k_nor_pdata = {
- .width = 4,
- .nr_parts = ARRAY_SIZE(acs5k_nor_partitions),
- .parts = acs5k_nor_partitions,
-};
-
-static struct resource acs5k_nor_resource[] = {
- [0] = {
- .start = SZ_32M, /* We expect the bootloader to map
- * the flash here.
- */
- .end = SZ_32M + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = SZ_32M + SZ_16M,
- .end = SZ_32M + SZ_32M - SZ_256K - 1,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct platform_device acs5k_device_nor = {
- .name = "physmap-flash",
- .id = -1,
- .num_resources = ARRAY_SIZE(acs5k_nor_resource),
- .resource = acs5k_nor_resource,
- .dev = {
- .platform_data = &acs5k_nor_pdata,
- },
-};
-
-static void __init acs5k_register_nor(void)
-{
- int ret;
-
- if (acs5k_nor_partitions[0].mask_flags == 0)
- printk(KERN_WARNING "Warning: Unprotecting bootloader and configuration partition\n");
-
- ret = platform_device_register(&acs5k_device_nor);
- if (ret < 0)
- printk(KERN_ERR "failed to register physmap-flash device\n");
-}
-
-static int __init acs5k_protection_setup(char *s)
-{
- /* We can't allocate anything here but we should be able
- * to trivially parse s and decide if we can protect the
- * bootloader partition or not
- */
- if (strcmp(s, "no") == 0)
- acs5k_nor_partitions[0].mask_flags = 0;
-
- return 1;
-}
-
-__setup("protect_bootloader=", acs5k_protection_setup);
-
-static void __init acs5k_init_gpio(void)
-{
- int i;
-
- ks8695_register_gpios();
- for (i = 0; i < 4; ++i)
- gpio_request(i, "ACS5K IRQ");
- gpio_request(7, "ACS5K KS_FRDY");
- for (i = 8; i < 16; ++i)
- gpio_request(i, "ACS5K Unused");
-
- gpio_request(3, "ACS5K CAN Control");
- gpio_request(6, "ACS5K Heartbeat");
- gpio_direction_output(3, 1); /* Default CAN_RESET high */
- gpio_direction_output(6, 0); /* Default KS8695_ACTIVE low */
- gpio_export(3, 0); /* export CAN_RESET as output only */
- gpio_export(6, 0); /* export KS8695_ACTIVE as output only */
-}
-
-static void __init acs5k_init(void)
-{
- acs5k_init_gpio();
-
- /* Network device */
- ks8695_add_device_lan(); /* eth0 = LAN */
- ks8695_add_device_wan(); /* ethX = WAN */
-
- /* NOR devices */
- acs5k_register_nor();
-
- /* I2C bus */
- acs5k_i2c_init();
-}
-
-MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
- /* Maintainer: Simtec Electronics. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = acs5k_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c
deleted file mode 100644
index d5f435cae6e0..000000000000
--- a/arch/arm/mach-ks8695/board-dsm320.c
+++ /dev/null
@@ -1,127 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ks8695/board-dsm320.c
- *
- * DSM-320 D-Link Wireless Media Player, board support.
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "devices.h"
-#include <mach/gpio-ks8695.h>
-
-#include "generic.h"
-
-#ifdef CONFIG_PCI
-static int dsm320_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- switch (slot) {
- case 0:
- /* PCI-AHB bridge? */
- return KS8695_IRQ_EXTERN0;
- case 18:
- /* Mini PCI slot */
- return KS8695_IRQ_EXTERN2;
- case 20:
- /* RealMAGIC chip */
- return KS8695_IRQ_EXTERN0;
- }
- BUG();
-}
-
-static struct ks8695_pci_cfg __initdata dsm320_pci = {
- .mode = KS8695_MODE_MINIPCI,
- .map_irq = dsm320_pci_map_irq,
-};
-
-static void __init dsm320_register_pci(void)
-{
- /* Initialise the GPIO lines for interrupt mode */
- /* RealMAGIC */
- ks8695_gpio_interrupt(KS8695_GPIO_0, IRQ_TYPE_LEVEL_LOW);
- /* MiniPCI Slot */
- ks8695_gpio_interrupt(KS8695_GPIO_2, IRQ_TYPE_LEVEL_LOW);
-
- ks8695_init_pci(&dsm320_pci);
-}
-
-#else
-static inline void __init dsm320_register_pci(void) { }
-#endif
-
-static struct physmap_flash_data dsm320_nor_pdata = {
- .width = 4,
- .nr_parts = 0,
-};
-
-static struct resource dsm320_nor_resource[] = {
- [0] = {
- .start = SZ_32M, /* We expect the bootloader to map
- * the flash here.
- */
- .end = SZ_32M + SZ_4M - 1,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct platform_device dsm320_device_nor = {
- .name = "physmap-flash",
- .id = -1,
- .num_resources = ARRAY_SIZE(dsm320_nor_resource),
- .resource = dsm320_nor_resource,
- .dev = {
- .platform_data = &dsm320_nor_pdata,
- },
-};
-
-void __init dsm320_register_nor(void)
-{
- int ret;
-
- ret = platform_device_register(&dsm320_device_nor);
- if (ret < 0)
- printk(KERN_ERR "failed to register physmap-flash device\n");
-}
-
-static void __init dsm320_init(void)
-{
- /* GPIO registration */
- ks8695_register_gpios();
-
- /* PCI registration */
- dsm320_register_pci();
-
- /* Network device */
- ks8695_add_device_lan(); /* eth0 = LAN */
-
- /* NOR devices */
- dsm320_register_nor();
-}
-
-MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
- /* Maintainer: Simtec Electronics. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = dsm320_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
deleted file mode 100644
index bf8856ce3fbb..000000000000
--- a/arch/arm/mach-ks8695/board-micrel.c
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ks8695/board-micrel.c
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/gpio-ks8695.h>
-#include "devices.h"
-
-#include "generic.h"
-
-#ifdef CONFIG_PCI
-static int micrel_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- return KS8695_IRQ_EXTERN0;
-}
-
-static struct ks8695_pci_cfg __initdata micrel_pci = {
- .mode = KS8695_MODE_MINIPCI,
- .map_irq = micrel_pci_map_irq,
-};
-#endif
-
-
-static void __init micrel_init(void)
-{
- printk(KERN_INFO "Micrel KS8695 Development Board initializing\n");
-
- ks8695_register_gpios();
-
-#ifdef CONFIG_PCI
- ks8695_init_pci(&micrel_pci);
-#endif
-
- /* Add devices */
- ks8695_add_device_wan(); /* eth0 = WAN */
- ks8695_add_device_lan(); /* eth1 = LAN */
-}
-
-MACHINE_START(KS8695, "KS8695 Centaur Development Board")
- /* Maintainer: Micrel Semiconductor Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = micrel_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-og.c b/arch/arm/mach-ks8695/board-og.c
deleted file mode 100644
index 12ffe9227f9c..000000000000
--- a/arch/arm/mach-ks8695/board-og.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * board-og.c -- support for the OpenGear KS8695 based boards.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include "devices.h"
-#include <mach/regs-gpio.h>
-#include <mach/gpio-ks8695.h>
-#include "generic.h"
-
-static int og_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (machine_is_im4004() && (slot == 8))
- return KS8695_IRQ_EXTERN1;
- return KS8695_IRQ_EXTERN0;
-}
-
-static struct ks8695_pci_cfg __initdata og_pci = {
- .mode = KS8695_MODE_PCI,
- .map_irq = og_pci_map_irq,
-};
-
-static void __init og_register_pci(void)
-{
- /* Initialize the GPIO lines for interrupt mode */
- ks8695_gpio_interrupt(KS8695_GPIO_0, IRQ_TYPE_LEVEL_LOW);
-
- /* Cardbus Slot */
- if (machine_is_im4004())
- ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_LOW);
-
- if (IS_ENABLED(CONFIG_PCI))
- ks8695_init_pci(&og_pci);
-}
-
-/*
- * The PCI bus reset is driven by a dedicated GPIO line. Toggle it here
- * and bring the PCI bus out of reset.
- */
-static void __init og_pci_bus_reset(void)
-{
- unsigned int rstline = 1;
-
- /* Some boards use a different GPIO as the PCI reset line */
- if (machine_is_im4004())
- rstline = 2;
- else if (machine_is_im42xx())
- rstline = 0;
-
- gpio_request(rstline, "PCI reset");
- gpio_direction_output(rstline, 0);
-
- /* Drive a reset on the PCI reset line */
- gpio_set_value(rstline, 1);
- gpio_set_value(rstline, 0);
- mdelay(100);
- gpio_set_value(rstline, 1);
- mdelay(100);
-}
-
-/*
- * Direct connect serial ports (non-PCI that is).
- */
-#define S8250_PHYS 0x03800000
-#define S8250_VIRT 0xf4000000
-#define S8250_SIZE 0x00100000
-
-static struct map_desc og_io_desc[] __initdata = {
- {
- .virtual = S8250_VIRT,
- .pfn = __phys_to_pfn(S8250_PHYS),
- .length = S8250_SIZE,
- .type = MT_DEVICE,
- }
-};
-
-static struct resource og_uart_resources[] = {
- {
- .start = S8250_VIRT,
- .end = S8250_VIRT + S8250_SIZE,
- .flags = IORESOURCE_MEM
- },
-};
-
-static struct plat_serial8250_port og_uart_data[] = {
- {
- .mapbase = S8250_VIRT,
- .membase = (char *) S8250_VIRT,
- .irq = 3,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 115200 * 16,
- },
- { },
-};
-
-static struct platform_device og_uart = {
- .name = "serial8250",
- .id = 0,
- .dev.platform_data = og_uart_data,
- .num_resources = 1,
- .resource = og_uart_resources
-};
-
-static struct platform_device *og_devices[] __initdata = {
- &og_uart
-};
-
-static void __init og_init(void)
-{
- ks8695_register_gpios();
-
- if (machine_is_cm4002()) {
- ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_HIGH);
- iotable_init(og_io_desc, ARRAY_SIZE(og_io_desc));
- platform_add_devices(og_devices, ARRAY_SIZE(og_devices));
- } else {
- og_pci_bus_reset();
- og_register_pci();
- }
-
- ks8695_add_device_lan();
- ks8695_add_device_wan();
-}
-
-#ifdef CONFIG_MACH_CM4002
-MACHINE_START(CM4002, "OpenGear/CM4002")
- /* OpenGear Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = og_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_CM4008
-MACHINE_START(CM4008, "OpenGear/CM4008")
- /* OpenGear Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = og_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_CM41xx
-MACHINE_START(CM41XX, "OpenGear/CM41xx")
- /* OpenGear Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = og_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_IM4004
-MACHINE_START(IM4004, "OpenGear/IM4004")
- /* OpenGear Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = og_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_IM42xx
-MACHINE_START(IM42XX, "OpenGear/IM42xx")
- /* OpenGear Inc. */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = og_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-ks8695/board-sg.c b/arch/arm/mach-ks8695/board-sg.c
deleted file mode 100644
index d5ec85a56375..000000000000
--- a/arch/arm/mach-ks8695/board-sg.c
+++ /dev/null
@@ -1,118 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * board-sg.c -- support for the SnapGear KS8695 based boards
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/partitions.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include "devices.h"
-#include "generic.h"
-
-/*
- * The SG310 machine type is fitted with a conventional 8MB Strataflash
- * device. Define its partitioning.
- */
-#define FL_BASE 0x02000000
-#define FL_SIZE SZ_8M
-
-static struct mtd_partition sg_mtd_partitions[] = {
- [0] = {
- .name = "SnapGear Boot Loader",
- .size = SZ_128K,
- },
- [1] = {
- .name = "SnapGear non-volatile configuration",
- .size = SZ_512K,
- .offset = SZ_256K,
- },
- [2] = {
- .name = "SnapGear image",
- .offset = SZ_512K + SZ_256K,
- },
- [3] = {
- .name = "SnapGear StrataFlash",
- },
- [4] = {
- .name = "SnapGear Boot Tags",
- .size = SZ_128K,
- .offset = SZ_128K,
- },
-};
-
-static struct physmap_flash_data sg_mtd_pdata = {
- .width = 1,
- .nr_parts = ARRAY_SIZE(sg_mtd_partitions),
- .parts = sg_mtd_partitions,
-};
-
-
-static struct resource sg_mtd_resource[] = {
- [0] = {
- .start = FL_BASE,
- .end = FL_BASE + FL_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device sg_mtd_device = {
- .name = "physmap-flash",
- .id = 0,
- .num_resources = ARRAY_SIZE(sg_mtd_resource),
- .resource = sg_mtd_resource,
- .dev = {
- .platform_data = &sg_mtd_pdata,
- },
-};
-
-static void __init sg_init(void)
-{
- ks8695_add_device_lan();
- ks8695_add_device_wan();
-
- if (machine_is_sg310())
- platform_device_register(&sg_mtd_device);
-}
-
-#ifdef CONFIG_MACH_LITE300
-MACHINE_START(LITE300, "SecureComputing/SG300")
- /* SnapGear */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = sg_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_SG310
-MACHINE_START(SG310, "McAfee/SG310")
- /* SnapGear */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = sg_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_SE4200
-MACHINE_START(SE4200, "SecureComputing/SE4200")
- /* SnapGear */
- .atag_offset = 0x100,
- .map_io = ks8695_map_io,
- .init_irq = ks8695_init_irq,
- .init_machine = sg_init,
- .init_time = ks8695_timer_init,
- .restart = ks8695_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-ks8695/cpu.c b/arch/arm/mach-ks8695/cpu.c
deleted file mode 100644
index aa6bb0c93aa8..000000000000
--- a/arch/arm/mach-ks8695/cpu.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ks8695/cpu.c
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 CPU support
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "regs-sys.h"
-#include <mach/regs-misc.h>
-
-
-static struct map_desc ks8695_io_desc[] __initdata = {
- {
- .virtual = (unsigned long)KS8695_IO_VA,
- .pfn = __phys_to_pfn(KS8695_IO_PA),
- .length = KS8695_IO_SIZE,
- .type = MT_DEVICE,
- }
-};
-
-static void __init ks8695_processor_info(void)
-{
- unsigned long id, rev;
-
- id = __raw_readl(KS8695_MISC_VA + KS8695_DID);
- rev = __raw_readl(KS8695_MISC_VA + KS8695_RID);
-
- printk("KS8695 ID=%04lx SubID=%02lx Revision=%02lx\n", (id & DID_ID), (rev & RID_SUBID), (rev & RID_REVISION));
-}
-
-static unsigned int sysclk[8] = { 125000000, 100000000, 62500000, 50000000, 41700000, 33300000, 31300000, 25000000 };
-static unsigned int cpuclk[8] = { 166000000, 166000000, 83000000, 83000000, 55300000, 55300000, 41500000, 41500000 };
-
-static void __init ks8695_clock_info(void)
-{
- unsigned int scdc = __raw_readl(KS8695_SYS_VA + KS8695_CLKCON) & CLKCON_SCDC;
-
- printk("Clocks: System %u MHz, CPU %u MHz\n",
- sysclk[scdc] / 1000000, cpuclk[scdc] / 1000000);
-}
-
-void __init ks8695_map_io(void)
-{
- iotable_init(ks8695_io_desc, ARRAY_SIZE(ks8695_io_desc));
-
- ks8695_processor_info();
- ks8695_clock_info();
-}
diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
deleted file mode 100644
index 61cf20beb45f..000000000000
--- a/arch/arm/mach-ks8695/devices.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * arch/arm/mach-ks8695/devices.c
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * 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.
- *
- * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include "regs-wan.h"
-#include "regs-lan.h"
-#include "regs-hpna.h"
-#include <mach/regs-switch.h>
-#include <mach/regs-misc.h>
-
-
-/* --------------------------------------------------------------------
- * Ethernet
- * -------------------------------------------------------------------- */
-
-static u64 eth_dmamask = 0xffffffffUL;
-
-static struct resource ks8695_wan_resources[] = {
- [0] = {
- .start = KS8695_WAN_PA,
- .end = KS8695_WAN_PA + 0x00ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .name = "WAN RX",
- .start = KS8695_IRQ_WAN_RX_STATUS,
- .end = KS8695_IRQ_WAN_RX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .name = "WAN TX",
- .start = KS8695_IRQ_WAN_TX_STATUS,
- .end = KS8695_IRQ_WAN_TX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .name = "WAN Link",
- .start = KS8695_IRQ_WAN_LINK,
- .end = KS8695_IRQ_WAN_LINK,
- .flags = IORESOURCE_IRQ,
- },
- [4] = {
- .name = "WAN PHY",
- .start = KS8695_MISC_PA,
- .end = KS8695_MISC_PA + 0x1f,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device ks8695_wan_device = {
- .name = "ks8695_ether",
- .id = 0,
- .dev = {
- .dma_mask = &eth_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
- .resource = ks8695_wan_resources,
- .num_resources = ARRAY_SIZE(ks8695_wan_resources),
-};
-
-
-static struct resource ks8695_lan_resources[] = {
- [0] = {
- .start = KS8695_LAN_PA,
- .end = KS8695_LAN_PA + 0x00ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .name = "LAN RX",
- .start = KS8695_IRQ_LAN_RX_STATUS,
- .end = KS8695_IRQ_LAN_RX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .name = "LAN TX",
- .start = KS8695_IRQ_LAN_TX_STATUS,
- .end = KS8695_IRQ_LAN_TX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .name = "LAN SWITCH",
- .start = KS8695_SWITCH_PA,
- .end = KS8695_SWITCH_PA + 0x4f,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device ks8695_lan_device = {
- .name = "ks8695_ether",
- .id = 1,
- .dev = {
- .dma_mask = &eth_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
- .resource = ks8695_lan_resources,
- .num_resources = ARRAY_SIZE(ks8695_lan_resources),
-};
-
-
-static struct resource ks8695_hpna_resources[] = {
- [0] = {
- .start = KS8695_HPNA_PA,
- .end = KS8695_HPNA_PA + 0x00ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .name = "HPNA RX",
- .start = KS8695_IRQ_HPNA_RX_STATUS,
- .end = KS8695_IRQ_HPNA_RX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .name = "HPNA TX",
- .start = KS8695_IRQ_HPNA_TX_STATUS,
- .end = KS8695_IRQ_HPNA_TX_STATUS,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device ks8695_hpna_device = {
- .name = "ks8695_ether",
- .id = 2,
- .dev = {
- .dma_mask = &eth_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
- .resource = ks8695_hpna_resources,
- .num_resources = ARRAY_SIZE(ks8695_hpna_resources),
-};
-
-void __init ks8695_add_device_wan(void)
-{
- platform_device_register(&ks8695_wan_device);
-}
-
-void __init ks8695_add_device_lan(void)
-{
- platform_device_register(&ks8695_lan_device);
-}
-
-void __init ks8696_add_device_hpna(void)
-{
- platform_device_register(&ks8695_hpna_device);
-}
-
-
-/* --------------------------------------------------------------------
- * Watchdog
- * -------------------------------------------------------------------- */
-
-static struct platform_device ks8695_wdt_device = {
- .name = "ks8695_wdt",
- .id = -1,
- .num_resources = 0,
-};
-
-static void __init ks8695_add_device_watchdog(void)
-{
- platform_device_register(&ks8695_wdt_device);
-}
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init ks8695_add_standard_devices(void)
-{
- ks8695_add_device_watchdog();
- return 0;
-}
-
-arch_initcall(ks8695_add_standard_devices);
diff --git a/arch/arm/mach-ks8695/devices.h b/arch/arm/mach-ks8695/devices.h
deleted file mode 100644
index cc23ee3820ea..000000000000
--- a/arch/arm/mach-ks8695/devices.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-ks8695/include/mach/devices.h
- *
- * Copyright (C) 2006 Andrew Victor
- */
-
-#ifndef __ASM_ARCH_DEVICES_H
-#define __ASM_ARCH_DEVICES_H
-
-#include <linux/pci.h>
-
- /* Ethernet */
-extern void __init ks8695_add_device_wan(void);
-extern void __init ks8695_add_device_lan(void);
-extern void __init ks8695_add_device_hpna(void);
-
- /* PCI */
-#define KS8695_MODE_PCI 0
-#define KS8695_MODE_MINIPCI 1
-#define KS8695_MODE_CARDBUS 2
-
-struct ks8695_pci_cfg {
- short mode;
- int (*map_irq)(const struct pci_dev *, u8, u8);
-};
-extern __init void ks8695_init_pci(struct ks8695_pci_cfg *);
-
-#endif
diff --git a/arch/arm/mach-ks8695/generic.h b/arch/arm/mach-ks8695/generic.h
deleted file mode 100644
index 9e9cbdd436a9..000000000000
--- a/arch/arm/mach-ks8695/generic.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-ks8695/generic.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
-*/
-
-extern __init void ks8695_map_io(void);
-extern __init void ks8695_init_irq(void);
-extern void ks8695_restart(enum reboot_mode, const char *);
-extern void ks8695_timer_init(void);
diff --git a/arch/arm/mach-ks8695/include/mach/entry-macro.S b/arch/arm/mach-ks8695/include/mach/entry-macro.S
deleted file mode 100644
index 7ff812cb010b..000000000000
--- a/arch/arm/mach-ks8695/include/mach/entry-macro.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/entry-macro.S
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * Low-level IRQ helper macros for KS8695
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-*/
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =KS8695_IRQ_VA @ Base address of interrupt controller
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, [\base, #KS8695_INTMS] @ Mask Status register
-
- teq \irqstat, #0
- beq 1001f
-
- mov \irqnr, #0
-
- tst \irqstat, #0xff
- moveq \irqstat, \irqstat, lsr #8
- addeq \irqnr, \irqnr, #8
- tsteq \irqstat, #0xff
- moveq \irqstat, \irqstat, lsr #8
- addeq \irqnr, \irqnr, #8
- tsteq \irqstat, #0xff
- moveq \irqstat, \irqstat, lsr #8
- addeq \irqnr, \irqnr, #8
- tst \irqstat, #0x0f
- moveq \irqstat, \irqstat, lsr #4
- addeq \irqnr, \irqnr, #4
- tst \irqstat, #0x03
- moveq \irqstat, \irqstat, lsr #2
- addeq \irqnr, \irqnr, #2
- tst \irqstat, #0x01
- addseq \irqnr, \irqnr, #1
-1001:
- .endm
diff --git a/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
deleted file mode 100644
index 600115f48fb3..000000000000
--- a/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2006 Andrew Victor
- */
-
-#ifndef __MACH_KS8659_GPIO_H
-#define __MACH_KS8659_GPIO_H
-
-#include <linux/kernel.h>
-
-#define KS8695_GPIO_0 0
-#define KS8695_GPIO_1 1
-#define KS8695_GPIO_2 2
-#define KS8695_GPIO_3 3
-#define KS8695_GPIO_4 4
-#define KS8695_GPIO_5 5
-#define KS8695_GPIO_6 6
-#define KS8695_GPIO_7 7
-#define KS8695_GPIO_8 8
-#define KS8695_GPIO_9 9
-#define KS8695_GPIO_10 10
-#define KS8695_GPIO_11 11
-#define KS8695_GPIO_12 12
-#define KS8695_GPIO_13 13
-#define KS8695_GPIO_14 14
-#define KS8695_GPIO_15 15
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
-
-/* Register the GPIOs */
-extern void ks8695_register_gpios(void);
-
-#endif /* __MACH_KS8659_GPIO_H */
diff --git a/arch/arm/mach-ks8695/include/mach/hardware.h b/arch/arm/mach-ks8695/include/mach/hardware.h
deleted file mode 100644
index 0fb889be8112..000000000000
--- a/arch/arm/mach-ks8695/include/mach/hardware.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-ks8695/include/mach/hardware.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - Memory Map definitions
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <linux/sizes.h>
-
-/*
- * Clocks are derived from MCLK, which is 25MHz
- */
-#define KS8695_CLOCK_RATE 25000000
-
-/*
- * Physical RAM address.
- */
-#define KS8695_SDRAM_PA 0x00000000
-
-
-/*
- * We map an entire MiB with the System Configuration Registers in even
- * though only 64KiB is needed. This makes it easier for use with the
- * head debug code as the initial MMU setup only deals in L1 sections.
- */
-#define KS8695_IO_PA 0x03F00000
-#define KS8695_IO_VA IOMEM(0xF0000000)
-#define KS8695_IO_SIZE SZ_1M
-
-#define KS8695_PCIMEM_PA 0x60000000
-#define KS8695_PCIMEM_SIZE SZ_512M
-
-#define KS8695_PCIIO_PA 0x80000000
-#define KS8695_PCIIO_SIZE SZ_64K
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/irqs.h b/arch/arm/mach-ks8695/include/mach/irqs.h
deleted file mode 100644
index 0cbb30672427..000000000000
--- a/arch/arm/mach-ks8695/include/mach/irqs.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-ks8695/include/mach/irqs.h
- *
- * Copyright (C) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-
-#define NR_IRQS 32
-
-/*
- * IRQ definitions
- */
-#define KS8695_IRQ_COMM_RX 0
-#define KS8695_IRQ_COMM_TX 1
-#define KS8695_IRQ_EXTERN0 2
-#define KS8695_IRQ_EXTERN1 3
-#define KS8695_IRQ_EXTERN2 4
-#define KS8695_IRQ_EXTERN3 5
-#define KS8695_IRQ_TIMER0 6
-#define KS8695_IRQ_TIMER1 7
-#define KS8695_IRQ_UART_TX 8
-#define KS8695_IRQ_UART_RX 9
-#define KS8695_IRQ_UART_LINE_STATUS 10
-#define KS8695_IRQ_UART_MODEM_STATUS 11
-#define KS8695_IRQ_LAN_RX_STOP 12
-#define KS8695_IRQ_LAN_TX_STOP 13
-#define KS8695_IRQ_LAN_RX_BUF 14
-#define KS8695_IRQ_LAN_TX_BUF 15
-#define KS8695_IRQ_LAN_RX_STATUS 16
-#define KS8695_IRQ_LAN_TX_STATUS 17
-#define KS8695_IRQ_HPNA_RX_STOP 18
-#define KS8695_IRQ_HPNA_TX_STOP 19
-#define KS8695_IRQ_HPNA_RX_BUF 20
-#define KS8695_IRQ_HPNA_TX_BUF 21
-#define KS8695_IRQ_HPNA_RX_STATUS 22
-#define KS8695_IRQ_HPNA_TX_STATUS 23
-#define KS8695_IRQ_BUS_ERROR 24
-#define KS8695_IRQ_WAN_RX_STOP 25
-#define KS8695_IRQ_WAN_TX_STOP 26
-#define KS8695_IRQ_WAN_RX_BUF 27
-#define KS8695_IRQ_WAN_TX_BUF 28
-#define KS8695_IRQ_WAN_RX_STATUS 29
-#define KS8695_IRQ_WAN_TX_STATUS 30
-#define KS8695_IRQ_WAN_LINK 31
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
deleted file mode 100644
index ab0d27fa8969..000000000000
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/memory.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 Memory definitions
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <mach/hardware.h>
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_PCI
-
-/* PCI mappings */
-#define __virt_to_bus(x) ((x) - PAGE_OFFSET + KS8695_PCIMEM_PA)
-#define __bus_to_virt(x) ((x) - KS8695_PCIMEM_PA + PAGE_OFFSET)
-
-/* Platform-bus mapping */
-extern struct bus_type platform_bus_type;
-#define is_lbus_device(dev) (dev && dev->bus == &platform_bus_type)
-#define __arch_dma_to_virt(dev, x) ({ (void *) (is_lbus_device(dev) ? \
- __phys_to_virt(x) : __bus_to_virt(x)); })
-#define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \
- (dma_addr_t)__virt_to_phys((unsigned long)x) \
- : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_pfn_to_dma(dev, pfn) \
- ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
- if (!is_lbus_device(dev)) \
- __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
- __dma; })
-
-#define __arch_dma_to_pfn(dev, x) \
- ({ dma_addr_t __dma = x; \
- if (!is_lbus_device(dev)) \
- __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \
- __phys_to_pfn(__dma); \
- })
-
-#endif
-
-#endif
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/regs-gpio.h b/arch/arm/mach-ks8695/include/mach/regs-gpio.h
deleted file mode 100644
index 90614a7d0548..000000000000
--- a/arch/arm/mach-ks8695/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-gpio.h
- *
- * Copyright (C) 2007 Andrew Victor
- *
- * KS8695 - GPIO control registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_GPIO_H
-#define KS8695_GPIO_H
-
-#define KS8695_GPIO_OFFSET (0xF0000 + 0xE600)
-#define KS8695_GPIO_VA (KS8695_IO_VA + KS8695_GPIO_OFFSET)
-#define KS8695_GPIO_PA (KS8695_IO_PA + KS8695_GPIO_OFFSET)
-
-
-#define KS8695_IOPM (0x00) /* I/O Port Mode Register */
-#define KS8695_IOPC (0x04) /* I/O Port Control Register */
-#define KS8695_IOPD (0x08) /* I/O Port Data Register */
-
-
-/* Port Mode Register */
-#define IOPM(x) (1 << (x)) /* Mode for GPIO Pin x */
-
-/* Port Control Register */
-#define IOPC_IOTIM1EN (1 << 17) /* GPIO Pin for Timer1 Enable */
-#define IOPC_IOTIM0EN (1 << 16) /* GPIO Pin for Timer0 Enable */
-#define IOPC_IOEINT3EN (1 << 15) /* GPIO Pin for External/Soft Interrupt 3 Enable */
-#define IOPC_IOEINT3TM (7 << 12) /* GPIO Pin for External/Soft Interrupt 3 Trigger Mode */
-#define IOPC_IOEINT3_MODE(x) ((x) << 12)
-#define IOPC_IOEINT2EN (1 << 11) /* GPIO Pin for External/Soft Interrupt 2 Enable */
-#define IOPC_IOEINT2TM (7 << 8) /* GPIO Pin for External/Soft Interrupt 2 Trigger Mode */
-#define IOPC_IOEINT2_MODE(x) ((x) << 8)
-#define IOPC_IOEINT1EN (1 << 7) /* GPIO Pin for External/Soft Interrupt 1 Enable */
-#define IOPC_IOEINT1TM (7 << 4) /* GPIO Pin for External/Soft Interrupt 1 Trigger Mode */
-#define IOPC_IOEINT1_MODE(x) ((x) << 4)
-#define IOPC_IOEINT0EN (1 << 3) /* GPIO Pin for External/Soft Interrupt 0 Enable */
-#define IOPC_IOEINT0TM (7 << 0) /* GPIO Pin for External/Soft Interrupt 0 Trigger Mode */
-#define IOPC_IOEINT0_MODE(x) ((x) << 0)
-
- /* Trigger Modes */
-#define IOPC_TM_LOW (0) /* Level Detection (Active Low) */
-#define IOPC_TM_HIGH (1) /* Level Detection (Active High) */
-#define IOPC_TM_RISING (2) /* Rising Edge Detection */
-#define IOPC_TM_FALLING (4) /* Falling Edge Detection */
-#define IOPC_TM_EDGE (6) /* Both Edge Detection */
-
-/* Port Data Register */
-#define IOPD(x) (1 << (x)) /* Signal Level of GPIO Pin x */
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/regs-irq.h b/arch/arm/mach-ks8695/include/mach/regs-irq.h
deleted file mode 100644
index 352b7e8704d5..000000000000
--- a/arch/arm/mach-ks8695/include/mach/regs-irq.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-irq.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - IRQ registers and bit definitions
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_IRQ_H
-#define KS8695_IRQ_H
-
-#define KS8695_IRQ_OFFSET (0xF0000 + 0xE200)
-#define KS8695_IRQ_VA (KS8695_IO_VA + KS8695_IRQ_OFFSET)
-#define KS8695_IRQ_PA (KS8695_IO_PA + KS8695_IRQ_OFFSET)
-
-
-/*
- * Interrupt Controller registers
- */
-#define KS8695_INTMC (0x00) /* Mode Control Register */
-#define KS8695_INTEN (0x04) /* Interrupt Enable Register */
-#define KS8695_INTST (0x08) /* Interrupt Status Register */
-#define KS8695_INTPW (0x0c) /* Interrupt Priority (WAN MAC) */
-#define KS8695_INTPH (0x10) /* Interrupt Priority (HPNA) [KS8695 only] */
-#define KS8695_INTPL (0x14) /* Interrupt Priority (LAN MAC) */
-#define KS8695_INTPT (0x18) /* Interrupt Priority (Timer) */
-#define KS8695_INTPU (0x1c) /* Interrupt Priority (UART) */
-#define KS8695_INTPE (0x20) /* Interrupt Priority (External Interrupt) */
-#define KS8695_INTPC (0x24) /* Interrupt Priority (Communications Channel) */
-#define KS8695_INTPBE (0x28) /* Interrupt Priority (Bus Error Response) */
-#define KS8695_INTMS (0x2c) /* Interrupt Mask Status Register */
-#define KS8695_INTHPF (0x30) /* Interrupt Pending Highest Priority (FIQ) */
-#define KS8695_INTHPI (0x34) /* Interrupt Pending Highest Priority (IRQ) */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/regs-misc.h b/arch/arm/mach-ks8695/include/mach/regs-misc.h
deleted file mode 100644
index 2740c52494a0..000000000000
--- a/arch/arm/mach-ks8695/include/mach/regs-misc.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-misc.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - Miscellaneous Registers
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_MISC_H
-#define KS8695_MISC_H
-
-#define KS8695_MISC_OFFSET (0xF0000 + 0xEA00)
-#define KS8695_MISC_VA (KS8695_IO_VA + KS8695_MISC_OFFSET)
-#define KS8695_MISC_PA (KS8695_IO_PA + KS8695_MISC_OFFSET)
-
-
-/*
- * Miscellaneous registers
- */
-#define KS8695_DID (0x00) /* Device ID */
-#define KS8695_RID (0x04) /* Revision ID */
-#define KS8695_HMC (0x08) /* HPNA Miscellaneous Control [KS8695 only] */
-#define KS8695_WMC (0x0c) /* WAN Miscellaneous Control */
-#define KS8695_WPPM (0x10) /* WAN PHY Power Management */
-#define KS8695_PPS (0x1c) /* PHY PowerSave */
-
-/* Device ID Register */
-#define DID_ID (0xffff << 0) /* Device ID */
-
-/* Revision ID Register */
-#define RID_SUBID (0xf << 4) /* Sub-Device ID */
-#define RID_REVISION (0xf << 0) /* Revision ID */
-
-/* HPNA Miscellaneous Control Register */
-#define HMC_HSS (1 << 1) /* Speed */
-#define HMC_HDS (1 << 0) /* Duplex */
-
-/* WAN Miscellaneous Control Register */
-#define WMC_WANC (1 << 30) /* Auto-negotiation complete */
-#define WMC_WANR (1 << 29) /* Auto-negotiation restart */
-#define WMC_WANAP (1 << 28) /* Advertise Pause */
-#define WMC_WANA100F (1 << 27) /* Advertise 100 FDX */
-#define WMC_WANA100H (1 << 26) /* Advertise 100 HDX */
-#define WMC_WANA10F (1 << 25) /* Advertise 10 FDX */
-#define WMC_WANA10H (1 << 24) /* Advertise 10 HDX */
-#define WMC_WLS (1 << 23) /* Link status */
-#define WMC_WDS (1 << 22) /* Duplex status */
-#define WMC_WSS (1 << 21) /* Speed status */
-#define WMC_WLPP (1 << 20) /* Link Partner Pause */
-#define WMC_WLP100F (1 << 19) /* Link Partner 100 FDX */
-#define WMC_WLP100H (1 << 18) /* Link Partner 100 HDX */
-#define WMC_WLP10F (1 << 17) /* Link Partner 10 FDX */
-#define WMC_WLP10H (1 << 16) /* Link Partner 10 HDX */
-#define WMC_WAND (1 << 15) /* Auto-negotiation disable */
-#define WMC_WANF100 (1 << 14) /* Force 100 */
-#define WMC_WANFF (1 << 13) /* Force FDX */
-#define WMC_WLED1S (7 << 4) /* LED1 Select */
-#define WLED1S_SPEED (0 << 4)
-#define WLED1S_LINK (1 << 4)
-#define WLED1S_DUPLEX (2 << 4)
-#define WLED1S_COLLISION (3 << 4)
-#define WLED1S_ACTIVITY (4 << 4)
-#define WLED1S_FDX_COLLISION (5 << 4)
-#define WLED1S_LINK_ACTIVITY (6 << 4)
-#define WMC_WLED0S (7 << 0) /* LED0 Select */
-#define WLED0S_SPEED (0 << 0)
-#define WLED0S_LINK (1 << 0)
-#define WLED0S_DUPLEX (2 << 0)
-#define WLED0S_COLLISION (3 << 0)
-#define WLED0S_ACTIVITY (4 << 0)
-#define WLED0S_FDX_COLLISION (5 << 0)
-#define WLED0S_LINK_ACTIVITY (6 << 0)
-
-/* WAN PHY Power Management Register */
-#define WPPM_WLPBK (1 << 14) /* Local Loopback */
-#define WPPM_WRLPKB (1 << 13) /* Remove Loopback */
-#define WPPM_WPI (1 << 12) /* PHY isolate */
-#define WPPM_WFL (1 << 10) /* Force link */
-#define WPPM_MDIXS (1 << 9) /* MDIX Status */
-#define WPPM_FEF (1 << 8) /* Far End Fault */
-#define WPPM_AMDIXP (1 << 7) /* Auto MDIX Parameter */
-#define WPPM_TXDIS (1 << 6) /* Disable transmitter */
-#define WPPM_DFEF (1 << 5) /* Disable Far End Fault */
-#define WPPM_PD (1 << 4) /* Power Down */
-#define WPPM_DMDX (1 << 3) /* Disable Auto MDI/MDIX */
-#define WPPM_FMDX (1 << 2) /* Force MDIX */
-#define WPPM_LPBK (1 << 1) /* MAX Loopback */
-
-/* PHY Power Save Register */
-#define PPS_PPSM (1 << 0) /* PHY Power Save Mode */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/regs-switch.h b/arch/arm/mach-ks8695/include/mach/regs-switch.h
deleted file mode 100644
index 97e8acb1cf6c..000000000000
--- a/arch/arm/mach-ks8695/include/mach/regs-switch.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-switch.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - Switch Registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_SWITCH_H
-#define KS8695_SWITCH_H
-
-#define KS8695_SWITCH_OFFSET (0xF0000 + 0xe800)
-#define KS8695_SWITCH_VA (KS8695_IO_VA + KS8695_SWITCH_OFFSET)
-#define KS8695_SWITCH_PA (KS8695_IO_PA + KS8695_SWITCH_OFFSET)
-
-
-/*
- * Switch registers
- */
-#define KS8695_SEC0 (0x00) /* Switch Engine Control 0 */
-#define KS8695_SEC1 (0x04) /* Switch Engine Control 1 */
-#define KS8695_SEC2 (0x08) /* Switch Engine Control 2 */
-
-#define KS8695_SEPXCZ(x,z) (0x0c + (((x)-1)*3 + ((z)-1))*4) /* Port Configuration Registers */
-
-#define KS8695_SEP12AN (0x48) /* Port 1 & 2 Auto-Negotiation */
-#define KS8695_SEP34AN (0x4c) /* Port 3 & 4 Auto-Negotiation */
-#define KS8695_SEIAC (0x50) /* Indirect Access Control */
-#define KS8695_SEIADH2 (0x54) /* Indirect Access Data High 2 */
-#define KS8695_SEIADH1 (0x58) /* Indirect Access Data High 1 */
-#define KS8695_SEIADL (0x5c) /* Indirect Access Data Low */
-#define KS8695_SEAFC (0x60) /* Advance Feature Control */
-#define KS8695_SEDSCPH (0x64) /* TOS Priority High */
-#define KS8695_SEDSCPL (0x68) /* TOS Priority Low */
-#define KS8695_SEMAH (0x6c) /* Switch Engine MAC Address High */
-#define KS8695_SEMAL (0x70) /* Switch Engine MAC Address Low */
-#define KS8695_LPPM12 (0x74) /* Port 1 & 2 PHY Power Management */
-#define KS8695_LPPM34 (0x78) /* Port 3 & 4 PHY Power Management */
-
-
-/* Switch Engine Control 0 */
-#define SEC0_LLED1S (7 << 25) /* LED1 Select */
-#define LLED1S_SPEED (0 << 25)
-#define LLED1S_LINK (1 << 25)
-#define LLED1S_DUPLEX (2 << 25)
-#define LLED1S_COLLISION (3 << 25)
-#define LLED1S_ACTIVITY (4 << 25)
-#define LLED1S_FDX_COLLISION (5 << 25)
-#define LLED1S_LINK_ACTIVITY (6 << 25)
-#define SEC0_LLED0S (7 << 22) /* LED0 Select */
-#define LLED0S_SPEED (0 << 22)
-#define LLED0S_LINK (1 << 22)
-#define LLED0S_DUPLEX (2 << 22)
-#define LLED0S_COLLISION (3 << 22)
-#define LLED0S_ACTIVITY (4 << 22)
-#define LLED0S_FDX_COLLISION (5 << 22)
-#define LLED0S_LINK_ACTIVITY (6 << 22)
-#define SEC0_ENABLE (1 << 0) /* Enable Switch */
-
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/regs-uart.h b/arch/arm/mach-ks8695/include/mach/regs-uart.h
deleted file mode 100644
index 941a542c5f23..000000000000
--- a/arch/arm/mach-ks8695/include/mach/regs-uart.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-ks8695/include/mach/regs-uart.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - UART register and bit definitions.
- */
-
-#ifndef KS8695_UART_H
-#define KS8695_UART_H
-
-#define KS8695_UART_OFFSET (0xF0000 + 0xE000)
-#define KS8695_UART_VA (KS8695_IO_VA + KS8695_UART_OFFSET)
-#define KS8695_UART_PA (KS8695_IO_PA + KS8695_UART_OFFSET)
-
-
-/*
- * UART registers
- */
-#define KS8695_URRB (0x00) /* Receive Buffer Register */
-#define KS8695_URTH (0x04) /* Transmit Holding Register */
-#define KS8695_URFC (0x08) /* FIFO Control Register */
-#define KS8695_URLC (0x0C) /* Line Control Register */
-#define KS8695_URMC (0x10) /* Modem Control Register */
-#define KS8695_URLS (0x14) /* Line Status Register */
-#define KS8695_URMS (0x18) /* Modem Status Register */
-#define KS8695_URBD (0x1C) /* Baud Rate Divisor Register */
-#define KS8695_USR (0x20) /* Status Register */
-
-
-/* FIFO Control Register */
-#define URFC_URFRT (3 << 6) /* Receive FIFO Trigger Level */
-#define URFC_URFRT_1 (0 << 6)
-#define URFC_URFRT_4 (1 << 6)
-#define URFC_URFRT_8 (2 << 6)
-#define URFC_URFRT_14 (3 << 6)
-#define URFC_URTFR (1 << 2) /* Transmit FIFO Reset */
-#define URFC_URRFR (1 << 1) /* Receive FIFO Reset */
-#define URFC_URFE (1 << 0) /* FIFO Enable */
-
-/* Line Control Register */
-#define URLC_URSBC (1 << 6) /* Set Break Condition */
-#define URLC_PARITY (7 << 3) /* Parity */
-#define URPE_NONE (0 << 3)
-#define URPE_ODD (1 << 3)
-#define URPE_EVEN (3 << 3)
-#define URPE_MARK (5 << 3)
-#define URPE_SPACE (7 << 3)
-#define URLC_URSB (1 << 2) /* Stop Bits */
-#define URLC_URCL (3 << 0) /* Character Length */
-#define URCL_5 (0 << 0)
-#define URCL_6 (1 << 0)
-#define URCL_7 (2 << 0)
-#define URCL_8 (3 << 0)
-
-/* Modem Control Register */
-#define URMC_URLB (1 << 4) /* Loop-back mode */
-#define URMC_UROUT2 (1 << 3) /* OUT2 signal */
-#define URMC_UROUT1 (1 << 2) /* OUT1 signal */
-#define URMC_URRTS (1 << 1) /* Request to Send */
-#define URMC_URDTR (1 << 0) /* Data Terminal Ready */
-
-/* Line Status Register */
-#define URLS_URRFE (1 << 7) /* Receive FIFO Error */
-#define URLS_URTE (1 << 6) /* Transmit Empty */
-#define URLS_URTHRE (1 << 5) /* Transmit Holding Register Empty */
-#define URLS_URBI (1 << 4) /* Break Interrupt */
-#define URLS_URFE (1 << 3) /* Framing Error */
-#define URLS_URPE (1 << 2) /* Parity Error */
-#define URLS_URROE (1 << 1) /* Receive Overrun Error */
-#define URLS_URDR (1 << 0) /* Receive Data Ready */
-
-/* Modem Status Register */
-#define URMS_URDCD (1 << 7) /* Data Carrier Detect */
-#define URMS_URRI (1 << 6) /* Ring Indicator */
-#define URMS_URDSR (1 << 5) /* Data Set Ready */
-#define URMS_URCTS (1 << 4) /* Clear to Send */
-#define URMS_URDDCD (1 << 3) /* Delta Data Carrier Detect */
-#define URMS_URTERI (1 << 2) /* Trailing Edge Ring Indicator */
-#define URMS_URDDST (1 << 1) /* Delta Data Set Ready */
-#define URMS_URDCTS (1 << 0) /* Delta Clear to Send */
-
-/* Status Register */
-#define USR_UTI (1 << 0) /* Timeout Indication */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/uncompress.h b/arch/arm/mach-ks8695/include/mach/uncompress.h
deleted file mode 100644
index dc78a29759b5..000000000000
--- a/arch/arm/mach-ks8695/include/mach/uncompress.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-ks8695/include/mach/uncompress.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - Kernel uncompressor
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <linux/io.h>
-#include <mach/regs-uart.h>
-
-static inline void putc(char c)
-{
- while (!(__raw_readl((void __iomem*)KS8695_UART_PA + KS8695_URLS) & URLS_URTHRE))
- barrier();
-
- __raw_writel(c, (void __iomem*)KS8695_UART_PA + KS8695_URTH);
-}
-
-static inline void flush(void)
-{
- while (!(__raw_readl((void __iomem*)KS8695_UART_PA + KS8695_URLS) & URLS_URTE))
- barrier();
-}
-
-#define arch_decomp_setup()
-
-#endif
diff --git a/arch/arm/mach-ks8695/irq.c b/arch/arm/mach-ks8695/irq.c
deleted file mode 100644
index 4b7ec8d9300c..000000000000
--- a/arch/arm/mach-ks8695/irq.c
+++ /dev/null
@@ -1,164 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ks8695/irq.c
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-static void ks8695_irq_mask(struct irq_data *d)
-{
- unsigned long inten;
-
- inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
- inten &= ~(1 << d->irq);
-
- __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
-}
-
-static void ks8695_irq_unmask(struct irq_data *d)
-{
- unsigned long inten;
-
- inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
- inten |= (1 << d->irq);
-
- __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
-}
-
-static void ks8695_irq_ack(struct irq_data *d)
-{
- __raw_writel((1 << d->irq), KS8695_IRQ_VA + KS8695_INTST);
-}
-
-
-static struct irq_chip ks8695_irq_level_chip;
-static struct irq_chip ks8695_irq_edge_chip;
-
-
-static int ks8695_irq_set_type(struct irq_data *d, unsigned int type)
-{
- unsigned long ctrl, mode;
- unsigned short level_triggered = 0;
-
- ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-
- switch (type) {
- case IRQ_TYPE_LEVEL_HIGH:
- mode = IOPC_TM_HIGH;
- level_triggered = 1;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- mode = IOPC_TM_LOW;
- level_triggered = 1;
- break;
- case IRQ_TYPE_EDGE_RISING:
- mode = IOPC_TM_RISING;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- mode = IOPC_TM_FALLING;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- mode = IOPC_TM_EDGE;
- break;
- default:
- return -EINVAL;
- }
-
- switch (d->irq) {
- case KS8695_IRQ_EXTERN0:
- ctrl &= ~IOPC_IOEINT0TM;
- ctrl |= IOPC_IOEINT0_MODE(mode);
- break;
- case KS8695_IRQ_EXTERN1:
- ctrl &= ~IOPC_IOEINT1TM;
- ctrl |= IOPC_IOEINT1_MODE(mode);
- break;
- case KS8695_IRQ_EXTERN2:
- ctrl &= ~IOPC_IOEINT2TM;
- ctrl |= IOPC_IOEINT2_MODE(mode);
- break;
- case KS8695_IRQ_EXTERN3:
- ctrl &= ~IOPC_IOEINT3TM;
- ctrl |= IOPC_IOEINT3_MODE(mode);
- break;
- default:
- return -EINVAL;
- }
-
- if (level_triggered) {
- irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip,
- handle_level_irq);
- }
- else {
- irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip,
- handle_edge_irq);
- }
-
- __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
- return 0;
-}
-
-static struct irq_chip ks8695_irq_level_chip = {
- .irq_ack = ks8695_irq_mask,
- .irq_mask = ks8695_irq_mask,
- .irq_unmask = ks8695_irq_unmask,
- .irq_set_type = ks8695_irq_set_type,
-};
-
-static struct irq_chip ks8695_irq_edge_chip = {
- .irq_ack = ks8695_irq_ack,
- .irq_mask = ks8695_irq_mask,
- .irq_unmask = ks8695_irq_unmask,
- .irq_set_type = ks8695_irq_set_type,
-};
-
-void __init ks8695_init_irq(void)
-{
- unsigned int irq;
-
- /* Disable all interrupts initially */
- __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC);
- __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN);
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq) {
- /* Level-triggered interrupts */
- case KS8695_IRQ_BUS_ERROR:
- case KS8695_IRQ_UART_MODEM_STATUS:
- case KS8695_IRQ_UART_LINE_STATUS:
- case KS8695_IRQ_UART_RX:
- case KS8695_IRQ_COMM_TX:
- case KS8695_IRQ_COMM_RX:
- irq_set_chip_and_handler(irq,
- &ks8695_irq_level_chip,
- handle_level_irq);
- break;
-
- /* Edge-triggered interrupts */
- default:
- /* clear pending bit */
- ks8695_irq_ack(irq_get_irq_data(irq));
- irq_set_chip_and_handler(irq,
- &ks8695_irq_edge_chip,
- handle_edge_irq);
- }
-
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
- }
-}
diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
deleted file mode 100644
index 83f330bf07dd..000000000000
--- a/arch/arm/mach-ks8695/pci.c
+++ /dev/null
@@ -1,247 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ks8695/pci.c
- *
- * Copyright (C) 2003, Micrel Semiconductors
- * Copyright (C) 2006, Greg Ungerer <gerg@snapgear.com>
- * Copyright (C) 2006, Ben Dooks
- * Copyright (C) 2007, Andrew Victor
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/signal.h>
-#include <asm/mach/pci.h>
-#include <mach/hardware.h>
-
-#include "devices.h"
-#include "regs-pci.h"
-
-
-static int pci_dbg;
-
-static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where)
-{
- unsigned long pbca;
-
- pbca = PBCA_ENABLE | (where & ~3);
- pbca |= PCI_SLOT(devfn) << 11 ;
- pbca |= PCI_FUNC(devfn) << 8;
- pbca |= bus_nr << 16;
-
- if (bus_nr == 0) {
- /* use Type-0 transaction */
- __raw_writel(pbca, KS8695_PCI_VA + KS8695_PBCA);
- } else {
- /* use Type-1 transaction */
- __raw_writel(pbca | PBCA_TYPE1, KS8695_PCI_VA + KS8695_PBCA);
- }
-}
-
-static void __iomem *ks8695_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
- int where)
-{
- ks8695_pci_setupconfig(bus->number, devfn, where);
- return KS8695_PCI_VA + KS8695_PBCD;
-}
-
-static void ks8695_local_writeconfig(int where, u32 value)
-{
- ks8695_pci_setupconfig(0, 0, where);
- __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
-}
-
-static struct pci_ops ks8695_pci_ops = {
- .map_bus = ks8695_pci_map_bus,
- .read = pci_generic_config_read32,
- .write = pci_generic_config_write32,
-};
-
-static struct resource pci_mem = {
- .name = "PCI Memory space",
- .start = KS8695_PCIMEM_PA,
- .end = KS8695_PCIMEM_PA + (KS8695_PCIMEM_SIZE - 1),
- .flags = IORESOURCE_MEM,
-};
-
-static struct resource pci_io = {
- .name = "PCI IO space",
- .start = KS8695_PCIIO_PA,
- .end = KS8695_PCIIO_PA + (KS8695_PCIIO_SIZE - 1),
- .flags = IORESOURCE_IO,
-};
-
-static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
-{
- if (nr > 0)
- return 0;
-
- request_resource(&iomem_resource, &pci_mem);
- request_resource(&ioport_resource, &pci_io);
-
- pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
- pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
-
- /* Assign and enable processor bridge */
- ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA);
-
- /* Enable bus-master & Memory Space access */
- ks8695_local_writeconfig(PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-
- /* Set cache-line size & latency. */
- ks8695_local_writeconfig(PCI_CACHE_LINE_SIZE, (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
-
- /* Reserve PCI memory space for PCI-AHB resources */
- if (!request_mem_region(KS8695_PCIMEM_PA, SZ_64M, "PCI-AHB Bridge")) {
- printk(KERN_ERR "Cannot allocate PCI-AHB Bridge memory.\n");
- return -EBUSY;
- }
-
- return 1;
-}
-
-static inline unsigned int size_mask(unsigned long size)
-{
- return (~size) + 1;
-}
-
-static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- unsigned long pc = instruction_pointer(regs);
- unsigned long instr = *(unsigned long *)pc;
- unsigned long cmdstat;
-
- cmdstat = __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS);
-
- printk(KERN_ERR "PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx [%s%s%s%s%s]\n",
- addr, fsr, regs->ARM_pc, regs->ARM_lr,
- cmdstat & (PCI_STATUS_SIG_TARGET_ABORT << 16) ? "GenTarget" : " ",
- cmdstat & (PCI_STATUS_REC_TARGET_ABORT << 16) ? "RecvTarget" : " ",
- cmdstat & (PCI_STATUS_REC_MASTER_ABORT << 16) ? "MasterAbort" : " ",
- cmdstat & (PCI_STATUS_SIG_SYSTEM_ERROR << 16) ? "SysError" : " ",
- cmdstat & (PCI_STATUS_DETECTED_PARITY << 16) ? "Parity" : " "
- );
-
- __raw_writel(cmdstat, KS8695_PCI_VA + KS8695_CRCFCS);
-
- /*
- * If the instruction being executed was a read,
- * make it look like it read all-ones.
- */
- if ((instr & 0x0c100000) == 0x04100000) {
- int reg = (instr >> 12) & 15;
- unsigned long val;
-
- if (instr & 0x00400000)
- val = 255;
- else
- val = -1;
-
- regs->uregs[reg] = val;
- regs->ARM_pc += 4;
- return 0;
- }
-
- if ((instr & 0x0e100090) == 0x00100090) {
- int reg = (instr >> 12) & 15;
-
- regs->uregs[reg] = -1;
- regs->ARM_pc += 4;
- return 0;
- }
-
- return 1;
-}
-
-static void __init ks8695_pci_preinit(void)
-{
- /* make software reset to avoid freeze if PCI bus was messed up */
- __raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS);
-
- /* stage 1 initialization, subid, subdevice = 0x0001 */
- __raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID);
-
- /* stage 2 initialization */
- /* prefetch limits with 16 words, retry enable */
- __raw_writel(0x40000000, KS8695_PCI_VA + KS8695_PBCS);
-
- /* configure memory mapping */
- __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBA);
- __raw_writel(size_mask(KS8695_PCIMEM_SIZE), KS8695_PCI_VA + KS8695_PMBAM);
- __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBAT);
- __raw_writel(0, KS8695_PCI_VA + KS8695_PMBAC);
-
- /* configure IO mapping */
- __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBA);
- __raw_writel(size_mask(KS8695_PCIIO_SIZE), KS8695_PCI_VA + KS8695_PIOBAM);
- __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBAT);
- __raw_writel(0, KS8695_PCI_VA + KS8695_PIOBAC);
-
- /* hook in fault handlers */
- hook_fault_code(8, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
- hook_fault_code(10, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
-}
-
-static void ks8695_show_pciregs(void)
-{
- if (!pci_dbg)
- return;
-
- printk(KERN_INFO "PCI: CRCFID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFID));
- printk(KERN_INFO "PCI: CRCFCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS));
- printk(KERN_INFO "PCI: CRCFRV = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFRV));
- printk(KERN_INFO "PCI: CRCFLT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFLT));
- printk(KERN_INFO "PCI: CRCBMA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCBMA));
- printk(KERN_INFO "PCI: CRCSID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCSID));
- printk(KERN_INFO "PCI: CRCFIT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFIT));
-
- printk(KERN_INFO "PCI: PBM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBM));
- printk(KERN_INFO "PCI: PBCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBCS));
-
- printk(KERN_INFO "PCI: PMBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBA));
- printk(KERN_INFO "PCI: PMBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAC));
- printk(KERN_INFO "PCI: PMBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAM));
- printk(KERN_INFO "PCI: PMBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAT));
-
- printk(KERN_INFO "PCI: PIOBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBA));
- printk(KERN_INFO "PCI: PIOBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAC));
- printk(KERN_INFO "PCI: PIOBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAM));
- printk(KERN_INFO "PCI: PIOBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAT));
-}
-
-
-static struct hw_pci ks8695_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ks8695_pci_ops,
- .preinit = ks8695_pci_preinit,
- .setup = ks8695_pci_setup,
- .postinit = NULL,
- .map_irq = NULL,
-};
-
-void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg)
-{
- if (__raw_readl(KS8695_PCI_VA + KS8695_CRCFRV) & CFRV_GUEST) {
- printk("PCI: KS8695 in guest mode, not initialising\n");
- return;
- }
-
- pcibios_min_io = 0;
- pcibios_min_mem = 0;
-
- printk(KERN_INFO "PCI: Initialising\n");
- ks8695_show_pciregs();
-
- /* set Mode */
- __raw_writel(cfg->mode << 29, KS8695_PCI_VA + KS8695_PBM);
-
- ks8695_pci.map_irq = cfg->map_irq; /* board-specific map_irq method */
-
- pci_common_init(&ks8695_pci);
-}
diff --git a/arch/arm/mach-ks8695/regs-hpna.h b/arch/arm/mach-ks8695/regs-hpna.h
deleted file mode 100644
index 815ce5c2e3b9..000000000000
--- a/arch/arm/mach-ks8695/regs-hpna.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-wan.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - HPNA Registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_HPNA_H
-#define KS8695_HPNA_H
-
-#define KS8695_HPNA_OFFSET (0xF0000 + 0xA000)
-#define KS8695_HPNA_VA (KS8695_IO_VA + KS8695_HPNA_OFFSET)
-#define KS8695_HPNA_PA (KS8695_IO_PA + KS8695_HPNA_OFFSET)
-
-
-/*
- * HPNA registers
- */
-
-#endif
diff --git a/arch/arm/mach-ks8695/regs-lan.h b/arch/arm/mach-ks8695/regs-lan.h
deleted file mode 100644
index 82c5f3791afb..000000000000
--- a/arch/arm/mach-ks8695/regs-lan.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-lan.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - LAN Registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_LAN_H
-#define KS8695_LAN_H
-
-#define KS8695_LAN_OFFSET (0xF0000 + 0x8000)
-#define KS8695_LAN_VA (KS8695_IO_VA + KS8695_LAN_OFFSET)
-#define KS8695_LAN_PA (KS8695_IO_PA + KS8695_LAN_OFFSET)
-
-
-/*
- * LAN registers
- */
-#define KS8695_LMDTXC (0x00) /* DMA Transmit Control */
-#define KS8695_LMDRXC (0x04) /* DMA Receive Control */
-#define KS8695_LMDTSC (0x08) /* DMA Transmit Start Command */
-#define KS8695_LMDRSC (0x0c) /* DMA Receive Start Command */
-#define KS8695_LTDLB (0x10) /* Transmit Descriptor List Base Address */
-#define KS8695_LRDLB (0x14) /* Receive Descriptor List Base Address */
-#define KS8695_LMAL (0x18) /* MAC Station Address Low */
-#define KS8695_LMAH (0x1c) /* MAC Station Address High */
-#define KS8695_LMAAL(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */
-#define KS8695_LMAAH(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */
-
-
-/* DMA Transmit Control Register */
-#define LMDTXC_LMTRST (1 << 31) /* Soft Reset */
-#define LMDTXC_LMTBS (0x3f << 24) /* Transmit Burst Size */
-#define LMDTXC_LMTUCG (1 << 18) /* Transmit UDP Checksum Generate */
-#define LMDTXC_LMTTCG (1 << 17) /* Transmit TCP Checksum Generate */
-#define LMDTXC_LMTICG (1 << 16) /* Transmit IP Checksum Generate */
-#define LMDTXC_LMTFCE (1 << 9) /* Transmit Flow Control Enable */
-#define LMDTXC_LMTLB (1 << 8) /* Loopback mode */
-#define LMDTXC_LMTEP (1 << 2) /* Transmit Enable Padding */
-#define LMDTXC_LMTAC (1 << 1) /* Transmit Add CRC */
-#define LMDTXC_LMTE (1 << 0) /* TX Enable */
-
-/* DMA Receive Control Register */
-#define LMDRXC_LMRBS (0x3f << 24) /* Receive Burst Size */
-#define LMDRXC_LMRUCC (1 << 18) /* Receive UDP Checksum check */
-#define LMDRXC_LMRTCG (1 << 17) /* Receive TCP Checksum check */
-#define LMDRXC_LMRICG (1 << 16) /* Receive IP Checksum check */
-#define LMDRXC_LMRFCE (1 << 9) /* Receive Flow Control Enable */
-#define LMDRXC_LMRB (1 << 6) /* Receive Broadcast */
-#define LMDRXC_LMRM (1 << 5) /* Receive Multicast */
-#define LMDRXC_LMRU (1 << 4) /* Receive Unicast */
-#define LMDRXC_LMRERR (1 << 3) /* Receive Error Frame */
-#define LMDRXC_LMRA (1 << 2) /* Receive All */
-#define LMDRXC_LMRE (1 << 1) /* RX Enable */
-
-/* Additional Station Address High */
-#define LMAAH_E (1 << 31) /* Address Enabled */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/regs-mem.h b/arch/arm/mach-ks8695/regs-mem.h
deleted file mode 100644
index 55806bc68ce3..000000000000
--- a/arch/arm/mach-ks8695/regs-mem.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-mem.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - Memory Controller registers and bit definitions
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_MEM_H
-#define KS8695_MEM_H
-
-#define KS8695_MEM_OFFSET (0xF0000 + 0x4000)
-#define KS8695_MEM_VA (KS8695_IO_VA + KS8695_MEM_OFFSET)
-#define KS8695_MEM_PA (KS8695_IO_PA + KS8695_MEM_OFFSET)
-
-
-/*
- * Memory Controller Registers
- */
-#define KS8695_EXTACON0 (0x00) /* External I/O 0 Access Control */
-#define KS8695_EXTACON1 (0x04) /* External I/O 1 Access Control */
-#define KS8695_EXTACON2 (0x08) /* External I/O 2 Access Control */
-#define KS8695_ROMCON0 (0x10) /* ROM/SRAM/Flash 1 Control Register */
-#define KS8695_ROMCON1 (0x14) /* ROM/SRAM/Flash 2 Control Register */
-#define KS8695_ERGCON (0x20) /* External I/O and ROM/SRAM/Flash General Register */
-#define KS8695_SDCON0 (0x30) /* SDRAM Control Register 0 */
-#define KS8695_SDCON1 (0x34) /* SDRAM Control Register 1 */
-#define KS8695_SDGCON (0x38) /* SDRAM General Control */
-#define KS8695_SDBCON (0x3c) /* SDRAM Buffer Control */
-#define KS8695_REFTIM (0x40) /* SDRAM Refresh Timer */
-
-
-/* External I/O Access Control Registers */
-#define EXTACON_EBNPTR (0x3ff << 22) /* Last Address Pointer */
-#define EXTACON_EBBPTR (0x3ff << 12) /* Base Pointer */
-#define EXTACON_EBTACT (7 << 9) /* Write Enable/Output Enable Active Time */
-#define EXTACON_EBTCOH (7 << 6) /* Chip Select Hold Time */
-#define EXTACON_EBTACS (7 << 3) /* Address Setup Time before ECSN */
-#define EXTACON_EBTCOS (7 << 0) /* Chip Select Time before OEN */
-
-/* ROM/SRAM/Flash Control Register */
-#define ROMCON_RBNPTR (0x3ff << 22) /* Next Pointer */
-#define ROMCON_RBBPTR (0x3ff << 12) /* Base Pointer */
-#define ROMCON_RBTACC (7 << 4) /* Access Cycle Time */
-#define ROMCON_RBTPA (3 << 2) /* Page Address Access Time */
-#define ROMCON_PMC (3 << 0) /* Page Mode Configuration */
-#define PMC_NORMAL (0 << 0)
-#define PMC_4WORD (1 << 0)
-#define PMC_8WORD (2 << 0)
-#define PMC_16WORD (3 << 0)
-
-/* External I/O and ROM/SRAM/Flash General Register */
-#define ERGCON_TMULT (3 << 28) /* Time Multiplier */
-#define ERGCON_DSX2 (3 << 20) /* Data Width (External I/O Bank 2) */
-#define ERGCON_DSX1 (3 << 18) /* Data Width (External I/O Bank 1) */
-#define ERGCON_DSX0 (3 << 16) /* Data Width (External I/O Bank 0) */
-#define ERGCON_DSR1 (3 << 2) /* Data Width (ROM/SRAM/Flash Bank 1) */
-#define ERGCON_DSR0 (3 << 0) /* Data Width (ROM/SRAM/Flash Bank 0) */
-
-/* SDRAM Control Register */
-#define SDCON_DBNPTR (0x3ff << 22) /* Last Address Pointer */
-#define SDCON_DBBPTR (0x3ff << 12) /* Base Pointer */
-#define SDCON_DBCAB (3 << 8) /* Column Address Bits */
-#define SDCON_DBBNUM (1 << 3) /* Number of Banks */
-#define SDCON_DBDBW (3 << 1) /* Data Bus Width */
-
-/* SDRAM General Control Register */
-#define SDGCON_SDTRC (3 << 2) /* RAS to CAS latency */
-#define SDGCON_SDCAS (3 << 0) /* CAS latency */
-
-/* SDRAM Buffer Control Register */
-#define SDBCON_SDESTA (1 << 31) /* SDRAM Engine Status */
-#define SDBCON_RBUFBDIS (1 << 24) /* Read Buffer Burst Enable */
-#define SDBCON_WFIFOEN (1 << 23) /* Write FIFO Enable */
-#define SDBCON_RBUFEN (1 << 22) /* Read Buffer Enable */
-#define SDBCON_FLUSHWFIFO (1 << 21) /* Flush Write FIFO */
-#define SDBCON_RBUFINV (1 << 20) /* Read Buffer Invalidate */
-#define SDBCON_SDINI (3 << 16) /* SDRAM Initialization Control */
-#define SDBCON_SDMODE (0x3fff << 0) /* SDRAM Mode Register Value Program */
-
-/* SDRAM Refresh Timer Register */
-#define REFTIM_REFTIM (0xffff << 0) /* Refresh Timer Value */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/regs-pci.h b/arch/arm/mach-ks8695/regs-pci.h
deleted file mode 100644
index 75a9db6edbd9..000000000000
--- a/arch/arm/mach-ks8695/regs-pci.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-pci.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - PCI bridge registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#define KS8695_PCI_OFFSET (0xF0000 + 0x2000)
-#define KS8695_PCI_VA (KS8695_IO_VA + KS8695_PCI_OFFSET)
-#define KS8695_PCI_PA (KS8695_IO_PA + KS8695_PCI_OFFSET)
-
-
-#define KS8695_CRCFID (0x000) /* Configuration: Identification */
-#define KS8695_CRCFCS (0x004) /* Configuration: Command and Status */
-#define KS8695_CRCFRV (0x008) /* Configuration: Revision */
-#define KS8695_CRCFLT (0x00C) /* Configuration: Latency Timer */
-#define KS8695_CRCBMA (0x010) /* Configuration: Base Memory Address */
-#define KS8695_CRCSID (0x02C) /* Configuration: Subsystem ID */
-#define KS8695_CRCFIT (0x03C) /* Configuration: Interrupt */
-#define KS8695_PBCA (0x100) /* Bridge Configuration Address */
-#define KS8695_PBCD (0x104) /* Bridge Configuration Data */
-#define KS8695_PBM (0x200) /* Bridge Mode */
-#define KS8695_PBCS (0x204) /* Bridge Control and Status */
-#define KS8695_PMBA (0x208) /* Bridge Memory Base Address */
-#define KS8695_PMBAC (0x20C) /* Bridge Memory Base Address Control */
-#define KS8695_PMBAM (0x210) /* Bridge Memory Base Address Mask */
-#define KS8695_PMBAT (0x214) /* Bridge Memory Base Address Translation */
-#define KS8695_PIOBA (0x218) /* Bridge I/O Base Address */
-#define KS8695_PIOBAC (0x21C) /* Bridge I/O Base Address Control */
-#define KS8695_PIOBAM (0x220) /* Bridge I/O Base Address Mask */
-#define KS8695_PIOBAT (0x224) /* Bridge I/O Base Address Translation */
-
-
-/* Configuration: Identification */
-
-/* Configuration: Command and Status */
-
-/* Configuration: Revision */
-
-
-
-#define CFRV_GUEST (1 << 23)
-
-#define PBCA_TYPE1 (1)
-#define PBCA_ENABLE (1 << 31)
-
-
diff --git a/arch/arm/mach-ks8695/regs-sys.h b/arch/arm/mach-ks8695/regs-sys.h
deleted file mode 100644
index 57c20be0c129..000000000000
--- a/arch/arm/mach-ks8695/regs-sys.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-sys.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - System control registers and bit definitions
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_SYS_H
-#define KS8695_SYS_H
-
-#define KS8695_SYS_OFFSET (0xF0000 + 0x0000)
-#define KS8695_SYS_VA (KS8695_IO_VA + KS8695_SYS_OFFSET)
-#define KS8695_SYS_PA (KS8695_IO_PA + KS8695_SYS_OFFSET)
-
-
-#define KS8695_SYSCFG (0x00) /* System Configuration Register */
-#define KS8695_CLKCON (0x04) /* System Clock and Bus Control Register */
-
-
-/* System Configuration Register */
-#define SYSCFG_SPRBP (0x3ff << 16) /* Register Bank Base Pointer */
-
-/* System Clock and Bus Control Register */
-#define CLKCON_SFMODE (1 << 8) /* System Fast Mode for Simulation */
-#define CLKCON_SCDC (7 << 0) /* System Clock Divider Select */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/regs-wan.h b/arch/arm/mach-ks8695/regs-wan.h
deleted file mode 100644
index c475bed22b8e..000000000000
--- a/arch/arm/mach-ks8695/regs-wan.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-wan.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * KS8695 - WAN Registers and bit definitions.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef KS8695_WAN_H
-#define KS8695_WAN_H
-
-#define KS8695_WAN_OFFSET (0xF0000 + 0x6000)
-#define KS8695_WAN_VA (KS8695_IO_VA + KS8695_WAN_OFFSET)
-#define KS8695_WAN_PA (KS8695_IO_PA + KS8695_WAN_OFFSET)
-
-
-/*
- * WAN registers
- */
-#define KS8695_WMDTXC (0x00) /* DMA Transmit Control */
-#define KS8695_WMDRXC (0x04) /* DMA Receive Control */
-#define KS8695_WMDTSC (0x08) /* DMA Transmit Start Command */
-#define KS8695_WMDRSC (0x0c) /* DMA Receive Start Command */
-#define KS8695_WTDLB (0x10) /* Transmit Descriptor List Base Address */
-#define KS8695_WRDLB (0x14) /* Receive Descriptor List Base Address */
-#define KS8695_WMAL (0x18) /* MAC Station Address Low */
-#define KS8695_WMAH (0x1c) /* MAC Station Address High */
-#define KS8695_WMAAL(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */
-#define KS8695_WMAAH(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */
-
-
-/* DMA Transmit Control Register */
-#define WMDTXC_WMTRST (1 << 31) /* Soft Reset */
-#define WMDTXC_WMTBS (0x3f << 24) /* Transmit Burst Size */
-#define WMDTXC_WMTUCG (1 << 18) /* Transmit UDP Checksum Generate */
-#define WMDTXC_WMTTCG (1 << 17) /* Transmit TCP Checksum Generate */
-#define WMDTXC_WMTICG (1 << 16) /* Transmit IP Checksum Generate */
-#define WMDTXC_WMTFCE (1 << 9) /* Transmit Flow Control Enable */
-#define WMDTXC_WMTLB (1 << 8) /* Loopback mode */
-#define WMDTXC_WMTEP (1 << 2) /* Transmit Enable Padding */
-#define WMDTXC_WMTAC (1 << 1) /* Transmit Add CRC */
-#define WMDTXC_WMTE (1 << 0) /* TX Enable */
-
-/* DMA Receive Control Register */
-#define WMDRXC_WMRBS (0x3f << 24) /* Receive Burst Size */
-#define WMDRXC_WMRUCC (1 << 18) /* Receive UDP Checksum check */
-#define WMDRXC_WMRTCG (1 << 17) /* Receive TCP Checksum check */
-#define WMDRXC_WMRICG (1 << 16) /* Receive IP Checksum check */
-#define WMDRXC_WMRFCE (1 << 9) /* Receive Flow Control Enable */
-#define WMDRXC_WMRB (1 << 6) /* Receive Broadcast */
-#define WMDRXC_WMRM (1 << 5) /* Receive Multicast */
-#define WMDRXC_WMRU (1 << 4) /* Receive Unicast */
-#define WMDRXC_WMRERR (1 << 3) /* Receive Error Frame */
-#define WMDRXC_WMRA (1 << 2) /* Receive All */
-#define WMDRXC_WMRE (1 << 0) /* RX Enable */
-
-/* Additional Station Address High */
-#define WMAAH_E (1 << 31) /* Address Enabled */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c
deleted file mode 100644
index 50561eec0c32..000000000000
--- a/arch/arm/mach-ks8695/time.c
+++ /dev/null
@@ -1,159 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ks8695/time.c
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/io.h>
-#include <linux/clockchips.h>
-
-#include <asm/mach/time.h>
-#include <asm/system_misc.h>
-
-#include <mach/regs-irq.h>
-
-#include "generic.h"
-
-#define KS8695_TMR_OFFSET (0xF0000 + 0xE400)
-#define KS8695_TMR_VA (KS8695_IO_VA + KS8695_TMR_OFFSET)
-#define KS8695_TMR_PA (KS8695_IO_PA + KS8695_TMR_OFFSET)
-
-/*
- * Timer registers
- */
-#define KS8695_TMCON (0x00) /* Timer Control Register */
-#define KS8695_T1TC (0x04) /* Timer 1 Timeout Count Register */
-#define KS8695_T0TC (0x08) /* Timer 0 Timeout Count Register */
-#define KS8695_T1PD (0x0C) /* Timer 1 Pulse Count Register */
-#define KS8695_T0PD (0x10) /* Timer 0 Pulse Count Register */
-
-/* Timer Control Register */
-#define TMCON_T1EN (1 << 1) /* Timer 1 Enable */
-#define TMCON_T0EN (1 << 0) /* Timer 0 Enable */
-
-/* Timer0 Timeout Counter Register */
-#define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */
-
-static int ks8695_set_periodic(struct clock_event_device *evt)
-{
- u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ);
- u32 half = DIV_ROUND_CLOSEST(rate, 2);
- u32 tmcon;
-
- /* Disable timer 1 */
- tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
- tmcon &= ~TMCON_T1EN;
- writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
-
- /* Both registers need to count down */
- writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
- writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
-
- /* Re-enable timer1 */
- tmcon |= TMCON_T1EN;
- writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
- return 0;
-}
-
-static int ks8695_set_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-
-{
- u32 half = DIV_ROUND_CLOSEST(cycles, 2);
- u32 tmcon;
-
- /* Disable timer 1 */
- tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
- tmcon &= ~TMCON_T1EN;
- writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
-
- /* Both registers need to count down */
- writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
- writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
-
- /* Re-enable timer1 */
- tmcon |= TMCON_T1EN;
- writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
-
- return 0;
-}
-
-static struct clock_event_device clockevent_ks8695 = {
- .name = "ks8695_t1tc",
- /* Reasonably fast and accurate clock event */
- .rating = 300,
- .features = CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_PERIODIC,
- .set_next_event = ks8695_set_next_event,
- .set_state_periodic = ks8695_set_periodic,
-};
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t ks8695_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &clockevent_ks8695;
-
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static struct irqaction ks8695_timer_irq = {
- .name = "ks8695_tick",
- .flags = IRQF_TIMER,
- .handler = ks8695_timer_interrupt,
-};
-
-static void ks8695_timer_setup(void)
-{
- unsigned long tmcon;
-
- /* Disable timer 0 and 1 */
- tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
- tmcon &= ~TMCON_T0EN;
- tmcon &= ~TMCON_T1EN;
- writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
-
- /*
- * Use timer 1 to fire IRQs on the timeline, minimum 2 cycles
- * (one on each counter) maximum 2*2^32, but the API will only
- * accept up to a 32bit full word (0xFFFFFFFFU).
- */
- clockevents_config_and_register(&clockevent_ks8695,
- KS8695_CLOCK_RATE, 2,
- 0xFFFFFFFFU);
-}
-
-void __init ks8695_timer_init(void)
-{
- ks8695_timer_setup();
-
- /* Enable timer interrupts */
- setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq);
-}
-
-void ks8695_restart(enum reboot_mode reboot_mode, const char *cmd)
-{
- unsigned int reg;
-
- if (reboot_mode == REBOOT_SOFT)
- soft_restart(0);
-
- /* disable timer0 */
- reg = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
- writel_relaxed(reg & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-
- /* enable watchdog mode */
- writel_relaxed((10 << 8) | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
-
- /* re-enable timer0 */
- writel_relaxed(reg | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-}
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
new file mode 100644
index 000000000000..ec87c65f4536
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config ARCH_LPC32XX
+ bool "NXP LPC32XX"
+ depends on ARCH_MULTI_V5
+ select ARM_AMBA
+ select CLKSRC_LPC32XX
+ select CPU_ARM926T
+ select GPIOLIB
+ help
+ Support for the NXP LPC32XX family of processors
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
index 5b71b4fab2cd..304ea61a0716 100644
--- a/arch/arm/mach-lpc32xx/common.c
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -8,12 +8,12 @@
*/
#include <linux/init.h>
+#include <linux/soc/nxp/lpc32xx-misc.h>
#include <asm/mach/map.h>
#include <asm/system_info.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include "lpc32xx.h"
#include "common.h"
/*
@@ -32,7 +32,7 @@ void lpc32xx_get_uid(u32 devid[4])
*/
#define LPC32XX_IRAM_BANK_SIZE SZ_128K
static u32 iram_size;
-u32 lpc32xx_return_iram_size(void)
+u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr)
{
if (iram_size == 0) {
u32 savedval1, savedval2;
@@ -53,10 +53,26 @@ u32 lpc32xx_return_iram_size(void)
} else
iram_size = LPC32XX_IRAM_BANK_SIZE * 2;
}
+ if (dmaaddr)
+ *dmaaddr = LPC32XX_IRAM_BASE;
+ if (mapbase)
+ *mapbase = io_p2v(LPC32XX_IRAM_BASE);
return iram_size;
}
-EXPORT_SYMBOL_GPL(lpc32xx_return_iram_size);
+EXPORT_SYMBOL_GPL(lpc32xx_return_iram);
+
+void lpc32xx_set_phy_interface_mode(phy_interface_t mode)
+{
+ u32 tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
+ tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
+ if (mode == PHY_INTERFACE_MODE_MII)
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS;
+ else
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
+ __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
+}
+EXPORT_SYMBOL_GPL(lpc32xx_set_phy_interface_mode);
static struct map_desc lpc32xx_io_desc[] __initdata = {
{
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
index 8e597ce48a73..32f0ad217807 100644
--- a/arch/arm/mach-lpc32xx/common.h
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -23,7 +23,6 @@ extern void __init lpc32xx_serial_init(void);
*/
extern void lpc32xx_get_uid(u32 devid[4]);
-extern u32 lpc32xx_return_iram_size(void);
/*
* Pointers used for sizing and copying suspend function data
*/
diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-lpc32xx/include/mach/board.h
deleted file mode 100644
index 476513d970a4..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/board.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arm/arch/mach-lpc32xx/include/mach/board.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- */
-
-#ifndef __ASM_ARCH_BOARD_H
-#define __ASM_ARCH_BOARD_H
-
-extern u32 lpc32xx_return_iram_size(void);
-
-#endif /* __ASM_ARCH_BOARD_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
deleted file mode 100644
index eec0f5f7e722..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-lpc32xx/include/mach/entry-macro.S
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- */
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-
-#define LPC32XX_INTC_MASKED_STATUS_OFS 0x8
-
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =IO_ADDRESS(LPC32XX_MIC_BASE)
- .endm
-
-/*
- * Return IRQ number in irqnr. Also return processor Z flag status in CPSR
- * as set if an interrupt is pending.
- */
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, [\base, #LPC32XX_INTC_MASKED_STATUS_OFS]
- clz \irqnr, \irqstat
- rsb \irqnr, \irqnr, #31
- teq \irqstat, #0
- .endm
diff --git a/arch/arm/mach-lpc32xx/include/mach/hardware.h b/arch/arm/mach-lpc32xx/include/mach/hardware.h
deleted file mode 100644
index 4866f096ffce..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/hardware.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-lpc32xx/include/mach/hardware.h
- *
- * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-/*
- * Start of virtual addresses for IO devices
- */
-#define IO_BASE 0xF0000000
-
-/*
- * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
- */
-#define IO_ADDRESS(x) IOMEM(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
- IO_BASE)
-
-#define io_p2v(x) ((void __iomem *) (unsigned long) IO_ADDRESS(x))
-#define io_v2p(x) ((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
-
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/uncompress.h b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
deleted file mode 100644
index a568812a0b91..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-lpc32xx/include/mach/uncompress.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- */
-
-#ifndef __ASM_ARM_ARCH_UNCOMPRESS_H
-#define __ASM_ARM_ARCH_UNCOMPRESS_H
-
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-
-/*
- * Uncompress output is hardcoded to standard UART 5
- */
-
-#define UART_FIFO_CTL_TX_RESET (1 << 2)
-#define UART_STATUS_TX_MT (1 << 6)
-
-#define _UARTREG(x) (void __iomem *)(LPC32XX_UART5_BASE + (x))
-
-#define LPC32XX_UART_DLLFIFO_O 0x00
-#define LPC32XX_UART_IIRFCR_O 0x08
-#define LPC32XX_UART_LSR_O 0x14
-
-static inline void putc(int ch)
-{
- /* Wait for transmit FIFO to empty */
- while ((__raw_readl(_UARTREG(LPC32XX_UART_LSR_O)) &
- UART_STATUS_TX_MT) == 0)
- ;
-
- __raw_writel((u32) ch, _UARTREG(LPC32XX_UART_DLLFIFO_O));
-}
-
-static inline void flush(void)
-{
- __raw_writel(__raw_readl(_UARTREG(LPC32XX_UART_IIRFCR_O)) |
- UART_FIFO_CTL_TX_RESET, _UARTREG(LPC32XX_UART_IIRFCR_O));
-}
-
-/* NULL functions; we don't presently need them */
-#define arch_decomp_setup()
-
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/platform.h b/arch/arm/mach-lpc32xx/lpc32xx.h
index 1c53790444fc..5eeb884a1993 100644
--- a/arch/arm/mach-lpc32xx/include/mach/platform.h
+++ b/arch/arm/mach-lpc32xx/lpc32xx.h
@@ -7,8 +7,8 @@
* Copyright (C) 2010 NXP Semiconductors
*/
-#ifndef __ASM_ARCH_PLATFORM_H
-#define __ASM_ARCH_PLATFORM_H
+#ifndef __ARM_LPC32XX_H
+#define __ARM_LPC32XX_H
#define _SBF(f, v) ((v) << (f))
#define _BIT(n) _SBF(n, 1)
@@ -700,4 +700,18 @@
#define LPC32XX_USB_OTG_DEV_CLOCK_ON _BIT(1)
#define LPC32XX_USB_OTG_HOST_CLOCK_ON _BIT(0)
+/*
+ * Start of virtual addresses for IO devices
+ */
+#define IO_BASE 0xF0000000
+
+/*
+ * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
+ */
+#define IO_ADDRESS(x) IOMEM(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
+ IO_BASE)
+
+#define io_p2v(x) ((void __iomem *) (unsigned long) IO_ADDRESS(x))
+#define io_v2p(x) ((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
+
#endif
diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c
index 32bca351a73b..b27fa1b9f56c 100644
--- a/arch/arm/mach-lpc32xx/pm.c
+++ b/arch/arm/mach-lpc32xx/pm.c
@@ -70,8 +70,7 @@
#include <asm/cacheflush.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include "lpc32xx.h"
#include "common.h"
#define TEMP_IRAM_AREA IO_ADDRESS(LPC32XX_IRAM_BASE)
diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c
index 3f9b30df9f0e..3e765c4bf986 100644
--- a/arch/arm/mach-lpc32xx/serial.c
+++ b/arch/arm/mach-lpc32xx/serial.c
@@ -16,8 +16,7 @@
#include <linux/clk.h>
#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include "lpc32xx.h"
#include "common.h"
#define LPC32XX_SUART_FIFO_SIZE 64
@@ -60,6 +59,36 @@ static struct uartinit uartinit_data[] __initdata = {
},
};
+/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */
+void lpc32xx_loopback_set(resource_size_t mapbase, int state)
+{
+ int bit;
+ u32 tmp;
+
+ switch (mapbase) {
+ case LPC32XX_HS_UART1_BASE:
+ bit = 0;
+ break;
+ case LPC32XX_HS_UART2_BASE:
+ bit = 1;
+ break;
+ case LPC32XX_HS_UART7_BASE:
+ bit = 6;
+ break;
+ default:
+ WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase);
+ return;
+ }
+
+ tmp = readl(LPC32XX_UARTCTL_CLOOP);
+ if (state)
+ tmp |= (1 << bit);
+ else
+ tmp &= ~(1 << bit);
+ writel(tmp, LPC32XX_UARTCTL_CLOOP);
+}
+EXPORT_SYMBOL_GPL(lpc32xx_loopback_set);
+
void __init lpc32xx_serial_init(void)
{
u32 tmp, clkmodes = 0;
diff --git a/arch/arm/mach-lpc32xx/suspend.S b/arch/arm/mach-lpc32xx/suspend.S
index 374f9f07fe48..3f0a8282ef6f 100644
--- a/arch/arm/mach-lpc32xx/suspend.S
+++ b/arch/arm/mach-lpc32xx/suspend.S
@@ -11,8 +11,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <mach/platform.h>
-#include <mach/hardware.h>
+#include "lpc32xx.h"
/* Using named register defines makes the code easier to follow */
#define WORK1_REG r0
diff --git a/arch/arm/mach-mmp/regs-icu.h b/arch/arm/mach-mmp/regs-icu.h
index 0375d5a7fcb2..410743d2b402 100644
--- a/arch/arm/mach-mmp/regs-icu.h
+++ b/arch/arm/mach-mmp/regs-icu.h
@@ -11,6 +11,9 @@
#define ICU_VIRT_BASE (AXI_VIRT_BASE + 0x82000)
#define ICU_REG(x) (ICU_VIRT_BASE + (x))
+#define ICU2_VIRT_BASE (AXI_VIRT_BASE + 0x84000)
+#define ICU2_REG(x) (ICU2_VIRT_BASE + (x))
+
#define ICU_INT_CONF(n) ICU_REG((n) << 2)
#define ICU_INT_CONF_MASK (0xf)
diff --git a/arch/arm/mach-mv78xx0/mv78xx0.h b/arch/arm/mach-mv78xx0/mv78xx0.h
index 2db1265ec121..c1a9a1d1b295 100644
--- a/arch/arm/mach-mv78xx0/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/mv78xx0.h
@@ -37,7 +37,7 @@
* fee50000 f0d00000 64K PCIe #5 I/O space
* fee60000 f0e00000 64K PCIe #6 I/O space
* fee70000 f0f00000 64K PCIe #7 I/O space
- * fd000000 f1000000 1M on-chip peripheral registers
+ * fec00000 f1000000 1M on-chip peripheral registers
*/
#define MV78XX0_CORE0_REGS_PHYS_BASE 0xf1020000
#define MV78XX0_CORE1_REGS_PHYS_BASE 0xf1024000
@@ -49,7 +49,7 @@
#define MV78XX0_PCIE_IO_SIZE SZ_1M
#define MV78XX0_REGS_PHYS_BASE 0xf1000000
-#define MV78XX0_REGS_VIRT_BASE IOMEM(0xfd000000)
+#define MV78XX0_REGS_VIRT_BASE IOMEM(0xfec00000)
#define MV78XX0_REGS_SIZE SZ_1M
#define MV78XX0_PCIE_MEM_PHYS_BASE 0xc0000000
diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig
deleted file mode 100644
index 1e5d9c870784..000000000000
--- a/arch/arm/mach-netx/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menu "NetX Implementations"
- depends on ARCH_NETX
-
-config MACH_NXDKN
- bool "Enable Hilscher nxdkn Eval Board support"
- help
- Board support for the Hilscher NetX Eval Board
-
-config MACH_NXDB500
- bool "Enable Hilscher nxdb500 Eval Board support"
- select ARM_AMBA
- help
- Board support for the Hilscher nxdb500 Eval Board
-
-config MACH_NXEB500HMI
- bool "Enable Hilscher nxeb500hmi Eval Board support"
- select ARM_AMBA
- help
- Board support for the Hilscher nxeb500hmi Eval Board
-
-endmenu
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile
deleted file mode 100644
index 44ea83f7d9c2..000000000000
--- a/arch/arm/mach-netx/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y += time.o generic.o pfifo.o xc.o
-
-# Specific board support
-obj-$(CONFIG_MACH_NXDKN) += nxdkn.o
-obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o
-obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
deleted file mode 100644
index 2dc80db07390..000000000000
--- a/arch/arm/mach-netx/fb.c
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/fb.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <linux/err.h>
-#include <linux/gfp.h>
-
-#include <asm/irq.h>
-
-#include <mach/netx-regs.h>
-#include <mach/hardware.h>
-
-static struct clcd_panel *netx_panel;
-
-void netx_clcd_enable(struct clcd_fb *fb)
-{
-}
-
-int netx_clcd_setup(struct clcd_fb *fb)
-{
- dma_addr_t dma;
-
- fb->panel = netx_panel;
-
- fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, 1024 * 1024, &dma,
- GFP_KERNEL);
- if (!fb->fb.screen_base) {
- printk(KERN_ERR "CLCD: unable to map framebuffer\n");
- return -ENOMEM;
- }
-
- fb->fb.fix.smem_start = dma;
- fb->fb.fix.smem_len = 1024*1024;
-
- return 0;
-}
-
-int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
- return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
- fb->fb.fix.smem_start, fb->fb.fix.smem_len);
-}
-
-void netx_clcd_remove(struct clcd_fb *fb)
-{
- dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
- fb->fb.fix.smem_start);
-}
-
-static AMBA_AHB_DEVICE(fb, "fb", 0, 0x00104000, { NETX_IRQ_LCD }, NULL);
-
-int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel)
-{
- netx_panel = panel;
- fb_device.dev.platform_data = board;
- return amba_device_register(&fb_device, &iomem_resource);
-}
diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h
deleted file mode 100644
index 5cdc01fc3c86..000000000000
--- a/arch/arm/mach-netx/fb.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/fb.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-void netx_clcd_enable(struct clcd_fb *fb);
-int netx_clcd_setup(struct clcd_fb *fb);
-int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
-void netx_clcd_remove(struct clcd_fb *fb);
-int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
deleted file mode 100644
index 88881fd45e9f..000000000000
--- a/arch/arm/mach-netx/generic.c
+++ /dev/null
@@ -1,182 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/generic.c
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-vic.h>
-#include <linux/reboot.h>
-#include <mach/hardware.h>
-#include <asm/mach/map.h>
-#include <mach/netx-regs.h>
-#include <asm/mach/irq.h>
-
-static struct map_desc netx_io_desc[] __initdata = {
- {
- .virtual = NETX_IO_VIRT,
- .pfn = __phys_to_pfn(NETX_IO_PHYS),
- .length = NETX_IO_SIZE,
- .type = MT_DEVICE
- }
-};
-
-void __init netx_map_io(void)
-{
- iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
-}
-
-static struct resource netx_rtc_resources[] = {
- [0] = {
- .start = 0x00101200,
- .end = 0x00101220,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device netx_rtc_device = {
- .name = "netx-rtc",
- .id = 0,
- .num_resources = ARRAY_SIZE(netx_rtc_resources),
- .resource = netx_rtc_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
- &netx_rtc_device,
-};
-
-#if 0
-#define DEBUG_IRQ(fmt...) printk(fmt)
-#else
-#define DEBUG_IRQ(fmt...) while (0) {}
-#endif
-
-static void netx_hif_demux_handler(struct irq_desc *desc)
-{
- unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
- unsigned int stat;
-
- stat = ((readl(NETX_DPMAS_INT_EN) &
- readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
-
- while (stat) {
- if (stat & 1) {
- DEBUG_IRQ("handling irq %d\n", irq);
- generic_handle_irq(irq);
- }
- irq++;
- stat >>= 1;
- }
-}
-
-static int
-netx_hif_irq_type(struct irq_data *d, unsigned int type)
-{
- unsigned int val, irq;
-
- val = readl(NETX_DPMAS_IF_CONF1);
-
- irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
-
- if (type & IRQ_TYPE_EDGE_RISING) {
- DEBUG_IRQ("rising edges\n");
- val |= (1 << 26) << irq;
- }
- if (type & IRQ_TYPE_EDGE_FALLING) {
- DEBUG_IRQ("falling edges\n");
- val &= ~((1 << 26) << irq);
- }
- if (type & IRQ_TYPE_LEVEL_LOW) {
- DEBUG_IRQ("low level\n");
- val &= ~((1 << 26) << irq);
- }
- if (type & IRQ_TYPE_LEVEL_HIGH) {
- DEBUG_IRQ("high level\n");
- val |= (1 << 26) << irq;
- }
-
- writel(val, NETX_DPMAS_IF_CONF1);
-
- return 0;
-}
-
-static void
-netx_hif_ack_irq(struct irq_data *d)
-{
- unsigned int val, irq;
-
- irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
- writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
-
- val = readl(NETX_DPMAS_INT_EN);
- val &= ~((1 << 24) << irq);
- writel(val, NETX_DPMAS_INT_EN);
-
- DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static void
-netx_hif_mask_irq(struct irq_data *d)
-{
- unsigned int val, irq;
-
- irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
- val = readl(NETX_DPMAS_INT_EN);
- val &= ~((1 << 24) << irq);
- writel(val, NETX_DPMAS_INT_EN);
- DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static void
-netx_hif_unmask_irq(struct irq_data *d)
-{
- unsigned int val, irq;
-
- irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
- val = readl(NETX_DPMAS_INT_EN);
- val |= (1 << 24) << irq;
- writel(val, NETX_DPMAS_INT_EN);
- DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static struct irq_chip netx_hif_chip = {
- .irq_ack = netx_hif_ack_irq,
- .irq_mask = netx_hif_mask_irq,
- .irq_unmask = netx_hif_unmask_irq,
- .irq_set_type = netx_hif_irq_type,
-};
-
-void __init netx_init_irq(void)
-{
- int irq;
-
- vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0);
-
- for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
- irq_set_chip_and_handler(irq, &netx_hif_chip,
- handle_level_irq);
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
- }
-
- writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
- irq_set_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
-}
-
-static int __init netx_init(void)
-{
- return platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-subsys_initcall(netx_init);
-
-void netx_restart(enum reboot_mode mode, const char *cmd)
-{
- writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES,
- NETX_SYSTEM_RES_CR);
-}
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
deleted file mode 100644
index 223e304574a5..000000000000
--- a/arch/arm/mach-netx/generic.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/generic.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/reboot.h>
-
-extern void __init netx_map_io(void);
-extern void __init netx_init_irq(void);
-extern void netx_restart(enum reboot_mode, const char *);
-
-extern void netx_timer_init(void);
diff --git a/arch/arm/mach-netx/include/mach/hardware.h b/arch/arm/mach-netx/include/mach/hardware.h
deleted file mode 100644
index 84253993d1e0..000000000000
--- a/arch/arm/mach-netx/include/mach/hardware.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/hardware.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#define NETX_IO_PHYS 0x00100000
-#define NETX_IO_VIRT 0xe0000000
-#define NETX_IO_SIZE 0x00100000
-
-#define SRAM_INTERNAL_PHYS_0 0x00000
-#define SRAM_INTERNAL_PHYS_1 0x08000
-#define SRAM_INTERNAL_PHYS_2 0x10000
-#define SRAM_INTERNAL_PHYS_3 0x18000
-#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000)
-
-#define XPEC_MEM_SIZE 0x4000
-#define XMAC_MEM_SIZE 0x1000
-#define SRAM_MEM_SIZE 0x8000
-
-#define io_p2v(x) IOMEM((x) - NETX_IO_PHYS + NETX_IO_VIRT)
-#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS)
-
-#endif
diff --git a/arch/arm/mach-netx/include/mach/irqs.h b/arch/arm/mach-netx/include/mach/irqs.h
deleted file mode 100644
index 540c92104fe8..000000000000
--- a/arch/arm/mach-netx/include/mach/irqs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/irqs.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#define NETX_IRQ_VIC_START 64
-#define NETX_IRQ_SOFTINT (NETX_IRQ_VIC_START + 0)
-#define NETX_IRQ_TIMER0 (NETX_IRQ_VIC_START + 1)
-#define NETX_IRQ_TIMER1 (NETX_IRQ_VIC_START + 2)
-#define NETX_IRQ_TIMER2 (NETX_IRQ_VIC_START + 3)
-#define NETX_IRQ_SYSTIME_NS (NETX_IRQ_VIC_START + 4)
-#define NETX_IRQ_SYSTIME_S (NETX_IRQ_VIC_START + 5)
-#define NETX_IRQ_GPIO_15 (NETX_IRQ_VIC_START + 6)
-#define NETX_IRQ_WATCHDOG (NETX_IRQ_VIC_START + 7)
-#define NETX_IRQ_UART0 (NETX_IRQ_VIC_START + 8)
-#define NETX_IRQ_UART1 (NETX_IRQ_VIC_START + 9)
-#define NETX_IRQ_UART2 (NETX_IRQ_VIC_START + 10)
-#define NETX_IRQ_USB (NETX_IRQ_VIC_START + 11)
-#define NETX_IRQ_SPI (NETX_IRQ_VIC_START + 12)
-#define NETX_IRQ_I2C (NETX_IRQ_VIC_START + 13)
-#define NETX_IRQ_LCD (NETX_IRQ_VIC_START + 14)
-#define NETX_IRQ_HIF (NETX_IRQ_VIC_START + 15)
-#define NETX_IRQ_GPIO_0_14 (NETX_IRQ_VIC_START + 16)
-#define NETX_IRQ_XPEC0 (NETX_IRQ_VIC_START + 17)
-#define NETX_IRQ_XPEC1 (NETX_IRQ_VIC_START + 18)
-#define NETX_IRQ_XPEC2 (NETX_IRQ_VIC_START + 19)
-#define NETX_IRQ_XPEC3 (NETX_IRQ_VIC_START + 20)
-#define NETX_IRQ_XPEC(no) (NETX_IRQ_VIC_START + 17 + (no))
-#define NETX_IRQ_MSYNC0 (NETX_IRQ_VIC_START + 21)
-#define NETX_IRQ_MSYNC1 (NETX_IRQ_VIC_START + 22)
-#define NETX_IRQ_MSYNC2 (NETX_IRQ_VIC_START + 23)
-#define NETX_IRQ_MSYNC3 (NETX_IRQ_VIC_START + 24)
-#define NETX_IRQ_IRQ_PHY (NETX_IRQ_VIC_START + 25)
-#define NETX_IRQ_ISO_AREA (NETX_IRQ_VIC_START + 26)
-/* int 27 is reserved */
-/* int 28 is reserved */
-#define NETX_IRQ_TIMER3 (NETX_IRQ_VIC_START + 29)
-#define NETX_IRQ_TIMER4 (NETX_IRQ_VIC_START + 30)
-/* int 31 is reserved */
-
-#define NETX_IRQS (NETX_IRQ_VIC_START + 32)
-
-/* for multiplexed irqs on gpio 0..14 */
-#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
-#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14)
-
-/* Host interface interrupts */
-#define NETX_IRQ_HIF_CHAINED(x) (NETX_IRQ_GPIO_LAST + 1 + (x))
-#define NETX_IRQ_HIF_PIO35 NETX_IRQ_HIF_CHAINED(0)
-#define NETX_IRQ_HIF_PIO36 NETX_IRQ_HIF_CHAINED(1)
-#define NETX_IRQ_HIF_PIO40 NETX_IRQ_HIF_CHAINED(2)
-#define NETX_IRQ_HIF_PIO47 NETX_IRQ_HIF_CHAINED(3)
-#define NETX_IRQ_HIF_PIO72 NETX_IRQ_HIF_CHAINED(4)
-#define NETX_IRQ_HIF_LAST NETX_IRQ_HIF_CHAINED(4)
-
-#define NR_IRQS (NETX_IRQ_HIF_LAST + 1)
diff --git a/arch/arm/mach-netx/include/mach/netx-regs.h b/arch/arm/mach-netx/include/mach/netx-regs.h
deleted file mode 100644
index 7c356a6ab80b..000000000000
--- a/arch/arm/mach-netx/include/mach/netx-regs.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/netx-regs.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#ifndef __ASM_ARCH_NETX_REGS_H
-#define __ASM_ARCH_NETX_REGS_H
-
-/* offsets relative to the beginning of the io space */
-#define NETX_OFS_SYSTEM 0x00000
-#define NETX_OFS_MEMCR 0x00100
-#define NETX_OFS_DPMAS 0x03000
-#define NETX_OFS_GPIO 0x00800
-#define NETX_OFS_PIO 0x00900
-#define NETX_OFS_UART0 0x00a00
-#define NETX_OFS_UART1 0x00a40
-#define NETX_OFS_UART2 0x00a80
-#define NETX_OF_MIIMU 0x00b00
-#define NETX_OFS_SPI 0x00c00
-#define NETX_OFS_I2C 0x00d00
-#define NETX_OFS_SYSTIME 0x01100
-#define NETX_OFS_RTC 0x01200
-#define NETX_OFS_EXTBUS 0x03600
-#define NETX_OFS_LCD 0x04000
-#define NETX_OFS_USB 0x20000
-#define NETX_OFS_XMAC0 0x60000
-#define NETX_OFS_XMAC1 0x61000
-#define NETX_OFS_XMAC2 0x62000
-#define NETX_OFS_XMAC3 0x63000
-#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000)
-#define NETX_OFS_PFIFO 0x64000
-#define NETX_OFS_XPEC0 0x70000
-#define NETX_OFS_XPEC1 0x74000
-#define NETX_OFS_XPEC2 0x78000
-#define NETX_OFS_XPEC3 0x7c000
-#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000)
-#define NETX_OFS_VIC 0xff000
-
-/* physical addresses */
-#define NETX_PA_SYSTEM (NETX_IO_PHYS + NETX_OFS_SYSTEM)
-#define NETX_PA_MEMCR (NETX_IO_PHYS + NETX_OFS_MEMCR)
-#define NETX_PA_DPMAS (NETX_IO_PHYS + NETX_OFS_DPMAS)
-#define NETX_PA_GPIO (NETX_IO_PHYS + NETX_OFS_GPIO)
-#define NETX_PA_PIO (NETX_IO_PHYS + NETX_OFS_PIO)
-#define NETX_PA_UART0 (NETX_IO_PHYS + NETX_OFS_UART0)
-#define NETX_PA_UART1 (NETX_IO_PHYS + NETX_OFS_UART1)
-#define NETX_PA_UART2 (NETX_IO_PHYS + NETX_OFS_UART2)
-#define NETX_PA_MIIMU (NETX_IO_PHYS + NETX_OF_MIIMU)
-#define NETX_PA_SPI (NETX_IO_PHYS + NETX_OFS_SPI)
-#define NETX_PA_I2C (NETX_IO_PHYS + NETX_OFS_I2C)
-#define NETX_PA_SYSTIME (NETX_IO_PHYS + NETX_OFS_SYSTIME)
-#define NETX_PA_RTC (NETX_IO_PHYS + NETX_OFS_RTC)
-#define NETX_PA_EXTBUS (NETX_IO_PHYS + NETX_OFS_EXTBUS)
-#define NETX_PA_LCD (NETX_IO_PHYS + NETX_OFS_LCD)
-#define NETX_PA_USB (NETX_IO_PHYS + NETX_OFS_USB)
-#define NETX_PA_XMAC0 (NETX_IO_PHYS + NETX_OFS_XMAC0)
-#define NETX_PA_XMAC1 (NETX_IO_PHYS + NETX_OFS_XMAC1)
-#define NETX_PA_XMAC2 (NETX_IO_PHYS + NETX_OFS_XMAC2)
-#define NETX_PA_XMAC3 (NETX_IO_PHYS + NETX_OFS_XMAC3)
-#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no))
-#define NETX_PA_PFIFO (NETX_IO_PHYS + NETX_OFS_PFIFO)
-#define NETX_PA_XPEC0 (NETX_IO_PHYS + NETX_OFS_XPEC0)
-#define NETX_PA_XPEC1 (NETX_IO_PHYS + NETX_OFS_XPEC1)
-#define NETX_PA_XPEC2 (NETX_IO_PHYS + NETX_OFS_XPEC2)
-#define NETX_PA_XPEC3 (NETX_IO_PHYS + NETX_OFS_XPEC3)
-#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no))
-#define NETX_PA_VIC (NETX_IO_PHYS + NETX_OFS_VIC)
-
-/* virtual addresses */
-#define NETX_VA_SYSTEM (NETX_IO_VIRT + NETX_OFS_SYSTEM)
-#define NETX_VA_MEMCR (NETX_IO_VIRT + NETX_OFS_MEMCR)
-#define NETX_VA_DPMAS (NETX_IO_VIRT + NETX_OFS_DPMAS)
-#define NETX_VA_GPIO (NETX_IO_VIRT + NETX_OFS_GPIO)
-#define NETX_VA_PIO (NETX_IO_VIRT + NETX_OFS_PIO)
-#define NETX_VA_UART0 (NETX_IO_VIRT + NETX_OFS_UART0)
-#define NETX_VA_UART1 (NETX_IO_VIRT + NETX_OFS_UART1)
-#define NETX_VA_UART2 (NETX_IO_VIRT + NETX_OFS_UART2)
-#define NETX_VA_MIIMU (NETX_IO_VIRT + NETX_OF_MIIMU)
-#define NETX_VA_SPI (NETX_IO_VIRT + NETX_OFS_SPI)
-#define NETX_VA_I2C (NETX_IO_VIRT + NETX_OFS_I2C)
-#define NETX_VA_SYSTIME (NETX_IO_VIRT + NETX_OFS_SYSTIME)
-#define NETX_VA_RTC (NETX_IO_VIRT + NETX_OFS_RTC)
-#define NETX_VA_EXTBUS (NETX_IO_VIRT + NETX_OFS_EXTBUS)
-#define NETX_VA_LCD (NETX_IO_VIRT + NETX_OFS_LCD)
-#define NETX_VA_USB (NETX_IO_VIRT + NETX_OFS_USB)
-#define NETX_VA_XMAC0 (NETX_IO_VIRT + NETX_OFS_XMAC0)
-#define NETX_VA_XMAC1 (NETX_IO_VIRT + NETX_OFS_XMAC1)
-#define NETX_VA_XMAC2 (NETX_IO_VIRT + NETX_OFS_XMAC2)
-#define NETX_VA_XMAC3 (NETX_IO_VIRT + NETX_OFS_XMAC3)
-#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no))
-#define NETX_VA_PFIFO (NETX_IO_VIRT + NETX_OFS_PFIFO)
-#define NETX_VA_XPEC0 (NETX_IO_VIRT + NETX_OFS_XPEC0)
-#define NETX_VA_XPEC1 (NETX_IO_VIRT + NETX_OFS_XPEC1)
-#define NETX_VA_XPEC2 (NETX_IO_VIRT + NETX_OFS_XPEC2)
-#define NETX_VA_XPEC3 (NETX_IO_VIRT + NETX_OFS_XPEC3)
-#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no))
-#define NETX_VA_VIC (NETX_IO_VIRT + NETX_OFS_VIC)
-
-/*********************************
- * System functions *
- *********************************/
-
-/* Registers */
-#define NETX_SYSTEM_REG(ofs) IOMEM(NETX_VA_SYSTEM + (ofs))
-#define NETX_SYSTEM_BOO_SR NETX_SYSTEM_REG(0x00)
-#define NETX_SYSTEM_IOC_CR NETX_SYSTEM_REG(0x04)
-#define NETX_SYSTEM_IOC_MR NETX_SYSTEM_REG(0x08)
-
-/* FIXME: Docs are not consistent */
-/* #define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x08) */
-#define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x0c)
-
-#define NETX_SYSTEM_PHY_CONTROL NETX_SYSTEM_REG(0x10)
-#define NETX_SYSTEM_REV NETX_SYSTEM_REG(0x34)
-#define NETX_SYSTEM_IOC_ACCESS_KEY NETX_SYSTEM_REG(0x70)
-#define NETX_SYSTEM_WDG_TR NETX_SYSTEM_REG(0x200)
-#define NETX_SYSTEM_WDG_CTR NETX_SYSTEM_REG(0x204)
-#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208)
-#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c)
-
-/* Bits */
-#define NETX_SYSTEM_RES_CR_RSTIN (1<<0)
-#define NETX_SYSTEM_RES_CR_WDG_RES (1<<1)
-#define NETX_SYSTEM_RES_CR_HOST_RES (1<<2)
-#define NETX_SYSTEM_RES_CR_FIRMW_RES (1<<3)
-#define NETX_SYSTEM_RES_CR_XPEC0_RES (1<<4)
-#define NETX_SYSTEM_RES_CR_XPEC1_RES (1<<5)
-#define NETX_SYSTEM_RES_CR_XPEC2_RES (1<<6)
-#define NETX_SYSTEM_RES_CR_XPEC3_RES (1<<7)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG0 (1<<20)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG1 (1<<21)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG2 (1<<22)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG3 (1<<23)
-#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN (1<<24)
-#define NETX_SYSTEM_RES_CR_RSTOUT (1<<25)
-#define NETX_SYSTEM_RES_CR_EN_RSTOUT (1<<26)
-
-#define PHY_CONTROL_RESET (1<<31)
-#define PHY_CONTROL_SIM_BYP (1<<30)
-#define PHY_CONTROL_CLK_XLATIN (1<<29)
-#define PHY_CONTROL_PHY1_EN (1<<21)
-#define PHY_CONTROL_PHY1_NP_MSG_CODE
-#define PHY_CONTROL_PHY1_AUTOMDIX (1<<17)
-#define PHY_CONTROL_PHY1_FIXMODE (1<<16)
-#define PHY_CONTROL_PHY1_MODE(mode) (((mode) & 0x7) << 13)
-#define PHY_CONTROL_PHY0_EN (1<<12)
-#define PHY_CONTROL_PHY0_NP_MSG_CODE
-#define PHY_CONTROL_PHY0_AUTOMDIX (1<<8)
-#define PHY_CONTROL_PHY0_FIXMODE (1<<7)
-#define PHY_CONTROL_PHY0_MODE(mode) (((mode) & 0x7) << 4)
-#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf)
-
-#define PHY_MODE_10BASE_T_HALF 0
-#define PHY_MODE_10BASE_T_FULL 1
-#define PHY_MODE_100BASE_TX_FX_FULL 2
-#define PHY_MODE_100BASE_TX_FX_HALF 3
-#define PHY_MODE_100BASE_TX_HALF 4
-#define PHY_MODE_REPEATER 5
-#define PHY_MODE_POWER_DOWN 6
-#define PHY_MODE_ALL 7
-
-/* Bits */
-#define VECT_CNTL_ENABLE (1 << 5)
-
-/*******************************
- * GPIO and timer module *
- *******************************/
-
-/* Registers */
-#define NETX_GPIO_REG(ofs) IOMEM(NETX_VA_GPIO + (ofs))
-#define NETX_GPIO_CFG(gpio) NETX_GPIO_REG(0x0 + ((gpio)<<2))
-#define NETX_GPIO_THRESHOLD_CAPTURE(gpio) NETX_GPIO_REG(0x40 + ((gpio)<<2))
-#define NETX_GPIO_COUNTER_CTRL(counter) NETX_GPIO_REG(0x80 + ((counter)<<2))
-#define NETX_GPIO_COUNTER_MAX(counter) NETX_GPIO_REG(0x94 + ((counter)<<2))
-#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2))
-#define NETX_GPIO_IRQ_ENABLE NETX_GPIO_REG(0xbc)
-#define NETX_GPIO_IRQ_DISABLE NETX_GPIO_REG(0xc0)
-#define NETX_GPIO_SYSTIME_NS_CMP NETX_GPIO_REG(0xc4)
-#define NETX_GPIO_LINE NETX_GPIO_REG(0xc8)
-#define NETX_GPIO_IRQ NETX_GPIO_REG(0xd0)
-
-/* Bits */
-#define NETX_GPIO_CFG_IOCFG_GP_INPUT (0x0)
-#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT (0x1)
-#define NETX_GPIO_CFG_IOCFG_GP_UART (0x2)
-#define NETX_GPIO_CFG_INV (1<<2)
-#define NETX_GPIO_CFG_MODE_INPUT_READ (0<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL (3<<3)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER0 (0<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER1 (1<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER2 (2<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER3 (3<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER4 (4<<5)
-#define NETX_GPIO_CFG_COUNT_REF_SYSTIME (7<<5)
-
-#define NETX_GPIO_COUNTER_CTRL_RUN (1<<0)
-#define NETX_GPIO_COUNTER_CTRL_SYM (1<<1)
-#define NETX_GPIO_COUNTER_CTRL_ONCE (1<<2)
-#define NETX_GPIO_COUNTER_CTRL_IRQ_EN (1<<3)
-#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT (1<<4)
-#define NETX_GPIO_COUNTER_CTRL_RST_EN (1<<5)
-#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT (1<<6)
-#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */
-
-#define GPIO_BIT(gpio) (1<<(gpio))
-#define COUNTER_BIT(counter) ((1<<16)<<(counter))
-
-/*******************************
- * PIO *
- *******************************/
-
-/* Registers */
-#define NETX_PIO_REG(ofs) IOMEM(NETX_VA_PIO + (ofs))
-#define NETX_PIO_INPIO NETX_PIO_REG(0x0)
-#define NETX_PIO_OUTPIO NETX_PIO_REG(0x4)
-#define NETX_PIO_OEPIO NETX_PIO_REG(0x8)
-
-/*******************************
- * MII Unit *
- *******************************/
-
-/* Registers */
-#define NETX_MIIMU IOMEM(NETX_VA_MIIMU)
-
-/* Bits */
-#define MIIMU_SNRDY (1<<0)
-#define MIIMU_PREAMBLE (1<<1)
-#define MIIMU_OPMODE_WRITE (1<<2)
-#define MIIMU_MDC_PERIOD (1<<3)
-#define MIIMU_PHY_NRES (1<<4)
-#define MIIMU_RTA (1<<5)
-#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6)
-#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11)
-#define MIIMU_DATA(data) (((data) & 0xffff) << 16)
-
-/*******************************
- * xmac / xpec *
- *******************************/
-
-/* XPEC register offsets relative to NETX_VA_XPEC(no) */
-#define NETX_XPEC_R0_OFS 0x00
-#define NETX_XPEC_R1_OFS 0x04
-#define NETX_XPEC_R2_OFS 0x08
-#define NETX_XPEC_R3_OFS 0x0c
-#define NETX_XPEC_R4_OFS 0x10
-#define NETX_XPEC_R5_OFS 0x14
-#define NETX_XPEC_R6_OFS 0x18
-#define NETX_XPEC_R7_OFS 0x1c
-#define NETX_XPEC_RANGE01_OFS 0x20
-#define NETX_XPEC_RANGE23_OFS 0x24
-#define NETX_XPEC_RANGE45_OFS 0x28
-#define NETX_XPEC_RANGE67_OFS 0x2c
-#define NETX_XPEC_PC_OFS 0x48
-#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2))
-#define NETX_XPEC_IRQ_OFS 0x8c
-#define NETX_XPEC_SYSTIME_NS_OFS 0x90
-#define NETX_XPEC_FIFO_DATA_OFS 0x94
-#define NETX_XPEC_SYSTIME_S_OFS 0x98
-#define NETX_XPEC_ADC_OFS 0x9c
-#define NETX_XPEC_URX_COUNT_OFS 0x40
-#define NETX_XPEC_UTX_COUNT_OFS 0x44
-#define NETX_XPEC_PC_OFS 0x48
-#define NETX_XPEC_ZERO_OFS 0x4c
-#define NETX_XPEC_STATCFG_OFS 0x50
-#define NETX_XPEC_EC_MASKA_OFS 0x54
-#define NETX_XPEC_EC_MASKB_OFS 0x58
-#define NETX_XPEC_EC_MASK0_OFS 0x5c
-#define NETX_XPEC_EC_MASK8_OFS 0x7c
-#define NETX_XPEC_EC_MASK9_OFS 0x80
-#define NETX_XPEC_XPU_HOLD_PC_OFS 0x100
-#define NETX_XPEC_RAM_START_OFS 0x2000
-
-/* Bits */
-#define XPU_HOLD_PC (1<<0)
-
-/* XMAC register offsets relative to NETX_VA_XMAC(no) */
-#define NETX_XMAC_RPU_PROGRAM_START_OFS 0x000
-#define NETX_XMAC_RPU_PROGRAM_END_OFS 0x3ff
-#define NETX_XMAC_TPU_PROGRAM_START_OFS 0x400
-#define NETX_XMAC_TPU_PROGRAM_END_OFS 0x7ff
-#define NETX_XMAC_RPU_HOLD_PC_OFS 0xa00
-#define NETX_XMAC_TPU_HOLD_PC_OFS 0xa04
-#define NETX_XMAC_STATUS_SHARED0_OFS 0x840
-#define NETX_XMAC_CONFIG_SHARED0_OFS 0x844
-#define NETX_XMAC_STATUS_SHARED1_OFS 0x848
-#define NETX_XMAC_CONFIG_SHARED1_OFS 0x84c
-#define NETX_XMAC_STATUS_SHARED2_OFS 0x850
-#define NETX_XMAC_CONFIG_SHARED2_OFS 0x854
-#define NETX_XMAC_STATUS_SHARED3_OFS 0x858
-#define NETX_XMAC_CONFIG_SHARED3_OFS 0x85c
-
-#define RPU_HOLD_PC (1<<15)
-#define TPU_HOLD_PC (1<<15)
-
-/*******************************
- * Pointer FIFO *
- *******************************/
-
-/* Registers */
-#define NETX_PFIFO_REG(ofs) IOMEM(NETX_VA_PFIFO + (ofs))
-#define NETX_PFIFO_BASE(pfifo) NETX_PFIFO_REG(0x00 + ((pfifo)<<2))
-#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2))
-#define NETX_PFIFO_RESET NETX_PFIFO_REG(0x100)
-#define NETX_PFIFO_FULL NETX_PFIFO_REG(0x104)
-#define NETX_PFIFO_EMPTY NETX_PFIFO_REG(0x108)
-#define NETX_PFIFO_OVEFLOW NETX_PFIFO_REG(0x10c)
-#define NETX_PFIFO_UNDERRUN NETX_PFIFO_REG(0x110)
-#define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2))
-#define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2))
-
-
-/*******************************
- * Memory Controller *
- *******************************/
-
-/* Registers */
-#define NETX_MEMCR_REG(ofs) IOMEM(NETX_VA_MEMCR + (ofs))
-#define NETX_MEMCR_SRAM_CTRL(cs) NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */
-#define NETX_MEMCR_SDRAM_CFG_CTRL NETX_MEMCR_REG(0x40)
-#define NETX_MEMCR_SDRAM_TIMING_CTRL NETX_MEMCR_REG(0x44)
-#define NETX_MEMCR_SDRAM_MODE NETX_MEMCR_REG(0x48)
-#define NETX_MEMCR_SDRAM_EXT_MODE NETX_MEMCR_REG(0x4c)
-#define NETX_MEMCR_PRIO_TIMESLOT_CTRL NETX_MEMCR_REG(0x80)
-#define NETX_MEMCR_PRIO_ACCESS_CTRL NETX_MEMCR_REG(0x84)
-
-/* Bits */
-#define NETX_MEMCR_SRAM_CTRL_WIDTHEXTMEM(x) (((x) & 0x3) << 24)
-#define NETX_MEMCR_SRAM_CTRL_WSPOSTPAUSEEXTMEM(x) (((x) & 0x3) << 16)
-#define NETX_MEMCR_SRAM_CTRL_WSPREPASEEXTMEM(x) (((x) & 0x3) << 8)
-#define NETX_MEMCR_SRAM_CTRL_WSEXTMEM(x) (((x) & 0x1f) << 0)
-
-
-/*******************************
- * Dual Port Memory *
- *******************************/
-
-/* Registers */
-#define NETX_DPMAS_REG(ofs) IOMEM(NETX_VA_DPMAS + (ofs))
-#define NETX_DPMAS_SYS_STAT NETX_DPMAS_REG(0x4d8)
-#define NETX_DPMAS_INT_STAT NETX_DPMAS_REG(0x4e0)
-#define NETX_DPMAS_INT_EN NETX_DPMAS_REG(0x4f0)
-#define NETX_DPMAS_IF_CONF0 NETX_DPMAS_REG(0x608)
-#define NETX_DPMAS_IF_CONF1 NETX_DPMAS_REG(0x60c)
-#define NETX_DPMAS_EXT_CONFIG(cs) NETX_DPMAS_REG(0x610 + 4 * (cs))
-#define NETX_DPMAS_IO_MODE0 NETX_DPMAS_REG(0x620) /* I/O 32..63 */
-#define NETX_DPMAS_DRV_EN0 NETX_DPMAS_REG(0x624)
-#define NETX_DPMAS_DATA0 NETX_DPMAS_REG(0x628)
-#define NETX_DPMAS_IO_MODE1 NETX_DPMAS_REG(0x630) /* I/O 64..84 */
-#define NETX_DPMAS_DRV_EN1 NETX_DPMAS_REG(0x634)
-#define NETX_DPMAS_DATA1 NETX_DPMAS_REG(0x638)
-
-/* Bits */
-#define NETX_DPMAS_INT_EN_GLB_EN (1<<31)
-#define NETX_DPMAS_INT_EN_MEM_LCK (1<<30)
-#define NETX_DPMAS_INT_EN_WDG (1<<29)
-#define NETX_DPMAS_INT_EN_PIO72 (1<<28)
-#define NETX_DPMAS_INT_EN_PIO47 (1<<27)
-#define NETX_DPMAS_INT_EN_PIO40 (1<<26)
-#define NETX_DPMAS_INT_EN_PIO36 (1<<25)
-#define NETX_DPMAS_INT_EN_PIO35 (1<<24)
-
-#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS (1<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT (2<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_IO (4<<28)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP (1<<14)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD (2<<14)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14)
-
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30)
-
-#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29)
-#define NETX_EXT_CONFIG_TADRHOLD(x) (((x) & 0x7) << 26)
-#define NETX_EXT_CONFIG_TCSON(x) (((x) & 0x7) << 23)
-#define NETX_EXT_CONFIG_TRDON(x) (((x) & 0x7) << 20)
-#define NETX_EXT_CONFIG_TWRON(x) (((x) & 0x7) << 17)
-#define NETX_EXT_CONFIG_TWROFF(x) (((x) & 0x1f) << 12)
-#define NETX_EXT_CONFIG_TRDWRCYC(x) (((x) & 0x1f) << 7)
-#define NETX_EXT_CONFIG_WAIT_POL (1<<6)
-#define NETX_EXT_CONFIG_WAIT_EN (1<<5)
-#define NETX_EXT_CONFIG_NRD_MODE (1<<4)
-#define NETX_EXT_CONFIG_DS_MODE (1<<3)
-#define NETX_EXT_CONFIG_NWR_MODE (1<<2)
-#define NETX_EXT_CONFIG_16BIT (1<<1)
-#define NETX_EXT_CONFIG_CS_ENABLE (1<<0)
-
-#define NETX_DPMAS_IO_MODE0_WRL (1<<13)
-#define NETX_DPMAS_IO_MODE0_WAIT (1<<14)
-#define NETX_DPMAS_IO_MODE0_READY (1<<15)
-#define NETX_DPMAS_IO_MODE0_CS0 (1<<19)
-#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20)
-
-#define NETX_DPMAS_IO_MODE1_CS2 (1<<15)
-#define NETX_DPMAS_IO_MODE1_CS1 (1<<16)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR (0<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36 (3<<30)
-
-/*******************************
- * I2C *
- *******************************/
-#define NETX_I2C_REG(ofs) IOMEM(NETX_VA_I2C, (ofs))
-#define NETX_I2C_CTRL NETX_I2C_REG(0x0)
-#define NETX_I2C_DATA NETX_I2C_REG(0x4)
-
-#endif /* __ASM_ARCH_NETX_REGS_H */
diff --git a/arch/arm/mach-netx/include/mach/pfifo.h b/arch/arm/mach-netx/include/mach/pfifo.h
deleted file mode 100644
index de23180bc937..000000000000
--- a/arch/arm/mach-netx/include/mach/pfifo.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/pfifo.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-
-#ifndef ASM_ARCH_PFIFO_H
-#define ASM_ARCH_PFIFO_H
-
-static inline int pfifo_push(int no, unsigned int pointer)
-{
- writel(pointer, NETX_PFIFO_BASE(no));
- return 0;
-}
-
-static inline unsigned int pfifo_pop(int no)
-{
- return readl(NETX_PFIFO_BASE(no));
-}
-
-static inline int pfifo_fill_level(int no)
-{
-
- return readl(NETX_PFIFO_FILL_LEVEL(no));
-}
-
-static inline int pfifo_full(int no)
-{
- return readl(NETX_PFIFO_FULL) & (1<<no) ? 1 : 0;
-}
-
-static inline int pfifo_empty(int no)
-{
- return readl(NETX_PFIFO_EMPTY) & (1<<no) ? 1 : 0;
-}
-
-int pfifo_request(unsigned int pfifo_mask);
-void pfifo_free(unsigned int pfifo_mask);
-
-#endif /* ASM_ARCH_PFIFO_H */
diff --git a/arch/arm/mach-netx/include/mach/uncompress.h b/arch/arm/mach-netx/include/mach/uncompress.h
deleted file mode 100644
index edc1ac997eab..000000000000
--- a/arch/arm/mach-netx/include/mach/uncompress.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/uncompress.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader. We search for the first enabled
- * port in the most probable order. If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-
-#define REG(x) (*(volatile unsigned long *)(x))
-
-#define UART1_BASE 0x100a00
-#define UART2_BASE 0x100a80
-
-#define UART_DR 0x0
-
-#define UART_CR 0x14
-#define CR_UART_EN (1<<0)
-
-#define UART_FR 0x18
-#define FR_BUSY (1<<3)
-#define FR_TXFF (1<<5)
-
-static inline void putc(char c)
-{
- unsigned long base;
-
- if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
- base = UART1_BASE;
- else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
- base = UART2_BASE;
- else
- return;
-
- while (REG(base + UART_FR) & FR_TXFF);
- REG(base + UART_DR) = c;
-}
-
-static inline void flush(void)
-{
- unsigned long base;
-
- if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
- base = UART1_BASE;
- else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
- base = UART2_BASE;
- else
- return;
-
- while (REG(base + UART_FR) & FR_BUSY);
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-netx/include/mach/xc.h b/arch/arm/mach-netx/include/mach/xc.h
deleted file mode 100644
index 465d5e250ab8..000000000000
--- a/arch/arm/mach-netx/include/mach/xc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/xc.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#ifndef __ASM_ARCH_XC_H
-#define __ASM_ARCH_XC_H
-
-struct xc {
- int no;
- unsigned int type;
- unsigned int version;
- void __iomem *xpec_base;
- void __iomem *xmac_base;
- void __iomem *sram_base;
- int irq;
- struct device *dev;
-};
-
-int xc_reset(struct xc *x);
-int xc_stop(struct xc* x);
-int xc_start(struct xc *x);
-int xc_running(struct xc *x);
-int xc_request_firmware(struct xc* x);
-struct xc* request_xc(int xcno, struct device *dev);
-void free_xc(struct xc *x);
-
-#endif /* __ASM_ARCH_XC_H */
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
deleted file mode 100644
index ad5e6747b834..000000000000
--- a/arch/arm/mach-netx/nxdb500.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxdb500.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-#include "fb.h"
-
-static struct clcd_panel qvga = {
- .mode = {
- .name = "QVGA",
- .refresh = 60,
- .xres = 240,
- .yres = 320,
- .pixclock = 187617,
- .left_margin = 6,
- .right_margin = 26,
- .upper_margin = 0,
- .lower_margin = 6,
- .hsync_len = 6,
- .vsync_len = 1,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
- },
- .width = -1,
- .height = -1,
- .tim2 = 16,
- .cntl = CNTL_LCDTFT | CNTL_BGR,
- .bpp = 16,
- .grayscale = 0,
-};
-
-static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
-{
- var->green.length = 5;
- var->green.msb_right = 0;
-
- return clcdfb_check(fb, var);
-}
-
-static int nxdb500_clcd_setup(struct clcd_fb *fb)
-{
- unsigned int val;
-
- fb->fb.var.green.length = 5;
- fb->fb.var.green.msb_right = 0;
-
- /* enable asic control */
- val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
- writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
-
- writel(3, NETX_SYSTEM_IOC_CR);
-
- val = readl(NETX_PIO_OUTPIO);
- writel(val | 1, NETX_PIO_OUTPIO);
-
- val = readl(NETX_PIO_OEPIO);
- writel(val | 1, NETX_PIO_OEPIO);
- return netx_clcd_setup(fb);
-}
-
-static struct clcd_board clcd_data = {
- .name = "netX",
- .check = nxdb500_check,
- .decode = clcdfb_decode,
- .enable = netx_clcd_enable,
- .setup = nxdb500_clcd_setup,
- .mmap = netx_clcd_mmap,
- .remove = netx_clcd_remove,
-};
-
-static struct netxeth_platform_data eth0_platform_data = {
- .xcno = 0,
-};
-
-static struct platform_device netx_eth0_device = {
- .name = "netx-eth",
- .id = 0,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth0_platform_data,
- }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
- .xcno = 1,
-};
-
-static struct platform_device netx_eth1_device = {
- .name = "netx-eth",
- .id = 1,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth1_platform_data,
- }
-};
-
-static struct resource netx_uart0_resources[] = {
- [0] = {
- .start = 0x00100A00,
- .end = 0x00100A3F,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (NETX_IRQ_UART0),
- .end = (NETX_IRQ_UART0),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netx_uart0_device = {
- .name = "netx-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(netx_uart0_resources),
- .resource = netx_uart0_resources,
-};
-
-static struct resource netx_uart1_resources[] = {
- [0] = {
- .start = 0x00100A40,
- .end = 0x00100A7F,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (NETX_IRQ_UART1),
- .end = (NETX_IRQ_UART1),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netx_uart1_device = {
- .name = "netx-uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(netx_uart1_resources),
- .resource = netx_uart1_resources,
-};
-
-static struct resource netx_uart2_resources[] = {
- [0] = {
- .start = 0x00100A80,
- .end = 0x00100ABF,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (NETX_IRQ_UART2),
- .end = (NETX_IRQ_UART2),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netx_uart2_device = {
- .name = "netx-uart",
- .id = 2,
- .num_resources = ARRAY_SIZE(netx_uart2_resources),
- .resource = netx_uart2_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
- &netx_eth0_device,
- &netx_eth1_device,
- &netx_uart0_device,
- &netx_uart1_device,
- &netx_uart2_device,
-};
-
-static void __init nxdb500_init(void)
-{
- netx_fb_init(&clcd_data, &qvga);
- platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXDB500, "Hilscher nxdb500")
- .atag_offset = 0x100,
- .map_io = netx_map_io,
- .init_irq = netx_init_irq,
- .init_time = netx_timer_init,
- .init_machine = nxdb500_init,
- .restart = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
deleted file mode 100644
index 917381559628..000000000000
--- a/arch/arm/mach-netx/nxdkn.c
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxdkn.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-
-static struct netxeth_platform_data eth0_platform_data = {
- .xcno = 0,
-};
-
-static struct platform_device nxdkn_eth0_device = {
- .name = "netx-eth",
- .id = 0,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth0_platform_data,
- }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
- .xcno = 1,
-};
-
-static struct platform_device nxdkn_eth1_device = {
- .name = "netx-eth",
- .id = 1,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth1_platform_data,
- }
-};
-
-static struct resource netx_uart0_resources[] = {
- [0] = {
- .start = 0x00100A00,
- .end = 0x00100A3F,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (NETX_IRQ_UART0),
- .end = (NETX_IRQ_UART0),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netx_uart0_device = {
- .name = "netx-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(netx_uart0_resources),
- .resource = netx_uart0_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
- &nxdkn_eth0_device,
- &nxdkn_eth1_device,
- &netx_uart0_device,
-};
-
-static void __init nxdkn_init(void)
-{
- platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXDKN, "Hilscher nxdkn")
- .atag_offset = 0x100,
- .map_io = netx_map_io,
- .init_irq = netx_init_irq,
- .init_time = netx_timer_init,
- .init_machine = nxdkn_init,
- .restart = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
deleted file mode 100644
index aa0d5b2ca712..000000000000
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxeb500hmi.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-#include "fb.h"
-
-static struct clcd_panel qvga = {
- .mode = {
- .name = "QVGA",
- .refresh = 60,
- .xres = 240,
- .yres = 320,
- .pixclock = 187617,
- .left_margin = 6,
- .right_margin = 26,
- .upper_margin = 0,
- .lower_margin = 6,
- .hsync_len = 6,
- .vsync_len = 1,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
- },
- .width = -1,
- .height = -1,
- .tim2 = 16,
- .cntl = CNTL_LCDTFT | CNTL_BGR,
- .bpp = 16,
- .grayscale = 0,
-};
-
-static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
-{
- var->green.length = 5;
- var->green.msb_right = 0;
-
- return clcdfb_check(fb, var);
-}
-
-static int nxeb500hmi_clcd_setup(struct clcd_fb *fb)
-{
- unsigned int val;
-
- fb->fb.var.green.length = 5;
- fb->fb.var.green.msb_right = 0;
-
- /* enable asic control */
- val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
- writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
-
- writel(3, NETX_SYSTEM_IOC_CR);
-
- /* GPIO 14 is used for display enable on newer boards */
- writel(9, NETX_GPIO_CFG(14));
-
- val = readl(NETX_PIO_OUTPIO);
- writel(val | 1, NETX_PIO_OUTPIO);
-
- val = readl(NETX_PIO_OEPIO);
- writel(val | 1, NETX_PIO_OEPIO);
- return netx_clcd_setup(fb);
-}
-
-static struct clcd_board clcd_data = {
- .name = "netX",
- .check = nxeb500hmi_check,
- .decode = clcdfb_decode,
- .enable = netx_clcd_enable,
- .setup = nxeb500hmi_clcd_setup,
- .mmap = netx_clcd_mmap,
- .remove = netx_clcd_remove,
-};
-
-static struct netxeth_platform_data eth0_platform_data = {
- .xcno = 0,
-};
-
-static struct platform_device netx_eth0_device = {
- .name = "netx-eth",
- .id = 0,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth0_platform_data,
- }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
- .xcno = 1,
-};
-
-static struct platform_device netx_eth1_device = {
- .name = "netx-eth",
- .id = 1,
- .num_resources = 0,
- .resource = NULL,
- .dev = {
- .platform_data = &eth1_platform_data,
- }
-};
-
-static struct resource netx_cf_resources[] = {
- [0] = {
- .start = 0x20000000,
- .end = 0x25ffffff,
- .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
- },
-};
-
-static struct platform_device netx_cf_device = {
- .name = "netx-cf",
- .id = 0,
- .resource = netx_cf_resources,
- .num_resources = ARRAY_SIZE(netx_cf_resources),
-};
-
-static struct resource netx_uart0_resources[] = {
- [0] = {
- .start = 0x00100A00,
- .end = 0x00100A3F,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (NETX_IRQ_UART0),
- .end = (NETX_IRQ_UART0),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netx_uart0_device = {
- .name = "netx-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(netx_uart0_resources),
- .resource = netx_uart0_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
- &netx_eth0_device,
- &netx_eth1_device,
- &netx_cf_device,
- &netx_uart0_device,
-};
-
-static void __init nxeb500hmi_init(void)
-{
- netx_fb_init(&clcd_data, &qvga);
- platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
- .atag_offset = 0x100,
- .map_io = netx_map_io,
- .init_irq = netx_init_irq,
- .init_time = netx_timer_init,
- .init_machine = nxeb500hmi_init,
- .restart = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c
deleted file mode 100644
index 2e5cc777329f..000000000000
--- a/arch/arm/mach-netx/pfifo.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/pfifo.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/netx-regs.h>
-#include <mach/pfifo.h>
-
-static DEFINE_MUTEX(pfifo_lock);
-
-static unsigned int pfifo_used = 0;
-
-int pfifo_request(unsigned int pfifo_mask)
-{
- int err = 0;
- unsigned int val;
-
- mutex_lock(&pfifo_lock);
-
- if (pfifo_mask & pfifo_used) {
- err = -EBUSY;
- goto out;
- }
-
- pfifo_used |= pfifo_mask;
-
- val = readl(NETX_PFIFO_RESET);
- writel(val | pfifo_mask, NETX_PFIFO_RESET);
- writel(val, NETX_PFIFO_RESET);
-
-out:
- mutex_unlock(&pfifo_lock);
- return err;
-}
-
-void pfifo_free(unsigned int pfifo_mask)
-{
- mutex_lock(&pfifo_lock);
- pfifo_used &= ~pfifo_mask;
- mutex_unlock(&pfifo_lock);
-}
-
-EXPORT_SYMBOL(pfifo_push);
-EXPORT_SYMBOL(pfifo_pop);
-EXPORT_SYMBOL(pfifo_fill_level);
-EXPORT_SYMBOL(pfifo_empty);
-EXPORT_SYMBOL(pfifo_request);
-EXPORT_SYMBOL(pfifo_free);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
deleted file mode 100644
index d9defa1ab605..000000000000
--- a/arch/arm/mach-netx/time.c
+++ /dev/null
@@ -1,141 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/time.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/time.h>
-#include <mach/netx-regs.h>
-
-#define NETX_CLOCK_FREQ 100000000
-#define NETX_LATCH DIV_ROUND_CLOSEST(NETX_CLOCK_FREQ, HZ)
-
-#define TIMER_CLOCKEVENT 0
-#define TIMER_CLOCKSOURCE 1
-
-static inline void timer_shutdown(struct clock_event_device *evt)
-{
- /* disable timer */
- writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-}
-
-static int netx_shutdown(struct clock_event_device *evt)
-{
- timer_shutdown(evt);
-
- return 0;
-}
-
-static int netx_set_oneshot(struct clock_event_device *evt)
-{
- u32 tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
-
- timer_shutdown(evt);
- writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
- writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-
- return 0;
-}
-
-static int netx_set_periodic(struct clock_event_device *evt)
-{
- u32 tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
- NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
-
- timer_shutdown(evt);
- writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
- writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-
- return 0;
-}
-
-static int netx_set_next_event(unsigned long evt,
- struct clock_event_device *clk)
-{
- writel(0 - evt, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKEVENT));
- return 0;
-}
-
-static struct clock_event_device netx_clockevent = {
- .name = "netx-timer" __stringify(TIMER_CLOCKEVENT),
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = netx_set_next_event,
- .set_state_shutdown = netx_shutdown,
- .set_state_periodic = netx_set_periodic,
- .set_state_oneshot = netx_set_oneshot,
- .tick_resume = netx_shutdown,
-};
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-netx_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &netx_clockevent;
-
- /* acknowledge interrupt */
- writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
-
- evt->event_handler(evt);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction netx_timer_irq = {
- .name = "NetX Timer Tick",
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
- .handler = netx_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt
- */
-void __init netx_timer_init(void)
-{
- /* disable timer initially */
- writel(0, NETX_GPIO_COUNTER_CTRL(0));
-
- /* Reset the timer value to zero */
- writel(0, NETX_GPIO_COUNTER_CURRENT(0));
-
- writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(0));
-
- /* acknowledge interrupt */
- writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
-
- /* Enable the interrupt in the specific timer
- * register and start timer
- */
- writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE);
- writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN,
- NETX_GPIO_COUNTER_CTRL(0));
-
- setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
-
- /* Setup timer one for clocksource */
- writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
- writel(0, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE));
- writel(0xffffffff, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKSOURCE));
-
- writel(NETX_GPIO_COUNTER_CTRL_RUN,
- NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
-
- clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
- "netx_timer", NETX_CLOCK_FREQ, 200, 32, clocksource_mmio_readl_up);
-
- /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine.
- * Adding some safety ... */
- netx_clockevent.cpumask = cpumask_of(0);
- clockevents_config_and_register(&netx_clockevent, NETX_CLOCK_FREQ,
- 0xa00, 0xfffffffe);
-}
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
deleted file mode 100644
index 885a618b2651..000000000000
--- a/arch/arm/mach-netx/xc.c
+++ /dev/null
@@ -1,246 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/xc.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/export.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/netx-regs.h>
-
-#include <mach/xc.h>
-
-static DEFINE_MUTEX(xc_lock);
-
-static int xc_in_use = 0;
-
-struct fw_desc {
- unsigned int ofs;
- unsigned int size;
- unsigned int patch_ofs;
- unsigned int patch_entries;
-};
-
-struct fw_header {
- unsigned int magic;
- unsigned int type;
- unsigned int version;
- unsigned int reserved[5];
- struct fw_desc fw_desc[3];
-} __attribute__ ((packed));
-
-int xc_stop(struct xc *x)
-{
- writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
- writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
- writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
- return 0;
-}
-
-int xc_start(struct xc *x)
-{
- writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
- writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
- writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
- return 0;
-}
-
-int xc_running(struct xc *x)
-{
- return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC)
- || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC)
- || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ?
- 0 : 1;
-}
-
-int xc_reset(struct xc *x)
-{
- writel(0, x->xpec_base + NETX_XPEC_PC_OFS);
- return 0;
-}
-
-static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size)
-{
- if (adr >= NETX_PA_XMAC(x->no) &&
- adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE)
- return 0;
-
- if (adr >= NETX_PA_XPEC(x->no) &&
- adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE)
- return 0;
-
- dev_err(x->dev, "Illegal pointer in firmware found. aborting\n");
-
- return -1;
-}
-
-static int xc_patch(struct xc *x, const void *patch, int count)
-{
- unsigned int val, adr;
- const unsigned int *data = patch;
-
- int i;
- for (i = 0; i < count; i++) {
- adr = *data++;
- val = *data++;
- if (xc_check_ptr(x, adr, 4) < 0)
- return -EINVAL;
-
- writel(val, (void __iomem *)io_p2v(adr));
- }
- return 0;
-}
-
-int xc_request_firmware(struct xc *x)
-{
- int ret;
- char name[16];
- const struct firmware *fw;
- struct fw_header *head;
- unsigned int size;
- int i;
- const void *src;
- unsigned long dst;
-
- sprintf(name, "xc%d.bin", x->no);
-
- ret = request_firmware(&fw, name, x->dev);
-
- if (ret < 0) {
- dev_err(x->dev, "request_firmware failed\n");
- return ret;
- }
-
- head = (struct fw_header *)fw->data;
- if (head->magic != 0x4e657458) {
- if (head->magic == 0x5874654e) {
- dev_err(x->dev,
- "firmware magic is 'XteN'. Endianness problems?\n");
- ret = -ENODEV;
- goto exit_release_firmware;
- }
- dev_err(x->dev, "unrecognized firmware magic 0x%08x\n",
- head->magic);
- ret = -ENODEV;
- goto exit_release_firmware;
- }
-
- x->type = head->type;
- x->version = head->version;
-
- ret = -EINVAL;
-
- for (i = 0; i < 3; i++) {
- src = fw->data + head->fw_desc[i].ofs;
- dst = *(unsigned int *)src;
- src += sizeof (unsigned int);
- size = head->fw_desc[i].size - sizeof (unsigned int);
-
- if (xc_check_ptr(x, dst, size))
- goto exit_release_firmware;
-
- memcpy((void *)io_p2v(dst), src, size);
-
- src = fw->data + head->fw_desc[i].patch_ofs;
- size = head->fw_desc[i].patch_entries;
- ret = xc_patch(x, src, size);
- if (ret < 0)
- goto exit_release_firmware;
- }
-
- ret = 0;
-
- exit_release_firmware:
- release_firmware(fw);
-
- return ret;
-}
-
-struct xc *request_xc(int xcno, struct device *dev)
-{
- struct xc *x = NULL;
-
- mutex_lock(&xc_lock);
-
- if (xcno > 3)
- goto exit;
- if (xc_in_use & (1 << xcno))
- goto exit;
-
- x = kmalloc(sizeof (struct xc), GFP_KERNEL);
- if (!x)
- goto exit;
-
- if (!request_mem_region
- (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, kobject_name(&dev->kobj)))
- goto exit_free;
-
- if (!request_mem_region
- (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, kobject_name(&dev->kobj)))
- goto exit_release_1;
-
- if (!request_mem_region
- (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, kobject_name(&dev->kobj)))
- goto exit_release_2;
-
- x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
- x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno));
- x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
- if (!x->sram_base)
- goto exit_release_3;
-
- x->irq = NETX_IRQ_XPEC(xcno);
-
- x->no = xcno;
- x->dev = dev;
-
- xc_in_use |= (1 << xcno);
-
- goto exit;
-
- exit_release_3:
- release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
- exit_release_2:
- release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
- exit_release_1:
- release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
- exit_free:
- kfree(x);
- x = NULL;
- exit:
- mutex_unlock(&xc_lock);
- return x;
-}
-
-void free_xc(struct xc *x)
-{
- int xcno = x->no;
-
- mutex_lock(&xc_lock);
-
- iounmap(x->sram_base);
- release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
- release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
- release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
- xc_in_use &= ~(1 << x->no);
- kfree(x);
-
- mutex_unlock(&xc_lock);
-}
-
-EXPORT_SYMBOL(free_xc);
-EXPORT_SYMBOL(request_xc);
-EXPORT_SYMBOL(xc_request_firmware);
-EXPORT_SYMBOL(xc_reset);
-EXPORT_SYMBOL(xc_running);
-EXPORT_SYMBOL(xc_start);
-EXPORT_SYMBOL(xc_stop);
diff --git a/arch/arm/mach-nspire/Makefile b/arch/arm/mach-nspire/Makefile
index 1d568c600452..4716b9b9aa7b 100644
--- a/arch/arm/mach-nspire/Makefile
+++ b/arch/arm/mach-nspire/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += nspire.o
-obj-y += clcd.o
diff --git a/arch/arm/mach-nspire/clcd.c b/arch/arm/mach-nspire/clcd.c
deleted file mode 100644
index 44738dcb391d..000000000000
--- a/arch/arm/mach-nspire/clcd.c
+++ /dev/null
@@ -1,114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-nspire/clcd.c
- *
- * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
- */
-
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <linux/dma-mapping.h>
-
-static struct clcd_panel nspire_cx_lcd_panel = {
- .mode = {
- .name = "Color LCD",
- .refresh = 60,
- .xres = 320,
- .yres = 240,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
- .pixclock = 1,
- .hsync_len = 6,
- .vsync_len = 1,
- .right_margin = 50,
- .left_margin = 38,
- .lower_margin = 3,
- .upper_margin = 17,
- },
- .width = 65, /* ~6.50 cm */
- .height = 49, /* ~4.87 cm */
- .tim2 = TIM2_IPC,
- .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
- .bpp = 16,
- .caps = CLCD_CAP_565,
-};
-
-static struct clcd_panel nspire_classic_lcd_panel = {
- .mode = {
- .name = "Grayscale LCD",
- .refresh = 60,
- .xres = 320,
- .yres = 240,
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED,
- .pixclock = 1,
- .hsync_len = 6,
- .vsync_len = 1,
- .right_margin = 6,
- .left_margin = 6,
- },
- .width = 71, /* 7.11cm */
- .height = 53, /* 5.33cm */
- .tim2 = 0x80007d0,
- .cntl = CNTL_LCDMONO8,
- .bpp = 8,
- .grayscale = 1,
- .caps = CLCD_CAP_5551,
-};
-
-int nspire_clcd_setup(struct clcd_fb *fb)
-{
- struct clcd_panel *panel;
- size_t panel_size;
- const char *type;
- dma_addr_t dma;
- int err;
-
- BUG_ON(!fb->dev->dev.of_node);
-
- err = of_property_read_string(fb->dev->dev.of_node, "lcd-type", &type);
- if (err) {
- pr_err("CLCD: Could not find lcd-type property\n");
- return err;
- }
-
- if (!strcmp(type, "cx")) {
- panel = &nspire_cx_lcd_panel;
- } else if (!strcmp(type, "classic")) {
- panel = &nspire_classic_lcd_panel;
- } else {
- pr_err("CLCD: Unknown lcd-type %s\n", type);
- return -EINVAL;
- }
-
- panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8;
- panel_size = ALIGN(panel_size, PAGE_SIZE);
-
- fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, panel_size, &dma,
- GFP_KERNEL);
-
- if (!fb->fb.screen_base) {
- pr_err("CLCD: unable to map framebuffer\n");
- return -ENOMEM;
- }
-
- fb->fb.fix.smem_start = dma;
- fb->fb.fix.smem_len = panel_size;
- fb->panel = panel;
-
- return 0;
-}
-
-int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
- return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
- fb->fb.fix.smem_start, fb->fb.fix.smem_len);
-}
-
-void nspire_clcd_remove(struct clcd_fb *fb)
-{
- dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
- fb->fb.fix.smem_start);
-}
diff --git a/arch/arm/mach-nspire/clcd.h b/arch/arm/mach-nspire/clcd.h
deleted file mode 100644
index 7f36bd8511c5..000000000000
--- a/arch/arm/mach-nspire/clcd.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/arm/mach-nspire/clcd.h
- *
- * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
- */
-
-int nspire_clcd_setup(struct clcd_fb *fb);
-int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
-void nspire_clcd_remove(struct clcd_fb *fb);
diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c
index 957bd0c0fbd5..2d4abb0288b9 100644
--- a/arch/arm/mach-nspire/nspire.c
+++ b/arch/arm/mach-nspire/nspire.c
@@ -12,14 +12,12 @@
#include <linux/irqchip/arm-vic.h>
#include <linux/clkdev.h>
#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include "mmio.h"
-#include "clcd.h"
static const char *const nspire_dt_match[] __initconst = {
"ti,nspire",
@@ -29,28 +27,6 @@ static const char *const nspire_dt_match[] __initconst = {
NULL,
};
-static struct clcd_board nspire_clcd_data = {
- .name = "LCD",
- .caps = CLCD_CAP_5551 | CLCD_CAP_565,
- .check = clcdfb_check,
- .decode = clcdfb_decode,
- .setup = nspire_clcd_setup,
- .mmap = nspire_clcd_mmap,
- .remove = nspire_clcd_remove,
-};
-
-
-static struct of_dev_auxdata nspire_auxdata[] __initdata = {
- OF_DEV_AUXDATA("arm,pl111", NSPIRE_LCD_PHYS_BASE,
- NULL, &nspire_clcd_data),
- { }
-};
-
-static void __init nspire_init(void)
-{
- of_platform_default_populate(NULL, nspire_auxdata, NULL);
-}
-
static void nspire_restart(enum reboot_mode mode, const char *cmd)
{
void __iomem *base = ioremap(NSPIRE_MISC_PHYS_BASE, SZ_4K);
@@ -62,6 +38,5 @@ static void nspire_restart(enum reboot_mode mode, const char *cmd)
DT_MACHINE_START(NSPIRE, "TI-NSPIRE")
.dt_compat = nspire_dt_match,
- .init_machine = nspire_init,
.restart = nspire_restart,
MACHINE_END
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index 81159af44862..14a6c3eb3298 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -126,6 +126,8 @@ restart:
orr r11, r11, r13 @ mask all requested interrupts
str r11, [r12, #OMAP1510_GPIO_INT_MASK]
+ str r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack all requested interrupts
+
ands r10, r13, #KEYBRD_CLK_MASK @ extract keyboard status - set?
beq hksw @ no - try next source
@@ -133,7 +135,6 @@ restart:
@@@@@@@@@@@@@@@@@@@@@@
@ Keyboard clock FIQ mode interrupt handler
@ r10 now contains KEYBRD_CLK_MASK, use it
- str r10, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack the interrupt
bic r11, r11, r10 @ unmask it
str r11, [r12, #OMAP1510_GPIO_INT_MASK]
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index 43899fa56674..0254eb9cf8c6 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -70,9 +70,7 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
* interrupts default to since commit 80ac93c27441
* requires interrupt already acked and unmasked.
*/
- if (irq_chip->irq_ack)
- irq_chip->irq_ack(d);
- if (irq_chip->irq_unmask)
+ if (!WARN_ON_ONCE(!irq_chip->irq_unmask))
irq_chip->irq_unmask(d);
}
for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
diff --git a/arch/arm/mach-omap2/.gitignore b/arch/arm/mach-omap2/.gitignore
new file mode 100644
index 000000000000..79a8d6ea7152
--- /dev/null
+++ b/arch/arm/mach-omap2/.gitignore
@@ -0,0 +1 @@
+pm-asm-offsets.h
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 600650551621..8f208197988f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -223,9 +223,12 @@ obj-y += omap_phy_internal.o
obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o
-include/generated/ti-pm-asm-offsets.h: arch/arm/mach-omap2/pm-asm-offsets.s FORCE
+$(obj)/pm-asm-offsets.h: $(obj)/pm-asm-offsets.s FORCE
$(call filechk,offsets,__TI_PM_ASM_OFFSETS_H__)
-$(obj)/sleep33xx.o $(obj)/sleep43xx.o: include/generated/ti-pm-asm-offsets.h
+$(obj)/sleep33xx.o $(obj)/sleep43xx.o: $(obj)/pm-asm-offsets.h
targets += pm-asm-offsets.s
+clean-files += pm-asm-offsets.h
+
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 14b9c13c1fa0..63423ea6a240 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -32,10 +32,8 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
char *hc_name;
hc_name = kzalloc(HSMMC_NAME_LEN + 1, GFP_KERNEL);
- if (!hc_name) {
- kfree(hc_name);
+ if (!hc_name)
return -ENOMEM;
- }
snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", c->mmc, 1);
mmc->name = hc_name;
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
new file mode 100644
index 000000000000..f1a6ece8108e
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * OMAP IOMMU quirks for various TI SoCs
+ *
+ * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Suman Anna <s-anna@ti.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "powerdomain.h"
+
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+ u8 *pwrst)
+{
+ struct powerdomain *pwrdm;
+ struct omap_device *od;
+ u8 next_pwrst;
+
+ od = to_omap_device(pdev);
+ if (!od)
+ return -ENODEV;
+
+ if (od->hwmods_cnt != 1)
+ return -EINVAL;
+
+ pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]);
+ if (!pwrdm)
+ return -EINVAL;
+
+ if (request)
+ *pwrst = pwrdm_read_next_pwrst(pwrdm);
+
+ if (*pwrst > PWRDM_POWER_RET)
+ return 0;
+
+ next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
+
+ return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+}
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index f9c02f9f1c92..5c3845730dbf 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -127,6 +127,9 @@ static int __init omap4_sram_init(void)
struct device_node *np;
struct gen_pool *sram_pool;
+ if (!soc_is_omap44xx() && !soc_is_omap54xx())
+ return 0;
+
np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
if (!np)
pr_warn("%s:Unable to allocate sram needed to handle errata I688\n",
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 4a5b4aee6615..1ec21e9ba1e9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -379,7 +379,8 @@ static struct omap_hwmod dra7xx_dcan2_hwmod = {
static struct omap_hwmod_class_sysconfig dra7xx_epwmss_sysc = {
.rev_offs = 0x0,
.sysc_offs = 0x4,
- .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET,
+ .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_RESET_STATUS,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_fields = &omap_hwmod_sysc_type2,
};
diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
index 68fee339d3f1..dc221249bc22 100644
--- a/arch/arm/mach-omap2/sleep33xx.S
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -6,7 +6,6 @@
* Dave Gerlach, Vaibhav Bedia
*/
-#include <generated/ti-pm-asm-offsets.h>
#include <linux/linkage.h>
#include <linux/platform_data/pm33xx.h>
#include <linux/ti-emif-sram.h>
@@ -15,6 +14,7 @@
#include "iomap.h"
#include "cm33xx.h"
+#include "pm-asm-offsets.h"
#define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED 0x00030000
#define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003
diff --git a/arch/arm/mach-omap2/sleep43xx.S b/arch/arm/mach-omap2/sleep43xx.S
index c1f4e4852644..90d2907a2eb2 100644
--- a/arch/arm/mach-omap2/sleep43xx.S
+++ b/arch/arm/mach-omap2/sleep43xx.S
@@ -6,7 +6,6 @@
* Dave Gerlach, Vaibhav Bedia
*/
-#include <generated/ti-pm-asm-offsets.h>
#include <linux/linkage.h>
#include <linux/ti-emif-sram.h>
#include <linux/platform_data/pm33xx.h>
@@ -19,6 +18,7 @@
#include "iomap.h"
#include "omap-secure.h"
#include "omap44xx.h"
+#include "pm-asm-offsets.h"
#include "prm33xx.h"
#include "prcm43xx.h"
diff --git a/arch/arm/mach-orion5x/orion5x.h b/arch/arm/mach-orion5x/orion5x.h
index 3364df331f01..2b66120fba86 100644
--- a/arch/arm/mach-orion5x/orion5x.h
+++ b/arch/arm/mach-orion5x/orion5x.h
@@ -31,13 +31,13 @@
* fc000000 device bus mappings (cs0/cs1)
*
* virt phys size
- * fe000000 f1000000 1M on-chip peripheral registers
+ * fec00000 f1000000 1M on-chip peripheral registers
* fee00000 f2000000 64K PCIe I/O space
* fee10000 f2100000 64K PCI I/O space
* fd000000 f0000000 16M PCIe WA space (Orion-1/Orion-NAS only)
****************************************************************************/
#define ORION5X_REGS_PHYS_BASE 0xf1000000
-#define ORION5X_REGS_VIRT_BASE IOMEM(0xfe000000)
+#define ORION5X_REGS_VIRT_BASE IOMEM(0xfec00000)
#define ORION5X_REGS_SIZE SZ_1M
#define ORION5X_PCIE_IO_PHYS_BASE 0xf2000000
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 0ce56ad754ce..ea2c84214bac 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -46,6 +46,7 @@ static int __init parse_tag_acorn(const struct tag *tag)
switch (tag->u.acorn.vram_pages) {
case 512:
vram_size += PAGE_SIZE * 256;
+ /* Fall through - ??? */
case 256:
vram_size += PAGE_SIZE * 256;
default:
diff --git a/arch/arm/mach-s3c64xx/setup-usb-phy.c b/arch/arm/mach-s3c64xx/setup-usb-phy.c
index 46a9e955607f..6aaaa1d8e8b9 100644
--- a/arch/arm/mach-s3c64xx/setup-usb-phy.c
+++ b/arch/arm/mach-s3c64xx/setup-usb-phy.c
@@ -15,6 +15,11 @@
#include "regs-sys.h"
#include "regs-usb-hsotg-phy.h"
+enum samsung_usb_phy_type {
+ USB_PHY_TYPE_DEVICE,
+ USB_PHY_TYPE_HOST,
+};
+
static int s3c_usb_otgphy_init(struct platform_device *pdev)
{
struct clk *xusbxti;
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 5a67a71f80cc..76a65df42d10 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -70,7 +70,7 @@ static void __init tegra_cpu_reset_handler_enable(void)
switch (err) {
case -ENOSYS:
tegra_cpu_reset_handler_set(reset_address);
- /* pass-through */
+ /* fall through */
case 0:
is_enabled = true;
break;
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 9580525102da..3875027ef8fc 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -110,7 +110,6 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd)
static const struct of_device_id u8500_local_bus_nodes[] = {
/* only create devices below soc node */
{ .compatible = "stericsson,db8500", },
- { .compatible = "stericsson,db8500-prcmu", },
{ .compatible = "simple-bus"},
{ },
};
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
index 0f5381d13494..354e0e7025ae 100644
--- a/arch/arm/mach-vexpress/spc.c
+++ b/arch/arm/mach-vexpress/spc.c
@@ -69,7 +69,7 @@
#define A7_PERFVAL_BASE 0xC30
/* Config interface control bits */
-#define SYSCFG_START (1 << 31)
+#define SYSCFG_START BIT(31)
#define SYSCFG_SCC (6 << 20)
#define SYSCFG_STAT (14 << 20)
@@ -162,7 +162,7 @@ void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set)
if (cluster >= MAX_CLUSTERS)
return;
- mask = 1 << cpu;
+ mask = BIT(cpu);
if (!cluster_is_a15(cluster))
mask <<= 4;
diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig
deleted file mode 100644
index b16ffc03bbe5..000000000000
--- a/arch/arm/mach-w90x900/Kconfig
+++ /dev/null
@@ -1,50 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-if ARCH_W90X900
-
-config CPU_W90P910
- bool
- help
- Support for W90P910 of Nuvoton W90X900 CPUs.
-
-config CPU_NUC950
- bool
- help
- Support for NUCP950 of Nuvoton NUC900 CPUs.
-
-config CPU_NUC960
- bool
- help
- Support for NUCP960 of Nuvoton NUC900 CPUs.
-
-menu "W90P910 Machines"
-
-config MACH_W90P910EVB
- bool "Nuvoton W90P910 Evaluation Board"
- default y
- select CPU_W90P910
- help
- Say Y here if you are using the Nuvoton W90P910EVB
-
-endmenu
-
-menu "NUC950 Machines"
-
-config MACH_W90P950EVB
- bool "Nuvoton NUC950 Evaluation Board"
- select CPU_NUC950
- help
- Say Y here if you are using the Nuvoton NUC950EVB
-
-endmenu
-
-menu "NUC960 Machines"
-
-config MACH_W90N960EVB
- bool "Nuvoton NUC960 Evaluation Board"
- select CPU_NUC960
- help
- Say Y here if you are using the Nuvoton NUC960EVB
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile
deleted file mode 100644
index 33b5bf53990f..000000000000
--- a/arch/arm/mach-w90x900/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y := irq.o time.o mfp.o gpio.o clock.o
-obj-y += clksel.o dev.o cpu.o
-# W90X900 CPU support files
-
-obj-$(CONFIG_CPU_W90P910) += nuc910.o
-obj-$(CONFIG_CPU_NUC950) += nuc950.o
-obj-$(CONFIG_CPU_NUC960) += nuc960.o
-
-# machine support
-
-obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o
-obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o
-obj-$(CONFIG_MACH_W90N960EVB) += mach-nuc960evb.o
diff --git a/arch/arm/mach-w90x900/Makefile.boot b/arch/arm/mach-w90x900/Makefile.boot
deleted file mode 100644
index 07d1b3b23ac0..000000000000
--- a/arch/arm/mach-w90x900/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-
diff --git a/arch/arm/mach-w90x900/clksel.c b/arch/arm/mach-w90x900/clksel.c
deleted file mode 100644
index b50577a5a840..000000000000
--- a/arch/arm/mach-w90x900/clksel.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/clksel.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-
-#define PLL0 0x00
-#define PLL1 0x01
-#define OTHER 0x02
-#define EXT 0x03
-#define MSOFFSET 0x0C
-#define ATAOFFSET 0x0a
-#define LCDOFFSET 0x06
-#define AUDOFFSET 0x04
-#define CPUOFFSET 0x00
-
-static DEFINE_MUTEX(clksel_sem);
-
-static void clock_source_select(const char *dev_id, unsigned int clkval)
-{
- unsigned int clksel, offset;
-
- clksel = __raw_readl(REG_CLKSEL);
-
- if (strcmp(dev_id, "nuc900-ms") == 0)
- offset = MSOFFSET;
- else if (strcmp(dev_id, "nuc900-atapi") == 0)
- offset = ATAOFFSET;
- else if (strcmp(dev_id, "nuc900-lcd") == 0)
- offset = LCDOFFSET;
- else if (strcmp(dev_id, "nuc900-ac97") == 0)
- offset = AUDOFFSET;
- else
- offset = CPUOFFSET;
-
- clksel &= ~(0x03 << offset);
- clksel |= (clkval << offset);
-
- __raw_writel(clksel, REG_CLKSEL);
-}
-
-void nuc900_clock_source(struct device *dev, unsigned char *src)
-{
- unsigned int clkval;
- const char *dev_id;
-
- BUG_ON(!src);
- clkval = 0;
-
- mutex_lock(&clksel_sem);
-
- if (dev)
- dev_id = dev_name(dev);
- else
- dev_id = "cpufreq";
-
- if (strcmp(src, "pll0") == 0)
- clkval = PLL0;
- else if (strcmp(src, "pll1") == 0)
- clkval = PLL1;
- else if (strcmp(src, "ext") == 0)
- clkval = EXT;
- else if (strcmp(src, "oth") == 0)
- clkval = OTHER;
-
- clock_source_select(dev_id, clkval);
-
- mutex_unlock(&clksel_sem);
-}
-EXPORT_SYMBOL(nuc900_clock_source);
-
diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c
deleted file mode 100644
index df55aa8ce5ff..000000000000
--- a/arch/arm/mach-w90x900/clock.c
+++ /dev/null
@@ -1,121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/clock.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "clock.h"
-
-#define SUBCLK 0x24
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (clk->enabled++ == 0)
- (clk->enable)(clk, 1);
- spin_unlock_irqrestore(&clocks_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- if (!clk)
- return;
-
- WARN_ON(clk->enabled == 0);
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (--clk->enabled == 0)
- (clk->enable)(clk, 0);
- spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- return 15000000;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void nuc900_clk_enable(struct clk *clk, int enable)
-{
- unsigned int clocks = clk->cken;
- unsigned long clken;
-
- clken = __raw_readl(W90X900_VA_CLKPWR);
-
- if (enable)
- clken |= clocks;
- else
- clken &= ~clocks;
-
- __raw_writel(clken, W90X900_VA_CLKPWR);
-}
-
-void nuc900_subclk_enable(struct clk *clk, int enable)
-{
- unsigned int clocks = clk->cken;
- unsigned long clken;
-
- clken = __raw_readl(W90X900_VA_CLKPWR + SUBCLK);
-
- if (enable)
- clken |= clocks;
- else
- clken &= ~clocks;
-
- __raw_writel(clken, W90X900_VA_CLKPWR + SUBCLK);
-}
-
-/* dummy functions, should not be called */
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- WARN_ON(clk);
- return 0;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- WARN_ON(clk);
- return 0;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- WARN_ON(clk);
- return 0;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
- WARN_ON(clk);
- return NULL;
-}
-EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h
deleted file mode 100644
index e81c369430b3..000000000000
--- a/arch/arm/mach-w90x900/clock.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/arm/mach-w90x900/clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/clkdev.h>
-
-void nuc900_clk_enable(struct clk *clk, int enable);
-void nuc900_subclk_enable(struct clk *clk, int enable);
-
-struct clk {
- unsigned long cken;
- unsigned int enabled;
- void (*enable)(struct clk *, int enable);
-};
-
-#define DEFINE_CLK(_name, _ctrlbit) \
-struct clk clk_##_name = { \
- .enable = nuc900_clk_enable, \
- .cken = (1 << _ctrlbit), \
- }
-
-#define DEFINE_SUBCLK(_name, _ctrlbit) \
-struct clk clk_##_name = { \
- .enable = nuc900_subclk_enable, \
- .cken = (1 << _ctrlbit), \
- }
-
-
-#define DEF_CLKLOOK(_clk, _devname, _conname) \
- { \
- .clk = _clk, \
- .dev_id = _devname, \
- .con_id = _conname, \
- }
-
diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c
deleted file mode 100644
index aeaafc2ebb01..000000000000
--- a/arch/arm/mach-w90x900/cpu.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/cpu.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC900 series cpu common support
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/system_misc.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-serial.h>
-#include <mach/regs-clock.h>
-#include "regs-ebi.h"
-#include "regs-timer.h"
-
-#include "cpu.h"
-#include "clock.h"
-#include "nuc9xx.h"
-
-/* Initial IO mappings */
-
-static struct map_desc nuc900_iodesc[] __initdata = {
- IODESC_ENT(IRQ),
- IODESC_ENT(GCR),
- IODESC_ENT(UART),
- IODESC_ENT(TIMER),
- IODESC_ENT(EBI),
- IODESC_ENT(GPIO),
-};
-
-/* Initial clock declarations. */
-static DEFINE_CLK(lcd, 0);
-static DEFINE_CLK(audio, 1);
-static DEFINE_CLK(fmi, 4);
-static DEFINE_SUBCLK(ms, 0);
-static DEFINE_SUBCLK(sd, 1);
-static DEFINE_CLK(dmac, 5);
-static DEFINE_CLK(atapi, 6);
-static DEFINE_CLK(emc, 7);
-static DEFINE_SUBCLK(rmii, 2);
-static DEFINE_CLK(usbd, 8);
-static DEFINE_CLK(usbh, 9);
-static DEFINE_CLK(g2d, 10);
-static DEFINE_CLK(pwm, 18);
-static DEFINE_CLK(ps2, 24);
-static DEFINE_CLK(kpi, 25);
-static DEFINE_CLK(wdt, 26);
-static DEFINE_CLK(gdma, 27);
-static DEFINE_CLK(adc, 28);
-static DEFINE_CLK(usi, 29);
-static DEFINE_CLK(ext, 0);
-static DEFINE_CLK(timer0, 19);
-static DEFINE_CLK(timer1, 20);
-static DEFINE_CLK(timer2, 21);
-static DEFINE_CLK(timer3, 22);
-static DEFINE_CLK(timer4, 23);
-
-static struct clk_lookup nuc900_clkregs[] = {
- DEF_CLKLOOK(&clk_lcd, "nuc900-lcd", NULL),
- DEF_CLKLOOK(&clk_audio, "nuc900-ac97", NULL),
- DEF_CLKLOOK(&clk_fmi, "nuc900-fmi", NULL),
- DEF_CLKLOOK(&clk_ms, "nuc900-fmi", "MS"),
- DEF_CLKLOOK(&clk_sd, "nuc900-fmi", "SD"),
- DEF_CLKLOOK(&clk_dmac, "nuc900-dmac", NULL),
- DEF_CLKLOOK(&clk_atapi, "nuc900-atapi", NULL),
- DEF_CLKLOOK(&clk_emc, "nuc900-emc", NULL),
- DEF_CLKLOOK(&clk_rmii, "nuc900-emc", "RMII"),
- DEF_CLKLOOK(&clk_usbd, "nuc900-usbd", NULL),
- DEF_CLKLOOK(&clk_usbh, "nuc900-usbh", NULL),
- DEF_CLKLOOK(&clk_g2d, "nuc900-g2d", NULL),
- DEF_CLKLOOK(&clk_pwm, "nuc900-pwm", NULL),
- DEF_CLKLOOK(&clk_ps2, "nuc900-ps2", NULL),
- DEF_CLKLOOK(&clk_kpi, "nuc900-kpi", NULL),
- DEF_CLKLOOK(&clk_wdt, "nuc900-wdt", NULL),
- DEF_CLKLOOK(&clk_gdma, "nuc900-gdma", NULL),
- DEF_CLKLOOK(&clk_adc, "nuc900-ts", NULL),
- DEF_CLKLOOK(&clk_usi, "nuc900-spi", NULL),
- DEF_CLKLOOK(&clk_ext, NULL, "ext"),
- DEF_CLKLOOK(&clk_timer0, NULL, "timer0"),
- DEF_CLKLOOK(&clk_timer1, NULL, "timer1"),
- DEF_CLKLOOK(&clk_timer2, NULL, "timer2"),
- DEF_CLKLOOK(&clk_timer3, NULL, "timer3"),
- DEF_CLKLOOK(&clk_timer4, NULL, "timer4"),
-};
-
-/* Initial serial platform data */
-
-struct plat_serial8250_port nuc900_uart_data[] = {
- NUC900_8250PORT(UART0),
- {},
-};
-
-struct platform_device nuc900_serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = nuc900_uart_data,
- },
-};
-
-/*Set NUC900 series cpu frequence*/
-static int __init nuc900_set_clkval(unsigned int cpufreq)
-{
- unsigned int pllclk, ahbclk, apbclk, val;
-
- pllclk = 0;
- ahbclk = 0;
- apbclk = 0;
-
- switch (cpufreq) {
- case 66:
- pllclk = PLL_66MHZ;
- ahbclk = AHB_CPUCLK_1_1;
- apbclk = APB_AHB_1_2;
- break;
-
- case 100:
- pllclk = PLL_100MHZ;
- ahbclk = AHB_CPUCLK_1_1;
- apbclk = APB_AHB_1_2;
- break;
-
- case 120:
- pllclk = PLL_120MHZ;
- ahbclk = AHB_CPUCLK_1_2;
- apbclk = APB_AHB_1_2;
- break;
-
- case 166:
- pllclk = PLL_166MHZ;
- ahbclk = AHB_CPUCLK_1_2;
- apbclk = APB_AHB_1_2;
- break;
-
- case 200:
- pllclk = PLL_200MHZ;
- ahbclk = AHB_CPUCLK_1_2;
- apbclk = APB_AHB_1_2;
- break;
- }
-
- __raw_writel(pllclk, REG_PLLCON0);
-
- val = __raw_readl(REG_CLKDIV);
- val &= ~(0x03 << 24 | 0x03 << 26);
- val |= (ahbclk << 24 | apbclk << 26);
- __raw_writel(val, REG_CLKDIV);
-
- return 0;
-}
-static int __init nuc900_set_cpufreq(char *str)
-{
- unsigned long cpufreq, val;
-
- if (!*str)
- return 0;
-
- if (kstrtoul(str, 0, &cpufreq))
- return 0;
-
- nuc900_clock_source(NULL, "ext");
-
- nuc900_set_clkval(cpufreq);
-
- mdelay(1);
-
- val = __raw_readl(REG_CKSKEW);
- val &= ~0xff;
- val |= DEFAULTSKEW;
- __raw_writel(val, REG_CKSKEW);
-
- nuc900_clock_source(NULL, "pll0");
-
- return 1;
-}
-
-__setup("cpufreq=", nuc900_set_cpufreq);
-
-/*Init NUC900 evb io*/
-
-void __init nuc900_map_io(struct map_desc *mach_desc, int mach_size)
-{
- unsigned long idcode = 0x0;
-
- iotable_init(mach_desc, mach_size);
- iotable_init(nuc900_iodesc, ARRAY_SIZE(nuc900_iodesc));
-
- idcode = __raw_readl(NUC900PDID);
- if (idcode == NUC910_CPUID)
- printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode);
- else if (idcode == NUC920_CPUID)
- printk(KERN_INFO "CPU type 0x%08lx is NUC920\n", idcode);
- else if (idcode == NUC950_CPUID)
- printk(KERN_INFO "CPU type 0x%08lx is NUC950\n", idcode);
- else if (idcode == NUC960_CPUID)
- printk(KERN_INFO "CPU type 0x%08lx is NUC960\n", idcode);
-}
-
-/*Init NUC900 clock*/
-
-void __init nuc900_init_clocks(void)
-{
- clkdev_add_table(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs));
-}
-
-#define WTCR (TMR_BA + 0x1C)
-#define WTCLK (1 << 10)
-#define WTE (1 << 7)
-#define WTRE (1 << 1)
-
-void nuc9xx_restart(enum reboot_mode mode, const char *cmd)
-{
- if (mode == REBOOT_SOFT) {
- /* Jump into ROM at address 0 */
- soft_restart(0);
- } else {
- __raw_writel(WTE | WTRE | WTCLK, WTCR);
- }
-}
diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h
deleted file mode 100644
index a56f36d04bac..000000000000
--- a/arch/arm/mach-w90x900/cpu.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/cpu.h
- *
- * Based on linux/include/asm-arm/plat-s3c24xx/cpu.h by Ben Dooks
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Header file for NUC900 CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#define IODESC_ENT(y) \
-{ \
- .virtual = (unsigned long)W90X900_VA_##y, \
- .pfn = __phys_to_pfn(W90X900_PA_##y), \
- .length = W90X900_SZ_##y, \
- .type = MT_DEVICE, \
-}
-
-#define NUC900_8250PORT(name) \
-{ \
- .membase = name##_BA, \
- .mapbase = name##_PA, \
- .irq = IRQ_##name, \
- .uartclk = 11313600, \
- .regshift = 2, \
- .iotype = UPIO_MEM, \
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
-}
-
-/*Cpu identifier register*/
-
-#define NUC900PDID W90X900_VA_GCR
-#define NUC910_CPUID 0x02900910
-#define NUC920_CPUID 0x02900920
-#define NUC950_CPUID 0x02900950
-#define NUC960_CPUID 0x02900960
-
-/* extern file from cpu.c */
-
-extern void nuc900_clock_source(struct device *dev, unsigned char *src);
-extern void nuc900_init_clocks(void);
-extern void nuc900_map_io(struct map_desc *mach_desc, int mach_size);
-extern void nuc900_board_init(struct platform_device **device, int size);
-
-/* for either public between 910 and 920, or between 920 and 950 */
-
-extern struct platform_device nuc900_serial_device;
-extern struct platform_device nuc900_device_fmi;
-extern struct platform_device nuc900_device_kpi;
-extern struct platform_device nuc900_device_rtc;
-extern struct platform_device nuc900_device_ts;
-extern struct platform_device nuc900_device_lcd;
diff --git a/arch/arm/mach-w90x900/dev.c b/arch/arm/mach-w90x900/dev.c
deleted file mode 100644
index ce5fe400cb99..000000000000
--- a/arch/arm/mach-w90x900/dev.c
+++ /dev/null
@@ -1,537 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/dev.c
- *
- * Copyright (C) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
-
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
-
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/regs-serial.h>
-#include <linux/platform_data/spi-nuc900.h>
-#include <mach/map.h>
-#include <linux/platform_data/video-nuc900fb.h>
-#include <mach/regs-ldm.h>
-#include <linux/platform_data/keypad-w90p910.h>
-
-#include "cpu.h"
-
-/*NUC900 evb norflash driver data */
-
-#define NUC900_FLASH_BASE 0xA0000000
-#define NUC900_FLASH_SIZE 0x400000
-#define SPIOFFSET 0x200
-#define SPIOREG_SIZE 0x100
-
-static struct mtd_partition nuc900_flash_partitions[] = {
- {
- .name = "NOR Partition 1 for kernel (960K)",
- .size = 0xF0000,
- .offset = 0x10000,
- },
- {
- .name = "NOR Partition 2 for image (1M)",
- .size = 0x100000,
- .offset = 0x100000,
- },
- {
- .name = "NOR Partition 3 for user (2M)",
- .size = 0x200000,
- .offset = 0x00200000,
- }
-};
-
-static struct physmap_flash_data nuc900_flash_data = {
- .width = 2,
- .parts = nuc900_flash_partitions,
- .nr_parts = ARRAY_SIZE(nuc900_flash_partitions),
-};
-
-static struct resource nuc900_flash_resources[] = {
- {
- .start = NUC900_FLASH_BASE,
- .end = NUC900_FLASH_BASE + NUC900_FLASH_SIZE - 1,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct platform_device nuc900_flash_device = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &nuc900_flash_data,
- },
- .resource = nuc900_flash_resources,
- .num_resources = ARRAY_SIZE(nuc900_flash_resources),
-};
-
-/* USB EHCI Host Controller */
-
-static struct resource nuc900_usb_ehci_resource[] = {
- [0] = {
- .start = W90X900_PA_USBEHCIHOST,
- .end = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_USBH,
- .end = IRQ_USBH,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 nuc900_device_usb_ehci_dmamask = 0xffffffffUL;
-
-static struct platform_device nuc900_device_usb_ehci = {
- .name = "nuc900-ehci",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_usb_ehci_resource),
- .resource = nuc900_usb_ehci_resource,
- .dev = {
- .dma_mask = &nuc900_device_usb_ehci_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
-};
-
-/* USB OHCI Host Controller */
-
-static struct resource nuc900_usb_ohci_resource[] = {
- [0] = {
- .start = W90X900_PA_USBOHCIHOST,
- .end = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_USBH,
- .end = IRQ_USBH,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 nuc900_device_usb_ohci_dmamask = 0xffffffffUL;
-static struct platform_device nuc900_device_usb_ohci = {
- .name = "nuc900-ohci",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_usb_ohci_resource),
- .resource = nuc900_usb_ohci_resource,
- .dev = {
- .dma_mask = &nuc900_device_usb_ohci_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
-};
-
-/* USB Device (Gadget)*/
-
-static struct resource nuc900_usbgadget_resource[] = {
- [0] = {
- .start = W90X900_PA_USBDEV,
- .end = W90X900_PA_USBDEV + W90X900_SZ_USBDEV - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_USBD,
- .end = IRQ_USBD,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct platform_device nuc900_device_usbgadget = {
- .name = "nuc900-usbgadget",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_usbgadget_resource),
- .resource = nuc900_usbgadget_resource,
-};
-
-/* MAC device */
-
-static struct resource nuc900_emc_resource[] = {
- [0] = {
- .start = W90X900_PA_EMC,
- .end = W90X900_PA_EMC + W90X900_SZ_EMC - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EMCTX,
- .end = IRQ_EMCTX,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_EMCRX,
- .end = IRQ_EMCRX,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 nuc900_device_emc_dmamask = 0xffffffffUL;
-static struct platform_device nuc900_device_emc = {
- .name = "nuc900-emc",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_emc_resource),
- .resource = nuc900_emc_resource,
- .dev = {
- .dma_mask = &nuc900_device_emc_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
-};
-
-/* SPI device */
-
-static struct nuc900_spi_info nuc900_spiflash_data = {
- .num_cs = 1,
- .lsb = 0,
- .txneg = 1,
- .rxneg = 0,
- .divider = 24,
- .sleep = 0,
- .txnum = 0,
- .txbitlen = 8,
- .bus_num = 0,
-};
-
-static struct resource nuc900_spi_resource[] = {
- [0] = {
- .start = W90X900_PA_I2C + SPIOFFSET,
- .end = W90X900_PA_I2C + SPIOFFSET + SPIOREG_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_SSP,
- .end = IRQ_SSP,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct platform_device nuc900_device_spi = {
- .name = "nuc900-spi",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_spi_resource),
- .resource = nuc900_spi_resource,
- .dev = {
- .platform_data = &nuc900_spiflash_data,
- }
-};
-
-/* spi device, spi flash info */
-
-static struct mtd_partition nuc900_spi_flash_partitions[] = {
- {
- .name = "bootloader(spi)",
- .size = 0x0100000,
- .offset = 0,
- },
-};
-
-static struct flash_platform_data nuc900_spi_flash_data = {
- .name = "m25p80",
- .parts = nuc900_spi_flash_partitions,
- .nr_parts = ARRAY_SIZE(nuc900_spi_flash_partitions),
- .type = "w25x16",
-};
-
-static struct spi_board_info nuc900_spi_board_info[] __initdata = {
- {
- .modalias = "m25p80",
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- .platform_data = &nuc900_spi_flash_data,
- .mode = SPI_MODE_0,
- },
-};
-
-/* WDT Device */
-
-static struct resource nuc900_wdt_resource[] = {
- [0] = {
- .start = W90X900_PA_TIMER,
- .end = W90X900_PA_TIMER + W90X900_SZ_TIMER - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_WDT,
- .end = IRQ_WDT,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct platform_device nuc900_device_wdt = {
- .name = "nuc900-wdt",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_wdt_resource),
- .resource = nuc900_wdt_resource,
-};
-
-/*
- * public device definition between 910 and 920, or 910
- * and 950 or 950 and 960...,their dev platform register
- * should be in specific file such as nuc950, nuc960 c
- * files rather than the public dev.c file here. so the
- * corresponding platform_device definition should not be
- * static.
-*/
-
-/* RTC controller*/
-
-static struct resource nuc900_rtc_resource[] = {
- [0] = {
- .start = W90X900_PA_RTC,
- .end = W90X900_PA_RTC + 0xff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_RTC,
- .end = IRQ_RTC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device nuc900_device_rtc = {
- .name = "nuc900-rtc",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_rtc_resource),
- .resource = nuc900_rtc_resource,
-};
-
-/*TouchScreen controller*/
-
-static struct resource nuc900_ts_resource[] = {
- [0] = {
- .start = W90X900_PA_ADC,
- .end = W90X900_PA_ADC + W90X900_SZ_ADC-1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_ADC,
- .end = IRQ_ADC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device nuc900_device_ts = {
- .name = "nuc900-ts",
- .id = -1,
- .resource = nuc900_ts_resource,
- .num_resources = ARRAY_SIZE(nuc900_ts_resource),
-};
-
-/* FMI Device */
-
-static struct resource nuc900_fmi_resource[] = {
- [0] = {
- .start = W90X900_PA_FMI,
- .end = W90X900_PA_FMI + W90X900_SZ_FMI - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_FMI,
- .end = IRQ_FMI,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-struct platform_device nuc900_device_fmi = {
- .name = "nuc900-fmi",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_fmi_resource),
- .resource = nuc900_fmi_resource,
-};
-
-/* KPI controller*/
-
-static int nuc900_keymap[] = {
- KEY(0, 0, KEY_A),
- KEY(0, 1, KEY_B),
- KEY(0, 2, KEY_C),
- KEY(0, 3, KEY_D),
-
- KEY(1, 0, KEY_E),
- KEY(1, 1, KEY_F),
- KEY(1, 2, KEY_G),
- KEY(1, 3, KEY_H),
-
- KEY(2, 0, KEY_I),
- KEY(2, 1, KEY_J),
- KEY(2, 2, KEY_K),
- KEY(2, 3, KEY_L),
-
- KEY(3, 0, KEY_M),
- KEY(3, 1, KEY_N),
- KEY(3, 2, KEY_O),
- KEY(3, 3, KEY_P),
-};
-
-static struct matrix_keymap_data nuc900_map_data = {
- .keymap = nuc900_keymap,
- .keymap_size = ARRAY_SIZE(nuc900_keymap),
-};
-
-struct w90p910_keypad_platform_data nuc900_keypad_info = {
- .keymap_data = &nuc900_map_data,
- .prescale = 0xfa,
- .debounce = 0x50,
-};
-
-static struct resource nuc900_kpi_resource[] = {
- [0] = {
- .start = W90X900_PA_KPI,
- .end = W90X900_PA_KPI + W90X900_SZ_KPI - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_KPI,
- .end = IRQ_KPI,
- .flags = IORESOURCE_IRQ,
- }
-
-};
-
-struct platform_device nuc900_device_kpi = {
- .name = "nuc900-kpi",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_kpi_resource),
- .resource = nuc900_kpi_resource,
- .dev = {
- .platform_data = &nuc900_keypad_info,
- }
-};
-
-/* LCD controller*/
-
-static struct nuc900fb_display nuc900_lcd_info[] = {
- /* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
- [0] = {
- .type = LCM_DCCS_VA_SRC_RGB565,
- .width = 320,
- .height = 240,
- .xres = 320,
- .yres = 240,
- .bpp = 16,
- .pixclock = 200000,
- .left_margin = 34,
- .right_margin = 54,
- .hsync_len = 10,
- .upper_margin = 18,
- .lower_margin = 4,
- .vsync_len = 1,
- .dccs = 0x8e00041a,
- .devctl = 0x060800c0,
- .fbctrl = 0x00a000a0,
- .scale = 0x04000400,
- },
-};
-
-static struct nuc900fb_mach_info nuc900_fb_info = {
-#if defined(CONFIG_GPM1040A0_320X240)
- .displays = &nuc900_lcd_info[0],
-#else
- .displays = nuc900_lcd_info,
-#endif
- .num_displays = ARRAY_SIZE(nuc900_lcd_info),
- .default_display = 0,
- .gpio_dir = 0x00000004,
- .gpio_dir_mask = 0xFFFFFFFD,
- .gpio_data = 0x00000004,
- .gpio_data_mask = 0xFFFFFFFD,
-};
-
-static struct resource nuc900_lcd_resource[] = {
- [0] = {
- .start = W90X900_PA_LCD,
- .end = W90X900_PA_LCD + W90X900_SZ_LCD - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_LCD,
- .end = IRQ_LCD,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 nuc900_device_lcd_dmamask = -1;
-struct platform_device nuc900_device_lcd = {
- .name = "nuc900-lcd",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_lcd_resource),
- .resource = nuc900_lcd_resource,
- .dev = {
- .dma_mask = &nuc900_device_lcd_dmamask,
- .coherent_dma_mask = -1,
- .platform_data = &nuc900_fb_info,
- }
-};
-
-/* AUDIO controller*/
-static u64 nuc900_device_audio_dmamask = -1;
-static struct resource nuc900_ac97_resource[] = {
- [0] = {
- .start = W90X900_PA_ACTL,
- .end = W90X900_PA_ACTL + W90X900_SZ_ACTL - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_ACTL,
- .end = IRQ_ACTL,
- .flags = IORESOURCE_IRQ,
- }
-
-};
-
-struct platform_device nuc900_device_ac97 = {
- .name = "nuc900-ac97",
- .id = -1,
- .num_resources = ARRAY_SIZE(nuc900_ac97_resource),
- .resource = nuc900_ac97_resource,
- .dev = {
- .dma_mask = &nuc900_device_audio_dmamask,
- .coherent_dma_mask = -1,
- }
-};
-
-/*Here should be your evb resourse,such as LCD*/
-
-static struct platform_device *nuc900_public_dev[] __initdata = {
- &nuc900_serial_device,
- &nuc900_flash_device,
- &nuc900_device_usb_ehci,
- &nuc900_device_usb_ohci,
- &nuc900_device_usbgadget,
- &nuc900_device_emc,
- &nuc900_device_spi,
- &nuc900_device_wdt,
- &nuc900_device_ac97,
-};
-
-/* Provide adding specific CPU platform devices API */
-
-void __init nuc900_board_init(struct platform_device **device, int size)
-{
- cpu_idle_poll_ctrl(true);
- platform_add_devices(device, size);
- platform_add_devices(nuc900_public_dev, ARRAY_SIZE(nuc900_public_dev));
- spi_register_board_info(nuc900_spi_board_info,
- ARRAY_SIZE(nuc900_spi_board_info));
-}
-
diff --git a/arch/arm/mach-w90x900/gpio.c b/arch/arm/mach-w90x900/gpio.c
deleted file mode 100644
index cb5df211f1ed..000000000000
--- a/arch/arm/mach-w90x900/gpio.c
+++ /dev/null
@@ -1,150 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/gpio.c
- *
- * Generic nuc900 GPIO handling
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/gpio/driver.h>
-
-#include <mach/hardware.h>
-
-#define GPIO_BASE (W90X900_VA_GPIO)
-#define GPIO_DIR (0x04)
-#define GPIO_OUT (0x08)
-#define GPIO_IN (0x0C)
-#define GROUPINERV (0x10)
-#define GPIO_GPIO(Nb) (0x00000001 << (Nb))
-
-#define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio) \
- { \
- .chip = { \
- .label = name, \
- .direction_input = nuc900_dir_input, \
- .direction_output = nuc900_dir_output, \
- .get = nuc900_gpio_get, \
- .set = nuc900_gpio_set, \
- .base = base_gpio, \
- .ngpio = nr_gpio, \
- } \
- }
-
-struct nuc900_gpio_chip {
- struct gpio_chip chip;
- void __iomem *regbase; /* Base of group register*/
- spinlock_t gpio_lock;
-};
-
-static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
- void __iomem *pio = nuc900_gpio->regbase + GPIO_IN;
- unsigned int regval;
-
- regval = __raw_readl(pio);
- regval &= GPIO_GPIO(offset);
-
- return (regval != 0);
-}
-
-static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
- struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
- void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT;
- unsigned int regval;
- unsigned long flags;
-
- spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
-
- regval = __raw_readl(pio);
-
- if (val)
- regval |= GPIO_GPIO(offset);
- else
- regval &= ~GPIO_GPIO(offset);
-
- __raw_writel(regval, pio);
-
- spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
-}
-
-static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset)
-{
- struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
- void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
- unsigned int regval;
- unsigned long flags;
-
- spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
-
- regval = __raw_readl(pio);
- regval &= ~GPIO_GPIO(offset);
- __raw_writel(regval, pio);
-
- spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
-
- return 0;
-}
-
-static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val)
-{
- struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
- void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT;
- void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
- unsigned int regval;
- unsigned long flags;
-
- spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
-
- regval = __raw_readl(pio);
- regval |= GPIO_GPIO(offset);
- __raw_writel(regval, pio);
-
- regval = __raw_readl(outreg);
-
- if (val)
- regval |= GPIO_GPIO(offset);
- else
- regval &= ~GPIO_GPIO(offset);
-
- __raw_writel(regval, outreg);
-
- spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
-
- return 0;
-}
-
-static struct nuc900_gpio_chip nuc900_gpio[] = {
- NUC900_GPIO_CHIP("GROUPC", 0, 16),
- NUC900_GPIO_CHIP("GROUPD", 16, 10),
- NUC900_GPIO_CHIP("GROUPE", 26, 14),
- NUC900_GPIO_CHIP("GROUPF", 40, 10),
- NUC900_GPIO_CHIP("GROUPG", 50, 17),
- NUC900_GPIO_CHIP("GROUPH", 67, 8),
- NUC900_GPIO_CHIP("GROUPI", 75, 17),
-};
-
-void __init nuc900_init_gpio(int nr_group)
-{
- unsigned i;
- struct nuc900_gpio_chip *gpio_chip;
-
- for (i = 0; i < nr_group; i++) {
- gpio_chip = &nuc900_gpio[i];
- spin_lock_init(&gpio_chip->gpio_lock);
- gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
- gpiochip_add_data(&gpio_chip->chip, gpio_chip);
- }
-}
diff --git a/arch/arm/mach-w90x900/include/mach/entry-macro.S b/arch/arm/mach-w90x900/include/mach/entry-macro.S
deleted file mode 100644
index 0ff612ac95ba..000000000000
--- a/arch/arm/mach-w90x900/include/mach/entry-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for W90P910-based platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- */
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- mov \base, #AIC_BA
-
- ldr \irqnr, [\base, #AIC_IPER]
- ldr \irqnr, [\base, #AIC_ISNR]
- cmp \irqnr, #0
-
- .endm
diff --git a/arch/arm/mach-w90x900/include/mach/hardware.h b/arch/arm/mach-w90x900/include/mach/hardware.h
deleted file mode 100644
index 137403960483..000000000000
--- a/arch/arm/mach-w90x900/include/mach/hardware.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/hardware.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/hardware.h
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <linux/sizes.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-w90x900/include/mach/irqs.h b/arch/arm/mach-w90x900/include/mach/irqs.h
deleted file mode 100644
index 23ea01d97a02..000000000000
--- a/arch/arm/mach-w90x900/include/mach/irqs.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/irqs.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/irqs.h
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-/*
- * we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- */
-
-#define W90X900_IRQ(x) (x)
-
-/* Main cpu interrupts */
-
-#define IRQ_WDT W90X900_IRQ(1)
-#define IRQ_GROUP0 W90X900_IRQ(2)
-#define IRQ_GROUP1 W90X900_IRQ(3)
-#define IRQ_ACTL W90X900_IRQ(4)
-#define IRQ_LCD W90X900_IRQ(5)
-#define IRQ_RTC W90X900_IRQ(6)
-#define IRQ_UART0 W90X900_IRQ(7)
-#define IRQ_UART1 W90X900_IRQ(8)
-#define IRQ_UART2 W90X900_IRQ(9)
-#define IRQ_UART3 W90X900_IRQ(10)
-#define IRQ_UART4 W90X900_IRQ(11)
-#define IRQ_TIMER0 W90X900_IRQ(12)
-#define IRQ_TIMER1 W90X900_IRQ(13)
-#define IRQ_T_INT_GROUP W90X900_IRQ(14)
-#define IRQ_USBH W90X900_IRQ(15)
-#define IRQ_EMCTX W90X900_IRQ(16)
-#define IRQ_EMCRX W90X900_IRQ(17)
-#define IRQ_GDMAGROUP W90X900_IRQ(18)
-#define IRQ_DMAC W90X900_IRQ(19)
-#define IRQ_FMI W90X900_IRQ(20)
-#define IRQ_USBD W90X900_IRQ(21)
-#define IRQ_ATAPI W90X900_IRQ(22)
-#define IRQ_G2D W90X900_IRQ(23)
-#define IRQ_PCI W90X900_IRQ(24)
-#define IRQ_SCGROUP W90X900_IRQ(25)
-#define IRQ_I2CGROUP W90X900_IRQ(26)
-#define IRQ_SSP W90X900_IRQ(27)
-#define IRQ_PWM W90X900_IRQ(28)
-#define IRQ_KPI W90X900_IRQ(29)
-#define IRQ_P2SGROUP W90X900_IRQ(30)
-#define IRQ_ADC W90X900_IRQ(31)
-#define NR_IRQS (IRQ_ADC+1)
-
-/*for irq group*/
-
-#define IRQ_PS2_PORT0 0x10000000
-#define IRQ_PS2_PORT1 0x20000000
-#define IRQ_I2C_LINE0 0x04000000
-#define IRQ_I2C_LINE1 0x08000000
-#define IRQ_SC_CARD0 0x01000000
-#define IRQ_SC_CARD1 0x02000000
-#define IRQ_GDMA_CH0 0x00100000
-#define IRQ_GDMA_CH1 0x00200000
-#define IRQ_TIMER2 0x00010000
-#define IRQ_TIMER3 0x00020000
-#define IRQ_TIMER4 0x00040000
-#define IRQ_GROUP0_IRQ0 0x00000001
-#define IRQ_GROUP0_IRQ1 0x00000002
-#define IRQ_GROUP0_IRQ2 0x00000004
-#define IRQ_GROUP0_IRQ3 0x00000008
-#define IRQ_GROUP1_IRQ4 0x00000010
-#define IRQ_GROUP1_IRQ5 0x00000020
-#define IRQ_GROUP1_IRQ6 0x00000040
-#define IRQ_GROUP1_IRQ7 0x00000080
-
-#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-w90x900/include/mach/map.h b/arch/arm/mach-w90x900/include/mach/map.h
deleted file mode 100644
index 570a74e04b1c..000000000000
--- a/arch/arm/mach-w90x900/include/mach/map.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/map.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/map.h
- */
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H
-
-#ifndef __ASSEMBLY__
-#define W90X900_ADDR(x) ((void __iomem *)(0xF0000000 + (x)))
-#else
-#define W90X900_ADDR(x) (0xF0000000 + (x))
-#endif
-
-#define AHB_IO_BASE 0xB0000000
-#define APB_IO_BASE 0xB8000000
-#define CLOCKPW_BASE (APB_IO_BASE+0x200)
-#define AIC_IO_BASE (APB_IO_BASE+0x2000)
-#define TIMER_IO_BASE (APB_IO_BASE+0x1000)
-
-/*
- * interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-#define W90X900_VA_IRQ W90X900_ADDR(0x00000000)
-#define W90X900_PA_IRQ (0xB8002000)
-#define W90X900_SZ_IRQ SZ_4K
-
-#define W90X900_VA_GCR W90X900_ADDR(0x08002000)
-#define W90X900_PA_GCR (0xB0000000)
-#define W90X900_SZ_GCR SZ_4K
-
-/* Clock and Power management */
-#define W90X900_VA_CLKPWR (W90X900_VA_GCR+0x200)
-#define W90X900_PA_CLKPWR (0xB0000200)
-#define W90X900_SZ_CLKPWR SZ_4K
-
-/* EBI management */
-#define W90X900_VA_EBI W90X900_ADDR(0x00001000)
-#define W90X900_PA_EBI (0xB0001000)
-#define W90X900_SZ_EBI SZ_4K
-
-/* UARTs */
-#define W90X900_VA_UART W90X900_ADDR(0x08000000)
-#define W90X900_PA_UART (0xB8000000)
-#define W90X900_SZ_UART SZ_4K
-
-/* Timers */
-#define W90X900_VA_TIMER W90X900_ADDR(0x08001000)
-#define W90X900_PA_TIMER (0xB8001000)
-#define W90X900_SZ_TIMER SZ_4K
-
-/* GPIO ports */
-#define W90X900_VA_GPIO W90X900_ADDR(0x08003000)
-#define W90X900_PA_GPIO (0xB8003000)
-#define W90X900_SZ_GPIO SZ_4K
-
-/* GDMA control */
-#define W90X900_VA_GDMA W90X900_ADDR(0x00004000)
-#define W90X900_PA_GDMA (0xB0004000)
-#define W90X900_SZ_GDMA SZ_4K
-
-/* USB host controller*/
-#define W90X900_VA_USBEHCIHOST W90X900_ADDR(0x00005000)
-#define W90X900_PA_USBEHCIHOST (0xB0005000)
-#define W90X900_SZ_USBEHCIHOST SZ_4K
-
-#define W90X900_VA_USBOHCIHOST W90X900_ADDR(0x00007000)
-#define W90X900_PA_USBOHCIHOST (0xB0007000)
-#define W90X900_SZ_USBOHCIHOST SZ_4K
-
-/* I2C hardware controller */
-#define W90X900_VA_I2C W90X900_ADDR(0x08006000)
-#define W90X900_PA_I2C (0xB8006000)
-#define W90X900_SZ_I2C SZ_4K
-
-/* Keypad Interface*/
-#define W90X900_VA_KPI W90X900_ADDR(0x08008000)
-#define W90X900_PA_KPI (0xB8008000)
-#define W90X900_SZ_KPI SZ_4K
-
-/* Smart card host*/
-#define W90X900_VA_SC W90X900_ADDR(0x08005000)
-#define W90X900_PA_SC (0xB8005000)
-#define W90X900_SZ_SC SZ_4K
-
-/* LCD controller*/
-#define W90X900_VA_LCD W90X900_ADDR(0x00008000)
-#define W90X900_PA_LCD (0xB0008000)
-#define W90X900_SZ_LCD SZ_4K
-
-/* 2D controller*/
-#define W90X900_VA_GE W90X900_ADDR(0x0000B000)
-#define W90X900_PA_GE (0xB000B000)
-#define W90X900_SZ_GE SZ_4K
-
-/* ATAPI */
-#define W90X900_VA_ATAPI W90X900_ADDR(0x0000A000)
-#define W90X900_PA_ATAPI (0xB000A000)
-#define W90X900_SZ_ATAPI SZ_4K
-
-/* ADC */
-#define W90X900_VA_ADC W90X900_ADDR(0x0800A000)
-#define W90X900_PA_ADC (0xB800A000)
-#define W90X900_SZ_ADC SZ_4K
-
-/* PS2 Interface*/
-#define W90X900_VA_PS2 W90X900_ADDR(0x08009000)
-#define W90X900_PA_PS2 (0xB8009000)
-#define W90X900_SZ_PS2 SZ_4K
-
-/* RTC */
-#define W90X900_VA_RTC W90X900_ADDR(0x08004000)
-#define W90X900_PA_RTC (0xB8004000)
-#define W90X900_SZ_RTC SZ_4K
-
-/* Pulse Width Modulation(PWM) Registers */
-#define W90X900_VA_PWM W90X900_ADDR(0x08007000)
-#define W90X900_PA_PWM (0xB8007000)
-#define W90X900_SZ_PWM SZ_4K
-
-/* Audio Controller controller */
-#define W90X900_VA_ACTL W90X900_ADDR(0x00009000)
-#define W90X900_PA_ACTL (0xB0009000)
-#define W90X900_SZ_ACTL SZ_4K
-
-/* DMA controller */
-#define W90X900_VA_DMA W90X900_ADDR(0x0000c000)
-#define W90X900_PA_DMA (0xB000c000)
-#define W90X900_SZ_DMA SZ_4K
-
-/* FMI controller */
-#define W90X900_VA_FMI W90X900_ADDR(0x0000d000)
-#define W90X900_PA_FMI (0xB000d000)
-#define W90X900_SZ_FMI SZ_4K
-
-/* USB Device port */
-#define W90X900_VA_USBDEV W90X900_ADDR(0x00006000)
-#define W90X900_PA_USBDEV (0xB0006000)
-#define W90X900_SZ_USBDEV SZ_4K
-
-/* External MAC control*/
-#define W90X900_VA_EMC W90X900_ADDR(0x00003000)
-#define W90X900_PA_EMC (0xB0003000)
-#define W90X900_SZ_EMC SZ_4K
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-w90x900/include/mach/mfp.h b/arch/arm/mach-w90x900/include/mach/mfp.h
deleted file mode 100644
index be5485efab0a..000000000000
--- a/arch/arm/mach-w90x900/include/mach/mfp.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/mfp.h
- *
- * Copyright (c) 2010 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/map.h
- */
-
-#ifndef __ASM_ARCH_MFP_H
-#define __ASM_ARCH_MFP_H
-
-extern void mfp_set_groupf(struct device *dev);
-extern void mfp_set_groupc(struct device *dev);
-extern void mfp_set_groupi(struct device *dev);
-extern void mfp_set_groupg(struct device *dev, const char *subname);
-extern void mfp_set_groupd(struct device *dev, const char *subname);
-
-#endif /* __ASM_ARCH_MFP_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-clock.h b/arch/arm/mach-w90x900/include/mach/regs-clock.h
deleted file mode 100644
index f06245d26bd7..000000000000
--- a/arch/arm/mach-w90x900/include/mach/regs-clock.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H
-
-/* Clock Control Registers */
-#define CLK_BA W90X900_VA_CLKPWR
-#define REG_CLKEN (CLK_BA + 0x00)
-#define REG_CLKSEL (CLK_BA + 0x04)
-#define REG_CLKDIV (CLK_BA + 0x08)
-#define REG_PLLCON0 (CLK_BA + 0x0C)
-#define REG_PLLCON1 (CLK_BA + 0x10)
-#define REG_PMCON (CLK_BA + 0x14)
-#define REG_IRQWAKECON (CLK_BA + 0x18)
-#define REG_IRQWAKEFLAG (CLK_BA + 0x1C)
-#define REG_IPSRST (CLK_BA + 0x20)
-#define REG_CLKEN1 (CLK_BA + 0x24)
-#define REG_CLKDIV1 (CLK_BA + 0x28)
-
-/* Define PLL freq setting */
-#define PLL_DISABLE 0x12B63
-#define PLL_66MHZ 0x2B63
-#define PLL_100MHZ 0x4F64
-#define PLL_120MHZ 0x4F63
-#define PLL_166MHZ 0x4124
-#define PLL_200MHZ 0x4F24
-
-/* Define AHB:CPUFREQ ratio */
-#define AHB_CPUCLK_1_1 0x00
-#define AHB_CPUCLK_1_2 0x01
-#define AHB_CPUCLK_1_4 0x02
-#define AHB_CPUCLK_1_8 0x03
-
-/* Define APB:AHB ratio */
-#define APB_AHB_1_2 0x01
-#define APB_AHB_1_4 0x02
-#define APB_AHB_1_8 0x03
-
-/* Define clock skew */
-#define DEFAULTSKEW 0x48
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-irq.h b/arch/arm/mach-w90x900/include/mach/regs-irq.h
deleted file mode 100644
index 89fcbc60b60a..000000000000
--- a/arch/arm/mach-w90x900/include/mach/regs-irq.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-irq.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/regs-irq.h
- */
-
-#ifndef ___ASM_ARCH_REGS_IRQ_H
-#define ___ASM_ARCH_REGS_IRQ_H
-
-/* Advance Interrupt Controller (AIC) Registers */
-
-#define AIC_BA W90X900_VA_IRQ
-
-#define REG_AIC_IRQSC (AIC_BA+0x80)
-#define REG_AIC_GEN (AIC_BA+0x84)
-#define REG_AIC_GASR (AIC_BA+0x88)
-#define REG_AIC_GSCR (AIC_BA+0x8C)
-#define REG_AIC_IRSR (AIC_BA+0x100)
-#define REG_AIC_IASR (AIC_BA+0x104)
-#define REG_AIC_ISR (AIC_BA+0x108)
-#define REG_AIC_IPER (AIC_BA+0x10C)
-#define REG_AIC_ISNR (AIC_BA+0x110)
-#define REG_AIC_IMR (AIC_BA+0x114)
-#define REG_AIC_OISR (AIC_BA+0x118)
-#define REG_AIC_MECR (AIC_BA+0x120)
-#define REG_AIC_MDCR (AIC_BA+0x124)
-#define REG_AIC_SSCR (AIC_BA+0x128)
-#define REG_AIC_SCCR (AIC_BA+0x12C)
-#define REG_AIC_EOSCR (AIC_BA+0x130)
-#define AIC_IPER (0x10C)
-#define AIC_ISNR (0x110)
-
-/*16-18 bits of REG_AIC_GEN define irq(2-4) group*/
-
-#define TIMER2_IRQ (1 << 16)
-#define TIMER3_IRQ (1 << 17)
-#define TIMER4_IRQ (1 << 18)
-#define TIME_GROUP_IRQ (TIMER2_IRQ|TIMER3_IRQ|TIMER4_IRQ)
-
-#endif /* ___ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-ldm.h b/arch/arm/mach-w90x900/include/mach/regs-ldm.h
deleted file mode 100644
index ffe7e67c99de..000000000000
--- a/arch/arm/mach-w90x900/include/mach/regs-ldm.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-serial.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * Description:
- * Nuvoton Display, LCM Register list
- * Author: Wang Qiang (rurality.linux@gmail.com) 2009/12/11
- */
-
-
-#ifndef __ASM_ARM_W90X900_REGS_LDM_H
-#define __ASM_ARM_W90X900_REGS_LDM_H
-
-#include <mach/map.h>
-
-/* Display Controller Control/Status Register */
-#define REG_LCM_DCCS (0x00)
-
-#define LCM_DCCS_ENG_RST (1 << 0)
-#define LCM_DCCS_VA_EN (1 << 1)
-#define LCM_DCCS_OSD_EN (1 << 2)
-#define LCM_DCCS_DISP_OUT_EN (1 << 3)
-#define LCM_DCCS_DISP_INT_EN (1 << 4)
-#define LCM_DCCS_CMD_ON (1 << 5)
-#define LCM_DCCS_FIELD_INTR (1 << 6)
-#define LCM_DCCS_SINGLE (1 << 7)
-
-enum LCM_DCCS_VA_SRC {
- LCM_DCCS_VA_SRC_YUV422 = (0 << 8),
- LCM_DCCS_VA_SRC_YCBCR422 = (1 << 8),
- LCM_DCCS_VA_SRC_RGB888 = (2 << 8),
- LCM_DCCS_VA_SRC_RGB666 = (3 << 8),
- LCM_DCCS_VA_SRC_RGB565 = (4 << 8),
- LCM_DCCS_VA_SRC_RGB444LOW = (5 << 8),
- LCM_DCCS_VA_SRC_RGB444HIGH = (7 << 8)
-};
-
-
-/* Display Device Control Register */
-#define REG_LCM_DEV_CTRL (0x04)
-
-enum LCM_DEV_CTRL_SWAP_YCbCr {
- LCM_DEV_CTRL_SWAP_UYVY = (0 << 1),
- LCM_DEV_CTRL_SWAP_YUYV = (1 << 1),
- LCM_DEV_CTRL_SWAP_VYUY = (2 << 1),
- LCM_DEV_CTRL_SWAP_YVYU = (3 << 1)
-};
-
-enum LCM_DEV_CTRL_RGB_SHIFT {
- LCM_DEV_CTRL_RGB_SHIFT_NOT = (0 << 3),
- LCM_DEV_CTRL_RGB_SHIFT_ONECYCLE = (1 << 3),
- LCM_DEV_CTRL_RGB_SHIFT_TWOCYCLE = (2 << 3),
- LCM_DEV_CTRL_RGB_SHIFT_NOT_DEF = (3 << 3)
-};
-
-enum LCM_DEV_CTRL_DEVICE {
- LCM_DEV_CTRL_DEVICE_YUV422 = (0 << 5),
- LCM_DEV_CTRL_DEVICE_YUV444 = (1 << 5),
- LCM_DEV_CTRL_DEVICE_UNIPAC = (4 << 5),
- LCM_DEV_CTRL_DEVICE_SEIKO_EPSON = (5 << 5),
- LCM_DEV_CTRL_DEVICE_HIGH_COLOR = (6 << 5),
- LCM_DEV_CTRL_DEVICE_MPU = (7 << 5)
-};
-
-#define LCM_DEV_CTRL_LCD_DDA (8)
-#define LCM_DEV_CTRL_YUV2CCIR (16)
-
-enum LCM_DEV_CTRL_LCD_SEL {
- LCM_DEV_CTRL_LCD_SEL_RGB_GBR = (0 << 17),
- LCM_DEV_CTRL_LCD_SEL_BGR_RBG = (1 << 17),
- LCM_DEV_CTRL_LCD_SEL_GBR_RGB = (2 << 17),
- LCM_DEV_CTRL_LCD_SEL_RBG_BGR = (3 << 17)
-};
-
-enum LCM_DEV_CTRL_FAL_D {
- LCM_DEV_CTRL_FAL_D_FALLING = (0 << 19),
- LCM_DEV_CTRL_FAL_D_RISING = (1 << 19),
-};
-
-enum LCM_DEV_CTRL_H_POL {
- LCM_DEV_CTRL_H_POL_LOW = (0 << 20),
- LCM_DEV_CTRL_H_POL_HIGH = (1 << 20),
-};
-
-enum LCM_DEV_CTRL_V_POL {
- LCM_DEV_CTRL_V_POL_LOW = (0 << 21),
- LCM_DEV_CTRL_V_POL_HIGH = (1 << 21),
-};
-
-enum LCM_DEV_CTRL_VR_LACE {
- LCM_DEV_CTRL_VR_LACE_NINTERLACE = (0 << 22),
- LCM_DEV_CTRL_VR_LACE_INTERLACE = (1 << 22),
-};
-
-enum LCM_DEV_CTRL_LACE {
- LCM_DEV_CTRL_LACE_NINTERLACE = (0 << 23),
- LCM_DEV_CTRL_LACE_INTERLACE = (1 << 23),
-};
-
-enum LCM_DEV_CTRL_RGB_SCALE {
- LCM_DEV_CTRL_RGB_SCALE_4096 = (0 << 24),
- LCM_DEV_CTRL_RGB_SCALE_65536 = (1 << 24),
- LCM_DEV_CTRL_RGB_SCALE_262144 = (2 << 24),
- LCM_DEV_CTRL_RGB_SCALE_16777216 = (3 << 24),
-};
-
-enum LCM_DEV_CTRL_DBWORD {
- LCM_DEV_CTRL_DBWORD_HALFWORD = (0 << 26),
- LCM_DEV_CTRL_DBWORD_FULLWORD = (1 << 26),
-};
-
-enum LCM_DEV_CTRL_MPU68 {
- LCM_DEV_CTRL_MPU68_80_SERIES = (0 << 27),
- LCM_DEV_CTRL_MPU68_68_SERIES = (1 << 27),
-};
-
-enum LCM_DEV_CTRL_DE_POL {
- LCM_DEV_CTRL_DE_POL_HIGH = (0 << 28),
- LCM_DEV_CTRL_DE_POL_LOW = (1 << 28),
-};
-
-#define LCM_DEV_CTRL_CMD16 (29)
-#define LCM_DEV_CTRL_CM16t18 (30)
-#define LCM_DEV_CTRL_CMD_LOW (31)
-
-/* MPU-Interface LCD Write Command */
-#define REG_LCM_MPU_CMD (0x08)
-
-/* Interrupt Control/Status Register */
-#define REG_LCM_INT_CS (0x0c)
-#define LCM_INT_CS_DISP_F_EN (1 << 0)
-#define LCM_INT_CS_UNDERRUN_EN (1 << 1)
-#define LCM_INT_CS_BUS_ERROR_INT (1 << 28)
-#define LCM_INT_CS_UNDERRUN_INT (1 << 29)
-#define LCM_INT_CS_DISP_F_STATUS (1 << 30)
-#define LCM_INT_CS_DISP_F_INT (1 << 31)
-
-/* CRTC Display Size Control Register */
-#define REG_LCM_CRTC_SIZE (0x10)
-#define LCM_CRTC_SIZE_VTTVAL(x) ((x) << 16)
-#define LCM_CRTC_SIZE_HTTVAL(x) ((x) << 0)
-
-/* CRTC Display Enable End */
-#define REG_LCM_CRTC_DEND (0x14)
-#define LCM_CRTC_DEND_VDENDVAL(x) ((x) << 16)
-#define LCM_CRTC_DEND_HDENDVAL(x) ((x) << 0)
-
-/* CRTC Internal Horizontal Retrace Control Register */
-#define REG_LCM_CRTC_HR (0x18)
-#define LCM_CRTC_HR_EVAL(x) ((x) << 16)
-#define LCM_CRTC_HR_SVAL(x) ((x) << 0)
-
-/* CRTC Horizontal Sync Control Register */
-#define REG_LCM_CRTC_HSYNC (0x1C)
-#define LCM_CRTC_HSYNC_SHIFTVAL(x) ((x) << 30)
-#define LCM_CRTC_HSYNC_EVAL(x) ((x) << 16)
-#define LCM_CRTC_HSYNC_SVAL(x) ((x) << 0)
-
-/* CRTC Internal Vertical Retrace Control Register */
-#define REG_LCM_CRTC_VR (0x20)
-#define LCM_CRTC_VR_EVAL(x) ((x) << 16)
-#define LCM_CRTC_VR_SVAL(x) ((x) << 0)
-
-/* Video Stream Frame Buffer-0 Starting Address */
-#define REG_LCM_VA_BADDR0 (0x24)
-
-/* Video Stream Frame Buffer-1 Starting Address */
-#define REG_LCM_VA_BADDR1 (0x28)
-
-/* Video Stream Frame Buffer Control Register */
-#define REG_LCM_VA_FBCTRL (0x2C)
-#define LCM_VA_FBCTRL_IO_REGION_HALF (1 << 28)
-#define LCM_VA_FBCTRL_FIELD_DUAL (1 << 29)
-#define LCM_VA_FBCTRL_START_BUF (1 << 30)
-#define LCM_VA_FBCTRL_DB_EN (1 << 31)
-
-/* Video Stream Scaling Control Register */
-#define REG_LCM_VA_SCALE (0x30)
-#define LCM_VA_SCALE_XCOPY_INTERPOLATION (0 << 15)
-#define LCM_VA_SCALE_XCOPY_DUPLICATION (1 << 15)
-
-/* Image Stream Active Window Coordinates */
-#define REG_LCM_VA_WIN (0x38)
-
-/* Image Stream Stuff Pixel */
-#define REG_LCM_VA_STUFF (0x3C)
-
-/* OSD Window Starting Coordinates */
-#define REG_LCM_OSD_WINS (0x40)
-
-/* OSD Window Ending Coordinates */
-#define REG_LCM_OSD_WINE (0x44)
-
-/* OSD Stream Frame Buffer Starting Address */
-#define REG_LCM_OSD_BADDR (0x48)
-
-/* OSD Stream Frame Buffer Control Register */
-#define REG_LCM_OSD_FBCTRL (0x4c)
-
-/* OSD Overlay Control Register */
-#define REG_LCM_OSD_OVERLAY (0x50)
-
-/* OSD Overlay Color-Key Pattern Register */
-#define REG_LCM_OSD_CKEY (0x54)
-
-/* OSD Overlay Color-Key Mask Register */
-#define REG_LCM_OSD_CMASK (0x58)
-
-/* OSD Window Skip1 Register */
-#define REG_LCM_OSD_SKIP1 (0x5C)
-
-/* OSD Window Skip2 Register */
-#define REG_LCM_OSD_SKIP2 (0x60)
-
-/* OSD horizontal up scaling control register */
-#define REG_LCM_OSD_SCALE (0x64)
-
-/* MPU Vsync control register */
-#define REG_LCM_MPU_VSYNC (0x68)
-
-/* Hardware cursor control Register */
-#define REG_LCM_HC_CTRL (0x6C)
-
-/* Hardware cursot tip point potison on va picture */
-#define REG_LCM_HC_POS (0x70)
-
-/* Hardware Cursor Window Buffer Control Register */
-#define REG_LCM_HC_WBCTRL (0x74)
-
-/* Hardware cursor memory base address register */
-#define REG_LCM_HC_BADDR (0x78)
-
-/* Hardware cursor color ram register mapped to bpp = 0 */
-#define REG_LCM_HC_COLOR0 (0x7C)
-
-/* Hardware cursor color ram register mapped to bpp = 1 */
-#define REG_LCM_HC_COLOR1 (0x80)
-
-/* Hardware cursor color ram register mapped to bpp = 2 */
-#define REG_LCM_HC_COLOR2 (0x84)
-
-/* Hardware cursor color ram register mapped to bpp = 3 */
-#define REG_LCM_HC_COLOR3 (0x88)
-
-#endif /* __ASM_ARM_W90X900_REGS_LDM_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-serial.h b/arch/arm/mach-w90x900/include/mach/regs-serial.h
deleted file mode 100644
index 797c9727a157..000000000000
--- a/arch/arm/mach-w90x900/include/mach/regs-serial.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-serial.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/regs-serial.h
- */
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define UART0_BA W90X900_VA_UART
-#define UART1_BA (W90X900_VA_UART+0x100)
-#define UART2_BA (W90X900_VA_UART+0x200)
-#define UART3_BA (W90X900_VA_UART+0x300)
-#define UART4_BA (W90X900_VA_UART+0x400)
-
-#define UART0_PA W90X900_PA_UART
-#define UART1_PA (W90X900_PA_UART+0x100)
-#define UART2_PA (W90X900_PA_UART+0x200)
-#define UART3_PA (W90X900_PA_UART+0x300)
-#define UART4_PA (W90X900_PA_UART+0x400)
-
-#ifndef __ASSEMBLY__
-
-struct w90x900_uart_clksrc {
- const char *name;
- unsigned int divisor;
- unsigned int min_baud;
- unsigned int max_baud;
-};
-
-struct w90x900_uartcfg {
- unsigned char hwport;
- unsigned char unused;
- unsigned short flags;
- unsigned long uart_flags;
-
- unsigned long ucon;
- unsigned long ulcon;
- unsigned long ufcon;
-
- struct w90x900_uart_clksrc *clocks;
- unsigned int clocks_size;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff --git a/arch/arm/mach-w90x900/include/mach/uncompress.h b/arch/arm/mach-w90x900/include/mach/uncompress.h
deleted file mode 100644
index 32e92a77ccae..000000000000
--- a/arch/arm/mach-w90x900/include/mach/uncompress.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/uncompress.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-/* Defines for UART registers */
-
-#include <mach/regs-serial.h>
-#include <mach/map.h>
-#include <linux/serial_reg.h>
-
-#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
-static volatile u32 * const uart_base = (u32 *)UART0_PA;
-
-static inline void putc(int ch)
-{
- /* Check THRE and TEMT bits before we transmit the character.
- */
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
- barrier();
-
- *uart_base = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif/* __ASM_W90X900_UNCOMPRESS_H */
diff --git a/arch/arm/mach-w90x900/irq.c b/arch/arm/mach-w90x900/irq.c
deleted file mode 100644
index 081b0f65477a..000000000000
--- a/arch/arm/mach-w90x900/irq.c
+++ /dev/null
@@ -1,212 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/irq.c
- *
- * based on linux/arch/arm/plat-s3c24xx/irq.c by Ben Dooks
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-#include "nuc9xx.h"
-
-struct group_irq {
- unsigned long gpen;
- unsigned int enabled;
- void (*enable)(struct group_irq *, int enable);
-};
-
-static DEFINE_SPINLOCK(groupirq_lock);
-
-#define DEFINE_GROUP(_name, _ctrlbit, _num) \
-struct group_irq group_##_name = { \
- .enable = nuc900_group_enable, \
- .gpen = ((1 << _num) - 1) << _ctrlbit, \
- }
-
-static void nuc900_group_enable(struct group_irq *gpirq, int enable);
-
-static DEFINE_GROUP(nirq0, 0, 4);
-static DEFINE_GROUP(nirq1, 4, 4);
-static DEFINE_GROUP(usbh, 8, 2);
-static DEFINE_GROUP(ottimer, 16, 3);
-static DEFINE_GROUP(gdma, 20, 2);
-static DEFINE_GROUP(sc, 24, 2);
-static DEFINE_GROUP(i2c, 26, 2);
-static DEFINE_GROUP(ps2, 28, 2);
-
-static int group_irq_enable(struct group_irq *group_irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&groupirq_lock, flags);
- if (group_irq->enabled++ == 0)
- (group_irq->enable)(group_irq, 1);
- spin_unlock_irqrestore(&groupirq_lock, flags);
-
- return 0;
-}
-
-static void group_irq_disable(struct group_irq *group_irq)
-{
- unsigned long flags;
-
- WARN_ON(group_irq->enabled == 0);
-
- spin_lock_irqsave(&groupirq_lock, flags);
- if (--group_irq->enabled == 0)
- (group_irq->enable)(group_irq, 0);
- spin_unlock_irqrestore(&groupirq_lock, flags);
-}
-
-static void nuc900_group_enable(struct group_irq *gpirq, int enable)
-{
- unsigned int groupen = gpirq->gpen;
- unsigned long regval;
-
- regval = __raw_readl(REG_AIC_GEN);
-
- if (enable)
- regval |= groupen;
- else
- regval &= ~groupen;
-
- __raw_writel(regval, REG_AIC_GEN);
-}
-
-static void nuc900_irq_mask(struct irq_data *d)
-{
- struct group_irq *group_irq;
-
- group_irq = NULL;
-
- __raw_writel(1 << d->irq, REG_AIC_MDCR);
-
- switch (d->irq) {
- case IRQ_GROUP0:
- group_irq = &group_nirq0;
- break;
-
- case IRQ_GROUP1:
- group_irq = &group_nirq1;
- break;
-
- case IRQ_USBH:
- group_irq = &group_usbh;
- break;
-
- case IRQ_T_INT_GROUP:
- group_irq = &group_ottimer;
- break;
-
- case IRQ_GDMAGROUP:
- group_irq = &group_gdma;
- break;
-
- case IRQ_SCGROUP:
- group_irq = &group_sc;
- break;
-
- case IRQ_I2CGROUP:
- group_irq = &group_i2c;
- break;
-
- case IRQ_P2SGROUP:
- group_irq = &group_ps2;
- break;
- }
-
- if (group_irq)
- group_irq_disable(group_irq);
-}
-
-/*
- * By the w90p910 spec,any irq,only write 1
- * to REG_AIC_EOSCR for ACK
- */
-
-static void nuc900_irq_ack(struct irq_data *d)
-{
- __raw_writel(0x01, REG_AIC_EOSCR);
-}
-
-static void nuc900_irq_unmask(struct irq_data *d)
-{
- struct group_irq *group_irq;
-
- group_irq = NULL;
-
- __raw_writel(1 << d->irq, REG_AIC_MECR);
-
- switch (d->irq) {
- case IRQ_GROUP0:
- group_irq = &group_nirq0;
- break;
-
- case IRQ_GROUP1:
- group_irq = &group_nirq1;
- break;
-
- case IRQ_USBH:
- group_irq = &group_usbh;
- break;
-
- case IRQ_T_INT_GROUP:
- group_irq = &group_ottimer;
- break;
-
- case IRQ_GDMAGROUP:
- group_irq = &group_gdma;
- break;
-
- case IRQ_SCGROUP:
- group_irq = &group_sc;
- break;
-
- case IRQ_I2CGROUP:
- group_irq = &group_i2c;
- break;
-
- case IRQ_P2SGROUP:
- group_irq = &group_ps2;
- break;
- }
-
- if (group_irq)
- group_irq_enable(group_irq);
-}
-
-static struct irq_chip nuc900_irq_chip = {
- .irq_ack = nuc900_irq_ack,
- .irq_mask = nuc900_irq_mask,
- .irq_unmask = nuc900_irq_unmask,
-};
-
-void __init nuc900_init_irq(void)
-{
- int irqno;
-
- __raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
-
- for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) {
- irq_set_chip_and_handler(irqno, &nuc900_irq_chip,
- handle_level_irq);
- irq_clear_status_flags(irqno, IRQ_NOREQUEST);
- }
-}
diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c
deleted file mode 100644
index e6d30af3e35a..000000000000
--- a/arch/arm/mach-w90x900/mach-nuc910evb.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc910evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc910.h"
-
-static void __init nuc910evb_map_io(void)
-{
- nuc910_map_io();
- nuc910_init_clocks();
-}
-
-static void __init nuc910evb_init(void)
-{
- nuc910_board_init();
-}
-
-MACHINE_START(W90P910EVB, "W90P910EVB")
- /* Maintainer: Wan ZongShun */
- .map_io = nuc910evb_map_io,
- .init_irq = nuc900_init_irq,
- .init_machine = nuc910evb_init,
- .init_time = nuc900_timer_init,
- .restart = nuc9xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
deleted file mode 100644
index 62547308c344..000000000000
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc950evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * history:
- * Wang Qiang (rurality.linux@gmail.com) add LCD support
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-#include <linux/platform_data/video-nuc900fb.h>
-
-#include "nuc950.h"
-
-static void __init nuc950evb_map_io(void)
-{
- nuc950_map_io();
- nuc950_init_clocks();
-}
-
-static void __init nuc950evb_init(void)
-{
- nuc950_board_init();
-}
-
-MACHINE_START(W90P950EVB, "W90P950EVB")
- /* Maintainer: Wan ZongShun */
- .map_io = nuc950evb_map_io,
- .init_irq = nuc900_init_irq,
- .init_machine = nuc950evb_init,
- .init_time = nuc900_timer_init,
- .restart = nuc9xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c
deleted file mode 100644
index 35a53459d0d2..000000000000
--- a/arch/arm/mach-w90x900/mach-nuc960evb.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc960evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc960.h"
-
-static void __init nuc960evb_map_io(void)
-{
- nuc960_map_io();
- nuc960_init_clocks();
-}
-
-static void __init nuc960evb_init(void)
-{
- nuc960_board_init();
-}
-
-MACHINE_START(W90N960EVB, "W90N960EVB")
- /* Maintainer: Wan ZongShun */
- .map_io = nuc960evb_map_io,
- .init_irq = nuc900_init_irq,
- .init_machine = nuc960evb_init,
- .init_time = nuc900_timer_init,
- .restart = nuc9xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-w90x900/mfp.c b/arch/arm/mach-w90x900/mfp.c
deleted file mode 100644
index 05f3779a3618..000000000000
--- a/arch/arm/mach-w90x900/mfp.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/mfp.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#define REG_MFSEL (W90X900_VA_GCR + 0xC)
-
-#define GPSELF (0x01 << 1)
-#define GPSELC (0x03 << 2)
-#define GPSELD (0x0f << 4)
-
-#define GPSELEI0 (0x01 << 26)
-#define GPSELEI1 (0x01 << 27)
-
-#define GPIOG0TO1 (0x03 << 14)
-#define GPIOG2TO3 (0x03 << 16)
-#define GPIOG22TO23 (0x03 << 22)
-#define GPIOG18TO20 (0x07 << 18)
-
-#define ENSPI (0x0a << 14)
-#define ENI2C0 (0x01 << 14)
-#define ENI2C1 (0x01 << 16)
-#define ENAC97 (0x02 << 22)
-#define ENSD1 (0x02 << 18)
-#define ENSD0 (0x0a << 4)
-#define ENKPI (0x02 << 2)
-#define ENNAND (0x01 << 2)
-
-static DEFINE_MUTEX(mfp_mutex);
-
-void mfp_set_groupf(struct device *dev)
-{
- unsigned long mfpen;
- const char *dev_id;
-
- BUG_ON(!dev);
-
- mutex_lock(&mfp_mutex);
-
- dev_id = dev_name(dev);
-
- mfpen = __raw_readl(REG_MFSEL);
-
- if (strcmp(dev_id, "nuc900-emc") == 0)
- mfpen |= GPSELF;/*enable mac*/
- else
- mfpen &= ~GPSELF;/*GPIOF[9:0]*/
-
- __raw_writel(mfpen, REG_MFSEL);
-
- mutex_unlock(&mfp_mutex);
-}
-EXPORT_SYMBOL(mfp_set_groupf);
-
-void mfp_set_groupc(struct device *dev)
-{
- unsigned long mfpen;
- const char *dev_id;
-
- BUG_ON(!dev);
-
- mutex_lock(&mfp_mutex);
-
- dev_id = dev_name(dev);
-
- mfpen = __raw_readl(REG_MFSEL);
-
- if (strcmp(dev_id, "nuc900-lcd") == 0)
- mfpen |= GPSELC;/*enable lcd*/
- else if (strcmp(dev_id, "nuc900-kpi") == 0) {
- mfpen &= (~GPSELC);/*enable kpi*/
- mfpen |= ENKPI;
- } else if (strcmp(dev_id, "nuc900-nand") == 0) {
- mfpen &= (~GPSELC);/*enable nand*/
- mfpen |= ENNAND;
- } else
- mfpen &= (~GPSELC);/*GPIOC[14:0]*/
-
- __raw_writel(mfpen, REG_MFSEL);
-
- mutex_unlock(&mfp_mutex);
-}
-EXPORT_SYMBOL(mfp_set_groupc);
-
-void mfp_set_groupi(struct device *dev)
-{
- unsigned long mfpen;
- const char *dev_id;
-
- BUG_ON(!dev);
-
- mutex_lock(&mfp_mutex);
-
- dev_id = dev_name(dev);
-
- mfpen = __raw_readl(REG_MFSEL);
-
- mfpen &= ~GPSELEI1;/*default gpio16*/
-
- if (strcmp(dev_id, "nuc900-wdog") == 0)
- mfpen |= GPSELEI1;/*enable wdog*/
- else if (strcmp(dev_id, "nuc900-atapi") == 0)
- mfpen |= GPSELEI0;/*enable atapi*/
- else if (strcmp(dev_id, "nuc900-keypad") == 0)
- mfpen &= ~GPSELEI0;/*enable keypad*/
-
- __raw_writel(mfpen, REG_MFSEL);
-
- mutex_unlock(&mfp_mutex);
-}
-EXPORT_SYMBOL(mfp_set_groupi);
-
-void mfp_set_groupg(struct device *dev, const char *subname)
-{
- unsigned long mfpen;
- const char *dev_id;
-
- BUG_ON((!dev) && (!subname));
-
- mutex_lock(&mfp_mutex);
-
- if (subname != NULL)
- dev_id = subname;
- else
- dev_id = dev_name(dev);
-
- mfpen = __raw_readl(REG_MFSEL);
-
- if (strcmp(dev_id, "nuc900-spi") == 0) {
- mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);
- mfpen |= ENSPI;/*enable spi*/
- } else if (strcmp(dev_id, "nuc900-i2c0") == 0) {
- mfpen &= ~(GPIOG0TO1);
- mfpen |= ENI2C0;/*enable i2c0*/
- } else if (strcmp(dev_id, "nuc900-i2c1") == 0) {
- mfpen &= ~(GPIOG2TO3);
- mfpen |= ENI2C1;/*enable i2c1*/
- } else if (strcmp(dev_id, "nuc900-ac97") == 0) {
- mfpen &= ~(GPIOG22TO23);
- mfpen |= ENAC97;/*enable AC97*/
- } else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
- mfpen &= ~(GPIOG18TO20);
- mfpen |= (ENSD1 | 0x01);/*enable sd1*/
- } else {
- mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/
- }
-
- __raw_writel(mfpen, REG_MFSEL);
-
- mutex_unlock(&mfp_mutex);
-}
-EXPORT_SYMBOL(mfp_set_groupg);
-
-void mfp_set_groupd(struct device *dev, const char *subname)
-{
- unsigned long mfpen;
- const char *dev_id;
-
- BUG_ON((!dev) && (!subname));
-
- mutex_lock(&mfp_mutex);
-
- if (subname != NULL)
- dev_id = subname;
- else
- dev_id = dev_name(dev);
-
- mfpen = __raw_readl(REG_MFSEL);
-
- if (strcmp(dev_id, "nuc900-mmc-port0") == 0) {
- mfpen &= ~GPSELD;/*enable sd0*/
- mfpen |= ENSD0;
- } else
- mfpen &= (~GPSELD);
-
- __raw_writel(mfpen, REG_MFSEL);
-
- mutex_unlock(&mfp_mutex);
-}
-EXPORT_SYMBOL(mfp_set_groupd);
diff --git a/arch/arm/mach-w90x900/nuc910.c b/arch/arm/mach-w90x900/nuc910.c
deleted file mode 100644
index 45ae8285bfc9..000000000000
--- a/arch/arm/mach-w90x900/nuc910.c
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/nuc910.c
- *
- * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC910 cpu support
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include "cpu.h"
-#include "clock.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc910_dev[] __initdata = {
- &nuc900_device_ts,
- &nuc900_device_rtc,
- &nuc900_device_lcd,
- &nuc900_device_kpi,
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc910evb_iodesc[] __initdata = {
- IODESC_ENT(USBEHCIHOST),
- IODESC_ENT(USBOHCIHOST),
- IODESC_ENT(KPI),
- IODESC_ENT(USBDEV),
- IODESC_ENT(ADC),
-};
-
-/*Init NUC910 evb io*/
-
-void __init nuc910_map_io(void)
-{
- nuc900_map_io(nuc910evb_iodesc, ARRAY_SIZE(nuc910evb_iodesc));
-}
-
-/*Init NUC910 clock*/
-
-void __init nuc910_init_clocks(void)
-{
- nuc900_init_clocks();
-}
-
-/*Init NUC910 board info*/
-
-void __init nuc910_board_init(void)
-{
- nuc900_board_init(nuc910_dev, ARRAY_SIZE(nuc910_dev));
-}
diff --git a/arch/arm/mach-w90x900/nuc910.h b/arch/arm/mach-w90x900/nuc910.h
deleted file mode 100644
index 53be3323736f..000000000000
--- a/arch/arm/mach-w90x900/nuc910.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/nuc910.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC900 CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-#include "nuc9xx.h"
-
-/* extern file from nuc910.c */
-
-extern void nuc910_board_init(void);
-extern void nuc910_init_clocks(void);
-extern void nuc910_map_io(void);
diff --git a/arch/arm/mach-w90x900/nuc950.c b/arch/arm/mach-w90x900/nuc950.c
deleted file mode 100644
index 3be114249cd8..000000000000
--- a/arch/arm/mach-w90x900/nuc950.c
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/nuc950.c
- *
- * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC950 cpu support
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-
-#include "cpu.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc950_dev[] __initdata = {
- &nuc900_device_kpi,
- &nuc900_device_fmi,
- &nuc900_device_lcd,
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc950evb_iodesc[] __initdata = {
-};
-
-/*Init NUC950 evb io*/
-
-void __init nuc950_map_io(void)
-{
- nuc900_map_io(nuc950evb_iodesc, ARRAY_SIZE(nuc950evb_iodesc));
-}
-
-/*Init NUC950 clock*/
-
-void __init nuc950_init_clocks(void)
-{
- nuc900_init_clocks();
-}
-
-/*Init NUC950 board info*/
-
-void __init nuc950_board_init(void)
-{
- nuc900_board_init(nuc950_dev, ARRAY_SIZE(nuc950_dev));
-}
diff --git a/arch/arm/mach-w90x900/nuc950.h b/arch/arm/mach-w90x900/nuc950.h
deleted file mode 100644
index 23cff81ea630..000000000000
--- a/arch/arm/mach-w90x900/nuc950.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/nuc950.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC900 CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-#include "nuc9xx.h"
-
-/* extern file from nuc950.c */
-
-extern void nuc950_board_init(void);
-extern void nuc950_init_clocks(void);
-extern void nuc950_map_io(void);
diff --git a/arch/arm/mach-w90x900/nuc960.c b/arch/arm/mach-w90x900/nuc960.c
deleted file mode 100644
index 8a27d74b975e..000000000000
--- a/arch/arm/mach-w90x900/nuc960.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-w90x900/nuc960.c
- *
- * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC960 cpu support
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include "cpu.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc960_dev[] __initdata = {
- &nuc900_device_kpi,
- &nuc900_device_fmi,
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc960evb_iodesc[] __initdata = {
-};
-
-/*Init NUC960 evb io*/
-
-void __init nuc960_map_io(void)
-{
- nuc900_map_io(nuc960evb_iodesc, ARRAY_SIZE(nuc960evb_iodesc));
-}
-
-/*Init NUC960 clock*/
-
-void __init nuc960_init_clocks(void)
-{
- nuc900_init_clocks();
-}
-
-/*Init NUC960 board info*/
-
-void __init nuc960_board_init(void)
-{
- nuc900_board_init(nuc960_dev, ARRAY_SIZE(nuc960_dev));
-}
diff --git a/arch/arm/mach-w90x900/nuc960.h b/arch/arm/mach-w90x900/nuc960.h
deleted file mode 100644
index 88bb13c971dc..000000000000
--- a/arch/arm/mach-w90x900/nuc960.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/nuc960.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC900 CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-#include "nuc9xx.h"
-
-/* extern file from nuc960.c */
-
-extern void nuc960_board_init(void);
-extern void nuc960_init_clocks(void);
-extern void nuc960_map_io(void);
diff --git a/arch/arm/mach-w90x900/nuc9xx.h b/arch/arm/mach-w90x900/nuc9xx.h
deleted file mode 100644
index 21f6f9c304e8..000000000000
--- a/arch/arm/mach-w90x900/nuc9xx.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/nuc9xx.h
- *
- * Copied from nuc910.h, which had:
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC900 CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/reboot.h>
-
-struct map_desc;
-
-/* core initialisation functions */
-
-extern void nuc900_init_irq(void);
-extern void nuc900_timer_init(void);
-extern void nuc9xx_restart(enum reboot_mode, const char *);
diff --git a/arch/arm/mach-w90x900/regs-ebi.h b/arch/arm/mach-w90x900/regs-ebi.h
deleted file mode 100644
index 3fb22702cfc0..000000000000
--- a/arch/arm/mach-w90x900/regs-ebi.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-ebi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#ifndef __ASM_ARCH_REGS_EBI_H
-#define __ASM_ARCH_REGS_EBI_H
-
-/* EBI Control Registers */
-
-#define EBI_BA W90X900_VA_EBI
-#define REG_EBICON (EBI_BA + 0x00)
-#define REG_ROMCON (EBI_BA + 0x04)
-#define REG_SDCONF0 (EBI_BA + 0x08)
-#define REG_SDCONF1 (EBI_BA + 0x0C)
-#define REG_SDTIME0 (EBI_BA + 0x10)
-#define REG_SDTIME1 (EBI_BA + 0x14)
-#define REG_EXT0CON (EBI_BA + 0x18)
-#define REG_EXT1CON (EBI_BA + 0x1C)
-#define REG_EXT2CON (EBI_BA + 0x20)
-#define REG_EXT3CON (EBI_BA + 0x24)
-#define REG_EXT4CON (EBI_BA + 0x28)
-#define REG_CKSKEW (EBI_BA + 0x2C)
-
-#endif /* __ASM_ARCH_REGS_EBI_H */
diff --git a/arch/arm/mach-w90x900/regs-gcr.h b/arch/arm/mach-w90x900/regs-gcr.h
deleted file mode 100644
index caf1090ecad8..000000000000
--- a/arch/arm/mach-w90x900/regs-gcr.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-gcr.h
- *
- * Copyright (c) 2010 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#ifndef __ASM_ARCH_REGS_GCR_H
-#define __ASM_ARCH_REGS_GCR_H
-
-/* Global control registers */
-
-#define GCR_BA W90X900_VA_GCR
-#define REG_PDID (GCR_BA+0x000)
-#define REG_PWRON (GCR_BA+0x004)
-#define REG_ARBCON (GCR_BA+0x008)
-#define REG_MFSEL (GCR_BA+0x00C)
-#define REG_EBIDPE (GCR_BA+0x010)
-#define REG_LCDDPE (GCR_BA+0x014)
-#define REG_GPIOCPE (GCR_BA+0x018)
-#define REG_GPIODPE (GCR_BA+0x01C)
-#define REG_GPIOEPE (GCR_BA+0x020)
-#define REG_GPIOFPE (GCR_BA+0x024)
-#define REG_GPIOGPE (GCR_BA+0x028)
-#define REG_GPIOHPE (GCR_BA+0x02C)
-#define REG_GPIOIPE (GCR_BA+0x030)
-#define REG_GTMP1 (GCR_BA+0x034)
-#define REG_GTMP2 (GCR_BA+0x038)
-#define REG_GTMP3 (GCR_BA+0x03C)
-
-#endif /* __ASM_ARCH_REGS_GCR_H */
diff --git a/arch/arm/mach-w90x900/regs-timer.h b/arch/arm/mach-w90x900/regs-timer.h
deleted file mode 100644
index d12807fd1e3e..000000000000
--- a/arch/arm/mach-w90x900/regs-timer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-timer.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/regs-timer.h
- */
-
-#ifndef __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-/* Timer Registers */
-
-#define TMR_BA W90X900_VA_TIMER
-#define REG_TCSR0 (TMR_BA+0x00)
-#define REG_TCSR1 (TMR_BA+0x04)
-#define REG_TICR0 (TMR_BA+0x08)
-#define REG_TICR1 (TMR_BA+0x0C)
-#define REG_TDR0 (TMR_BA+0x10)
-#define REG_TDR1 (TMR_BA+0x14)
-#define REG_TISR (TMR_BA+0x18)
-#define REG_WTCR (TMR_BA+0x1C)
-#define REG_TCSR2 (TMR_BA+0x20)
-#define REG_TCSR3 (TMR_BA+0x24)
-#define REG_TICR2 (TMR_BA+0x28)
-#define REG_TICR3 (TMR_BA+0x2C)
-#define REG_TDR2 (TMR_BA+0x30)
-#define REG_TDR3 (TMR_BA+0x34)
-#define REG_TCSR4 (TMR_BA+0x40)
-#define REG_TICR4 (TMR_BA+0x48)
-#define REG_TDR4 (TMR_BA+0x50)
-
-#endif /* __ASM_ARCH_REGS_TIMER_H */
diff --git a/arch/arm/mach-w90x900/regs-usb.h b/arch/arm/mach-w90x900/regs-usb.h
deleted file mode 100644
index 98046c811bf7..000000000000
--- a/arch/arm/mach-w90x900/regs-usb.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-w90x900/include/mach/regs-usb.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#ifndef __ASM_ARCH_REGS_USB_H
-#define __ASM_ARCH_REGS_USB_H
-
-/* usb Control Registers */
-#define USBH_BA W90X900_VA_USBEHCIHOST
-#define USBD_BA W90X900_VA_USBDEV
-#define USBO_BA W90X900_VA_USBOHCIHOST
-
-/* USB Host Control Registers */
-#define REG_UPSCR0 (USBH_BA+0x064)
-#define REG_UPSCR1 (USBH_BA+0x068)
-#define REG_USBPCR0 (USBH_BA+0x0C4)
-#define REG_USBPCR1 (USBH_BA+0x0C8)
-
-/* USBH OHCI Control Registers */
-#define REG_OpModEn (USBO_BA+0x204)
-/*This bit controls the polarity of over
-*current flag from external power IC.
-*/
-#define OCALow 0x08
-
-#endif /* __ASM_ARCH_REGS_USB_H */
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c
deleted file mode 100644
index dd20fab9a960..000000000000
--- a/arch/arm/mach-w90x900/time.c
+++ /dev/null
@@ -1,168 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/arch/arm/mach-w90x900/time.c
- *
- * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#include <mach/map.h>
-#include "regs-timer.h"
-
-#include "nuc9xx.h"
-
-#define RESETINT 0x1f
-#define PERIOD (0x01 << 27)
-#define ONESHOT (0x00 << 27)
-#define COUNTEN (0x01 << 30)
-#define INTEN (0x01 << 29)
-
-#define TICKS_PER_SEC 100
-#define PRESCALE 0x63 /* Divider = prescale + 1 */
-
-#define TDR_SHIFT 24
-
-static unsigned int timer0_load;
-
-static int nuc900_clockevent_shutdown(struct clock_event_device *evt)
-{
- unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
-
- __raw_writel(val, REG_TCSR0);
- return 0;
-}
-
-static int nuc900_clockevent_set_oneshot(struct clock_event_device *evt)
-{
- unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
-
- val |= (ONESHOT | COUNTEN | INTEN | PRESCALE);
-
- __raw_writel(val, REG_TCSR0);
- return 0;
-}
-
-static int nuc900_clockevent_set_periodic(struct clock_event_device *evt)
-{
- unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
-
- __raw_writel(timer0_load, REG_TICR0);
- val |= (PERIOD | COUNTEN | INTEN | PRESCALE);
- __raw_writel(val, REG_TCSR0);
- return 0;
-}
-
-static int nuc900_clockevent_setnextevent(unsigned long evt,
- struct clock_event_device *clk)
-{
- unsigned int val;
-
- __raw_writel(evt, REG_TICR0);
-
- val = __raw_readl(REG_TCSR0);
- val |= (COUNTEN | INTEN | PRESCALE);
- __raw_writel(val, REG_TCSR0);
-
- return 0;
-}
-
-static struct clock_event_device nuc900_clockevent_device = {
- .name = "nuc900-timer0",
- .features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT,
- .set_state_shutdown = nuc900_clockevent_shutdown,
- .set_state_periodic = nuc900_clockevent_set_periodic,
- .set_state_oneshot = nuc900_clockevent_set_oneshot,
- .tick_resume = nuc900_clockevent_shutdown,
- .set_next_event = nuc900_clockevent_setnextevent,
- .rating = 300,
-};
-
-/*IRQ handler for the timer*/
-
-static irqreturn_t nuc900_timer0_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &nuc900_clockevent_device;
-
- __raw_writel(0x01, REG_TISR); /* clear TIF0 */
-
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static struct irqaction nuc900_timer0_irq = {
- .name = "nuc900-timer0",
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
- .handler = nuc900_timer0_interrupt,
-};
-
-static void __init nuc900_clockevents_init(void)
-{
- unsigned int rate;
- struct clk *clk = clk_get(NULL, "timer0");
-
- BUG_ON(IS_ERR(clk));
-
- __raw_writel(0x00, REG_TCSR0);
-
- clk_enable(clk);
- rate = clk_get_rate(clk) / (PRESCALE + 1);
-
- timer0_load = (rate / TICKS_PER_SEC);
-
- __raw_writel(RESETINT, REG_TISR);
- setup_irq(IRQ_TIMER0, &nuc900_timer0_irq);
-
- nuc900_clockevent_device.cpumask = cpumask_of(0);
-
- clockevents_config_and_register(&nuc900_clockevent_device, rate,
- 0xf, 0xffffffff);
-}
-
-static void __init nuc900_clocksource_init(void)
-{
- unsigned int val;
- unsigned int rate;
- struct clk *clk = clk_get(NULL, "timer1");
-
- BUG_ON(IS_ERR(clk));
-
- __raw_writel(0x00, REG_TCSR1);
-
- clk_enable(clk);
- rate = clk_get_rate(clk) / (PRESCALE + 1);
-
- __raw_writel(0xffffffff, REG_TICR1);
-
- val = __raw_readl(REG_TCSR1);
- val |= (COUNTEN | PERIOD | PRESCALE);
- __raw_writel(val, REG_TCSR1);
-
- clocksource_mmio_init(REG_TDR1, "nuc900-timer1", rate, 200,
- TDR_SHIFT, clocksource_mmio_readl_down);
-}
-
-void __init nuc900_timer_init(void)
-{
- nuc900_clocksource_init();
- nuc900_clockevents_init();
-}
diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S
index ab85003cf9ad..3449e0d1f990 100644
--- a/arch/arm/mach-zynq/headsmp.S
+++ b/arch/arm/mach-zynq/headsmp.S
@@ -7,6 +7,8 @@
#include <linux/init.h>
#include <asm/assembler.h>
+ .arm
+
ENTRY(zynq_secondary_trampoline)
ARM_BE8(setend be) @ ensure we are in BE8 mode
ldr r0, zynq_secondary_trampoline_jump
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index a7cfe07156f4..a10085be9073 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -57,7 +57,7 @@ int zynq_cpun_start(u32 address, int cpu)
* 0x4: Jump by mov instruction
* 0x8: Jumping address
*/
- memcpy((__force void *)zero, &zynq_secondary_trampoline,
+ memcpy_toio(zero, &zynq_secondary_trampoline,
trampoline_size);
writel(address, zero + trampoline_size);
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(zynq_cpun_start);
static int zynq_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- return zynq_cpun_start(__pa_symbol(secondary_startup), cpu);
+ return zynq_cpun_start(__pa_symbol(secondary_startup_arm), cpu);
}
/*
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 820b60a50125..0ab3a86b1f52 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -106,7 +106,7 @@ config CPU_ARM922T
help
The ARM922T is a version of the ARM920T, but with smaller
instruction and data caches. It is used in Altera's
- Excalibur XA device family and Micrel's KS8695 Centaur.
+ Excalibur XA device family and the ARM Integrator.
Say Y if you want support for the ARM922T processor.
Otherwise, say N.
@@ -663,6 +663,7 @@ config ARM_LPAE
depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
!CPU_32v4 && !CPU_32v3
select PHYS_ADDR_T_64BIT
+ select SWIOTLB
help
Say Y if you have an ARMv7 processor supporting the LPAE page
table format and you would like to access memory beyond the
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 8cdb78642e93..04b36436cbc0 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -695,7 +695,7 @@ thumb2arm(u16 tinstr)
return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] |
(tinstr & 255); /* register_list */
}
- /* Else fall through for illegal instruction case */
+ /* Else, fall through - for illegal instruction case */
default:
return BAD_INSTR;
@@ -751,6 +751,8 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
case 0xe8e0:
case 0xe9e0:
poffset->un = (tinst2 & 0xff) << 2;
+ /* Fall through */
+
case 0xe940:
case 0xe9c0:
return do_alignment_ldrdstrd;
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 61d834157bc0..382e1c2855e8 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -42,6 +42,7 @@ static void mc_copy_user_page(void *from, void *to)
* when prefetching destination as well. (NP)
*/
asm volatile ("\
+.arch xscale \n\
pld [%0, #0] \n\
pld [%0, #32] \n\
pld [%1, #0] \n\
@@ -106,8 +107,9 @@ void
xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
{
void *ptr, *kaddr = kmap_atomic(page);
- asm volatile(
- "mov r1, %2 \n\
+ asm volatile("\
+.arch xscale \n\
+ mov r1, %2 \n\
mov r2, #0 \n\
mov r3, #0 \n\
1: mov ip, %0 \n\
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4789c60a86e3..d42557ee69c2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-noncoherent.h>
#include <linux/dma-contiguous.h>
#include <linux/highmem.h>
#include <linux/memblock.h>
@@ -1125,6 +1126,19 @@ int arm_dma_supported(struct device *dev, u64 mask)
static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
{
+ /*
+ * When CONFIG_ARM_LPAE is set, physical address can extend above
+ * 32-bits, which then can't be addressed by devices that only support
+ * 32-bit DMA.
+ * Use the generic dma-direct / swiotlb ops code in that case, as that
+ * handles bounce buffering for us.
+ *
+ * Note: this checks CONFIG_ARM_LPAE instead of CONFIG_SWIOTLB as the
+ * latter is also selected by the Xen code, but that code for now relies
+ * on non-NULL dev_dma_ops. To be cleaned up later.
+ */
+ if (IS_ENABLED(CONFIG_ARM_LPAE))
+ return NULL;
return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
}
@@ -2329,6 +2343,9 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
const struct dma_map_ops *dma_ops;
dev->archdata.dma_coherent = coherent;
+#ifdef CONFIG_SWIOTLB
+ dev->dma_coherent = coherent;
+#endif
/*
* Don't override the dma_ops if they have already been set. Ideally
@@ -2363,3 +2380,45 @@ void arch_teardown_dma_ops(struct device *dev)
/* Let arch_setup_dma_ops() start again from scratch upon re-probe */
set_dma_ops(dev, NULL);
}
+
+#ifdef CONFIG_SWIOTLB
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir)
+{
+ __dma_page_cpu_to_dev(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
+ size, dir);
+}
+
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir)
+{
+ __dma_page_dev_to_cpu(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
+ size, dir);
+}
+
+long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
+ dma_addr_t dma_addr)
+{
+ return dma_to_pfn(dev, dma_addr);
+}
+
+pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
+ unsigned long attrs)
+{
+ return __get_dma_pgprot(attrs, prot);
+}
+
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp, unsigned long attrs)
+{
+ return __dma_alloc(dev, size, dma_handle, gfp,
+ __get_dma_pgprot(attrs, PAGE_KERNEL), false,
+ attrs, __builtin_return_address(0));
+}
+
+void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t dma_handle, unsigned long attrs)
+{
+ __arm_dma_free(dev, size, cpu_addr, dma_handle, attrs, false);
+}
+#endif /* CONFIG_SWIOTLB */
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 4920a206dce9..b4be3baa83d4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -21,6 +21,7 @@
#include <linux/dma-contiguous.h>
#include <linux/sizes.h>
#include <linux/stop_machine.h>
+#include <linux/swiotlb.h>
#include <asm/cp15.h>
#include <asm/mach-types.h>
@@ -174,6 +175,11 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
int pfn_valid(unsigned long pfn)
{
+ phys_addr_t addr = __pfn_to_phys(pfn);
+
+ if (__phys_to_pfn(addr) != pfn)
+ return 0;
+
return memblock_is_map_memory(__pfn_to_phys(pfn));
}
EXPORT_SYMBOL(pfn_valid);
@@ -463,6 +469,10 @@ static void __init free_highpages(void)
*/
void __init mem_init(void)
{
+#ifdef CONFIG_ARM_LPAE
+ swiotlb_init(1);
+#endif
+
set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
/* this will put all unused low memory onto the freelists */
@@ -623,7 +633,8 @@ static void update_sections_early(struct section_perm perms[], int n)
if (t->flags & PF_KTHREAD)
continue;
for_each_thread(t, s)
- set_section_perms(perms, n, true, s->mm);
+ if (s->mm)
+ set_section_perms(perms, n, true, s->mm);
}
set_section_perms(perms, n, true, current->active_mm);
set_section_perms(perms, n, true, &init_mm);
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
deleted file mode 100644
index 4d839a3cf284..000000000000
--- a/arch/arm/plat-iop/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-
-# IOP32X
-obj-$(CONFIG_ARCH_IOP32X) += i2c.o
-obj-$(CONFIG_ARCH_IOP32X) += pci.o
-obj-$(CONFIG_ARCH_IOP32X) += setup.o
-obj-$(CONFIG_ARCH_IOP32X) += time.o
-obj-$(CONFIG_ARCH_IOP32X) += cp6.o
-obj-$(CONFIG_ARCH_IOP32X) += adma.o
-obj-$(CONFIG_ARCH_IOP32X) += pmu.o
-obj-$(CONFIG_ARCH_IOP32X) += restart.o
-
-# IOP33X
-obj-$(CONFIG_ARCH_IOP33X) += i2c.o
-obj-$(CONFIG_ARCH_IOP33X) += pci.o
-obj-$(CONFIG_ARCH_IOP33X) += setup.o
-obj-$(CONFIG_ARCH_IOP33X) += time.o
-obj-$(CONFIG_ARCH_IOP33X) += cp6.o
-obj-$(CONFIG_ARCH_IOP33X) += adma.o
-obj-$(CONFIG_ARCH_IOP33X) += pmu.o
-obj-$(CONFIG_ARCH_IOP33X) += restart.o
-
-# IOP13XX
-obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
-obj-$(CONFIG_ARCH_IOP13XX) += time.o
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 79f43acf9acb..08c99413d02c 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -388,17 +388,15 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
/*
* not supported by current hardware on OMAP1
* w |= (0x03 << 7);
- * fall through
*/
+ /* fall through */
case OMAP_DMA_DATA_BURST_16:
if (dma_omap2plus()) {
burst = 0x3;
break;
}
- /*
- * OMAP1 don't support burst 16
- * fall through
- */
+ /* OMAP1 don't support burst 16 */
+ /* fall through */
default:
BUG();
}
@@ -474,10 +472,8 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
burst = 0x3;
break;
}
- /*
- * OMAP1 don't support burst 16
- * fall through
- */
+ /* OMAP1 don't support burst 16 */
+ /* fall through */
default:
printk(KERN_ERR "Invalid DMA burst mode\n");
BUG();
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 51e721f5e491..c0bfceb88340 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -12,6 +12,7 @@
/* Bring in machine-local definitions, especially S3C_GPIO_END */
#include <mach/gpio-samsung.h>
+#include <linux/gpio/driver.h>
#define GPIOCON_OFF (0x00)
#define GPIODAT_OFF (0x04)
diff --git a/arch/arm/plat-samsung/include/plat/usb-phy.h b/arch/arm/plat-samsung/include/plat/usb-phy.h
index 6d0c788beb9d..94da89ecbd3b 100644
--- a/arch/arm/plat-samsung/include/plat/usb-phy.h
+++ b/arch/arm/plat-samsung/include/plat/usb-phy.h
@@ -7,8 +7,6 @@
#ifndef __PLAT_SAMSUNG_USB_PHY_H
#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
-#include <linux/usb/samsung_usb_phy.h>
-
extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
new file mode 100644
index 000000000000..d6465823b281
--- /dev/null
+++ b/arch/arm64/Kbuild
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += kernel/ mm/
+obj-$(CONFIG_NET) += net/
+obj-$(CONFIG_KVM) += kvm/
+obj-$(CONFIG_XEN) += xen/
+obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3adcec05b1f6..6ae6ad8a4db0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -148,6 +148,7 @@ config ARM64
select HAVE_FAST_GUP
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_TRACER
+ select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_GCC_PLUGINS
select HAVE_HW_BREAKPOINT if PERF_EVENTS
@@ -286,7 +287,7 @@ config PGTABLE_LEVELS
int
default 2 if ARM64_16K_PAGES && ARM64_VA_BITS_36
default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
- default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52)
+ default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_VA_BITS_52)
default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47
default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48
@@ -297,6 +298,21 @@ config ARCH_SUPPORTS_UPROBES
config ARCH_PROC_KCORE_TEXT
def_bool y
+config KASAN_SHADOW_OFFSET
+ hex
+ depends on KASAN
+ default 0xdfffa00000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && !KASAN_SW_TAGS
+ default 0xdfffd00000000000 if ARM64_VA_BITS_47 && !KASAN_SW_TAGS
+ default 0xdffffe8000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS
+ default 0xdfffffd000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS
+ default 0xdffffffa00000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS
+ default 0xefff900000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && KASAN_SW_TAGS
+ default 0xefffc80000000000 if ARM64_VA_BITS_47 && KASAN_SW_TAGS
+ default 0xeffffe4000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS
+ default 0xefffffc800000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS
+ default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
+ default 0xffffffffffffffff
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
@@ -744,13 +760,14 @@ config ARM64_VA_BITS_47
config ARM64_VA_BITS_48
bool "48-bit"
-config ARM64_USER_VA_BITS_52
- bool "52-bit (user)"
+config ARM64_VA_BITS_52
+ bool "52-bit"
depends on ARM64_64K_PAGES && (ARM64_PAN || !ARM64_SW_TTBR0_PAN)
help
Enable 52-bit virtual addressing for userspace when explicitly
- requested via a hint to mmap(). The kernel will continue to
- use 48-bit virtual addresses for its own mappings.
+ requested via a hint to mmap(). The kernel will also use 52-bit
+ virtual addresses for its own mappings (provided HW support for
+ this feature is available, otherwise it reverts to 48-bit).
NOTE: Enabling 52-bit virtual addressing in conjunction with
ARMv8.3 Pointer Authentication will result in the PAC being
@@ -763,7 +780,7 @@ endchoice
config ARM64_FORCE_52BIT
bool "Force 52-bit virtual addresses for userspace"
- depends on ARM64_USER_VA_BITS_52 && EXPERT
+ depends on ARM64_VA_BITS_52 && EXPERT
help
For systems with 52-bit userspace VAs enabled, the kernel will attempt
to maintain compatibility with older software by providing 48-bit VAs
@@ -780,7 +797,8 @@ config ARM64_VA_BITS
default 39 if ARM64_VA_BITS_39
default 42 if ARM64_VA_BITS_42
default 47 if ARM64_VA_BITS_47
- default 48 if ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52
+ default 48 if ARM64_VA_BITS_48
+ default 52 if ARM64_VA_BITS_52
choice
prompt "Physical address space size"
@@ -1110,6 +1128,15 @@ config ARM64_SW_TTBR0_PAN
zeroed area and reserved ASID. The user access routines
restore the valid TTBR0_EL1 temporarily.
+config ARM64_TAGGED_ADDR_ABI
+ bool "Enable the tagged user addresses syscall ABI"
+ default y
+ help
+ When this option is enabled, user applications can opt in to a
+ relaxed ABI via prctl() allowing tagged addresses to be passed
+ to system calls as pointer arguments. For details, see
+ Documentation/arm64/tagged-address-abi.txt.
+
menuconfig COMPAT
bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT
@@ -1263,6 +1290,7 @@ config ARM64_PAN
config ARM64_LSE_ATOMICS
bool "Atomic instructions"
+ depends on JUMP_LABEL
default y
help
As part of the Large System Extensions, ARMv8.1 introduces new
@@ -1467,6 +1495,7 @@ endif
config RELOCATABLE
bool
+ select ARCH_HAS_RELR
help
This builds the kernel as a Position Independent Executable (PIE),
which retains all relocation metadata required to relocate the
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 4778c775de1b..16d761475a86 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -77,6 +77,7 @@ config ARCH_BRCMSTB
config ARCH_EXYNOS
bool "ARMv8 based Samsung Exynos SoC family"
select COMMON_CLK_SAMSUNG
+ select EXYNOS_CHIPID
select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
select EXYNOS_PMU
select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -173,6 +174,7 @@ config ARCH_MXC
select PM
select PM_GENERIC_DOMAINS
select SOC_BUS
+ select TIMER_IMX_SYS_CTR
help
This enables support for the ARMv8 based SoCs in the
NXP i.MX family.
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index bb1f1dbb34e8..f843d298792d 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -39,6 +39,12 @@ $(warning LSE atomics not supported by binutils)
endif
endif
+cc_has_k_constraint := $(call try-run,echo \
+ 'int main(void) { \
+ asm volatile("and w0, w0, %w0" :: "K" (4294967295)); \
+ return 0; \
+ }' | $(CC) -S -x c -o "$$TMP" -,,-DCONFIG_CC_HAS_K_CONSTRAINT=1)
+
ifeq ($(CONFIG_ARM64), y)
brokengasinst := $(call as-instr,1:\n.inst 0\n.rept . - 1b\n\nnop\n.endr\n,,-DCONFIG_BROKEN_GAS_INST=1)
@@ -52,7 +58,7 @@ ifeq ($(CONFIG_GENERIC_COMPAT_VDSO), y)
ifeq ($(CONFIG_CC_IS_CLANG), y)
$(warning CROSS_COMPILE_COMPAT is clang, the compat vDSO will not be built)
- else ifeq ($(CROSS_COMPILE_COMPAT),)
+ else ifeq ($(strip $(CROSS_COMPILE_COMPAT)),)
$(warning CROSS_COMPILE_COMPAT not defined or empty, the compat vDSO will not be built)
else ifeq ($(shell which $(CROSS_COMPILE_COMPAT)gcc 2> /dev/null),)
$(error $(CROSS_COMPILE_COMPAT)gcc not found, check CROSS_COMPILE_COMPAT)
@@ -63,7 +69,8 @@ ifeq ($(CONFIG_GENERIC_COMPAT_VDSO), y)
endif
endif
-KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) $(compat_vdso)
+KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) \
+ $(compat_vdso) $(cc_has_k_constraint)
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
KBUILD_AFLAGS += $(lseinstr) $(brokengasinst) $(compat_vdso)
@@ -126,21 +133,9 @@ KBUILD_CFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
-# KASAN_SHADOW_OFFSET = VA_START + (1 << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT))
-# - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT))
-# in 32-bit arithmetic
-KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \
- (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \
- + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \
- - (1 << (64 - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) )) )
-
export TEXT_OFFSET GZFLAGS
-core-y += arch/arm64/kernel/ arch/arm64/mm/
-core-$(CONFIG_NET) += arch/arm64/net/
-core-$(CONFIG_KVM) += arch/arm64/kvm/
-core-$(CONFIG_XEN) += arch/arm64/xen/
-core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
+core-y += arch/arm64/
libs-y := arch/arm64/lib/ $(libs-y)
core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index f6db0611cb85..d2418021768b 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-oceanic-5205-5inmfd.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino-emmc.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
@@ -25,3 +26,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts
new file mode 100644
index 000000000000..96ab0227e82d
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Martin Ayotte <martinayotte@gmail.com>
+ * Copyright (C) 2019 Sunil Mohan Adapa <sunil@medhas.org>
+ */
+
+#include "sun50i-a64-olinuxino.dts"
+
+/ {
+ model = "Olimex A64-Olinuxino-eMMC";
+ compatible = "olimex,a64-olinuxino-emmc", "allwinner,sun50i-a64";
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_dcdc1>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
index 5ef3c62c765e..04446e4716c4 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
@@ -190,6 +190,10 @@
status = "okay";
};
+&r_ir {
+ status = "okay";
+};
+
&r_rsb {
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 9cc9bdde81ac..69128a6dfc46 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -228,10 +228,10 @@
display_clocks: clock@0 {
compatible = "allwinner,sun50i-a64-de2-clk";
reg = <0x0 0x100000>;
- clocks = <&ccu CLK_DE>,
- <&ccu CLK_BUS_DE>;
- clock-names = "mod",
- "bus";
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_DE>;
+ clock-names = "bus",
+ "mod";
resets = <&ccu RST_BUS_DE>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -1015,7 +1015,7 @@
resets = <&ccu RST_BUS_HDMI1>;
reset-names = "ctrl";
phys = <&hdmi_phy>;
- phy-names = "hdmi-phy";
+ phy-names = "phy";
status = "disabled";
ports {
@@ -1094,6 +1094,19 @@
#size-cells = <0>;
};
+ r_ir: ir@1f02000 {
+ compatible = "allwinner,sun50i-a64-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x01f02000 0x400>;
+ clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_APB0_IR>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_ir_rx_pin>;
+ status = "disabled";
+ };
+
r_pwm: pwm@1f03800 {
compatible = "allwinner,sun50i-a64-pwm",
"allwinner,sun5i-a13-pwm";
@@ -1121,6 +1134,11 @@
function = "s_i2c";
};
+ r_ir_rx_pin: r-ir-rx-pin {
+ pins = "PL11";
+ function = "s_cir_rx";
+ };
+
r_pwm_pin: r-pwm-pin {
pins = "PL10";
function = "s_pwm";
@@ -1151,6 +1169,7 @@
"allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
index 0dc33c90dd60..1d05d570142f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
@@ -25,6 +25,7 @@
connector {
compatible = "hdmi-connector";
type = "a";
+ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */
port {
hdmi_con_in: endpoint {
@@ -51,6 +52,24 @@
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
+
+ sound-spdif {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "sun50i-h6-spdif";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_out>;
+ };
+ };
+
+ spdif_out: spdif-out {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ };
};
&de {
@@ -232,6 +251,10 @@
};
};
+&r_ir {
+ status = "okay";
+};
+
&r_pio {
/*
* PL0 and PL1 are used for PMIC I2C
@@ -243,6 +266,10 @@
vcc-pm-supply = <&reg_aldo1>;
};
+&spdif {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_ph_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
index 17d496990108..eb379cd402ac 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
@@ -21,6 +21,18 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -44,12 +56,44 @@
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
+
+ reg_vcc33_wifi: vcc33-wifi {
+ /* Always on 3.3V regulator for WiFi and BT */
+ 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 {
+ /* Always on 1.8V/300mA regulator for WiFi and BT 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 = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */
+ post-power-on-delay-ms = <200>;
+ };
};
&cpu0 {
cpu-supply = <&reg_dcdca>;
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -58,6 +102,16 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
@@ -65,6 +119,23 @@
status = "okay";
};
+&mmc1 {
+ vmmc-supply = <&reg_vcc33_wifi>;
+ vqmmc-supply = <&reg_vcc_wifi_io>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ brcm: sdio-wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&r_pio>;
+ interrupts = <1 0 IRQ_TYPE_LEVEL_LOW>; /* PM0 */
+ interrupt-names = "host-wake";
+ };
+};
+
&ohci0 {
status = "okay";
};
@@ -76,6 +147,7 @@
&pio {
vcc-pc-supply = <&reg_bldo2>;
vcc-pd-supply = <&reg_cldo1>;
+ vcc-pg-supply = <&reg_vcc_wifi_io>;
};
&r_i2c {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
index 62e27948a3fa..ec9b6a578e3f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
@@ -189,6 +189,10 @@
};
};
+&r_ir {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_ph_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index 189834518391..30102daf83cc 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -255,6 +255,10 @@
};
};
+&r_ir {
+ status = "okay";
+};
+
&r_pio {
vcc-pm-supply = <&reg_aldo1>;
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
new file mode 100644
index 000000000000..7e7cb10e3d96
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (c) 2019 Jernej Skrabec <jernej.skrabec@siol.net>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Tanix TX6";
+ compatible = "oranth,tanix-tx6", "allwinner,sun50i-h6";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ connector {
+ compatible = "hdmi-connector";
+ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&de {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ vmmc-supply = <&reg_vcc3v3>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&r_ir {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usb2otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb2phy {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 7628a7c83096..4020a1aafa3e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -56,14 +56,6 @@
status = "disabled";
};
- iosc: internal-osc-clk {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <16000000>;
- clock-accuracy = <300000000>;
- clock-output-names = "iosc";
- };
-
osc24M: osc24M_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
@@ -71,11 +63,11 @@
clock-output-names = "osc24M";
};
- osc32k: osc32k_clk {
+ ext_osc32k: ext_osc32k_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
- clock-output-names = "osc32k";
+ clock-output-names = "ext_osc32k";
};
psci {
@@ -197,7 +189,7 @@
ccu: clock@3001000 {
compatible = "allwinner,sun50i-h6-ccu";
reg = <0x03001000 0x1000>;
- clocks = <&osc24M>, <&osc32k>, <&iosc>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
clock-names = "hosc", "losc", "iosc";
#clock-cells = <1>;
#reset-cells = <1>;
@@ -215,7 +207,7 @@
#dma-cells = <1>;
};
- sid: sid@3006000 {
+ sid: efuse@3006000 {
compatible = "allwinner,sun50i-h6-sid";
reg = <0x03006000 0x400>;
};
@@ -225,6 +217,7 @@
"allwinner,sun6i-a31-wdt";
reg = <0x030090a0 0x20>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
/* Broken on some H6 boards */
status = "disabled";
};
@@ -236,7 +229,7 @@
<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>;
+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
#gpio-cells = <3>;
@@ -256,6 +249,21 @@
function = "hdmi";
};
+ i2c0_pins: i2c0-pins {
+ pins = "PD25", "PD26";
+ function = "i2c0";
+ };
+
+ i2c1_pins: i2c1-pins {
+ pins = "PH5", "PH6";
+ function = "i2c1";
+ };
+
+ i2c2_pins: i2c2-pins {
+ pins = "PD23", "PD24";
+ function = "i2c2";
+ };
+
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3",
"PF4", "PF5";
@@ -282,6 +290,11 @@
bias-pull-up;
};
+ spdif_tx_pin: spdif-tx-pin {
+ pins = "PH7";
+ function = "spdif";
+ };
+
uart0_ph_pins: uart0-ph-pins {
pins = "PH0", "PH1";
function = "uart0";
@@ -391,6 +404,48 @@
status = "disabled";
};
+ i2c0: i2c@5002000 {
+ compatible = "allwinner,sun50i-h6-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002000 0x400>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@5002400 {
+ compatible = "allwinner,sun50i-h6-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002400 0x400>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@5002800 {
+ compatible = "allwinner,sun50i-h6-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002800 0x400>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
emac: ethernet@5020000 {
compatible = "allwinner,sun50i-h6-emac",
"allwinner,sun50i-a64-emac";
@@ -411,6 +466,21 @@
};
};
+ spdif: spdif@5093000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun50i-h6-spdif";
+ reg = <0x05093000 0x400>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
+ clock-names = "apb", "spdif";
+ resets = <&ccu RST_BUS_SPDIF>;
+ dmas = <&dma 2>;
+ dma-names = "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdif_tx_pin>;
+ status = "disabled";
+ };
+
usb2otg: usb@5100000 {
compatible = "allwinner,sun50i-h6-musb",
"allwinner,sun8i-a33-musb";
@@ -504,7 +574,7 @@
resets = <&ccu RST_BUS_HDMI_SUB>, <&ccu RST_BUS_HDCP>;
reset-names = "ctrl", "hdcp";
phys = <&hdmi_phy>;
- phy-names = "hdmi-phy";
+ phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
status = "disabled";
@@ -633,10 +703,20 @@
};
};
+ rtc: rtc@7000000 {
+ compatible = "allwinner,sun50i-h6-rtc";
+ reg = <0x07000000 0x400>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clock-output-names = "osc32k", "osc32k-out", "iosc";
+ clocks = <&ext_osc32k>;
+ #clock-cells = <1>;
+ };
+
r_ccu: clock@7010000 {
compatible = "allwinner,sun50i-h6-r-ccu";
reg = <0x07010000 0x400>;
- clocks = <&osc24M>, <&osc32k>, <&iosc>,
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>,
<&ccu CLK_PLL_PERIPH0>;
clock-names = "hosc", "losc", "iosc", "pll-periph";
#clock-cells = <1>;
@@ -648,6 +728,7 @@
"allwinner,sun6i-a31-wdt";
reg = <0x07020400 0x20>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
};
r_intc: interrupt-controller@7021000 {
@@ -664,7 +745,7 @@
reg = <0x07022000 0x400>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k>;
+ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
#gpio-cells = <3>;
@@ -675,10 +756,30 @@
pins = "PL0", "PL1";
function = "s_i2c";
};
+
+ r_ir_rx_pin: r-ir-rx-pin {
+ pins = "PL9";
+ function = "s_cir_rx";
+ };
+ };
+
+ r_ir: ir@7040000 {
+ compatible = "allwinner,sun50i-h6-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x07040000 0x400>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1_IR>,
+ <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_R_APB1_IR>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_ir_rx_pin>;
+ status = "disabled";
};
r_i2c: i2c@7081400 {
- compatible = "allwinner,sun6i-a31-i2c";
+ compatible = "allwinner,sun50i-h6-i2c",
+ "allwinner,sun6i-a31-i2c";
reg = <0x07081400 0x400>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_R_APB2_I2C>;
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index b05d78164fc1..144a2c19ac02 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -302,6 +302,22 @@
status = "disabled";
};
+ nand: nand@ffb90000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "altr,socfpga-denali-nand";
+ reg = <0xffb90000 0x10000>,
+ <0xffb80000 0x1000>;
+ reg-names = "nand_data", "denali_reg";
+ interrupts = <0 97 4>;
+ clocks = <&clkmgr STRATIX10_NAND_CLK>,
+ <&clkmgr STRATIX10_NAND_X_CLK>,
+ <&clkmgr STRATIX10_NAND_ECC_CLK>;
+ clock-names = "nand", "nand_x", "ecc";
+ resets = <&rst NAND_RESET>, <&rst NAND_OCP_RESET>;
+ status = "disabled";
+ };
+
ocram: sram@ffe00000 {
compatible = "mmio-sram";
reg = <0xffe00000 0x100000>;
@@ -324,6 +340,8 @@
#dma-requests = <32>;
clocks = <&clkmgr STRATIX10_L4_MAIN_CLK>;
clock-names = "apb_pclk";
+ resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>;
+ reset-names = "dma", "dma-ocp";
};
rst: rstmgr@ffd11000 {
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 07b861fe5fa5..84afecba9ec0 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -3,6 +3,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12a-sei510.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb
@@ -32,3 +34,5 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-sm1-sei610.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-sm1-khadas-vim3l.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 6219337033a0..82919b106010 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -174,14 +174,16 @@
compatible = "amlogic,meson-axg-dwmac",
"snps,dwmac-3.70a",
"snps,dwmac";
- reg = <0x0 0xff3f0000 0x0 0x10000
- 0x0 0xff634540 0x0 0x8>;
+ reg = <0x0 0xff3f0000 0x0 0x10000>,
+ <0x0 0xff634540 0x0 0x8>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
clocks = <&clkc CLKID_ETH>,
<&clkc CLKID_FCLK_DIV2>,
<&clkc CLKID_MPLL2>;
clock-names = "stmmaceth", "clkin0", "clkin1";
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <2048>;
status = "disabled";
};
@@ -1116,7 +1118,7 @@
};
mailbox: mailbox@ff63c404 {
- compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
+ compatible = "amlogic,meson-gxbb-mhu";
reg = <0 0xff63c404 0 0x4c>;
interrupts = <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 209 IRQ_TYPE_EDGE_RISING>,
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
new file mode 100644
index 000000000000..3f39e020f74e
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -0,0 +1,2435 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Amlogic, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/axg-audio-clkc.h>
+#include <dt-bindings/clock/g12a-clkc.h>
+#include <dt-bindings/clock/g12a-aoclkc.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
+#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
+#include <dt-bindings/reset/amlogic,meson-g12a-reset.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ tdmif_a: audio-controller-0 {
+ 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";
+ status = "disabled";
+ };
+
+ tdmif_b: audio-controller-1 {
+ 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";
+ status = "disabled";
+ };
+
+ tdmif_c: audio-controller-2 {
+ 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";
+ status = "disabled";
+ };
+
+ efuse: efuse {
+ compatible = "amlogic,meson-gxbb-efuse";
+ clocks = <&clkc CLKID_EFUSE>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ read-only;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* 3 MiB reserved for ARM Trusted Firmware (BL31) */
+ secmon_reserved: secmon@5000000 {
+ reg = <0x0 0x05000000 0x0 0x300000>;
+ no-map;
+ };
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x10000000>;
+ alignment = <0x0 0x400000>;
+ linux,cma-default;
+ };
+ };
+
+ sm: secure-monitor {
+ compatible = "amlogic,meson-gxbb-sm";
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ethmac: ethernet@ff3f0000 {
+ compatible = "amlogic,meson-axg-dwmac",
+ "snps,dwmac-3.70a",
+ "snps,dwmac";
+ reg = <0x0 0xff3f0000 0x0 0x10000>,
+ <0x0 0xff634540 0x0 0x8>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&clkc CLKID_ETH>,
+ <&clkc CLKID_FCLK_DIV2>,
+ <&clkc CLKID_MPLL2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1";
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <2048>;
+ status = "disabled";
+
+ mdio0: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ };
+ };
+
+ apb: bus@ff600000 {
+ compatible = "simple-bus";
+ reg = <0x0 0xff600000 0x0 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xff600000 0x0 0x200000>;
+
+ hdmi_tx: hdmi-tx@0 {
+ compatible = "amlogic,meson-g12a-dw-hdmi";
+ reg = <0x0 0x0 0x0 0x10000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
+ resets = <&reset RESET_HDMITX_CAPB3>,
+ <&reset RESET_HDMITX_PHY>,
+ <&reset RESET_HDMITX>;
+ reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
+ clocks = <&clkc CLKID_HDMI>,
+ <&clkc CLKID_HTX_PCLK>,
+ <&clkc CLKID_VPU_INTR>;
+ clock-names = "isfr", "iahb", "venci";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+
+ /* VPU VENC Input */
+ hdmi_tx_venc_port: port@0 {
+ reg = <0>;
+
+ hdmi_tx_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+
+ /* TMDS Output */
+ hdmi_tx_tmds_port: port@1 {
+ reg = <1>;
+ };
+ };
+
+ apb_efuse: bus@30000 {
+ compatible = "simple-bus";
+ reg = <0x0 0x30000 0x0 0x2000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x30000 0x0 0x2000>;
+
+ hwrng: rng@218 {
+ compatible = "amlogic,meson-rng";
+ reg = <0x0 0x218 0x0 0x4>;
+ };
+ };
+
+ periphs: bus@34400 {
+ compatible = "simple-bus";
+ reg = <0x0 0x34400 0x0 0x400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>;
+
+ periphs_pinctrl: pinctrl@40 {
+ compatible = "amlogic,meson-g12a-periphs-pinctrl";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio: bank@40 {
+ reg = <0x0 0x40 0x0 0x4c>,
+ <0x0 0xe8 0x0 0x18>,
+ <0x0 0x120 0x0 0x18>,
+ <0x0 0x2c0 0x0 0x40>,
+ <0x0 0x340 0x0 0x1c>;
+ reg-names = "gpio",
+ "pull",
+ "pull-enable",
+ "mux",
+ "ds";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&periphs_pinctrl 0 0 86>;
+ };
+
+ cec_ao_a_h_pins: cec_ao_a_h {
+ mux {
+ groups = "cec_ao_a_h";
+ function = "cec_ao_a_h";
+ bias-disable;
+ };
+ };
+
+ cec_ao_b_h_pins: cec_ao_b_h {
+ mux {
+ groups = "cec_ao_b_h";
+ function = "cec_ao_b_h";
+ bias-disable;
+ };
+ };
+
+ emmc_pins: emmc {
+ mux-0 {
+ groups = "emmc_nand_d0",
+ "emmc_nand_d1",
+ "emmc_nand_d2",
+ "emmc_nand_d3",
+ "emmc_nand_d4",
+ "emmc_nand_d5",
+ "emmc_nand_d6",
+ "emmc_nand_d7",
+ "emmc_cmd";
+ function = "emmc";
+ bias-pull-up;
+ drive-strength-microamp = <4000>;
+ };
+
+ mux-1 {
+ groups = "emmc_clk";
+ function = "emmc";
+ bias-disable;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ emmc_ds_pins: emmc-ds {
+ mux {
+ groups = "emmc_nand_ds";
+ function = "emmc";
+ bias-pull-down;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ emmc_clk_gate_pins: emmc_clk_gate {
+ mux {
+ groups = "BOOT_8";
+ function = "gpio_periphs";
+ bias-pull-down;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ hdmitx_ddc_pins: hdmitx_ddc {
+ mux {
+ groups = "hdmitx_sda",
+ "hdmitx_sck";
+ function = "hdmitx";
+ bias-disable;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ hdmitx_hpd_pins: hdmitx_hpd {
+ mux {
+ groups = "hdmitx_hpd_in";
+ function = "hdmitx";
+ bias-disable;
+ };
+ };
+
+
+ i2c0_sda_c_pins: i2c0-sda-c {
+ mux {
+ groups = "i2c0_sda_c";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+
+ };
+ };
+
+ i2c0_sck_c_pins: i2c0-sck-c {
+ mux {
+ groups = "i2c0_sck_c";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_sda_z0_pins: i2c0-sda-z0 {
+ mux {
+ groups = "i2c0_sda_z0";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_sck_z1_pins: i2c0-sck-z1 {
+ mux {
+ groups = "i2c0_sck_z1";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_sda_z7_pins: i2c0-sda-z7 {
+ mux {
+ groups = "i2c0_sda_z7";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_sda_z8_pins: i2c0-sda-z8 {
+ mux {
+ groups = "i2c0_sda_z8";
+ function = "i2c0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sda_x_pins: i2c1-sda-x {
+ mux {
+ groups = "i2c1_sda_x";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sck_x_pins: i2c1-sck-x {
+ mux {
+ groups = "i2c1_sck_x";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sda_h2_pins: i2c1-sda-h2 {
+ mux {
+ groups = "i2c1_sda_h2";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sck_h3_pins: i2c1-sck-h3 {
+ mux {
+ groups = "i2c1_sck_h3";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sda_h6_pins: i2c1-sda-h6 {
+ mux {
+ groups = "i2c1_sda_h6";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_sck_h7_pins: i2c1-sck-h7 {
+ mux {
+ groups = "i2c1_sck_h7";
+ function = "i2c1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_sda_x_pins: i2c2-sda-x {
+ mux {
+ groups = "i2c2_sda_x";
+ function = "i2c2";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_sck_x_pins: i2c2-sck-x {
+ mux {
+ groups = "i2c2_sck_x";
+ function = "i2c2";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_sda_z_pins: i2c2-sda-z {
+ mux {
+ groups = "i2c2_sda_z";
+ function = "i2c2";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_sck_z_pins: i2c2-sck-z {
+ mux {
+ groups = "i2c2_sck_z";
+ function = "i2c2";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_sda_h_pins: i2c3-sda-h {
+ mux {
+ groups = "i2c3_sda_h";
+ function = "i2c3";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_sck_h_pins: i2c3-sck-h {
+ mux {
+ groups = "i2c3_sck_h";
+ function = "i2c3";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_sda_a_pins: i2c3-sda-a {
+ mux {
+ groups = "i2c3_sda_a";
+ function = "i2c3";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_sck_a_pins: i2c3-sck-a {
+ mux {
+ groups = "i2c3_sck_a";
+ function = "i2c3";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ mclk0_a_pins: mclk0-a {
+ mux {
+ groups = "mclk0_a";
+ function = "mclk0";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ mclk1_a_pins: mclk1-a {
+ mux {
+ groups = "mclk1_a";
+ function = "mclk1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ mclk1_x_pins: mclk1-x {
+ mux {
+ groups = "mclk1_x";
+ function = "mclk1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ mclk1_z_pins: mclk1-z {
+ mux {
+ groups = "mclk1_z";
+ function = "mclk1";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ pdm_din0_a_pins: pdm-din0-a {
+ mux {
+ groups = "pdm_din0_a";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din0_c_pins: pdm-din0-c {
+ mux {
+ groups = "pdm_din0_c";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din0_x_pins: pdm-din0-x {
+ mux {
+ groups = "pdm_din0_x";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din0_z_pins: pdm-din0-z {
+ mux {
+ groups = "pdm_din0_z";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din1_a_pins: pdm-din1-a {
+ mux {
+ groups = "pdm_din1_a";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din1_c_pins: pdm-din1-c {
+ mux {
+ groups = "pdm_din1_c";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din1_x_pins: pdm-din1-x {
+ mux {
+ groups = "pdm_din1_x";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din1_z_pins: pdm-din1-z {
+ mux {
+ groups = "pdm_din1_z";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din2_a_pins: pdm-din2-a {
+ mux {
+ groups = "pdm_din2_a";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din2_c_pins: pdm-din2-c {
+ mux {
+ groups = "pdm_din2_c";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din2_x_pins: pdm-din2-x {
+ mux {
+ groups = "pdm_din2_x";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din2_z_pins: pdm-din2-z {
+ mux {
+ groups = "pdm_din2_z";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din3_a_pins: pdm-din3-a {
+ mux {
+ groups = "pdm_din3_a";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din3_c_pins: pdm-din3-c {
+ mux {
+ groups = "pdm_din3_c";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din3_x_pins: pdm-din3-x {
+ mux {
+ groups = "pdm_din3_x";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_din3_z_pins: pdm-din3-z {
+ mux {
+ groups = "pdm_din3_z";
+ function = "pdm";
+ bias-disable;
+ };
+ };
+
+ pdm_dclk_a_pins: pdm-dclk-a {
+ mux {
+ groups = "pdm_dclk_a";
+ function = "pdm";
+ bias-disable;
+ drive-strength-microamp = <500>;
+ };
+ };
+
+ pdm_dclk_c_pins: pdm-dclk-c {
+ mux {
+ groups = "pdm_dclk_c";
+ function = "pdm";
+ bias-disable;
+ drive-strength-microamp = <500>;
+ };
+ };
+
+ pdm_dclk_x_pins: pdm-dclk-x {
+ mux {
+ groups = "pdm_dclk_x";
+ function = "pdm";
+ bias-disable;
+ drive-strength-microamp = <500>;
+ };
+ };
+
+ pdm_dclk_z_pins: pdm-dclk-z {
+ mux {
+ groups = "pdm_dclk_z";
+ function = "pdm";
+ bias-disable;
+ drive-strength-microamp = <500>;
+ };
+ };
+
+ pwm_a_pins: pwm-a {
+ mux {
+ groups = "pwm_a";
+ function = "pwm_a";
+ bias-disable;
+ };
+ };
+
+ pwm_b_x7_pins: pwm-b-x7 {
+ mux {
+ groups = "pwm_b_x7";
+ function = "pwm_b";
+ bias-disable;
+ };
+ };
+
+ pwm_b_x19_pins: pwm-b-x19 {
+ mux {
+ groups = "pwm_b_x19";
+ function = "pwm_b";
+ bias-disable;
+ };
+ };
+
+ pwm_c_c_pins: pwm-c-c {
+ mux {
+ groups = "pwm_c_c";
+ function = "pwm_c";
+ bias-disable;
+ };
+ };
+
+ pwm_c_x5_pins: pwm-c-x5 {
+ mux {
+ groups = "pwm_c_x5";
+ function = "pwm_c";
+ bias-disable;
+ };
+ };
+
+ pwm_c_x8_pins: pwm-c-x8 {
+ mux {
+ groups = "pwm_c_x8";
+ function = "pwm_c";
+ bias-disable;
+ };
+ };
+
+ pwm_d_x3_pins: pwm-d-x3 {
+ mux {
+ groups = "pwm_d_x3";
+ function = "pwm_d";
+ bias-disable;
+ };
+ };
+
+ pwm_d_x6_pins: pwm-d-x6 {
+ mux {
+ groups = "pwm_d_x6";
+ function = "pwm_d";
+ bias-disable;
+ };
+ };
+
+ pwm_e_pins: pwm-e {
+ mux {
+ groups = "pwm_e";
+ function = "pwm_e";
+ bias-disable;
+ };
+ };
+
+ pwm_f_x_pins: pwm-f-x {
+ mux {
+ groups = "pwm_f_x";
+ function = "pwm_f";
+ bias-disable;
+ };
+ };
+
+ pwm_f_h_pins: pwm-f-h {
+ mux {
+ groups = "pwm_f_h";
+ function = "pwm_f";
+ bias-disable;
+ };
+ };
+
+ sdcard_c_pins: sdcard_c {
+ mux-0 {
+ groups = "sdcard_d0_c",
+ "sdcard_d1_c",
+ "sdcard_d2_c",
+ "sdcard_d3_c",
+ "sdcard_cmd_c";
+ function = "sdcard";
+ bias-pull-up;
+ drive-strength-microamp = <4000>;
+ };
+
+ mux-1 {
+ groups = "sdcard_clk_c";
+ function = "sdcard";
+ bias-disable;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ sdcard_clk_gate_c_pins: sdcard_clk_gate_c {
+ mux {
+ groups = "GPIOC_4";
+ function = "gpio_periphs";
+ bias-pull-down;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ sdcard_z_pins: sdcard_z {
+ mux-0 {
+ groups = "sdcard_d0_z",
+ "sdcard_d1_z",
+ "sdcard_d2_z",
+ "sdcard_d3_z",
+ "sdcard_cmd_z";
+ function = "sdcard";
+ bias-pull-up;
+ drive-strength-microamp = <4000>;
+ };
+
+ mux-1 {
+ groups = "sdcard_clk_z";
+ function = "sdcard";
+ bias-disable;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ sdcard_clk_gate_z_pins: sdcard_clk_gate_z {
+ mux {
+ groups = "GPIOZ_6";
+ function = "gpio_periphs";
+ bias-pull-down;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ sdio_pins: sdio {
+ mux {
+ groups = "sdio_d0",
+ "sdio_d1",
+ "sdio_d2",
+ "sdio_d3",
+ "sdio_clk",
+ "sdio_cmd";
+ function = "sdio";
+ bias-disable;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ sdio_clk_gate_pins: sdio_clk_gate {
+ mux {
+ groups = "GPIOX_4";
+ function = "gpio_periphs";
+ bias-pull-down;
+ drive-strength-microamp = <4000>;
+ };
+ };
+
+ spdif_in_a10_pins: spdif-in-a10 {
+ mux {
+ groups = "spdif_in_a10";
+ function = "spdif_in";
+ bias-disable;
+ };
+ };
+
+ spdif_in_a12_pins: spdif-in-a12 {
+ mux {
+ groups = "spdif_in_a12";
+ function = "spdif_in";
+ bias-disable;
+ };
+ };
+
+ spdif_in_h_pins: spdif-in-h {
+ mux {
+ groups = "spdif_in_h";
+ function = "spdif_in";
+ bias-disable;
+ };
+ };
+
+ spdif_out_h_pins: spdif-out-h {
+ mux {
+ groups = "spdif_out_h";
+ function = "spdif_out";
+ drive-strength-microamp = <500>;
+ bias-disable;
+ };
+ };
+
+ spdif_out_a11_pins: spdif-out-a11 {
+ mux {
+ groups = "spdif_out_a11";
+ function = "spdif_out";
+ drive-strength-microamp = <500>;
+ bias-disable;
+ };
+ };
+
+ spdif_out_a13_pins: spdif-out-a13 {
+ mux {
+ groups = "spdif_out_a13";
+ function = "spdif_out";
+ drive-strength-microamp = <500>;
+ bias-disable;
+ };
+ };
+
+ tdm_a_din0_pins: tdm-a-din0 {
+ mux {
+ groups = "tdm_a_din0";
+ function = "tdm_a";
+ bias-disable;
+ };
+ };
+
+
+ tdm_a_din1_pins: tdm-a-din1 {
+ mux {
+ groups = "tdm_a_din1";
+ function = "tdm_a";
+ bias-disable;
+ };
+ };
+
+ tdm_a_dout0_pins: tdm-a-dout0 {
+ mux {
+ groups = "tdm_a_dout0";
+ function = "tdm_a";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_a_dout1_pins: tdm-a-dout1 {
+ mux {
+ groups = "tdm_a_dout1";
+ function = "tdm_a";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_a_fs_pins: tdm-a-fs {
+ mux {
+ groups = "tdm_a_fs";
+ function = "tdm_a";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_a_sclk_pins: tdm-a-sclk {
+ mux {
+ groups = "tdm_a_sclk";
+ function = "tdm_a";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_a_slv_fs_pins: tdm-a-slv-fs {
+ mux {
+ groups = "tdm_a_slv_fs";
+ function = "tdm_a";
+ bias-disable;
+ };
+ };
+
+
+ tdm_a_slv_sclk_pins: tdm-a-slv-sclk {
+ mux {
+ groups = "tdm_a_slv_sclk";
+ function = "tdm_a";
+ bias-disable;
+ };
+ };
+
+ tdm_b_din0_pins: tdm-b-din0 {
+ mux {
+ groups = "tdm_b_din0";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_din1_pins: tdm-b-din1 {
+ mux {
+ groups = "tdm_b_din1";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_din2_pins: tdm-b-din2 {
+ mux {
+ groups = "tdm_b_din2";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_din3_a_pins: tdm-b-din3-a {
+ mux {
+ groups = "tdm_b_din3_a";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_din3_h_pins: tdm-b-din3-h {
+ mux {
+ groups = "tdm_b_din3_h";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_dout0_pins: tdm-b-dout0 {
+ mux {
+ groups = "tdm_b_dout0";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_dout1_pins: tdm-b-dout1 {
+ mux {
+ groups = "tdm_b_dout1";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_dout2_pins: tdm-b-dout2 {
+ mux {
+ groups = "tdm_b_dout2";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_dout3_a_pins: tdm-b-dout3-a {
+ mux {
+ groups = "tdm_b_dout3_a";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_dout3_h_pins: tdm-b-dout3-h {
+ mux {
+ groups = "tdm_b_dout3_h";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_fs_pins: tdm-b-fs {
+ mux {
+ groups = "tdm_b_fs";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_sclk_pins: tdm-b-sclk {
+ mux {
+ groups = "tdm_b_sclk";
+ function = "tdm_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_b_slv_fs_pins: tdm-b-slv-fs {
+ mux {
+ groups = "tdm_b_slv_fs";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_b_slv_sclk_pins: tdm-b-slv-sclk {
+ mux {
+ groups = "tdm_b_slv_sclk";
+ function = "tdm_b";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din0_a_pins: tdm-c-din0-a {
+ mux {
+ groups = "tdm_c_din0_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din0_z_pins: tdm-c-din0-z {
+ mux {
+ groups = "tdm_c_din0_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din1_a_pins: tdm-c-din1-a {
+ mux {
+ groups = "tdm_c_din1_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din1_z_pins: tdm-c-din1-z {
+ mux {
+ groups = "tdm_c_din1_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din2_a_pins: tdm-c-din2-a {
+ mux {
+ groups = "tdm_c_din2_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ eth_leds_pins: eth-leds {
+ mux {
+ groups = "eth_link_led",
+ "eth_act_led";
+ function = "eth";
+ bias-disable;
+ };
+ };
+
+ eth_pins: eth {
+ mux {
+ groups = "eth_mdio",
+ "eth_mdc",
+ "eth_rgmii_rx_clk",
+ "eth_rx_dv",
+ "eth_rxd0",
+ "eth_rxd1",
+ "eth_txen",
+ "eth_txd0",
+ "eth_txd1";
+ function = "eth";
+ drive-strength-microamp = <4000>;
+ bias-disable;
+ };
+ };
+
+ eth_rgmii_pins: eth-rgmii {
+ mux {
+ groups = "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ drive-strength-microamp = <4000>;
+ bias-disable;
+ };
+ };
+
+ tdm_c_din2_z_pins: tdm-c-din2-z {
+ mux {
+ groups = "tdm_c_din2_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din3_a_pins: tdm-c-din3-a {
+ mux {
+ groups = "tdm_c_din3_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_din3_z_pins: tdm-c-din3-z {
+ mux {
+ groups = "tdm_c_din3_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_dout0_a_pins: tdm-c-dout0-a {
+ mux {
+ groups = "tdm_c_dout0_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout0_z_pins: tdm-c-dout0-z {
+ mux {
+ groups = "tdm_c_dout0_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout1_a_pins: tdm-c-dout1-a {
+ mux {
+ groups = "tdm_c_dout1_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout1_z_pins: tdm-c-dout1-z {
+ mux {
+ groups = "tdm_c_dout1_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout2_a_pins: tdm-c-dout2-a {
+ mux {
+ groups = "tdm_c_dout2_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout2_z_pins: tdm-c-dout2-z {
+ mux {
+ groups = "tdm_c_dout2_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout3_a_pins: tdm-c-dout3-a {
+ mux {
+ groups = "tdm_c_dout3_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_dout3_z_pins: tdm-c-dout3-z {
+ mux {
+ groups = "tdm_c_dout3_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_fs_a_pins: tdm-c-fs-a {
+ mux {
+ groups = "tdm_c_fs_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_fs_z_pins: tdm-c-fs-z {
+ mux {
+ groups = "tdm_c_fs_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_sclk_a_pins: tdm-c-sclk-a {
+ mux {
+ groups = "tdm_c_sclk_a";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_sclk_z_pins: tdm-c-sclk-z {
+ mux {
+ groups = "tdm_c_sclk_z";
+ function = "tdm_c";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_c_slv_fs_a_pins: tdm-c-slv-fs-a {
+ mux {
+ groups = "tdm_c_slv_fs_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_slv_fs_z_pins: tdm-c-slv-fs-z {
+ mux {
+ groups = "tdm_c_slv_fs_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_slv_sclk_a_pins: tdm-c-slv-sclk-a {
+ mux {
+ groups = "tdm_c_slv_sclk_a";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ tdm_c_slv_sclk_z_pins: tdm-c-slv-sclk-z {
+ mux {
+ groups = "tdm_c_slv_sclk_z";
+ function = "tdm_c";
+ bias-disable;
+ };
+ };
+
+ uart_a_pins: uart-a {
+ mux {
+ groups = "uart_a_tx",
+ "uart_a_rx";
+ function = "uart_a";
+ bias-disable;
+ };
+ };
+
+ uart_a_cts_rts_pins: uart-a-cts-rts {
+ mux {
+ groups = "uart_a_cts",
+ "uart_a_rts";
+ function = "uart_a";
+ bias-disable;
+ };
+ };
+
+ uart_b_pins: uart-b {
+ mux {
+ groups = "uart_b_tx",
+ "uart_b_rx";
+ function = "uart_b";
+ bias-disable;
+ };
+ };
+
+ uart_c_pins: uart-c {
+ mux {
+ groups = "uart_c_tx",
+ "uart_c_rx";
+ function = "uart_c";
+ bias-disable;
+ };
+ };
+
+ uart_c_cts_rts_pins: uart-c-cts-rts {
+ mux {
+ groups = "uart_c_cts",
+ "uart_c_rts";
+ function = "uart_c";
+ bias-disable;
+ };
+ };
+ };
+ };
+
+ usb2_phy0: phy@36000 {
+ compatible = "amlogic,g12a-usb2-phy";
+ reg = <0x0 0x36000 0x0 0x2000>;
+ clocks = <&xtal>;
+ clock-names = "xtal";
+ resets = <&reset RESET_USB_PHY20>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
+
+ dmc: bus@38000 {
+ compatible = "simple-bus";
+ reg = <0x0 0x38000 0x0 0x400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>;
+
+ canvas: video-lut@48 {
+ compatible = "amlogic,canvas";
+ reg = <0x0 0x48 0x0 0x14>;
+ };
+ };
+
+ usb2_phy1: phy@3a000 {
+ compatible = "amlogic,g12a-usb2-phy";
+ reg = <0x0 0x3a000 0x0 0x2000>;
+ clocks = <&xtal>;
+ clock-names = "xtal";
+ resets = <&reset RESET_USB_PHY21>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
+
+ hiu: bus@3c000 {
+ compatible = "simple-bus";
+ reg = <0x0 0x3c000 0x0 0x1400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x3c000 0x0 0x1400>;
+
+ hhi: system-controller@0 {
+ compatible = "amlogic,meson-gx-hhi-sysctrl",
+ "simple-mfd", "syscon";
+ reg = <0 0 0 0x400>;
+
+ clkc: clock-controller {
+ compatible = "amlogic,g12a-clkc";
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "xtal";
+ };
+
+ pwrc: power-controller {
+ compatible = "amlogic,meson-g12a-pwrc";
+ #power-domain-cells = <1>;
+ amlogic,ao-sysctrl = <&rti>;
+ resets = <&reset RESET_VIU>,
+ <&reset RESET_VENC>,
+ <&reset RESET_VCBUS>,
+ <&reset RESET_BT656>,
+ <&reset RESET_RDMA>,
+ <&reset RESET_VENCI>,
+ <&reset RESET_VENCP>,
+ <&reset RESET_VDAC>,
+ <&reset RESET_VDI6>,
+ <&reset RESET_VENCL>,
+ <&reset RESET_VID_LOCK>;
+ reset-names = "viu", "venc", "vcbus", "bt656",
+ "rdma", "venci", "vencp", "vdac",
+ "vdi6", "vencl", "vid_lock";
+ clocks = <&clkc CLKID_VPU>,
+ <&clkc CLKID_VAPB>;
+ clock-names = "vpu", "vapb";
+ /*
+ * VPU clocking is provided by two identical clock paths
+ * VPU_0 and VPU_1 muxed to a single clock by a glitch
+ * free mux to safely change frequency while running.
+ * Same for VAPB but with a final gate after the glitch free mux.
+ */
+ assigned-clocks = <&clkc CLKID_VPU_0_SEL>,
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_VPU>, /* Glitch free mux */
+ <&clkc CLKID_VAPB_0_SEL>,
+ <&clkc CLKID_VAPB_0>,
+ <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */
+ assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_FCLK_DIV4>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VAPB_0>;
+ assigned-clock-rates = <0>, /* Do Nothing */
+ <666666666>,
+ <0>, /* Do Nothing */
+ <0>, /* Do Nothing */
+ <250000000>,
+ <0>; /* Do Nothing */
+ };
+ };
+ };
+
+ pdm: audio-controller@40000 {
+ compatible = "amlogic,g12a-pdm",
+ "amlogic,axg-pdm";
+ reg = <0x0 0x40000 0x0 0x34>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "PDM";
+ clocks = <&clkc_audio AUD_CLKID_PDM>,
+ <&clkc_audio AUD_CLKID_PDM_DCLK>,
+ <&clkc_audio AUD_CLKID_PDM_SYSCLK>;
+ clock-names = "pclk", "dclk", "sysclk";
+ status = "disabled";
+ };
+
+ audio: bus@42000 {
+ compatible = "simple-bus";
+ reg = <0x0 0x42000 0x0 0x2000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x42000 0x0 0x2000>;
+
+ clkc_audio: clock-controller@0 {
+ status = "disabled";
+ compatible = "amlogic,g12a-audio-clkc";
+ reg = <0x0 0x0 0x0 0xb4>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ clocks = <&clkc CLKID_AUDIO>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL3>,
+ <&clkc CLKID_HIFI_PLL>,
+ <&clkc CLKID_FCLK_DIV3>,
+ <&clkc CLKID_FCLK_DIV4>,
+ <&clkc CLKID_GP0_PLL>;
+ clock-names = "pclk",
+ "mst_in0",
+ "mst_in1",
+ "mst_in2",
+ "mst_in3",
+ "mst_in4",
+ "mst_in5",
+ "mst_in6",
+ "mst_in7";
+
+ resets = <&reset RESET_AUDIO>;
+ };
+
+ toddr_a: audio-controller@100 {
+ compatible = "amlogic,g12a-toddr",
+ "amlogic,axg-toddr";
+ reg = <0x0 0x100 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "TODDR_A";
+ interrupts = <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_TODDR_A>;
+ resets = <&arb AXG_ARB_TODDR_A>;
+ status = "disabled";
+ };
+
+ toddr_b: audio-controller@140 {
+ compatible = "amlogic,g12a-toddr",
+ "amlogic,axg-toddr";
+ reg = <0x0 0x140 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "TODDR_B";
+ interrupts = <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_TODDR_B>;
+ resets = <&arb AXG_ARB_TODDR_B>;
+ status = "disabled";
+ };
+
+ toddr_c: audio-controller@180 {
+ compatible = "amlogic,g12a-toddr",
+ "amlogic,axg-toddr";
+ reg = <0x0 0x180 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "TODDR_C";
+ interrupts = <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_TODDR_C>;
+ resets = <&arb AXG_ARB_TODDR_C>;
+ status = "disabled";
+ };
+
+ frddr_a: audio-controller@1c0 {
+ compatible = "amlogic,g12a-frddr",
+ "amlogic,axg-frddr";
+ reg = <0x0 0x1c0 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "FRDDR_A";
+ interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
+ resets = <&arb AXG_ARB_FRDDR_A>;
+ status = "disabled";
+ };
+
+ frddr_b: audio-controller@200 {
+ compatible = "amlogic,g12a-frddr",
+ "amlogic,axg-frddr";
+ reg = <0x0 0x200 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "FRDDR_B";
+ interrupts = <GIC_SPI 153 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_FRDDR_B>;
+ resets = <&arb AXG_ARB_FRDDR_B>;
+ status = "disabled";
+ };
+
+ frddr_c: audio-controller@240 {
+ compatible = "amlogic,g12a-frddr",
+ "amlogic,axg-frddr";
+ reg = <0x0 0x240 0x0 0x1c>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "FRDDR_C";
+ interrupts = <GIC_SPI 154 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_FRDDR_C>;
+ resets = <&arb AXG_ARB_FRDDR_C>;
+ status = "disabled";
+ };
+
+ arb: reset-controller@280 {
+ status = "disabled";
+ compatible = "amlogic,meson-axg-audio-arb";
+ reg = <0x0 0x280 0x0 0x4>;
+ #reset-cells = <1>;
+ clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
+ };
+
+ tdmin_a: audio-controller@300 {
+ compatible = "amlogic,g12a-tdmin",
+ "amlogic,axg-tdmin";
+ reg = <0x0 0x300 0x0 0x40>;
+ sound-name-prefix = "TDMIN_A";
+ resets = <&clkc_audio AUD_RESET_TDMIN_A>;
+ clocks = <&clkc_audio AUD_CLKID_TDMIN_A>,
+ <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ tdmin_b: audio-controller@340 {
+ compatible = "amlogic,g12a-tdmin",
+ "amlogic,axg-tdmin";
+ reg = <0x0 0x340 0x0 0x40>;
+ sound-name-prefix = "TDMIN_B";
+ resets = <&clkc_audio AUD_RESET_TDMIN_B>;
+ clocks = <&clkc_audio AUD_CLKID_TDMIN_B>,
+ <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ tdmin_c: audio-controller@380 {
+ compatible = "amlogic,g12a-tdmin",
+ "amlogic,axg-tdmin";
+ reg = <0x0 0x380 0x0 0x40>;
+ sound-name-prefix = "TDMIN_C";
+ resets = <&clkc_audio AUD_RESET_TDMIN_C>;
+ clocks = <&clkc_audio AUD_CLKID_TDMIN_C>,
+ <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ tdmin_lb: audio-controller@3c0 {
+ compatible = "amlogic,g12a-tdmin",
+ "amlogic,axg-tdmin";
+ reg = <0x0 0x3c0 0x0 0x40>;
+ sound-name-prefix = "TDMIN_LB";
+ resets = <&clkc_audio AUD_RESET_TDMIN_LB>;
+ clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>,
+ <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ spdifin: audio-controller@400 {
+ compatible = "amlogic,g12a-spdifin",
+ "amlogic,axg-spdifin";
+ reg = <0x0 0x400 0x0 0x30>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SPDIFIN";
+ interrupts = <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_audio AUD_CLKID_SPDIFIN>,
+ <&clkc_audio AUD_CLKID_SPDIFIN_CLK>;
+ clock-names = "pclk", "refclk";
+ status = "disabled";
+ };
+
+ spdifout: audio-controller@480 {
+ compatible = "amlogic,g12a-spdifout",
+ "amlogic,axg-spdifout";
+ reg = <0x0 0x480 0x0 0x50>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SPDIFOUT";
+ clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
+ <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
+ clock-names = "pclk", "mclk";
+ status = "disabled";
+ };
+
+ tdmout_a: audio-controller@500 {
+ compatible = "amlogic,g12a-tdmout";
+ reg = <0x0 0x500 0x0 0x40>;
+ sound-name-prefix = "TDMOUT_A";
+ resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
+ clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
+ <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ tdmout_b: audio-controller@540 {
+ compatible = "amlogic,g12a-tdmout";
+ reg = <0x0 0x540 0x0 0x40>;
+ sound-name-prefix = "TDMOUT_B";
+ resets = <&clkc_audio AUD_RESET_TDMOUT_B>;
+ clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>,
+ <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ tdmout_c: audio-controller@580 {
+ compatible = "amlogic,g12a-tdmout";
+ reg = <0x0 0x580 0x0 0x40>;
+ sound-name-prefix = "TDMOUT_C";
+ resets = <&clkc_audio AUD_RESET_TDMOUT_C>;
+ clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>,
+ <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>,
+ <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>,
+ <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>;
+ clock-names = "pclk", "sclk", "sclk_sel",
+ "lrclk", "lrclk_sel";
+ status = "disabled";
+ };
+
+ spdifout_b: audio-controller@680 {
+ compatible = "amlogic,g12a-spdifout",
+ "amlogic,axg-spdifout";
+ reg = <0x0 0x680 0x0 0x50>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SPDIFOUT_B";
+ clocks = <&clkc_audio AUD_CLKID_SPDIFOUT_B>,
+ <&clkc_audio AUD_CLKID_SPDIFOUT_B_CLK>;
+ clock-names = "pclk", "mclk";
+ status = "disabled";
+ };
+
+ tohdmitx: audio-controller@744 {
+ compatible = "amlogic,g12a-tohdmitx";
+ reg = <0x0 0x744 0x0 0x4>;
+ #sound-dai-cells = <1>;
+ sound-name-prefix = "TOHDMITX";
+ status = "disabled";
+ };
+ };
+
+ usb3_pcie_phy: phy@46000 {
+ compatible = "amlogic,g12a-usb3-pcie-phy";
+ reg = <0x0 0x46000 0x0 0x2000>;
+ clocks = <&clkc CLKID_PCIE_PLL>;
+ clock-names = "ref_clk";
+ resets = <&reset RESET_PCIE_PHY>;
+ reset-names = "phy";
+ assigned-clocks = <&clkc CLKID_PCIE_PLL>;
+ assigned-clock-rates = <100000000>;
+ #phy-cells = <1>;
+ };
+
+ eth_phy: mdio-multiplexer@4c000 {
+ compatible = "amlogic,g12a-mdio-mux";
+ reg = <0x0 0x4c000 0x0 0xa4>;
+ clocks = <&clkc CLKID_ETH_PHY>,
+ <&xtal>,
+ <&clkc CLKID_MPLL_50M>;
+ clock-names = "pclk", "clkin0", "clkin1";
+ mdio-parent-bus = <&mdio0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ext_mdio: mdio@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ int_mdio: mdio@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ internal_ephy: ethernet_phy@8 {
+ compatible = "ethernet-phy-id0180.3301",
+ "ethernet-phy-ieee802.3-c22";
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <8>;
+ max-speed = <100>;
+ };
+ };
+ };
+ };
+
+ aobus: bus@ff800000 {
+ compatible = "simple-bus";
+ reg = <0x0 0xff800000 0x0 0x100000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>;
+
+ rti: sys-ctrl@0 {
+ compatible = "amlogic,meson-gx-ao-sysctrl",
+ "simple-mfd", "syscon";
+ reg = <0x0 0x0 0x0 0x100>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0x0 0x0 0x100>;
+
+ clkc_AO: clock-controller {
+ compatible = "amlogic,meson-g12a-aoclkc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ clocks = <&xtal>, <&clkc CLKID_CLK81>;
+ clock-names = "xtal", "mpeg-clk";
+ };
+
+ ao_pinctrl: pinctrl@14 {
+ compatible = "amlogic,meson-g12a-aobus-pinctrl";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio_ao: bank@14 {
+ reg = <0x0 0x14 0x0 0x8>,
+ <0x0 0x1c 0x0 0x8>,
+ <0x0 0x24 0x0 0x14>;
+ reg-names = "mux",
+ "ds",
+ "gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&ao_pinctrl 0 0 15>;
+ };
+
+ i2c_ao_sck_pins: i2c_ao_sck_pins {
+ mux {
+ groups = "i2c_ao_sck";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c_ao_sda_pins: i2c_ao_sda {
+ mux {
+ groups = "i2c_ao_sda";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c_ao_sck_e_pins: i2c_ao_sck_e {
+ mux {
+ groups = "i2c_ao_sck_e";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c_ao_sda_e_pins: i2c_ao_sda_e {
+ mux {
+ groups = "i2c_ao_sda_e";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ mclk0_ao_pins: mclk0-ao {
+ mux {
+ groups = "mclk0_ao";
+ function = "mclk0_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_din0_pins: tdm-ao-b-din0 {
+ mux {
+ groups = "tdm_ao_b_din0";
+ function = "tdm_ao_b";
+ bias-disable;
+ };
+ };
+
+ spdif_ao_out_pins: spdif-ao-out {
+ mux {
+ groups = "spdif_ao_out";
+ function = "spdif_ao_out";
+ drive-strength-microamp = <500>;
+ bias-disable;
+ };
+ };
+
+ tdm_ao_b_din1_pins: tdm-ao-b-din1 {
+ mux {
+ groups = "tdm_ao_b_din1";
+ function = "tdm_ao_b";
+ bias-disable;
+ };
+ };
+
+ tdm_ao_b_din2_pins: tdm-ao-b-din2 {
+ mux {
+ groups = "tdm_ao_b_din2";
+ function = "tdm_ao_b";
+ bias-disable;
+ };
+ };
+
+ tdm_ao_b_dout0_pins: tdm-ao-b-dout0 {
+ mux {
+ groups = "tdm_ao_b_dout0";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_dout1_pins: tdm-ao-b-dout1 {
+ mux {
+ groups = "tdm_ao_b_dout1";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_dout2_pins: tdm-ao-b-dout2 {
+ mux {
+ groups = "tdm_ao_b_dout2";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_fs_pins: tdm-ao-b-fs {
+ mux {
+ groups = "tdm_ao_b_fs";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_sclk_pins: tdm-ao-b-sclk {
+ mux {
+ groups = "tdm_ao_b_sclk";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs {
+ mux {
+ groups = "tdm_ao_b_slv_fs";
+ function = "tdm_ao_b";
+ bias-disable;
+ };
+ };
+
+ tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk {
+ mux {
+ groups = "tdm_ao_b_slv_sclk";
+ function = "tdm_ao_b";
+ bias-disable;
+ };
+ };
+
+ uart_ao_a_pins: uart-a-ao {
+ mux {
+ groups = "uart_ao_a_tx",
+ "uart_ao_a_rx";
+ function = "uart_ao_a";
+ bias-disable;
+ };
+ };
+
+ uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts {
+ mux {
+ groups = "uart_ao_a_cts",
+ "uart_ao_a_rts";
+ function = "uart_ao_a";
+ bias-disable;
+ };
+ };
+
+ pwm_a_e_pins: pwm-a-e {
+ mux {
+ groups = "pwm_a_e";
+ function = "pwm_a_e";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_a_pins: pwm-ao-a {
+ mux {
+ groups = "pwm_ao_a";
+ function = "pwm_ao_a";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_b_pins: pwm-ao-b {
+ mux {
+ groups = "pwm_ao_b";
+ function = "pwm_ao_b";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_c_4_pins: pwm-ao-c-4 {
+ mux {
+ groups = "pwm_ao_c_4";
+ function = "pwm_ao_c";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_c_6_pins: pwm-ao-c-6 {
+ mux {
+ groups = "pwm_ao_c_6";
+ function = "pwm_ao_c";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_d_5_pins: pwm-ao-d-5 {
+ mux {
+ groups = "pwm_ao_d_5";
+ function = "pwm_ao_d";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_d_10_pins: pwm-ao-d-10 {
+ mux {
+ groups = "pwm_ao_d_10";
+ function = "pwm_ao_d";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_d_e_pins: pwm-ao-d-e {
+ mux {
+ groups = "pwm_ao_d_e";
+ function = "pwm_ao_d";
+ };
+ };
+
+ remote_input_ao_pins: remote-input-ao {
+ mux {
+ groups = "remote_ao_input";
+ function = "remote_ao_input";
+ bias-disable;
+ };
+ };
+ };
+ };
+
+ vrtc: rtc@0a8 {
+ compatible = "amlogic,meson-vrtc";
+ reg = <0x0 0x000a8 0x0 0x4>;
+ };
+
+ cec_AO: cec@100 {
+ compatible = "amlogic,meson-gx-ao-cec";
+ reg = <0x0 0x00100 0x0 0x14>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_AO CLKID_AO_CEC>;
+ clock-names = "core";
+ status = "disabled";
+ };
+
+ sec_AO: ao-secure@140 {
+ compatible = "amlogic,meson-gx-ao-secure", "syscon";
+ reg = <0x0 0x140 0x0 0x140>;
+ amlogic,has-chip-id;
+ };
+
+ cecb_AO: cec@280 {
+ compatible = "amlogic,meson-g12a-ao-cec";
+ reg = <0x0 0x00280 0x0 0x1c>;
+ interrupts = <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_AO CLKID_AO_CTS_OSCIN>;
+ clock-names = "oscin";
+ status = "disabled";
+ };
+
+ pwm_AO_cd: pwm@2000 {
+ compatible = "amlogic,meson-g12a-ao-pwm-cd";
+ reg = <0x0 0x2000 0x0 0x20>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ uart_AO: serial@3000 {
+ compatible = "amlogic,meson-gx-uart",
+ "amlogic,meson-ao-uart";
+ reg = <0x0 0x3000 0x0 0x18>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+ status = "disabled";
+ };
+
+ uart_AO_B: serial@4000 {
+ compatible = "amlogic,meson-gx-uart",
+ "amlogic,meson-ao-uart";
+ reg = <0x0 0x4000 0x0 0x18>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+ status = "disabled";
+ };
+
+ i2c_AO: i2c@5000 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x05000 0x0 0x20>;
+ interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc CLKID_I2C>;
+ };
+
+ pwm_AO_ab: pwm@7000 {
+ compatible = "amlogic,meson-g12a-ao-pwm-ab";
+ reg = <0x0 0x7000 0x0 0x20>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ ir: ir@8000 {
+ compatible = "amlogic,meson-gxbb-ir";
+ reg = <0x0 0x8000 0x0 0x20>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ saradc: adc@9000 {
+ compatible = "amlogic,meson-g12a-saradc",
+ "amlogic,meson-saradc";
+ reg = <0x0 0x9000 0x0 0x48>;
+ #io-channel-cells = <1>;
+ interrupts = <GIC_SPI 200 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>,
+ <&clkc_AO CLKID_AO_SAR_ADC>,
+ <&clkc_AO CLKID_AO_SAR_ADC_CLK>,
+ <&clkc_AO CLKID_AO_SAR_ADC_SEL>;
+ clock-names = "clkin", "core", "adc_clk", "adc_sel";
+ status = "disabled";
+ };
+ };
+
+ vpu: vpu@ff900000 {
+ compatible = "amlogic,meson-g12a-vpu";
+ reg = <0x0 0xff900000 0x0 0x100000>,
+ <0x0 0xff63c000 0x0 0x1000>;
+ reg-names = "vpu", "hhi";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ amlogic,canvas = <&canvas>;
+
+ /* CVBS VDAC output port */
+ cvbs_vdac_port: port@0 {
+ reg = <0>;
+ };
+
+ /* HDMI-TX output port */
+ hdmi_tx_port: port@1 {
+ reg = <1>;
+
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&hdmi_tx_in>;
+ };
+ };
+ };
+
+ gic: interrupt-controller@ffc01000 {
+ compatible = "arm,gic-400";
+ reg = <0x0 0xffc01000 0 0x1000>,
+ <0x0 0xffc02000 0 0x2000>,
+ <0x0 0xffc04000 0 0x2000>,
+ <0x0 0xffc06000 0 0x2000>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9
+ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ };
+
+ cbus: bus@ffd00000 {
+ compatible = "simple-bus";
+ reg = <0x0 0xffd00000 0x0 0x100000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x100000>;
+
+ reset: reset-controller@1004 {
+ compatible = "amlogic,meson-axg-reset";
+ reg = <0x0 0x1004 0x0 0x9c>;
+ #reset-cells = <1>;
+ };
+
+ gpio_intc: interrupt-controller@f080 {
+ compatible = "amlogic,meson-g12a-gpio-intc",
+ "amlogic,meson-gpio-intc";
+ reg = <0x0 0xf080 0x0 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
+ };
+
+ pwm_ef: pwm@19000 {
+ compatible = "amlogic,meson-g12a-ee-pwm";
+ reg = <0x0 0x19000 0x0 0x20>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_cd: pwm@1a000 {
+ compatible = "amlogic,meson-g12a-ee-pwm";
+ reg = <0x0 0x1a000 0x0 0x20>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_ab: pwm@1b000 {
+ compatible = "amlogic,meson-g12a-ee-pwm";
+ reg = <0x0 0x1b000 0x0 0x20>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@1c000 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1c000 0x0 0x20>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc CLKID_I2C>;
+ };
+
+ i2c2: i2c@1d000 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1d000 0x0 0x20>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc CLKID_I2C>;
+ };
+
+ i2c1: i2c@1e000 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1e000 0x0 0x20>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc CLKID_I2C>;
+ };
+
+ i2c0: i2c@1f000 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1f000 0x0 0x20>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc CLKID_I2C>;
+ };
+
+ clk_msr: clock-measure@18000 {
+ compatible = "amlogic,meson-g12a-clk-measure";
+ reg = <0x0 0x18000 0x0 0x10>;
+ };
+
+ uart_C: serial@22000 {
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x22000 0x0 0x18>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+ status = "disabled";
+ };
+
+ uart_B: serial@23000 {
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x23000 0x0 0x18>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+ status = "disabled";
+ };
+
+ uart_A: serial@24000 {
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x24000 0x0 0x18>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+ status = "disabled";
+ };
+ };
+
+ sd_emmc_a: sd@ffe03000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0xffe03000 0x0 0x800>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ clocks = <&clkc CLKID_SD_EMMC_A>,
+ <&clkc CLKID_SD_EMMC_A_CLK0>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_A>;
+ };
+
+ sd_emmc_b: sd@ffe05000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0xffe05000 0x0 0x800>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ clocks = <&clkc CLKID_SD_EMMC_B>,
+ <&clkc CLKID_SD_EMMC_B_CLK0>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_B>;
+ };
+
+ sd_emmc_c: mmc@ffe07000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0xffe07000 0x0 0x800>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ clocks = <&clkc CLKID_SD_EMMC_C>,
+ <&clkc CLKID_SD_EMMC_C_CLK0>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_C>;
+ };
+
+ usb: usb@ffe09000 {
+ status = "disabled";
+ compatible = "amlogic,meson-g12a-usb-ctrl";
+ reg = <0x0 0xffe09000 0x0 0xa0>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&clkc CLKID_USB>;
+ resets = <&reset RESET_USB>;
+
+ dr_mode = "otg";
+
+ phys = <&usb2_phy0>, <&usb2_phy1>,
+ <&usb3_pcie_phy PHY_TYPE_USB3>;
+ phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0";
+
+ dwc2: usb@ff400000 {
+ compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+ reg = <0x0 0xff400000 0x0 0x40000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+ clock-names = "ddr";
+ phys = <&usb2_phy1>;
+ phy-names = "usb2-phy";
+ dr_mode = "peripheral";
+ g-rx-fifo-size = <192>;
+ g-np-tx-fifo-size = <128>;
+ g-tx-fifo-size = <128 128 16 16 16>;
+ };
+
+ dwc3: usb@ff500000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0xff500000 0x0 0x100000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "host";
+ snps,dis_u2_susphy_quirk;
+ snps,quirk-frame-length-adjustment;
+ };
+ };
+
+ mali: gpu@ffe40000 {
+ compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost";
+ reg = <0x0 0xffe40000 0x0 0x40000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gpu", "mmu", "job";
+ clocks = <&clkc CLKID_MALI>;
+ resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
+
+ /*
+ * Mali clocking is provided by two identical clock paths
+ * MALI_0 and MALI_1 muxed to a single clock by a glitch
+ * free mux to safely change frequency while running.
+ */
+ assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
+ <&clkc CLKID_MALI_0>,
+ <&clkc CLKID_MALI>; /* Glitch free mux */
+ assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_MALI_0>;
+ assigned-clock-rates = <0>, /* Do Nothing */
+ <800000000>,
+ <0>; /* Do Nothing */
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13
+ (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14
+ (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11
+ (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10
+ (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
+ arm,no-tick-in-suspend;
+ };
+
+ xtal: xtal-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "xtal";
+ #clock-cells = <0>;
+ };
+
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
index c7a87368850b..c9fa23a56562 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
@@ -129,6 +129,25 @@
enable-active-high;
};
+ vddcpu: regulator-vddcpu {
+ /*
+ * SY8120B1ABC DC/DC Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU";
+ regulator-min-microvolt = <721000>;
+ regulator-max-microvolt = <1022000>;
+
+ vin-supply = <&dc_in>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
vddio_ao1v8: regulator-vddio_ao1v8 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_AO1V8";
@@ -297,6 +316,34 @@
status = "okay";
};
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -339,6 +386,20 @@
pinctrl-names = "default";
};
+&ir {
+ status = "okay";
+ pinctrl-0 = <&remote_input_ao_pins>;
+ pinctrl-names = "default";
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
+};
+
&pwm_ef {
status = "okay";
pinctrl-0 = <&pwm_e_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
index 8551fbd4a488..2a324f0136e3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
@@ -129,6 +129,24 @@
regulator-always-on;
};
+ vddcpu: regulator-vddcpu {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU";
+ regulator-min-microvolt = <721000>;
+ regulator-max-microvolt = <1022000>;
+
+ vin-supply = <&main_12v>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
};
&cec_AO {
@@ -145,6 +163,34 @@
hdmi-phandle = <&hdmi_tx>;
};
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -197,6 +243,14 @@
pinctrl-names = "default";
};
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
+};
+
/* SD card */
&sd_emmc_b {
status = "okay";
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 fe4013cca876..17155fb73fce 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
@@ -11,7 +11,7 @@
#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
/ {
- compatible = "amediatech,x96-max", "amlogic,u200", "amlogic,g12a";
+ compatible = "amediatech,x96-max", "amlogic,g12a";
model = "Shenzhen Amediatech Technology Co., Ltd X96 Max";
aliases {
@@ -132,6 +132,22 @@
regulator-always-on;
};
+ vddcpu: regulator-vddcpu {
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU";
+ regulator-min-microvolt = <721000>;
+ regulator-max-microvolt = <1022000>;
+
+ vin-supply = <&dc_in>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
sound {
compatible = "amlogic,axg-sound-card";
model = "G12A-X96-MAX";
@@ -242,6 +258,34 @@
status = "okay";
};
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -277,6 +321,15 @@
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
pinctrl-names = "default";
+ linux,rc-map-name = "rc-x96max";
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
};
&ext_mdio {
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
index f8d43e3dcf20..eb5d177d7a99 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
@@ -3,56 +3,12 @@
* Copyright (c) 2018 Amlogic, Inc. All rights reserved.
*/
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/axg-audio-clkc.h>
-#include <dt-bindings/clock/g12a-clkc.h>
-#include <dt-bindings/clock/g12a-aoclkc.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
-#include <dt-bindings/reset/amlogic,meson-g12a-reset.h>
+#include "meson-g12-common.dtsi"
+#include <dt-bindings/power/meson-g12a-power.h>
/ {
compatible = "amlogic,g12a";
- interrupt-parent = <&gic>;
- #address-cells = <2>;
- #size-cells = <2>;
-
- tdmif_a: audio-controller-0 {
- 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";
- status = "disabled";
- };
-
- tdmif_b: audio-controller-1 {
- 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";
- status = "disabled";
- };
-
- tdmif_c: audio-controller-2 {
- 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";
- status = "disabled";
- };
-
cpus {
#address-cells = <0x2>;
#size-cells = <0x0>;
@@ -94,2359 +50,75 @@
};
};
- efuse: efuse {
- compatible = "amlogic,meson-gxbb-efuse";
- clocks = <&clkc CLKID_EFUSE>;
- #address-cells = <1>;
- #size-cells = <1>;
- read-only;
- };
+ cpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
- psci {
- compatible = "arm,psci-1.0";
- method = "smc";
- };
-
- reserved-memory {
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- /* 3 MiB reserved for ARM Trusted Firmware (BL31) */
- secmon_reserved: secmon@5000000 {
- reg = <0x0 0x05000000 0x0 0x300000>;
- no-map;
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
};
- linux,cma {
- compatible = "shared-dma-pool";
- reusable;
- size = <0x0 0x10000000>;
- alignment = <0x0 0x400000>;
- linux,cma-default;
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
};
- };
-
- sm: secure-monitor {
- compatible = "amlogic,meson-gxbb-sm";
- };
-
- soc {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- ethmac: ethernet@ff3f0000 {
- compatible = "amlogic,meson-axg-dwmac",
- "snps,dwmac-3.70a",
- "snps,dwmac";
- reg = <0x0 0xff3f0000 0x0 0x10000
- 0x0 0xff634540 0x0 0x8>;
- interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "macirq";
- clocks = <&clkc CLKID_ETH>,
- <&clkc CLKID_FCLK_DIV2>,
- <&clkc CLKID_MPLL2>;
- clock-names = "stmmaceth", "clkin0", "clkin1";
- status = "disabled";
-
- mdio0: mdio {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "snps,dwmac-mdio";
- };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
};
- apb: bus@ff600000 {
- compatible = "simple-bus";
- reg = <0x0 0xff600000 0x0 0x200000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0xff600000 0x0 0x200000>;
-
- hdmi_tx: hdmi-tx@0 {
- compatible = "amlogic,meson-g12a-dw-hdmi";
- reg = <0x0 0x0 0x0 0x10000>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
- resets = <&reset RESET_HDMITX_CAPB3>,
- <&reset RESET_HDMITX_PHY>,
- <&reset RESET_HDMITX>;
- reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
- clocks = <&clkc CLKID_HDMI>,
- <&clkc CLKID_HTX_PCLK>,
- <&clkc CLKID_VPU_INTR>;
- clock-names = "isfr", "iahb", "venci";
- #address-cells = <1>;
- #size-cells = <0>;
- #sound-dai-cells = <0>;
- status = "disabled";
-
- /* VPU VENC Input */
- hdmi_tx_venc_port: port@0 {
- reg = <0>;
-
- hdmi_tx_in: endpoint {
- remote-endpoint = <&hdmi_tx_out>;
- };
- };
-
- /* TMDS Output */
- hdmi_tx_tmds_port: port@1 {
- reg = <1>;
- };
- };
-
- apb_efuse: bus@30000 {
- compatible = "simple-bus";
- reg = <0x0 0x30000 0x0 0x2000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x30000 0x0 0x2000>;
-
- hwrng: rng@218 {
- compatible = "amlogic,meson-rng";
- reg = <0x0 0x218 0x0 0x4>;
- };
- };
-
- periphs: bus@34400 {
- compatible = "simple-bus";
- reg = <0x0 0x34400 0x0 0x400>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>;
-
- periphs_pinctrl: pinctrl@40 {
- compatible = "amlogic,meson-g12a-periphs-pinctrl";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- gpio: bank@40 {
- reg = <0x0 0x40 0x0 0x4c>,
- <0x0 0xe8 0x0 0x18>,
- <0x0 0x120 0x0 0x18>,
- <0x0 0x2c0 0x0 0x40>,
- <0x0 0x340 0x0 0x1c>;
- reg-names = "gpio",
- "pull",
- "pull-enable",
- "mux",
- "ds";
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&periphs_pinctrl 0 0 86>;
- };
-
- cec_ao_a_h_pins: cec_ao_a_h {
- mux {
- groups = "cec_ao_a_h";
- function = "cec_ao_a_h";
- bias-disable;
- };
- };
-
- cec_ao_b_h_pins: cec_ao_b_h {
- mux {
- groups = "cec_ao_b_h";
- function = "cec_ao_b_h";
- bias-disable;
- };
- };
-
- emmc_pins: emmc {
- mux-0 {
- groups = "emmc_nand_d0",
- "emmc_nand_d1",
- "emmc_nand_d2",
- "emmc_nand_d3",
- "emmc_nand_d4",
- "emmc_nand_d5",
- "emmc_nand_d6",
- "emmc_nand_d7",
- "emmc_cmd";
- function = "emmc";
- bias-pull-up;
- drive-strength-microamp = <4000>;
- };
-
- mux-1 {
- groups = "emmc_clk";
- function = "emmc";
- bias-disable;
- drive-strength-microamp = <4000>;
- };
- };
-
- emmc_ds_pins: emmc-ds {
- mux {
- groups = "emmc_nand_ds";
- function = "emmc";
- bias-pull-down;
- drive-strength-microamp = <4000>;
- };
- };
-
- emmc_clk_gate_pins: emmc_clk_gate {
- mux {
- groups = "BOOT_8";
- function = "gpio_periphs";
- bias-pull-down;
- drive-strength-microamp = <4000>;
- };
- };
-
- hdmitx_ddc_pins: hdmitx_ddc {
- mux {
- groups = "hdmitx_sda",
- "hdmitx_sck";
- function = "hdmitx";
- bias-disable;
- drive-strength-microamp = <4000>;
- };
- };
-
- hdmitx_hpd_pins: hdmitx_hpd {
- mux {
- groups = "hdmitx_hpd_in";
- function = "hdmitx";
- bias-disable;
- };
- };
-
-
- i2c0_sda_c_pins: i2c0-sda-c {
- mux {
- groups = "i2c0_sda_c";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
-
- };
- };
-
- i2c0_sck_c_pins: i2c0-sck-c {
- mux {
- groups = "i2c0_sck_c";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c0_sda_z0_pins: i2c0-sda-z0 {
- mux {
- groups = "i2c0_sda_z0";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c0_sck_z1_pins: i2c0-sck-z1 {
- mux {
- groups = "i2c0_sck_z1";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c0_sda_z7_pins: i2c0-sda-z7 {
- mux {
- groups = "i2c0_sda_z7";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c0_sda_z8_pins: i2c0-sda-z8 {
- mux {
- groups = "i2c0_sda_z8";
- function = "i2c0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sda_x_pins: i2c1-sda-x {
- mux {
- groups = "i2c1_sda_x";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sck_x_pins: i2c1-sck-x {
- mux {
- groups = "i2c1_sck_x";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sda_h2_pins: i2c1-sda-h2 {
- mux {
- groups = "i2c1_sda_h2";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sck_h3_pins: i2c1-sck-h3 {
- mux {
- groups = "i2c1_sck_h3";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sda_h6_pins: i2c1-sda-h6 {
- mux {
- groups = "i2c1_sda_h6";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c1_sck_h7_pins: i2c1-sck-h7 {
- mux {
- groups = "i2c1_sck_h7";
- function = "i2c1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c2_sda_x_pins: i2c2-sda-x {
- mux {
- groups = "i2c2_sda_x";
- function = "i2c2";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c2_sck_x_pins: i2c2-sck-x {
- mux {
- groups = "i2c2_sck_x";
- function = "i2c2";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c2_sda_z_pins: i2c2-sda-z {
- mux {
- groups = "i2c2_sda_z";
- function = "i2c2";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c2_sck_z_pins: i2c2-sck-z {
- mux {
- groups = "i2c2_sck_z";
- function = "i2c2";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c3_sda_h_pins: i2c3-sda-h {
- mux {
- groups = "i2c3_sda_h";
- function = "i2c3";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c3_sck_h_pins: i2c3-sck-h {
- mux {
- groups = "i2c3_sck_h";
- function = "i2c3";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c3_sda_a_pins: i2c3-sda-a {
- mux {
- groups = "i2c3_sda_a";
- function = "i2c3";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c3_sck_a_pins: i2c3-sck-a {
- mux {
- groups = "i2c3_sck_a";
- function = "i2c3";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- mclk0_a_pins: mclk0-a {
- mux {
- groups = "mclk0_a";
- function = "mclk0";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- mclk1_a_pins: mclk1-a {
- mux {
- groups = "mclk1_a";
- function = "mclk1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- mclk1_x_pins: mclk1-x {
- mux {
- groups = "mclk1_x";
- function = "mclk1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- mclk1_z_pins: mclk1-z {
- mux {
- groups = "mclk1_z";
- function = "mclk1";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- pdm_din0_a_pins: pdm-din0-a {
- mux {
- groups = "pdm_din0_a";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din0_c_pins: pdm-din0-c {
- mux {
- groups = "pdm_din0_c";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din0_x_pins: pdm-din0-x {
- mux {
- groups = "pdm_din0_x";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din0_z_pins: pdm-din0-z {
- mux {
- groups = "pdm_din0_z";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din1_a_pins: pdm-din1-a {
- mux {
- groups = "pdm_din1_a";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din1_c_pins: pdm-din1-c {
- mux {
- groups = "pdm_din1_c";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din1_x_pins: pdm-din1-x {
- mux {
- groups = "pdm_din1_x";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din1_z_pins: pdm-din1-z {
- mux {
- groups = "pdm_din1_z";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din2_a_pins: pdm-din2-a {
- mux {
- groups = "pdm_din2_a";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din2_c_pins: pdm-din2-c {
- mux {
- groups = "pdm_din2_c";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din2_x_pins: pdm-din2-x {
- mux {
- groups = "pdm_din2_x";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din2_z_pins: pdm-din2-z {
- mux {
- groups = "pdm_din2_z";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din3_a_pins: pdm-din3-a {
- mux {
- groups = "pdm_din3_a";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din3_c_pins: pdm-din3-c {
- mux {
- groups = "pdm_din3_c";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din3_x_pins: pdm-din3-x {
- mux {
- groups = "pdm_din3_x";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_din3_z_pins: pdm-din3-z {
- mux {
- groups = "pdm_din3_z";
- function = "pdm";
- bias-disable;
- };
- };
-
- pdm_dclk_a_pins: pdm-dclk-a {
- mux {
- groups = "pdm_dclk_a";
- function = "pdm";
- bias-disable;
- drive-strength-microamp = <500>;
- };
- };
-
- pdm_dclk_c_pins: pdm-dclk-c {
- mux {
- groups = "pdm_dclk_c";
- function = "pdm";
- bias-disable;
- drive-strength-microamp = <500>;
- };
- };
-
- pdm_dclk_x_pins: pdm-dclk-x {
- mux {
- groups = "pdm_dclk_x";
- function = "pdm";
- bias-disable;
- drive-strength-microamp = <500>;
- };
- };
-
- pdm_dclk_z_pins: pdm-dclk-z {
- mux {
- groups = "pdm_dclk_z";
- function = "pdm";
- bias-disable;
- drive-strength-microamp = <500>;
- };
- };
-
- pwm_a_pins: pwm-a {
- mux {
- groups = "pwm_a";
- function = "pwm_a";
- bias-disable;
- };
- };
-
- pwm_b_x7_pins: pwm-b-x7 {
- mux {
- groups = "pwm_b_x7";
- function = "pwm_b";
- bias-disable;
- };
- };
-
- pwm_b_x19_pins: pwm-b-x19 {
- mux {
- groups = "pwm_b_x19";
- function = "pwm_b";
- bias-disable;
- };
- };
-
- pwm_c_c_pins: pwm-c-c {
- mux {
- groups = "pwm_c_c";
- function = "pwm_c";
- bias-disable;
- };
- };
-
- pwm_c_x5_pins: pwm-c-x5 {
- mux {
- groups = "pwm_c_x5";
- function = "pwm_c";
- bias-disable;
- };
- };
-
- pwm_c_x8_pins: pwm-c-x8 {
- mux {
- groups = "pwm_c_x8";
- function = "pwm_c";
- bias-disable;
- };
- };
-
- pwm_d_x3_pins: pwm-d-x3 {
- mux {
- groups = "pwm_d_x3";
- function = "pwm_d";
- bias-disable;
- };
- };
-
- pwm_d_x6_pins: pwm-d-x6 {
- mux {
- groups = "pwm_d_x6";
- function = "pwm_d";
- bias-disable;
- };
- };
-
- pwm_e_pins: pwm-e {
- mux {
- groups = "pwm_e";
- function = "pwm_e";
- bias-disable;
- };
- };
-
- pwm_f_x_pins: pwm-f-x {
- mux {
- groups = "pwm_f_x";
- function = "pwm_f";
- bias-disable;
- };
- };
-
- pwm_f_h_pins: pwm-f-h {
- mux {
- groups = "pwm_f_h";
- function = "pwm_f";
- bias-disable;
- };
- };
-
- sdcard_c_pins: sdcard_c {
- mux-0 {
- groups = "sdcard_d0_c",
- "sdcard_d1_c",
- "sdcard_d2_c",
- "sdcard_d3_c",
- "sdcard_cmd_c";
- function = "sdcard";
- bias-pull-up;
- drive-strength-microamp = <4000>;
- };
-
- mux-1 {
- groups = "sdcard_clk_c";
- function = "sdcard";
- bias-disable;
- drive-strength-microamp = <4000>;
- };
- };
-
- sdcard_clk_gate_c_pins: sdcard_clk_gate_c {
- mux {
- groups = "GPIOC_4";
- function = "gpio_periphs";
- bias-pull-down;
- drive-strength-microamp = <4000>;
- };
- };
-
- sdcard_z_pins: sdcard_z {
- mux-0 {
- groups = "sdcard_d0_z",
- "sdcard_d1_z",
- "sdcard_d2_z",
- "sdcard_d3_z",
- "sdcard_cmd_z";
- function = "sdcard";
- bias-pull-up;
- drive-strength-microamp = <4000>;
- };
-
- mux-1 {
- groups = "sdcard_clk_z";
- function = "sdcard";
- bias-disable;
- drive-strength-microamp = <4000>;
- };
- };
-
- sdcard_clk_gate_z_pins: sdcard_clk_gate_z {
- mux {
- groups = "GPIOZ_6";
- function = "gpio_periphs";
- bias-pull-down;
- drive-strength-microamp = <4000>;
- };
- };
-
- sdio_pins: sdio {
- mux {
- groups = "sdio_d0",
- "sdio_d1",
- "sdio_d2",
- "sdio_d3",
- "sdio_clk",
- "sdio_cmd";
- function = "sdio";
- bias-disable;
- drive-strength-microamp = <4000>;
- };
- };
-
- sdio_clk_gate_pins: sdio_clk_gate {
- mux {
- groups = "GPIOX_4";
- function = "gpio_periphs";
- bias-pull-down;
- drive-strength-microamp = <4000>;
- };
- };
-
- spdif_in_a10_pins: spdif-in-a10 {
- mux {
- groups = "spdif_in_a10";
- function = "spdif_in";
- bias-disable;
- };
- };
-
- spdif_in_a12_pins: spdif-in-a12 {
- mux {
- groups = "spdif_in_a12";
- function = "spdif_in";
- bias-disable;
- };
- };
-
- spdif_in_h_pins: spdif-in-h {
- mux {
- groups = "spdif_in_h";
- function = "spdif_in";
- bias-disable;
- };
- };
-
- spdif_out_h_pins: spdif-out-h {
- mux {
- groups = "spdif_out_h";
- function = "spdif_out";
- drive-strength-microamp = <500>;
- bias-disable;
- };
- };
-
- spdif_out_a11_pins: spdif-out-a11 {
- mux {
- groups = "spdif_out_a11";
- function = "spdif_out";
- drive-strength-microamp = <500>;
- bias-disable;
- };
- };
-
- spdif_out_a13_pins: spdif-out-a13 {
- mux {
- groups = "spdif_out_a13";
- function = "spdif_out";
- drive-strength-microamp = <500>;
- bias-disable;
- };
- };
-
- tdm_a_din0_pins: tdm-a-din0 {
- mux {
- groups = "tdm_a_din0";
- function = "tdm_a";
- bias-disable;
- };
- };
-
-
- tdm_a_din1_pins: tdm-a-din1 {
- mux {
- groups = "tdm_a_din1";
- function = "tdm_a";
- bias-disable;
- };
- };
-
- tdm_a_dout0_pins: tdm-a-dout0 {
- mux {
- groups = "tdm_a_dout0";
- function = "tdm_a";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_a_dout1_pins: tdm-a-dout1 {
- mux {
- groups = "tdm_a_dout1";
- function = "tdm_a";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_a_fs_pins: tdm-a-fs {
- mux {
- groups = "tdm_a_fs";
- function = "tdm_a";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_a_sclk_pins: tdm-a-sclk {
- mux {
- groups = "tdm_a_sclk";
- function = "tdm_a";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_a_slv_fs_pins: tdm-a-slv-fs {
- mux {
- groups = "tdm_a_slv_fs";
- function = "tdm_a";
- bias-disable;
- };
- };
-
-
- tdm_a_slv_sclk_pins: tdm-a-slv-sclk {
- mux {
- groups = "tdm_a_slv_sclk";
- function = "tdm_a";
- bias-disable;
- };
- };
-
- tdm_b_din0_pins: tdm-b-din0 {
- mux {
- groups = "tdm_b_din0";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_din1_pins: tdm-b-din1 {
- mux {
- groups = "tdm_b_din1";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_din2_pins: tdm-b-din2 {
- mux {
- groups = "tdm_b_din2";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_din3_a_pins: tdm-b-din3-a {
- mux {
- groups = "tdm_b_din3_a";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_din3_h_pins: tdm-b-din3-h {
- mux {
- groups = "tdm_b_din3_h";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_dout0_pins: tdm-b-dout0 {
- mux {
- groups = "tdm_b_dout0";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_dout1_pins: tdm-b-dout1 {
- mux {
- groups = "tdm_b_dout1";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_dout2_pins: tdm-b-dout2 {
- mux {
- groups = "tdm_b_dout2";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_dout3_a_pins: tdm-b-dout3-a {
- mux {
- groups = "tdm_b_dout3_a";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_dout3_h_pins: tdm-b-dout3-h {
- mux {
- groups = "tdm_b_dout3_h";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_fs_pins: tdm-b-fs {
- mux {
- groups = "tdm_b_fs";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_sclk_pins: tdm-b-sclk {
- mux {
- groups = "tdm_b_sclk";
- function = "tdm_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_b_slv_fs_pins: tdm-b-slv-fs {
- mux {
- groups = "tdm_b_slv_fs";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_b_slv_sclk_pins: tdm-b-slv-sclk {
- mux {
- groups = "tdm_b_slv_sclk";
- function = "tdm_b";
- bias-disable;
- };
- };
-
- tdm_c_din0_a_pins: tdm-c-din0-a {
- mux {
- groups = "tdm_c_din0_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din0_z_pins: tdm-c-din0-z {
- mux {
- groups = "tdm_c_din0_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din1_a_pins: tdm-c-din1-a {
- mux {
- groups = "tdm_c_din1_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din1_z_pins: tdm-c-din1-z {
- mux {
- groups = "tdm_c_din1_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din2_a_pins: tdm-c-din2-a {
- mux {
- groups = "tdm_c_din2_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- eth_leds_pins: eth-leds {
- mux {
- groups = "eth_link_led",
- "eth_act_led";
- function = "eth";
- bias-disable;
- };
- };
-
- eth_pins: eth {
- mux {
- groups = "eth_mdio",
- "eth_mdc",
- "eth_rgmii_rx_clk",
- "eth_rx_dv",
- "eth_rxd0",
- "eth_rxd1",
- "eth_txen",
- "eth_txd0",
- "eth_txd1";
- function = "eth";
- drive-strength-microamp = <4000>;
- bias-disable;
- };
- };
-
- eth_rgmii_pins: eth-rgmii {
- mux {
- groups = "eth_rxd2_rgmii",
- "eth_rxd3_rgmii",
- "eth_rgmii_tx_clk",
- "eth_txd2_rgmii",
- "eth_txd3_rgmii";
- function = "eth";
- drive-strength-microamp = <4000>;
- bias-disable;
- };
- };
-
- tdm_c_din2_z_pins: tdm-c-din2-z {
- mux {
- groups = "tdm_c_din2_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din3_a_pins: tdm-c-din3-a {
- mux {
- groups = "tdm_c_din3_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_din3_z_pins: tdm-c-din3-z {
- mux {
- groups = "tdm_c_din3_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_dout0_a_pins: tdm-c-dout0-a {
- mux {
- groups = "tdm_c_dout0_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout0_z_pins: tdm-c-dout0-z {
- mux {
- groups = "tdm_c_dout0_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout1_a_pins: tdm-c-dout1-a {
- mux {
- groups = "tdm_c_dout1_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout1_z_pins: tdm-c-dout1-z {
- mux {
- groups = "tdm_c_dout1_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout2_a_pins: tdm-c-dout2-a {
- mux {
- groups = "tdm_c_dout2_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout2_z_pins: tdm-c-dout2-z {
- mux {
- groups = "tdm_c_dout2_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout3_a_pins: tdm-c-dout3-a {
- mux {
- groups = "tdm_c_dout3_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_dout3_z_pins: tdm-c-dout3-z {
- mux {
- groups = "tdm_c_dout3_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_fs_a_pins: tdm-c-fs-a {
- mux {
- groups = "tdm_c_fs_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_fs_z_pins: tdm-c-fs-z {
- mux {
- groups = "tdm_c_fs_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_sclk_a_pins: tdm-c-sclk-a {
- mux {
- groups = "tdm_c_sclk_a";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_sclk_z_pins: tdm-c-sclk-z {
- mux {
- groups = "tdm_c_sclk_z";
- function = "tdm_c";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_c_slv_fs_a_pins: tdm-c-slv-fs-a {
- mux {
- groups = "tdm_c_slv_fs_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_slv_fs_z_pins: tdm-c-slv-fs-z {
- mux {
- groups = "tdm_c_slv_fs_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_slv_sclk_a_pins: tdm-c-slv-sclk-a {
- mux {
- groups = "tdm_c_slv_sclk_a";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- tdm_c_slv_sclk_z_pins: tdm-c-slv-sclk-z {
- mux {
- groups = "tdm_c_slv_sclk_z";
- function = "tdm_c";
- bias-disable;
- };
- };
-
- uart_a_pins: uart-a {
- mux {
- groups = "uart_a_tx",
- "uart_a_rx";
- function = "uart_a";
- bias-disable;
- };
- };
-
- uart_a_cts_rts_pins: uart-a-cts-rts {
- mux {
- groups = "uart_a_cts",
- "uart_a_rts";
- function = "uart_a";
- bias-disable;
- };
- };
-
- uart_b_pins: uart-b {
- mux {
- groups = "uart_b_tx",
- "uart_b_rx";
- function = "uart_b";
- bias-disable;
- };
- };
-
- uart_c_pins: uart-c {
- mux {
- groups = "uart_c_tx",
- "uart_c_rx";
- function = "uart_c";
- bias-disable;
- };
- };
-
- uart_c_cts_rts_pins: uart-c-cts-rts {
- mux {
- groups = "uart_c_cts",
- "uart_c_rts";
- function = "uart_c";
- bias-disable;
- };
- };
- };
- };
-
- usb2_phy0: phy@36000 {
- compatible = "amlogic,g12a-usb2-phy";
- reg = <0x0 0x36000 0x0 0x2000>;
- clocks = <&xtal>;
- clock-names = "xtal";
- resets = <&reset RESET_USB_PHY20>;
- reset-names = "phy";
- #phy-cells = <0>;
- };
-
- dmc: bus@38000 {
- compatible = "simple-bus";
- reg = <0x0 0x38000 0x0 0x400>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>;
-
- canvas: video-lut@48 {
- compatible = "amlogic,canvas";
- reg = <0x0 0x48 0x0 0x14>;
- };
- };
-
- usb2_phy1: phy@3a000 {
- compatible = "amlogic,g12a-usb2-phy";
- reg = <0x0 0x3a000 0x0 0x2000>;
- clocks = <&xtal>;
- clock-names = "xtal";
- resets = <&reset RESET_USB_PHY21>;
- reset-names = "phy";
- #phy-cells = <0>;
- };
-
- hiu: bus@3c000 {
- compatible = "simple-bus";
- reg = <0x0 0x3c000 0x0 0x1400>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x3c000 0x0 0x1400>;
-
- hhi: system-controller@0 {
- compatible = "amlogic,meson-gx-hhi-sysctrl",
- "simple-mfd", "syscon";
- reg = <0 0 0 0x400>;
-
- clkc: clock-controller {
- compatible = "amlogic,g12a-clkc";
- #clock-cells = <1>;
- clocks = <&xtal>;
- clock-names = "xtal";
- };
- };
- };
-
- pdm: audio-controller@40000 {
- compatible = "amlogic,g12a-pdm",
- "amlogic,axg-pdm";
- reg = <0x0 0x40000 0x0 0x34>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "PDM";
- clocks = <&clkc_audio AUD_CLKID_PDM>,
- <&clkc_audio AUD_CLKID_PDM_DCLK>,
- <&clkc_audio AUD_CLKID_PDM_SYSCLK>;
- clock-names = "pclk", "dclk", "sysclk";
- status = "disabled";
- };
-
- audio: bus@42000 {
- compatible = "simple-bus";
- reg = <0x0 0x42000 0x0 0x2000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x42000 0x0 0x2000>;
-
- clkc_audio: clock-controller@0 {
- status = "disabled";
- compatible = "amlogic,g12a-audio-clkc";
- reg = <0x0 0x0 0x0 0xb4>;
- #clock-cells = <1>;
-
- clocks = <&clkc CLKID_AUDIO>,
- <&clkc CLKID_MPLL0>,
- <&clkc CLKID_MPLL1>,
- <&clkc CLKID_MPLL2>,
- <&clkc CLKID_MPLL3>,
- <&clkc CLKID_HIFI_PLL>,
- <&clkc CLKID_FCLK_DIV3>,
- <&clkc CLKID_FCLK_DIV4>,
- <&clkc CLKID_GP0_PLL>;
- clock-names = "pclk",
- "mst_in0",
- "mst_in1",
- "mst_in2",
- "mst_in3",
- "mst_in4",
- "mst_in5",
- "mst_in6",
- "mst_in7";
-
- resets = <&reset RESET_AUDIO>;
- };
-
- toddr_a: audio-controller@100 {
- compatible = "amlogic,g12a-toddr",
- "amlogic,axg-toddr";
- reg = <0x0 0x100 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "TODDR_A";
- interrupts = <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_TODDR_A>;
- resets = <&arb AXG_ARB_TODDR_A>;
- status = "disabled";
- };
-
- toddr_b: audio-controller@140 {
- compatible = "amlogic,g12a-toddr",
- "amlogic,axg-toddr";
- reg = <0x0 0x140 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "TODDR_B";
- interrupts = <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_TODDR_B>;
- resets = <&arb AXG_ARB_TODDR_B>;
- status = "disabled";
- };
-
- toddr_c: audio-controller@180 {
- compatible = "amlogic,g12a-toddr",
- "amlogic,axg-toddr";
- reg = <0x0 0x180 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "TODDR_C";
- interrupts = <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_TODDR_C>;
- resets = <&arb AXG_ARB_TODDR_C>;
- status = "disabled";
- };
-
- frddr_a: audio-controller@1c0 {
- compatible = "amlogic,g12a-frddr",
- "amlogic,axg-frddr";
- reg = <0x0 0x1c0 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "FRDDR_A";
- interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
- resets = <&arb AXG_ARB_FRDDR_A>;
- status = "disabled";
- };
-
- frddr_b: audio-controller@200 {
- compatible = "amlogic,g12a-frddr",
- "amlogic,axg-frddr";
- reg = <0x0 0x200 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "FRDDR_B";
- interrupts = <GIC_SPI 153 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_FRDDR_B>;
- resets = <&arb AXG_ARB_FRDDR_B>;
- status = "disabled";
- };
-
- frddr_c: audio-controller@240 {
- compatible = "amlogic,g12a-frddr",
- "amlogic,axg-frddr";
- reg = <0x0 0x240 0x0 0x1c>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "FRDDR_C";
- interrupts = <GIC_SPI 154 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_FRDDR_C>;
- resets = <&arb AXG_ARB_FRDDR_C>;
- status = "disabled";
- };
-
- arb: reset-controller@280 {
- status = "disabled";
- compatible = "amlogic,meson-axg-audio-arb";
- reg = <0x0 0x280 0x0 0x4>;
- #reset-cells = <1>;
- clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
- };
-
- tdmin_a: audio-controller@300 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
- reg = <0x0 0x300 0x0 0x40>;
- sound-name-prefix = "TDMIN_A";
- clocks = <&clkc_audio AUD_CLKID_TDMIN_A>,
- <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- tdmin_b: audio-controller@340 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
- reg = <0x0 0x340 0x0 0x40>;
- sound-name-prefix = "TDMIN_B";
- clocks = <&clkc_audio AUD_CLKID_TDMIN_B>,
- <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- tdmin_c: audio-controller@380 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
- reg = <0x0 0x380 0x0 0x40>;
- sound-name-prefix = "TDMIN_C";
- clocks = <&clkc_audio AUD_CLKID_TDMIN_C>,
- <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- tdmin_lb: audio-controller@3c0 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
- reg = <0x0 0x3c0 0x0 0x40>;
- sound-name-prefix = "TDMIN_LB";
- clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>,
- <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- spdifin: audio-controller@400 {
- compatible = "amlogic,g12a-spdifin",
- "amlogic,axg-spdifin";
- reg = <0x0 0x400 0x0 0x30>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "SPDIFIN";
- interrupts = <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_audio AUD_CLKID_SPDIFIN>,
- <&clkc_audio AUD_CLKID_SPDIFIN_CLK>;
- clock-names = "pclk", "refclk";
- status = "disabled";
- };
-
- spdifout: audio-controller@480 {
- compatible = "amlogic,g12a-spdifout",
- "amlogic,axg-spdifout";
- reg = <0x0 0x480 0x0 0x50>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "SPDIFOUT";
- clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
- <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
- clock-names = "pclk", "mclk";
- status = "disabled";
- };
-
- tdmout_a: audio-controller@500 {
- compatible = "amlogic,g12a-tdmout";
- reg = <0x0 0x500 0x0 0x40>;
- sound-name-prefix = "TDMOUT_A";
- clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
- <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- tdmout_b: audio-controller@540 {
- compatible = "amlogic,g12a-tdmout";
- reg = <0x0 0x540 0x0 0x40>;
- sound-name-prefix = "TDMOUT_B";
- clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>,
- <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- tdmout_c: audio-controller@580 {
- compatible = "amlogic,g12a-tdmout";
- reg = <0x0 0x580 0x0 0x40>;
- sound-name-prefix = "TDMOUT_C";
- clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>,
- <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>,
- <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>,
- <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>;
- clock-names = "pclk", "sclk", "sclk_sel",
- "lrclk", "lrclk_sel";
- status = "disabled";
- };
-
- spdifout_b: audio-controller@680 {
- compatible = "amlogic,g12a-spdifout",
- "amlogic,axg-spdifout";
- reg = <0x0 0x680 0x0 0x50>;
- #sound-dai-cells = <0>;
- sound-name-prefix = "SPDIFOUT_B";
- clocks = <&clkc_audio AUD_CLKID_SPDIFOUT_B>,
- <&clkc_audio AUD_CLKID_SPDIFOUT_B_CLK>;
- clock-names = "pclk", "mclk";
- status = "disabled";
- };
-
- tohdmitx: audio-controller@744 {
- compatible = "amlogic,g12a-tohdmitx";
- reg = <0x0 0x744 0x0 0x4>;
- #sound-dai-cells = <1>;
- sound-name-prefix = "TOHDMITX";
- status = "disabled";
- };
- };
-
- usb3_pcie_phy: phy@46000 {
- compatible = "amlogic,g12a-usb3-pcie-phy";
- reg = <0x0 0x46000 0x0 0x2000>;
- clocks = <&clkc CLKID_PCIE_PLL>;
- clock-names = "ref_clk";
- resets = <&reset RESET_PCIE_PHY>;
- reset-names = "phy";
- assigned-clocks = <&clkc CLKID_PCIE_PLL>;
- assigned-clock-rates = <100000000>;
- #phy-cells = <1>;
- };
-
- eth_phy: mdio-multiplexer@4c000 {
- compatible = "amlogic,g12a-mdio-mux";
- reg = <0x0 0x4c000 0x0 0xa4>;
- clocks = <&clkc CLKID_ETH_PHY>,
- <&xtal>,
- <&clkc CLKID_MPLL_50M>;
- clock-names = "pclk", "clkin0", "clkin1";
- mdio-parent-bus = <&mdio0>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- ext_mdio: mdio@0 {
- reg = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
- };
-
- int_mdio: mdio@1 {
- reg = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- internal_ephy: ethernet_phy@8 {
- compatible = "ethernet-phy-id0180.3301",
- "ethernet-phy-ieee802.3-c22";
- interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
- reg = <8>;
- max-speed = <100>;
- };
- };
- };
+ opp-667000000 {
+ opp-hz = /bits/ 64 <666666666>;
+ opp-microvolt = <731000>;
};
- aobus: bus@ff800000 {
- compatible = "simple-bus";
- reg = <0x0 0xff800000 0x0 0x100000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>;
-
- rti: sys-ctrl@0 {
- compatible = "amlogic,meson-gx-ao-sysctrl",
- "simple-mfd", "syscon";
- reg = <0x0 0x0 0x0 0x100>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x0 0x0 0x100>;
-
- clkc_AO: clock-controller {
- compatible = "amlogic,meson-g12a-aoclkc";
- #clock-cells = <1>;
- #reset-cells = <1>;
- clocks = <&xtal>, <&clkc CLKID_CLK81>;
- clock-names = "xtal", "mpeg-clk";
- };
-
- pwrc_vpu: power-controller-vpu {
- compatible = "amlogic,meson-g12a-pwrc-vpu";
- #power-domain-cells = <0>;
- amlogic,hhi-sysctrl = <&hhi>;
- resets = <&reset RESET_VIU>,
- <&reset RESET_VENC>,
- <&reset RESET_VCBUS>,
- <&reset RESET_BT656>,
- <&reset RESET_RDMA>,
- <&reset RESET_VENCI>,
- <&reset RESET_VENCP>,
- <&reset RESET_VDAC>,
- <&reset RESET_VDI6>,
- <&reset RESET_VENCL>,
- <&reset RESET_VID_LOCK>;
- clocks = <&clkc CLKID_VPU>,
- <&clkc CLKID_VAPB>;
- clock-names = "vpu", "vapb";
- /*
- * VPU clocking is provided by two identical clock paths
- * VPU_0 and VPU_1 muxed to a single clock by a glitch
- * free mux to safely change frequency while running.
- * Same for VAPB but with a final gate after the glitch free mux.
- */
- assigned-clocks = <&clkc CLKID_VPU_0_SEL>,
- <&clkc CLKID_VPU_0>,
- <&clkc CLKID_VPU>, /* Glitch free mux */
- <&clkc CLKID_VAPB_0_SEL>,
- <&clkc CLKID_VAPB_0>,
- <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */
- assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
- <0>, /* Do Nothing */
- <&clkc CLKID_VPU_0>,
- <&clkc CLKID_FCLK_DIV4>,
- <0>, /* Do Nothing */
- <&clkc CLKID_VAPB_0>;
- assigned-clock-rates = <0>, /* Do Nothing */
- <666666666>,
- <0>, /* Do Nothing */
- <0>, /* Do Nothing */
- <250000000>,
- <0>; /* Do Nothing */
- };
-
- ao_pinctrl: pinctrl@14 {
- compatible = "amlogic,meson-g12a-aobus-pinctrl";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- gpio_ao: bank@14 {
- reg = <0x0 0x14 0x0 0x8>,
- <0x0 0x1c 0x0 0x8>,
- <0x0 0x24 0x0 0x14>;
- reg-names = "mux",
- "ds",
- "gpio";
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&ao_pinctrl 0 0 15>;
- };
-
- i2c_ao_sck_pins: i2c_ao_sck_pins {
- mux {
- groups = "i2c_ao_sck";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c_ao_sda_pins: i2c_ao_sda {
- mux {
- groups = "i2c_ao_sda";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c_ao_sck_e_pins: i2c_ao_sck_e {
- mux {
- groups = "i2c_ao_sck_e";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- i2c_ao_sda_e_pins: i2c_ao_sda_e {
- mux {
- groups = "i2c_ao_sda_e";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- mclk0_ao_pins: mclk0-ao {
- mux {
- groups = "mclk0_ao";
- function = "mclk0_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_din0_pins: tdm-ao-b-din0 {
- mux {
- groups = "tdm_ao_b_din0";
- function = "tdm_ao_b";
- bias-disable;
- };
- };
-
- spdif_ao_out_pins: spdif-ao-out {
- mux {
- groups = "spdif_ao_out";
- function = "spdif_ao_out";
- drive-strength-microamp = <500>;
- bias-disable;
- };
- };
-
- tdm_ao_b_din1_pins: tdm-ao-b-din1 {
- mux {
- groups = "tdm_ao_b_din1";
- function = "tdm_ao_b";
- bias-disable;
- };
- };
-
- tdm_ao_b_din2_pins: tdm-ao-b-din2 {
- mux {
- groups = "tdm_ao_b_din2";
- function = "tdm_ao_b";
- bias-disable;
- };
- };
-
- tdm_ao_b_dout0_pins: tdm-ao-b-dout0 {
- mux {
- groups = "tdm_ao_b_dout0";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_dout1_pins: tdm-ao-b-dout1 {
- mux {
- groups = "tdm_ao_b_dout1";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_dout2_pins: tdm-ao-b-dout2 {
- mux {
- groups = "tdm_ao_b_dout2";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_fs_pins: tdm-ao-b-fs {
- mux {
- groups = "tdm_ao_b_fs";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_sclk_pins: tdm-ao-b-sclk {
- mux {
- groups = "tdm_ao_b_sclk";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs {
- mux {
- groups = "tdm_ao_b_slv_fs";
- function = "tdm_ao_b";
- bias-disable;
- };
- };
-
- tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk {
- mux {
- groups = "tdm_ao_b_slv_sclk";
- function = "tdm_ao_b";
- bias-disable;
- };
- };
-
- uart_ao_a_pins: uart-a-ao {
- mux {
- groups = "uart_ao_a_tx",
- "uart_ao_a_rx";
- function = "uart_ao_a";
- bias-disable;
- };
- };
-
- uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts {
- mux {
- groups = "uart_ao_a_cts",
- "uart_ao_a_rts";
- function = "uart_ao_a";
- bias-disable;
- };
- };
-
- pwm_ao_a_pins: pwm-ao-a {
- mux {
- groups = "pwm_ao_a";
- function = "pwm_ao_a";
- bias-disable;
- };
- };
-
- pwm_ao_b_pins: pwm-ao-b {
- mux {
- groups = "pwm_ao_b";
- function = "pwm_ao_b";
- bias-disable;
- };
- };
-
- pwm_ao_c_4_pins: pwm-ao-c-4 {
- mux {
- groups = "pwm_ao_c_4";
- function = "pwm_ao_c";
- bias-disable;
- };
- };
-
- pwm_ao_c_6_pins: pwm-ao-c-6 {
- mux {
- groups = "pwm_ao_c_6";
- function = "pwm_ao_c";
- bias-disable;
- };
- };
-
- pwm_ao_d_5_pins: pwm-ao-d-5 {
- mux {
- groups = "pwm_ao_d_5";
- function = "pwm_ao_d";
- bias-disable;
- };
- };
-
- pwm_ao_d_10_pins: pwm-ao-d-10 {
- mux {
- groups = "pwm_ao_d_10";
- function = "pwm_ao_d";
- bias-disable;
- };
- };
-
- pwm_ao_d_e_pins: pwm-ao-d-e {
- mux {
- groups = "pwm_ao_d_e";
- function = "pwm_ao_d";
- };
- };
-
- remote_input_ao_pins: remote-input-ao {
- mux {
- groups = "remote_ao_input";
- function = "remote_ao_input";
- bias-disable;
- };
- };
- };
- };
-
- cec_AO: cec@100 {
- compatible = "amlogic,meson-gx-ao-cec";
- reg = <0x0 0x00100 0x0 0x14>;
- interrupts = <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_AO CLKID_AO_CEC>;
- clock-names = "core";
- status = "disabled";
- };
-
- sec_AO: ao-secure@140 {
- compatible = "amlogic,meson-gx-ao-secure", "syscon";
- reg = <0x0 0x140 0x0 0x140>;
- amlogic,has-chip-id;
- };
-
- cecb_AO: cec@280 {
- compatible = "amlogic,meson-g12a-ao-cec";
- reg = <0x0 0x00280 0x0 0x1c>;
- interrupts = <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc_AO CLKID_AO_CTS_OSCIN>;
- clock-names = "oscin";
- status = "disabled";
- };
-
- pwm_AO_cd: pwm@2000 {
- compatible = "amlogic,meson-g12a-ao-pwm-cd";
- reg = <0x0 0x2000 0x0 0x20>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- uart_AO: serial@3000 {
- compatible = "amlogic,meson-gx-uart",
- "amlogic,meson-ao-uart";
- reg = <0x0 0x3000 0x0 0x18>;
- interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc_AO CLKID_AO_UART>, <&xtal>;
- clock-names = "xtal", "pclk", "baud";
- status = "disabled";
- };
-
- uart_AO_B: serial@4000 {
- compatible = "amlogic,meson-gx-uart",
- "amlogic,meson-ao-uart";
- reg = <0x0 0x4000 0x0 0x18>;
- interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
- clock-names = "xtal", "pclk", "baud";
- status = "disabled";
- };
-
- i2c_AO: i2c@5000 {
- compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
- reg = <0x0 0x05000 0x0 0x20>;
- interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- };
-
- pwm_AO_ab: pwm@7000 {
- compatible = "amlogic,meson-g12a-ao-pwm-ab";
- reg = <0x0 0x7000 0x0 0x20>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- ir: ir@8000 {
- compatible = "amlogic,meson-gxbb-ir";
- reg = <0x0 0x8000 0x0 0x20>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
- status = "disabled";
- };
-
- saradc: adc@9000 {
- compatible = "amlogic,meson-g12a-saradc",
- "amlogic,meson-saradc";
- reg = <0x0 0x9000 0x0 0x48>;
- #io-channel-cells = <1>;
- interrupts = <GIC_SPI 200 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>,
- <&clkc_AO CLKID_AO_SAR_ADC>,
- <&clkc_AO CLKID_AO_SAR_ADC_CLK>,
- <&clkc_AO CLKID_AO_SAR_ADC_SEL>;
- clock-names = "clkin", "core", "adc_clk", "adc_sel";
- status = "disabled";
- };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
};
- vpu: vpu@ff900000 {
- compatible = "amlogic,meson-g12a-vpu";
- reg = <0x0 0xff900000 0x0 0x100000>,
- <0x0 0xff63c000 0x0 0x1000>;
- reg-names = "vpu", "hhi";
- interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- amlogic,canvas = <&canvas>;
- power-domains = <&pwrc_vpu>;
-
- /* CVBS VDAC output port */
- cvbs_vdac_port: port@0 {
- reg = <0>;
- };
-
- /* HDMI-TX output port */
- hdmi_tx_port: port@1 {
- reg = <1>;
-
- hdmi_tx_out: endpoint {
- remote-endpoint = <&hdmi_tx_in>;
- };
- };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
};
- gic: interrupt-controller@ffc01000 {
- compatible = "arm,gic-400";
- reg = <0x0 0xffc01000 0 0x1000>,
- <0x0 0xffc02000 0 0x2000>,
- <0x0 0xffc04000 0 0x2000>,
- <0x0 0xffc06000 0 0x2000>;
- interrupt-controller;
- interrupts = <GIC_PPI 9
- (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
- #interrupt-cells = <3>;
- #address-cells = <0>;
+ opp-1398000000 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
};
- cbus: bus@ffd00000 {
- compatible = "simple-bus";
- reg = <0x0 0xffd00000 0x0 0x100000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x100000>;
-
- reset: reset-controller@1004 {
- compatible = "amlogic,meson-g12a-reset",
- "amlogic,meson-axg-reset";
- reg = <0x0 0x1004 0x0 0x9c>;
- #reset-cells = <1>;
- };
-
- gpio_intc: interrupt-controller@f080 {
- compatible = "amlogic,meson-g12a-gpio-intc",
- "amlogic,meson-gpio-intc";
- reg = <0x0 0xf080 0x0 0x10>;
- interrupt-controller;
- #interrupt-cells = <2>;
- amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
- };
-
- pwm_ef: pwm@19000 {
- compatible = "amlogic,meson-g12a-ee-pwm";
- reg = <0x0 0x19000 0x0 0x20>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm_cd: pwm@1a000 {
- compatible = "amlogic,meson-g12a-ee-pwm";
- reg = <0x0 0x1a000 0x0 0x20>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm_ab: pwm@1b000 {
- compatible = "amlogic,meson-g12a-ee-pwm";
- reg = <0x0 0x1b000 0x0 0x20>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- i2c3: i2c@1c000 {
- compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
- reg = <0x0 0x1c000 0x0 0x20>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- };
-
- i2c2: i2c@1d000 {
- compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
- reg = <0x0 0x1d000 0x0 0x20>;
- interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- };
-
- i2c1: i2c@1e000 {
- compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
- reg = <0x0 0x1e000 0x0 0x20>;
- interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- };
-
- i2c0: i2c@1f000 {
- compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
- reg = <0x0 0x1f000 0x0 0x20>;
- interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- };
-
- clk_msr: clock-measure@18000 {
- compatible = "amlogic,meson-g12a-clk-measure";
- reg = <0x0 0x18000 0x0 0x10>;
- };
-
- uart_C: serial@22000 {
- compatible = "amlogic,meson-gx-uart";
- reg = <0x0 0x22000 0x0 0x18>;
- interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
- clock-names = "xtal", "pclk", "baud";
- status = "disabled";
- };
-
- uart_B: serial@23000 {
- compatible = "amlogic,meson-gx-uart";
- reg = <0x0 0x23000 0x0 0x18>;
- interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
- clock-names = "xtal", "pclk", "baud";
- status = "disabled";
- };
-
- uart_A: serial@24000 {
- compatible = "amlogic,meson-gx-uart";
- reg = <0x0 0x24000 0x0 0x18>;
- interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
- clock-names = "xtal", "pclk", "baud";
- status = "disabled";
- };
- };
-
- sd_emmc_a: sd@ffe03000 {
- compatible = "amlogic,meson-axg-mmc";
- reg = <0x0 0xffe03000 0x0 0x800>;
- interrupts = <GIC_SPI 189 IRQ_TYPE_EDGE_RISING>;
- status = "disabled";
- clocks = <&clkc CLKID_SD_EMMC_A>,
- <&clkc CLKID_SD_EMMC_A_CLK0>,
- <&clkc CLKID_FCLK_DIV2>;
- clock-names = "core", "clkin0", "clkin1";
- resets = <&reset RESET_SD_EMMC_A>;
- amlogic,dram-access-quirk;
- };
-
- sd_emmc_b: sd@ffe05000 {
- compatible = "amlogic,meson-axg-mmc";
- reg = <0x0 0xffe05000 0x0 0x800>;
- interrupts = <GIC_SPI 190 IRQ_TYPE_EDGE_RISING>;
- status = "disabled";
- clocks = <&clkc CLKID_SD_EMMC_B>,
- <&clkc CLKID_SD_EMMC_B_CLK0>,
- <&clkc CLKID_FCLK_DIV2>;
- clock-names = "core", "clkin0", "clkin1";
- resets = <&reset RESET_SD_EMMC_B>;
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
};
- sd_emmc_c: mmc@ffe07000 {
- compatible = "amlogic,meson-axg-mmc";
- reg = <0x0 0xffe07000 0x0 0x800>;
- interrupts = <GIC_SPI 191 IRQ_TYPE_EDGE_RISING>;
- status = "disabled";
- clocks = <&clkc CLKID_SD_EMMC_C>,
- <&clkc CLKID_SD_EMMC_C_CLK0>,
- <&clkc CLKID_FCLK_DIV2>;
- clock-names = "core", "clkin0", "clkin1";
- resets = <&reset RESET_SD_EMMC_C>;
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
};
- usb: usb@ffe09000 {
- status = "disabled";
- compatible = "amlogic,meson-g12a-usb-ctrl";
- reg = <0x0 0xffe09000 0x0 0xa0>;
- interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- clocks = <&clkc CLKID_USB>;
- resets = <&reset RESET_USB>;
-
- dr_mode = "otg";
-
- phys = <&usb2_phy0>, <&usb2_phy1>,
- <&usb3_pcie_phy PHY_TYPE_USB3>;
- phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0";
-
- dwc2: usb@ff400000 {
- compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
- reg = <0x0 0xff400000 0x0 0x40000>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
- clock-names = "ddr";
- phys = <&usb2_phy1>;
- dr_mode = "peripheral";
- g-rx-fifo-size = <192>;
- g-np-tx-fifo-size = <128>;
- g-tx-fifo-size = <128 128 16 16 16>;
- };
-
- dwc3: usb@ff500000 {
- compatible = "snps,dwc3";
- reg = <0x0 0xff500000 0x0 0x100000>;
- interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
- dr_mode = "host";
- snps,dis_u2_susphy_quirk;
- snps,quirk-frame-length-adjustment;
- };
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
};
- mali: gpu@ffe40000 {
- compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost";
- reg = <0x0 0xffe40000 0x0 0x40000>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "gpu", "mmu", "job";
- clocks = <&clkc CLKID_MALI>;
- resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
-
- /*
- * Mali clocking is provided by two identical clock paths
- * MALI_0 and MALI_1 muxed to a single clock by a glitch
- * free mux to safely change frequency while running.
- */
- assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
- <&clkc CLKID_MALI_0>,
- <&clkc CLKID_MALI>; /* Glitch free mux */
- assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>,
- <0>, /* Do Nothing */
- <&clkc CLKID_MALI_0>;
- assigned-clock-rates = <0>, /* Do Nothing */
- <800000000>,
- <0>; /* Do Nothing */
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <981000>;
};
};
+};
- timer {
- compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 13
- (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 14
- (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 11
- (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 10
- (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
- };
+&ethmac {
+ power-domains = <&pwrc PWRC_G12A_ETH_ID>;
+};
- xtal: xtal-clk {
- compatible = "fixed-clock";
- clock-frequency = <24000000>;
- clock-output-names = "xtal";
- #clock-cells = <0>;
- };
+&vpu {
+ power-domains = <&pwrc PWRC_G12A_VPU_ID>;
+};
+&sd_emmc_a {
+ amlogic,dram-access-quirk;
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts
new file mode 100644
index 000000000000..3a6a1e0c1e32
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (c) 2019 Christian Hewitt <christianshewitt@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "meson-g12b-a311d.dtsi"
+#include "meson-khadas-vim3.dtsi"
+#include "meson-g12b-khadas-vim3.dtsi"
+
+/ {
+ compatible = "khadas,vim3", "amlogic,a311d", "amlogic,g12b";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
new file mode 100644
index 000000000000..d61f43052a34
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12b.dtsi"
+
+/ {
+ cpu_opp_table_0: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-667000000 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <761000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <781000>;
+ };
+
+ opp-1398000000 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <811000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <861000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <901000>;
+ };
+
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <951000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <1001000>;
+ };
+ };
+
+ cpub_opp_table_1: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-667000000 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <751000>;
+ };
+
+ opp-1398000000 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <771000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <771000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <781000>;
+ };
+
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <791000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <831000>;
+ };
+
+ opp-1908000000 {
+ opp-hz = /bits/ 64 <1908000000>;
+ opp-microvolt = <861000>;
+ };
+
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <911000>;
+ };
+
+ opp-2108000000 {
+ opp-hz = /bits/ 64 <2108000000>;
+ opp-microvolt = <951000>;
+ };
+
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <1011000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
new file mode 100644
index 000000000000..554863429aa6
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (c) 2019 Christian Hewitt <christianshewitt@gmail.com>
+ */
+
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+
+/ {
+ vddcpu_a: regulator-vddcpu-a {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU_A";
+ regulator-min-microvolt = <690000>;
+ regulator-max-microvolt = <1050000>;
+
+ vin-supply = <&dc_in>;
+
+ pwms = <&pwm_ab 0 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddcpu_b: regulator-vddcpu-b {
+ /*
+ * Silergy SY8030DEC Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU_B";
+ regulator-min-microvolt = <690000>;
+ regulator-max-microvolt = <1050000>;
+
+ vin-supply = <&vsys_3v3>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sound {
+ compatible = "amlogic,axg-sound-card";
+ model = "G12A-KHADAS-VIM3";
+ audio-aux-devs = <&tdmout_b>;
+ audio-routing = "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";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+ status = "okay";
+
+ dai-link-0 {
+ sound-dai = <&frddr_a>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&frddr_b>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&frddr_c>;
+ };
+
+ /* 8ch hdmi interface */
+ dai-link-3 {
+ sound-dai = <&tdmif_b>;
+ 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 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+ };
+ };
+
+ /* hdmi glue */
+ dai-link-4 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&arb {
+ status = "okay";
+};
+
+&clkc_audio {
+ status = "okay";
+};
+
+&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>;
+};
+
+&frddr_b {
+ status = "okay";
+};
+
+&frddr_c {
+ status = "okay";
+};
+
+&pwm_ab {
+ pinctrl-0 = <&pwm_a_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin0";
+ status = "okay";
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
+};
+
+&tdmif_b {
+ status = "okay";
+};
+
+&tdmout_b {
+ status = "okay";
+};
+
+&tohdmitx {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts
index 81780ffcc7f0..42f15405750c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts
@@ -6,7 +6,7 @@
/dts-v1/;
-#include "meson-g12b.dtsi"
+#include "meson-g12b-s922x.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/meson-g12a-gpio.h>
#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
@@ -53,6 +53,7 @@
gpio = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>;
enable-active-high;
+ regulator-always-on;
};
tf_io: gpio-regulator-tf_io {
@@ -65,8 +66,8 @@
gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
gpios-states = <0>;
- states = <3300000 0
- 1800000 1>;
+ states = <3300000 0>,
+ <1800000 1>;
};
flash_1v8: regulator-flash_1v8 {
@@ -114,6 +115,44 @@
/* FIXME: actually controlled by VDDCPU_B_EN */
};
+ vddcpu_a: regulator-vddcpu-a {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU_A";
+ regulator-min-microvolt = <721000>;
+ regulator-max-microvolt = <1022000>;
+
+ vin-supply = <&main_12v>;
+
+ pwms = <&pwm_ab 0 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddcpu_b: regulator-vddcpu-b {
+ /*
+ * Silergy SY8120B1ABC Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU_B";
+ regulator-min-microvolt = <721000>;
+ regulator-max-microvolt = <1022000>;
+
+ vin-supply = <&main_12v>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
hub_5v: regulator-hub_5v {
compatible = "regulator-fixed";
regulator-name = "HUB_5V";
@@ -245,6 +284,48 @@
status = "okay";
};
+&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>;
+};
+
&ext_mdio {
external_phy: ethernet-phy@0 {
/* Realtek RTL8211F (0x001cc916) */
@@ -314,6 +395,23 @@
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
pinctrl-names = "default";
+ linux,rc-map-name = "rc-odroid";
+};
+
+&pwm_ab {
+ pinctrl-0 = <&pwm_a_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin0";
+ status = "okay";
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
};
/* SD card */
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts
new file mode 100644
index 000000000000..b73deb282120
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (c) 2019 Christian Hewitt <christianshewitt@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "meson-g12b-s922x.dtsi"
+#include "meson-khadas-vim3.dtsi"
+#include "meson-g12b-khadas-vim3.dtsi"
+
+/ {
+ compatible = "khadas,vim3", "amlogic,s922x", "amlogic,g12b";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
new file mode 100644
index 000000000000..046cc332d07f
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12b.dtsi"
+
+/ {
+ cpu_opp_table_0: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-667000000 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
+ };
+
+ opp-1398000000 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
+ };
+
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
+ };
+
+ opp-1896000000 {
+ opp-hz = /bits/ 64 <1896000000>;
+ opp-microvolt = <981000>;
+ };
+ };
+
+ cpub_opp_table_1: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <751000>;
+ };
+
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <751000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <751000>;
+ };
+
+ opp-667000000 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <751000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <771000>;
+ };
+
+ opp-1398000000 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <791000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <821000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <861000>;
+ };
+
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <891000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
index 9e88e513b22d..5628ccd54531 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
@@ -4,12 +4,16 @@
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
-#include "meson-g12a.dtsi"
+#include "meson-g12-common.dtsi"
+#include <dt-bindings/power/meson-g12a-power.h>
/ {
compatible = "amlogic,g12b";
cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
cpu-map {
cluster0 {
core0 {
@@ -40,8 +44,21 @@
};
};
- /delete-node/ cpu@2;
- /delete-node/ cpu@3;
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
cpu100: cpu@100 {
device_type = "cpu";
@@ -74,9 +91,25 @@
enable-method = "psci";
next-level-cache = <&l2>;
};
+
+ l2: l2-cache0 {
+ compatible = "cache";
+ };
};
};
&clkc {
compatible = "amlogic,g12b-clkc";
};
+
+&ethmac {
+ power-domains = <&pwrc PWRC_G12A_ETH_ID>;
+};
+
+&vpu {
+ power-domains = <&pwrc PWRC_G12A_VPU_ID>;
+};
+
+&sd_emmc_a {
+ amlogic,dram-access-quirk;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index 74d03fc706be..6733050d735f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -220,7 +220,7 @@
};
reset: reset-controller@4404 {
- compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
+ compatible = "amlogic,meson-gxbb-reset";
reg = <0x0 0x04404 0x0 0x9c>;
#reset-cells = <1>;
};
@@ -317,7 +317,7 @@
};
spifc: spi@8c80 {
- compatible = "amlogic,meson-gx-spifc", "amlogic,meson-gxbb-spifc";
+ compatible = "amlogic,meson-gxbb-spifc";
reg = <0x0 0x08c80 0x0 0x80>;
#address-cells = <1>;
#size-cells = <0>;
@@ -325,7 +325,7 @@
};
watchdog@98d0 {
- compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
+ compatible = "amlogic,meson-gxbb-wdt";
reg = <0x0 0x098d0 0x0 0x10>;
clocks = <&xtal>;
};
@@ -437,7 +437,21 @@
};
};
- periphs: periphs@c8834000 {
+ vdec: video-codec@c8820000 {
+ compatible = "amlogic,gx-vdec";
+ reg = <0x0 0xc8820000 0x0 0x10000>,
+ <0x0 0xc110a580 0x0 0xe4>;
+ reg-names = "dos", "esparser";
+
+ interrupts = <GIC_SPI 44 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "vdec", "esparser";
+
+ amlogic,ao-sysctrl = <&sysctrl_AO>;
+ amlogic,canvas = <&canvas>;
+ };
+
+ periphs: bus@c8834000 {
compatible = "simple-bus";
reg = <0x0 0xc8834000 0x0 0x2000>;
#address-cells = <2>;
@@ -476,7 +490,7 @@
};
mailbox: mailbox@404 {
- compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
+ compatible = "amlogic,meson-gxbb-mhu";
reg = <0 0x404 0 0x4c>;
interrupts = <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 209 IRQ_TYPE_EDGE_RISING>,
@@ -489,10 +503,12 @@
compatible = "amlogic,meson-gxbb-dwmac",
"snps,dwmac-3.70a",
"snps,dwmac";
- reg = <0x0 0xc9410000 0x0 0x10000
- 0x0 0xc8834540 0x0 0x4>;
+ reg = <0x0 0xc9410000 0x0 0x10000>,
+ <0x0 0xc8834540 0x0 0x4>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <2048>;
status = "disabled";
};
@@ -528,9 +544,8 @@
vpu: vpu@d0100000 {
compatible = "amlogic,meson-gx-vpu";
reg = <0x0 0xd0100000 0x0 0x100000>,
- <0x0 0xc883c000 0x0 0x1000>,
- <0x0 0xc8838000 0x0 0x1000>;
- reg-names = "vpu", "hhi", "dmc";
+ <0x0 0xc883c000 0x0 0x1000>;
+ reg-names = "vpu", "hhi";
interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
index c34c1c90ccb6..233eb1cd7967 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
@@ -10,6 +10,7 @@
/ {
compatible = "friendlyarm,nanopi-k2", "amlogic,meson-gxbb";
+ model = "FriendlyARM NanoPi K2";
aliases {
serial0 = &uart_AO;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index b636912a2715..afcf8a9f667b 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -75,8 +75,8 @@
gpios-states = <1>;
/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
- states = <1800000 0
- 3300000 1>;
+ states = <1800000 0>,
+ <3300000 1>;
};
vddio_boot: regulator-vddio_boot {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 9972b1515da6..6039adda12ee 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -77,8 +77,8 @@
gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
gpios-states = <0>;
- states = <3300000 0
- 1800000 1>;
+ states = <3300000 0>,
+ <1800000 1>;
};
vcc1v8: regulator-vcc1v8 {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
index 56e0dd1ff55c..150a82f3b2d7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
@@ -21,6 +21,6 @@
phy-mode = "rmii";
snps,reset-gpio = <&gpio GPIOZ_14 0>;
- snps,reset-delays-us = <0 10000 1000000>;
+ snps,reset-delays-us = <0>, <10000>, <1000000>;
snps,reset-active-low;
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index e8f925871edf..89f7b41b0e9e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -46,8 +46,8 @@
gpios-states = <1>;
/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
- states = <1800000 0
- 3300000 1>;
+ states = <1800000 0>,
+ <3300000 1>;
regulator-settling-time-up-us = <10000>;
regulator-settling-time-down-us = <150000>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
index 2bfe69902552..83b985bb015e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
@@ -12,3 +12,7 @@
compatible = "wetek,hub", "amlogic,meson-gxbb";
model = "WeTek Hub";
};
+
+&ir {
+ linux,rc-map-name = "rc-wetek-hub";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
index 0038522315de..1d32d1f6d032 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
@@ -54,3 +54,7 @@
&usb1 {
status = "okay";
};
+
+&ir {
+ linux,rc-map-name = "rc-wetek-play2";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index f734faaf7b78..0cb40326b0d3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -845,3 +845,14 @@
compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
power-domains = <&pwrc_vpu>;
};
+
+&vdec {
+ compatible = "amlogic,gxbb-vdec", "amlogic,gx-vdec";
+ clocks = <&clkc CLKID_DOS_PARSER>,
+ <&clkc CLKID_DOS>,
+ <&clkc CLKID_VDEC_1>,
+ <&clkc CLKID_VDEC_HEVC>;
+ clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc";
+ resets = <&reset RESET_PARSER>;
+ reset-names = "esparser";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
index 789c819c99c4..dd729ac2300d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
@@ -20,3 +20,7 @@
reg = <0x0 0x0 0x0 0x40000000>; /* 1 GiB or 2 GiB */
};
};
+
+&ir {
+ linux,rc-map-name = "rc-tanix-tx3mini";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
index 796baea7a0bf..c8d74e61dec1 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
@@ -38,8 +38,8 @@
gpios-states = <1>;
/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
- states = <1800000 0
- 3300000 1>;
+ states = <1800000 0>,
+ <3300000 1>;
};
vddio_boot: regulator-vddio_boot {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index 5499e8de5c74..2a5cd303123d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -110,7 +110,7 @@
};
&ir {
- linux,rc-map-name = "rc-geekbox";
+ linux,rc-map-name = "rc-khadas";
};
&gpio_ao {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
index 26907ac82930..c433a031841f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
@@ -38,8 +38,8 @@
gpios-states = <1>;
/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
- states = <1800000 0
- 3300000 1>;
+ states = <1800000 0>,
+ <3300000 1>;
};
vddio_boot: regulator-vddio_boot {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c959456bacc6..49ff0a7d0210 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -80,9 +80,6 @@
};
&ethmac {
- reg = <0x0 0xc9410000 0x0 0x10000
- 0x0 0xc8834540 0x0 0x4>;
-
clocks = <&clkc CLKID_ETH>,
<&clkc CLKID_FCLK_DIV2>,
<&clkc CLKID_MPLL2>;
@@ -712,7 +709,7 @@
#size-cells = <0>;
internal_phy: ethernet-phy@8 {
- compatible = "ethernet-phy-id0181.4400", "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id0181.4400";
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
reg = <8>;
max-speed = <100>;
@@ -848,3 +845,14 @@
compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
power-domains = <&pwrc_vpu>;
};
+
+&vdec {
+ compatible = "amlogic,gxl-vdec", "amlogic,gx-vdec";
+ clocks = <&clkc CLKID_DOS_PARSER>,
+ <&clkc CLKID_DOS>,
+ <&clkc CLKID_VDEC_1>,
+ <&clkc CLKID_VDEC_HEVC>;
+ clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc";
+ resets = <&reset RESET_PARSER>;
+ reset-names = "esparser";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
index 989d33ac6eae..f25ddd18a607 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
@@ -299,7 +299,7 @@
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
pinctrl-names = "default";
- linux,rc-map-name = "rc-geekbox";
+ linux,rc-map-name = "rc-khadas";
};
&pwm_AO_ab {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
index 7a85a82bf65d..a0e677d5a8f7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
@@ -144,3 +144,7 @@
&dwc3 {
phys = <&usb3_phy>, <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>;
};
+
+&vdec {
+ compatible = "amlogic,gxm-vdec", "amlogic,gx-vdec";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi
new file mode 100644
index 000000000000..8647da7d6609
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (c) 2019 Christian Hewitt <christianshewitt@gmail.com>
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
+
+/ {
+ model = "Khadas VIM3";
+
+ aliases {
+ serial0 = &uart_AO;
+ ethernet0 = &ethmac;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 2>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1710000>;
+
+ button-function {
+ label = "Function";
+ linux,code = <KEY_FN>;
+ press-threshold-microvolt = <10000>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ white {
+ label = "vim3:white:sys";
+ gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ red {
+ label = "vim3:red";
+ gpios = <&gpio_expander 5 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
+ };
+
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ poll-interval = <100>;
+
+ power-button {
+ label = "power";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+ clocks = <&wifi32k>;
+ clock-names = "ext_clock";
+ };
+
+ dc_in: regulator-dc_in {
+ compatible = "regulator-fixed";
+ regulator-name = "DC_IN";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ vcc_5v: regulator-vcc_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_in>;
+
+ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
+ enable-active-high;
+ };
+
+ vcc_1v8: regulator-vcc_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_3v3>;
+ 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 = <&vsys_3v3>;
+ regulator-always-on;
+ /* FIXME: actually controlled by VDDCPU_B_EN */
+ };
+
+ vddao_1v8: regulator-vddao_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDIO_AO1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vsys_3v3>;
+ regulator-always-on;
+ };
+
+ emmc_1v8: regulator-emmc_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "EMMC_AO1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_3v3>;
+ regulator-always-on;
+ };
+
+ vsys_3v3: regulator-vsys_3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSYS_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&dc_in>;
+ regulator-always-on;
+ };
+
+ usb_pwr: regulator-usb_pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "USB_PWR";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v>;
+
+ gpio = <&gpio GPIOA_6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+
+ wifi32k: wifi32k {
+ compatible = "pwm-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+ };
+};
+
+&cec_AO {
+ pinctrl-0 = <&cec_ao_a_h_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&cecb_AO {
+ pinctrl-0 = <&cec_ao_b_h_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&ext_mdio {
+ external_phy: ethernet-phy@0 {
+ /* Realtek RTL8211F (0x001cc916) */
+ reg = <0>;
+ max-speed = <1000>;
+
+ interrupt-parent = <&gpio_intc>;
+ /* MAC_INTR on GPIOZ_14 */
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&ethmac {
+ pinctrl-0 = <&eth_pins>, <&eth_rgmii_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ phy-mode = "rgmii";
+ phy-handle = <&external_phy>;
+ amlogic,tx-delay-ns = <2>;
+};
+
+&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>;
+ };
+};
+
+&i2c_AO {
+ status = "okay";
+ pinctrl-0 = <&i2c_ao_sck_pins>, <&i2c_ao_sda_pins>;
+ pinctrl-names = "default";
+
+ gpio_expander: gpio-controller@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ vcc-supply = <&vcc_3v3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ };
+};
+
+&ir {
+ status = "okay";
+ pinctrl-0 = <&remote_input_ao_pins>;
+ pinctrl-names = "default";
+ linux,rc-map-name = "rc-khadas";
+};
+
+&pwm_ef {
+ status = "okay";
+ pinctrl-0 = <&pwm_e_pins>;
+ pinctrl-names = "default";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddao_1v8>;
+};
+
+/* SDIO */
+&sd_emmc_a {
+ status = "okay";
+ pinctrl-0 = <&sdio_pins>;
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ max-frequency = <100000000>;
+
+ non-removable;
+ disable-wp;
+
+ mmc-pwrseq = <&sdio_pwrseq>;
+
+ vmmc-supply = <&vsys_3v3>;
+ vqmmc-supply = <&vddao_1v8>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+/* 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;
+ max-frequency = <50000000>;
+ disable-wp;
+
+ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&vsys_3v3>;
+ vqmmc-supply = <&vsys_3v3>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ max-frequency = <200000000>;
+ disable-wp;
+
+ mmc-pwrseq = <&emmc_pwrseq>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&emmc_1v8>;
+};
+
+&uart_A {
+ status = "okay";
+ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ max-speed = <2000000>;
+ clocks = <&wifi32k>;
+ clock-names = "lpo";
+ };
+};
+
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_ao_a_pins>;
+ pinctrl-names = "default";
+};
+
+&usb2_phy0 {
+ phy-supply = <&dc_in>;
+};
+
+&usb2_phy1 {
+ phy-supply = <&usb_pwr>;
+};
+
+&usb3_pcie_phy {
+ phy-supply = <&usb_pwr>;
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "peripheral";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts
new file mode 100644
index 000000000000..5233bd7cacfb
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include "meson-sm1.dtsi"
+#include "meson-khadas-vim3.dtsi"
+
+/ {
+ compatible = "khadas,vim3l", "amlogic,sm1";
+ model = "Khadas VIM3L";
+
+ vddcpu: regulator-vddcpu {
+ /*
+ * Silergy SY8030DEC Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU";
+ regulator-min-microvolt = <690000>;
+ regulator-max-microvolt = <1050000>;
+
+ vin-supply = <&vsys_3v3>;
+
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU1_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU2_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU3_CLK>;
+ clock-latency = <50000>;
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
new file mode 100644
index 000000000000..3435aaa4e8db
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre SAS. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "meson-sm1.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
+
+/ {
+ compatible = "seirobotics,sei610", "amlogic,sm1";
+ model = "SEI Robotics SEI610";
+
+ aliases {
+ serial0 = &uart_AO;
+ ethernet0 = &ethmac;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys-polled";
+ poll-interval = <100>;
+
+ key1 {
+ label = "A";
+ linux,code = <BTN_0>;
+ gpios = <&gpio GPIOH_6 GPIO_ACTIVE_LOW>;
+ };
+
+ key2 {
+ label = "B";
+ linux,code = <BTN_1>;
+ gpios = <&gpio GPIOH_7 GPIO_ACTIVE_LOW>;
+ };
+
+ key3 {
+ label = "C";
+ linux,code = <BTN_2>;
+ gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ bluetooth {
+ label = "sei610:blue:bt";
+ gpios = <&gpio GPIOC_7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+ default-state = "off";
+ };
+ };
+
+ pwmleds {
+ compatible = "pwm-leds";
+
+ power {
+ label = "sei610:red:power";
+ pwms = <&pwm_AO_ab 0 30518 0>;
+ max-brightness = <255>;
+ linux,default-trigger = "default-on";
+ active-low;
+ };
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x40000000>;
+ };
+
+ ao_5v: regulator-ao_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "AO_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_in>;
+ regulator-always-on;
+ };
+
+ dc_in: regulator-dc_in {
+ compatible = "regulator-fixed";
+ regulator-name = "DC_IN";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ emmc_1v8: regulator-emmc_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "EMMC_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vddao_3v3>;
+ 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 = <&dc_in>;
+ regulator-always-on;
+ };
+
+ /* Used by Tuner, RGB Led & IR Emitter LED array */
+ vddao_3v3_t: regulator-vddao_3v3_t {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDAO_3V3_T";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vddao_3v3>;
+ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
+ enable-active-low;
+ regulator-always-on;
+ };
+
+ vddcpu: regulator-vddcpu {
+ /*
+ * SY8120B1ABC DC/DC Regulator.
+ */
+ compatible = "pwm-regulator";
+
+ regulator-name = "VDDCPU";
+ regulator-min-microvolt = <690000>;
+ regulator-max-microvolt = <1050000>;
+
+ vin-supply = <&dc_in>;
+
+ pwms = <&pwm_AO_cd 1 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddio_ao1v8: regulator-vddio_ao1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDIO_AO1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vddao_3v3>;
+ regulator-always-on;
+ };
+
+ reserved-memory {
+ /* TEE Reserved Memory */
+ bl32_reserved: bl32@5000000 {
+ reg = <0x0 0x05300000 0x0 0x2000000>;
+ no-map;
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+ clocks = <&wifi32k>;
+ clock-names = "ext_clock";
+ };
+
+ wifi32k: wifi32k {
+ compatible = "pwm-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+ };
+};
+
+&cec_AO {
+ pinctrl-0 = <&cec_ao_a_h_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&cecb_AO {
+ pinctrl-0 = <&cec_ao_b_h_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU1_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU2_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU3_CLK>;
+ clock-latency = <50000>;
+};
+
+&ethmac {
+ status = "okay";
+ phy-handle = <&internal_ephy>;
+ phy-mode = "rmii";
+};
+
+&hdmi_tx {
+ status = "okay";
+ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+ pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+ hdmi_tx_tmds_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>;
+ pinctrl-names = "default";
+};
+
+&ir {
+ status = "okay";
+ pinctrl-0 = <&remote_input_ao_pins>;
+ pinctrl-names = "default";
+};
+
+&pwm_AO_ab {
+ status = "okay";
+ pinctrl-0 = <&pwm_ao_a_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin0";
+};
+
+&pwm_AO_cd {
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+ status = "okay";
+};
+
+&pwm_ef {
+ status = "okay";
+ pinctrl-0 = <&pwm_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin0";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_ao1v8>;
+};
+
+/* SDIO */
+&sd_emmc_a {
+ status = "okay";
+ pinctrl-0 = <&sdio_pins>;
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ max-frequency = <100000000>;
+
+ non-removable;
+ disable-wp;
+
+ mmc-pwrseq = <&sdio_pwrseq>;
+
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&vddio_ao1v8>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+/* 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;
+ max-frequency = <50000000>;
+ disable-wp;
+
+ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&vddao_3v3>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ max-frequency = <200000000>;
+ non-removable;
+ disable-wp;
+
+ mmc-pwrseq = <&emmc_pwrseq>;
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&emmc_1v8>;
+};
+
+&uart_A {
+ status = "okay";
+ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ max-speed = <2000000>;
+ clocks = <&wifi32k>;
+ clock-names = "lpo";
+ vbat-supply = <&vddao_3v3>;
+ vddio-supply = <&vddio_ao1v8>;
+ };
+};
+
+/* Exposed via the on-board USB to Serial FT232RL IC */
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_ao_a_pins>;
+ pinctrl-names = "default";
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "otg";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
new file mode 100644
index 000000000000..521573f3a5ba
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12-common.dtsi"
+#include <dt-bindings/power/meson-sm1-power.h>
+
+/ {
+ compatible = "amlogic,sm1";
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x2>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x3>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ l2: l2-cache0 {
+ compatible = "cache";
+ };
+ };
+
+ cpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <730000>;
+ };
+
+ opp-250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <730000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <730000>;
+ };
+
+ opp-667000000 {
+ opp-hz = /bits/ 64 <666666666>;
+ opp-microvolt = <750000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <770000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <780000>;
+ };
+
+ opp-1404000000 {
+ opp-hz = /bits/ 64 <1404000000>;
+ opp-microvolt = <790000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <800000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <810000>;
+ };
+
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <850000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <900000>;
+ };
+
+ opp-1908000000 {
+ opp-hz = /bits/ 64 <1908000000>;
+ opp-microvolt = <950000>;
+ };
+ };
+};
+
+&cecb_AO {
+ compatible = "amlogic,meson-sm1-ao-cec";
+};
+
+&clk_msr {
+ compatible = "amlogic,meson-sm1-clk-measure";
+};
+
+
+&clkc {
+ compatible = "amlogic,sm1-clkc";
+};
+
+&ethmac {
+ power-domains = <&pwrc PWRC_SM1_ETH_ID>;
+};
+
+&pwrc {
+ compatible = "amlogic,meson-sm1-pwrc";
+};
+
+&vpu {
+ power-domains = <&pwrc PWRC_SM1_VPU_ID>;
+};
+
+&usb {
+ power-domains = <&pwrc PWRC_SM1_USB_ID>;
+};
diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
index 687707020ec1..62ab0d54ff71 100644
--- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts
+++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
@@ -265,13 +265,5 @@
<0 0 42 &gic 0 0 GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
<0 0 43 &gic 0 0 GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
<0 0 44 &gic 0 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-
- motherboard {
- iofpga@3,00000000 {
- clcd@1f0000 {
- max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
- };
- };
- };
};
};
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
index 454cf6c44c49..03a7bf079c8f 100644
--- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
@@ -188,8 +188,6 @@
interrupts = <14>;
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
clock-names = "clcdclk", "apb_pclk";
- /* 800x600 16bpp @36MHz works fine */
- max-memory-bandwidth = <54000000>;
memory-region = <&vram>;
port {
diff --git a/arch/arm64/boot/dts/bitmain/bm1880.dtsi b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
index 7726fd4c6be6..d65453f99a99 100644
--- a/arch/arm64/boot/dts/bitmain/bm1880.dtsi
+++ b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
@@ -5,6 +5,7 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/bitmain,bm1880-reset.h>
/ {
compatible = "bitmain,bm1880";
@@ -88,9 +89,15 @@
#size-cells = <1>;
ranges = <0x0 0x0 0x50010000 0x1000>;
- pinctrl: pinctrl@50 {
+ pinctrl: pinctrl@400 {
compatible = "bitmain,bm1880-pinctrl";
- reg = <0x50 0x4B0>;
+ reg = <0x400 0x120>;
+ };
+
+ rst: reset-controller@c00 {
+ compatible = "bitmain,bm1880-reset";
+ reg = <0xc00 0x8>;
+ #reset-cells = <1>;
};
};
@@ -154,6 +161,7 @@
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
+ resets = <&rst BM1880_RST_UART0_1_CLK>;
status = "disabled";
};
@@ -163,6 +171,7 @@
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
+ resets = <&rst BM1880_RST_UART0_1_ACLK>;
status = "disabled";
};
@@ -172,6 +181,7 @@
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
+ resets = <&rst BM1880_RST_UART2_3_CLK>;
status = "disabled";
};
@@ -181,6 +191,7 @@
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
+ resets = <&rst BM1880_RST_UART2_3_ACLK>;
status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index c043aca66572..93fce8f0c66d 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -8,6 +8,7 @@ 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-ls1046a-frwy.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-qds.dtb
@@ -21,8 +22,13 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mn-ddr4-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-nitrogen.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8qxp-ai_ml.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index ec6257a5b251..124a7e2d8442 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -323,7 +323,7 @@
#size-cells = <0>;
reg = <0x0 0x2180000 0x0 0x10000>;
interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 0>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -333,7 +333,7 @@
#size-cells = <0>;
reg = <0x0 0x2190000 0x0 0x10000>;
interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 0>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
index de6ef39f3118..5e14e5a19744 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
@@ -95,6 +95,14 @@
status = "okay";
};
+&esdhc {
+ status = "okay";
+};
+
+&esdhc1 {
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
index 9fb911317ecd..1a69221d9a1b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
@@ -83,6 +83,19 @@
};
};
+&esdhc {
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
+ status = "okay";
+};
+
+&esdhc1 {
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index 7975519b4f56..b139b29cef87 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -29,6 +29,7 @@
clocks = <&clockgen 1 0>;
next-level-cache = <&l2>;
cpu-idle-states = <&CPU_PW20>;
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -39,6 +40,7 @@
clocks = <&clockgen 1 0>;
next-level-cache = <&l2>;
cpu-idle-states = <&CPU_PW20>;
+ #cooling-cells = <2>;
};
l2: l2-cache {
@@ -70,11 +72,18 @@
clock-output-names = "sysclk";
};
- dpclk: clock-dp {
+ osc_27m: clock-osc-27m {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <27000000>;
- clock-output-names= "dpclk";
+ clock-output-names = "phy_27m";
+ };
+
+ dpclk: clock-controller@f1f0000 {
+ compatible = "fsl,ls1028a-plldig";
+ reg = <0x0 0xf1f0000 0x0 0xffff>;
+ #clock-cells = <1>;
+ clocks = <&osc_27m>;
};
aclk: clock-axi {
@@ -171,7 +180,7 @@
#size-cells = <0>;
reg = <0x0 0x2000000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -181,7 +190,7 @@
#size-cells = <0>;
reg = <0x0 0x2010000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -191,7 +200,7 @@
#size-cells = <0>;
reg = <0x0 0x2020000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -201,7 +210,7 @@
#size-cells = <0>;
reg = <0x0 0x2030000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -211,7 +220,7 @@
#size-cells = <0>;
reg = <0x0 0x2040000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -221,7 +230,7 @@
#size-cells = <0>;
reg = <0x0 0x2050000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -231,7 +240,7 @@
#size-cells = <0>;
reg = <0x0 0x2060000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
status = "disabled";
};
@@ -241,7 +250,34 @@
#size-cells = <0>;
reg = <0x0 0x2070000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 1>;
+ clocks = <&clockgen 4 3>;
+ status = "disabled";
+ };
+
+ esdhc: mmc@2140000 {
+ compatible = "fsl,ls1028a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x2140000 0x0 0x10000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>; /* fixed up by bootloader */
+ clocks = <&clockgen 2 1>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ little-endian;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ esdhc1: mmc@2150000 {
+ compatible = "fsl,ls1028a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x2150000 0x0 0x10000>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>; /* fixed up by bootloader */
+ clocks = <&clockgen 2 1>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ broken-cd;
+ little-endian;
+ bus-width = <4>;
status = "disabled";
};
@@ -277,33 +313,36 @@
};
gpio1: gpio@2300000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ little-endian;
};
gpio2: gpio@2310000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ little-endian;
};
gpio3: gpio@2320000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ little-endian;
};
usb0: usb@3100000 {
@@ -503,6 +542,89 @@
status = "disabled";
};
+ tmu: tmu@1f00000 {
+ compatible = "fsl,qoriq-tmu";
+ reg = <0x0 0x1f80000 0x0 0x10000>;
+ interrupts = <0 23 0x4>;
+ fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
+ fsl,tmu-calibration = <0x00000000 0x00000024
+ 0x00000001 0x0000002b
+ 0x00000002 0x00000031
+ 0x00000003 0x00000038
+ 0x00000004 0x0000003f
+ 0x00000005 0x00000045
+ 0x00000006 0x0000004c
+ 0x00000007 0x00000053
+ 0x00000008 0x00000059
+ 0x00000009 0x00000060
+ 0x0000000a 0x00000066
+ 0x0000000b 0x0000006d
+
+ 0x00010000 0x0000001c
+ 0x00010001 0x00000024
+ 0x00010002 0x0000002c
+ 0x00010003 0x00000035
+ 0x00010004 0x0000003d
+ 0x00010005 0x00000045
+ 0x00010006 0x0000004d
+ 0x00010007 0x00000045
+ 0x00010008 0x0000005e
+ 0x00010009 0x00000066
+ 0x0001000a 0x0000006e
+
+ 0x00020000 0x00000018
+ 0x00020001 0x00000022
+ 0x00020002 0x0000002d
+ 0x00020003 0x00000038
+ 0x00020004 0x00000043
+ 0x00020005 0x0000004d
+ 0x00020006 0x00000058
+ 0x00020007 0x00000063
+ 0x00020008 0x0000006e
+
+ 0x00030000 0x00000010
+ 0x00030001 0x0000001c
+ 0x00030002 0x00000029
+ 0x00030003 0x00000036
+ 0x00030004 0x00000042
+ 0x00030005 0x0000004f
+ 0x00030006 0x0000005b
+ 0x00030007 0x00000068>;
+ little-endian;
+ #thermal-sensor-cells = <1>;
+ };
+
+ thermal-zones {
+ core-cluster {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+ thermal-sensors = <&tmu 0>;
+
+ trips {
+ core_cluster_alert: core-cluster-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ core_cluster_crit: core-cluster-crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&core_cluster_alert>;
+ cooling-device =
+ <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
pcie@1f0000000 { /* Integrated Endpoint Root Complex */
compatible = "pci-host-ecam-generic";
reg = <0x01 0xf0000000 0x0 0x100000>;
@@ -551,9 +673,10 @@
interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
<0 223 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "DE", "SE";
- clocks = <&dpclk>, <&aclk>, <&aclk>, <&pclk>;
+ clocks = <&dpclk 0>, <&aclk>, <&aclk>, <&pclk>;
clock-names = "pxlclk", "mclk", "aclk", "pclk";
arm,malidp-output-port-lines = /bits/ 8 <8 8 8>;
+ arm,malidp-arqos-value = <0xd000d000>;
port {
dp0_out: endpoint {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
new file mode 100644
index 000000000000..3595be0f2527
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree Include file for Freescale Layerscape-1046A family SoC.
+ *
+ * Copyright 2019 NXP.
+ *
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1046a.dtsi"
+
+/ {
+ model = "LS1046A FRWY Board";
+ compatible = "fsl,ls1046a-frwy", "fsl,ls1046a";
+
+ aliases {
+ serial0 = &duart0;
+ serial1 = &duart1;
+ serial2 = &duart2;
+ serial3 = &duart3;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ sb_3v3: regulator-sb3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "LT8642SEV-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&duart0 {
+ status = "okay";
+};
+
+&duart1 {
+ status = "okay";
+};
+
+&duart2 {
+ status = "okay";
+};
+
+&duart3 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9546";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ power-monitor@40 {
+ compatible = "ti,ina220";
+ reg = <0x40>;
+ shunt-resistor = <1000>;
+ };
+
+ temperature-sensor@4c {
+ compatible = "nxp,sa56004";
+ reg = <0x4c>;
+ vcc-supply = <&sb_3v3>;
+ };
+
+ rtc@51 {
+ compatible = "nxp,pcf2129";
+ reg = <0x51>;
+ };
+
+ eeprom@52 {
+ compatible = "atmel,24c512";
+ reg = <0x52>;
+ };
+
+ eeprom@53 {
+ compatible = "atmel,24c512";
+ reg = <0x53>;
+ };
+
+ };
+ };
+};
+
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ /* NAND Flash */
+ ranges = <0x0 0x0 0x0 0x7e800000 0x00010000>;
+ status = "okay";
+
+ nand@0,0 {
+ compatible = "fsl,ifc-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x0 0x0 0x10000>;
+ };
+
+};
+
+#include "fsl-ls1046-post.dtsi"
+
+&fman0 {
+ ethernet@e0000 {
+ phy-handle = <&qsgmii_phy4>;
+ phy-connection-type = "qsgmii";
+ };
+
+ ethernet@e8000 {
+ phy-handle = <&qsgmii_phy2>;
+ phy-connection-type = "qsgmii";
+ };
+
+ ethernet@ea000 {
+ phy-handle = <&qsgmii_phy1>;
+ phy-connection-type = "qsgmii";
+ };
+
+ ethernet@f2000 {
+ phy-handle = <&qsgmii_phy3>;
+ phy-connection-type = "qsgmii";
+ };
+
+ mdio@fd000 {
+ qsgmii_phy1: ethernet-phy@1c {
+ reg = <0x1c>;
+ };
+
+ qsgmii_phy2: ethernet-phy@1d {
+ reg = <0x1d>;
+ };
+
+ qsgmii_phy3: ethernet-phy@1e {
+ reg = <0x1e>;
+ };
+
+ qsgmii_phy4: ethernet-phy@1f {
+ reg = <0x1f>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 6f48d21b97c0..120e62dad154 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -17,6 +17,39 @@
compatible = "fsl,ls1088a-qds", "fsl,ls1088a";
};
+&dspi {
+ bus-num = <0>;
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+
+ flash@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-cpol;
+ spi-cpha;
+ spi-max-frequency = <3500000>;
+ reg = <1>;
+ };
+
+ flash@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-cpol;
+ spi-cpha;
+ spi-max-frequency = <3500000>;
+ reg = <2>;
+ };
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index dacd8cf03a7f..d1469b0747c7 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -252,6 +252,19 @@
#thermal-sensor-cells = <1>;
};
+ dspi: spi@2100000 {
+ compatible = "fsl,ls1088a-dspi",
+ "fsl,ls1021a-v1.0-dspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2100000 0x0 0x10000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dspi";
+ clocks = <&clockgen 4 1>;
+ spi-num-chipselects = <6>;
+ status = "disabled";
+ };
+
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21c0500 0x0 0x100>;
@@ -269,9 +282,10 @@
};
gpio0: gpio@2300000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+ little-endian;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -279,9 +293,10 @@
};
gpio1: gpio@2310000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+ little-endian;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -289,9 +304,10 @@
};
gpio2: gpio@2320000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+ little-endian;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -299,9 +315,10 @@
};
gpio3: gpio@2330000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+ little-endian;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -324,7 +341,7 @@
#size-cells = <0>;
reg = <0x0 0x2000000 0x0 0x10000>;
interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 3>;
+ clocks = <&clockgen 4 7>;
status = "disabled";
};
@@ -334,7 +351,7 @@
#size-cells = <0>;
reg = <0x0 0x2010000 0x0 0x10000>;
interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 3>;
+ clocks = <&clockgen 4 7>;
status = "disabled";
};
@@ -344,7 +361,7 @@
#size-cells = <0>;
reg = <0x0 0x2020000 0x0 0x10000>;
interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 3>;
+ clocks = <&clockgen 4 7>;
status = "disabled";
};
@@ -354,7 +371,7 @@
#size-cells = <0>;
reg = <0x0 0x2030000 0x0 0x10000>;
interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clockgen 4 3>;
+ clocks = <&clockgen 4 7>;
status = "disabled";
};
@@ -609,6 +626,11 @@
<GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
};
+ console@8340020 {
+ compatible = "fsl,dpaa2-console";
+ reg = <0x00000000 0x08340020 0 0x2>;
+ };
+
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
index 3ace91945b72..64101c9962ce 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -321,6 +321,11 @@
};
};
+ console@8340020 {
+ compatible = "fsl,dpaa2-console";
+ reg = <0x00000000 0x08340020 0 0x2>;
+ };
+
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index e6fdba39453c..408e0ecdce6a 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -485,7 +485,7 @@
reg = <0x0 0x2000000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
scl-gpio = <&gpio2 15 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
@@ -497,7 +497,7 @@
reg = <0x0 0x2010000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -508,7 +508,7 @@
reg = <0x0 0x2020000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -519,7 +519,7 @@
reg = <0x0 0x2030000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -530,7 +530,7 @@
reg = <0x0 0x2040000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
scl-gpio = <&gpio2 16 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
@@ -542,7 +542,7 @@
reg = <0x0 0x2050000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -553,7 +553,7 @@
reg = <0x0 0x2060000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -564,7 +564,7 @@
reg = <0x0 0x2070000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
- clocks = <&clockgen 4 7>;
+ clocks = <&clockgen 4 15>;
status = "disabled";
};
@@ -848,6 +848,11 @@
dma-coherent;
};
+ console@8340020 {
+ compatible = "fsl,dpaa2-console";
+ reg = <0x00000000 0x08340020 0 0x2>;
+ };
+
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
index ee7f2b2fc1ff..f7a15f3904c2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include <dt-bindings/usb/pd.h>
#include "imx8mm.dtsi"
/ {
@@ -89,9 +90,6 @@
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
- at803x,led-act-blind-workaround;
- at803x,eee-okay;
- at803x,vddio-1p8v;
};
};
};
@@ -115,6 +113,21 @@
status = "okay";
};
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&typec1_dr_sw>;
+ };
+ };
+};
+
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
@@ -257,6 +270,42 @@
};
};
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ ptn5110: tcpc@50 {
+ compatible = "nxp,ptn5110";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_typec1>;
+ reg = <0x50>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <11 8>;
+ status = "okay";
+
+ port {
+ typec1_dr_sw: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+
+ typec1_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ power-role = "dual";
+ data-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
+ PDO_VAR(5000, 20000, 3000)>;
+ op-sink-microwatt = <15000000>;
+ self-powered;
+ };
+ };
+};
+
&iomuxc {
pinctrl-names = "default";
@@ -299,6 +348,13 @@
>;
};
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
pinctrl_pmic: pmicirq {
fsl,pins = <
MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
@@ -320,6 +376,12 @@
>;
};
+ pinctrl_typec1: typec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_STROBE_GPIO2_IO11 0x159
+ >;
+ };
+
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
index e25f7fcd7997..cffa8991880d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
+++ b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
@@ -462,7 +462,7 @@
#define MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x1CC 0x434 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_RXFS_TPSMP_HTRANS0 0x1CC 0x434 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_RXC_SAI3_RX_BCLK 0x1D0 0x438 0x000 0x0 0x0
-#define MX8MM_IOMUXC_SAI3_RXC_GPT1_CAPTURE2 0x1D0 0x438 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI3_RXC_GPT1_CLK 0x1D0 0x438 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_RXC_SAI5_RX_BCLK 0x1D0 0x438 0x4D0 0x2 0x2
#define MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x1D0 0x438 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_RXC_TPSMP_HTRANS1 0x1D0 0x438 0x000 0x7 0x0
@@ -472,7 +472,7 @@
#define MX8MM_IOMUXC_SAI3_RXD_GPIO4_IO30 0x1D4 0x43C 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_RXD_TPSMP_HDATA0 0x1D4 0x43C 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0x1D8 0x440 0x000 0x0 0x0
-#define MX8MM_IOMUXC_SAI3_TXFS_GPT1_CLK 0x1D8 0x440 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI3_TXFS_GPT1_CAPTURE2 0x1D8 0x440 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_SAI5_RX_DATA1 0x1D8 0x440 0x4D8 0x2 0x2
#define MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31 0x1D8 0x440 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_TPSMP_HDATA1 0x1D8 0x440 0x000 0x7 0x0
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 89ef22a8f81e..5f9d0da196e1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -44,6 +44,19 @@
#address-cells = <1>;
#size-cells = <0>;
+ idle-states {
+ entry-method = "psci";
+
+ cpu_pd_wait: cpu-pd-wait {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010033>;
+ local-timer-stop;
+ entry-latency-us = <1000>;
+ exit-latency-us = <700>;
+ min-residency-us = <2700>;
+ };
+ };
+
A53_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
@@ -55,6 +68,7 @@
operating-points-v2 = <&a53_opp_table>;
nvmem-cells = <&cpu_speed_grade>;
nvmem-cell-names = "speed_grade";
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_1: cpu@1 {
@@ -66,6 +80,7 @@
enable-method = "psci";
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_2: cpu@2 {
@@ -77,6 +92,7 @@
enable-method = "psci";
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_3: cpu@3 {
@@ -88,6 +104,7 @@
enable-method = "psci";
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_L2: l2-cache0 {
@@ -104,6 +121,7 @@
opp-microvolt = <850000>;
opp-supported-hw = <0xe>, <0x7>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
opp-1600000000 {
@@ -111,14 +129,15 @@
opp-microvolt = <900000>;
opp-supported-hw = <0xc>, <0x7>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
opp-1800000000 {
opp-hz = /bits/ 64 <1800000000>;
opp-microvolt = <1000000>;
- /* Consumer only but rely on speed grading */
- opp-supported-hw = <0x8>, <0x7>;
+ opp-supported-hw = <0x8>, <0x3>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
};
@@ -295,6 +314,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 10 30>;
};
gpio2: gpio@30210000 {
@@ -307,6 +327,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 40 21>;
};
gpio3: gpio@30220000 {
@@ -319,6 +340,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 61 26>;
};
gpio4: gpio@30230000 {
@@ -331,6 +353,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 87 32>;
};
gpio5: gpio@30240000 {
@@ -343,6 +366,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 119 30>;
};
wdog1: watchdog@30280000 {
@@ -451,10 +475,22 @@
<&clk_ext3>, <&clk_ext4>;
clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
"clk_ext3", "clk_ext4";
+ assigned-clocks = <&clk IMX8MM_CLK_NOC>,
+ <&clk IMX8MM_CLK_AUDIO_AHB>,
+ <&clk IMX8MM_CLK_IPG_AUDIO_ROOT>,
+ <&clk IMX8MM_SYS_PLL3>,
+ <&clk IMX8MM_VIDEO_PLL1>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL3_OUT>,
+ <&clk IMX8MM_SYS_PLL1_800M>;
+ assigned-clock-rates = <0>,
+ <400000000>,
+ <400000000>,
+ <750000000>,
+ <594000000>;
};
src: reset-controller@30390000 {
- compatible = "fsl,imx8mm-src", "syscon";
+ compatible = "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon";
reg = <0x30390000 0x10000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
@@ -751,10 +787,8 @@
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
clock-names = "usb1_ctrl_root_clk";
- assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>,
- <&clk IMX8MM_CLK_USB_CORE_REF>;
- assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>,
- <&clk IMX8MM_SYS_PLL1_100M>;
+ assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
fsl,usbphy = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
status = "disabled";
@@ -772,10 +806,8 @@
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
clock-names = "usb1_ctrl_root_clk";
- assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>,
- <&clk IMX8MM_CLK_USB_CORE_REF>;
- assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>,
- <&clk IMX8MM_SYS_PLL1_100M>;
+ assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
fsl,usbphy = <&usbphynop2>;
fsl,usbmisc = <&usbmisc2 0>;
status = "disabled";
@@ -826,5 +858,12 @@
interrupt-controller;
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ ddr-pmu@3d800000 {
+ compatible = "fsl,imx8mm-ddr-pmu", "fsl,imx8m-ddr-pmu";
+ reg = <0x3d800000 0x400000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
new file mode 100644
index 000000000000..11c705d225d0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2019 NXP
+ */
+
+/dts-v1/;
+
+#include "imx8mn.dtsi"
+
+/ {
+ model = "NXP i.MX8MNano DDR4 EVK board";
+ compatible = "fsl,imx8mn-ddr4-evk", "fsl,imx8mn";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MN_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MN_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MN_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MN_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MN_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MN_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MN_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MN_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MN_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MN_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MN_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MN_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_pmic: pmicirq {
+ fsl,pins = <
+ MX8MN_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MN_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MN_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x1c4
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MN_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MN_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MN_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MN_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MN_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ MX8MN_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MN_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MN_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MN_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MN_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MN_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ MX8MN_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MN_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MN_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MN_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MN_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MN_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ MX8MN_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000190
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000194
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000196
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ at803x,led-act-blind-workaround;
+ at803x,eee-disabled;
+ at803x,vddio-1p8v;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic@4b {
+ compatible = "rohm,bd71847";
+ reg = <0x4b>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 GPIO_ACTIVE_LOW>;
+ rohm,reset-snvs-powered;
+
+ regulators {
+ buck1_reg: BUCK1 {
+ regulator-name = "BUCK1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "BUCK2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck3_reg: BUCK3 {
+ // BUCK5 in datasheet
+ regulator-name = "BUCK3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ buck4_reg: BUCK4 {
+ // BUCK6 in datasheet
+ regulator-name = "BUCK4";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5_reg: BUCK5 {
+ // BUCK7 in datasheet
+ regulator-name = "BUCK5";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6_reg: BUCK6 {
+ // BUCK8 in datasheet
+ regulator-name = "BUCK6";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "LDO3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "LDO4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "LDO6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+&uart2 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usdhc2 {
+ 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>;
+ cd-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ 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 = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
new file mode 100644
index 000000000000..785f4c420fa4
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <dt-bindings/clock/imx8mn-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "imx8mn-pinfunc.h"
+
+/ {
+ compatible = "fsl,imx8mn";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ ethernet0 = &fec1;
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ i2c0 = &i2c1;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ i2c3 = &i2c4;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ A53_0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ clock-latency = <61036>;
+ clocks = <&clk IMX8MN_CLK_ARM>;
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ operating-points-v2 = <&a53_opp_table>;
+ nvmem-cells = <&cpu_speed_grade>;
+ nvmem-cell-names = "speed_grade";
+ };
+
+ A53_1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ clock-latency = <61036>;
+ clocks = <&clk IMX8MN_CLK_ARM>;
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ operating-points-v2 = <&a53_opp_table>;
+ };
+
+ A53_2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x2>;
+ clock-latency = <61036>;
+ clocks = <&clk IMX8MN_CLK_ARM>;
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ operating-points-v2 = <&a53_opp_table>;
+ };
+
+ A53_3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
+ clock-latency = <61036>;
+ clocks = <&clk IMX8MN_CLK_ARM>;
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ operating-points-v2 = <&a53_opp_table>;
+ };
+
+ A53_L2: l2-cache0 {
+ compatible = "cache";
+ };
+ };
+
+ a53_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <850000>;
+ opp-supported-hw = <0xb00>, <0x7>;
+ clock-latency-ns = <150000>;
+ opp-suspend;
+ };
+
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt = <950000>;
+ opp-supported-hw = <0x300>, <0x7>;
+ clock-latency-ns = <150000>;
+ opp-suspend;
+ };
+
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1000000>;
+ opp-supported-hw = <0x100>, <0x3>;
+ clock-latency-ns = <150000>;
+ opp-suspend;
+ };
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x0 0x40000000 0 0x80000000>;
+ };
+
+ osc_32k: clock-osc-32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "osc_32k";
+ };
+
+ osc_24m: clock-osc-24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_24m";
+ };
+
+ clk_ext1: clock-ext1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext1";
+ };
+
+ clk_ext2: clock-ext2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext2";
+ };
+
+ clk_ext3: clock-ext3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext3";
+ };
+
+ clk_ext4: clock-ext4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <133000000>;
+ clock-output-names = "clk_ext4";
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <8000000>;
+ arm,no-tick-in-suspend;
+ };
+
+ soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x0 0x3e000000>;
+
+ aips1: bus@30000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x30000000 0x400000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ gpio1: gpio@30200000 {
+ compatible = "fsl,imx8mn-gpio", "fsl,imx35-gpio";
+ reg = <0x30200000 0x10000>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_GPIO1_ROOT>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 10 30>;
+ };
+
+ gpio2: gpio@30210000 {
+ compatible = "fsl,imx8mn-gpio", "fsl,imx35-gpio";
+ reg = <0x30210000 0x10000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_GPIO2_ROOT>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 40 21>;
+ };
+
+ gpio3: gpio@30220000 {
+ compatible = "fsl,imx8mn-gpio", "fsl,imx35-gpio";
+ reg = <0x30220000 0x10000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_GPIO3_ROOT>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 61 26>;
+ };
+
+ gpio4: gpio@30230000 {
+ compatible = "fsl,imx8mn-gpio", "fsl,imx35-gpio";
+ reg = <0x30230000 0x10000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_GPIO4_ROOT>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 21 108 11>;
+ };
+
+ gpio5: gpio@30240000 {
+ compatible = "fsl,imx8mn-gpio", "fsl,imx35-gpio";
+ reg = <0x30240000 0x10000>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_GPIO5_ROOT>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 119 30>;
+ };
+
+ wdog1: watchdog@30280000 {
+ compatible = "fsl,imx8mn-wdt", "fsl,imx21-wdt";
+ reg = <0x30280000 0x10000>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_WDOG1_ROOT>;
+ status = "disabled";
+ };
+
+ wdog2: watchdog@30290000 {
+ compatible = "fsl,imx8mn-wdt", "fsl,imx21-wdt";
+ reg = <0x30290000 0x10000>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_WDOG2_ROOT>;
+ status = "disabled";
+ };
+
+ wdog3: watchdog@302a0000 {
+ compatible = "fsl,imx8mn-wdt", "fsl,imx21-wdt";
+ reg = <0x302a0000 0x10000>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_WDOG3_ROOT>;
+ status = "disabled";
+ };
+
+ sdma3: dma-controller@302b0000 {
+ compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+ reg = <0x302b0000 0x10000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SDMA3_ROOT>,
+ <&clk IMX8MN_CLK_SDMA3_ROOT>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+ };
+
+ sdma2: dma-controller@302c0000 {
+ compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+ reg = <0x302c0000 0x10000>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SDMA2_ROOT>,
+ <&clk IMX8MN_CLK_SDMA2_ROOT>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+ };
+
+ iomuxc: pinctrl@30330000 {
+ compatible = "fsl,imx8mn-iomuxc";
+ reg = <0x30330000 0x10000>;
+ };
+
+ gpr: iomuxc-gpr@30340000 {
+ compatible = "fsl,imx8mn-iomuxc-gpr", "syscon";
+ reg = <0x30340000 0x10000>;
+ };
+
+ ocotp: ocotp-ctrl@30350000 {
+ compatible = "fsl,imx8mn-ocotp", "fsl,imx7d-ocotp", "syscon";
+ reg = <0x30350000 0x10000>;
+ clocks = <&clk IMX8MN_CLK_OCOTP_ROOT>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpu_speed_grade: speed-grade@10 {
+ reg = <0x10 4>;
+ };
+ };
+
+ anatop: anatop@30360000 {
+ compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop",
+ "syscon", "simple-bus";
+ reg = <0x30360000 0x10000>;
+ };
+
+ snvs: snvs@30370000 {
+ compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd";
+ reg = <0x30370000 0x10000>;
+
+ snvs_rtc: snvs-rtc-lp {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ regmap = <&snvs>;
+ offset = <0x34>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "snvs-rtc";
+ };
+
+ snvs_pwrkey: snvs-powerkey {
+ compatible = "fsl,sec-v4.0-pwrkey";
+ regmap = <&snvs>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ linux,keycode = <KEY_POWER>;
+ wakeup-source;
+ status = "disabled";
+ };
+ };
+
+ clk: clock-controller@30380000 {
+ compatible = "fsl,imx8mn-ccm";
+ reg = <0x30380000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
+ <&clk_ext3>, <&clk_ext4>;
+ clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
+ "clk_ext3", "clk_ext4";
+ };
+
+ src: reset-controller@30390000 {
+ compatible = "fsl,imx8mn-src", "syscon";
+ reg = <0x30390000 0x10000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+ };
+
+ aips2: bus@30400000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x30400000 0x400000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pwm1: pwm@30660000 {
+ compatible = "fsl,imx8mn-pwm", "fsl,imx27-pwm";
+ reg = <0x30660000 0x10000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_PWM1_ROOT>,
+ <&clk IMX8MN_CLK_PWM1_ROOT>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@30670000 {
+ compatible = "fsl,imx8mn-pwm", "fsl,imx27-pwm";
+ reg = <0x30670000 0x10000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_PWM2_ROOT>,
+ <&clk IMX8MN_CLK_PWM2_ROOT>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@30680000 {
+ compatible = "fsl,imx8mn-pwm", "fsl,imx27-pwm";
+ reg = <0x30680000 0x10000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_PWM3_ROOT>,
+ <&clk IMX8MN_CLK_PWM3_ROOT>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@30690000 {
+ compatible = "fsl,imx8mn-pwm", "fsl,imx27-pwm";
+ reg = <0x30690000 0x10000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_PWM4_ROOT>,
+ <&clk IMX8MN_CLK_PWM4_ROOT>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+ };
+
+ aips3: bus@30800000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x30800000 0x400000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ ecspi1: spi@30820000 {
+ compatible = "fsl,imx8mn-ecspi", "fsl,imx51-ecspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30820000 0x10000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_ECSPI1_ROOT>,
+ <&clk IMX8MN_CLK_ECSPI1_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ ecspi2: spi@30830000 {
+ compatible = "fsl,imx8mn-ecspi", "fsl,imx51-ecspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30830000 0x10000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_ECSPI2_ROOT>,
+ <&clk IMX8MN_CLK_ECSPI2_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ ecspi3: spi@30840000 {
+ compatible = "fsl,imx8mn-ecspi", "fsl,imx51-ecspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30840000 0x10000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_ECSPI3_ROOT>,
+ <&clk IMX8MN_CLK_ECSPI3_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@30860000 {
+ compatible = "fsl,imx8mn-uart", "fsl,imx6q-uart";
+ reg = <0x30860000 0x10000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_UART1_ROOT>,
+ <&clk IMX8MN_CLK_UART1_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@30880000 {
+ compatible = "fsl,imx8mn-uart", "fsl,imx6q-uart";
+ reg = <0x30880000 0x10000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_UART3_ROOT>,
+ <&clk IMX8MN_CLK_UART3_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart2: serial@30890000 {
+ compatible = "fsl,imx8mn-uart", "fsl,imx6q-uart";
+ reg = <0x30890000 0x10000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_UART2_ROOT>,
+ <&clk IMX8MN_CLK_UART2_ROOT>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ i2c1: i2c@30a20000 {
+ compatible = "fsl,imx8mn-i2c", "fsl,imx21-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30a20000 0x10000>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_I2C1_ROOT>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@30a30000 {
+ compatible = "fsl,imx8mn-i2c", "fsl,imx21-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30a30000 0x10000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_I2C2_ROOT>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@30a40000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx8mn-i2c", "fsl,imx21-i2c";
+ reg = <0x30a40000 0x10000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_I2C3_ROOT>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@30a50000 {
+ compatible = "fsl,imx8mn-i2c", "fsl,imx21-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x30a50000 0x10000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_I2C4_ROOT>;
+ status = "disabled";
+ };
+
+ uart4: serial@30a60000 {
+ compatible = "fsl,imx8mn-uart", "fsl,imx6q-uart";
+ reg = <0x30a60000 0x10000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_UART4_ROOT>,
+ <&clk IMX8MN_CLK_UART4_ROOT>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma1 28 4 0>, <&sdma1 29 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ usdhc1: mmc@30b40000 {
+ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x30b40000 0x10000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_DUMMY>,
+ <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
+ <&clk IMX8MN_CLK_USDHC1_ROOT>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&clk IMX8MN_CLK_USDHC1>;
+ assigned-clock-rates = <400000000>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usdhc2: mmc@30b50000 {
+ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x30b50000 0x10000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_DUMMY>,
+ <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
+ <&clk IMX8MN_CLK_USDHC2_ROOT>;
+ clock-names = "ipg", "ahb", "per";
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usdhc3: mmc@30b60000 {
+ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x30b60000 0x10000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_DUMMY>,
+ <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
+ <&clk IMX8MN_CLK_USDHC3_ROOT>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&clk IMX8MN_CLK_USDHC3_ROOT>;
+ assigned-clock-rates = <400000000>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ sdma1: dma-controller@30bd0000 {
+ compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+ reg = <0x30bd0000 0x10000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SDMA1_ROOT>,
+ <&clk IMX8MN_CLK_SDMA1_ROOT>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+ };
+
+ fec1: ethernet@30be0000 {
+ compatible = "fsl,imx8mn-fec", "fsl,imx6sx-fec";
+ reg = <0x30be0000 0x10000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_ENET1_ROOT>,
+ <&clk IMX8MN_CLK_ENET1_ROOT>,
+ <&clk IMX8MN_CLK_ENET_TIMER>,
+ <&clk IMX8MN_CLK_ENET_REF>,
+ <&clk IMX8MN_CLK_ENET_PHY_REF>;
+ clock-names = "ipg", "ahb", "ptp",
+ "enet_clk_ref", "enet_out";
+ assigned-clocks = <&clk IMX8MN_CLK_ENET_AXI>,
+ <&clk IMX8MN_CLK_ENET_TIMER>,
+ <&clk IMX8MN_CLK_ENET_REF>,
+ <&clk IMX8MN_CLK_ENET_TIMER>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
+ <&clk IMX8MN_SYS_PLL2_100M>,
+ <&clk IMX8MN_SYS_PLL2_125M>;
+ assigned-clock-rates = <0>, <0>, <125000000>, <100000000>;
+ fsl,num-tx-queues = <3>;
+ fsl,num-rx-queues = <3>;
+ status = "disabled";
+ };
+
+ };
+
+ aips4: bus@32c00000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x32c00000 0x400000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ usbotg1: usb@32e40000 {
+ compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb";
+ reg = <0x32e40000 0x200>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_USB1_CTRL_ROOT>;
+ clock-names = "usb1_ctrl_root_clk";
+ assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>,
+ <&clk IMX8MN_CLK_USB_CORE_REF>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>,
+ <&clk IMX8MN_SYS_PLL1_100M>;
+ fsl,usbphy = <&usbphynop1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+ status = "disabled";
+ };
+
+ usbmisc1: usbmisc@32e40200 {
+ compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc";
+ #index-cells = <1>;
+ reg = <0x32e40200 0x200>;
+ };
+
+ usbotg2: usb@32e50000 {
+ compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb";
+ reg = <0x32e50000 0x200>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_USB1_CTRL_ROOT>;
+ clock-names = "usb1_ctrl_root_clk";
+ assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>,
+ <&clk IMX8MN_CLK_USB_CORE_REF>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>,
+ <&clk IMX8MN_SYS_PLL1_100M>;
+ fsl,usbphy = <&usbphynop2>;
+ fsl,usbmisc = <&usbmisc2 0>;
+ status = "disabled";
+ };
+
+ usbmisc2: usbmisc@32e50200 {
+ compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc";
+ #index-cells = <1>;
+ reg = <0x32e50200 0x200>;
+ };
+
+ };
+
+ dma_apbh: dma-controller@33000000 {
+ compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh";
+ reg = <0x33000000 0x2000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&clk IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK>;
+ };
+
+ gpmi: nand-controller@33002000 {
+ compatible = "fsl,imx8mn-gpmi-nand", "fsl,imx7d-gpmi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
+ reg-names = "gpmi-nand", "bch";
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bch";
+ clocks = <&clk IMX8MN_CLK_NAND_ROOT>,
+ <&clk IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK>;
+ clock-names = "gpmi_io", "gpmi_bch_apb";
+ dmas = <&dma_apbh 0>;
+ dma-names = "rx-tx";
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@38800000 {
+ compatible = "arm,gic-v3";
+ reg = <0x38800000 0x10000>,
+ <0x38880000 0xc0000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ usbphynop1: usbphynop1 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
+ assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
+ clock-names = "main_clk";
+ };
+
+ usbphynop2: usbphynop2 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
+ assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
+ clock-names = "main_clk";
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index e3df9b8cd9ca..05958124f173 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -118,9 +118,9 @@
&sai2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2>;
- assigned-clocks = <&clk IMX8MQ_CLK_SAI2>;
- assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>;
- assigned-clock-rates = <24576000>;
+ assigned-clocks = <&clk IMX8MQ_AUDIO_PLL1_BYPASS>, <&clk IMX8MQ_CLK_SAI2>;
+ assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1>, <&clk IMX8MQ_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <0>, <24576000>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts b/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts
new file mode 100644
index 000000000000..f52e872ac96f
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2018 Jon Nettleton <jon@solid-run.com>
+ */
+
+/dts-v1/;
+
+#include "dt-bindings/usb/pd.h"
+#include "imx8mq-sr-som.dtsi"
+
+/ {
+ model = "SolidRun i.MX8MQ HummingBoard Pulse";
+ compatible = "solidrun,hummingboard-pulse", "fsl,imx8mq";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_vmmc>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 13 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_v_5v0: regulator-v-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "v_5v0";
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-always-on;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ typec_ptn5100: usb-typec@50 {
+ compatible = "nxp,ptn5110";
+ reg = <0x50>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_typec>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 2000,
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_SUSPEND |
+ PDO_FIXED_EXTPOWER)>;
+ sink-pdos = <PDO_FIXED(5000, 2000,
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_SUSPEND |
+ PDO_FIXED_EXTPOWER)
+ PDO_FIXED(9000, 2000,
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_SUSPEND |
+ PDO_FIXED_EXTPOWER)>;
+ op-sink-microwatt = <9000000>;
+
+ port {
+ typec1_dr_sw: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+ };
+ };
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ rtc@69 {
+ compatible = "abracon,ab1805";
+ reg = <0x69>;
+ abracon,tc-diode = "schottky";
+ abracon,tc-resistor = <3>;
+ };
+};
+
+&uart2 { /* J35 header */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+ status = "okay";
+};
+
+&uart3 { /* Mikrobus */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART3>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usdhc2 {
+ 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>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ dr_mode = "otg";
+ status = "okay";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&typec1_dr_sw>;
+ };
+ };
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* MikroBus Analog */
+ MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x41
+ /* MikroBus Reset */
+ MX8MQ_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x41
+ /*
+ * The following 2 pins need to be commented out and
+ * reconfigured to enable RTS/CTS on UART3
+ */
+ /* MikroBus PWM */
+ MX8MQ_IOMUXC_ECSPI1_MISO_GPIO5_IO8 0x41
+ /* MikroBus INT */
+ MX8MQ_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x41
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_typec: typecgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_RE_B_GPIO3_IO15 0x16
+ MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x17059
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART3_TXD_UART3_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART3_RXD_UART3_DCE_RX 0x49
+ /*
+ * These pins are by default GPIO on the Mikro Bus
+ * Header. To use RTS/CTS on UART3 comment them out
+ * of the hoggrp and enable them here
+ */
+ /* MX8MQ_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x49 */
+ /* MX8MQ_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x49 */
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ >;
+ };
+
+ pinctrl_usdhc2_vmmc: usdhc2vmmcgpio {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x41
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x8d
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xcd
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xcd
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xcd
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xcd
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xcd
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x9f
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xdf
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xdf
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xdf
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xdf
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xdf
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
index 5179e22f5126..683a11035643 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
@@ -174,6 +174,10 @@
assigned-clock-rates = <786432000>, <722534400>;
};
+&dphy {
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
new file mode 100644
index 000000000000..c832bf0fcc60
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Boundary Devices
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx8mq.dtsi"
+
+/ {
+ model = "Boundary Devices i.MX8MQ Nitrogen8M";
+ compatible = "boundary,imx8mq-nitrogen8m", "fsl,imx8mq";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000 0 0x80000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ reg_vref_0v9: regulator-vref-0v9 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-0v9";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ };
+
+ reg_vref_1v8: regulator-vref-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_vref_2v5: regulator-vref-2v5 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-2v5";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ };
+
+ reg_vref_3v3: regulator-vref-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_vref_5v: regulator-vref-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <4>;
+ interrupts-extended = <&gpio1 11 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ i2cmux@70 {
+ compatible = "nxp,pca9546";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_pca9546>;
+ reg = <0x70>;
+ reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c1a: i2c1@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_arm_dram: regulator@60 {
+ compatible = "fcs,fan53555";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_arm_dram>;
+ reg = <0x60>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ vsel-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ i2c1b: i2c1@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_dram_1p1v: regulator@60 {
+ compatible = "fcs,fan53555";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_dram_1p1v>;
+ reg = <0x60>;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ vsel-gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ i2c1c: i2c1@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_soc_gpu_vpu: regulator@60 {
+ compatible = "fcs,fan53555";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_soc_gpu_vpu>;
+ reg = <0x60>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ vsel-gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ i2c1d: i2c1@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@68 {
+ compatible = "microcrystal,rv4162";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1d_rv4162>;
+ reg = <0x68>;
+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+ };
+ };
+};
+
+&uart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+ status = "okay";
+};
+
+&usdhc1 {
+ bus-width = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ non-removable;
+ vmmc-supply = <&reg_vref_1v8>;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* J17 connector, odd */
+ MX8MQ_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x19 /* Pin 19 */
+ MX8MQ_IOMUXC_SAI1_RXC_GPIO4_IO1 0x19 /* Pin 21 */
+ MX8MQ_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x19 /* Pin 23 */
+ MX8MQ_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x19 /* Pin 25 */
+ MX8MQ_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x19 /* Pin 27 */
+ MX8MQ_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x19 /* Pin 29 */
+ MX8MQ_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x19 /* Pin 31 */
+ MX8MQ_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x19 /* Pin 33 */
+ MX8MQ_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x19 /* Pin 35 */
+ MX8MQ_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x19 /* Pin 39 */
+ MX8MQ_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x19 /* Pin 41 */
+ MX8MQ_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x19 /* Pin 43 */
+ MX8MQ_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x19 /* Pin 45 */
+ MX8MQ_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x19 /* Pin 47 */
+ MX8MQ_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x19 /* Pin 49 */
+ MX8MQ_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x19 /* Pin 51 */
+
+ /* J17 connector, even */
+ MX8MQ_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x19 /* Pin 44 */
+ MX8MQ_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19 /* Pin 48 */
+ MX8MQ_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* Pin 50 */
+ MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19 /* Pin 54 */
+ MX8MQ_IOMUXC_GPIO1_IO05_GPIO1_IO5 0x19 /* Pin 56 */
+
+ /* J18 connector, odd */
+ MX8MQ_IOMUXC_NAND_CE3_B_GPIO3_IO4 0x19 /* Pin 41 */
+ MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5 0x19 /* Pin 43 */
+ MX8MQ_IOMUXC_NAND_READY_B_GPIO3_IO16 0x19 /* Pin 45 */
+ MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x19 /* Pin 47 */
+ MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18 0x19 /* Pin 49 */
+ MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* Pin 53 */
+
+ /* J18 connector, even */
+ MX8MQ_IOMUXC_NAND_ALE_GPIO3_IO0 0x19 /* Pin 32 */
+ MX8MQ_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x19 /* Pin 36 */
+ MX8MQ_IOMUXC_NAND_DATA00_GPIO3_IO6 0x19 /* Pin 38 */
+ MX8MQ_IOMUXC_NAND_DATA01_GPIO3_IO7 0x19 /* Pin 40 */
+ MX8MQ_IOMUXC_NAND_DATA02_GPIO3_IO8 0x19 /* Pin 42 */
+ MX8MQ_IOMUXC_NAND_DATA03_GPIO3_IO9 0x19 /* Pin 44 */
+ MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10 0x19 /* Pin 46 */
+
+ /* J13 Pin 2, WL_WAKE */
+ MX8MQ_IOMUXC_SAI5_RXD2_GPIO3_IO23 0xd6
+ /* J13 Pin 4, WL_IRQ, not needed for Silex */
+ MX8MQ_IOMUXC_SAI5_RXD0_GPIO3_IO21 0xd6
+ /* J13 pin 9, unused */
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
+ /* J13 Pin 41, BT_CLK_REQ */
+ MX8MQ_IOMUXC_SAI5_RXD1_GPIO3_IO22 0xd6
+ /* J13 Pin 42, BT_HOST_WAKE */
+ MX8MQ_IOMUXC_SAI5_MCLK_GPIO3_IO25 0xd6
+
+ /* Clock for both CSI1 and CSI2 */
+ MX8MQ_IOMUXC_GPIO1_IO15_CCMSRCGPCMIX_CLKO2 0x07
+ /* test points */
+ MX8MQ_IOMUXC_GPIO1_IO04_GPIO1_IO4 0xc1 /* TP87 */
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ MX8MQ_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x59
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19
+ >;
+ };
+
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c1_pca9546: i2c1-pca9546grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x49
+ >;
+ };
+
+ pinctrl_i2c1d_rv4162: i2c1d-rv4162grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x49
+ >;
+ };
+
+ pinctrl_reg_arm_dram: reg-arm-dramgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x16
+ >;
+ };
+
+ pinctrl_reg_dram_1p1v: reg-dram-1p1vgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_STROBE_GPIO2_IO11 0x16
+ >;
+ };
+
+ pinctrl_reg_soc_gpu_vpu: reg-soc-gpu-vpugrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_WP_GPIO2_IO20 0x16
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x45
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x45
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x45
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x45
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
+ MX8MQ_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x8d
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xcd
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xcd
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xcd
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xcd
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xcd
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xcd
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xcd
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xcd
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xcd
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x9f
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xdf
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xdf
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xdf
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xdf
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xdf
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xdf
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xdf
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xdf
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xdf
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
new file mode 100644
index 000000000000..8a4aee2348ee
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Wandboard, Org.
+ * Copyright 2017 NXP
+ *
+ * Author: Richard Hu <hakahu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+ model = "TechNexion PICO-PI-8M";
+ compatible = "technexion,pico-pi-imx8m", "fsl,imx8mq";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ pmic_osc: clock-pmic {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "pmic_osc";
+ };
+
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_otg_vbus>;
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 14 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1 &pinctrl_enet_3v3>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pmic@4b {
+ reg = <0x4b>;
+ compatible = "rohm,bd71837";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ clocks = <&pmic_osc>;
+ clock-names = "osc";
+ clock-output-names = "pmic_clk";
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 GPIO_ACTIVE_LOW>;
+ interrupt-names = "irq";
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <900000>;
+ rohm,dvs-idle-voltage = <850000>;
+ rohm,dvs-suspend-voltage = <800000>;
+ };
+
+ buck2: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ buck3: BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ rohm,dvs-run-voltage = <1000000>;
+ };
+
+ buck4: BUCK4 {
+ regulator-name = "buck4";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ rohm,dvs-run-voltage = <1000000>;
+ };
+
+ buck5: BUCK5 {
+ regulator-name = "buck5";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ };
+
+ buck6: BUCK6 {
+ regulator-name = "buck6";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ buck7: BUCK7 {
+ regulator-name = "buck7";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ };
+
+ buck8: BUCK8 {
+ regulator-name = "buck8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ };
+
+ ldo1: LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo5: LDO5 {
+ regulator-name = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo6: LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo7: LDO7 {
+ regulator-name = "ldo7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&uart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&usdhc2 {
+ 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>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_otg_vbus: otgvbusgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* USB OTG VBUS Enable */
+ >;
+ };
+
+ pinctrl_pmic: pmicirq {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x49
+ MX8MQ_IOMUXC_UART4_TXD_UART2_DCE_RTS_B 0x49
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x85
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi
new file mode 100644
index 000000000000..d7f03c65832b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2018 Jon Nettleton <jon@solid-run.com>
+ */
+
+#include "imx8mq.dtsi"
+
+/ {
+ reg_vdd_3v3: regulator-vdd-3v3 {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-name = "vdd_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ phy-reset-duration = <2>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <4>;
+ };
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ pmic: pmic@8 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3ab {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ 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>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+};
+
+&pgc_gpu{
+ power-supply = <&sw1a_reg>;
+};
+
+&pgc_vpu {
+ power-supply = <&sw1c_reg>;
+};
+
+&qspi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+
+ /* SPI flash; not assembled by default */
+ spi_flash: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ compatible = "micron,n25q256a", "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ status = "disabled";
+ };
+};
+
+&uart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+ assigned-clock-rates = <25000000>;
+ status = "okay";
+};
+
+&uart4 { /* ublox BT */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MQ_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
+ assigned-clock-rates = <80000000>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B 0x74
+ MX8MQ_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x16
+ MX8MQ_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x16
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_ALE_QSPI_A_SCLK 0x82
+ MX8MQ_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B 0x82
+ MX8MQ_IOMUXC_NAND_DATA00_QSPI_A_DATA0 0x82
+ MX8MQ_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x82
+ MX8MQ_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x82
+ MX8MQ_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x82
+
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+ MX8MQ_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART4_TXD_UART4_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART4_RXD_UART4_DCE_RX 0x49
+ MX8MQ_IOMUXC_SAI3_TXD_GPIO5_IO1 0x19
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83
+ MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x8d
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xcd
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xcd
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xcd
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xcd
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xcd
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xcd
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xcd
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xcd
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xcd
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x8d
+ MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x9f
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xdf
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xdf
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xdf
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xdf
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xdf
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xdf
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xdf
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xdf
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xdf
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x9f
+ MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
index 7a1706f969f0..af99473ada04 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
@@ -68,18 +68,6 @@
regulator-always-on;
};
- reg_5p0_user_usb: regulator-5p0-user-usb {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_reg_user_usb>;
- vin-supply = <&reg_5p0_main>;
- regulator-name = "5V_USER_USB";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 12 GPIO_ACTIVE_LOW>;
- startup-delay-us = <1000>;
- };
-
reg_usdhc2_vmmc: regulator-vsd-3v3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_reg_usdhc2>;
@@ -244,6 +232,13 @@
line-name = "usb-mode1";
};
+ usb-pwr {
+ gpio-hog;
+ gpios = <12 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "usb-pwr-ctrl-en-n";
+ };
+
usb-mode2 {
gpio-hog;
gpios = <13 GPIO_ACTIVE_HIGH>;
@@ -257,6 +252,17 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
+
+ ucs1002: charger@32 {
+ compatible = "microchip,ucs1002";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ucs1002>;
+ reg = <0x32>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <17 IRQ_TYPE_EDGE_BOTH>,
+ <18 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "a_det", "alert";
+ };
};
&i2c2 {
@@ -428,7 +434,7 @@
};
&usb3_phy0 {
- vbus-supply = <&reg_5p0_user_usb>;
+ vbus-supply = <&ucs1002>;
status = "okay";
};
@@ -532,6 +538,7 @@
fsl,pins = <
MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10 0x6
MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x6
+ MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x6
MX8MQ_IOMUXC_NAND_DATA07_GPIO3_IO13 0x6
>;
};
@@ -597,12 +604,6 @@
>;
};
- pinctrl_reg_user_usb: reguserusbgrp {
- fsl,pins = <
- MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x6
- >;
- };
-
pinctrl_switch_irq: switchgrp {
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x41
@@ -630,6 +631,13 @@
>;
};
+ pinctrl_ucs1002: ucs1002grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_WE_B_GPIO3_IO17 0x41
+ MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18 0x41
+ >;
+ };
+
pinctrl_usbhub: usbhubgrp {
fsl,pins = <
MX8MQ_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x41
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index b4529773af51..3f3594d9485c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -156,6 +156,7 @@
/* Industrial only */
opp-supported-hw = <0xf>, <0x4>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
opp-1000000000 {
@@ -164,21 +165,23 @@
/* Consumer only */
opp-supported-hw = <0xe>, <0x3>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
opp-1300000000 {
opp-hz = /bits/ 64 <1300000000>;
opp-microvolt = <1000000>;
- opp-supported-hw = <0xc>, <0x7>;
+ opp-supported-hw = <0xc>, <0x4>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
opp-1500000000 {
opp-hz = /bits/ 64 <1500000000>;
opp-microvolt = <1000000>;
- /* Consumer only but rely on speed grading */
- opp-supported-hw = <0x8>, <0x7>;
+ opp-supported-hw = <0x8>, <0x3>;
clock-latency-ns = <150000>;
+ opp-suspend;
};
};
@@ -288,6 +291,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 10 30>;
};
gpio2: gpio@30210000 {
@@ -300,6 +304,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 40 21>;
};
gpio3: gpio@30220000 {
@@ -312,6 +317,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 61 26>;
};
gpio4: gpio@30230000 {
@@ -324,6 +330,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 87 32>;
};
gpio5: gpio@30240000 {
@@ -336,12 +343,14 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 119 30>;
};
tmu: tmu@30260000 {
compatible = "fsl,imx8mq-tmu";
reg = <0x30260000 0x10000>;
interrupt = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MQ_CLK_TMU_ROOT>;
little-endian;
fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
fsl,tmu-calibration = <0x00000000 0x00000023
@@ -431,8 +440,15 @@
};
iomuxc_gpr: syscon@30340000 {
- compatible = "fsl,imx8mq-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon";
+ compatible = "fsl,imx8mq-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr",
+ "syscon", "simple-mfd";
reg = <0x30340000 0x10000>;
+
+ mux: mux-controller {
+ compatible = "mmio-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x34 0x00000004>; /* MIPI_MUX_SEL */
+ };
};
ocotp: ocotp-ctrl@30350000 {
@@ -723,8 +739,7 @@
sai2: sai@308b0000 {
#sound-dai-cells = <0>;
- compatible = "fsl,imx8mq-sai",
- "fsl,imx6sx-sai";
+ compatible = "fsl,imx8mq-sai";
reg = <0x308b0000 0x10000>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MQ_CLK_SAI2_IPG>,
@@ -736,6 +751,19 @@
status = "disabled";
};
+ dphy: dphy@30a00300 {
+ compatible = "fsl,imx8mq-mipi-dphy";
+ reg = <0x30a00300 0x100>;
+ clocks = <&clk IMX8MQ_CLK_DSI_PHY_REF>;
+ clock-names = "phy_ref";
+ assigned-clocks = <&clk IMX8MQ_CLK_DSI_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MQ_VIDEO_PLL1_OUT>;
+ assigned-clock-rates = <24000000>;
+ #phy-cells = <0>;
+ power-domains = <&pgc_mipi>;
+ status = "disabled";
+ };
+
i2c1: i2c@30a20000 {
compatible = "fsl,imx8mq-i2c", "fsl,imx21-i2c";
reg = <0x30a20000 0x10000>;
@@ -909,9 +937,9 @@
usb_dwc3_0: usb@38100000 {
compatible = "fsl,imx8mq-dwc3", "snps,dwc3";
reg = <0x38100000 0x10000>;
- clocks = <&clk IMX8MQ_CLK_USB_BUS>,
+ clocks = <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>,
<&clk IMX8MQ_CLK_USB_CORE_REF>,
- <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>;
+ <&clk IMX8MQ_CLK_32K>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>,
<&clk IMX8MQ_CLK_USB_CORE_REF>;
@@ -941,9 +969,9 @@
usb_dwc3_1: usb@38200000 {
compatible = "fsl,imx8mq-dwc3", "snps,dwc3";
reg = <0x38200000 0x10000>;
- clocks = <&clk IMX8MQ_CLK_USB_BUS>,
+ clocks = <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>,
<&clk IMX8MQ_CLK_USB_CORE_REF>,
- <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>;
+ <&clk IMX8MQ_CLK_32K>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>,
<&clk IMX8MQ_CLK_USB_CORE_REF>;
@@ -1041,5 +1069,12 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
};
+
+ ddr-pmu@3d800000 {
+ compatible = "fsl,imx8mq-ddr-pmu", "fsl,imx8m-ddr-pmu";
+ reg = <0x3d800000 0x400000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts
new file mode 100644
index 000000000000..91eef9754101
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Einfochips
+ * Copyright 2019 Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include "imx8qxp.dtsi"
+
+/ {
+ model = "Einfochips i.MX8QXP AI_ML";
+ compatible = "einfochips,imx8qxp-ai_ml", "fsl,imx8qxp";
+
+ aliases {
+ serial1 = &adma_lpuart1;
+ serial2 = &adma_lpuart2;
+ serial3 = &adma_lpuart3;
+ };
+
+ chosen {
+ stdout-path = &adma_lpuart2;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0 0x80000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_leds>;
+
+ user-led1 {
+ label = "green:user1";
+ gpios = <&lsio_gpio4 16 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ user-led2 {
+ label = "green:user2";
+ gpios = <&lsio_gpio0 6 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ };
+
+ user-led3 {
+ label = "green:user3";
+ gpios = <&lsio_gpio0 7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc1";
+ default-state = "off";
+ };
+
+ user-led4 {
+ label = "green:user4";
+ gpios = <&lsio_gpio4 21 GPIO_ACTIVE_HIGH>;
+ panic-indicator;
+ linux,default-trigger = "none";
+ };
+
+ wlan-active-led {
+ label = "yellow:wlan";
+ gpios = <&lsio_gpio4 17 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
+
+ bt-active-led {
+ label = "blue:bt";
+ gpios = <&lsio_gpio4 18 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "hci0-power";
+ default-state = "off";
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_reg_on>;
+ reset-gpios = <&lsio_gpio3 24 GPIO_ACTIVE_LOW>;
+ };
+};
+
+/* BT */
+&adma_lpuart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart0>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+/* LS-UART0 */
+&adma_lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart1>;
+ status = "okay";
+};
+
+/* Debug */
+&adma_lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+ status = "okay";
+};
+
+/* PCI-E UART */
+&adma_lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+ };
+};
+
+/* WiFi */
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ bus-width = <4>;
+ no-sd;
+ non-removable;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+/* SD */
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ cd-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ IMX8QXP_ENET0_MDC_CONN_ENET0_MDC 0x06000020
+ IMX8QXP_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020
+ IMX8QXP_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x06000020
+ IMX8QXP_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x06000020
+ IMX8QXP_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x06000020
+ IMX8QXP_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x06000020
+ IMX8QXP_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x06000020
+ IMX8QXP_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x06000020
+ IMX8QXP_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x06000020
+ IMX8QXP_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x06000020
+ IMX8QXP_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x06000020
+ IMX8QXP_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x06000020
+ IMX8QXP_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x06000020
+ IMX8QXP_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x06000020
+ >;
+ };
+
+ pinctrl_leds: ledsgrp{
+ fsl,pins = <
+ IMX8QXP_ESAI0_TX2_RX3_LSIO_GPIO0_IO06 0x00000021
+ IMX8QXP_ESAI0_TX3_RX2_LSIO_GPIO0_IO07 0x00000021
+ IMX8QXP_EMMC0_DATA7_LSIO_GPIO4_IO16 0x00000021
+ IMX8QXP_USDHC1_WP_LSIO_GPIO4_IO21 0x00000021
+ IMX8QXP_EMMC0_STROBE_LSIO_GPIO4_IO17 0x00000021
+ IMX8QXP_EMMC0_RESET_B_LSIO_GPIO4_IO18 0x00000021
+ >;
+ };
+
+ pinctrl_lpuart0: lpuart0grp {
+ fsl,pins = <
+ IMX8QXP_UART0_RX_ADMA_UART0_RX 0X06000020
+ IMX8QXP_UART0_TX_ADMA_UART0_TX 0X06000020
+ IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020
+ IMX8QXP_FLEXCAN0_RX_ADMA_UART0_RTS_B 0x06000020
+ >;
+ };
+
+ pinctrl_lpuart1: lpuart1grp {
+ fsl,pins = <
+ IMX8QXP_UART1_RX_ADMA_UART1_RX 0X06000020
+ IMX8QXP_UART1_TX_ADMA_UART1_TX 0X06000020
+ >;
+ };
+
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QXP_UART2_RX_ADMA_UART2_RX 0X06000020
+ IMX8QXP_UART2_TX_ADMA_UART2_TX 0X06000020
+ >;
+ };
+
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN2_RX_ADMA_UART3_RX 0X06000020
+ IMX8QXP_FLEXCAN2_TX_ADMA_UART3_TX 0X06000020
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x00000021
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000021
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000021
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000021
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x00000021
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x00000021
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x00000021
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x00000021
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x00000021
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x00000021
+ IMX8QXP_USDHC1_CD_B_LSIO_GPIO4_IO22 0x00000021
+ >;
+ };
+
+ pinctrl_wifi_reg_on: wifiregongrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 0x00000021
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index bfdada2db176..19468058e6ae 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -230,3 +230,7 @@
>;
};
};
+
+&adma_dsp {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index 05fa0b7f36bb..1133b412182a 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -30,6 +30,9 @@
mmc2 = &usdhc3;
mu1 = &lsio_mu1;
serial0 = &adma_lpuart0;
+ serial1 = &adma_lpuart1;
+ serial2 = &adma_lpuart2;
+ serial3 = &adma_lpuart3;
};
cpus {
@@ -113,6 +116,17 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ dsp_reserved: dsp@92400000 {
+ reg = <0 0x92400000 0 0x2000000>;
+ no-map;
+ };
+ };
+
pmu {
compatible = "arm,armv8-pmuv3";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
@@ -204,13 +218,35 @@
#clock-cells = <1>;
};
+ adma_dsp: dsp@596e8000 {
+ compatible = "fsl,imx8qxp-dsp";
+ reg = <0x596e8000 0x88000>;
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>;
+ clock-names = "ipg", "ocram", "core";
+ power-domains = <&pd IMX_SC_R_MU_13A>,
+ <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_DSP>,
+ <&pd IMX_SC_R_DSP_RAM>;
+ mbox-names = "txdb0", "txdb1",
+ "rxdb0", "rxdb1";
+ mboxes = <&lsio_mu13 2 0>,
+ <&lsio_mu13 2 1>,
+ <&lsio_mu13 3 0>,
+ <&lsio_mu13 3 1>;
+ memory-region = <&dsp_reserved>;
+ status = "disabled";
+ };
+
adma_lpuart0: serial@5a060000 {
compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
reg = <0x5a060000 0x1000>;
interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
- clocks = <&adma_lpcg IMX_ADMA_LPCG_UART0_BAUD_CLK>;
- clock-names = "ipg";
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_UART0_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_UART0_BAUD_CLK>;
+ clock-names = "ipg", "baud";
power-domains = <&pd IMX_SC_R_UART_0>;
status = "disabled";
};
@@ -220,8 +256,9 @@
reg = <0x5a070000 0x1000>;
interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
- clocks = <&adma_lpcg IMX_ADMA_LPCG_UART1_BAUD_CLK>;
- clock-names = "ipg";
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_UART1_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_UART1_BAUD_CLK>;
+ clock-names = "ipg", "baud";
power-domains = <&pd IMX_SC_R_UART_1>;
status = "disabled";
};
@@ -231,8 +268,9 @@
reg = <0x5a080000 0x1000>;
interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
- clocks = <&adma_lpcg IMX_ADMA_LPCG_UART2_BAUD_CLK>;
- clock-names = "ipg";
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_UART2_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_UART2_BAUD_CLK>;
+ clock-names = "ipg", "baud";
power-domains = <&pd IMX_SC_R_UART_2>;
status = "disabled";
};
@@ -242,8 +280,9 @@
reg = <0x5a090000 0x1000>;
interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
- clocks = <&adma_lpcg IMX_ADMA_LPCG_UART3_BAUD_CLK>;
- clock-names = "ipg";
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_UART3_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_UART3_BAUD_CLK>;
+ clock-names = "ipg", "baud";
power-domains = <&pd IMX_SC_R_UART_3>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
index e4ceb3a73c81..36abc25320a8 100644
--- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
@@ -249,6 +249,8 @@
#dma-cells = <1>;
#dma-channels = <8>;
#dma-requests = <32>;
+ resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>;
+ reset-names = "dma", "dma-ocp";
};
rst: rstmgr@ffd11000 {
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index f43c43168b00..7f69e3dfcb13 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -419,6 +419,13 @@
clocks = <&nb_periph_clk 15>;
};
+ rwtm: mailbox@b0000 {
+ compatible = "marvell,armada-3700-rwtm-mailbox";
+ reg = <0xb0000 0x100>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ };
+
sdhci1: sdhci@d0000 {
compatible = "marvell,armada-3700-sdhci",
"marvell,sdhci-xenon";
diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index f34ee87a0f56..a7eb4e7697a2 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -73,16 +73,6 @@
gpio = <&expander0 1 GPIO_ACTIVE_HIGH>;
vin-supply = <&cp0_exp_usb3_1_current_regulator>;
};
-
- cp0_usb3_0_phy: cp0-usb3-0-phy {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp0_reg_usb3_0_vbus>;
- };
-
- cp0_usb3_1_phy: cp0-usb3-1-phy {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp0_reg_usb3_1_vbus>;
- };
};
&i2c0 {
@@ -124,6 +114,8 @@
&cp0_pcie2 {
status = "okay";
+ phys = <&cp0_comphy5 2>;
+ phy-names = "cp0-pcie2-x1-phy";
};
&cp0_i2c0 {
@@ -219,15 +211,36 @@
&cp0_sata0 {
status = "okay";
+
+ sata-port@1 {
+ phys = <&cp0_comphy3 1>;
+ phy-names = "cp0-sata0-1-phy";
+ };
+};
+
+&cp0_comphy1 {
+ cp0_usbh0_con: connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&cp0_reg_usb3_0_vbus>;
+ };
};
&cp0_usb3_0 {
- usb-phy = <&cp0_usb3_0_phy>;
+ phys = <&cp0_comphy1 0>;
+ phy-names = "cp0-usb3h0-comphy";
status = "okay";
};
+&cp0_comphy4 {
+ cp0_usbh1_con: connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&cp0_reg_usb3_1_vbus>;
+ };
+};
+
&cp0_usb3_1 {
- usb-phy = <&cp0_usb3_1_phy>;
+ phys = <&cp0_comphy4 1>;
+ phy-names = "cp0-usb3h1-comphy";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
index f275d9420d5b..bd881497b872 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -51,11 +51,6 @@
status = "okay";
};
- usb3h0_phy: usb3_phy0 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&v_5v0_usb3_hst_vbus>;
- };
-
sfp_cp0_eth0: sfp-cp0-eth0 {
compatible = "sff,sfp";
i2c-bus = <&cp0_i2c1>;
@@ -243,6 +238,8 @@
pinctrl-names = "default";
pinctrl-0 = <&cp0_pci0_reset_pins &cp0_wlan_disable_pins>;
reset-gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>;
+ phys = <&cp0_comphy0 0>;
+ phy-names = "cp0-pcie0-x1-phy";
status = "okay";
};
@@ -348,6 +345,11 @@
&cp1_sata0 {
pinctrl-0 = <&cp0_pci1_reset_pins>;
status = "okay";
+
+ sata-port@1 {
+ phys = <&cp1_comphy0 1>;
+ phy-names = "cp1-sata0-1-phy";
+ };
};
&cp1_mdio {
@@ -467,7 +469,15 @@
};
};
+&cp1_comphy2 {
+ cp1_usbh0_con: connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&v_5v0_usb3_hst_vbus>;
+ };
+};
+
&cp1_usb3_0 {
- usb-phy = <&usb3h0_phy>;
+ phys = <&cp1_comphy2 0>;
+ phy-names = "cp1-usb3h0-comphy";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index d6e9c014c2f9..09fb5256f1db 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -54,11 +54,6 @@
vcc-supply = <&cp0_reg_usb3_0_vbus>;
};
- cp0_usb3_1_phy: cp0-usb3-1-phy {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp0_reg_usb3_1_vbus>;
- };
-
cp1_reg_usb3_0_vbus: cp1-usb3-0-vbus {
compatible = "regulator-fixed";
regulator-name = "cp1-usb3h0-vbus";
@@ -108,11 +103,15 @@
/* CON6 on CP0 expansion */
&cp0_pcie0 {
+ phys = <&cp0_comphy0 0>;
+ phy-names = "cp0-pcie0-x1-phy";
status = "okay";
};
/* CON5 on CP0 expansion */
&cp0_pcie2 {
+ phys = <&cp0_comphy5 2>;
+ phy-names = "cp0-pcie2-x1-phy";
status = "okay";
};
@@ -143,6 +142,15 @@
/* CON4 on CP0 expansion */
&cp0_sata0 {
status = "okay";
+
+ sata-port@0 {
+ phys = <&cp0_comphy1 0>;
+ phy-names = "cp0-sata0-0-phy";
+ };
+ sata-port@1 {
+ phys = <&cp0_comphy3 1>;
+ phy-names = "cp0-sata0-1-phy";
+ };
};
/* CON9 on CP0 expansion */
@@ -151,9 +159,17 @@
status = "okay";
};
+&cp0_comphy4 {
+ cp0_usbh1_con: connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&cp0_reg_usb3_1_vbus>;
+ };
+};
+
/* CON10 on CP0 expansion */
&cp0_usb3_1 {
- usb-phy = <&cp0_usb3_1_phy>;
+ phys = <&cp0_comphy4 1>;
+ phy-names = "cp0-usb3h1-comphy";
status = "okay";
};
@@ -187,16 +203,22 @@
/* CON6 on CP1 expansion */
&cp1_pcie0 {
+ phys = <&cp1_comphy0 0>;
+ phy-names = "cp1-pcie0-x1-phy";
status = "okay";
};
/* CON7 on CP1 expansion */
&cp1_pcie1 {
+ phys = <&cp1_comphy4 1>;
+ phy-names = "cp1-pcie1-x1-phy";
status = "okay";
};
/* CON5 on CP1 expansion */
&cp1_pcie2 {
+ phys = <&cp1_comphy5 2>;
+ phy-names = "cp1-pcie2-x1-phy";
status = "okay";
};
@@ -273,6 +295,15 @@
/* CON4 on CP1 expansion */
&cp1_sata0 {
status = "okay";
+
+ sata-port@0 {
+ phys = <&cp1_comphy1 0>;
+ phy-names = "cp1-sata0-0-phy";
+ };
+ sata-port@1 {
+ phys = <&cp1_comphy3 1>;
+ phy-names = "cp1-sata0-1-phy";
+ };
};
/* CON9 on CP1 expansion */
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
index 205071b45a32..d250f4b2bfed 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
@@ -61,11 +61,6 @@
status = "okay";
};
- usb3h0_phy: usb3_phy0 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&v_5v0_usb3_hst_vbus>;
- };
-
sfp_eth0: sfp-eth0 {
/* CON15,16 - CPM lane 4 */
compatible = "sff,sfp";
@@ -186,6 +181,10 @@
reset-gpios = <&cp0_gpio2 20 GPIO_ACTIVE_LOW>;
ranges = <0x81000000 0x0 0xf9010000 0x0 0xf9010000 0x0 0x10000
0x82000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x20000000>;
+ phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>,
+ <&cp0_comphy2 0>, <&cp0_comphy3 0>;
+ phy-names = "cp0-pcie0-x4-lane0-phy", "cp0-pcie0-x4-lane1-phy",
+ "cp0-pcie0-x4-lane2-phy", "cp0-pcie0-x4-lane3-phy";
status = "okay";
};
@@ -239,8 +238,13 @@
};
&cp0_sata0 {
- /* CPM Lane 0 - U29 */
status = "okay";
+
+ /* CPM Lane 5 - U29 */
+ sata-port@1 {
+ phys = <&cp0_comphy5 1>;
+ phy-names = "cp0-sata0-1-phy";
+ };
};
&cp0_sdhci0 {
@@ -324,9 +328,19 @@
};
&cp1_sata0 {
+ status = "okay";
+
/* CPS Lane 1 - U32 */
+ sata-port@0 {
+ phys = <&cp1_comphy1 0>;
+ phy-names = "cp1-sata0-0-phy";
+ };
+
/* CPS Lane 3 - U31 */
- status = "okay";
+ sata-port@1 {
+ phys = <&cp1_comphy3 1>;
+ phy-names = "cp1-sata0-1-phy";
+ };
};
&cp1_spi1 {
@@ -341,8 +355,16 @@
};
};
+&cp1_comphy2 {
+ cp1_usbh0_con: connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&v_5v0_usb3_hst_vbus>;
+ };
+};
+
&cp1_usb3_0 {
/* CPS Lane 2 - CON7 */
- usb-phy = <&usb3h0_phy>;
+ phys = <&cp1_comphy2 0>;
+ phy-names = "cp1-usb3h0-comphy";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
index ea13ae78f50d..c25bc65727b5 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
@@ -21,6 +21,7 @@
reg = <0x000>;
enable-method = "psci";
#cooling-cells = <2>;
+ clocks = <&cpu_clk 0>;
};
cpu1: cpu@1 {
device_type = "cpu";
@@ -28,6 +29,7 @@
reg = <0x001>;
enable-method = "psci";
#cooling-cells = <2>;
+ clocks = <&cpu_clk 0>;
};
cpu2: cpu@100 {
device_type = "cpu";
@@ -35,6 +37,7 @@
reg = <0x100>;
enable-method = "psci";
#cooling-cells = <2>;
+ clocks = <&cpu_clk 1>;
};
cpu3: cpu@101 {
device_type = "cpu";
@@ -42,7 +45,7 @@
reg = <0x101>;
enable-method = "psci";
#cooling-cells = <2>;
+ clocks = <&cpu_clk 1>;
};
};
-
};
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
index 96228f93b272..d06dd198f2c7 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
@@ -280,6 +280,13 @@
#address-cells = <1>;
#size-cells = <1>;
+ cpu_clk: clock-cpu@278 {
+ compatible = "marvell,ap806-cpu-clock";
+ clocks = <&ap_clk 0>, <&ap_clk 1>;
+ #clock-cells = <1>;
+ reg = <0x278 0xa30>;
+ };
+
ap_thermal: thermal-sensor@80 {
compatible = "marvell,armada-ap806-thermal";
reg = <0x80 0x10>;
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
index f71afb1de18f..d81944902650 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
@@ -133,6 +133,9 @@
compatible = "marvell,comphy-cp110";
reg = <0x120000 0x6000>;
marvell,system-controller = <&CP110_LABEL(syscon0)>;
+ clocks = <&CP110_LABEL(clk) 1 5>, <&CP110_LABEL(clk) 1 6>,
+ <&CP110_LABEL(clk) 1 18>;
+ clock-names = "mg_clk", "mg_core_clk", "axi_clk";
#address-cells = <1>;
#size-cells = <0>;
@@ -306,7 +309,17 @@
interrupts = <107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&CP110_LABEL(clk) 1 15>,
<&CP110_LABEL(clk) 1 16>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
+
+ sata-port@0 {
+ reg = <0>;
+ };
+
+ sata-port@1 {
+ reg = <1>;
+ };
};
CP110_LABEL(xor0): xor@6a0000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
index d8e555cbb5d3..1fb195c683c3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
@@ -30,7 +30,103 @@
status = "okay";
};
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_0>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_1>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_2>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_3>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_4>;
+ status = "okay";
+ clock-frequency = <1000000>;
+};
+
+&i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins_5>;
+ status = "okay";
+ clock-frequency = <1000000>;
+};
+
&pio {
+ i2c_pins_0: i2c0{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
+ <PINMUX_GPIO83__FUNC_SCL0>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
+ i2c_pins_1: i2c1{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
+ <PINMUX_GPIO84__FUNC_SCL1>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
+ i2c_pins_2: i2c2{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
+ <PINMUX_GPIO104__FUNC_SDA2>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
+ i2c_pins_3: i2c3{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
+ <PINMUX_GPIO51__FUNC_SDA3>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
+ i2c_pins_4: i2c4{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
+ <PINMUX_GPIO106__FUNC_SDA4>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
+ i2c_pins_5: i2c5{
+ pins_i2c{
+ pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
+ <PINMUX_GPIO49__FUNC_SDA5>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <00>;
+ };
+ };
+
spi_pins_0: spi0{
pins_spi{
pinmux = <PINMUX_GPIO85__FUNC_SPI0_MI>,
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index c2749c4631bc..97f84aa9fc6e 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -16,6 +16,21 @@
#address-cells = <2>;
#size-cells = <2>;
+ aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ i2c6 = &i2c6;
+ i2c7 = &i2c7;
+ i2c8 = &i2c8;
+ i2c9 = &i2c9;
+ i2c10 = &i2c10;
+ i2c11 = &i2c11;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -248,7 +263,7 @@
compatible = "mediatek,mt8183-pwrap";
reg = <0 0x1000d000 0 0x1000>;
reg-names = "pwrap";
- interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_MUX_PMICSPI>,
<&infracfg CLK_INFRA_PMIC_AP>;
clock-names = "spi", "wrap";
@@ -294,6 +309,64 @@
status = "disabled";
};
+ i2c6: i2c@11005000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11005000 0 0x1000>,
+ <0 0x11000600 0 0x80>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C6>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@11007000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11007000 0 0x1000>,
+ <0 0x11000080 0 0x80>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C0>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@11008000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11008000 0 0x1000>,
+ <0 0x11000100 0 0x80>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C1>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C1_ARBITER>;
+ clock-names = "main", "dma","arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@11009000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11009000 0 0x1000>,
+ <0 0x11000280 0 0x80>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C2>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C2_ARBITER>;
+ clock-names = "main", "dma", "arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
spi0: spi@1100a000 {
compatible = "mediatek,mt8183-spi";
#address-cells = <1>;
@@ -307,6 +380,20 @@
status = "disabled";
};
+ i2c3: i2c@1100f000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x1100f000 0 0x1000>,
+ <0 0x11000400 0 0x80>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C3>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
spi1: spi@11010000 {
compatible = "mediatek,mt8183-spi";
#address-cells = <1>;
@@ -320,6 +407,20 @@
status = "disabled";
};
+ i2c1: i2c@11011000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11011000 0 0x1000>,
+ <0 0x11000480 0 0x80>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C4>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
spi2: spi@11012000 {
compatible = "mediatek,mt8183-spi";
#address-cells = <1>;
@@ -346,6 +447,66 @@
status = "disabled";
};
+ i2c9: i2c@11014000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11014000 0 0x1000>,
+ <0 0x11000180 0 0x80>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C1_IMM>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C1_ARBITER>;
+ clock-names = "main", "dma", "arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c10: i2c@11015000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11015000 0 0x1000>,
+ <0 0x11000300 0 0x80>;
+ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C2_IMM>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C2_ARBITER>;
+ clock-names = "main", "dma", "arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@11016000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11016000 0 0x1000>,
+ <0 0x11000500 0 0x80>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C5>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C5_ARBITER>;
+ clock-names = "main", "dma", "arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c11: i2c@11017000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x11017000 0 0x1000>,
+ <0 0x11000580 0 0x80>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C5_IMM>,
+ <&infracfg CLK_INFRA_AP_DMA>,
+ <&infracfg CLK_INFRA_I2C5_ARBITER>;
+ clock-names = "main", "dma", "arb";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
spi4: spi@11018000 {
compatible = "mediatek,mt8183-spi";
#address-cells = <1>;
@@ -372,6 +533,34 @@
status = "disabled";
};
+ i2c7: i2c@1101a000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x1101a000 0 0x1000>,
+ <0 0x11000680 0 0x80>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C7>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@1101b000 {
+ compatible = "mediatek,mt8183-i2c";
+ reg = <0 0x1101b000 0 0x1000>,
+ <0 0x11000700 0 0x80>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_I2C8>,
+ <&infracfg CLK_INFRA_AP_DMA>;
+ clock-names = "main", "dma";
+ clock-div = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
audiosys: syscon@11220000 {
compatible = "mediatek,mt8183-audiosys", "syscon";
reg = <0 0x11220000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 0a7e5dfce6f7..6498a1ec893f 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -3,14 +3,22 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb
dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8150.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a3u-eur.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a5u-eur.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
new file mode 100644
index 000000000000..2b28e383fd0b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916.dtsi"
+#include "pm8916.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Longcheer L8150";
+ compatible = "longcheer,l8150", "qcom,msm8916-v1-qrd/9-v1", "qcom,msm8916";
+
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ soc {
+ sdhci@7824000 {
+ status = "okay";
+
+ vmmc-supply = <&pm8916_l8>;
+ vqmmc-supply = <&pm8916_l5>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+ };
+
+ sdhci@7864000 {
+ status = "okay";
+
+ vmmc-supply = <&pm8916_l11>;
+ vqmmc-supply = <&pm8916_l12>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ non-removable;
+ };
+
+ serial@78b0000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp1_uart2_default>;
+ pinctrl-1 = <&blsp1_uart2_sleep>;
+ };
+
+ usb@78d9000 {
+ status = "okay";
+ dr_mode = "peripheral";
+ extcon = <&usb_vbus>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ ulpi {
+ phy {
+ extcon = <&usb_vbus>;
+ v1p8-supply = <&pm8916_l7>;
+ v3p3-supply = <&pm8916_l13>;
+ };
+ };
+ };
+
+ /*
+ * Attempting to enable these devices causes a "synchronous
+ * external abort". Suspected cause is that the debug power
+ * domain is not enabled by default on this device.
+ * Disable these devices for now to avoid the crash.
+ *
+ * See: https://lore.kernel.org/linux-arm-msm/20190618202623.GA53651@gerhold.net/
+ */
+ tpiu@820000 { status = "disabled"; };
+ funnel@821000 { status = "disabled"; };
+ replicator@824000 { status = "disabled"; };
+ etf@825000 { status = "disabled"; };
+ etr@826000 { status = "disabled"; };
+ funnel@841000 { status = "disabled"; };
+ debug@850000 { status = "disabled"; };
+ debug@852000 { status = "disabled"; };
+ debug@854000 { status = "disabled"; };
+ debug@856000 { status = "disabled"; };
+ etm@85c000 { status = "disabled"; };
+ etm@85d000 { status = "disabled"; };
+ etm@85e000 { status = "disabled"; };
+ etm@85f000 { status = "disabled"; };
+ };
+
+ // FIXME: Use extcon device provided by charger driver when available
+ usb_vbus: usb-vbus {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&msmgpio 62 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_vbus_default>;
+ };
+};
+
+&msmgpio {
+ usb_vbus_default: usb-vbus-default {
+ pinmux {
+ function = "gpio";
+ pins = "gpio62";
+ };
+ pinconf {
+ pins = "gpio62";
+ bias-pull-up;
+ };
+ };
+};
+
+&smd_rpm_regulators {
+ vdd_l1_l2_l3-supply = <&pm8916_s3>;
+ vdd_l4_l5_l6-supply = <&pm8916_s4>;
+ vdd_l7-supply = <&pm8916_s4>;
+
+ s1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2100000>;
+ };
+
+ l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1287500>;
+ };
+
+ l4 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l8 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ l9 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l10 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ l11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ regulator-system-load = <200000>;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ l13 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ l18 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
new file mode 100644
index 000000000000..e675ff48fdd2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include "msm8916.dtsi"
+#include "pm8916.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ soc {
+ sdhci@7824000 {
+ status = "okay";
+
+ vmmc-supply = <&pm8916_l8>;
+ vqmmc-supply = <&pm8916_l5>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+ };
+
+ sdhci@7864000 {
+ status = "okay";
+
+ vmmc-supply = <&pm8916_l11>;
+ vqmmc-supply = <&pm8916_l12>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>;
+ };
+
+ serial@78b0000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp1_uart2_default>;
+ pinctrl-1 = <&blsp1_uart2_sleep>;
+ };
+
+ usb@78d9000 {
+ status = "okay";
+ extcon = <&muic>, <&muic>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ ulpi {
+ phy {
+ extcon = <&muic>;
+ v1p8-supply = <&pm8916_l7>;
+ v3p3-supply = <&pm8916_l13>;
+ };
+ };
+ };
+
+ /*
+ * Attempting to enable these devices causes a "synchronous
+ * external abort". Suspected cause is that the debug power
+ * domain is not enabled by default on this device.
+ * Disable these devices for now to avoid the crash.
+ *
+ * See: https://lore.kernel.org/linux-arm-msm/20190618202623.GA53651@gerhold.net/
+ */
+ tpiu@820000 { status = "disabled"; };
+ funnel@821000 { status = "disabled"; };
+ replicator@824000 { status = "disabled"; };
+ etf@825000 { status = "disabled"; };
+ etr@826000 { status = "disabled"; };
+ funnel@841000 { status = "disabled"; };
+ debug@850000 { status = "disabled"; };
+ debug@852000 { status = "disabled"; };
+ debug@854000 { status = "disabled"; };
+ debug@856000 { status = "disabled"; };
+ etm@85c000 { status = "disabled"; };
+ etm@85d000 { status = "disabled"; };
+ etm@85e000 { status = "disabled"; };
+ etm@85f000 { status = "disabled"; };
+ };
+
+ i2c-muic {
+ compatible = "i2c-gpio";
+ sda-gpios = <&msmgpio 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&msmgpio 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ muic: sm5502@25 {
+ compatible = "siliconmitus,sm5502-muic";
+
+ reg = <0x25>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&muic_int_default>;
+ };
+ };
+};
+
+&msmgpio {
+ muic_int_default: muic_int_default {
+ pinmux {
+ function = "gpio";
+ pins = "gpio12";
+ };
+ pinconf {
+ pins = "gpio12";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+};
+
+&smd_rpm_regulators {
+ vdd_l1_l2_l3-supply = <&pm8916_s3>;
+ vdd_l4_l5_l6-supply = <&pm8916_s4>;
+ vdd_l7-supply = <&pm8916_s4>;
+
+ s1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2100000>;
+ };
+
+ l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1287500>;
+ };
+
+ l4 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l8 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ l9 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l10 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ l11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ regulator-system-load = <200000>;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ l13 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ l18 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
new file mode 100644
index 000000000000..d10f7ac5089f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-samsung-a2015-common.dtsi"
+
+/ {
+ model = "Samsung Galaxy A3U (EUR)";
+ compatible = "samsung,a3u-eur", "qcom,msm8916";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
new file mode 100644
index 000000000000..1aa59da98495
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-samsung-a2015-common.dtsi"
+
+/ {
+ model = "Samsung Galaxy A5U (EUR)";
+ compatible = "samsung,a5u-eur", "qcom,msm8916";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 96c0a481f454..87f4d9c1b0d4 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -633,6 +633,474 @@
reg = <0x300000 0x90000>;
};
+ stm@3002000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0x3002000 0x1000>,
+ <0x8280000 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint =
+ <&funnel0_in>;
+ };
+ };
+ };
+ };
+
+ tpiu@3020000 {
+ compatible = "arm,coresight-tpiu", "arm,primecell";
+ reg = <0x3020000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ port {
+ tpiu_in: endpoint {
+ remote-endpoint =
+ <&replicator_out1>;
+ };
+ };
+ };
+ };
+
+ funnel@3021000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3021000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+ funnel0_in: endpoint {
+ remote-endpoint =
+ <&stm_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ funnel0_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ funnel@3022000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3022000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@6 {
+ reg = <6>;
+ funnel1_in: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ funnel1_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@3023000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3023000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+
+ out-ports {
+ port {
+ funnel2_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in2>;
+ };
+ };
+ };
+ };
+
+ funnel@3025000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3025000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ merge_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ merge_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ merge_funnel_in2: endpoint {
+ remote-endpoint =
+ <&funnel2_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ merge_funnel_out: endpoint {
+ remote-endpoint =
+ <&etf_in>;
+ };
+ };
+ };
+ };
+
+ replicator@3026000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0x3026000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ port {
+ replicator_in: endpoint {
+ remote-endpoint =
+ <&etf_out>;
+ };
+ };
+ };
+
+ out-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ replicator_out0: endpoint {
+ remote-endpoint =
+ <&etr_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ replicator_out1: endpoint {
+ remote-endpoint =
+ <&tpiu_in>;
+ };
+ };
+ };
+ };
+
+ etf@3027000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x3027000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ port {
+ etf_in: endpoint {
+ remote-endpoint =
+ <&merge_funnel_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ etf_out: endpoint {
+ remote-endpoint =
+ <&replicator_in>;
+ };
+ };
+ };
+ };
+
+ etr@3028000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x3028000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+ arm,scatter-gather;
+
+ in-ports {
+ port {
+ etr_in: endpoint {
+ remote-endpoint =
+ <&replicator_out0>;
+ };
+ };
+ };
+ };
+
+ debug@3810000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x3810000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU0>;
+ };
+
+ etm@3840000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x3840000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU0>;
+
+ out-ports {
+ port {
+ etm0_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in0>;
+ };
+ };
+ };
+ };
+
+ debug@3910000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x3910000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU1>;
+ };
+
+ etm@3940000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x3940000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU1>;
+
+ out-ports {
+ port {
+ etm1_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@39b0000 { /* APSS Funnel 0 */
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x39b0000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel0_in0: endpoint {
+ remote-endpoint = <&etm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel0_in1: endpoint {
+ remote-endpoint = <&etm1_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ apss_funnel0_out: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ debug@3a10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x3a10000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU2>;
+ };
+
+ etm@3a40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x3a40000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU2>;
+
+ out-ports {
+ port {
+ etm2_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_in0>;
+ };
+ };
+ };
+ };
+
+ debug@3b10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x3b10000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU3>;
+ };
+
+ etm@3b40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x3b40000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU3>;
+
+ out-ports {
+ port {
+ etm3_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@3bb0000 { /* APSS Funnel 1 */
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3bb0000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel1_in0: endpoint {
+ remote-endpoint = <&etm2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel1_in1: endpoint {
+ remote-endpoint = <&etm3_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ apss_funnel1_out: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@3bc0000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x3bc0000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_merge_funnel_in0: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_merge_funnel_in1: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_out>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ apss_merge_funnel_out: endpoint {
+ remote-endpoint =
+ <&funnel1_in>;
+ };
+ };
+ };
+ };
+
kryocc: clock-controller@6400000 {
compatible = "qcom,apcc-msm8996";
reg = <0x6400000 0x90000>;
@@ -1163,7 +1631,7 @@
};
};
- vfe_smmu: arm,smmu@da0000 {
+ vfe_smmu: iommu@da0000 {
compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
reg = <0xda0000 0x10000>;
@@ -1314,7 +1782,7 @@
};
};
- adreno_smmu: arm,smmu@b40000 {
+ adreno_smmu: iommu@b40000 {
compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
reg = <0xb40000 0x10000>;
@@ -1331,7 +1799,7 @@
power-domains = <&mmcc GPU_GDSC>;
};
- mdp_smmu: arm,smmu@d00000 {
+ mdp_smmu: iommu@d00000 {
compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
reg = <0xd00000 0x10000>;
@@ -1347,7 +1815,7 @@
power-domains = <&mmcc MDSS_GDSC>;
};
- lpass_q6_smmu: arm,smmu-lpass_q6@1600000 {
+ lpass_q6_smmu: iommu@1600000 {
compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
reg = <0x1600000 0x20000>;
#iommu-cells = <1>;
@@ -1794,6 +2262,74 @@
"ref";
};
};
+
+ venus_smmu: arm,smmu-venus@d40000 {
+ compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+ reg = <0xd40000 0x20000>;
+ #global-interrupts = <1>;
+ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&mmcc MMAGIC_VIDEO_GDSC>;
+ clocks = <&mmcc SMMU_VIDEO_AHB_CLK>,
+ <&mmcc SMMU_VIDEO_AXI_CLK>;
+ clock-names = "iface", "bus";
+ #iommu-cells = <1>;
+ status = "okay";
+ };
+
+ video-codec@c00000 {
+ compatible = "qcom,msm8996-venus";
+ reg = <0x00c00000 0xff000>;
+ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&mmcc VENUS_GDSC>;
+ clocks = <&mmcc VIDEO_CORE_CLK>,
+ <&mmcc VIDEO_AHB_CLK>,
+ <&mmcc VIDEO_AXI_CLK>,
+ <&mmcc VIDEO_MAXI_CLK>;
+ clock-names = "core", "iface", "bus", "mbus";
+ iommus = <&venus_smmu 0x00>,
+ <&venus_smmu 0x01>,
+ <&venus_smmu 0x0a>,
+ <&venus_smmu 0x07>,
+ <&venus_smmu 0x0e>,
+ <&venus_smmu 0x0f>,
+ <&venus_smmu 0x08>,
+ <&venus_smmu 0x09>,
+ <&venus_smmu 0x0b>,
+ <&venus_smmu 0x0c>,
+ <&venus_smmu 0x0d>,
+ <&venus_smmu 0x10>,
+ <&venus_smmu 0x11>,
+ <&venus_smmu 0x21>,
+ <&venus_smmu 0x28>,
+ <&venus_smmu 0x29>,
+ <&venus_smmu 0x2b>,
+ <&venus_smmu 0x2c>,
+ <&venus_smmu 0x2d>,
+ <&venus_smmu 0x31>;
+ memory-region = <&venus_region>;
+ status = "okay";
+
+ video-decoder {
+ compatible = "venus-decoder";
+ clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
+ clock-names = "core";
+ power-domains = <&mmcc VENUS_CORE0_GDSC>;
+ };
+
+ video-encoder {
+ compatible = "venus-encoder";
+ clocks = <&mmcc VIDEO_SUBCORE1_CLK>;
+ clock-names = "core";
+ power-domains = <&mmcc VENUS_CORE1_GDSC>;
+ };
+ };
};
sound: sound {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts b/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts
new file mode 100644
index 000000000000..db5821be1e2f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */
+
+/dts-v1/;
+
+#include "msm8998-clamshell.dtsi"
+
+/ {
+ model = "Asus NovaGo TP370QL";
+ compatible = "asus,novago-tp370ql", "qcom,msm8998";
+};
+
+&blsp1_i2c6 {
+ status = "okay";
+
+ touchpad@15 {
+ compatible = "hid-over-i2c";
+ interrupt-parent = <&tlmm>;
+ interrupts = <0x7b IRQ_TYPE_LEVEL_LOW>;
+ reg = <0x15>;
+ hid-descr-addr = <0x0001>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchpad>;
+ };
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ interrupt-parent = <&tlmm>;
+ interrupts = <0x25 IRQ_TYPE_LEVEL_LOW>;
+ reg = <0x3a>;
+ hid-descr-addr = <0x0001>;
+ };
+};
+
+&sdhc2 {
+ cd-gpios = <&tlmm 95 GPIO_ACTIVE_HIGH>;
+};
+
+&tlmm {
+ touchpad: touchpad {
+ config {
+ pins = "gpio123";
+ bias-pull-up;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
new file mode 100644
index 000000000000..9682d4dd7496
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */
+
+/*
+ * Common include for MSM8998 clamshell devices, ie the Lenovo Miix 630,
+ * Asus NovaGo TP370QL, and HP Envy x2. All three devices are basically the
+ * same, with differences in peripherals.
+ */
+
+#include "msm8998.dtsi"
+#include "pm8998.dtsi"
+#include "pm8005.dtsi"
+
+/ {
+ chosen {
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&qusb2phy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+};
+
+&rpm_requests {
+ pm8998-regulators {
+ compatible = "qcom,rpm-pm8998-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+ vdd_s7-supply = <&vph_pwr>;
+ vdd_s8-supply = <&vph_pwr>;
+ vdd_s9-supply = <&vph_pwr>;
+ vdd_s10-supply = <&vph_pwr>;
+ vdd_s11-supply = <&vph_pwr>;
+ vdd_s12-supply = <&vph_pwr>;
+ vdd_s13-supply = <&vph_pwr>;
+ vdd_l1_l27-supply = <&vreg_s7a_1p025>;
+ vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>;
+ vdd_l3_l11-supply = <&vreg_s7a_1p025>;
+ vdd_l4_l5-supply = <&vreg_s7a_1p025>;
+ vdd_l6-supply = <&vreg_s5a_2p04>;
+ vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>;
+ vdd_l9-supply = <&vph_pwr>;
+ vdd_l10_l23_l25-supply = <&vph_pwr>;
+ vdd_l13_l19_l21-supply = <&vph_pwr>;
+ vdd_l16_l28-supply = <&vph_pwr>;
+ vdd_l18_l22-supply = <&vph_pwr>;
+ vdd_l20_l24-supply = <&vph_pwr>;
+ vdd_l26-supply = <&vreg_s3a_1p35>;
+ vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>;
+
+ vreg_s3a_1p35: s3 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ };
+ vreg_s4a_1p8: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ };
+ vreg_s5a_2p04: s5 {
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2040000>;
+ };
+ vreg_s7a_1p025: s7 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1028000>;
+ };
+ vreg_l1a_0p875: l1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-allow-set-load;
+ };
+ vreg_l2a_1p2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-allow-set-load;
+ };
+ vreg_l3a_1p0: l3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+ vreg_l5a_0p8: l5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+ vreg_l6a_1p8: l6 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <1808000>;
+ };
+ vreg_l7a_1p8: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ vreg_l8a_1p2: l8 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+ vreg_l9a_1p8: l9 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+ vreg_l10a_1p8: l10 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+ vreg_l11a_1p0: l11 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+ vreg_l12a_1p8: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ vreg_l13a_2p95: l13 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+ vreg_l14a_1p88: l14 {
+ regulator-min-microvolt = <1880000>;
+ regulator-max-microvolt = <1880000>;
+ };
+ vreg_15a_1p8: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ vreg_l16a_2p7: l16 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ };
+ vreg_l17a_1p3: l17 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ };
+ vreg_l18a_2p7: l18 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ };
+ vreg_l19a_3p0: l19 {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ };
+ vreg_l20a_2p95: l20 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-allow-set-load;
+ };
+ vreg_l21a_2p95: l21 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-allow-set-load;
+ regulator-system-load = <800000>;
+ };
+ vreg_l22a_2p85: l22 {
+ regulator-min-microvolt = <2864000>;
+ regulator-max-microvolt = <2864000>;
+ };
+ vreg_l23a_3p3: l23 {
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
+ };
+ vreg_l24a_3p075: l24 {
+ regulator-min-microvolt = <3088000>;
+ regulator-max-microvolt = <3088000>;
+ };
+ vreg_l25a_3p3: l25 {
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3312000>;
+ };
+ vreg_l26a_1p2: l26 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+ vreg_l28_3p0: l28 {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ };
+
+ vreg_lvs1a_1p8: lvs1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_lvs2a_1p8: lvs2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ touchpad: touchpad {
+ config {
+ pins = "gpio123";
+ bias-pull-up; /* pull up */
+ };
+ };
+};
+
+&sdhc2 {
+ status = "okay";
+
+ vmmc-supply = <&vreg_l21a_2p95>;
+ vqmmc-supply = <&vreg_l13a_2p95>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+};
+
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ dr_mode = "host"; /* Force to host until we have Type-C hooked up */
+};
+
+&usb3phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l2a_1p2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts b/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts
new file mode 100644
index 000000000000..24073127091f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */
+
+/dts-v1/;
+
+#include "msm8998-clamshell.dtsi"
+
+/ {
+ model = "HP Envy x2";
+ compatible = "hp,envy-x2", "qcom,msm8998";
+};
+
+&blsp1_i2c6 {
+ status = "okay";
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ interrupt-parent = <&tlmm>;
+ interrupts = <0x79 IRQ_TYPE_LEVEL_LOW>;
+ reg = <0x3a>;
+ hid-descr-addr = <0x0001>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchpad>;
+ };
+};
+
+&sdhc2 {
+ cd-gpios = <&tlmm 95 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
new file mode 100644
index 000000000000..407c6a32911c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */
+
+/dts-v1/;
+
+#include "msm8998-clamshell.dtsi"
+
+/ {
+ model = "Lenovo Miix 630";
+ compatible = "lenovo,miix-630", "qcom,msm8998";
+};
+
+&blsp1_i2c6 {
+ status = "okay";
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ interrupt-parent = <&tlmm>;
+ interrupts = <0x79 IRQ_TYPE_LEVEL_LOW>;
+ reg = <0x3a>;
+ hid-descr-addr = <0x0001>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchpad>;
+ };
+};
+
+&sdhc2 {
+ cd-gpios = <&tlmm 95 GPIO_ACTIVE_HIGH>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index c13ed7aeb1e0..c6f81431983e 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -787,14 +787,22 @@
ranges = <0 0 0 0xffffffff>;
compatible = "simple-bus";
- rpm_msg_ram: memory@68000 {
+ gcc: clock-controller@100000 {
+ compatible = "qcom,gcc-msm8998";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ reg = <0x00100000 0xb0000>;
+ };
+
+ rpm_msg_ram: memory@778000 {
compatible = "qcom,rpm-msg-ram";
- reg = <0x778000 0x7000>;
+ reg = <0x00778000 0x7000>;
};
qfprom: qfprom@780000 {
compatible = "qcom,qfprom";
- reg = <0x780000 0x621c>;
+ reg = <0x00780000 0x621c>;
#address-cells = <1>;
#size-cells = <1>;
@@ -804,47 +812,10 @@
};
};
- gcc: clock-controller@100000 {
- compatible = "qcom,gcc-msm8998";
- #clock-cells = <1>;
- #reset-cells = <1>;
- #power-domain-cells = <1>;
- reg = <0x100000 0xb0000>;
- };
-
- tlmm: pinctrl@3400000 {
- compatible = "qcom,msm8998-pinctrl";
- reg = <0x3400000 0xc00000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <0x2>;
- interrupt-controller;
- #interrupt-cells = <0x2>;
- };
-
- spmi_bus: spmi@800f000 {
- compatible = "qcom,spmi-pmic-arb";
- reg = <0x800f000 0x1000>,
- <0x8400000 0x1000000>,
- <0x9400000 0x1000000>,
- <0xa400000 0x220000>,
- <0x800a000 0x3000>;
- reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
- interrupt-names = "periph_irq";
- interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>;
- qcom,ee = <0>;
- qcom,channel = <0>;
- #address-cells = <2>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <4>;
- cell-index = <0>;
- };
-
tsens0: thermal@10ab000 {
compatible = "qcom,msm8998-tsens", "qcom,tsens-v2";
- reg = <0x10ab000 0x1000>, /* TM */
- <0x10aa000 0x1000>; /* SROT */
+ reg = <0x010ab000 0x1000>, /* TM */
+ <0x010aa000 0x1000>; /* SROT */
#qcom,sensors = <14>;
#thermal-sensor-cells = <1>;
@@ -852,8 +823,8 @@
tsens1: thermal@10ae000 {
compatible = "qcom,msm8998-tsens", "qcom,tsens-v2";
- reg = <0x10ae000 0x1000>, /* TM */
- <0x10ad000 0x1000>; /* SROT */
+ reg = <0x010ae000 0x1000>, /* TM */
+ <0x010ad000 0x1000>; /* SROT */
#qcom,sensors = <8>;
#thermal-sensor-cells = <1>;
@@ -943,16 +914,542 @@
};
};
+ ufshc: ufshc@1da4000 {
+ compatible = "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
+ reg = <0x01da4000 0x2500>;
+ interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&ufsphy_lanes>;
+ phy-names = "ufsphy";
+ lanes-per-direction = <2>;
+ power-domains = <&gcc UFS_GDSC>;
+ #reset-cells = <1>;
+
+ clock-names =
+ "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk",
+ "rx_lane1_sync_clk";
+ clocks =
+ <&gcc GCC_UFS_AXI_CLK>,
+ <&gcc GCC_AGGRE1_UFS_AXI_CLK>,
+ <&gcc GCC_UFS_AHB_CLK>,
+ <&gcc GCC_UFS_UNIPRO_CORE_CLK>,
+ <&rpmcc RPM_SMD_LN_BB_CLK1>,
+ <&gcc GCC_UFS_TX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_RX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_RX_SYMBOL_1_CLK>;
+ freq-table-hz =
+ <50000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <37500000 150000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <0 0>;
+
+ resets = <&gcc GCC_UFS_BCR>;
+ reset-names = "rst";
+ };
+
+ ufsphy: phy@1da7000 {
+ compatible = "qcom,msm8998-qmp-ufs-phy";
+ reg = <0x01da7000 0x18c>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clock-names =
+ "ref",
+ "ref_aux";
+ clocks =
+ <&gcc GCC_UFS_CLKREF_CLK>,
+ <&gcc GCC_UFS_PHY_AUX_CLK>;
+
+ reset-names = "ufsphy";
+ resets = <&ufshc 0>;
+
+ ufsphy_lanes: lanes@1da7400 {
+ reg = <0x01da7400 0x128>,
+ <0x01da7600 0x1fc>,
+ <0x01da7c00 0x1dc>,
+ <0x01da7800 0x128>,
+ <0x01da7a00 0x1fc>;
+ #phy-cells = <0>;
+ };
+ };
+
tcsr_mutex_regs: syscon@1f40000 {
compatible = "syscon";
- reg = <0x1f40000 0x20000>;
+ reg = <0x01f40000 0x20000>;
};
- apcs_glb: mailbox@9820000 {
- compatible = "qcom,msm8998-apcs-hmss-global";
- reg = <0x17911000 0x1000>;
+ tlmm: pinctrl@3400000 {
+ compatible = "qcom,msm8998-pinctrl";
+ reg = <0x03400000 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <0x2>;
+ interrupt-controller;
+ #interrupt-cells = <0x2>;
+ };
- #mbox-cells = <1>;
+ stm@6002000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0x06002000 0x1000>,
+ <0x16280000 0x180000>;
+ reg-names = "stm-base", "stm-data-base";
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint = <&funnel0_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@6041000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x06041000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ funnel0_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+ funnel0_in7: endpoint {
+ remote-endpoint = <&stm_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6042000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x06042000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ funnel1_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in1>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@6 {
+ reg = <6>;
+ funnel1_in6: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6045000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x06045000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ merge_funnel_out: endpoint {
+ remote-endpoint =
+ <&etf_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ merge_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ merge_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel1_out>;
+ };
+ };
+ };
+ };
+
+ replicator@6046000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0x06046000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ replicator_out: endpoint {
+ remote-endpoint = <&etr_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ replicator_in: endpoint {
+ remote-endpoint = <&etf_out>;
+ };
+ };
+ };
+ };
+
+ etf@6047000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x06047000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ etf_out: endpoint {
+ remote-endpoint =
+ <&replicator_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ etf_in: endpoint {
+ remote-endpoint =
+ <&merge_funnel_out>;
+ };
+ };
+ };
+ };
+
+ etr@6048000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x06048000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+ arm,scatter-gather;
+
+ in-ports {
+ port {
+ etr_in: endpoint {
+ remote-endpoint =
+ <&replicator_out>;
+ };
+ };
+ };
+ };
+
+ etm@7840000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07840000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU0>;
+
+ out-ports {
+ port {
+ etm0_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ etm@7940000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07940000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU1>;
+
+ out-ports {
+ port {
+ etm1_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ etm@7a40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07a40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU2>;
+
+ out-ports {
+ port {
+ etm2_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in2>;
+ };
+ };
+ };
+ };
+
+ etm@7b40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07b40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU3>;
+
+ out-ports {
+ port {
+ etm3_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in3>;
+ };
+ };
+ };
+ };
+
+ funnel@7b60000 { /* APSS Funnel */
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07b60000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ apss_funnel_out: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel_in0: endpoint {
+ remote-endpoint =
+ <&etm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel_in1: endpoint {
+ remote-endpoint =
+ <&etm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ apss_funnel_in2: endpoint {
+ remote-endpoint =
+ <&etm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_funnel_in3: endpoint {
+ remote-endpoint =
+ <&etm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ apss_funnel_in4: endpoint {
+ remote-endpoint =
+ <&etm4_out>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ apss_funnel_in5: endpoint {
+ remote-endpoint =
+ <&etm5_out>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ apss_funnel_in6: endpoint {
+ remote-endpoint =
+ <&etm6_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ apss_funnel_in7: endpoint {
+ remote-endpoint =
+ <&etm7_out>;
+ };
+ };
+ };
+ };
+
+ funnel@7b70000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x07b70000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ out-ports {
+ port {
+ apss_merge_funnel_out: endpoint {
+ remote-endpoint =
+ <&funnel1_in6>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ apss_merge_funnel_in: endpoint {
+ remote-endpoint =
+ <&apss_funnel_out>;
+ };
+ };
+ };
+ };
+
+ etm@7c40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07c40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU4>;
+
+ port{
+ etm4_out: endpoint {
+ remote-endpoint = <&apss_funnel_in4>;
+ };
+ };
+ };
+
+ etm@7d40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07d40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU5>;
+
+ port{
+ etm5_out: endpoint {
+ remote-endpoint = <&apss_funnel_in5>;
+ };
+ };
+ };
+
+ etm@7e40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07e40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU6>;
+
+ port{
+ etm6_out: endpoint {
+ remote-endpoint = <&apss_funnel_in6>;
+ };
+ };
+ };
+
+ etm@7f40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x07f40000 0x1000>;
+
+ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU7>;
+
+ port{
+ etm7_out: endpoint {
+ remote-endpoint = <&apss_funnel_in7>;
+ };
+ };
+ };
+
+ spmi_bus: spmi@800f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x0800f000 0x1000>,
+ <0x08400000 0x1000000>,
+ <0x09400000 0x1000000>,
+ <0x0a400000 0x220000>,
+ <0x0800a000 0x3000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
};
usb3: usb@a8f8800 {
@@ -1044,7 +1541,7 @@
sdhc2: sdhci@c0a4900 {
compatible = "qcom,sdhci-msm-v4";
- reg = <0xc0a4900 0x314>, <0xc0a4000 0x800>;
+ reg = <0x0c0a4900 0x314>, <0x0c0a4000 0x800>;
reg-names = "hc_mem", "core_mem";
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
@@ -1149,6 +1646,16 @@
#size-cells = <0>;
};
+ blsp2_uart1: serial@c1b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x0c1b0000 0x1000>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>,
+ <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+ };
+
blsp2_i2c0: i2c@c1b5000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x0c1b5000 0x600>;
@@ -1239,14 +1746,11 @@
#size-cells = <0>;
};
- blsp2_uart1: serial@c1b0000 {
- compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
- reg = <0xc1b0000 0x1000>;
- interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>,
- <&gcc GCC_BLSP2_AHB_CLK>;
- clock-names = "core", "iface";
- status = "disabled";
+ apcs_glb: mailbox@17911000 {
+ compatible = "qcom,msm8998-apcs-hmss-global";
+ reg = <0x17911000 0x1000>;
+
+ #mbox-cells = <1>;
};
timer@17920000 {
@@ -1320,75 +1824,6 @@
redistributor-stride = <0x0 0x20000>;
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
-
- ufshc: ufshc@1da4000 {
- compatible = "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
- reg = <0x01da4000 0x2500>;
- interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
- phys = <&ufsphy_lanes>;
- phy-names = "ufsphy";
- lanes-per-direction = <2>;
- power-domains = <&gcc UFS_GDSC>;
- #reset-cells = <1>;
-
- clock-names =
- "core_clk",
- "bus_aggr_clk",
- "iface_clk",
- "core_clk_unipro",
- "ref_clk",
- "tx_lane0_sync_clk",
- "rx_lane0_sync_clk",
- "rx_lane1_sync_clk";
- clocks =
- <&gcc GCC_UFS_AXI_CLK>,
- <&gcc GCC_AGGRE1_UFS_AXI_CLK>,
- <&gcc GCC_UFS_AHB_CLK>,
- <&gcc GCC_UFS_UNIPRO_CORE_CLK>,
- <&rpmcc RPM_SMD_LN_BB_CLK1>,
- <&gcc GCC_UFS_TX_SYMBOL_0_CLK>,
- <&gcc GCC_UFS_RX_SYMBOL_0_CLK>,
- <&gcc GCC_UFS_RX_SYMBOL_1_CLK>;
- freq-table-hz =
- <50000000 200000000>,
- <0 0>,
- <0 0>,
- <37500000 150000000>,
- <0 0>,
- <0 0>,
- <0 0>,
- <0 0>;
-
- resets = <&gcc GCC_UFS_BCR>;
- reset-names = "rst";
- };
-
- ufsphy: phy@1da7000 {
- compatible = "qcom,msm8998-qmp-ufs-phy";
- reg = <0x01da7000 0x18c>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- clock-names =
- "ref",
- "ref_aux";
- clocks =
- <&gcc GCC_UFS_CLKREF_CLK>,
- <&gcc GCC_UFS_PHY_AUX_CLK>;
-
- reset-names = "ufsphy";
- resets = <&ufshc 0>;
-
- ufsphy_lanes: lanes@1da7400 {
- reg = <0x01da7400 0x128>,
- <0x01da7600 0x1fc>,
- <0x01da7c00 0x1dc>,
- <0x01da7800 0x128>,
- <0x01da7a00 0x1fc>;
- #phy-cells = <0>;
- };
- };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8150.dtsi b/arch/arm64/boot/dts/qcom/pm8150.dtsi
new file mode 100644
index 000000000000..b6e304748a57
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8150.dtsi
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+
+&spmi_bus {
+ pm8150_0: pmic@0 {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pon: power-on@800 {
+ compatible = "qcom,pm8916-pon";
+ reg = <0x0800>;
+ pwrkey {
+ compatible = "qcom,pm8941-pwrkey";
+ interrupts = <0x0 0x8 0x0 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_POWER>;
+
+ status = "disabled";
+ };
+ };
+
+ pm8150_adc: adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ reg = <0x3100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ ref-gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,pre-scaling = <1 1>;
+ label = "ref_gnd";
+ };
+
+ vref-1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,pre-scaling = <1 1>;
+ label = "vref_1p25";
+ };
+
+ die-temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ label = "die_temp";
+ };
+ };
+
+ rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+
+ status = "disabled";
+ };
+
+ pm8150_gpios: gpio@c000 {
+ compatible = "qcom,pm8150-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <0x0 0xc0 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc1 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc2 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc3 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc4 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc5 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc6 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc7 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc8 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xc9 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xca 0x0 IRQ_TYPE_NONE>,
+ <0x0 0xcb 0x0 IRQ_TYPE_NONE>;
+ };
+ };
+
+ pmic@1 {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0x1 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
new file mode 100644
index 000000000000..322379d5c31f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+ pmic@2 {
+ compatible = "qcom,pm8150b", "qcom,spmi-pmic";
+ reg = <0x2 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-on@800 {
+ compatible = "qcom,pm8916-pon";
+ reg = <0x0800>;
+
+ status = "disabled";
+ };
+
+ adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ reg = <0x3100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ ref-gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,pre-scaling = <1 1>;
+ label = "ref_gnd";
+ };
+
+ vref-1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,pre-scaling = <1 1>;
+ label = "vref_1p25";
+ };
+
+ die-temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ label = "die_temp";
+ };
+
+ chg-temp@9 {
+ reg = <ADC5_CHG_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ label = "chg_temp";
+ };
+ };
+
+ pm8150b_gpios: gpio@c000 {
+ compatible = "qcom,pm8150b-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <0x2 0xc0 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc1 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc2 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc3 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc4 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc5 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc6 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc7 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc8 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xc9 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xca 0x0 IRQ_TYPE_NONE>,
+ <0x2 0xcb 0x0 IRQ_TYPE_NONE>;
+ };
+ };
+
+ pmic@3 {
+ compatible = "qcom,pm8150b", "qcom,spmi-pmic";
+ reg = <0x3 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
new file mode 100644
index 000000000000..eb0e9a090e42
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+ pmic@4 {
+ compatible = "qcom,pm8150l", "qcom,spmi-pmic";
+ reg = <0x4 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-on@800 {
+ compatible = "qcom,pm8916-pon";
+ reg = <0x0800>;
+
+ status = "disabled";
+ };
+
+ adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ reg = <0x3100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ interrupts = <0x4 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ ref-gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,pre-scaling = <1 1>;
+ label = "ref_gnd";
+ };
+
+ vref-1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,pre-scaling = <1 1>;
+ label = "vref_1p25";
+ };
+
+ die-temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ label = "die_temp";
+ };
+ };
+
+ pm8150l_gpios: gpio@c000 {
+ compatible = "qcom,pm8150l-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <0x4 0xc0 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc1 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc2 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc3 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc4 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc5 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc6 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc7 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc8 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xc9 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xca 0x0 IRQ_TYPE_NONE>,
+ <0x4 0xcb 0x0 IRQ_TYPE_NONE>;
+ };
+ };
+
+ pmic@5 {
+ compatible = "qcom,pm8150l", "qcom,spmi-pmic";
+ reg = <0x5 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index 051a52df80f9..dc2ce23cde05 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -78,7 +78,7 @@
#size-cells = <0>;
#io-channel-cells = <1>;
- adc-chan@ADC5_DIE_TEMP {
+ adc-chan@6 {
reg = <ADC5_DIE_TEMP>;
label = "die_temp";
};
diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi
index 14240fedd916..ff4005186895 100644
--- a/arch/arm64/boot/dts/qcom/pms405.dtsi
+++ b/arch/arm64/boot/dts/qcom/pms405.dtsi
@@ -88,41 +88,41 @@
#size-cells = <0>;
#io-channel-cells = <1>;
- ref_gnd {
+ ref_gnd@0 {
reg = <ADC5_REF_GND>;
qcom,pre-scaling = <1 1>;
};
- vref_1p25 {
+ vref_1p25@1 {
reg = <ADC5_1P25VREF>;
qcom,pre-scaling = <1 1>;
};
- pon_1: vph_pwr {
+ pon_1: vph_pwr@131 {
reg = <ADC5_VPH_PWR>;
qcom,pre-scaling = <1 3>;
};
- die_temp {
+ die_temp@6 {
reg = <ADC5_DIE_TEMP>;
qcom,pre-scaling = <1 1>;
};
- pa_therm1: thermistor1 {
+ pa_therm1: thermistor1@77 {
reg = <ADC5_AMUX_THM1_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
qcom,pre-scaling = <1 1>;
};
- pa_therm3: thermistor3 {
+ pa_therm3: thermistor3@79 {
reg = <ADC5_AMUX_THM3_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
qcom,pre-scaling = <1 1>;
};
- xo_therm: xo_temp {
+ xo_therm: xo_temp@76 {
reg = <ADC5_XO_THERM_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
@@ -141,8 +141,6 @@
pms405_1: pms405@1 {
compatible = "qcom,spmi-pmic";
reg = <0x1 SPMI_USID>;
- #address-cells = <1>;
- #size-cells = <0>;
pms405_spmi_regulators: regulators {
compatible = "qcom,pms405-regulators";
diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
index 11c0a7137823..501a7330dbc8 100644
--- a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
@@ -61,7 +61,9 @@
protected-clocks = <GCC_BIMC_CDSP_CLK>,
<GCC_CDSP_CFG_AHB_CLK>,
<GCC_CDSP_BIMC_CLK_SRC>,
- <GCC_CDSP_TBU_CLK>;
+ <GCC_CDSP_TBU_CLK>,
+ <141>, /* GCC_WCSS_Q6_AHB_CLK */
+ <142>; /* GCC_WCSS_Q6_AXIM_CLK */
};
&pms405_spmi_regulators {
@@ -270,6 +272,9 @@
&wifi {
status = "okay";
+ vdd-0.8-cx-mx-supply = <&vreg_l2_1p275>;
+ vdd-1.8-xo-supply = <&vreg_l5_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l1_1p3>;
};
/* PINCTRL - additions to nodes defined in qcs404.dtsi */
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index 3d0789775009..a97eeb4569c0 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -111,8 +111,13 @@
#size-cells = <2>;
ranges;
- memory@85600000 {
- reg = <0 0x85600000 0 0x90000>;
+ tz_apps_mem: memory@85900000 {
+ reg = <0 0x85900000 0 0x500000>;
+ no-map;
+ };
+
+ xbl_mem: memory@85e00000 {
+ reg = <0 0x85e00000 0 0x100000>;
no-map;
};
@@ -121,28 +126,33 @@
no-map;
};
- memory@86100000 {
+ tz_mem: memory@86100000 {
reg = <0 0x86100000 0 0x300000>;
no-map;
};
wlan_fw_mem: memory@86400000 {
- reg = <0 0x86400000 0 0x1c00000>;
+ reg = <0 0x86400000 0 0x1100000>;
+ no-map;
+ };
+
+ adsp_fw_mem: memory@87500000 {
+ reg = <0 0x87500000 0 0x1a00000>;
no-map;
};
- adsp_fw_mem: memory@88000000 {
- reg = <0 0x88000000 0 0x1a00000>;
+ cdsp_fw_mem: memory@88f00000 {
+ reg = <0 0x88f00000 0 0x600000>;
no-map;
};
- cdsp_fw_mem: memory@89a00000 {
- reg = <0 0x89a00000 0 0x600000>;
+ wlan_msa_mem: memory@89500000 {
+ reg = <0 0x89500000 0 0x100000>;
no-map;
};
- wlan_msa_mem: memory@8a000000 {
- reg = <0 0x8a000000 0 0x100000>;
+ uefi_mem: memory@9f800000 {
+ reg = <0 0x9f800000 0 0x800000>;
no-map;
};
};
@@ -1077,7 +1087,7 @@
thermal-sensors = <&tsens 0>;
trips {
- aoss_alert0: trip-point@0 {
+ aoss_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <2000>;
type = "hot";
@@ -1092,7 +1102,7 @@
thermal-sensors = <&tsens 1>;
trips {
- q6_hvx_alert0: trip-point@0 {
+ q6_hvx_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <2000>;
type = "hot";
@@ -1107,7 +1117,7 @@
thermal-sensors = <&tsens 2>;
trips {
- lpass_alert0: trip-point@0 {
+ lpass_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <2000>;
type = "hot";
@@ -1122,7 +1132,7 @@
thermal-sensors = <&tsens 3>;
trips {
- wlan_alert0: trip-point@0 {
+ wlan_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <2000>;
type = "hot";
@@ -1137,12 +1147,12 @@
thermal-sensors = <&tsens 4>;
trips {
- cluster_alert0: trip-point@0 {
+ cluster_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
};
- cluster_alert1: trip-point@1 {
+ cluster_alert1: trip-point1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
@@ -1171,12 +1181,12 @@
thermal-sensors = <&tsens 5>;
trips {
- cpu0_alert0: trip-point@0 {
+ cpu0_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
};
- cpu0_alert1: trip-point@1 {
+ cpu0_alert1: trip-point1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
@@ -1205,12 +1215,12 @@
thermal-sensors = <&tsens 6>;
trips {
- cpu1_alert0: trip-point@0 {
+ cpu1_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
};
- cpu1_alert1: trip-point@1 {
+ cpu1_alert1: trip-point1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
@@ -1239,12 +1249,12 @@
thermal-sensors = <&tsens 7>;
trips {
- cpu2_alert0: trip-point@0 {
+ cpu2_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
};
- cpu2_alert1: trip-point@1 {
+ cpu2_alert1: trip-point1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
@@ -1273,12 +1283,12 @@
thermal-sensors = <&tsens 8>;
trips {
- cpu3_alert0: trip-point@0 {
+ cpu3_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
};
- cpu3_alert1: trip-point@1 {
+ cpu3_alert1: trip-point1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
@@ -1307,7 +1317,7 @@
thermal-sensors = <&tsens 9>;
trips {
- gpu_alert0: trip-point@0 {
+ gpu_alert0: trip-point0 {
temperature = <95000>;
hysteresis = <2000>;
type = "hot";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
index 1ebbd568dfd7..34881c0113cb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -745,7 +745,7 @@ ap_ts_i2c: &i2c14 {
* All the hardware muxes would allow us to hook things up in different
* ways to some potential benefit for static configurations (you could
* achieve extra USB2 bandwidth by using two different ports for the
- * two conenctors or possibly even get USB3 peripheral mode), but in
+ * two connectors or possibly even get USB3 peripheral mode), but in
* each case you end up forcing to disconnect/reconnect an in-use
* USB session in some cases depending on what you hotplug into the
* other connector. Thus hardcoding this as peripheral makes sense.
@@ -963,27 +963,27 @@ ap_ts_i2c: &i2c14 {
};
&pm8998_adc {
- adc-chan@ADC5_AMUX_THM1_100K_PU {
+ adc-chan@4d {
reg = <ADC5_AMUX_THM1_100K_PU>;
label = "sdm_temp";
};
- adc-chan@ADC5_AMUX_THM2_100K_PU {
+ adc-chan@4e {
reg = <ADC5_AMUX_THM2_100K_PU>;
label = "quiet_temp";
};
- adc-chan@ADC5_AMUX_THM3_100K_PU {
+ adc-chan@4f {
reg = <ADC5_AMUX_THM3_100K_PU>;
label = "lte_temp_1";
};
- adc-chan@ADC5_AMUX_THM4_100K_PU {
+ adc-chan@50 {
reg = <ADC5_AMUX_THM4_100K_PU>;
label = "lte_temp_2";
};
- adc-chan@ADC5_AMUX_THM5_100K_PU {
+ adc-chan@51 {
reg = <ADC5_AMUX_THM5_100K_PU>;
label = "charger_temp";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 4babff5f19b5..f406a4340b05 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -194,6 +194,7 @@
&LITTLE_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <607>;
+ dynamic-power-coefficient = <100>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
next-level-cache = <&L2_0>;
@@ -215,6 +216,7 @@
&LITTLE_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <607>;
+ dynamic-power-coefficient = <100>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
next-level-cache = <&L2_100>;
@@ -233,6 +235,7 @@
&LITTLE_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <607>;
+ dynamic-power-coefficient = <100>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
next-level-cache = <&L2_200>;
@@ -251,6 +254,7 @@
&LITTLE_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <607>;
+ dynamic-power-coefficient = <100>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
next-level-cache = <&L2_300>;
@@ -269,6 +273,7 @@
cpu-idle-states = <&BIG_CPU_SLEEP_0
&BIG_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
+ dynamic-power-coefficient = <396>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
next-level-cache = <&L2_400>;
@@ -287,6 +292,7 @@
cpu-idle-states = <&BIG_CPU_SLEEP_0
&BIG_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
+ dynamic-power-coefficient = <396>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
next-level-cache = <&L2_500>;
@@ -305,6 +311,7 @@
cpu-idle-states = <&BIG_CPU_SLEEP_0
&BIG_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
+ dynamic-power-coefficient = <396>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
next-level-cache = <&L2_600>;
@@ -323,6 +330,7 @@
cpu-idle-states = <&BIG_CPU_SLEEP_0
&BIG_CPU_SLEEP_1
&CLUSTER_SLEEP_0>;
+ dynamic-power-coefficient = <396>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
next-level-cache = <&L2_700>;
@@ -483,6 +491,25 @@
label = "lpass";
qcom,remote-pid = <2>;
mboxes = <&apss_shared 8>;
+ 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 0x1823 0x0>;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x1824 0x0>;
+ };
+ };
};
};
@@ -512,6 +539,61 @@
label = "turing";
qcom,remote-pid = <5>;
mboxes = <&apss_shared 4>;
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,glink-channels = "fastrpcglink-apps-dsp";
+ label = "cdsp";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compute-cb@1 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <1>;
+ iommus = <&apps_smmu 0x1401 0x30>;
+ };
+
+ compute-cb@2 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <2>;
+ iommus = <&apps_smmu 0x1402 0x30>;
+ };
+
+ compute-cb@3 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <3>;
+ iommus = <&apps_smmu 0x1403 0x30>;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x1404 0x30>;
+ };
+
+ compute-cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&apps_smmu 0x1405 0x30>;
+ };
+
+ compute-cb@6 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <6>;
+ iommus = <&apps_smmu 0x1406 0x30>;
+ };
+
+ compute-cb@7 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <7>;
+ iommus = <&apps_smmu 0x1407 0x30>;
+ };
+
+ compute-cb@8 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <8>;
+ iommus = <&apps_smmu 0x1408 0x30>;
+ };
+ };
};
};
@@ -620,7 +702,7 @@
method = "smc";
};
- soc: soc {
+ soc: soc@0 {
#address-cells = <2>;
#size-cells = <2>;
ranges = <0 0 0 0 0x10 0>;
@@ -1275,6 +1357,13 @@
};
};
+ cache-controller@1100000 {
+ compatible = "qcom,sdm845-llcc";
+ reg = <0 0x01100000 0 0x200000>, <0 0x01300000 0 0x50000>;
+ reg-names = "llcc_base", "llcc_broadcast_base";
+ interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sdm845-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
@@ -1815,6 +1904,457 @@
clock-names = "xo";
};
+ stm@6002000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0 0x06002000 0 0x1000>,
+ <0 0x16280000 0 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint =
+ <&funnel0_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@6041000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06041000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel0_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+ funnel0_in7: endpoint {
+ remote-endpoint = <&stm_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6043000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06043000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel2_out: endpoint {
+ remote-endpoint =
+ <&merge_funnel_in2>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@5 {
+ reg = <5>;
+ funnel2_in5: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6045000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06045000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ merge_funnel_out: endpoint {
+ remote-endpoint = <&etf_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ merge_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ merge_funnel_in2: endpoint {
+ remote-endpoint =
+ <&funnel2_out>;
+ };
+ };
+ };
+ };
+
+ replicator@6046000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0 0x06046000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ replicator_out: endpoint {
+ remote-endpoint = <&etr_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ replicator_in: endpoint {
+ remote-endpoint = <&etf_out>;
+ };
+ };
+ };
+ };
+
+ etf@6047000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x06047000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etf_out: endpoint {
+ remote-endpoint =
+ <&replicator_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+ etf_in: endpoint {
+ remote-endpoint =
+ <&merge_funnel_out>;
+ };
+ };
+ };
+ };
+
+ etr@6048000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x06048000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,scatter-gather;
+
+ in-ports {
+ port {
+ etr_in: endpoint {
+ remote-endpoint =
+ <&replicator_out>;
+ };
+ };
+ };
+ };
+
+ etm@7040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07040000 0 0x1000>;
+
+ cpu = <&CPU0>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm0_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ etm@7140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07140000 0 0x1000>;
+
+ cpu = <&CPU1>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm1_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ etm@7240000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07240000 0 0x1000>;
+
+ cpu = <&CPU2>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm2_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in2>;
+ };
+ };
+ };
+ };
+
+ etm@7340000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07340000 0 0x1000>;
+
+ cpu = <&CPU3>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm3_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in3>;
+ };
+ };
+ };
+ };
+
+ etm@7440000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07440000 0 0x1000>;
+
+ cpu = <&CPU4>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm4_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in4>;
+ };
+ };
+ };
+ };
+
+ etm@7540000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07540000 0 0x1000>;
+
+ cpu = <&CPU5>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm5_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in5>;
+ };
+ };
+ };
+ };
+
+ etm@7640000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07640000 0 0x1000>;
+
+ cpu = <&CPU6>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm6_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in6>;
+ };
+ };
+ };
+ };
+
+ etm@7740000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07740000 0 0x1000>;
+
+ cpu = <&CPU7>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etm7_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@7800000 { /* APSS Funnel */
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x07800000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ apss_funnel_out: endpoint {
+ remote-endpoint =
+ <&apss_merge_funnel_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel_in0: endpoint {
+ remote-endpoint =
+ <&etm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel_in1: endpoint {
+ remote-endpoint =
+ <&etm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ apss_funnel_in2: endpoint {
+ remote-endpoint =
+ <&etm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_funnel_in3: endpoint {
+ remote-endpoint =
+ <&etm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ apss_funnel_in4: endpoint {
+ remote-endpoint =
+ <&etm4_out>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ apss_funnel_in5: endpoint {
+ remote-endpoint =
+ <&etm5_out>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ apss_funnel_in6: endpoint {
+ remote-endpoint =
+ <&etm6_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ apss_funnel_in7: endpoint {
+ remote-endpoint =
+ <&etm7_out>;
+ };
+ };
+ };
+ };
+
+ funnel@7810000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x07810000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ apss_merge_funnel_out: endpoint {
+ remote-endpoint =
+ <&funnel2_in5>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ apss_merge_funnel_in: endpoint {
+ remote-endpoint =
+ <&apss_funnel_out>;
+ };
+ };
+ };
+ };
+
sdhc_2: sdhci@8804000 {
compatible = "qcom,sdm845-sdhci", "qcom,sdhci-msm-v5";
reg = <0 0x08804000 0 0x1000>;
@@ -2027,6 +2567,36 @@
};
};
+ video-codec@aa00000 {
+ compatible = "qcom,sdm845-venus";
+ reg = <0 0x0aa00000 0 0xff000>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&videocc VENUS_GDSC>;
+ clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
+ <&videocc VIDEO_CC_VENUS_AHB_CLK>,
+ <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;
+ clock-names = "core", "iface", "bus";
+ iommus = <&apps_smmu 0x10a0 0x8>,
+ <&apps_smmu 0x10b0 0x0>;
+ memory-region = <&venus_mem>;
+
+ video-core0 {
+ compatible = "venus-decoder";
+ clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
+ <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
+ clock-names = "core", "bus";
+ power-domains = <&videocc VCODEC0_GDSC>;
+ };
+
+ video-core1 {
+ compatible = "venus-encoder";
+ clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
+ <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
+ clock-names = "core", "bus";
+ power-domains = <&videocc VCODEC1_GDSC>;
+ };
+ };
+
videocc: clock-controller@ab00000 {
compatible = "qcom,sdm845-videocc";
reg = <0 0x0ab00000 0 0x10000>;
@@ -2131,9 +2701,6 @@
status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -2198,9 +2765,6 @@
status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -2411,6 +2975,14 @@
#clock-cells = <0>;
#power-domain-cells = <1>;
+
+ cx_cdev: cx {
+ #cooling-cells = <2>;
+ };
+
+ ebi_cdev: ebi {
+ #cooling-cells = <2>;
+ };
};
spmi_bus: spmi@c440000 {
@@ -2538,6 +3110,8 @@
rpmhcc: clock-controller {
compatible = "qcom,sdm845-rpmh-clk";
#clock-cells = <1>;
+ clock-names = "xo";
+ clocks = <&xo_board>;
};
rpmhpd: power-controller {
@@ -2718,13 +3292,13 @@
thermal-sensors = <&tsens0 1>;
trips {
- cpu0_alert0: trip-point@0 {
+ cpu0_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu0_alert1: trip-point@1 {
+ cpu0_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2762,13 +3336,13 @@
thermal-sensors = <&tsens0 2>;
trips {
- cpu1_alert0: trip-point@0 {
+ cpu1_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu1_alert1: trip-point@1 {
+ cpu1_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2806,13 +3380,13 @@
thermal-sensors = <&tsens0 3>;
trips {
- cpu2_alert0: trip-point@0 {
+ cpu2_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu2_alert1: trip-point@1 {
+ cpu2_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2850,13 +3424,13 @@
thermal-sensors = <&tsens0 4>;
trips {
- cpu3_alert0: trip-point@0 {
+ cpu3_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu3_alert1: trip-point@1 {
+ cpu3_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2894,13 +3468,13 @@
thermal-sensors = <&tsens0 7>;
trips {
- cpu4_alert0: trip-point@0 {
+ cpu4_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu4_alert1: trip-point@1 {
+ cpu4_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2938,13 +3512,13 @@
thermal-sensors = <&tsens0 8>;
trips {
- cpu5_alert0: trip-point@0 {
+ cpu5_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu5_alert1: trip-point@1 {
+ cpu5_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -2982,13 +3556,13 @@
thermal-sensors = <&tsens0 9>;
trips {
- cpu6_alert0: trip-point@0 {
+ cpu6_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu6_alert1: trip-point@1 {
+ cpu6_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -3026,13 +3600,13 @@
thermal-sensors = <&tsens0 10>;
trips {
- cpu7_alert0: trip-point@0 {
+ cpu7_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "passive";
};
- cpu7_alert1: trip-point@1 {
+ cpu7_alert1: trip-point1 {
temperature = <95000>;
hysteresis = <2000>;
type = "passive";
@@ -3070,7 +3644,7 @@
thermal-sensors = <&tsens0 0>;
trips {
- aoss0_alert0: trip-point@0 {
+ aoss0_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3085,7 +3659,7 @@
thermal-sensors = <&tsens0 5>;
trips {
- cluster0_alert0: trip-point@0 {
+ cluster0_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3105,7 +3679,7 @@
thermal-sensors = <&tsens0 6>;
trips {
- cluster1_alert0: trip-point@0 {
+ cluster1_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3125,7 +3699,7 @@
thermal-sensors = <&tsens0 11>;
trips {
- gpu1_alert0: trip-point@0 {
+ gpu1_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3140,7 +3714,7 @@
thermal-sensors = <&tsens0 12>;
trips {
- gpu2_alert0: trip-point@0 {
+ gpu2_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3155,7 +3729,7 @@
thermal-sensors = <&tsens1 0>;
trips {
- aoss1_alert0: trip-point@0 {
+ aoss1_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3170,7 +3744,7 @@
thermal-sensors = <&tsens1 1>;
trips {
- q6_modem_alert0: trip-point@0 {
+ q6_modem_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3185,7 +3759,7 @@
thermal-sensors = <&tsens1 2>;
trips {
- mem_alert0: trip-point@0 {
+ mem_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3200,7 +3774,7 @@
thermal-sensors = <&tsens1 3>;
trips {
- wlan_alert0: trip-point@0 {
+ wlan_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3215,7 +3789,7 @@
thermal-sensors = <&tsens1 4>;
trips {
- q6_hvx_alert0: trip-point@0 {
+ q6_hvx_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3230,7 +3804,7 @@
thermal-sensors = <&tsens1 5>;
trips {
- camera_alert0: trip-point@0 {
+ camera_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3245,7 +3819,7 @@
thermal-sensors = <&tsens1 6>;
trips {
- video_alert0: trip-point@0 {
+ video_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
@@ -3260,7 +3834,7 @@
thermal-sensors = <&tsens1 7>;
trips {
- modem_alert0: trip-point@0 {
+ modem_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
type = "hot";
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
new file mode 100644
index 000000000000..ded120d3aef5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Lenovo Yoga C630
+ *
+ * Copyright (c) 2019, Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sdm845.dtsi"
+#include "pm8998.dtsi"
+
+/ {
+ model = "Lenovo Yoga C630";
+ compatible = "lenovo,yoga-c630", "qcom,sdm845";
+
+ aliases {
+ hsuart0 = &uart6;
+ };
+};
+
+&apps_rsc {
+ pm8998-rpmh-regulators {
+ compatible = "qcom,pm8998-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vdd-l2-l8-l17-supply = <&vreg_s3a_1p35>;
+ vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p04>;
+
+ vreg_s2a_1p125: smps2 {
+ };
+
+ vreg_s3a_1p35: smps3 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s4a_1p8: smps4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5a_2p04: smps5 {
+ regulator-min-microvolt = <2040000>;
+ regulator-max-microvolt = <2040000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s7a_1p025: smps7 {
+ };
+
+ vdd_qusb_hs0:
+ vdda_hp_pcie_core:
+ vdda_mipi_csi0_0p9:
+ vdda_mipi_csi1_0p9:
+ vdda_mipi_csi2_0p9:
+ vdda_mipi_dsi0_pll:
+ vdda_mipi_dsi1_pll:
+ vdda_qlink_lv:
+ vdda_qlink_lv_ck:
+ vdda_qrefs_0p875:
+ vdda_pcie_core:
+ vdda_pll_cc_ebi01:
+ vdda_pll_cc_ebi23:
+ vdda_sp_sensor:
+ vdda_ufs1_core:
+ vdda_ufs2_core:
+ vdda_usb1_ss_core:
+ vdda_usb2_ss_core:
+ vreg_l1a_0p875: ldo1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_10:
+ vreg_l2a_1p2: ldo2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l3a_1p0: ldo3 {
+ };
+
+ vdd_wcss_cx:
+ vdd_wcss_mx:
+ vdda_wcss_pll:
+ vreg_l5a_0p8: ldo5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_13:
+ vreg_l6a_1p8: ldo6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a_1p8: ldo7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8a_1p2: ldo8 {
+ };
+
+ vreg_l9a_1p8: ldo9 {
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ };
+
+ vreg_l11a_1p0: ldo11 {
+ };
+
+ vdd_qfprom:
+ vdd_qfprom_sp:
+ vdda_apc1_cs_1p8:
+ vdda_gfx_cs_1p8:
+ vdda_qrefs_1p8:
+ vdda_qusb_hs0_1p8:
+ vddpx_11:
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_2:
+ vreg_l13a_2p95: ldo13 {
+ };
+
+ vreg_l14a_1p88: ldo14 {
+ regulator-min-microvolt = <1880000>;
+ regulator-max-microvolt = <1880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ };
+
+ vreg_l17a_1p3: ldo17 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18a_2p7: ldo18 {
+ };
+
+ vreg_l19a_3p0: ldo19 {
+ regulator-min-microvolt = <3100000>;
+ regulator-max-microvolt = <3108000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l20a_2p95: ldo20 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l21a_2p95: ldo21 {
+ };
+
+ vreg_l22a_2p85: ldo22 {
+ };
+
+ vreg_l23a_3p3: ldo23 {
+ };
+
+ vdda_qusb_hs0_3p1:
+ vreg_l24a_3p075: ldo24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3083000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l25a_3p3: ldo25 {
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3112000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_hp_pcie_1p2:
+ vdda_hv_ebi0:
+ vdda_hv_ebi1:
+ vdda_hv_ebi2:
+ vdda_hv_ebi3:
+ vdda_mipi_csi_1p25:
+ vdda_mipi_dsi0_1p2:
+ vdda_mipi_dsi1_1p2:
+ vdda_pcie_1p2:
+ vdda_ufs1_1p2:
+ vdda_ufs2_1p2:
+ vdda_usb1_ss_1p2:
+ vdda_usb2_ss_1p2:
+ vreg_l26a_1p2: ldo26 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1208000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l28a_3p0: ldo28 {
+ };
+
+ vreg_lvs1a_1p8: lvs1 {
+ };
+
+ vreg_lvs2a_1p8: lvs2 {
+ };
+ };
+};
+
+&apps_smmu {
+ /* TODO: Figure out how to survive booting with this enabled */
+ status = "disabled";
+};
+
+&gcc {
+ protected-clocks = <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+};
+
+&i2c1 {
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+&i2c3 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ hid@15 {
+ compatible = "hid-over-i2c";
+ reg = <0x15>;
+ hid-descr-addr = <0x1>;
+
+ interrupts-extended = <&tlmm 37 IRQ_TYPE_EDGE_RISING>;
+ };
+
+ hid@2c {
+ compatible = "hid-over-i2c";
+ reg = <0x2c>;
+ hid-descr-addr = <0x20>;
+
+ interrupts-extended = <&tlmm 37 IRQ_TYPE_EDGE_RISING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_hid_active>;
+ };
+};
+
+&i2c5 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ hid@10 {
+ compatible = "hid-over-i2c";
+ reg = <0x10>;
+ hid-descr-addr = <0x1>;
+
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6_hid_active>;
+ };
+};
+
+&i2c11 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ hid@5c {
+ compatible = "hid-over-i2c";
+ reg = <0x5c>;
+ hid-descr-addr = <0x1>;
+
+ interrupts-extended = <&tlmm 92 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c12_hid_active>;
+ };
+};
+
+&qup_i2c12_default {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ i2c2_hid_active: i2c2-hid-active {
+ pins = <37>;
+ function = "gpio";
+
+ input-enable;
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ i2c6_hid_active: i2c6-hid-active {
+ pins = <125>;
+ function = "gpio";
+
+ input-enable;
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ i2c12_hid_active: i2c12-hid-active {
+ pins = <92>;
+ function = "gpio";
+
+ input-enable;
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+};
+
+&uart6 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn3990-bt";
+
+ vddio-supply = <&vreg_s4a_1p8>;
+ vddxo-supply = <&vreg_l7a_1p8>;
+ vddrf-supply = <&vreg_l17a_1p3>;
+ vddch0-supply = <&vreg_l25a_3p3>;
+ max-speed = <3200000>;
+ };
+};
+
+&ufs_mem_hc {
+ status = "okay";
+
+ vcc-supply = <&vreg_l20a_2p95>;
+ vcc-max-microamp = <600000>;
+};
+
+&ufs_mem_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vdda_ufs1_core>;
+ vdda-pll-supply = <&vdda_ufs1_1p2>;
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+
+ vdd-supply = <&vdda_usb1_ss_core>;
+ vdda-pll-supply = <&vdda_qusb_hs0_1p8>;
+ vdda-phy-dpdm-supply = <&vdda_qusb_hs0_3p1>;
+
+ qcom,imp-res-offset-value = <8>;
+ qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_21_6_MA>;
+ qcom,preemphasis-level = <QUSB2_V2_PREEMPHASIS_5_PERCENT>;
+ qcom,preemphasis-width = <QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT>;
+};
+
+&usb_1_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vdda_usb1_ss_1p2>;
+ vdda-pll-supply = <&vdda_usb1_ss_core>;
+};
+
+&usb_2 {
+ status = "okay";
+};
+
+&usb_2_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_2_hsphy {
+ status = "okay";
+
+ vdd-supply = <&vdda_usb2_ss_core>;
+ vdda-pll-supply = <&vdda_qusb_hs0_1p8>;
+ vdda-phy-dpdm-supply = <&vdda_qusb_hs0_3p1>;
+
+ qcom,imp-res-offset-value = <8>;
+ qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_22_8_MA>;
+};
+
+&usb_2_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vdda_usb2_ss_1p2>;
+ vdda-pll-supply = <&vdda_usb2_ss_core>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
new file mode 100644
index 000000000000..aa5de42fcae4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sm8150.dtsi"
+#include "pm8150.dtsi"
+#include "pm8150b.dtsi"
+#include "pm8150l.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SM8150 MTP";
+ compatible = "qcom,sm8150-mtp";
+
+ aliases {
+ serial0 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ };
+
+ /*
+ * Apparently RPMh does not provide support for PM8150 S4 because it
+ * is always-on; model it as a fixed regulator.
+ */
+ vreg_s4a_1p8: pm8150-s4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s4a_1p8";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+
+ vin-supply = <&vph_pwr>;
+ };
+};
+
+&apps_rsc {
+ pm8150-rpmh-regulators {
+ compatible = "qcom,pm8150-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+
+ vdd-l1-l8-l11-supply = <&vreg_s6a_0p9>;
+ vdd-l2-l10-supply = <&vreg_bob>;
+ vdd-l3-l4-l5-l18-supply = <&vreg_s6a_0p9>;
+ vdd-l6-l9-supply = <&vreg_s8c_1p3>;
+ vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p0>;
+ vdd-l13-l16-l17-supply = <&vreg_bob>;
+
+ vreg_s5a_2p0: smps5 {
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_s6a_0p9: smps6 {
+ regulator-min-microvolt = <920000>;
+ regulator-max-microvolt = <1128000>;
+ };
+
+ vdda_wcss_pll:
+ vreg_l1a_0p75: ldo1 {
+ regulator-min-microvolt = <752000>;
+ regulator-max-microvolt = <752000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_pdphy:
+ vdda_usb_hs_3p1:
+ vreg_l2a_3p1: ldo2 {
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3a_0p8: ldo3 {
+ regulator-min-microvolt = <480000>;
+ regulator-max-microvolt = <932000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_usb_hs_core:
+ vdda_csi_0_0p9:
+ vdda_csi_1_0p9:
+ vdda_csi_2_0p9:
+ vdda_csi_3_0p9:
+ vdda_dsi_0_0p9:
+ vdda_dsi_1_0p9:
+ vdda_dsi_0_pll_0p9:
+ vdda_dsi_1_pll_0p9:
+ vdda_pcie_1ln_core:
+ vdda_pcie_2ln_core:
+ vdda_pll_hv_cc_ebi01:
+ vdda_pll_hv_cc_ebi23:
+ vdda_qrefs_0p875_5:
+ vdda_sp_sensor:
+ vdda_ufs_2ln_core_1:
+ vdda_ufs_2ln_core_2:
+ vdda_usb_ss_dp_core_1:
+ vdda_usb_ss_dp_core_2:
+ vdda_qlink_lv:
+ vdda_qlink_lv_ck:
+ vreg_l5a_0p875: ldo5 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6a_1p2: ldo6 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a_1p8: ldo7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_10:
+ vreg_l9a_1p2: ldo9 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10a_2p5: ldo10 {
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11a_0p8: ldo11 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_qfprom:
+ vdd_qfprom_sp:
+ vdda_apc_cs_1p8:
+ vdda_gfx_cs_1p8:
+ vdda_usb_hs_1p8:
+ vdda_qrefs_vref_1p8:
+ vddpx_10_a:
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13a_2p7: ldo13 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p8: ldo14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15a_1p7: ldo15 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1704000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17a_3p0: ldo17 {
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ pm8150l-rpmh-regulators {
+ compatible = "qcom,pm8150l-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+
+ vdd-l1-l8-supply = <&vreg_s4a_1p8>;
+ vdd-l2-l3-supply = <&vreg_s8c_1p3>;
+ vdd-l4-l5-l6-supply = <&vreg_bob>;
+ vdd-l7-l11-supply = <&vreg_bob>;
+ vdd-l9-l10-supply = <&vreg_bob>;
+
+ vdd-bob-supply = <&vph_pwr>;
+ vdd-flash-supply = <&vreg_bob>;
+ vdd-rgb-supply = <&vreg_bob>;
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ regulator-allow-bypass;
+ };
+
+ vreg_s8c_1p3: smps8 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ };
+
+ vreg_l1c_1p8: ldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_wcss_adcdac_1:
+ vdda_wcss_adcdac_22:
+ vreg_l2c_1p3: ldo2 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_hv_ebi0:
+ vdda_hv_ebi1:
+ vdda_hv_ebi2:
+ vdda_hv_ebi3:
+ vdda_hv_refgen0:
+ vdda_qlink_hv_ck:
+ vreg_l3c_1p2: ldo3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_5:
+ vreg_l4c_1p8: ldo4 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <2928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_6:
+ vreg_l5c_1p8: ldo5 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <2928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_2:
+ vreg_l6c_2p9: ldo6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c_3p0: ldo7 {
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c_1p8: ldo8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c_2p9: ldo9 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c_3p3: ldo10 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c_3p3: ldo11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ pm8009-rpmh-regulators {
+ compatible = "qcom,pm8009-rpmh-regulators";
+ qcom,pmic-id = "f";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vreg_bob>;
+
+ vdd-l2-supply = <&vreg_s8c_1p3>;
+ vdd-l5-l6-supply = <&vreg_bob>;
+
+ vreg_l2f_1p2: ldo2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5f_2p85: ldo5 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6f_2p85: ldo6 {
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <2856000>;
+ };
+ };
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&pon {
+ pwrkey {
+ status = "okay";
+ };
+
+ resin {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <0x0 0x8 0x1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <126 4>;
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
new file mode 100644
index 000000000000..8f23fcadecb8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ clocks {
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ clock-output-names = "xo_board";
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32764>;
+ clock-output-names = "sleep_clk";
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ L3_0: l3-cache {
+ compatible = "cache";
+ };
+ };
+ };
+
+ CPU1: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_100>;
+ L2_100: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+
+ };
+
+ CPU2: cpu@200 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ next-level-cache = <&L2_200>;
+ L2_200: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU3: cpu@300 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ next-level-cache = <&L2_300>;
+ L2_300: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU4: cpu@400 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ next-level-cache = <&L2_400>;
+ L2_400: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU5: cpu@500 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ next-level-cache = <&L2_500>;
+ L2_500: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU6: cpu@600 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ next-level-cache = <&L2_600>;
+ L2_600: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU7: cpu@700 {
+ device_type = "cpu";
+ compatible = "qcom,kryo485";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ next-level-cache = <&L2_700>;
+ L2_700: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+ };
+
+ firmware {
+ scm: scm {
+ compatible = "qcom,scm-sm8150", "qcom,scm";
+ #reset-cells = <1>;
+ };
+ };
+
+ tcsr_mutex: hwlock {
+ compatible = "qcom,tcsr-mutex";
+ syscon = <&tcsr_mutex_regs 0 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x80000000 0x0 0x0>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: memory@85700000 {
+ reg = <0x0 0x85700000 0x0 0x600000>;
+ no-map;
+ };
+
+ xbl_mem: memory@85d00000 {
+ reg = <0x0 0x85d00000 0x0 0x140000>;
+ no-map;
+ };
+
+ aop_mem: memory@85f00000 {
+ reg = <0x0 0x85f00000 0x0 0x20000>;
+ no-map;
+ };
+
+ aop_cmd_db: memory@85f20000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x85f20000 0x0 0x20000>;
+ no-map;
+ };
+
+ smem_mem: memory@86000000 {
+ reg = <0x0 0x86000000 0x0 0x200000>;
+ no-map;
+ };
+
+ tz_mem: memory@86200000 {
+ reg = <0x0 0x86200000 0x0 0x3900000>;
+ no-map;
+ };
+
+ rmtfs_mem: memory@89b00000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0x89b00000 0x0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
+ camera_mem: memory@8b700000 {
+ reg = <0x0 0x8b700000 0x0 0x500000>;
+ no-map;
+ };
+
+ wlan_mem: memory@8bc00000 {
+ reg = <0x0 0x8bc00000 0x0 0x180000>;
+ no-map;
+ };
+
+ npu_mem: memory@8bd80000 {
+ reg = <0x0 0x8bd80000 0x0 0x80000>;
+ no-map;
+ };
+
+ adsp_mem: memory@8be00000 {
+ reg = <0x0 0x8be00000 0x0 0x1a00000>;
+ no-map;
+ };
+
+ mpss_mem: memory@8d800000 {
+ reg = <0x0 0x8d800000 0x0 0x9600000>;
+ no-map;
+ };
+
+ venus_mem: memory@96e00000 {
+ reg = <0x0 0x96e00000 0x0 0x500000>;
+ no-map;
+ };
+
+ slpi_mem: memory@97300000 {
+ reg = <0x0 0x97300000 0x0 0x1400000>;
+ no-map;
+ };
+
+ ipa_fw_mem: memory@98700000 {
+ reg = <0x0 0x98700000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: memory@98710000 {
+ reg = <0x0 0x98710000 0x0 0x5000>;
+ no-map;
+ };
+
+ gpu_mem: memory@98715000 {
+ reg = <0x0 0x98715000 0x0 0x2000>;
+ no-map;
+ };
+
+ spss_mem: memory@98800000 {
+ reg = <0x0 0x98800000 0x0 0x100000>;
+ no-map;
+ };
+
+ cdsp_mem: memory@98900000 {
+ reg = <0x0 0x98900000 0x0 0x1400000>;
+ no-map;
+ };
+
+ qseecom_mem: memory@9e400000 {
+ reg = <0x0 0x9e400000 0x0 0x1400000>;
+ no-map;
+ };
+ };
+
+ smem {
+ compatible = "qcom,smem";
+ memory-region = <&smem_mem>;
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ soc: soc@0 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0 0 0 0 0x10 0>;
+ dma-ranges = <0 0 0 0 0x10 0>;
+ compatible = "simple-bus";
+
+ gcc: clock-controller@100000 {
+ compatible = "qcom,gcc-sm8150";
+ reg = <0x0 0x00100000 0x0 0x1f0000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ clock-names = "bi_tcxo",
+ "sleep_clk";
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&sleep_clk>;
+ };
+
+ qupv3_id_1: geniqup@ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x0 0x00ac0000 0x0 0x6000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc 123>,
+ <&gcc 124>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ uart2: serial@a90000 {
+ compatible = "qcom,geni-debug-uart";
+ reg = <0x0 0x00a90000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc 105>;
+ interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+ };
+
+ tcsr_mutex_regs: syscon@1f40000 {
+ compatible = "syscon";
+ reg = <0x0 0x01f40000 0x0 0x40000>;
+ };
+
+ tlmm: pinctrl@3100000 {
+ compatible = "qcom,sm8150-pinctrl";
+ reg = <0x0 0x03100000 0x0 0x300000>,
+ <0x0 0x03500000 0x0 0x300000>,
+ <0x0 0x03900000 0x0 0x300000>,
+ <0x0 0x03D00000 0x0 0x300000>;
+ reg-names = "west", "east", "north", "south";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 175>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ aoss_qmp: power-controller@c300000 {
+ compatible = "qcom,sm8150-aoss-qmp";
+ reg = <0x0 0x0c300000 0x0 0x100000>;
+ interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apss_shared 0>;
+
+ #clock-cells = <0>;
+ #power-domain-cells = <1>;
+ };
+
+ spmi_bus: spmi@c440000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x0 0x0c440000 0x0 0x0001100>,
+ <0x0 0x0c600000 0x0 0x2000000>,
+ <0x0 0x0e600000 0x0 0x0100000>,
+ <0x0 0x0e700000 0x0 0x00a0000>,
+ <0x0 0x0c40a000 0x0 0x0026000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 481 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ intc: interrupt-controller@17a00000 {
+ compatible = "arm,gic-v3";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x0 0x17a00000 0x0 0x10000>, /* GICD */
+ <0x0 0x17a60000 0x0 0x100000>; /* GICR * 8 */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ apss_shared: mailbox@17c00000 {
+ compatible = "qcom,sm8150-apss-shared";
+ reg = <0x0 0x17c00000 0x0 0x1000>;
+ #mbox-cells = <1>;
+ };
+
+ timer@17c20000 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x0 0x17c20000 0x0 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@17c21000{
+ frame-number = <0>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c21000 0x0 0x1000>,
+ <0x0 0x17c22000 0x0 0x1000>;
+ };
+
+ frame@17c23000 {
+ frame-number = <1>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c23000 0x0 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17c25000 {
+ frame-number = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c25000 0x0 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17c27000 {
+ frame-number = <3>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c26000 0x0 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17c29000 {
+ frame-number = <4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c29000 0x0 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17c2b000 {
+ frame-number = <5>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c2b000 0x0 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17c2d000 {
+ frame-number = <6>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0 0x17c2d000 0x0 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ apps_rsc: rsc@18200000 {
+ label = "apps_rsc";
+ compatible = "qcom,rpmh-rsc";
+ reg = <0x0 0x18200000 0x0 0x10000>,
+ <0x0 0x18210000 0x0 0x10000>,
+ <0x0 0x18220000 0x0 0x10000>;
+ reg-names = "drv-0", "drv-1", "drv-2";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,tcs-offset = <0xd00>;
+ qcom,drv-id = <2>;
+ qcom,tcs-config = <ACTIVE_TCS 2>,
+ <SLEEP_TCS 1>,
+ <WAKE_TCS 1>,
+ <CONTROL_TCS 0>;
+
+ rpmhcc: clock-controller {
+ compatible = "qcom,sm8150-rpmh-clk";
+ #clock-cells = <1>;
+ clock-names = "xo";
+ clocks = <&xo_board>;
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 3 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/hihope-common.dtsi b/arch/arm64/boot/dts/renesas/hihope-common.dtsi
index 3311a982fff8..3e376d29a730 100644
--- a/arch/arm64/boot/dts/renesas/hihope-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-common.dtsi
@@ -10,6 +10,7 @@
/ {
aliases {
serial0 = &scif2;
+ serial1 = &hscif0;
};
chosen {
@@ -31,6 +32,13 @@
leds {
compatible = "gpio-leds";
+ bt_active_led {
+ label = "blue:bt";
+ gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "hci0-power";
+ default-state = "off";
+ };
+
led0 {
gpios = <&gpio6 11 GPIO_ACTIVE_HIGH>;
};
@@ -46,6 +54,13 @@
led3 {
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
};
+
+ wlan_active_led {
+ label = "yellow:wlan";
+ gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
};
reg_1p8v: regulator0 {
@@ -66,6 +81,14 @@
regulator-always-on;
};
+ sound_card: sound {
+ compatible = "audio-graph-card";
+
+ label = "rcar-sound";
+
+ dais = <&rsnd_port0>;
+ };
+
vbus0_usb2: regulator-vbus0-usb2 {
compatible = "regulator-fixed";
@@ -90,6 +113,17 @@
1800000 0>;
};
+ wlan_en_reg: regulator-wlan_en {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us = <70000>;
+
+ gpio = <&gpio_expander 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
x302_clk: x302-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -103,6 +137,10 @@
};
};
+&audio_clk_a {
+ clock-frequency = <22579200>;
+};
+
&du {
clocks = <&cpg CPG_MOD 724>,
<&cpg CPG_MOD 723>,
@@ -150,6 +188,25 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint0>;
+ };
+ };
+ };
+};
+
+&hscif0 {
+ pinctrl-0 = <&hscif0_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "ti,wl1837-st";
+ enable-gpios = <&gpio_expander 2 GPIO_ACTIVE_HIGH>;
};
};
@@ -162,6 +219,13 @@
clock-frequency = <400000>;
status = "okay";
+ gpio_expander: gpio@20 {
+ compatible = "onnn,pca9654";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
versaclock5: clock-generator@6a {
compatible = "idt,5p49v5923";
reg = <0x6a>;
@@ -187,6 +251,11 @@
pinctrl-0 = <&scif_clk_pins>;
pinctrl-names = "default";
+ hscif0_pins: hscif0 {
+ groups = "hscif0_data", "hscif0_ctrl";
+ function = "hscif0";
+ };
+
scif2_pins: scif2 {
groups = "scif2_data_a";
function = "scif2";
@@ -209,12 +278,23 @@
power-source = <1800>;
};
+ sdhi2_pins: sd2 {
+ groups = "sdhi2_data4", "sdhi2_ctrl";
+ function = "sdhi2";
+ power-source = <1800>;
+ };
+
sdhi3_pins: sd3 {
groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
function = "sdhi3";
power-source = <1800>;
};
+ sound_clk_pins: sound_clk {
+ groups = "audio_clk_a_a";
+ function = "audio_clk";
+ };
+
usb0_pins: usb0 {
groups = "usb0";
function = "usb0";
@@ -238,6 +318,30 @@
};
};
+&rcar_sound {
+ pinctrl-0 = <&sound_clk_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ /* Single DAI */
+ #sound-dai-cells = <0>;
+
+ ports {
+ rsnd_port0: port@0 {
+ rsnd_endpoint0: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+
+ playback = <&ssi2>;
+ };
+ };
+ };
+};
+
&rwdt {
timeout-sec = <60>;
status = "okay";
@@ -268,6 +372,27 @@
status = "okay";
};
+&sdhi2 {
+ status = "okay";
+ pinctrl-0 = <&sdhi2_pins>;
+ pinctrl-names = "default";
+
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ non-removable;
+ cap-power-off-card;
+ keep-power-in-suspend;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@2 {
+ compatible = "ti,wl1837";
+ reg = <2>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
+
&sdhi3 {
pinctrl-0 = <&sdhi3_pins>;
pinctrl-1 = <&sdhi3_pins>;
@@ -279,6 +404,7 @@
mmc-hs200-1_8v;
non-removable;
fixed-emmc-driver-type = <1>;
+ status = "okay";
};
&usb_extal_clk {
diff --git a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
index 07a6eeaed12e..4280b190dc68 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
@@ -31,6 +31,18 @@
};
};
+&can0 {
+ pinctrl-0 = <&can0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-0 = <&can1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&pciec0 {
status = "okay";
};
@@ -60,4 +72,14 @@
drive-strength = <12>;
};
};
+
+ can0_pins: can0 {
+ groups = "can0_data_a";
+ function = "can0";
+ };
+
+ can1_pins: can1 {
+ groups = "can1_data";
+ function = "can1";
+ };
};
diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
index f209457c7807..06c7c849c8ab 100644
--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -1128,6 +1128,8 @@
<&cpg CPG_CORE R8A774A1_CLK_CANFD>,
<&can_clk>;
clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
resets = <&cpg 916>;
status = "disabled";
@@ -1142,11 +1144,38 @@
<&cpg CPG_CORE R8A774A1_CLK_CANFD>,
<&can_clk>;
clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
resets = <&cpg 915>;
status = "disabled";
};
+ canfd: can@e66c0000 {
+ compatible = "renesas,r8a774a1-canfd",
+ "renesas,rcar-gen3-canfd";
+ reg = <0 0xe66c0000 0 0x8000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 914>,
+ <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "fck", "canfd", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
+ power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+ resets = <&cpg 914>;
+ status = "disabled";
+
+ channel0 {
+ status = "disabled";
+ };
+
+ channel1 {
+ status = "disabled";
+ };
+ };
+
pwm0: pwm@e6e30000 {
compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
reg = <0 0xe6e30000 0 0x8>;
@@ -1653,7 +1682,7 @@
<0 0xec5a0000 0 0x100>, /* ADG */
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec541000 0 0x280>, /* SSI */
- <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/
+ <0 0xec760000 0 0x200>; /* Audio DMAC peri peri*/
reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
clocks = <&cpg CPG_MOD 1005>,
@@ -1697,6 +1726,28 @@
"ssi.1", "ssi.0";
status = "disabled";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ };
+ };
+
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
rcar_sound,dvc {
dvc0: dvc-0 {
dmas = <&audma1 0xbc>;
@@ -1713,17 +1764,6 @@
mix1: mix-1 { };
};
- rcar_sound,ctu {
- ctu00: ctu-0 { };
- ctu01: ctu-1 { };
- ctu02: ctu-2 { };
- ctu03: ctu-3 { };
- ctu10: ctu-4 { };
- ctu11: ctu-5 { };
- ctu12: ctu-6 { };
- ctu13: ctu-7 { };
- };
-
rcar_sound,src {
src0: src-0 {
interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
@@ -1780,64 +1820,264 @@
rcar_sound,ssi {
ssi0: ssi-0 {
interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x01>, <&audma1 0x02>;
+ dma-names = "rx", "tx";
};
ssi1: ssi-1 {
interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x03>, <&audma1 0x04>;
+ dma-names = "rx", "tx";
};
ssi2: ssi-2 {
interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x05>, <&audma1 0x06>;
+ dma-names = "rx", "tx";
};
ssi3: ssi-3 {
interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x07>, <&audma1 0x08>;
+ dma-names = "rx", "tx";
};
ssi4: ssi-4 {
interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x09>, <&audma1 0x0a>;
+ dma-names = "rx", "tx";
};
ssi5: ssi-5 {
interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x0b>, <&audma1 0x0c>;
+ dma-names = "rx", "tx";
};
ssi6: ssi-6 {
interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x0d>, <&audma1 0x0e>;
+ dma-names = "rx", "tx";
};
ssi7: ssi-7 {
interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x0f>, <&audma1 0x10>;
+ dma-names = "rx", "tx";
};
ssi8: ssi-8 {
interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x11>, <&audma1 0x12>;
+ dma-names = "rx", "tx";
};
ssi9: ssi-9 {
interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
- dma-names = "rx", "tx", "rxu", "txu";
+ dmas = <&audma0 0x13>, <&audma1 0x14>;
+ dma-names = "rx", "tx";
};
};
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
+ rcar_sound,ssiu {
+ ssiu00: ssiu-0 {
+ dmas = <&audma0 0x15>, <&audma1 0x16>;
+ dma-names = "rx", "tx";
};
- port@1 {
- reg = <1>;
+ ssiu01: ssiu-1 {
+ dmas = <&audma0 0x35>, <&audma1 0x36>;
+ dma-names = "rx", "tx";
+ };
+ ssiu02: ssiu-2 {
+ dmas = <&audma0 0x37>, <&audma1 0x38>;
+ dma-names = "rx", "tx";
+ };
+ ssiu03: ssiu-3 {
+ dmas = <&audma0 0x47>, <&audma1 0x48>;
+ dma-names = "rx", "tx";
+ };
+ ssiu04: ssiu-4 {
+ dmas = <&audma0 0x3F>, <&audma1 0x40>;
+ dma-names = "rx", "tx";
+ };
+ ssiu05: ssiu-5 {
+ dmas = <&audma0 0x43>, <&audma1 0x44>;
+ dma-names = "rx", "tx";
+ };
+ ssiu06: ssiu-6 {
+ dmas = <&audma0 0x4F>, <&audma1 0x50>;
+ dma-names = "rx", "tx";
+ };
+ ssiu07: ssiu-7 {
+ dmas = <&audma0 0x53>, <&audma1 0x54>;
+ dma-names = "rx", "tx";
+ };
+ ssiu10: ssiu-8 {
+ dmas = <&audma0 0x49>, <&audma1 0x4a>;
+ dma-names = "rx", "tx";
+ };
+ ssiu11: ssiu-9 {
+ dmas = <&audma0 0x4B>, <&audma1 0x4C>;
+ dma-names = "rx", "tx";
+ };
+ ssiu12: ssiu-10 {
+ dmas = <&audma0 0x57>, <&audma1 0x58>;
+ dma-names = "rx", "tx";
+ };
+ ssiu13: ssiu-11 {
+ dmas = <&audma0 0x59>, <&audma1 0x5A>;
+ dma-names = "rx", "tx";
+ };
+ ssiu14: ssiu-12 {
+ dmas = <&audma0 0x5F>, <&audma1 0x60>;
+ dma-names = "rx", "tx";
+ };
+ ssiu15: ssiu-13 {
+ dmas = <&audma0 0xC3>, <&audma1 0xC4>;
+ dma-names = "rx", "tx";
+ };
+ ssiu16: ssiu-14 {
+ dmas = <&audma0 0xC7>, <&audma1 0xC8>;
+ dma-names = "rx", "tx";
+ };
+ ssiu17: ssiu-15 {
+ dmas = <&audma0 0xCB>, <&audma1 0xCC>;
+ dma-names = "rx", "tx";
+ };
+ ssiu20: ssiu-16 {
+ dmas = <&audma0 0x63>, <&audma1 0x64>;
+ dma-names = "rx", "tx";
+ };
+ ssiu21: ssiu-17 {
+ dmas = <&audma0 0x67>, <&audma1 0x68>;
+ dma-names = "rx", "tx";
+ };
+ ssiu22: ssiu-18 {
+ dmas = <&audma0 0x6B>, <&audma1 0x6C>;
+ dma-names = "rx", "tx";
+ };
+ ssiu23: ssiu-19 {
+ dmas = <&audma0 0x6D>, <&audma1 0x6E>;
+ dma-names = "rx", "tx";
+ };
+ ssiu24: ssiu-20 {
+ dmas = <&audma0 0xCF>, <&audma1 0xCE>;
+ dma-names = "rx", "tx";
+ };
+ ssiu25: ssiu-21 {
+ dmas = <&audma0 0xEB>, <&audma1 0xEC>;
+ dma-names = "rx", "tx";
+ };
+ ssiu26: ssiu-22 {
+ dmas = <&audma0 0xED>, <&audma1 0xEE>;
+ dma-names = "rx", "tx";
+ };
+ ssiu27: ssiu-23 {
+ dmas = <&audma0 0xEF>, <&audma1 0xF0>;
+ dma-names = "rx", "tx";
+ };
+ ssiu30: ssiu-24 {
+ dmas = <&audma0 0x6f>, <&audma1 0x70>;
+ dma-names = "rx", "tx";
+ };
+ ssiu31: ssiu-25 {
+ dmas = <&audma0 0x21>, <&audma1 0x22>;
+ dma-names = "rx", "tx";
+ };
+ ssiu32: ssiu-26 {
+ dmas = <&audma0 0x23>, <&audma1 0x24>;
+ dma-names = "rx", "tx";
+ };
+ ssiu33: ssiu-27 {
+ dmas = <&audma0 0x25>, <&audma1 0x26>;
+ dma-names = "rx", "tx";
+ };
+ ssiu34: ssiu-28 {
+ dmas = <&audma0 0x27>, <&audma1 0x28>;
+ dma-names = "rx", "tx";
+ };
+ ssiu35: ssiu-29 {
+ dmas = <&audma0 0x29>, <&audma1 0x2A>;
+ dma-names = "rx", "tx";
+ };
+ ssiu36: ssiu-30 {
+ dmas = <&audma0 0x2B>, <&audma1 0x2C>;
+ dma-names = "rx", "tx";
+ };
+ ssiu37: ssiu-31 {
+ dmas = <&audma0 0x2D>, <&audma1 0x2E>;
+ dma-names = "rx", "tx";
+ };
+ ssiu40: ssiu-32 {
+ dmas = <&audma0 0x71>, <&audma1 0x72>;
+ dma-names = "rx", "tx";
+ };
+ ssiu41: ssiu-33 {
+ dmas = <&audma0 0x17>, <&audma1 0x18>;
+ dma-names = "rx", "tx";
+ };
+ ssiu42: ssiu-34 {
+ dmas = <&audma0 0x19>, <&audma1 0x1A>;
+ dma-names = "rx", "tx";
+ };
+ ssiu43: ssiu-35 {
+ dmas = <&audma0 0x1B>, <&audma1 0x1C>;
+ dma-names = "rx", "tx";
+ };
+ ssiu44: ssiu-36 {
+ dmas = <&audma0 0x1D>, <&audma1 0x1E>;
+ dma-names = "rx", "tx";
+ };
+ ssiu45: ssiu-37 {
+ dmas = <&audma0 0x1F>, <&audma1 0x20>;
+ dma-names = "rx", "tx";
+ };
+ ssiu46: ssiu-38 {
+ dmas = <&audma0 0x31>, <&audma1 0x32>;
+ dma-names = "rx", "tx";
+ };
+ ssiu47: ssiu-39 {
+ dmas = <&audma0 0x33>, <&audma1 0x34>;
+ dma-names = "rx", "tx";
+ };
+ ssiu50: ssiu-40 {
+ dmas = <&audma0 0x73>, <&audma1 0x74>;
+ dma-names = "rx", "tx";
+ };
+ ssiu60: ssiu-41 {
+ dmas = <&audma0 0x75>, <&audma1 0x76>;
+ dma-names = "rx", "tx";
+ };
+ ssiu70: ssiu-42 {
+ dmas = <&audma0 0x79>, <&audma1 0x7a>;
+ dma-names = "rx", "tx";
+ };
+ ssiu80: ssiu-43 {
+ dmas = <&audma0 0x7b>, <&audma1 0x7c>;
+ dma-names = "rx", "tx";
+ };
+ ssiu90: ssiu-44 {
+ dmas = <&audma0 0x7d>, <&audma1 0x7e>;
+ dma-names = "rx", "tx";
+ };
+ ssiu91: ssiu-45 {
+ dmas = <&audma0 0x7F>, <&audma1 0x80>;
+ dma-names = "rx", "tx";
+ };
+ ssiu92: ssiu-46 {
+ dmas = <&audma0 0x81>, <&audma1 0x82>;
+ dma-names = "rx", "tx";
+ };
+ ssiu93: ssiu-47 {
+ dmas = <&audma0 0x83>, <&audma1 0x84>;
+ dma-names = "rx", "tx";
+ };
+ ssiu94: ssiu-48 {
+ dmas = <&audma0 0xA3>, <&audma1 0xA4>;
+ dma-names = "rx", "tx";
+ };
+ ssiu95: ssiu-49 {
+ dmas = <&audma0 0xA5>, <&audma1 0xA6>;
+ dma-names = "rx", "tx";
+ };
+ ssiu96: ssiu-50 {
+ dmas = <&audma0 0xA7>, <&audma1 0xA8>;
+ dma-names = "rx", "tx";
+ };
+ ssiu97: ssiu-51 {
+ dmas = <&audma0 0xA9>, <&audma1 0xAA>;
+ dma-names = "rx", "tx";
};
};
};
@@ -2506,6 +2746,18 @@
thermal-sensors = <&tsc 2>;
sustainable-power = <3874>;
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ cooling-device = <&a57_0 0 2>;
+ contribution = <1024>;
+ };
+ map1 {
+ trip = <&target>;
+ cooling-device = <&a53_0 0 2>;
+ contribution = <1024>;
+ };
+ };
trips {
target: trip-point1 {
temperature = <100000>;
@@ -2519,18 +2771,6 @@
type = "critical";
};
};
- cooling-maps {
- map0 {
- trip = <&target>;
- cooling-device = <&a57_0 0 2>;
- contribution = <1024>;
- };
- map1 {
- trip = <&target>;
- cooling-device = <&a53_0 0 2>;
- contribution = <1024>;
- };
- };
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
index 46a77eefa536..c99b1dec52ef 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
+++ b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
@@ -65,6 +65,15 @@
reg = <0x0 0x48000000 0x0 0x78000000>;
};
+ reg_12p0v: regulator-12p0v {
+ compatible = "regulator-fixed";
+ regulator-name = "D12.0V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
sound: sound {
compatible = "simple-audio-card";
@@ -73,13 +82,13 @@
simple-audio-card,bitclock-master = <&sndcpu>;
simple-audio-card,frame-master = <&sndcpu>;
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
-
sndcodec: simple-audio-card,codec {
sound-dai = <&tda19988>;
};
+
+ sndcpu: simple-audio-card,cpu {
+ sound-dai = <&rcar_sound>;
+ };
};
vcc_sdhi0: regulator-vcc-sdhi0 {
@@ -271,16 +280,16 @@
function = "du";
};
- i2c1_pins: i2c1 {
- groups = "i2c1_b";
- function = "i2c1";
- };
-
hscif2_pins: hscif2 {
groups = "hscif2_data_a", "hscif2_ctrl_a";
function = "hscif2";
};
+ i2c1_pins: i2c1 {
+ groups = "i2c1_b";
+ function = "i2c1";
+ };
+
scif2_pins: scif2 {
groups = "scif2_data_a";
function = "scif2";
@@ -304,16 +313,16 @@
power-source = <1800>;
};
- sound_pins: sound {
- groups = "ssi01239_ctrl", "ssi0_data";
- function = "ssi";
- };
-
sound_clk_pins: sound_clk {
groups = "audio_clkout1_a";
function = "audio_clk";
};
+ sound_pins: sound {
+ groups = "ssi01239_ctrl", "ssi0_data";
+ function = "ssi";
+ };
+
usb30_pins: usb30 {
groups = "usb30", "usb30_id";
function = "usb30";
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
index e7b5bf23f978..a1c2de90e470 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
@@ -973,6 +973,8 @@
<&cpg CPG_CORE R8A774C0_CLK_CANFD>,
<&can_clk>;
clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A774C0_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
resets = <&cpg 916>;
status = "disabled";
@@ -987,6 +989,8 @@
<&cpg CPG_CORE R8A774C0_CLK_CANFD>,
<&can_clk>;
clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A774C0_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
resets = <&cpg 915>;
status = "disabled";
@@ -1367,6 +1371,17 @@
"ssi.1", "ssi.0";
status = "disabled";
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
rcar_sound,dvc {
dvc0: dvc-0 {
dmas = <&audma0 0xbc>;
@@ -1383,17 +1398,6 @@
mix1: mix-1 { };
};
- rcar_sound,ctu {
- ctu00: ctu-0 { };
- ctu01: ctu-1 { };
- ctu02: ctu-2 { };
- ctu03: ctu-3 { };
- ctu10: ctu-4 { };
- ctu11: ctu-5 { };
- ctu12: ctu-6 { };
- ctu13: ctu-7 { };
- };
-
rcar_sound,src {
src0: src-0 {
interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
@@ -1702,13 +1706,24 @@
renesas,fcp = <&fcpvb0>;
};
- fcpvb0: fcp@fe96f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfe96f000 0 0x200>;
- clocks = <&cpg CPG_MOD 607>;
+ vspd0: vsp@fea20000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea20000 0 0x7000>;
+ interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 623>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
- resets = <&cpg 607>;
- iommus = <&ipmmu_vp0 5>;
+ resets = <&cpg 623>;
+ renesas,fcp = <&fcpvd0>;
+ };
+
+ vspd1: vsp@fea28000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea28000 0 0x7000>;
+ interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 622>;
+ power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+ resets = <&cpg 622>;
+ renesas,fcp = <&fcpvd1>;
};
vspi0: vsp@fe9a0000 {
@@ -1721,23 +1736,13 @@
renesas,fcp = <&fcpvi0>;
};
- fcpvi0: fcp@fe9af000 {
+ fcpvb0: fcp@fe96f000 {
compatible = "renesas,fcpv";
- reg = <0 0xfe9af000 0 0x200>;
- clocks = <&cpg CPG_MOD 611>;
- power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
- resets = <&cpg 611>;
- iommus = <&ipmmu_vp0 8>;
- };
-
- vspd0: vsp@fea20000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfea20000 0 0x7000>;
- interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 623>;
+ reg = <0 0xfe96f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 607>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
- resets = <&cpg 623>;
- renesas,fcp = <&fcpvd0>;
+ resets = <&cpg 607>;
+ iommus = <&ipmmu_vp0 5>;
};
fcpvd0: fcp@fea27000 {
@@ -1749,16 +1754,6 @@
iommus = <&ipmmu_vi0 8>;
};
- vspd1: vsp@fea28000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfea28000 0 0x7000>;
- interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 622>;
- power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
- resets = <&cpg 622>;
- renesas,fcp = <&fcpvd1>;
- };
-
fcpvd1: fcp@fea2f000 {
compatible = "renesas,fcpv";
reg = <0 0xfea2f000 0 0x200>;
@@ -1768,6 +1763,15 @@
iommus = <&ipmmu_vi0 9>;
};
+ fcpvi0: fcp@fe9af000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe9af000 0 0x200>;
+ clocks = <&cpg CPG_MOD 611>;
+ power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+ resets = <&cpg 611>;
+ iommus = <&ipmmu_vp0 8>;
+ };
+
csi40: csi2@feaa0000 {
compatible = "renesas,r8a774c0-csi2";
reg = <0 0xfeaa0000 0 0x10000>;
@@ -1801,13 +1805,13 @@
du: display@feb00000 {
compatible = "renesas,du-r8a774c0";
- reg = <0 0xfeb00000 0 0x80000>;
+ reg = <0 0xfeb00000 0 0x40000>;
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 724>,
<&cpg CPG_MOD 723>;
clock-names = "du.0", "du.1";
- vsps = <&vspd0 0 &vspd1 0>;
+ vsps = <&vspd0 0>, <&vspd1 0>;
status = "disabled";
ports {
@@ -1844,6 +1848,8 @@
resets = <&cpg 727>;
status = "disabled";
+ renesas,companion = <&lvds1>;
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -1902,6 +1908,9 @@
polling-delay = <1000>;
thermal-sensors = <&thermal>;
+ cooling-maps {
+ };
+
trips {
cpu-crit {
temperature = <120000>;
@@ -1909,9 +1918,6 @@
type = "critical";
};
};
-
- cooling-maps {
- };
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
index c1a56eab7b24..c72968623e94 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
@@ -52,12 +52,6 @@
status = "okay";
};
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
&hdmi0 {
status = "okay";
@@ -108,6 +102,13 @@
status = "okay";
};
+&pfc {
+ usb2_pins: usb2 {
+ groups = "usb2";
+ function = "usb2";
+ };
+};
+
&rcar_sound {
ports {
/* rsnd_port0 is on salvator-common */
@@ -138,17 +139,16 @@
};
};
-&pfc {
- usb2_pins: usb2 {
- groups = "usb2";
- function = "usb2";
- };
-};
-
&sata {
status = "okay";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&usb2_phy2 {
pinctrl-0 = <&usb2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
index 40d10daca852..e4650ae5b75a 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
@@ -7,22 +7,75 @@
#include "r8a7795.dtsi"
-&soc {
- xhci1: usb@ee040000 {
- compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci";
- reg = <0 0xee040000 0 0xc00>;
- interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 327>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 327>;
- status = "disabled";
- };
+&audma0 {
+ iommus = <&ipmmu_mp1 0>, <&ipmmu_mp1 1>,
+ <&ipmmu_mp1 2>, <&ipmmu_mp1 3>,
+ <&ipmmu_mp1 4>, <&ipmmu_mp1 5>,
+ <&ipmmu_mp1 6>, <&ipmmu_mp1 7>,
+ <&ipmmu_mp1 8>, <&ipmmu_mp1 9>,
+ <&ipmmu_mp1 10>, <&ipmmu_mp1 11>,
+ <&ipmmu_mp1 12>, <&ipmmu_mp1 13>,
+ <&ipmmu_mp1 14>, <&ipmmu_mp1 15>;
+};
- /delete-node/ mmu@febe0000;
- /delete-node/ mmu@fe980000;
- /delete-node/ mmu@fd950000;
- /delete-node/ mmu@fd960000;
- /delete-node/ mmu@fd970000;
+&audma1 {
+ iommus = <&ipmmu_mp1 16>, <&ipmmu_mp1 17>,
+ <&ipmmu_mp1 18>, <&ipmmu_mp1 19>,
+ <&ipmmu_mp1 20>, <&ipmmu_mp1 21>,
+ <&ipmmu_mp1 22>, <&ipmmu_mp1 23>,
+ <&ipmmu_mp1 24>, <&ipmmu_mp1 25>,
+ <&ipmmu_mp1 26>, <&ipmmu_mp1 27>,
+ <&ipmmu_mp1 28>, <&ipmmu_mp1 29>,
+ <&ipmmu_mp1 30>, <&ipmmu_mp1 31>;
+};
+
+&du {
+ vsps = <&vspd0 &vspd1 &vspd2 &vspd3>;
+};
+
+&fcpvb1 {
+ iommus = <&ipmmu_vp0 7>;
+};
+
+&fcpf1 {
+ iommus = <&ipmmu_vp0 1>;
+};
+
+&fcpvi1 {
+ iommus = <&ipmmu_vp0 9>;
+};
+
+&fcpvd2 {
+ iommus = <&ipmmu_vi0 10>;
+};
+
+&gpio1 {
+ gpio-ranges = <&pfc 0 32 28>;
+};
+
+&ipmmu_vi0 {
+ renesas,ipmmu-main = <&ipmmu_mm 11>;
+};
+
+&ipmmu_vp0 {
+ renesas,ipmmu-main = <&ipmmu_mm 12>;
+};
+
+&ipmmu_vc0 {
+ renesas,ipmmu-main = <&ipmmu_mm 9>;
+};
+
+&ipmmu_vc1 {
+ renesas,ipmmu-main = <&ipmmu_mm 10>;
+};
+
+&ipmmu_rt {
+ renesas,ipmmu-main = <&ipmmu_mm 7>;
+};
+
+&soc {
+ /delete-node/ dma-controller@e6460000;
+ /delete-node/ dma-controller@e6470000;
ipmmu_mp1: mmu@ec680000 {
compatible = "renesas,ipmmu-r8a7795";
@@ -40,13 +93,37 @@
#iommu-cells = <1>;
};
- /delete-node/ usb-phy@ee0e0200;
- /delete-node/ usb@ee0e0100;
- /delete-node/ usb@ee0e0000;
+ /delete-node/ mmu@fd950000;
+ /delete-node/ mmu@fd960000;
+ /delete-node/ mmu@fd970000;
+ /delete-node/ mmu@febe0000;
+ /delete-node/ mmu@fe980000;
+
+ xhci1: usb@ee040000 {
+ compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci";
+ reg = <0 0xee040000 0 0xc00>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 327>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 327>;
+ status = "disabled";
+ };
+
/delete-node/ usb@e659c000;
+ /delete-node/ usb@ee0e0000;
+ /delete-node/ usb@ee0e0100;
- /delete-node/ dma-controller@e6460000;
- /delete-node/ dma-controller@e6470000;
+ /delete-node/ usb-phy@ee0e0200;
+
+ fdp1@fe948000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe948000 0 0x2400>;
+ interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 117>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 117>;
+ renesas,fcp = <&fcpf2>;
+ };
fcpf2: fcp@fe952000 {
compatible = "renesas,fcpf";
@@ -57,15 +134,13 @@
iommus = <&ipmmu_vp0 2>;
};
- vspi2: vsp@fe9c0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9c0000 0 0x8000>;
- interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 629>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 629>;
-
- renesas,fcp = <&fcpvi2>;
+ fcpvd3: fcp@fea3f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea3f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 600>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 600>;
+ iommus = <&ipmmu_vi0 11>;
};
fcpvi2: fcp@fe9cf000 {
@@ -88,23 +163,15 @@
renesas,fcp = <&fcpvd3>;
};
- fcpvd3: fcp@fea3f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea3f000 0 0x200>;
- clocks = <&cpg CPG_MOD 600>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 600>;
- iommus = <&ipmmu_vi0 11>;
- };
-
- fdp1@fe948000 {
- compatible = "renesas,fdp1";
- reg = <0 0xfe948000 0 0x2400>;
- interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 117>;
+ vspi2: vsp@fe9c0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9c0000 0 0x8000>;
+ interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 629>;
power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 117>;
- renesas,fcp = <&fcpf2>;
+ resets = <&cpg 629>;
+
+ renesas,fcp = <&fcpvi2>;
};
csi21: csi2@fea90000 {
@@ -163,72 +230,6 @@
};
};
-&gpio1 {
- gpio-ranges = <&pfc 0 32 28>;
-};
-
-&ipmmu_vi0 {
- renesas,ipmmu-main = <&ipmmu_mm 11>;
-};
-
-&ipmmu_vp0 {
- renesas,ipmmu-main = <&ipmmu_mm 12>;
-};
-
-&ipmmu_vc0 {
- renesas,ipmmu-main = <&ipmmu_mm 9>;
-};
-
-&ipmmu_vc1 {
- renesas,ipmmu-main = <&ipmmu_mm 10>;
-};
-
-&ipmmu_rt {
- renesas,ipmmu-main = <&ipmmu_mm 7>;
-};
-
-&audma0 {
- iommus = <&ipmmu_mp1 0>, <&ipmmu_mp1 1>,
- <&ipmmu_mp1 2>, <&ipmmu_mp1 3>,
- <&ipmmu_mp1 4>, <&ipmmu_mp1 5>,
- <&ipmmu_mp1 6>, <&ipmmu_mp1 7>,
- <&ipmmu_mp1 8>, <&ipmmu_mp1 9>,
- <&ipmmu_mp1 10>, <&ipmmu_mp1 11>,
- <&ipmmu_mp1 12>, <&ipmmu_mp1 13>,
- <&ipmmu_mp1 14>, <&ipmmu_mp1 15>;
-};
-
-&audma1 {
- iommus = <&ipmmu_mp1 16>, <&ipmmu_mp1 17>,
- <&ipmmu_mp1 18>, <&ipmmu_mp1 19>,
- <&ipmmu_mp1 20>, <&ipmmu_mp1 21>,
- <&ipmmu_mp1 22>, <&ipmmu_mp1 23>,
- <&ipmmu_mp1 24>, <&ipmmu_mp1 25>,
- <&ipmmu_mp1 26>, <&ipmmu_mp1 27>,
- <&ipmmu_mp1 28>, <&ipmmu_mp1 29>,
- <&ipmmu_mp1 30>, <&ipmmu_mp1 31>;
-};
-
-&fcpvb1 {
- iommus = <&ipmmu_vp0 7>;
-};
-
-&fcpf1 {
- iommus = <&ipmmu_vp0 1>;
-};
-
-&fcpvi1 {
- iommus = <&ipmmu_vp0 9>;
-};
-
-&fcpvd2 {
- iommus = <&ipmmu_vi0 10>;
-};
-
-&du {
- vsps = <&vspd0 &vspd1 &vspd2 &vspd3>;
-};
-
&vin0 {
ports {
port@1 {
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
index d2d48b33b37f..72874f675359 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
@@ -52,12 +52,6 @@
status = "okay";
};
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
&hdmi0 {
status = "okay";
@@ -108,6 +102,13 @@
status = "okay";
};
+&pfc {
+ usb2_pins: usb2 {
+ groups = "usb2";
+ function = "usb2";
+ };
+};
+
&rcar_sound {
ports {
/* rsnd_port0 is on salvator-common */
@@ -138,17 +139,16 @@
};
};
-&pfc {
- usb2_pins: usb2 {
- groups = "usb2";
- function = "usb2";
- };
-};
-
&sata {
status = "okay";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&usb2_phy2 {
pinctrl-0 = <&usb2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
index 42101fc76837..36667c81d43d 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
@@ -57,17 +57,6 @@
status = "okay";
};
-&hsusb3 {
- dr_mode = "otg";
- status = "okay";
-};
-
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
&hdmi0 {
status = "okay";
@@ -114,6 +103,11 @@
remote-endpoint = <&rcar_dw_hdmi1_out>;
};
+&hsusb3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
&ohci2 {
status = "okay";
};
@@ -123,36 +117,6 @@
status = "okay";
};
-&rcar_sound {
- ports {
- /* rsnd_port0 is on salvator-common */
- rsnd_port1: port@1 {
- reg = <1>;
- rsnd_endpoint1: endpoint {
- remote-endpoint = <&dw_hdmi0_snd_in>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_endpoint1>;
- frame-master = <&rsnd_endpoint1>;
-
- playback = <&ssi2>;
- };
- };
- rsnd_port2: port@2 {
- reg = <2>;
- rsnd_endpoint2: endpoint {
- remote-endpoint = <&dw_hdmi1_snd_in>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_endpoint2>;
- frame-master = <&rsnd_endpoint2>;
-
- playback = <&ssi3>;
- };
- };
- };
-};
-
&pca9654 {
pcie_sata_switch {
gpio-hog;
@@ -186,11 +150,47 @@
};
};
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ reg = <1>;
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ rsnd_port2: port@2 {
+ reg = <2>;
+ rsnd_endpoint2: endpoint {
+ remote-endpoint = <&dw_hdmi1_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint2>;
+ frame-master = <&rsnd_endpoint2>;
+
+ playback = <&ssi3>;
+ };
+ };
+ };
+};
+
/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */
&sata {
status = "okay";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&usb2_phy2 {
pinctrl-0 = <&usb2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index 1745ac4b307e..95deff66eeb6 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -2731,6 +2731,83 @@
resets = <&cpg 820>;
};
+ vspbc: vsp@fe920000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe920000 0 0x8000>;
+ interrupts = <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 624>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 624>;
+
+ renesas,fcp = <&fcpvb1>;
+ };
+
+ vspbd: vsp@fe960000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe960000 0 0x8000>;
+ interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 626>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 626>;
+
+ renesas,fcp = <&fcpvb0>;
+ };
+
+ vspd0: vsp@fea20000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea20000 0 0x5000>;
+ interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 623>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 623>;
+
+ renesas,fcp = <&fcpvd0>;
+ };
+
+ vspd1: vsp@fea28000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea28000 0 0x5000>;
+ interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 622>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 622>;
+
+ renesas,fcp = <&fcpvd1>;
+ };
+
+ vspd2: vsp@fea30000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea30000 0 0x5000>;
+ interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 621>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 621>;
+
+ renesas,fcp = <&fcpvd2>;
+ };
+
+ vspi0: vsp@fe9a0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9a0000 0 0x8000>;
+ interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 631>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 631>;
+
+ renesas,fcp = <&fcpvi0>;
+ };
+
+ vspi1: vsp@fe9b0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9b0000 0 0x8000>;
+ interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 630>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 630>;
+
+ renesas,fcp = <&fcpvi1>;
+ };
+
fdp1@fe940000 {
compatible = "renesas,fdp1";
reg = <0 0xfe940000 0 0x2400>;
@@ -2832,83 +2909,6 @@
iommus = <&ipmmu_vi1 10>;
};
- vspbd: vsp@fe960000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe960000 0 0x8000>;
- interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 626>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 626>;
-
- renesas,fcp = <&fcpvb0>;
- };
-
- vspbc: vsp@fe920000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe920000 0 0x8000>;
- interrupts = <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 624>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 624>;
-
- renesas,fcp = <&fcpvb1>;
- };
-
- vspd0: vsp@fea20000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfea20000 0 0x5000>;
- interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 623>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 623>;
-
- renesas,fcp = <&fcpvd0>;
- };
-
- vspd1: vsp@fea28000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfea28000 0 0x5000>;
- interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 622>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 622>;
-
- renesas,fcp = <&fcpvd1>;
- };
-
- vspd2: vsp@fea30000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfea30000 0 0x5000>;
- interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 621>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 621>;
-
- renesas,fcp = <&fcpvd2>;
- };
-
- vspi0: vsp@fe9a0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9a0000 0 0x8000>;
- interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 631>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 631>;
-
- renesas,fcp = <&fcpvi0>;
- };
-
- vspi1: vsp@fe9b0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9b0000 0 0x8000>;
- interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 630>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 630>;
-
- renesas,fcp = <&fcpvi1>;
- };
-
csi20: csi2@fea80000 {
compatible = "renesas,r8a7795-csi2";
reg = <0 0xfea80000 0 0x10000>;
@@ -3112,7 +3112,7 @@
<&cpg CPG_MOD 722>,
<&cpg CPG_MOD 721>;
clock-names = "du.0", "du.1", "du.2", "du.3";
- vsps = <&vspd0 0 &vspd1 0 &vspd2 0 &vspd0 1>;
+ vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
status = "disabled";
ports {
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
index 2aefa53cb16b..de37e91e3b7a 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
@@ -36,11 +36,6 @@
"dclkin.0", "dclkin.1", "dclkin.2";
};
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1>; /* HDMI0 */
-};
-
&hdmi0 {
status = "okay";
@@ -81,3 +76,8 @@
};
};
};
+
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
index d58ede18108d..a1cbfef2053f 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
@@ -36,11 +36,6 @@
"dclkin.0", "dclkin.1", "dclkin.2";
};
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1>; /* HDMI0 */
-};
-
&hdmi0 {
status = "okay";
@@ -81,3 +76,8 @@
};
};
};
+
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 26df5b88efd7..3dc9d73f589a 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -1833,6 +1833,17 @@
"ssi.1", "ssi.0";
status = "disabled";
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
rcar_sound,dvc {
dvc0: dvc-0 {
dmas = <&audma1 0xbc>;
@@ -1849,17 +1860,6 @@
mix1: mix-1 { };
};
- rcar_sound,ctu {
- ctu00: ctu-0 { };
- ctu01: ctu-1 { };
- ctu02: ctu-2 { };
- ctu03: ctu-3 { };
- ctu10: ctu-4 { };
- ctu11: ctu-5 { };
- ctu12: ctu-6 { };
- ctu13: ctu-7 { };
- };
-
rcar_sound,src {
src0: src-0 {
interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
@@ -1913,6 +1913,59 @@
};
};
+ rcar_sound,ssi {
+ ssi0: ssi-0 {
+ interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x01>, <&audma1 0x02>;
+ dma-names = "rx", "tx";
+ };
+ ssi1: ssi-1 {
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x03>, <&audma1 0x04>;
+ dma-names = "rx", "tx";
+ };
+ ssi2: ssi-2 {
+ interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x05>, <&audma1 0x06>;
+ dma-names = "rx", "tx";
+ };
+ ssi3: ssi-3 {
+ interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x07>, <&audma1 0x08>;
+ dma-names = "rx", "tx";
+ };
+ ssi4: ssi-4 {
+ interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x09>, <&audma1 0x0a>;
+ dma-names = "rx", "tx";
+ };
+ ssi5: ssi-5 {
+ interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x0b>, <&audma1 0x0c>;
+ dma-names = "rx", "tx";
+ };
+ ssi6: ssi-6 {
+ interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x0d>, <&audma1 0x0e>;
+ dma-names = "rx", "tx";
+ };
+ ssi7: ssi-7 {
+ interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x0f>, <&audma1 0x10>;
+ dma-names = "rx", "tx";
+ };
+ ssi8: ssi-8 {
+ interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x11>, <&audma1 0x12>;
+ dma-names = "rx", "tx";
+ };
+ ssi9: ssi-9 {
+ interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x13>, <&audma1 0x14>;
+ dma-names = "rx", "tx";
+ };
+ };
+
rcar_sound,ssiu {
ssiu00: ssiu-0 {
dmas = <&audma0 0x15>, <&audma1 0x16>;
@@ -2123,59 +2176,6 @@
dma-names = "rx", "tx";
};
};
-
- rcar_sound,ssi {
- ssi0: ssi-0 {
- interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x01>, <&audma1 0x02>;
- dma-names = "rx", "tx";
- };
- ssi1: ssi-1 {
- interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x03>, <&audma1 0x04>;
- dma-names = "rx", "tx";
- };
- ssi2: ssi-2 {
- interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x05>, <&audma1 0x06>;
- dma-names = "rx", "tx";
- };
- ssi3: ssi-3 {
- interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x07>, <&audma1 0x08>;
- dma-names = "rx", "tx";
- };
- ssi4: ssi-4 {
- interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x09>, <&audma1 0x0a>;
- dma-names = "rx", "tx";
- };
- ssi5: ssi-5 {
- interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0b>, <&audma1 0x0c>;
- dma-names = "rx", "tx";
- };
- ssi6: ssi-6 {
- interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0d>, <&audma1 0x0e>;
- dma-names = "rx", "tx";
- };
- ssi7: ssi-7 {
- interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x0f>, <&audma1 0x10>;
- dma-names = "rx", "tx";
- };
- ssi8: ssi-8 {
- interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x11>, <&audma1 0x12>;
- dma-names = "rx", "tx";
- };
- ssi9: ssi-9 {
- interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x13>, <&audma1 0x14>;
- dma-names = "rx", "tx";
- };
- };
};
audma0: dma-controller@ec700000 {
@@ -2860,6 +2860,18 @@
thermal-sensors = <&tsc 2>;
sustainable-power = <3874>;
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ cooling-device = <&a57_0 2 4>;
+ contribution = <1024>;
+ };
+ map1 {
+ trip = <&target>;
+ cooling-device = <&a53_0 0 2>;
+ contribution = <1024>;
+ };
+ };
trips {
target: trip-point1 {
temperature = <100000>;
@@ -2873,18 +2885,6 @@
type = "critical";
};
};
- cooling-maps {
- map0 {
- trip = <&target>;
- cooling-device = <&a57_0 2 4>;
- contribution = <1024>;
- };
- map1 {
- trip = <&target>;
- cooling-device = <&a53_0 0 2>;
- contribution = <1024>;
- };
- };
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
index 340a3c72b65a..660a0240eec5 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
@@ -41,9 +41,37 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
&hdmi0_con {
remote-endpoint = <&rcar_dw_hdmi0_out>;
};
+
+&rcar_sound {
+ ports {
+ rsnd_port1: port@1 {
+ reg = <1>;
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ };
+};
+
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
index f03a5e9e0c42..5cef64605464 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
@@ -41,6 +41,12 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
@@ -57,7 +63,29 @@
};
};
+&rcar_sound {
+ ports {
+ rsnd_port1: port@1 {
+ reg = <1>;
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ };
+};
+
/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */
&sata {
status = "okay";
};
+
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index 131f895ab778..4ae163220f60 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -2255,14 +2255,6 @@
renesas,fcp = <&fcpvb0>;
};
- fcpvb0: fcp@fe96f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfe96f000 0 0x200>;
- clocks = <&cpg CPG_MOD 607>;
- power-domains = <&sysc R8A77965_PD_A3VP>;
- resets = <&cpg 607>;
- };
-
vspi0: vsp@fe9a0000 {
compatible = "renesas,vsp2";
reg = <0 0xfe9a0000 0 0x8000>;
@@ -2274,14 +2266,6 @@
renesas,fcp = <&fcpvi0>;
};
- fcpvi0: fcp@fe9af000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfe9af000 0 0x200>;
- clocks = <&cpg CPG_MOD 611>;
- power-domains = <&sysc R8A77965_PD_A3VP>;
- resets = <&cpg 611>;
- };
-
vspd0: vsp@fea20000 {
compatible = "renesas,vsp2";
reg = <0 0xfea20000 0 0x5000>;
@@ -2293,14 +2277,6 @@
renesas,fcp = <&fcpvd0>;
};
- fcpvd0: fcp@fea27000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea27000 0 0x200>;
- clocks = <&cpg CPG_MOD 603>;
- power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
- resets = <&cpg 603>;
- };
-
vspd1: vsp@fea28000 {
compatible = "renesas,vsp2";
reg = <0 0xfea28000 0 0x5000>;
@@ -2312,6 +2288,22 @@
renesas,fcp = <&fcpvd1>;
};
+ fcpvb0: fcp@fe96f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe96f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 607>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 607>;
+ };
+
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
+ };
+
fcpvd1: fcp@fea2f000 {
compatible = "renesas,fcpv";
reg = <0 0xfea2f000 0 0x200>;
@@ -2320,6 +2312,14 @@
resets = <&cpg 602>;
};
+ fcpvi0: fcp@fe9af000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe9af000 0 0x200>;
+ clocks = <&cpg CPG_MOD 611>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 611>;
+ };
+
csi20: csi2@fea80000 {
compatible = "renesas,r8a77965-csi2";
reg = <0 0xfea80000 0 0x10000>;
@@ -2469,7 +2469,7 @@
clock-names = "du.0", "du.1", "du.3";
status = "disabled";
- vsps = <&vspd0 0 &vspd1 0 &vspd0 1>;
+ vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>;
ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
index 233f26fbec17..2afb91ec9c8d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
@@ -23,10 +23,13 @@
stdout-path = "serial0:115200n8";
};
- memory@48000000 {
- device_type = "memory";
- /* first 128MB is reserved for secure area. */
- reg = <0x0 0x48000000 0x0 0x38000000>;
+ d3p3: regulator-fixed {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
};
hdmi-out {
@@ -40,15 +43,6 @@
};
};
- d3p3: regulator-fixed {
- compatible = "regulator-fixed";
- regulator-name = "fixed-3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
lvds-decoder {
compatible = "thine,thc63lvd1024";
@@ -73,6 +67,12 @@
};
};
};
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
+ };
};
&avb {
@@ -102,6 +102,10 @@
};
};
+&du {
+ status = "okay";
+};
+
&extal_clk {
clock-frequency = <16666666>;
};
@@ -157,6 +161,18 @@
};
};
+&lvds0 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ lvds0_out: endpoint {
+ remote-endpoint = <&thc63lvd1024_in>;
+ };
+ };
+ };
+};
+
&pfc {
avb_pins: avb0 {
groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
@@ -190,19 +206,3 @@
status = "okay";
};
-
-&du {
- status = "okay";
-};
-
-&lvds0 {
- status = "okay";
-
- ports {
- port@1 {
- lvds0_out: endpoint {
- remote-endpoint = <&thc63lvd1024_in>;
- };
- };
- };
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
index 15cc9fed2e16..d7c7b9156e08 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
@@ -21,6 +21,41 @@
stdout-path = "serial0:115200n8";
};
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&adv7511_out>;
+ };
+ };
+ };
+
+ lvds-decoder {
+ compatible = "thine,thc63lvd1024";
+ vcc-supply = <&vcc_d3_3v>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ thc63lvd1024_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ thc63lvd1024_out: endpoint {
+ remote-endpoint = <&adv7511_in>;
+ };
+ };
+ };
+ };
+
memory@48000000 {
device_type = "memory";
/* first 128MB is reserved for secure area. */
@@ -59,41 +94,6 @@
regulator-boot-on;
regulator-always-on;
};
-
- lvds-decoder {
- compatible = "thine,thc63lvd1024";
- vcc-supply = <&vcc_d3_3v>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- thc63lvd1024_in: endpoint {
- remote-endpoint = <&lvds0_out>;
- };
- };
-
- port@2 {
- reg = <2>;
- thc63lvd1024_out: endpoint {
- remote-endpoint = <&adv7511_in>;
- };
- };
- };
- };
-
- hdmi-out {
- compatible = "hdmi-connector";
- type = "a";
-
- port {
- hdmi_con: endpoint {
- remote-endpoint = <&adv7511_out>;
- };
- };
- };
};
&avb {
@@ -128,29 +128,6 @@
clock-frequency = <32768>;
};
-&pfc {
- avb_pins: avb0 {
- groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
- function = "avb0";
- };
-
- i2c0_pins: i2c0 {
- groups = "i2c0";
- function = "i2c0";
- };
-
- mmc_pins: mmc_3_3v {
- groups = "mmc_data8", "mmc_ctrl";
- function = "mmc";
- power-source = <3300>;
- };
-
- scif0_pins: scif0 {
- groups = "scif0_data";
- function = "scif0";
- };
-};
-
&i2c0 {
pinctrl-0 = <&i2c0_pins>;
pinctrl-names = "default";
@@ -220,6 +197,29 @@
status = "okay";
};
+&pfc {
+ avb_pins: avb0 {
+ groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
+ function = "avb0";
+ };
+
+ i2c0_pins: i2c0 {
+ groups = "i2c0";
+ function = "i2c0";
+ };
+
+ mmc_pins: mmc_3_3v {
+ groups = "mmc_data8", "mmc_ctrl";
+ function = "mmc";
+ power-source = <3300>;
+ };
+
+ scif0_pins: scif0 {
+ groups = "scif0_data";
+ function = "scif0";
+ };
+};
+
&scif0 {
pinctrl-0 = <&scif0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
index 5b6164d4b8e3..0cd3b376635d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
@@ -1181,6 +1181,9 @@
polling-delay = <1000>;
thermal-sensors = <&thermal>;
+ cooling-maps {
+ };
+
trips {
cpu-crit {
temperature = <120000>;
@@ -1188,9 +1191,6 @@
type = "critical";
};
};
-
- cooling-maps {
- };
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
index 5a7012be0d6a..3dde028e22a6 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
@@ -22,35 +22,20 @@
stdout-path = "serial0:115200n8";
};
- memory@48000000 {
- device_type = "memory";
- /* first 128MB is reserved for secure area. */
- reg = <0 0x48000000 0 0x78000000>;
- };
-
- d3_3v: regulator-0 {
- compatible = "regulator-fixed";
- regulator-name = "D3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- vddq_vin01: regulator-1 {
+ d1_8v: regulator-2 {
compatible = "regulator-fixed";
- regulator-name = "VDDQ_VIN01";
+ regulator-name = "D1.8V";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
- d1_8v: regulator-2 {
+ d3_3v: regulator-0 {
compatible = "regulator-fixed";
- regulator-name = "D1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
+ regulator-name = "D3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
@@ -90,6 +75,21 @@
};
};
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0 0x48000000 0 0x78000000>;
+ };
+
+ vddq_vin01: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDQ_VIN01";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
x1_clk: x1-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
index dd14a41b32cd..adbfd8f07d06 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
@@ -22,12 +22,6 @@
stdout-path = "serial0:115200n8";
};
- memory@48000000 {
- device_type = "memory";
- /* first 128MB is reserved for secure area. */
- reg = <0 0x48000000 0 0x78000000>;
- };
-
hdmi-out {
compatible = "hdmi-connector";
type = "a";
@@ -63,6 +57,12 @@
};
};
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0 0x48000000 0 0x78000000>;
+ };
+
osc1_clk: osc1-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
index a901a341dcf7..461a47ea656d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -1299,9 +1299,9 @@
#iommu-cells = <1>;
};
- ipmmu_vc0: mmu@fe6b0000 {
+ ipmmu_vc0: mmu@fe990000 {
compatible = "renesas,ipmmu-r8a77980";
- reg = <0 0xfe6b0000 0 0x1000>;
+ reg = <0 0xfe990000 0 0x1000>;
renesas,ipmmu-main = <&ipmmu_mm 12>;
power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
#iommu-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 83fc13ac3fa1..b38f9d442fc0 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -23,12 +23,6 @@
stdout-path = "serial0:115200n8";
};
- memory@48000000 {
- device_type = "memory";
- /* first 128MB is reserved for secure area. */
- reg = <0x0 0x48000000 0x0 0x38000000>;
- };
-
audio_clkout: audio-clkout {
/*
* This is same as <&rcar_sound 0>
@@ -107,36 +101,10 @@
};
};
- vga {
- compatible = "vga-connector";
-
- port {
- vga_in: endpoint {
- remote-endpoint = <&adv7123_out>;
- };
- };
- };
-
- vga-encoder {
- compatible = "adi,adv7123";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- adv7123_in: endpoint {
- remote-endpoint = <&du_out_rgb>;
- };
- };
- port@1 {
- reg = <1>;
- adv7123_out: endpoint {
- remote-endpoint = <&vga_in>;
- };
- };
- };
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
};
reg_1p8v: regulator0 {
@@ -157,15 +125,13 @@
regulator-always-on;
};
- vbus0_usb2: regulator-vbus0-usb2 {
+ reg_12p0v: regulator2 {
compatible = "regulator-fixed";
-
- regulator-name = "USB20_VBUS_CN";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
-
- gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>;
- enable-active-high;
+ regulator-name = "D12.0V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-boot-on;
+ regulator-always-on;
};
rsnd_ak4613: sound {
@@ -176,34 +142,24 @@
simple-audio-card,bitclock-master = <&sndcpu>;
simple-audio-card,frame-master = <&sndcpu>;
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
-
sndcodec: simple-audio-card,codec {
sound-dai = <&ak4613>;
};
- };
- x12_clk: x12 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24576000>;
+ sndcpu: simple-audio-card,cpu {
+ sound-dai = <&rcar_sound>;
+ };
};
- reg_12p0v: regulator2 {
+ vbus0_usb2: regulator-vbus0-usb2 {
compatible = "regulator-fixed";
- regulator-name = "D12.0V";
- regulator-min-microvolt = <12000000>;
- regulator-max-microvolt = <12000000>;
- regulator-boot-on;
- regulator-always-on;
- };
- x13_clk: x13 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <74250000>;
+ regulator-name = "USB20_VBUS_CN";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
vcc_sdhi0: regulator-vcc-sdhi0 {
@@ -253,6 +209,50 @@
states = <3300000 1
1800000 0>;
};
+
+ vga {
+ compatible = "vga-connector";
+
+ port {
+ vga_in: endpoint {
+ remote-endpoint = <&adv7123_out>;
+ };
+ };
+ };
+
+ vga-encoder {
+ compatible = "adi,adv7123";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7123_in: endpoint {
+ remote-endpoint = <&du_out_rgb>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ adv7123_out: endpoint {
+ remote-endpoint = <&vga_in>;
+ };
+ };
+ };
+ };
+
+ x12_clk: x12 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
+
+ x13_clk: x13 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <74250000>;
+ };
};
&audio_clk_a {
@@ -271,6 +271,14 @@
interrupt-parent = <&gpio2>;
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+ /*
+ * TX clock internal delay mode is required for reliable
+ * 1Gbps communication using the KSZ9031RNX phy present on
+ * the Ebisu board, however, TX clock internal delay mode
+ * isn't supported on r8a77990. Thus, limit speed to
+ * 100Mbps for reliable communication.
+ */
+ max-speed = <100>;
};
};
@@ -547,6 +555,11 @@
function = "pwm5";
};
+ scif2_pins: scif2 {
+ groups = "scif2_data_a";
+ function = "scif2";
+ };
+
sdhi0_pins: sd0 {
groups = "sdhi0_data4", "sdhi0_ctrl";
function = "sdhi0";
@@ -577,20 +590,15 @@
power-source = <1800>;
};
- sound_pins: sound {
- groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data";
- function = "ssi";
- };
-
sound_clk_pins: sound_clk {
groups = "audio_clk_a", "audio_clk_b_a", "audio_clk_c_a",
"audio_clkout_a", "audio_clkout1_a";
function = "audio_clk";
};
- scif2_pins: scif2 {
- groups = "scif2_data_a";
- function = "scif2";
+ sound_pins: sound {
+ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data";
+ function = "ssi";
};
usb0_pins: usb {
@@ -671,38 +679,6 @@
status = "okay";
};
-&ssi1 {
- shared-pin;
-};
-
-&usb2_phy0 {
- pinctrl-0 = <&usb0_pins>;
- pinctrl-names = "default";
-
- vbus-supply = <&vbus0_usb2>;
- status = "okay";
-};
-
-&usb3_peri0 {
- companion = <&xhci0>;
- status = "okay";
-};
-
-&vin4 {
- status = "okay";
-};
-
-&vin5 {
- status = "okay";
-};
-
-&xhci0 {
- pinctrl-0 = <&usb30_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
-
&sdhi0 {
pinctrl-0 = <&sdhi0_pins>;
pinctrl-1 = <&sdhi0_pins_uhs>;
@@ -746,3 +722,35 @@
non-removable;
status = "okay";
};
+
+&ssi1 {
+ shared-pin;
+};
+
+&usb2_phy0 {
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
+
+ vbus-supply = <&vbus0_usb2>;
+ status = "okay";
+};
+
+&usb3_peri0 {
+ companion = <&xhci0>;
+ status = "okay";
+};
+
+&vin4 {
+ status = "okay";
+};
+
+&vin5 {
+ status = "okay";
+};
+
+&xhci0 {
+ pinctrl-0 = <&usb30_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index b4318661f35e..455954c3d98e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -1326,6 +1326,17 @@
"ssi.1", "ssi.0";
status = "disabled";
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
rcar_sound,dvc {
dvc0: dvc-0 {
dmas = <&audma0 0xbc>;
@@ -1342,17 +1353,6 @@
mix1: mix-1 { };
};
- rcar_sound,ctu {
- ctu00: ctu-0 { };
- ctu01: ctu-1 { };
- ctu02: ctu-2 { };
- ctu03: ctu-3 { };
- ctu10: ctu-4 { };
- ctu11: ctu-5 { };
- ctu12: ctu-6 { };
- ctu13: ctu-7 { };
- };
-
rcar_sound,src {
src0: src-0 {
interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
@@ -1766,7 +1766,9 @@
clocks = <&cpg CPG_MOD 724>,
<&cpg CPG_MOD 723>;
clock-names = "du.0", "du.1";
- vsps = <&vspd0 0 &vspd1 0>;
+ resets = <&cpg 724>;
+ reset-names = "du.0";
+ vsps = <&vspd0 0>, <&vspd1 0>;
status = "disabled";
ports {
@@ -1864,25 +1866,25 @@
thermal-sensors = <&thermal 0>;
sustainable-power = <717>;
- trips {
- target: trip-point1 {
- temperature = <100000>;
- hysteresis = <2000>;
- type = "passive";
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ cooling-device = <&a53_0 0 2>;
+ contribution = <1024>;
};
+ };
+ trips {
sensor1_crit: sensor1-crit {
temperature = <120000>;
hysteresis = <2000>;
type = "critical";
};
- };
- cooling-maps {
- map0 {
- trip = <&target>;
- cooling-device = <&a53_0 0 2>;
- contribution = <1024>;
+ target: trip-point1 {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "passive";
};
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index 0711170b26b1..67634cb01d6b 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -19,11 +19,6 @@
ethernet0 = &avb;
};
- chosen {
- bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
- stdout-path = "serial0:115200n8";
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 50000>;
@@ -35,6 +30,11 @@
enable-gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
};
+ chosen {
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+ stdout-path = "serial0:115200n8";
+ };
+
composite-in {
compatible = "composite-video-connector";
@@ -97,7 +97,7 @@
reg = <0x0 0x48000000 0x0 0x18000000>;
};
- reg_1p8v: regulator0 {
+ reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
regulator-min-microvolt = <1800000>;
@@ -106,7 +106,7 @@
regulator-always-on;
};
- reg_3p3v: regulator1 {
+ reg_3p3v: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
@@ -115,7 +115,7 @@
regulator-always-on;
};
- reg_12p0v: regulator1 {
+ reg_12p0v: regulator-12p0v {
compatible = "regulator-fixed";
regulator-name = "D12.0V";
regulator-min-microvolt = <12000000>;
@@ -175,6 +175,14 @@
reg = <0>;
interrupt-parent = <&gpio5>;
interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+ /*
+ * TX clock internal delay mode is required for reliable
+ * 1Gbps communication using the KSZ9031RNX phy present on
+ * the Draak board, however, TX clock internal delay mode
+ * isn't supported on r8a77995. Thus, limit speed to
+ * 100Mbps for reliable communication.
+ */
+ max-speed = <100>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index 0a344eb55094..183fef86cf7c 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -242,41 +242,6 @@
resets = <&cpg 407>;
};
- hscif0: serial@e6540000 {
- compatible = "renesas,hscif-r8a77995",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe6540000 0 0x60>;
- interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 520>,
- <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac1 0x31>, <&dmac1 0x30>,
- <&dmac2 0x31>, <&dmac2 0x30>;
- dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 520>;
- status = "disabled";
- };
-
- hscif3: serial@e66a0000 {
- compatible = "renesas,hscif-r8a77995",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe66a0000 0 0x60>;
- interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 517>,
- <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac0 0x37>, <&dmac0 0x36>;
- dma-names = "tx", "rx";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 517>;
- status = "disabled";
- };
-
i2c0: i2c@e6500000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -344,6 +309,41 @@
status = "disabled";
};
+ hscif0: serial@e6540000 {
+ compatible = "renesas,hscif-r8a77995",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe6540000 0 0x60>;
+ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 520>,
+ <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac1 0x31>, <&dmac1 0x30>,
+ <&dmac2 0x31>, <&dmac2 0x30>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 520>;
+ status = "disabled";
+ };
+
+ hscif3: serial@e66a0000 {
+ compatible = "renesas,hscif-r8a77995",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe66a0000 0 0x60>;
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 517>,
+ <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+ dma-names = "tx", "rx";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 517>;
+ status = "disabled";
+ };
+
hsusb: usb@e6590000 {
compatible = "renesas,usbhs-r8a77995",
"renesas,rcar-gen3-usbhs";
@@ -995,13 +995,15 @@
du: display@feb00000 {
compatible = "renesas,du-r8a77995";
- reg = <0 0xfeb00000 0 0x80000>;
+ reg = <0 0xfeb00000 0 0x40000>;
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 724>,
<&cpg CPG_MOD 723>;
clock-names = "du.0", "du.1";
- vsps = <&vspd0 0 &vspd1 0>;
+ resets = <&cpg 724>;
+ reset-names = "du.0";
+ vsps = <&vspd0 0>, <&vspd1 0>;
status = "disabled";
ports {
@@ -1098,6 +1100,9 @@
polling-delay = <1000>;
thermal-sensors = <&thermal>;
+ cooling-maps {
+ };
+
trips {
cpu-crit {
temperature = <120000>;
@@ -1105,9 +1110,6 @@
type = "critical";
};
};
-
- cooling-maps {
- };
};
};
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index 5c2c84723ec5..21e01056e759 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -87,6 +87,28 @@
};
};
+ hdmi0-out {
+ compatible = "hdmi-connector";
+ label = "HDMI0 OUT";
+ type = "a";
+
+ port {
+ hdmi0_con: endpoint {
+ };
+ };
+ };
+
+ hdmi1-out {
+ compatible = "hdmi-connector";
+ label = "HDMI1 OUT";
+ type = "a";
+
+ port {
+ hdmi1_con: endpoint {
+ };
+ };
+ };
+
keys {
compatible = "gpio-keys";
@@ -238,28 +260,6 @@
1800000 0>;
};
- hdmi0-out {
- compatible = "hdmi-connector";
- label = "HDMI0 OUT";
- type = "a";
-
- port {
- hdmi0_con: endpoint {
- };
- };
- };
-
- hdmi1-out {
- compatible = "hdmi-connector";
- label = "HDMI1 OUT";
- type = "a";
-
- port {
- hdmi1_con: endpoint {
- };
- };
- };
-
vga {
compatible = "vga-connector";
@@ -462,20 +462,6 @@
#gpio-cells = <2>;
};
- csa_vdd: adc@7c {
- compatible = "maxim,max9611";
- reg = <0x7c>;
-
- shunt-resistor-micro-ohms = <5000>;
- };
-
- csa_dvfs: adc@7f {
- compatible = "maxim,max9611";
- reg = <0x7f>;
-
- shunt-resistor-micro-ohms = <5000>;
- };
-
video-receiver@70 {
compatible = "adi,adv7482";
reg = <0x70 0x71 0x72 0x73 0x74 0x75
@@ -527,6 +513,20 @@
};
};
};
+
+ csa_vdd: adc@7c {
+ compatible = "maxim,max9611";
+ reg = <0x7c>;
+
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ csa_dvfs: adc@7f {
+ compatible = "maxim,max9611";
+ reg = <0x7f>;
+
+ shunt-resistor-micro-ohms = <5000>;
+ };
};
&i2c_dvfs {
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
index 27851a77f538..202177706cde 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
@@ -83,6 +83,56 @@
};
&i2c2 {
+ i2cswitch2: i2c-switch@71 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
+
+ /* Audio_SDA, Audio_SCL */
+ i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+
+ pcm3168a: audio-codec@44 {
+ #sound-dai-cells = <0>;
+ compatible = "ti,pcm3168a";
+ reg = <0x44>;
+ clocks = <&clksndsel>;
+ clock-names = "scki";
+
+ VDD1-supply = <&snd_3p3v>;
+ VDD2-supply = <&snd_3p3v>;
+ VCCAD1-supply = <&snd_vcc5v>;
+ VCCAD2-supply = <&snd_vcc5v>;
+ VCCDA1-supply = <&snd_vcc5v>;
+ VCCDA2-supply = <&snd_vcc5v>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ mclk-fs = <512>;
+ port@0 {
+ reg = <0>;
+ pcm3168a_endpoint_p: endpoint {
+ remote-endpoint = <&rsnd_for_pcm3168a_play>;
+ clocks = <&clksndsel>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ pcm3168a_endpoint_c: endpoint {
+ remote-endpoint = <&rsnd_for_pcm3168a_capture>;
+ clocks = <&clksndsel>;
+ };
+ };
+ };
+ };
+ };
+ };
+
/* U11 */
gpio_exp_74: gpio@74 {
compatible = "ti,tca9539";
@@ -100,13 +150,6 @@
line-name = "Audio_Out_OFF";
};
- sd-wifi-mux {
- gpio-hog;
- gpios = <5 GPIO_ACTIVE_HIGH>;
- output-low; /* Connect WL1837 */
- line-name = "SD WiFi mux";
- };
-
hub_pwen {
gpio-hog;
gpios = <6 GPIO_ACTIVE_HIGH>;
@@ -121,6 +164,13 @@
line-name = "HUB rst";
};
+ otg_extlpn {
+ gpio-hog;
+ gpios = <9 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "OTG EXTLPn";
+ };
+
otg_offvbusn {
gpio-hog;
gpios = <8 GPIO_ACTIVE_HIGH>;
@@ -128,11 +178,11 @@
line-name = "OTG OFFVBUSn";
};
- otg_extlpn {
+ sd-wifi-mux {
gpio-hog;
- gpios = <9 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "OTG EXTLPn";
+ gpios = <5 GPIO_ACTIVE_HIGH>;
+ output-low; /* Connect WL1837 */
+ line-name = "SD WiFi mux";
};
snd_rst {
@@ -153,59 +203,17 @@
interrupt-parent = <&gpio6>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
};
+};
- i2cswitch2: i2c-switch@71 {
+&i2c4 {
+ i2cswitch4: i2c-switch@71 {
compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x71>;
- reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
-
- /* Audio_SDA, Audio_SCL */
- i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
-
- pcm3168a: audio-codec@44 {
- #sound-dai-cells = <0>;
- compatible = "ti,pcm3168a";
- reg = <0x44>;
- clocks = <&clksndsel>;
- clock-names = "scki";
-
- VDD1-supply = <&snd_3p3v>;
- VDD2-supply = <&snd_3p3v>;
- VCCAD1-supply = <&snd_vcc5v>;
- VCCAD2-supply = <&snd_vcc5v>;
- VCCDA1-supply = <&snd_vcc5v>;
- VCCDA2-supply = <&snd_vcc5v>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- mclk-fs = <512>;
- port@0 {
- reg = <0>;
- pcm3168a_endpoint_p: endpoint {
- remote-endpoint = <&rsnd_for_pcm3168a_play>;
- clocks = <&clksndsel>;
- };
- };
- port@1 {
- reg = <1>;
- pcm3168a_endpoint_c: endpoint {
- remote-endpoint = <&rsnd_for_pcm3168a_capture>;
- clocks = <&clksndsel>;
- };
- };
- };
- };
- };
+ reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
};
-};
-&i2c4 {
gpio_exp_76: gpio@76 {
compatible = "ti,tca9539";
reg = <0x76>;
@@ -225,14 +233,6 @@
interrupt-parent = <&gpio5>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
};
-
- i2cswitch4: i2c-switch@71 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x71>;
- reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
- };
};
&ohci0 {
@@ -279,14 +279,50 @@
power-source = <3300>;
};
+ sound_pcm_pins: sound-pcm {
+ groups = "ssi349_ctrl", "ssi3_data", "ssi4_data";
+ function = "ssi";
+ };
+
usb0_pins: usb0 {
groups = "usb0";
function = "usb0";
};
+};
- sound_pcm_pins: sound-pcm {
- groups = "ssi349_ctrl", "ssi3_data", "ssi4_data";
- function = "ssi";
+&rcar_sound {
+ pinctrl-0 = <&sound_pins
+ &sound_clk_pins
+ &sound_pcm_pins>;
+
+ ports {
+ /* rsnd_port0/1 are on salvator-common */
+ rsnd_port2: port@2 {
+ reg = <2>;
+ rsnd_for_pcm3168a_play: endpoint {
+ remote-endpoint = <&pcm3168a_endpoint_p>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_for_pcm3168a_play>;
+ frame-master = <&rsnd_for_pcm3168a_play>;
+ dai-tdm-slot-num = <8>;
+
+ playback = <&ssi3>;
+ };
+ };
+ rsnd_port3: port@3 {
+ reg = <3>;
+ rsnd_for_pcm3168a_capture: endpoint {
+ remote-endpoint = <&pcm3168a_endpoint_c>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_for_pcm3168a_capture>;
+ frame-master = <&rsnd_for_pcm3168a_capture>;
+ dai-tdm-slot-num = <6>;
+
+ capture = <&ssi4>;
+ };
+ };
};
};
@@ -322,17 +358,6 @@
};
};
-&usb2_phy0 {
- pinctrl-0 = <&usb0_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
-
-&xhci0 {
- status = "okay";
-};
-
&sound_card {
dais = <&rsnd_port0 /* ak4613 */
&rsnd_port1 /* HDMI0 */
@@ -341,42 +366,17 @@
>;
};
-&rcar_sound {
- pinctrl-0 = <&sound_pins
- &sound_clk_pins
- &sound_pcm_pins>;
-
- ports {
- /* rsnd_port0/1 are on salvator-common */
- rsnd_port2: port@2 {
- reg = <2>;
- rsnd_for_pcm3168a_play: endpoint {
- remote-endpoint = <&pcm3168a_endpoint_p>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_for_pcm3168a_play>;
- frame-master = <&rsnd_for_pcm3168a_play>;
- dai-tdm-slot-num = <8>;
-
- playback = <&ssi3>;
- };
- };
- rsnd_port3: port@3 {
- reg = <3>;
- rsnd_for_pcm3168a_capture: endpoint {
- remote-endpoint = <&pcm3168a_endpoint_c>;
+&ssi4 {
+ shared-pin;
+};
- dai-format = "i2s";
- bitclock-master = <&rsnd_for_pcm3168a_capture>;
- frame-master = <&rsnd_for_pcm3168a_capture>;
- dai-tdm-slot-num = <6>;
+&usb2_phy0 {
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
- capture = <&ssi4>;
- };
- };
- };
+ status = "okay";
};
-&ssi4 {
- shared-pin;
+&xhci0 {
+ status = "okay";
};
diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi
index 7e498b46e9ae..3ef89171538f 100644
--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -428,6 +428,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&scif2 {
pinctrl-0 = <&scif2_pins>;
pinctrl-names = "default";
@@ -478,8 +483,3 @@
status = "okay";
};
-
-&rwdt {
- timeout-sec = <60>;
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index daa2c78e22c3..1f18a9392d15 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -20,6 +20,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-hugsun-x99.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-captain.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-v.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-leez-p710.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index 7cfd5ca6cc85..62936b432f9a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -34,10 +34,9 @@
vcc_host_5v: vcc-host-5v-regulator {
compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
- pinctrl-0 = <&usb30_host_drv>;
+ pinctrl-0 = <&usb20_host_drv>;
regulator-name = "vcc_host_5v";
regulator-always-on;
regulator-boot-on;
@@ -320,12 +319,6 @@
rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
-
- usb3 {
- usb30_host_drv: usb30-host-drv {
- rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
};
&sdmmc {
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index e9fefd8a7e02..31cc1541f1f5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -278,6 +278,7 @@
};
pd_vpu@RK3328_PD_VPU {
reg = <RK3328_PD_VPU>;
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
};
};
@@ -596,6 +597,17 @@
status = "disabled";
};
+ vpu: video-codec@ff350000 {
+ compatible = "rockchip,rk3328-vpu";
+ reg = <0x0 0xff350000 0x0 0x800>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "vdpu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vpu_mmu>;
+ power-domains = <&power RK3328_PD_VPU>;
+ };
+
vpu_mmu: iommu@ff350800 {
compatible = "rockchip,iommu";
reg = <0x0 0xff350800 0x0 0x40>;
@@ -604,7 +616,7 @@
clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
clock-names = "aclk", "iface";
#iommu-cells = <0>;
- status = "disabled";
+ power-domains = <&power RK3328_PD_VPU>;
};
rkvdec_mmu: iommu@ff360480 {
@@ -801,6 +813,7 @@
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
status = "disabled";
};
@@ -812,6 +825,7 @@
<&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
status = "disabled";
};
@@ -823,6 +837,7 @@
<&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 3e2272b56eb7..e152b0ca0290 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -43,6 +43,20 @@
backlight = <&backlight>;
power-supply = <&pp3300_disp>;
+ panel-timing {
+ clock-frequency = <266604720>;
+ hactive = <2400>;
+ hfront-porch = <48>;
+ hback-porch = <84>;
+ hsync-len = <32>;
+ hsync-active = <0>;
+ vactive = <1600>;
+ vfront-porch = <3>;
+ vback-porch = <120>;
+ vsync-len = <10>;
+ vsync-active = <0>;
+ };
+
port {
panel_in_edp: endpoint {
remote-endpoint = <&edp_out_panel>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
new file mode 100644
index 000000000000..73be38a53796
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
@@ -0,0 +1,645 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Andy Yan <andy.yan@gmail.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+ model = "Leez RK3399 P710";
+ compatible = "leez,p710", "rockchip,rk3399";
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ clkin_gmac: external-gmac-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "clkin_gmac";
+ #clock-cells = <0>;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk808 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_reg_on_h>;
+ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+ };
+
+ dc5v_adp: dc5v-adp {
+ compatible = "regulator-fixed";
+ regulator-name = "dc5v_adapter";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc3v3_lan: vcc3v3-lan {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_lan";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vim-supply = <&vcc3v3_sys>;
+ };
+
+ vcc3v3_sys: vcc3v3-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_host0: vcc5v0_host1: vcc5v0-host {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_host";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <5500000>;
+ regulator-max-microvolt = <5500000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_host3: vcc5v0-host3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_host3";
+ enable-active-high;
+ gpio = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_host3_en>;
+ regulator-always-on;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc5v_adp>;
+ };
+
+ vdd_log: vdd-log {
+ compatible = "pwm-regulator";
+ pwms = <&pwm2 0 25000 1>;
+ regulator-name = "vdd_log";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&emmc_phy {
+ status = "okay";
+};
+
+&gmac {
+ assigned-clocks = <&cru SCLK_RMII_SRC>;
+ assigned-clock-parents = <&clkin_gmac>;
+ clock_in_out = "input";
+ phy-supply = <&vcc3v3_lan>;
+ phy-mode = "rgmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 50000>;
+ tx_delay = <0x28>;
+ rx_delay = <0x11>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_cec>;
+ status = "okay";
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ i2c-scl-rising-time-ns = <168>;
+ i2c-scl-falling-time-ns = <4>;
+ status = "okay";
+
+ rk808: pmic@1b {
+ compatible = "rockchip,rk808";
+ reg = <0x1b>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "xin32k", "rk808-clkout2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc5v0_sys>;
+ vcc12-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcc_1v8>;
+
+ regulators {
+ vdd_center: DCDC_REG1 {
+ regulator-name = "vdd_center";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_l: DCDC_REG2 {
+ regulator-name = "vdd_cpu_l";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_1v8: DCDC_REG4 {
+ regulator-name = "vcc_1v8";
+ 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>;
+ };
+ };
+
+ vcc1v8_dvp: LDO_REG1 {
+ regulator-name = "vcc1v8_dvp";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_hdmi: LDO_REG2 {
+ regulator-name = "vcc1v8_hdmi";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_1v8: LDO_REG3 {
+ regulator-name = "vcca_1v8";
+ 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>;
+ };
+ };
+
+ vccio_sd: LDO_REG4 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3000000>;
+ };
+ };
+
+ vcca3v0_codec: LDO_REG5 {
+ regulator-name = "vcca3v0_codec";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v5: LDO_REG6 {
+ regulator-name = "vcc_1v5";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1500000>;
+ };
+ };
+
+ vcc0v9_hdmi: LDO_REG7 {
+ regulator-name = "vcc0v9_hdmi";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v0: LDO_REG8 {
+ regulator-name = "vcc_3v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3000000>;
+ };
+ };
+ };
+ };
+
+ vdd_cpu_b: regulator@40 {
+ compatible = "silergy,syr827";
+ reg = <0x40>;
+ fcs,suspend-voltage-selector = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vsel1_gpio>;
+ regulator-name = "vdd_cpu_b";
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1500000>;
+ regulator-ramp-delay = <1000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_gpu: regulator@41 {
+ compatible = "silergy,syr828";
+ reg = <0x41>;
+ fcs,suspend-voltage-selector = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vsel2_gpio>;
+ regulator-name = "vdd_gpu";
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1500000>;
+ regulator-ramp-delay = <1000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c1 {
+ i2c-scl-rising-time-ns = <300>;
+ i2c-scl-falling-time-ns = <15>;
+ status = "okay";
+};
+
+&i2c3 {
+ i2c-scl-rising-time-ns = <450>;
+ i2c-scl-falling-time-ns = <15>;
+ status = "okay";
+};
+
+&i2c4 {
+ i2c-scl-rising-time-ns = <600>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2s0 {
+ rockchip,playback-channels = <8>;
+ rockchip,capture-channels = <8>;
+ status = "okay";
+};
+
+&i2s1 {
+ rockchip,playback-channels = <2>;
+ rockchip,capture-channels = <2>;
+ status = "okay";
+};
+
+&i2s2 {
+ status = "okay";
+};
+
+&io_domains {
+ status = "okay";
+
+ bt656-supply = <&vcc1v8_dvp>;
+ audio-supply = <&vcc_1v8>;
+ sdmmc-supply = <&vccio_sd>;
+ gpio1830-supply = <&vcc_3v0>;
+};
+
+&pmu_io_domains {
+ status = "okay";
+ pmu1830-supply = <&vcc_3v0>;
+};
+
+&pinctrl {
+ bt {
+ bt_reg_on_h: bt-reg-on-h {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake_l: bt-host-wake-l {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_l: bt-wake-l {
+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ vsel1_gpio: vsel1-gpio {
+ rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ vsel2_gpio: vsel2-gpio {
+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ usb2 {
+ vcc5v0_host3_en: vcc5v0-host3-en {
+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on_h: wifi-reg-on-h {
+ rockchip,pins =
+ <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_host_wake_l: wifi-host-wake-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&saradc {
+ status = "okay";
+
+ vref-supply = <&vcc_1v8>;
+};
+
+&sdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ bus-width = <4>;
+ clock-frequency = <50000000>;
+ cap-sdio-irq;
+ cap-sd-highspeed;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+ sd-uhs-sdr104;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ compatible = "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_host_wake_l>;
+ };
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <150000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_clk &sdmmc_cd &sdmmc_cmd &sdmmc_bus4>;
+ status = "okay";
+};
+
+&tcphy0 {
+ status = "okay";
+};
+
+&tcphy1 {
+ status = "okay";
+};
+
+&tsadc {
+ status = "okay";
+
+ /* tshut mode 0:CRU 1:GPIO */
+ rockchip,hw-tshut-mode = <1>;
+ /* tshut polarity 0:LOW 1:HIGH */
+ rockchip,hw-tshut-polarity = <1>;
+};
+
+&u2phy0 {
+ status = "okay";
+
+ u2phy0_otg: otg-port {
+ status = "okay";
+ };
+
+ u2phy0_host: host-port {
+ phy-supply = <&vcc5v0_host0>;
+ status = "okay";
+ };
+};
+
+&u2phy1 {
+ status = "okay";
+
+ u2phy1_otg: otg-port {
+ status = "okay";
+ };
+
+ u2phy1_host: host-port {
+ phy-supply = <&vcc5v0_host1>;
+ status = "okay";
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&rk808 1>;
+ clock-names = "ext_clock";
+ device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_reg_on_h>;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usbdrd3_0 {
+ status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+ status = "okay";
+ dr_mode = "otg";
+};
+
+&usbdrd3_1 {
+ status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&vopb {
+ status = "okay";
+};
+
+&vopb_mmu {
+ status = "okay";
+};
+
+&vopl {
+ status = "okay";
+};
+
+&vopl_mmu {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
index eb5594062006..0401d4ec1f45 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
@@ -58,6 +58,13 @@
};
};
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ fan-supply = <&vcc12v_dcin>;
+ pwms = <&pwm1 0 50000 0>;
+ };
+
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&rk808 1>;
@@ -602,6 +609,10 @@
status = "okay";
};
+&pwm1 {
+ status = "okay";
+};
+
&pwm2 {
status = "okay";
};
@@ -631,6 +642,16 @@
status = "okay";
};
+&spi1 {
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ };
+};
+
&tcphy0 {
status = "okay";
};
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0e58ef02880c..8e05c39eab08 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -72,6 +72,7 @@ CONFIG_RANDOMIZE_BASE=y
CONFIG_HIBERNATION=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
@@ -84,6 +85,7 @@ CONFIG_ACPI_CPPC_CPUFREQ=m
CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=m
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=m
CONFIG_ARM_TEGRA186_CPUFREQ=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_RASPBERRYPI_FIRMWARE=y
@@ -95,6 +97,7 @@ CONFIG_IMX_SCU_PD=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
+CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
@@ -196,6 +199,8 @@ CONFIG_PCIE_HISI_STB=y
CONFIG_PCIE_TEGRA194=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_FW_LOADER_USER_HELPER=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
@@ -366,6 +371,7 @@ CONFIG_I2C_IMX_LPI2C=y
CONFIG_I2C_MESON=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_PXA=y
+CONFIG_I2C_QCOM_GENI=m
CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_SH_MOBILE=y
@@ -392,6 +398,7 @@ CONFIG_SPMI=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_IMX8MM=y
+CONFIG_PINCTRL_IMX8MN=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QXP=y
CONFIG_PINCTRL_IPQ8074=y
@@ -403,6 +410,7 @@ CONFIG_PINCTRL_QCS404=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_SDM845=y
+CONFIG_PINCTRL_SM8150=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_PL061=y
@@ -445,6 +453,7 @@ CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_S3C2410_WATCHDOG=y
+CONFIG_DW_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=m
CONFIG_IMX2_WDT=y
CONFIG_IMX_SC_WDT=m
@@ -489,6 +498,7 @@ CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_IR_MESON=m
+CONFIG_IR_SUNXI=m
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
@@ -526,11 +536,13 @@ CONFIG_DRM_RCAR_DU=m
CONFIG_DRM_SUN4I=m
CONFIG_DRM_SUN8I_DW_HDMI=m
CONFIG_DRM_SUN8I_MIXER=m
+CONFIG_DRM_MSM=m
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_VC4=m
+CONFIG_DRM_ETNAVIV=m
CONFIG_DRM_HISI_HIBMC=m
CONFIG_DRM_HISI_KIRIN=m
CONFIG_DRM_MESON=m
@@ -539,6 +551,7 @@ CONFIG_DRM_LIMA=m
CONFIG_DRM_PANFROST=m
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
@@ -558,6 +571,7 @@ CONFIG_SND_SOC_ROCKCHIP_RT5645=m
CONFIG_SND_SOC_RK3399_GRU_SOUND=m
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SOC_RCAR=m
+CONFIG_SND_SUN4I_SPDIF=m
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
@@ -651,6 +665,7 @@ CONFIG_DMADEVICES=y
CONFIG_FSL_EDMA=y
CONFIG_DMA_BCM2835=m
CONFIG_DMA_SUN6I=m
+CONFIG_IMX_SDMA=y
CONFIG_K3_DMA=y
CONFIG_MV_XOR=y
CONFIG_MV_XOR_V2=y
@@ -676,11 +691,15 @@ CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_PWM=y
+CONFIG_CLK_RASPBERRYPI=m
CONFIG_CLK_IMX8MM=y
+CONFIG_CLK_IMX8MN=y
CONFIG_CLK_IMX8MQ=y
CONFIG_CLK_IMX8QXP=y
CONFIG_TI_SCI_CLK=y
CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_A53PLL=y
+CONFIG_QCOM_CLK_APCS_MSM8916=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_QCOM_CLK_RPMH=y
CONFIG_IPQ_GCC_8074=y
@@ -690,6 +709,7 @@ CONFIG_MSM_MMCC_8996=y
CONFIG_MSM_GCC_8998=y
CONFIG_QCS_GCC_404=y
CONFIG_SDM_GCC_845=y
+CONFIG_SM_GCC_8150=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
@@ -768,6 +788,7 @@ CONFIG_PHY_HISTB_COMBPHY=y
CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
CONFIG_PHY_QCOM_QMP=m
+CONFIG_PHY_QCOM_QUSB2=m
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
@@ -780,6 +801,7 @@ CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PHY_UNIPHIER_USB2=y
CONFIG_PHY_UNIPHIER_USB3=y
CONFIG_PHY_TEGRA_XUSB=y
+CONFIG_FSL_IMX8_DDR_PMU=m
CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 79155a8cfe7c..89e4c8b79349 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -155,6 +155,12 @@ static inline void gic_pmr_mask_irqs(void)
BUILD_BUG_ON(GICD_INT_DEF_PRI < (GIC_PRIO_IRQOFF |
GIC_PRIO_PSR_I_SET));
BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
+ /*
+ * Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared
+ * and non-secure PMR accesses are not subject to the shifts that
+ * are applied to IRQ priorities
+ */
+ BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
gic_write_pmr(GIC_PRIO_IRQOFF);
}
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index e3a15c751b13..b8cf7c85ffa2 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -124,17 +124,6 @@ alternative_endif
.endm
/*
- * Sanitise a 64-bit bounded index wrt speculation, returning zero if out
- * of bounds.
- */
- .macro mask_nospec64, idx, limit, tmp
- sub \tmp, \idx, \limit
- bic \tmp, \tmp, \idx
- and \idx, \idx, \tmp, asr #63
- csdb
- .endm
-
-/*
* NOP sequence
*/
.macro nops, num
@@ -350,6 +339,13 @@ alternative_endif
.endm
/*
+ * tcr_set_t1sz - update TCR.T1SZ
+ */
+ .macro tcr_set_t1sz, valreg, t1sz
+ bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH
+ .endm
+
+/*
* tcr_compute_pa_size - set TCR.(I)PS to the highest supported
* ID_AA64MMFR0_EL1.PARange value
*
@@ -538,9 +534,13 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
* In future this may be nop'ed out when dealing with 52-bit kernel VAs.
* ttbr: Value of ttbr to set, modified.
*/
- .macro offset_ttbr1, ttbr
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+ .macro offset_ttbr1, ttbr, tmp
+#ifdef CONFIG_ARM64_VA_BITS_52
+ mrs_s \tmp, SYS_ID_AA64MMFR2_EL1
+ and \tmp, \tmp, #(0xf << ID_AA64MMFR2_LVA_SHIFT)
+ cbnz \tmp, .Lskipoffs_\@
orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
+.Lskipoffs_\@ :
#endif
.endm
@@ -550,7 +550,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
* to be nop'ed out when dealing with 52-bit kernel VAs.
*/
.macro restore_ttbr1, ttbr
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+#ifdef CONFIG_ARM64_VA_BITS_52
bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
#endif
.endm
diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h
index 657b0457d83c..9543b5e0534d 100644
--- a/arch/arm64/include/asm/atomic.h
+++ b/arch/arm64/include/asm/atomic.h
@@ -13,21 +13,91 @@
#include <linux/types.h>
#include <asm/barrier.h>
+#include <asm/cmpxchg.h>
#include <asm/lse.h>
-#ifdef __KERNEL__
-
-#define __ARM64_IN_ATOMIC_IMPL
-
-#if defined(CONFIG_ARM64_LSE_ATOMICS) && defined(CONFIG_AS_LSE)
-#include <asm/atomic_lse.h>
-#else
-#include <asm/atomic_ll_sc.h>
-#endif
-
-#undef __ARM64_IN_ATOMIC_IMPL
-
-#include <asm/cmpxchg.h>
+#define ATOMIC_OP(op) \
+static inline void arch_##op(int i, atomic_t *v) \
+{ \
+ __lse_ll_sc_body(op, i, v); \
+}
+
+ATOMIC_OP(atomic_andnot)
+ATOMIC_OP(atomic_or)
+ATOMIC_OP(atomic_xor)
+ATOMIC_OP(atomic_add)
+ATOMIC_OP(atomic_and)
+ATOMIC_OP(atomic_sub)
+
+#undef ATOMIC_OP
+
+#define ATOMIC_FETCH_OP(name, op) \
+static inline int arch_##op##name(int i, atomic_t *v) \
+{ \
+ return __lse_ll_sc_body(op##name, i, v); \
+}
+
+#define ATOMIC_FETCH_OPS(op) \
+ ATOMIC_FETCH_OP(_relaxed, op) \
+ ATOMIC_FETCH_OP(_acquire, op) \
+ ATOMIC_FETCH_OP(_release, op) \
+ ATOMIC_FETCH_OP( , op)
+
+ATOMIC_FETCH_OPS(atomic_fetch_andnot)
+ATOMIC_FETCH_OPS(atomic_fetch_or)
+ATOMIC_FETCH_OPS(atomic_fetch_xor)
+ATOMIC_FETCH_OPS(atomic_fetch_add)
+ATOMIC_FETCH_OPS(atomic_fetch_and)
+ATOMIC_FETCH_OPS(atomic_fetch_sub)
+ATOMIC_FETCH_OPS(atomic_add_return)
+ATOMIC_FETCH_OPS(atomic_sub_return)
+
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_FETCH_OPS
+
+#define ATOMIC64_OP(op) \
+static inline void arch_##op(long i, atomic64_t *v) \
+{ \
+ __lse_ll_sc_body(op, i, v); \
+}
+
+ATOMIC64_OP(atomic64_andnot)
+ATOMIC64_OP(atomic64_or)
+ATOMIC64_OP(atomic64_xor)
+ATOMIC64_OP(atomic64_add)
+ATOMIC64_OP(atomic64_and)
+ATOMIC64_OP(atomic64_sub)
+
+#undef ATOMIC64_OP
+
+#define ATOMIC64_FETCH_OP(name, op) \
+static inline long arch_##op##name(long i, atomic64_t *v) \
+{ \
+ return __lse_ll_sc_body(op##name, i, v); \
+}
+
+#define ATOMIC64_FETCH_OPS(op) \
+ ATOMIC64_FETCH_OP(_relaxed, op) \
+ ATOMIC64_FETCH_OP(_acquire, op) \
+ ATOMIC64_FETCH_OP(_release, op) \
+ ATOMIC64_FETCH_OP( , op)
+
+ATOMIC64_FETCH_OPS(atomic64_fetch_andnot)
+ATOMIC64_FETCH_OPS(atomic64_fetch_or)
+ATOMIC64_FETCH_OPS(atomic64_fetch_xor)
+ATOMIC64_FETCH_OPS(atomic64_fetch_add)
+ATOMIC64_FETCH_OPS(atomic64_fetch_and)
+ATOMIC64_FETCH_OPS(atomic64_fetch_sub)
+ATOMIC64_FETCH_OPS(atomic64_add_return)
+ATOMIC64_FETCH_OPS(atomic64_sub_return)
+
+#undef ATOMIC64_FETCH_OP
+#undef ATOMIC64_FETCH_OPS
+
+static inline long arch_atomic64_dec_if_positive(atomic64_t *v)
+{
+ return __lse_ll_sc_body(atomic64_dec_if_positive, v);
+}
#define ATOMIC_INIT(i) { (i) }
@@ -157,5 +227,4 @@
#include <asm-generic/atomic-instrumented.h>
-#endif
-#endif
+#endif /* __ASM_ATOMIC_H */
diff --git a/arch/arm64/include/asm/atomic_ll_sc.h b/arch/arm64/include/asm/atomic_ll_sc.h
index c8c850bc3dfb..7b012148bfd6 100644
--- a/arch/arm64/include/asm/atomic_ll_sc.h
+++ b/arch/arm64/include/asm/atomic_ll_sc.h
@@ -10,83 +10,92 @@
#ifndef __ASM_ATOMIC_LL_SC_H
#define __ASM_ATOMIC_LL_SC_H
-#ifndef __ARM64_IN_ATOMIC_IMPL
-#error "please don't include this file directly"
+#include <linux/stringify.h>
+
+#if IS_ENABLED(CONFIG_ARM64_LSE_ATOMICS) && IS_ENABLED(CONFIG_AS_LSE)
+#define __LL_SC_FALLBACK(asm_ops) \
+" b 3f\n" \
+" .subsection 1\n" \
+"3:\n" \
+asm_ops "\n" \
+" b 4f\n" \
+" .previous\n" \
+"4:\n"
+#else
+#define __LL_SC_FALLBACK(asm_ops) asm_ops
+#endif
+
+#ifndef CONFIG_CC_HAS_K_CONSTRAINT
+#define K
#endif
/*
* AArch64 UP and SMP safe atomic ops. We use load exclusive and
* store exclusive to ensure that these are atomic. We may loop
* to ensure that the update happens.
- *
- * NOTE: these functions do *not* follow the PCS and must explicitly
- * save any clobbered registers other than x0 (regardless of return
- * value). This is achieved through -fcall-saved-* compiler flags for
- * this file, which unfortunately don't work on a per-function basis
- * (the optimize attribute silently ignores these options).
*/
-#define ATOMIC_OP(op, asm_op) \
-__LL_SC_INLINE void \
-__LL_SC_PREFIX(arch_atomic_##op(int i, atomic_t *v)) \
+#define ATOMIC_OP(op, asm_op, constraint) \
+static inline void \
+__ll_sc_atomic_##op(int i, atomic_t *v) \
{ \
unsigned long tmp; \
int result; \
\
asm volatile("// atomic_" #op "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %2\n" \
"1: ldxr %w0, %2\n" \
" " #asm_op " %w0, %w0, %w3\n" \
" stxr %w1, %w0, %2\n" \
-" cbnz %w1, 1b" \
+" cbnz %w1, 1b\n") \
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i)); \
-} \
-__LL_SC_EXPORT(arch_atomic_##op);
+ : __stringify(constraint) "r" (i)); \
+}
-#define ATOMIC_OP_RETURN(name, mb, acq, rel, cl, op, asm_op) \
-__LL_SC_INLINE int \
-__LL_SC_PREFIX(arch_atomic_##op##_return##name(int i, atomic_t *v)) \
+#define ATOMIC_OP_RETURN(name, mb, acq, rel, cl, op, asm_op, constraint)\
+static inline int \
+__ll_sc_atomic_##op##_return##name(int i, atomic_t *v) \
{ \
unsigned long tmp; \
int result; \
\
asm volatile("// atomic_" #op "_return" #name "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %2\n" \
"1: ld" #acq "xr %w0, %2\n" \
" " #asm_op " %w0, %w0, %w3\n" \
" st" #rel "xr %w1, %w0, %2\n" \
" cbnz %w1, 1b\n" \
-" " #mb \
+" " #mb ) \
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i) \
+ : __stringify(constraint) "r" (i) \
: cl); \
\
return result; \
-} \
-__LL_SC_EXPORT(arch_atomic_##op##_return##name);
+}
-#define ATOMIC_FETCH_OP(name, mb, acq, rel, cl, op, asm_op) \
-__LL_SC_INLINE int \
-__LL_SC_PREFIX(arch_atomic_fetch_##op##name(int i, atomic_t *v)) \
+#define ATOMIC_FETCH_OP(name, mb, acq, rel, cl, op, asm_op, constraint) \
+static inline int \
+__ll_sc_atomic_fetch_##op##name(int i, atomic_t *v) \
{ \
unsigned long tmp; \
int val, result; \
\
asm volatile("// atomic_fetch_" #op #name "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %3\n" \
"1: ld" #acq "xr %w0, %3\n" \
" " #asm_op " %w1, %w0, %w4\n" \
" st" #rel "xr %w2, %w1, %3\n" \
" cbnz %w2, 1b\n" \
-" " #mb \
+" " #mb ) \
: "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i) \
+ : __stringify(constraint) "r" (i) \
: cl); \
\
return result; \
-} \
-__LL_SC_EXPORT(arch_atomic_fetch_##op##name);
+}
#define ATOMIC_OPS(...) \
ATOMIC_OP(__VA_ARGS__) \
@@ -99,8 +108,8 @@ __LL_SC_EXPORT(arch_atomic_fetch_##op##name);
ATOMIC_FETCH_OP (_acquire, , a, , "memory", __VA_ARGS__)\
ATOMIC_FETCH_OP (_release, , , l, "memory", __VA_ARGS__)
-ATOMIC_OPS(add, add)
-ATOMIC_OPS(sub, sub)
+ATOMIC_OPS(add, add, I)
+ATOMIC_OPS(sub, sub, J)
#undef ATOMIC_OPS
#define ATOMIC_OPS(...) \
@@ -110,77 +119,82 @@ ATOMIC_OPS(sub, sub)
ATOMIC_FETCH_OP (_acquire, , a, , "memory", __VA_ARGS__)\
ATOMIC_FETCH_OP (_release, , , l, "memory", __VA_ARGS__)
-ATOMIC_OPS(and, and)
-ATOMIC_OPS(andnot, bic)
-ATOMIC_OPS(or, orr)
-ATOMIC_OPS(xor, eor)
+ATOMIC_OPS(and, and, K)
+ATOMIC_OPS(or, orr, K)
+ATOMIC_OPS(xor, eor, K)
+/*
+ * GAS converts the mysterious and undocumented BIC (immediate) alias to
+ * an AND (immediate) instruction with the immediate inverted. We don't
+ * have a constraint for this, so fall back to register.
+ */
+ATOMIC_OPS(andnot, bic, )
#undef ATOMIC_OPS
#undef ATOMIC_FETCH_OP
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP
-#define ATOMIC64_OP(op, asm_op) \
-__LL_SC_INLINE void \
-__LL_SC_PREFIX(arch_atomic64_##op(s64 i, atomic64_t *v)) \
+#define ATOMIC64_OP(op, asm_op, constraint) \
+static inline void \
+__ll_sc_atomic64_##op(s64 i, atomic64_t *v) \
{ \
s64 result; \
unsigned long tmp; \
\
asm volatile("// atomic64_" #op "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %2\n" \
"1: ldxr %0, %2\n" \
" " #asm_op " %0, %0, %3\n" \
" stxr %w1, %0, %2\n" \
-" cbnz %w1, 1b" \
+" cbnz %w1, 1b") \
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i)); \
-} \
-__LL_SC_EXPORT(arch_atomic64_##op);
+ : __stringify(constraint) "r" (i)); \
+}
-#define ATOMIC64_OP_RETURN(name, mb, acq, rel, cl, op, asm_op) \
-__LL_SC_INLINE s64 \
-__LL_SC_PREFIX(arch_atomic64_##op##_return##name(s64 i, atomic64_t *v))\
+#define ATOMIC64_OP_RETURN(name, mb, acq, rel, cl, op, asm_op, constraint)\
+static inline long \
+__ll_sc_atomic64_##op##_return##name(s64 i, atomic64_t *v) \
{ \
s64 result; \
unsigned long tmp; \
\
asm volatile("// atomic64_" #op "_return" #name "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %2\n" \
"1: ld" #acq "xr %0, %2\n" \
" " #asm_op " %0, %0, %3\n" \
" st" #rel "xr %w1, %0, %2\n" \
" cbnz %w1, 1b\n" \
-" " #mb \
+" " #mb ) \
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i) \
+ : __stringify(constraint) "r" (i) \
: cl); \
\
return result; \
-} \
-__LL_SC_EXPORT(arch_atomic64_##op##_return##name);
+}
-#define ATOMIC64_FETCH_OP(name, mb, acq, rel, cl, op, asm_op) \
-__LL_SC_INLINE s64 \
-__LL_SC_PREFIX(arch_atomic64_fetch_##op##name(s64 i, atomic64_t *v)) \
+#define ATOMIC64_FETCH_OP(name, mb, acq, rel, cl, op, asm_op, constraint)\
+static inline long \
+__ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \
{ \
s64 result, val; \
unsigned long tmp; \
\
asm volatile("// atomic64_fetch_" #op #name "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %3\n" \
"1: ld" #acq "xr %0, %3\n" \
" " #asm_op " %1, %0, %4\n" \
" st" #rel "xr %w2, %1, %3\n" \
" cbnz %w2, 1b\n" \
-" " #mb \
+" " #mb ) \
: "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \
- : "Ir" (i) \
+ : __stringify(constraint) "r" (i) \
: cl); \
\
return result; \
-} \
-__LL_SC_EXPORT(arch_atomic64_fetch_##op##name);
+}
#define ATOMIC64_OPS(...) \
ATOMIC64_OP(__VA_ARGS__) \
@@ -193,8 +207,8 @@ __LL_SC_EXPORT(arch_atomic64_fetch_##op##name);
ATOMIC64_FETCH_OP (_acquire,, a, , "memory", __VA_ARGS__) \
ATOMIC64_FETCH_OP (_release,, , l, "memory", __VA_ARGS__)
-ATOMIC64_OPS(add, add)
-ATOMIC64_OPS(sub, sub)
+ATOMIC64_OPS(add, add, I)
+ATOMIC64_OPS(sub, sub, J)
#undef ATOMIC64_OPS
#define ATOMIC64_OPS(...) \
@@ -204,23 +218,29 @@ ATOMIC64_OPS(sub, sub)
ATOMIC64_FETCH_OP (_acquire,, a, , "memory", __VA_ARGS__) \
ATOMIC64_FETCH_OP (_release,, , l, "memory", __VA_ARGS__)
-ATOMIC64_OPS(and, and)
-ATOMIC64_OPS(andnot, bic)
-ATOMIC64_OPS(or, orr)
-ATOMIC64_OPS(xor, eor)
+ATOMIC64_OPS(and, and, L)
+ATOMIC64_OPS(or, orr, L)
+ATOMIC64_OPS(xor, eor, L)
+/*
+ * GAS converts the mysterious and undocumented BIC (immediate) alias to
+ * an AND (immediate) instruction with the immediate inverted. We don't
+ * have a constraint for this, so fall back to register.
+ */
+ATOMIC64_OPS(andnot, bic, )
#undef ATOMIC64_OPS
#undef ATOMIC64_FETCH_OP
#undef ATOMIC64_OP_RETURN
#undef ATOMIC64_OP
-__LL_SC_INLINE s64
-__LL_SC_PREFIX(arch_atomic64_dec_if_positive(atomic64_t *v))
+static inline s64
+__ll_sc_atomic64_dec_if_positive(atomic64_t *v)
{
s64 result;
unsigned long tmp;
asm volatile("// atomic64_dec_if_positive\n"
+ __LL_SC_FALLBACK(
" prfm pstl1strm, %2\n"
"1: ldxr %0, %2\n"
" subs %0, %0, #1\n"
@@ -228,20 +248,19 @@ __LL_SC_PREFIX(arch_atomic64_dec_if_positive(atomic64_t *v))
" stlxr %w1, %0, %2\n"
" cbnz %w1, 1b\n"
" dmb ish\n"
-"2:"
+"2:")
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
:
: "cc", "memory");
return result;
}
-__LL_SC_EXPORT(arch_atomic64_dec_if_positive);
-#define __CMPXCHG_CASE(w, sfx, name, sz, mb, acq, rel, cl) \
-__LL_SC_INLINE u##sz \
-__LL_SC_PREFIX(__cmpxchg_case_##name##sz(volatile void *ptr, \
+#define __CMPXCHG_CASE(w, sfx, name, sz, mb, acq, rel, cl, constraint) \
+static inline u##sz \
+__ll_sc__cmpxchg_case_##name##sz(volatile void *ptr, \
unsigned long old, \
- u##sz new)) \
+ u##sz new) \
{ \
unsigned long tmp; \
u##sz oldval; \
@@ -255,6 +274,7 @@ __LL_SC_PREFIX(__cmpxchg_case_##name##sz(volatile void *ptr, \
old = (u##sz)old; \
\
asm volatile( \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %[v]\n" \
"1: ld" #acq "xr" #sfx "\t%" #w "[oldval], %[v]\n" \
" eor %" #w "[tmp], %" #w "[oldval], %" #w "[old]\n" \
@@ -262,46 +282,51 @@ __LL_SC_PREFIX(__cmpxchg_case_##name##sz(volatile void *ptr, \
" st" #rel "xr" #sfx "\t%w[tmp], %" #w "[new], %[v]\n" \
" cbnz %w[tmp], 1b\n" \
" " #mb "\n" \
- "2:" \
+ "2:") \
: [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \
[v] "+Q" (*(u##sz *)ptr) \
- : [old] "Kr" (old), [new] "r" (new) \
+ : [old] __stringify(constraint) "r" (old), [new] "r" (new) \
: cl); \
\
return oldval; \
-} \
-__LL_SC_EXPORT(__cmpxchg_case_##name##sz);
+}
-__CMPXCHG_CASE(w, b, , 8, , , , )
-__CMPXCHG_CASE(w, h, , 16, , , , )
-__CMPXCHG_CASE(w, , , 32, , , , )
-__CMPXCHG_CASE( , , , 64, , , , )
-__CMPXCHG_CASE(w, b, acq_, 8, , a, , "memory")
-__CMPXCHG_CASE(w, h, acq_, 16, , a, , "memory")
-__CMPXCHG_CASE(w, , acq_, 32, , a, , "memory")
-__CMPXCHG_CASE( , , acq_, 64, , a, , "memory")
-__CMPXCHG_CASE(w, b, rel_, 8, , , l, "memory")
-__CMPXCHG_CASE(w, h, rel_, 16, , , l, "memory")
-__CMPXCHG_CASE(w, , rel_, 32, , , l, "memory")
-__CMPXCHG_CASE( , , rel_, 64, , , l, "memory")
-__CMPXCHG_CASE(w, b, mb_, 8, dmb ish, , l, "memory")
-__CMPXCHG_CASE(w, h, mb_, 16, dmb ish, , l, "memory")
-__CMPXCHG_CASE(w, , mb_, 32, dmb ish, , l, "memory")
-__CMPXCHG_CASE( , , mb_, 64, dmb ish, , l, "memory")
+/*
+ * Earlier versions of GCC (no later than 8.1.0) appear to incorrectly
+ * handle the 'K' constraint for the value 4294967295 - thus we use no
+ * constraint for 32 bit operations.
+ */
+__CMPXCHG_CASE(w, b, , 8, , , , , K)
+__CMPXCHG_CASE(w, h, , 16, , , , , K)
+__CMPXCHG_CASE(w, , , 32, , , , , K)
+__CMPXCHG_CASE( , , , 64, , , , , L)
+__CMPXCHG_CASE(w, b, acq_, 8, , a, , "memory", K)
+__CMPXCHG_CASE(w, h, acq_, 16, , a, , "memory", K)
+__CMPXCHG_CASE(w, , acq_, 32, , a, , "memory", K)
+__CMPXCHG_CASE( , , acq_, 64, , a, , "memory", L)
+__CMPXCHG_CASE(w, b, rel_, 8, , , l, "memory", K)
+__CMPXCHG_CASE(w, h, rel_, 16, , , l, "memory", K)
+__CMPXCHG_CASE(w, , rel_, 32, , , l, "memory", K)
+__CMPXCHG_CASE( , , rel_, 64, , , l, "memory", L)
+__CMPXCHG_CASE(w, b, mb_, 8, dmb ish, , l, "memory", K)
+__CMPXCHG_CASE(w, h, mb_, 16, dmb ish, , l, "memory", K)
+__CMPXCHG_CASE(w, , mb_, 32, dmb ish, , l, "memory", K)
+__CMPXCHG_CASE( , , mb_, 64, dmb ish, , l, "memory", L)
#undef __CMPXCHG_CASE
#define __CMPXCHG_DBL(name, mb, rel, cl) \
-__LL_SC_INLINE long \
-__LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1, \
+static inline long \
+__ll_sc__cmpxchg_double##name(unsigned long old1, \
unsigned long old2, \
unsigned long new1, \
unsigned long new2, \
- volatile void *ptr)) \
+ volatile void *ptr) \
{ \
unsigned long tmp, ret; \
\
asm volatile("// __cmpxchg_double" #name "\n" \
+ __LL_SC_FALLBACK( \
" prfm pstl1strm, %2\n" \
"1: ldxp %0, %1, %2\n" \
" eor %0, %0, %3\n" \
@@ -311,18 +336,18 @@ __LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1, \
" st" #rel "xp %w0, %5, %6, %2\n" \
" cbnz %w0, 1b\n" \
" " #mb "\n" \
- "2:" \
+ "2:") \
: "=&r" (tmp), "=&r" (ret), "+Q" (*(unsigned long *)ptr) \
: "r" (old1), "r" (old2), "r" (new1), "r" (new2) \
: cl); \
\
return ret; \
-} \
-__LL_SC_EXPORT(__cmpxchg_double##name);
+}
__CMPXCHG_DBL( , , , )
__CMPXCHG_DBL(_mb, dmb ish, l, "memory")
#undef __CMPXCHG_DBL
+#undef K
#endif /* __ASM_ATOMIC_LL_SC_H */
diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h
index 69acb1c19a15..c6bd87d2915b 100644
--- a/arch/arm64/include/asm/atomic_lse.h
+++ b/arch/arm64/include/asm/atomic_lse.h
@@ -10,22 +10,13 @@
#ifndef __ASM_ATOMIC_LSE_H
#define __ASM_ATOMIC_LSE_H
-#ifndef __ARM64_IN_ATOMIC_IMPL
-#error "please don't include this file directly"
-#endif
-
-#define __LL_SC_ATOMIC(op) __LL_SC_CALL(arch_atomic_##op)
#define ATOMIC_OP(op, asm_op) \
-static inline void arch_atomic_##op(int i, atomic_t *v) \
+static inline void __lse_atomic_##op(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(op), \
-" " #asm_op " %w[i], %[v]\n") \
- : [i] "+r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS); \
+ asm volatile( \
+" " #asm_op " %w[i], %[v]\n" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v)); \
}
ATOMIC_OP(andnot, stclr)
@@ -36,21 +27,15 @@ ATOMIC_OP(add, stadd)
#undef ATOMIC_OP
#define ATOMIC_FETCH_OP(name, mb, op, asm_op, cl...) \
-static inline int arch_atomic_fetch_##op##name(int i, atomic_t *v) \
+static inline int __lse_atomic_fetch_##op##name(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC(fetch_##op##name), \
- /* LSE atomics */ \
-" " #asm_op #mb " %w[i], %w[i], %[v]") \
- : [i] "+r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ asm volatile( \
+" " #asm_op #mb " %w[i], %w[i], %[v]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return w0; \
+ return i; \
}
#define ATOMIC_FETCH_OPS(op, asm_op) \
@@ -68,23 +53,18 @@ ATOMIC_FETCH_OPS(add, ldadd)
#undef ATOMIC_FETCH_OPS
#define ATOMIC_OP_ADD_RETURN(name, mb, cl...) \
-static inline int arch_atomic_add_return##name(int i, atomic_t *v) \
+static inline int __lse_atomic_add_return##name(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
+ u32 tmp; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC(add_return##name) \
- __nops(1), \
- /* LSE atomics */ \
- " ldadd" #mb " %w[i], w30, %[v]\n" \
- " add %w[i], %w[i], w30") \
- : [i] "+r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ asm volatile( \
+ " ldadd" #mb " %w[i], %w[tmp], %[v]\n" \
+ " add %w[i], %w[i], %w[tmp]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \
+ : "r" (v) \
+ : cl); \
\
- return w0; \
+ return i; \
}
ATOMIC_OP_ADD_RETURN(_relaxed, )
@@ -94,41 +74,26 @@ ATOMIC_OP_ADD_RETURN( , al, "memory")
#undef ATOMIC_OP_ADD_RETURN
-static inline void arch_atomic_and(int i, atomic_t *v)
+static inline void __lse_atomic_and(int i, atomic_t *v)
{
- register int w0 asm ("w0") = i;
- register atomic_t *x1 asm ("x1") = v;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- __LL_SC_ATOMIC(and)
- __nops(1),
- /* LSE atomics */
+ asm volatile(
" mvn %w[i], %w[i]\n"
- " stclr %w[i], %[v]")
- : [i] "+&r" (w0), [v] "+Q" (v->counter)
- : "r" (x1)
- : __LL_SC_CLOBBERS);
+ " stclr %w[i], %[v]"
+ : [i] "+&r" (i), [v] "+Q" (v->counter)
+ : "r" (v));
}
#define ATOMIC_FETCH_OP_AND(name, mb, cl...) \
-static inline int arch_atomic_fetch_and##name(int i, atomic_t *v) \
+static inline int __lse_atomic_fetch_and##name(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC(fetch_and##name) \
- __nops(1), \
- /* LSE atomics */ \
+ asm volatile( \
" mvn %w[i], %w[i]\n" \
- " ldclr" #mb " %w[i], %w[i], %[v]") \
- : [i] "+&r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ " ldclr" #mb " %w[i], %w[i], %[v]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return w0; \
+ return i; \
}
ATOMIC_FETCH_OP_AND(_relaxed, )
@@ -138,42 +103,29 @@ ATOMIC_FETCH_OP_AND( , al, "memory")
#undef ATOMIC_FETCH_OP_AND
-static inline void arch_atomic_sub(int i, atomic_t *v)
+static inline void __lse_atomic_sub(int i, atomic_t *v)
{
- register int w0 asm ("w0") = i;
- register atomic_t *x1 asm ("x1") = v;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- __LL_SC_ATOMIC(sub)
- __nops(1),
- /* LSE atomics */
+ asm volatile(
" neg %w[i], %w[i]\n"
- " stadd %w[i], %[v]")
- : [i] "+&r" (w0), [v] "+Q" (v->counter)
- : "r" (x1)
- : __LL_SC_CLOBBERS);
+ " stadd %w[i], %[v]"
+ : [i] "+&r" (i), [v] "+Q" (v->counter)
+ : "r" (v));
}
#define ATOMIC_OP_SUB_RETURN(name, mb, cl...) \
-static inline int arch_atomic_sub_return##name(int i, atomic_t *v) \
+static inline int __lse_atomic_sub_return##name(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
+ u32 tmp; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC(sub_return##name) \
- __nops(2), \
- /* LSE atomics */ \
+ asm volatile( \
" neg %w[i], %w[i]\n" \
- " ldadd" #mb " %w[i], w30, %[v]\n" \
- " add %w[i], %w[i], w30") \
- : [i] "+&r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS , ##cl); \
+ " ldadd" #mb " %w[i], %w[tmp], %[v]\n" \
+ " add %w[i], %w[i], %w[tmp]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \
+ : "r" (v) \
+ : cl); \
\
- return w0; \
+ return i; \
}
ATOMIC_OP_SUB_RETURN(_relaxed, )
@@ -184,23 +136,16 @@ ATOMIC_OP_SUB_RETURN( , al, "memory")
#undef ATOMIC_OP_SUB_RETURN
#define ATOMIC_FETCH_OP_SUB(name, mb, cl...) \
-static inline int arch_atomic_fetch_sub##name(int i, atomic_t *v) \
+static inline int __lse_atomic_fetch_sub##name(int i, atomic_t *v) \
{ \
- register int w0 asm ("w0") = i; \
- register atomic_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC(fetch_sub##name) \
- __nops(1), \
- /* LSE atomics */ \
+ asm volatile( \
" neg %w[i], %w[i]\n" \
- " ldadd" #mb " %w[i], %w[i], %[v]") \
- : [i] "+&r" (w0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ " ldadd" #mb " %w[i], %w[i], %[v]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return w0; \
+ return i; \
}
ATOMIC_FETCH_OP_SUB(_relaxed, )
@@ -209,20 +154,14 @@ ATOMIC_FETCH_OP_SUB(_release, l, "memory")
ATOMIC_FETCH_OP_SUB( , al, "memory")
#undef ATOMIC_FETCH_OP_SUB
-#undef __LL_SC_ATOMIC
-#define __LL_SC_ATOMIC64(op) __LL_SC_CALL(arch_atomic64_##op)
#define ATOMIC64_OP(op, asm_op) \
-static inline void arch_atomic64_##op(s64 i, atomic64_t *v) \
+static inline void __lse_atomic64_##op(s64 i, atomic64_t *v) \
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(op), \
-" " #asm_op " %[i], %[v]\n") \
- : [i] "+r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS); \
+ asm volatile( \
+" " #asm_op " %[i], %[v]\n" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v)); \
}
ATOMIC64_OP(andnot, stclr)
@@ -233,21 +172,15 @@ ATOMIC64_OP(add, stadd)
#undef ATOMIC64_OP
#define ATOMIC64_FETCH_OP(name, mb, op, asm_op, cl...) \
-static inline s64 arch_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \
+static inline long __lse_atomic64_fetch_##op##name(s64 i, atomic64_t *v)\
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC64(fetch_##op##name), \
- /* LSE atomics */ \
-" " #asm_op #mb " %[i], %[i], %[v]") \
- : [i] "+r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ asm volatile( \
+" " #asm_op #mb " %[i], %[i], %[v]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return x0; \
+ return i; \
}
#define ATOMIC64_FETCH_OPS(op, asm_op) \
@@ -265,23 +198,18 @@ ATOMIC64_FETCH_OPS(add, ldadd)
#undef ATOMIC64_FETCH_OPS
#define ATOMIC64_OP_ADD_RETURN(name, mb, cl...) \
-static inline s64 arch_atomic64_add_return##name(s64 i, atomic64_t *v) \
+static inline long __lse_atomic64_add_return##name(s64 i, atomic64_t *v)\
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
+ unsigned long tmp; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC64(add_return##name) \
- __nops(1), \
- /* LSE atomics */ \
- " ldadd" #mb " %[i], x30, %[v]\n" \
- " add %[i], %[i], x30") \
- : [i] "+r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ asm volatile( \
+ " ldadd" #mb " %[i], %x[tmp], %[v]\n" \
+ " add %[i], %[i], %x[tmp]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \
+ : "r" (v) \
+ : cl); \
\
- return x0; \
+ return i; \
}
ATOMIC64_OP_ADD_RETURN(_relaxed, )
@@ -291,41 +219,26 @@ ATOMIC64_OP_ADD_RETURN( , al, "memory")
#undef ATOMIC64_OP_ADD_RETURN
-static inline void arch_atomic64_and(s64 i, atomic64_t *v)
+static inline void __lse_atomic64_and(s64 i, atomic64_t *v)
{
- register s64 x0 asm ("x0") = i;
- register atomic64_t *x1 asm ("x1") = v;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- __LL_SC_ATOMIC64(and)
- __nops(1),
- /* LSE atomics */
+ asm volatile(
" mvn %[i], %[i]\n"
- " stclr %[i], %[v]")
- : [i] "+&r" (x0), [v] "+Q" (v->counter)
- : "r" (x1)
- : __LL_SC_CLOBBERS);
+ " stclr %[i], %[v]"
+ : [i] "+&r" (i), [v] "+Q" (v->counter)
+ : "r" (v));
}
#define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \
-static inline s64 arch_atomic64_fetch_and##name(s64 i, atomic64_t *v) \
+static inline long __lse_atomic64_fetch_and##name(s64 i, atomic64_t *v) \
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC64(fetch_and##name) \
- __nops(1), \
- /* LSE atomics */ \
+ asm volatile( \
" mvn %[i], %[i]\n" \
- " ldclr" #mb " %[i], %[i], %[v]") \
- : [i] "+&r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ " ldclr" #mb " %[i], %[i], %[v]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return x0; \
+ return i; \
}
ATOMIC64_FETCH_OP_AND(_relaxed, )
@@ -335,42 +248,29 @@ ATOMIC64_FETCH_OP_AND( , al, "memory")
#undef ATOMIC64_FETCH_OP_AND
-static inline void arch_atomic64_sub(s64 i, atomic64_t *v)
+static inline void __lse_atomic64_sub(s64 i, atomic64_t *v)
{
- register s64 x0 asm ("x0") = i;
- register atomic64_t *x1 asm ("x1") = v;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- __LL_SC_ATOMIC64(sub)
- __nops(1),
- /* LSE atomics */
+ asm volatile(
" neg %[i], %[i]\n"
- " stadd %[i], %[v]")
- : [i] "+&r" (x0), [v] "+Q" (v->counter)
- : "r" (x1)
- : __LL_SC_CLOBBERS);
+ " stadd %[i], %[v]"
+ : [i] "+&r" (i), [v] "+Q" (v->counter)
+ : "r" (v));
}
#define ATOMIC64_OP_SUB_RETURN(name, mb, cl...) \
-static inline s64 arch_atomic64_sub_return##name(s64 i, atomic64_t *v) \
+static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v) \
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
+ unsigned long tmp; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC64(sub_return##name) \
- __nops(2), \
- /* LSE atomics */ \
+ asm volatile( \
" neg %[i], %[i]\n" \
- " ldadd" #mb " %[i], x30, %[v]\n" \
- " add %[i], %[i], x30") \
- : [i] "+&r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ " ldadd" #mb " %[i], %x[tmp], %[v]\n" \
+ " add %[i], %[i], %x[tmp]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \
+ : "r" (v) \
+ : cl); \
\
- return x0; \
+ return i; \
}
ATOMIC64_OP_SUB_RETURN(_relaxed, )
@@ -381,23 +281,16 @@ ATOMIC64_OP_SUB_RETURN( , al, "memory")
#undef ATOMIC64_OP_SUB_RETURN
#define ATOMIC64_FETCH_OP_SUB(name, mb, cl...) \
-static inline s64 arch_atomic64_fetch_sub##name(s64 i, atomic64_t *v) \
+static inline long __lse_atomic64_fetch_sub##name(s64 i, atomic64_t *v) \
{ \
- register s64 x0 asm ("x0") = i; \
- register atomic64_t *x1 asm ("x1") = v; \
- \
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_ATOMIC64(fetch_sub##name) \
- __nops(1), \
- /* LSE atomics */ \
+ asm volatile( \
" neg %[i], %[i]\n" \
- " ldadd" #mb " %[i], %[i], %[v]") \
- : [i] "+&r" (x0), [v] "+Q" (v->counter) \
- : "r" (x1) \
- : __LL_SC_CLOBBERS, ##cl); \
+ " ldadd" #mb " %[i], %[i], %[v]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
\
- return x0; \
+ return i; \
}
ATOMIC64_FETCH_OP_SUB(_relaxed, )
@@ -407,54 +300,44 @@ ATOMIC64_FETCH_OP_SUB( , al, "memory")
#undef ATOMIC64_FETCH_OP_SUB
-static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
+static inline s64 __lse_atomic64_dec_if_positive(atomic64_t *v)
{
- register long x0 asm ("x0") = (long)v;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- __LL_SC_ATOMIC64(dec_if_positive)
- __nops(6),
- /* LSE atomics */
- "1: ldr x30, %[v]\n"
- " subs %[ret], x30, #1\n"
+ unsigned long tmp;
+
+ asm volatile(
+ "1: ldr %x[tmp], %[v]\n"
+ " subs %[ret], %x[tmp], #1\n"
" b.lt 2f\n"
- " casal x30, %[ret], %[v]\n"
- " sub x30, x30, #1\n"
- " sub x30, x30, %[ret]\n"
- " cbnz x30, 1b\n"
- "2:")
- : [ret] "+&r" (x0), [v] "+Q" (v->counter)
+ " casal %x[tmp], %[ret], %[v]\n"
+ " sub %x[tmp], %x[tmp], #1\n"
+ " sub %x[tmp], %x[tmp], %[ret]\n"
+ " cbnz %x[tmp], 1b\n"
+ "2:"
+ : [ret] "+&r" (v), [v] "+Q" (v->counter), [tmp] "=&r" (tmp)
:
- : __LL_SC_CLOBBERS, "cc", "memory");
+ : "cc", "memory");
- return x0;
+ return (long)v;
}
-#undef __LL_SC_ATOMIC64
-
-#define __LL_SC_CMPXCHG(op) __LL_SC_CALL(__cmpxchg_case_##op)
-
#define __CMPXCHG_CASE(w, sfx, name, sz, mb, cl...) \
-static inline u##sz __cmpxchg_case_##name##sz(volatile void *ptr, \
+static inline u##sz __lse__cmpxchg_case_##name##sz(volatile void *ptr, \
u##sz old, \
u##sz new) \
{ \
register unsigned long x0 asm ("x0") = (unsigned long)ptr; \
register u##sz x1 asm ("x1") = old; \
register u##sz x2 asm ("x2") = new; \
+ unsigned long tmp; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_CMPXCHG(name##sz) \
- __nops(2), \
- /* LSE atomics */ \
- " mov " #w "30, %" #w "[old]\n" \
- " cas" #mb #sfx "\t" #w "30, %" #w "[new], %[v]\n" \
- " mov %" #w "[ret], " #w "30") \
- : [ret] "+r" (x0), [v] "+Q" (*(unsigned long *)ptr) \
+ asm volatile( \
+ " mov %" #w "[tmp], %" #w "[old]\n" \
+ " cas" #mb #sfx "\t%" #w "[tmp], %" #w "[new], %[v]\n" \
+ " mov %" #w "[ret], %" #w "[tmp]" \
+ : [ret] "+r" (x0), [v] "+Q" (*(unsigned long *)ptr), \
+ [tmp] "=&r" (tmp) \
: [old] "r" (x1), [new] "r" (x2) \
- : __LL_SC_CLOBBERS, ##cl); \
+ : cl); \
\
return x0; \
}
@@ -476,13 +359,10 @@ __CMPXCHG_CASE(w, h, mb_, 16, al, "memory")
__CMPXCHG_CASE(w, , mb_, 32, al, "memory")
__CMPXCHG_CASE(x, , mb_, 64, al, "memory")
-#undef __LL_SC_CMPXCHG
#undef __CMPXCHG_CASE
-#define __LL_SC_CMPXCHG_DBL(op) __LL_SC_CALL(__cmpxchg_double##op)
-
#define __CMPXCHG_DBL(name, mb, cl...) \
-static inline long __cmpxchg_double##name(unsigned long old1, \
+static inline long __lse__cmpxchg_double##name(unsigned long old1, \
unsigned long old2, \
unsigned long new1, \
unsigned long new2, \
@@ -496,20 +376,16 @@ static inline long __cmpxchg_double##name(unsigned long old1, \
register unsigned long x3 asm ("x3") = new2; \
register unsigned long x4 asm ("x4") = (unsigned long)ptr; \
\
- asm volatile(ARM64_LSE_ATOMIC_INSN( \
- /* LL/SC */ \
- __LL_SC_CMPXCHG_DBL(name) \
- __nops(3), \
- /* LSE atomics */ \
+ asm volatile( \
" casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\
" eor %[old1], %[old1], %[oldval1]\n" \
" eor %[old2], %[old2], %[oldval2]\n" \
- " orr %[old1], %[old1], %[old2]") \
+ " orr %[old1], %[old1], %[old2]" \
: [old1] "+&r" (x0), [old2] "+&r" (x1), \
[v] "+Q" (*(unsigned long *)ptr) \
: [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \
[oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \
- : __LL_SC_CLOBBERS, ##cl); \
+ : cl); \
\
return x0; \
}
@@ -517,7 +393,6 @@ static inline long __cmpxchg_double##name(unsigned long old1, \
__CMPXCHG_DBL( , )
__CMPXCHG_DBL(_mb, al, "memory")
-#undef __LL_SC_CMPXCHG_DBL
#undef __CMPXCHG_DBL
#endif /* __ASM_ATOMIC_LSE_H */
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
index 64eeaa41e7ca..43da6dd29592 100644
--- a/arch/arm64/include/asm/cache.h
+++ b/arch/arm64/include/asm/cache.h
@@ -78,7 +78,7 @@ static inline u32 cache_type_cwg(void)
return (read_cpuid_cachetype() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
}
-#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+#define __read_mostly __section(.data..read_mostly)
static inline int cache_line_size_of_cpu(void)
{
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
index 7a299a20f6dc..a1398f2f9994 100644
--- a/arch/arm64/include/asm/cmpxchg.h
+++ b/arch/arm64/include/asm/cmpxchg.h
@@ -10,7 +10,6 @@
#include <linux/build_bug.h>
#include <linux/compiler.h>
-#include <asm/atomic.h>
#include <asm/barrier.h>
#include <asm/lse.h>
@@ -104,6 +103,50 @@ __XCHG_GEN(_mb)
#define arch_xchg_release(...) __xchg_wrapper(_rel, __VA_ARGS__)
#define arch_xchg(...) __xchg_wrapper( _mb, __VA_ARGS__)
+#define __CMPXCHG_CASE(name, sz) \
+static inline u##sz __cmpxchg_case_##name##sz(volatile void *ptr, \
+ u##sz old, \
+ u##sz new) \
+{ \
+ return __lse_ll_sc_body(_cmpxchg_case_##name##sz, \
+ ptr, old, new); \
+}
+
+__CMPXCHG_CASE( , 8)
+__CMPXCHG_CASE( , 16)
+__CMPXCHG_CASE( , 32)
+__CMPXCHG_CASE( , 64)
+__CMPXCHG_CASE(acq_, 8)
+__CMPXCHG_CASE(acq_, 16)
+__CMPXCHG_CASE(acq_, 32)
+__CMPXCHG_CASE(acq_, 64)
+__CMPXCHG_CASE(rel_, 8)
+__CMPXCHG_CASE(rel_, 16)
+__CMPXCHG_CASE(rel_, 32)
+__CMPXCHG_CASE(rel_, 64)
+__CMPXCHG_CASE(mb_, 8)
+__CMPXCHG_CASE(mb_, 16)
+__CMPXCHG_CASE(mb_, 32)
+__CMPXCHG_CASE(mb_, 64)
+
+#undef __CMPXCHG_CASE
+
+#define __CMPXCHG_DBL(name) \
+static inline long __cmpxchg_double##name(unsigned long old1, \
+ unsigned long old2, \
+ unsigned long new1, \
+ unsigned long new2, \
+ volatile void *ptr) \
+{ \
+ return __lse_ll_sc_body(_cmpxchg_double##name, \
+ old1, old2, new1, new2, ptr); \
+}
+
+__CMPXCHG_DBL( )
+__CMPXCHG_DBL(_mb)
+
+#undef __CMPXCHG_DBL
+
#define __CMPXCHG_GEN(sfx) \
static inline unsigned long __cmpxchg##sfx(volatile void *ptr, \
unsigned long old, \
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index fb8ad4616b3b..b0d53a265f1d 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -4,7 +4,6 @@
*/
#ifndef __ASM_COMPAT_H
#define __ASM_COMPAT_H
-#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
/*
@@ -215,5 +214,4 @@ static inline int is_compat_thread(struct thread_info *thread)
}
#endif /* CONFIG_COMPAT */
-#endif /* __KERNEL__ */
#endif /* __ASM_COMPAT_H */
diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
index c09d633c3109..86aabf1e0199 100644
--- a/arch/arm64/include/asm/cpu_ops.h
+++ b/arch/arm64/include/asm/cpu_ops.h
@@ -23,6 +23,8 @@
* @cpu_boot: Boots a cpu into the kernel.
* @cpu_postboot: Optionally, perform any post-boot cleanup or necesary
* synchronisation. Called from the cpu being booted.
+ * @cpu_can_disable: Determines whether a CPU can be disabled based on
+ * mechanism-specific information.
* @cpu_disable: Prepares a cpu to die. May fail for some mechanism-specific
* reason, which will cause the hot unplug to be aborted. Called
* from the cpu to be killed.
@@ -42,6 +44,7 @@ struct cpu_operations {
int (*cpu_boot)(unsigned int);
void (*cpu_postboot)(void);
#ifdef CONFIG_HOTPLUG_CPU
+ bool (*cpu_can_disable)(unsigned int cpu);
int (*cpu_disable)(unsigned int cpu);
void (*cpu_die)(unsigned int cpu);
int (*cpu_kill)(unsigned int cpu);
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 407e2bf23676..9cde5d2e768f 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -35,9 +35,10 @@
*/
enum ftr_type {
- FTR_EXACT, /* Use a predefined safe value */
- FTR_LOWER_SAFE, /* Smaller value is safe */
- FTR_HIGHER_SAFE,/* Bigger value is safe */
+ FTR_EXACT, /* Use a predefined safe value */
+ FTR_LOWER_SAFE, /* Smaller value is safe */
+ FTR_HIGHER_SAFE, /* Bigger value is safe */
+ FTR_HIGHER_OR_ZERO_SAFE, /* Bigger value is safe, but 0 is biggest */
};
#define FTR_STRICT true /* SANITY check strict matching required */
@@ -288,9 +289,16 @@ struct arm64_cpu_capabilities {
u16 type;
bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
/*
- * Take the appropriate actions to enable this capability for this CPU.
- * For each successfully booted CPU, this method is called for each
- * globally detected capability.
+ * Take the appropriate actions to configure this capability
+ * for this CPU. If the capability is detected by the kernel
+ * this will be called on all the CPUs in the system,
+ * including the hotplugged CPUs, regardless of whether the
+ * capability is available on that specific CPU. This is
+ * useful for some capabilities (e.g, working around CPU
+ * errata), where all the CPUs must take some action (e.g,
+ * changing system control/configuration). Thus, if an action
+ * is required only if the CPU has the capability, then the
+ * routine must check it before taking any action.
*/
void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
union {
@@ -362,21 +370,6 @@ cpucap_multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
return false;
}
-/*
- * Take appropriate action for all matching entries in the shared capability
- * entry.
- */
-static inline void
-cpucap_multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
-{
- const struct arm64_cpu_capabilities *caps;
-
- for (caps = entry->match_list; caps->matches; caps++)
- if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
- caps->cpu_enable)
- caps->cpu_enable(caps);
-}
-
extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
extern struct static_key_false arm64_const_caps_ready;
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index e7d46631cc42..b1454d117cd2 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -51,14 +51,6 @@
#define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
MIDR_ARCHITECTURE_MASK)
-#define MIDR_IS_CPU_MODEL_RANGE(midr, model, rv_min, rv_max) \
-({ \
- u32 _model = (midr) & MIDR_CPU_MODEL_MASK; \
- u32 rv = (midr) & (MIDR_REVISION_MASK | MIDR_VARIANT_MASK); \
- \
- _model == (model) && rv >= (rv_min) && rv <= (rv_max); \
- })
-
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_APM 0x50
#define ARM_CPU_IMP_CAVIUM 0x43
@@ -159,10 +151,19 @@ struct midr_range {
#define MIDR_REV(m, v, r) MIDR_RANGE(m, v, r, v, r)
#define MIDR_ALL_VERSIONS(m) MIDR_RANGE(m, 0, 0, 0xf, 0xf)
+static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
+ u32 rv_max)
+{
+ u32 _model = midr & MIDR_CPU_MODEL_MASK;
+ u32 rv = midr & (MIDR_REVISION_MASK | MIDR_VARIANT_MASK);
+
+ return _model == model && rv >= rv_min && rv <= rv_max;
+}
+
static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
{
- return MIDR_IS_CPU_MODEL_RANGE(midr, range->model,
- range->rv_min, range->rv_max);
+ return midr_is_cpu_model_range(midr, range->model,
+ range->rv_min, range->rv_max);
}
static inline bool
diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h
index 987926ed535e..063c964af705 100644
--- a/arch/arm64/include/asm/daifflags.h
+++ b/arch/arm64/include/asm/daifflags.h
@@ -13,6 +13,8 @@
#define DAIF_PROCCTX 0
#define DAIF_PROCCTX_NOIRQ PSR_I_BIT
#define DAIF_ERRCTX (PSR_I_BIT | PSR_A_BIT)
+#define DAIF_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
+
/* mask/save/unmask/restore all exceptions, including interrupts. */
static inline void local_daif_mask(void)
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index d8ec5bb881c2..7619f473155f 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -5,8 +5,6 @@
#ifndef __ASM_DEBUG_MONITORS_H
#define __ASM_DEBUG_MONITORS_H
-#ifdef __KERNEL__
-
#include <linux/errno.h>
#include <linux/types.h>
#include <asm/brk-imm.h>
@@ -128,5 +126,4 @@ static inline int reinstall_suspended_bps(struct pt_regs *regs)
int aarch32_break_handler(struct pt_regs *regs);
#endif /* __ASSEMBLY */
-#endif /* __KERNEL__ */
#endif /* __ASM_DEBUG_MONITORS_H */
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index bdcb0922a40c..fb3e5044f473 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -5,8 +5,6 @@
#ifndef __ASM_DMA_MAPPING_H
#define __ASM_DMA_MAPPING_H
-#ifdef __KERNEL__
-
#include <linux/types.h>
#include <linux/vmalloc.h>
@@ -27,5 +25,4 @@ static inline bool is_device_dma_coherent(struct device *dev)
return dev->dma_coherent;
}
-#endif /* __KERNEL__ */
#endif /* __ASM_DMA_MAPPING_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8e79ce9c3f5c..b54d3a86c444 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -79,7 +79,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
/*
* On arm64, we have to ensure that the initrd ends up in the linear region,
- * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
+ * which is a 1 GB aligned region of size '1UL << (VA_BITS_MIN - 1)' that is
* guaranteed to cover the kernel Image.
*
* Since the EFI stub is part of the kernel Image, we can relax the
@@ -90,7 +90,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
unsigned long image_addr)
{
- return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
+ return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
}
#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
@@ -105,7 +105,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
#define alloc_screen_info(x...) &screen_info
-#define free_screen_info(x...)
+
+static inline void free_screen_info(efi_system_table_t *sys_table_arg,
+ struct screen_info *si)
+{
+}
/* redeclare as 'hidden' so the compiler will generate relative references */
extern struct screen_info screen_info __attribute__((__visibility__("hidden")));
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 3c7037c6ba9b..b618017205a3 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -202,7 +202,7 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
({ \
set_thread_flag(TIF_32BIT); \
})
-#ifdef CONFIG_GENERIC_COMPAT_VDSO
+#ifdef CONFIG_COMPAT_VDSO
#define COMPAT_ARCH_DLINFO \
do { \
/* \
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 65ac18400979..cb29253ae86b 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -34,7 +34,8 @@
#define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */
#define ESR_ELx_EC_SYS64 (0x18)
#define ESR_ELx_EC_SVE (0x19)
-/* Unallocated EC: 0x1A - 0x1E */
+#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */
+/* Unallocated EC: 0x1b - 0x1E */
#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */
#define ESR_ELx_EC_IABT_LOW (0x20)
#define ESR_ELx_EC_IABT_CUR (0x21)
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index ed57b760f38c..a17393ff6677 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -30,4 +30,6 @@ static inline u32 disr_to_esr(u64 disr)
return esr;
}
+asmlinkage void enter_from_user_mode(void);
+
#endif /* __ASM_EXCEPTION_H */
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index b6a2c352f4c3..59f10dd13f12 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -21,7 +21,7 @@
#include <linux/stddef.h>
#include <linux/types.h>
-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#ifdef CONFIG_COMPAT
/* Masks for extracting the FPSR and FPCR from the FPSCR */
#define VFP_FPSCR_STAT_MASK 0xf800009f
#define VFP_FPSCR_CTRL_MASK 0x07f79f00
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index 6211e3105491..6cc26a127819 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -5,8 +5,6 @@
#ifndef __ASM_FUTEX_H
#define __ASM_FUTEX_H
-#ifdef __KERNEL__
-
#include <linux/futex.h>
#include <linux/uaccess.h>
@@ -129,5 +127,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr,
return ret;
}
-#endif /* __KERNEL__ */
#endif /* __ASM_FUTEX_H */
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
index db9ab760e6fd..bc7aaed4b34e 100644
--- a/arch/arm64/include/asm/hw_breakpoint.h
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -10,8 +10,6 @@
#include <asm/sysreg.h>
#include <asm/virt.h>
-#ifdef __KERNEL__
-
struct arch_hw_breakpoint_ctrl {
u32 __reserved : 19,
len : 8,
@@ -156,5 +154,4 @@ static inline int get_num_wrps(void)
ID_AA64DFR0_WRPS_SHIFT);
}
-#endif /* __KERNEL__ */
#endif /* __ASM_BREAKPOINT_H */
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 7ed92626949d..323cb306bd28 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -8,8 +8,6 @@
#ifndef __ASM_IO_H
#define __ASM_IO_H
-#ifdef __KERNEL__
-
#include <linux/types.h>
#include <asm/byteorder.h>
@@ -97,7 +95,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
({ \
unsigned long tmp; \
\
- rmb(); \
+ dma_rmb(); \
\
/* \
* Create a dummy control dependency from the IO read to any \
@@ -111,7 +109,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
})
#define __io_par(v) __iormb(v)
-#define __iowmb() wmb()
+#define __iowmb() dma_wmb()
/*
* Relaxed I/O memory access primitives. These follow the Device memory
@@ -165,14 +163,13 @@ extern void __memset_io(volatile void __iomem *, int, size_t);
* I/O memory mapping functions.
*/
extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot);
-extern void __iounmap(volatile void __iomem *addr);
+extern void iounmap(volatile void __iomem *addr);
extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
#define ioremap_wt(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
-#define iounmap __iounmap
/*
* PCI configuration space mapping function.
@@ -207,5 +204,4 @@ extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
extern int devmem_is_allowed(unsigned long pfn);
-#endif /* __KERNEL__ */
#endif /* __ASM_IO_H */
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
index 7872f260c9ee..1a59f0ed1ae3 100644
--- a/arch/arm64/include/asm/irqflags.h
+++ b/arch/arm64/include/asm/irqflags.h
@@ -5,8 +5,6 @@
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
-#ifdef __KERNEL__
-
#include <asm/alternative.h>
#include <asm/ptrace.h>
#include <asm/sysreg.h>
@@ -128,5 +126,4 @@ static inline void arch_local_irq_restore(unsigned long flags)
: "memory");
}
-#endif
-#endif
+#endif /* __ASM_IRQFLAGS_H */
diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
index b52aacd2c526..b0dc4abc3589 100644
--- a/arch/arm64/include/asm/kasan.h
+++ b/arch/arm64/include/asm/kasan.h
@@ -18,11 +18,8 @@
* KASAN_SHADOW_START: beginning of the kernel virtual addresses.
* KASAN_SHADOW_END: KASAN_SHADOW_START + 1/N of kernel virtual addresses,
* where N = (1 << KASAN_SHADOW_SCALE_SHIFT).
- */
-#define KASAN_SHADOW_START (VA_START)
-#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
-
-/*
+ *
+ * KASAN_SHADOW_OFFSET:
* This value is used to map an address to the corresponding shadow
* address by the following formula:
* shadow_addr = (address >> KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET
@@ -33,8 +30,8 @@
* KASAN_SHADOW_OFFSET = KASAN_SHADOW_END -
* (1ULL << (64 - KASAN_SHADOW_SCALE_SHIFT))
*/
-#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << \
- (64 - KASAN_SHADOW_SCALE_SHIFT)))
+#define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (1UL << ((va) - KASAN_SHADOW_SCALE_SHIFT)))
+#define KASAN_SHADOW_START _KASAN_SHADOW_START(vabits_actual)
void kasan_init(void);
void kasan_copy_shadow(pgd_t *pgdir);
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index a8b205e5c4a8..ddf9d762ac62 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -316,9 +316,10 @@
#define kvm_arm_exception_class \
ECN(UNKNOWN), ECN(WFx), ECN(CP15_32), ECN(CP15_64), ECN(CP14_MR), \
- ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(CP14_64), ECN(SVC64), \
- ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(IMP_DEF), ECN(IABT_LOW), \
- ECN(IABT_CUR), ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
+ ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(PAC), ECN(CP14_64), \
+ ECN(SVC64), ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(SVE), \
+ ECN(IMP_DEF), ECN(IABT_LOW), ECN(IABT_CUR), \
+ ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
ECN(SP_ALIGN), ECN(FP_EXC32), ECN(FP_EXC64), ECN(SERROR), \
ECN(BREAKPT_LOW), ECN(BREAKPT_CUR), ECN(SOFTSTP_LOW), \
ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \
diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h
index 8262325e2fc6..80b388278149 100644
--- a/arch/arm64/include/asm/lse.h
+++ b/arch/arm64/include/asm/lse.h
@@ -2,56 +2,47 @@
#ifndef __ASM_LSE_H
#define __ASM_LSE_H
+#include <asm/atomic_ll_sc.h>
+
#if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
#include <linux/compiler_types.h>
#include <linux/export.h>
+#include <linux/jump_label.h>
#include <linux/stringify.h>
#include <asm/alternative.h>
+#include <asm/atomic_lse.h>
#include <asm/cpucaps.h>
-#ifdef __ASSEMBLER__
-
-.arch_extension lse
-
-.macro alt_lse, llsc, lse
- alternative_insn "\llsc", "\lse", ARM64_HAS_LSE_ATOMICS
-.endm
-
-#else /* __ASSEMBLER__ */
-
__asm__(".arch_extension lse");
-/* Move the ll/sc atomics out-of-line */
-#define __LL_SC_INLINE notrace
-#define __LL_SC_PREFIX(x) __ll_sc_##x
-#define __LL_SC_EXPORT(x) EXPORT_SYMBOL(__LL_SC_PREFIX(x))
+extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
+extern struct static_key_false arm64_const_caps_ready;
+
+static inline bool system_uses_lse_atomics(void)
+{
+ return (static_branch_likely(&arm64_const_caps_ready)) &&
+ static_branch_likely(&cpu_hwcap_keys[ARM64_HAS_LSE_ATOMICS]);
+}
-/* Macro for constructing calls to out-of-line ll/sc atomics */
-#define __LL_SC_CALL(op) "bl\t" __stringify(__LL_SC_PREFIX(op)) "\n"
-#define __LL_SC_CLOBBERS "x16", "x17", "x30"
+#define __lse_ll_sc_body(op, ...) \
+({ \
+ system_uses_lse_atomics() ? \
+ __lse_##op(__VA_ARGS__) : \
+ __ll_sc_##op(__VA_ARGS__); \
+})
/* In-line patching at runtime */
#define ARM64_LSE_ATOMIC_INSN(llsc, lse) \
ALTERNATIVE(llsc, lse, ARM64_HAS_LSE_ATOMICS)
-#endif /* __ASSEMBLER__ */
#else /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
-#ifdef __ASSEMBLER__
-
-.macro alt_lse, llsc, lse
- \llsc
-.endm
-
-#else /* __ASSEMBLER__ */
+static inline bool system_uses_lse_atomics(void) { return false; }
-#define __LL_SC_INLINE static inline
-#define __LL_SC_PREFIX(x) x
-#define __LL_SC_EXPORT(x)
+#define __lse_ll_sc_body(op, ...) __ll_sc_##op(__VA_ARGS__)
#define ARM64_LSE_ATOMIC_INSN(llsc, lse) llsc
-#endif /* __ASSEMBLER__ */
#endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
#endif /* __ASM_LSE_H */
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index b7ba75809751..b61b50bf68b1 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -12,10 +12,10 @@
#include <linux/compiler.h>
#include <linux/const.h>
+#include <linux/sizes.h>
#include <linux/types.h>
#include <asm/bug.h>
#include <asm/page-def.h>
-#include <linux/sizes.h>
/*
* Size of the PCI I/O space. This must remain a power of two so that
@@ -26,37 +26,50 @@
/*
* VMEMMAP_SIZE - allows the whole linear region to be covered by
* a struct page array
+ *
+ * If we are configured with a 52-bit kernel VA then our VMEMMAP_SIZE
+ * needs to cover the memory region from the beginning of the 52-bit
+ * PAGE_OFFSET all the way to PAGE_END for 48-bit. This allows us to
+ * keep a constant PAGE_OFFSET and "fallback" to using the higher end
+ * of the VMEMMAP where 52-bit support is not available in hardware.
*/
-#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT))
+#define VMEMMAP_SIZE ((_PAGE_END(VA_BITS_MIN) - PAGE_OFFSET) \
+ >> (PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT))
/*
- * PAGE_OFFSET - the virtual address of the start of the linear map (top
- * (VA_BITS - 1))
- * KIMAGE_VADDR - the virtual address of the start of the kernel image
+ * PAGE_OFFSET - the virtual address of the start of the linear map, at the
+ * start of the TTBR1 address space.
+ * PAGE_END - the end of the linear map, where all other kernel mappings begin.
+ * KIMAGE_VADDR - the virtual address of the start of the kernel image.
* VA_BITS - the maximum number of bits for virtual addresses.
- * VA_START - the first kernel virtual address.
*/
#define VA_BITS (CONFIG_ARM64_VA_BITS)
-#define VA_START (UL(0xffffffffffffffff) - \
- (UL(1) << VA_BITS) + 1)
-#define PAGE_OFFSET (UL(0xffffffffffffffff) - \
- (UL(1) << (VA_BITS - 1)) + 1)
+#define _PAGE_OFFSET(va) (-(UL(1) << (va)))
+#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS))
#define KIMAGE_VADDR (MODULES_END)
-#define BPF_JIT_REGION_START (VA_START + KASAN_SHADOW_SIZE)
+#define BPF_JIT_REGION_START (KASAN_SHADOW_END)
#define BPF_JIT_REGION_SIZE (SZ_128M)
#define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE)
#define MODULES_END (MODULES_VADDR + MODULES_VSIZE)
#define MODULES_VADDR (BPF_JIT_REGION_END)
#define MODULES_VSIZE (SZ_128M)
-#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE)
+#define VMEMMAP_START (-VMEMMAP_SIZE - SZ_2M)
#define PCI_IO_END (VMEMMAP_START - SZ_2M)
#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE)
#define FIXADDR_TOP (PCI_IO_START - SZ_2M)
-#define KERNEL_START _text
-#define KERNEL_END _end
+#if VA_BITS > 48
+#define VA_BITS_MIN (48)
+#else
+#define VA_BITS_MIN (VA_BITS)
+#endif
+
+#define _PAGE_END(va) (-(UL(1) << ((va) - 1)))
+
+#define KERNEL_START _text
+#define KERNEL_END _end
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+#ifdef CONFIG_ARM64_VA_BITS_52
#define MAX_USER_VA_BITS 52
#else
#define MAX_USER_VA_BITS VA_BITS
@@ -68,12 +81,14 @@
* significantly, so double the (minimum) stack size when they are in use.
*/
#ifdef CONFIG_KASAN
-#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT))
+#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
+#define KASAN_SHADOW_END ((UL(1) << (64 - KASAN_SHADOW_SCALE_SHIFT)) \
+ + KASAN_SHADOW_OFFSET)
#define KASAN_THREAD_SHIFT 1
#else
-#define KASAN_SHADOW_SIZE (0)
#define KASAN_THREAD_SHIFT 0
-#endif
+#define KASAN_SHADOW_END (_PAGE_END(VA_BITS_MIN))
+#endif /* CONFIG_KASAN */
#define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT)
@@ -117,14 +132,14 @@
* 16 KB granule: 128 level 3 entries, with contiguous bit
* 64 KB granule: 32 level 3 entries, with contiguous bit
*/
-#define SEGMENT_ALIGN SZ_2M
+#define SEGMENT_ALIGN SZ_2M
#else
/*
* 4 KB granule: 16 level 3 entries, with contiguous bit
* 16 KB granule: 4 level 3 entries, without contiguous bit
* 64 KB granule: 1 level 3 entry
*/
-#define SEGMENT_ALIGN SZ_64K
+#define SEGMENT_ALIGN SZ_64K
#endif
/*
@@ -157,10 +172,13 @@
#endif
#ifndef __ASSEMBLY__
+extern u64 vabits_actual;
+#define PAGE_END (_PAGE_END(vabits_actual))
#include <linux/bitops.h>
#include <linux/mmdebug.h>
+extern s64 physvirt_offset;
extern s64 memstart_addr;
/* PHYS_OFFSET - the physical address of the start of memory. */
#define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
@@ -176,9 +194,6 @@ static inline unsigned long kaslr_offset(void)
return kimage_vaddr - KIMAGE_VADDR;
}
-/* the actual size of a user virtual address */
-extern u64 vabits_user;
-
/*
* Allow all memory at the discovery stage. We will clip it later.
*/
@@ -201,19 +216,23 @@ extern u64 vabits_user;
* pass on to access_ok(), for instance.
*/
#define untagged_addr(addr) \
- ((__typeof__(addr))sign_extend64((u64)(addr), 55))
+ ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
#ifdef CONFIG_KASAN_SW_TAGS
#define __tag_shifted(tag) ((u64)(tag) << 56)
-#define __tag_set(addr, tag) (__typeof__(addr))( \
- ((u64)(addr) & ~__tag_shifted(0xff)) | __tag_shifted(tag))
#define __tag_reset(addr) untagged_addr(addr)
#define __tag_get(addr) (__u8)((u64)(addr) >> 56)
#else
-#define __tag_set(addr, tag) (addr)
+#define __tag_shifted(tag) 0UL
#define __tag_reset(addr) (addr)
#define __tag_get(addr) 0
-#endif
+#endif /* CONFIG_KASAN_SW_TAGS */
+
+static inline const void *__tag_set(const void *addr, u8 tag)
+{
+ u64 __addr = (u64)addr & ~__tag_shifted(0xff);
+ return (const void *)(__addr | __tag_shifted(tag));
+}
/*
* Physical vs virtual RAM address space conversion. These are
@@ -223,19 +242,18 @@ extern u64 vabits_user;
/*
- * The linear kernel range starts in the middle of the virtual adddress
+ * The linear kernel range starts at the bottom of the virtual address
* space. Testing the top bit for the start of the region is a
- * sufficient check.
+ * sufficient check and avoids having to worry about the tag.
*/
-#define __is_lm_address(addr) (!!((addr) & BIT(VA_BITS - 1)))
+#define __is_lm_address(addr) (!(((u64)addr) & BIT(vabits_actual - 1)))
-#define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
+#define __lm_to_phys(addr) (((addr) + physvirt_offset))
#define __kimg_to_phys(addr) ((addr) - kimage_voffset)
#define __virt_to_phys_nodebug(x) ({ \
- phys_addr_t __x = (phys_addr_t)(x); \
- __is_lm_address(__x) ? __lm_to_phys(__x) : \
- __kimg_to_phys(__x); \
+ phys_addr_t __x = (phys_addr_t)(__tag_reset(x)); \
+ __is_lm_address(__x) ? __lm_to_phys(__x) : __kimg_to_phys(__x); \
})
#define __pa_symbol_nodebug(x) __kimg_to_phys((phys_addr_t)(x))
@@ -246,9 +264,9 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
#else
#define __virt_to_phys(x) __virt_to_phys_nodebug(x)
#define __phys_addr_symbol(x) __pa_symbol_nodebug(x)
-#endif
+#endif /* CONFIG_DEBUG_VIRTUAL */
-#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
+#define __phys_to_virt(x) ((unsigned long)((x) - physvirt_offset))
#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
/*
@@ -282,41 +300,38 @@ static inline void *phys_to_virt(phys_addr_t x)
#define __pa_nodebug(x) __virt_to_phys_nodebug((unsigned long)(x))
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
-#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
+#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
+#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
/*
- * virt_to_page(k) convert a _valid_ virtual address to struct page *
- * virt_addr_valid(k) indicates whether a virtual address is valid
+ * virt_to_page(x) convert a _valid_ virtual address to struct page *
+ * virt_addr_valid(x) indicates whether a virtual address is valid
*/
#define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET)
#if !defined(CONFIG_SPARSEMEM_VMEMMAP) || defined(CONFIG_DEBUG_VIRTUAL)
-#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_to_page(x) pfn_to_page(virt_to_pfn(x))
#else
-#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
-#define __page_to_voff(kaddr) (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
-
-#define page_to_virt(page) ({ \
- unsigned long __addr = \
- ((__page_to_voff(page)) | PAGE_OFFSET); \
- unsigned long __addr_tag = \
- __tag_set(__addr, page_kasan_tag(page)); \
- ((void *)__addr_tag); \
+#define page_to_virt(x) ({ \
+ __typeof__(x) __page = x; \
+ u64 __idx = ((u64)__page - VMEMMAP_START) / sizeof(struct page);\
+ u64 __addr = PAGE_OFFSET + (__idx * PAGE_SIZE); \
+ (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\
})
-#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
+#define virt_to_page(x) ({ \
+ u64 __idx = (__tag_reset((u64)x) - PAGE_OFFSET) / PAGE_SIZE; \
+ u64 __addr = VMEMMAP_START + (__idx * sizeof(struct page)); \
+ (struct page *)__addr; \
+})
+#endif /* !CONFIG_SPARSEMEM_VMEMMAP || CONFIG_DEBUG_VIRTUAL */
-#define _virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \
- + PHYS_OFFSET) >> PAGE_SHIFT)
-#endif
-#endif
+#define virt_addr_valid(addr) ({ \
+ __typeof__(addr) __addr = addr; \
+ __is_lm_address(__addr) && pfn_valid(virt_to_pfn(__addr)); \
+})
-#define _virt_addr_is_linear(kaddr) \
- (__tag_reset((u64)(kaddr)) >= PAGE_OFFSET)
-#define virt_addr_valid(kaddr) \
- (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
+#endif /* !ASSEMBLY */
/*
* Given that the GIC architecture permits ITS implementations that can only be
@@ -331,4 +346,4 @@ static inline void *phys_to_virt(phys_addr_t x)
#include <asm-generic/memory_model.h>
-#endif
+#endif /* __ASM_MEMORY_H */
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index fd6161336653..f217e3292919 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -126,7 +126,7 @@ extern void init_mem_pgprot(void);
extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot, bool page_mappings_only);
-extern void *fixmap_remap_fdt(phys_addr_t dt_phys);
+extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
extern void mark_linear_text_alias_ro(void);
#define INIT_MM_CONTEXT(name) \
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 7ed0adb187a8..3827ff4040a3 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -63,7 +63,7 @@ extern u64 idmap_ptrs_per_pgd;
static inline bool __cpu_uses_extended_idmap(void)
{
- if (IS_ENABLED(CONFIG_ARM64_USER_VA_BITS_52))
+ if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52))
return false;
return unlikely(idmap_t0sz != TCR_T0SZ(VA_BITS));
@@ -95,7 +95,7 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
isb();
}
-#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS))
+#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual))
#define cpu_set_idmap_tcr_t0sz() __cpu_set_tcr_t0sz(idmap_t0sz)
/*
diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
index 9e690686e8aa..70b323cf8300 100644
--- a/arch/arm64/include/asm/pci.h
+++ b/arch/arm64/include/asm/pci.h
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_PCI_H
#define __ASM_PCI_H
-#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/slab.h>
@@ -35,5 +34,4 @@ static inline int pci_proc_domain(struct pci_bus *bus)
}
#endif /* CONFIG_PCI */
-#endif /* __KERNEL__ */
#endif /* __ASM_PCI_H */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index db92950bb1a0..3df60f97da1f 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -304,7 +304,7 @@
#define TTBR_BADDR_MASK_52 (((UL(1) << 46) - 1) << 2)
#endif
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+#ifdef CONFIG_ARM64_VA_BITS_52
/* Must be at least 64-byte aligned to prevent corruption of the TTBR */
#define TTBR1_BADDR_4852_OFFSET (((UL(1) << (52 - PGDIR_SHIFT)) - \
(UL(1) << (48 - PGDIR_SHIFT))) * 8)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 87a4b2ddc1a1..470ba7ae8821 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -21,9 +21,7 @@
* and fixed mappings
*/
#define VMALLOC_START (MODULES_END)
-#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
-
-#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
+#define VMALLOC_END (- PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
#define FIRST_USER_ADDRESS 0UL
@@ -35,6 +33,8 @@
#include <linux/mm_types.h>
#include <linux/sched.h>
+extern struct page *vmemmap;
+
extern void __pte_error(const char *file, int line, unsigned long val);
extern void __pmd_error(const char *file, int line, unsigned long val);
extern void __pud_error(const char *file, int line, unsigned long val);
@@ -209,7 +209,7 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
static inline pte_t pte_mkdevmap(pte_t pte)
{
- return set_pte_bit(pte, __pgprot(PTE_DEVMAP));
+ return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
}
static inline void set_pte(pte_t *ptep, pte_t pte)
@@ -220,8 +220,10 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
* Only if the new pte is valid and kernel, otherwise TLB maintenance
* or update_mmu_cache() have the necessary barriers.
*/
- if (pte_valid_not_user(pte))
+ if (pte_valid_not_user(pte)) {
dsb(ishst);
+ isb();
+ }
}
extern void __sync_icache_dcache(pte_t pteval);
@@ -301,7 +303,6 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
/*
* Huge pte definitions.
*/
-#define pte_huge(pte) (!(pte_val(pte) & PTE_TABLE_BIT))
#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
/*
@@ -397,7 +398,10 @@ static inline int pmd_protnone(pmd_t pmd)
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define pmd_devmap(pmd) pte_devmap(pmd_pte(pmd))
#endif
-#define pmd_mkdevmap(pmd) pte_pmd(pte_mkdevmap(pmd_pte(pmd)))
+static inline pmd_t pmd_mkdevmap(pmd_t pmd)
+{
+ return pte_pmd(set_pte_bit(pmd_pte(pmd), __pgprot(PTE_DEVMAP)));
+}
#define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd))
#define __phys_to_pmd_val(phys) __phys_to_pte_val(phys)
@@ -448,8 +452,8 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
PMD_TYPE_SECT)
#if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3
-#define pud_sect(pud) (0)
-#define pud_table(pud) (1)
+static inline bool pud_sect(pud_t pud) { return false; }
+static inline bool pud_table(pud_t pud) { return true; }
#else
#define pud_sect(pud) ((pud_val(pud) & PUD_TYPE_MASK) == \
PUD_TYPE_SECT)
@@ -482,8 +486,10 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
WRITE_ONCE(*pmdp, pmd);
- if (pmd_valid(pmd))
+ if (pmd_valid(pmd)) {
dsb(ishst);
+ isb();
+ }
}
static inline void pmd_clear(pmd_t *pmdp)
@@ -541,8 +547,10 @@ static inline void set_pud(pud_t *pudp, pud_t pud)
WRITE_ONCE(*pudp, pud);
- if (pud_valid(pud))
+ if (pud_valid(pud)) {
dsb(ishst);
+ isb();
+ }
}
static inline void pud_clear(pud_t *pudp)
@@ -600,6 +608,7 @@ static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
WRITE_ONCE(*pgdp, pgd);
dsb(ishst);
+ isb();
}
static inline void pgd_clear(pgd_t *pgdp)
@@ -857,8 +866,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
-#define kc_vaddr_to_offset(v) ((v) & ~VA_START)
-#define kc_offset_to_vaddr(o) ((o) | VA_START)
+#define kc_vaddr_to_offset(v) ((v) & ~PAGE_END)
+#define kc_offset_to_vaddr(o) ((o) | PAGE_END)
#ifdef CONFIG_ARM64_PA_BITS_52
#define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h
index d328540cb85e..7a24bad1a58b 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -69,7 +69,7 @@ extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
* The EL0 pointer bits used by a pointer authentication code.
* This is dependent on TBI0 being enabled, or bits 63:56 would also apply.
*/
-#define ptrauth_user_pac_mask() GENMASK(54, vabits_user)
+#define ptrauth_user_pac_mask() GENMASK(54, vabits_actual)
/* Only valid for EL0 TTBR0 instruction pointers */
static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h
index 368d90a9d0e5..a2ce65a0c1fa 100644
--- a/arch/arm64/include/asm/proc-fns.h
+++ b/arch/arm64/include/asm/proc-fns.h
@@ -9,7 +9,6 @@
#ifndef __ASM_PROCFNS_H
#define __ASM_PROCFNS_H
-#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <asm/page.h>
@@ -25,5 +24,4 @@ extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr);
#include <asm/memory.h>
#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
#endif /* __ASM_PROCFNS_H */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index fd5b1a4efc70..c67848c55009 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -20,7 +20,6 @@
#define NET_IP_ALIGN 0
#ifndef __ASSEMBLY__
-#ifdef __KERNEL__
#include <linux/build_bug.h>
#include <linux/cache.h>
@@ -42,8 +41,8 @@
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
*/
-#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS)
-#define TASK_SIZE_64 (UL(1) << vabits_user)
+#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS_MIN)
+#define TASK_SIZE_64 (UL(1) << vabits_actual)
#ifdef CONFIG_COMPAT
#if defined(CONFIG_ARM64_64K_PAGES) && defined(CONFIG_KUSER_HELPERS)
@@ -193,6 +192,16 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
regs->pmr_save = GIC_PRIO_IRQON;
}
+static inline void set_ssbs_bit(struct pt_regs *regs)
+{
+ regs->pstate |= PSR_SSBS_BIT;
+}
+
+static inline void set_compat_ssbs_bit(struct pt_regs *regs)
+{
+ regs->pstate |= PSR_AA32_SSBS_BIT;
+}
+
static inline void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
@@ -200,7 +209,7 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
regs->pstate = PSR_MODE_EL0t;
if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
- regs->pstate |= PSR_SSBS_BIT;
+ set_ssbs_bit(regs);
regs->sp = sp;
}
@@ -219,7 +228,7 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
#endif
if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
- regs->pstate |= PSR_AA32_SSBS_BIT;
+ set_compat_ssbs_bit(regs);
regs->compat_sp = sp;
}
@@ -273,8 +282,6 @@ static inline void spin_lock_prefetch(const void *ptr)
#define HAVE_ARCH_PICK_MMAP_LAYOUT
-#endif
-
extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */
extern void __init minsigstksz_setup(void);
@@ -296,6 +303,14 @@ extern void __init minsigstksz_setup(void);
/* PR_PAC_RESET_KEYS prctl */
#define PAC_RESET_KEYS(tsk, arg) ptrauth_prctl_reset_keys(tsk, arg)
+#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
+/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */
+long set_tagged_addr_ctrl(unsigned long arg);
+long get_tagged_addr_ctrl(void);
+#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(arg)
+#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl()
+#endif
+
/*
* For CONFIG_GCC_PLUGIN_STACKLEAK
*
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index b1dd039023ef..fbebb411ae20 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -30,7 +30,7 @@
* in the the priority mask, it indicates that PSR.I should be set and
* interrupt disabling temporarily does not rely on IRQ priorities.
*/
-#define GIC_PRIO_IRQON 0xc0
+#define GIC_PRIO_IRQON 0xe0
#define GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80)
#define GIC_PRIO_PSR_I_SET (1 << 4)
@@ -301,6 +301,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->regs[0];
}
+static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
+{
+ regs->regs[0] = rc;
+}
+
/**
* regs_get_kernel_argument() - get Nth function argument in kernel
* @regs: pt_regs of that context
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index bd43d1cf724b..7e9f163d02ec 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -5,7 +5,6 @@
#ifndef __ASM_SIGNAL32_H
#define __ASM_SIGNAL32_H
-#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
@@ -79,5 +78,4 @@ static inline void compat_setup_restart_syscall(struct pt_regs *regs)
{
}
#endif /* CONFIG_COMPAT */
-#endif /* __KERNEL__ */
#endif /* __ASM_SIGNAL32_H */
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index df45af931459..4d9b1f48dc39 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -8,19 +8,12 @@
#include <linux/percpu.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
+#include <linux/types.h>
#include <asm/memory.h>
#include <asm/ptrace.h>
#include <asm/sdei.h>
-struct stackframe {
- unsigned long fp;
- unsigned long pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- int graph;
-#endif
-};
-
enum stack_type {
STACK_TYPE_UNKNOWN,
STACK_TYPE_TASK,
@@ -28,6 +21,7 @@ enum stack_type {
STACK_TYPE_OVERFLOW,
STACK_TYPE_SDEI_NORMAL,
STACK_TYPE_SDEI_CRITICAL,
+ __NR_STACK_TYPES
};
struct stack_info {
@@ -36,6 +30,37 @@ struct stack_info {
enum stack_type type;
};
+/*
+ * A snapshot of a frame record or fp/lr register values, along with some
+ * accounting information necessary for robust unwinding.
+ *
+ * @fp: The fp value in the frame record (or the real fp)
+ * @pc: The fp value in the frame record (or the real lr)
+ *
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
+ * longer valid to unwind to.
+ *
+ * @prev_fp: The fp that pointed to this frame record, or a synthetic value
+ * of 0. This is used to ensure that within a stack, each
+ * subsequent frame record is at an increasing address.
+ * @prev_type: The type of stack this frame record was on, or a synthetic
+ * value of STACK_TYPE_UNKNOWN. This is used to detect a
+ * transition from one stack to another.
+ *
+ * @graph: When FUNCTION_GRAPH_TRACER is selected, holds the index of a
+ * replacement lr value in the ftrace graph stack.
+ */
+struct stackframe {
+ unsigned long fp;
+ unsigned long pc;
+ DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
+ unsigned long prev_fp;
+ enum stack_type prev_type;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ int graph;
+#endif
+};
+
extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
int (*fn)(struct stackframe *, void *), void *data);
@@ -64,8 +89,9 @@ static inline bool on_irq_stack(unsigned long sp,
return true;
}
-static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp,
- struct stack_info *info)
+static inline bool on_task_stack(const struct task_struct *tsk,
+ unsigned long sp,
+ struct stack_info *info)
{
unsigned long low = (unsigned long)task_stack_page(tsk);
unsigned long high = low + THREAD_SIZE;
@@ -112,10 +138,13 @@ static inline bool on_overflow_stack(unsigned long sp,
* We can only safely access per-cpu stacks from current in a non-preemptible
* context.
*/
-static inline bool on_accessible_stack(struct task_struct *tsk,
- unsigned long sp,
- struct stack_info *info)
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+ unsigned long sp,
+ struct stack_info *info)
{
+ if (info)
+ info->type = STACK_TYPE_UNKNOWN;
+
if (on_task_stack(tsk, sp, info))
return true;
if (tsk != current || preemptible())
@@ -130,4 +159,27 @@ static inline bool on_accessible_stack(struct task_struct *tsk,
return false;
}
+static inline void start_backtrace(struct stackframe *frame,
+ unsigned long fp, unsigned long pc)
+{
+ frame->fp = fp;
+ frame->pc = pc;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ frame->graph = 0;
+#endif
+
+ /*
+ * Prime the first unwind.
+ *
+ * In unwind_frame() we'll check that the FP points to a valid stack,
+ * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
+ * treated as a transition to whichever stack that happens to be. The
+ * prev_fp value won't be used, but we set it to 0 such that it is
+ * definitely not an accessible stack address.
+ */
+ bitmap_zero(frame->stacks_done, __NR_STACK_TYPES);
+ frame->prev_fp = 0;
+ frame->prev_type = STACK_TYPE_UNKNOWN;
+}
+
#endif /* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 06ebcfef73df..972d196c7714 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -212,6 +212,9 @@
#define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0)
#define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0)
+#define SYS_PAR_EL1_F BIT(1)
+#define SYS_PAR_EL1_FST GENMASK(6, 1)
+
/*** Statistical Profiling Extension ***/
/* ID registers */
#define SYS_PMSIDR_EL1 sys_reg(3, 0, 9, 9, 7)
@@ -499,28 +502,11 @@
#define SCTLR_EL2_RES1 ((BIT(4)) | (BIT(5)) | (BIT(11)) | (BIT(16)) | \
(BIT(18)) | (BIT(22)) | (BIT(23)) | (BIT(28)) | \
(BIT(29)))
-#define SCTLR_EL2_RES0 ((BIT(6)) | (BIT(7)) | (BIT(8)) | (BIT(9)) | \
- (BIT(10)) | (BIT(13)) | (BIT(14)) | (BIT(15)) | \
- (BIT(17)) | (BIT(20)) | (BIT(24)) | (BIT(26)) | \
- (BIT(27)) | (BIT(30)) | (BIT(31)) | \
- (0xffffefffUL << 32))
#ifdef CONFIG_CPU_BIG_ENDIAN
#define ENDIAN_SET_EL2 SCTLR_ELx_EE
-#define ENDIAN_CLEAR_EL2 0
#else
#define ENDIAN_SET_EL2 0
-#define ENDIAN_CLEAR_EL2 SCTLR_ELx_EE
-#endif
-
-/* SCTLR_EL2 value used for the hyp-stub */
-#define SCTLR_EL2_SET (SCTLR_ELx_IESB | ENDIAN_SET_EL2 | SCTLR_EL2_RES1)
-#define SCTLR_EL2_CLEAR (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
- SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_WXN | \
- SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0)
-
-#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffffUL
-#error "Inconsistent SCTLR_EL2 set/clear bits"
#endif
/* SCTLR_EL1 specific flags. */
@@ -539,16 +525,11 @@
#define SCTLR_EL1_RES1 ((BIT(11)) | (BIT(20)) | (BIT(22)) | (BIT(28)) | \
(BIT(29)))
-#define SCTLR_EL1_RES0 ((BIT(6)) | (BIT(10)) | (BIT(13)) | (BIT(17)) | \
- (BIT(27)) | (BIT(30)) | (BIT(31)) | \
- (0xffffefffUL << 32))
#ifdef CONFIG_CPU_BIG_ENDIAN
#define ENDIAN_SET_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE)
-#define ENDIAN_CLEAR_EL1 0
#else
#define ENDIAN_SET_EL1 0
-#define ENDIAN_CLEAR_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE)
#endif
#define SCTLR_EL1_SET (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA |\
@@ -556,13 +537,6 @@
SCTLR_EL1_DZE | SCTLR_EL1_UCT |\
SCTLR_EL1_NTWE | SCTLR_ELx_IESB | SCTLR_EL1_SPAN |\
ENDIAN_SET_EL1 | SCTLR_EL1_UCI | SCTLR_EL1_RES1)
-#define SCTLR_EL1_CLEAR (SCTLR_ELx_A | SCTLR_EL1_CP15BEN | SCTLR_EL1_ITD |\
- SCTLR_EL1_UMA | SCTLR_ELx_WXN | ENDIAN_CLEAR_EL1 |\
- SCTLR_ELx_DSSBS | SCTLR_EL1_NTWI | SCTLR_EL1_RES0)
-
-#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffffUL
-#error "Inconsistent SCTLR_EL1 set/clear bits"
-#endif
/* id_aa64isar0 */
#define ID_AA64ISAR0_TS_SHIFT 52
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 180b34ec5965..f0cec4160136 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -8,8 +8,6 @@
#ifndef __ASM_THREAD_INFO_H
#define __ASM_THREAD_INFO_H
-#ifdef __KERNEL__
-
#include <linux/compiler.h>
#ifndef __ASSEMBLY__
@@ -59,29 +57,18 @@ void arch_release_task_struct(struct task_struct *tsk);
#endif
-/*
- * thread information flags:
- * TIF_SYSCALL_TRACE - syscall trace active
- * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace
- * TIF_SYSCALL_AUDIT - syscall auditing
- * TIF_SECCOMP - syscall secure computing
- * TIF_SYSCALL_EMU - syscall emulation active
- * TIF_SIGPENDING - signal pending
- * TIF_NEED_RESCHED - rescheduling necessary
- * TIF_NOTIFY_RESUME - callback before returning to user
- */
-#define TIF_SIGPENDING 0
-#define TIF_NEED_RESCHED 1
+#define TIF_SIGPENDING 0 /* signal pending */
+#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
#define TIF_FSCHECK 5 /* Check FS is USER_DS on return */
#define TIF_NOHZ 7
-#define TIF_SYSCALL_TRACE 8
-#define TIF_SYSCALL_AUDIT 9
-#define TIF_SYSCALL_TRACEPOINT 10
-#define TIF_SECCOMP 11
-#define TIF_SYSCALL_EMU 12
+#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
+#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
+#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
+#define TIF_SECCOMP 11 /* syscall secure computing */
+#define TIF_SYSCALL_EMU 12 /* syscall emulation active */
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_FREEZE 19
#define TIF_RESTORE_SIGMASK 20
@@ -90,6 +77,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define TIF_SVE 23 /* Scalable Vector Extension in use */
#define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */
#define TIF_SSBD 25 /* Wants SSB mitigation */
+#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
@@ -121,5 +109,4 @@ void arch_release_task_struct(struct task_struct *tsk);
.addr_limit = KERNEL_DS, \
}
-#endif /* __KERNEL__ */
#endif /* __ASM_THREAD_INFO_H */
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 8af7a85f76bd..bc3949064725 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -251,6 +251,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
dsb(ish);
+ isb();
}
#endif
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
index 0524f2438649..a4d945db95a2 100644
--- a/arch/arm64/include/asm/topology.h
+++ b/arch/arm64/include/asm/topology.h
@@ -4,29 +4,6 @@
#include <linux/cpumask.h>
-struct cpu_topology {
- int thread_id;
- int core_id;
- int package_id;
- int llc_id;
- cpumask_t thread_sibling;
- cpumask_t core_sibling;
- cpumask_t llc_sibling;
-};
-
-extern struct cpu_topology cpu_topology[NR_CPUS];
-
-#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id)
-#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
-#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
-#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
-#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling)
-
-void init_cpu_topology(void);
-void store_cpu_topology(unsigned int cpuid);
-void remove_cpu_topology(unsigned int cpuid);
-const struct cpumask *cpu_coregroup_mask(int cpu);
-
#ifdef CONFIG_NUMA
struct pci_bus;
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 5a1c32260c1f..097d6bfac0b7 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -62,6 +62,10 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si
{
unsigned long ret, limit = current_thread_info()->addr_limit;
+ if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) &&
+ test_thread_flag(TIF_TAGGED_ADDR))
+ addr = untagged_addr(addr);
+
__chk_user_ptr(addr);
asm volatile(
// A + B <= C + 1 for all A,B,C, in four easy steps:
@@ -215,7 +219,8 @@ static inline void uaccess_enable_not_uao(void)
/*
* Sanitise a uaccess pointer such that it becomes NULL if above the
- * current addr_limit.
+ * current addr_limit. In case the pointer is tagged (has the top byte set),
+ * untag the pointer before checking.
*/
#define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr)
static inline void __user *__uaccess_mask_ptr(const void __user *ptr)
@@ -223,10 +228,11 @@ static inline void __user *__uaccess_mask_ptr(const void __user *ptr)
void __user *safe_ptr;
asm volatile(
- " bics xzr, %1, %2\n"
+ " bics xzr, %3, %2\n"
" csel %0, %1, xzr, eq\n"
: "=&r" (safe_ptr)
- : "r" (ptr), "r" (current_thread_info()->addr_limit)
+ : "r" (ptr), "r" (current_thread_info()->addr_limit),
+ "r" (untagged_addr(ptr))
: "cc");
csdb();
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 9c15e0a06301..07468428fd29 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -5,8 +5,6 @@
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
-#ifdef __KERNEL__
-
/*
* Default link address for the vDSO.
* Since we randomise the VDSO mapping, there's little point in trying
@@ -28,6 +26,4 @@
#endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
#endif /* __ASM_VDSO_H */
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index f4812777f5c5..c50ee1b7d5cd 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -16,6 +16,8 @@
#define VDSO_HAS_CLOCK_GETRES 1
+#define VDSO_HAS_32BIT_FALLBACK 1
+
static __always_inline
int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
struct timezone *_tz)
@@ -52,6 +54,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
}
static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+ register struct old_timespec32 *ts asm("r1") = _ts;
+ register clockid_t clkid asm("r0") = _clkid;
+ register long ret asm ("r0");
+ register long nr asm("r7") = __NR_compat_clock_gettime;
+
+ asm volatile(
+ " swi #0\n"
+ : "=r" (ret)
+ : "r" (clkid), "r" (ts), "r" (nr)
+ : "memory");
+
+ return ret;
+}
+
+static __always_inline
int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
register struct __kernel_timespec *ts asm("r1") = _ts;
@@ -72,6 +91,27 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
return ret;
}
+static __always_inline
+int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+ register struct old_timespec32 *ts asm("r1") = _ts;
+ register clockid_t clkid asm("r0") = _clkid;
+ register long ret asm ("r0");
+ register long nr asm("r7") = __NR_compat_clock_getres;
+
+ /* The checks below are required for ABI consistency with arm */
+ if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
+ return -EINVAL;
+
+ asm volatile(
+ " swi #0\n"
+ : "=r" (ret)
+ : "r" (clkid), "r" (ts), "r" (nr)
+ : "memory");
+
+ return ret;
+}
+
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
{
u64 res;
diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
index ba6dbc3de864..1f38bf330a6e 100644
--- a/arch/arm64/include/asm/vdso_datapage.h
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -5,8 +5,6 @@
#ifndef __ASM_VDSO_DATAPAGE_H
#define __ASM_VDSO_DATAPAGE_H
-#ifdef __KERNEL__
-
#ifndef __ASSEMBLY__
struct vdso_data {
@@ -32,6 +30,4 @@ struct vdso_data {
#endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
#endif /* __ASM_VDSO_DATAPAGE_H */
diff --git a/arch/arm64/include/uapi/asm/bpf_perf_event.h b/arch/arm64/include/uapi/asm/bpf_perf_event.h
index b551b741653d..5e1e648aeec4 100644
--- a/arch/arm64/include/uapi/asm/bpf_perf_event.h
+++ b/arch/arm64/include/uapi/asm/bpf_perf_event.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
#define _UAPI__ASM_BPF_PERF_EVENT_H__
diff --git a/arch/arm64/include/uapi/asm/stat.h b/arch/arm64/include/uapi/asm/stat.h
deleted file mode 100644
index 313325fa22fa..000000000000
--- a/arch/arm64/include/uapi/asm/stat.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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. 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, see <http://www.gnu.org/licenses/>.
- */
-#include <asm-generic/stat.h>
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f29f36a65175..9323bcc40a58 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -184,9 +184,17 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+ /*
+ * We already refuse to boot CPUs that don't support our configured
+ * page size, so we can only detect mismatches for a page size other
+ * than the one we're currently using. Unfortunately, SoCs like this
+ * exist in the wild so, even though we don't like it, we'll have to go
+ * along with it and treat them as non-strict.
+ */
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
/* Linux shouldn't care about secure memory */
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
@@ -225,8 +233,8 @@ static const struct arm64_ftr_bits ftr_ctr[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 1, 1),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IDC_SHIFT, 1, 1),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_CWG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_ERG_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_CWG_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_ERG_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DMINLINE_SHIFT, 4, 1),
/*
* Linux can handle differing I-cache policies. Userspace JITs will
@@ -468,6 +476,10 @@ static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new,
case FTR_LOWER_SAFE:
ret = new < cur ? new : cur;
break;
+ case FTR_HIGHER_OR_ZERO_SAFE:
+ if (!cur || !new)
+ break;
+ /* Fallthrough */
case FTR_HIGHER_SAFE:
ret = new > cur ? new : cur;
break;
@@ -882,7 +894,7 @@ static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int _
u32 midr = read_cpuid_id();
/* Cavium ThunderX pass 1.x and 2.x */
- return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX,
+ return midr_is_cpu_model_range(midr, MIDR_THUNDERX,
MIDR_CPU_VAR_REV(0, 0),
MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK));
}
diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
index d1048173fd8a..e4d6af2fdec7 100644
--- a/arch/arm64/kernel/cpuidle.c
+++ b/arch/arm64/kernel/cpuidle.c
@@ -11,6 +11,7 @@
#include <linux/cpu_pm.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/psci.h>
#include <asm/cpuidle.h>
#include <asm/cpu_ops.h>
@@ -46,17 +47,58 @@ int arm_cpuidle_suspend(int index)
#define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags))
+static int psci_acpi_cpu_init_idle(unsigned int cpu)
+{
+ int i, count;
+ struct acpi_lpi_state *lpi;
+ struct acpi_processor *pr = per_cpu(processors, cpu);
+
+ /*
+ * If the PSCI cpu_suspend function hook has not been initialized
+ * idle states must not be enabled, so bail out
+ */
+ if (!psci_ops.cpu_suspend)
+ return -EOPNOTSUPP;
+
+ if (unlikely(!pr || !pr->flags.has_lpi))
+ return -EINVAL;
+
+ count = pr->power.count - 1;
+ if (count <= 0)
+ return -ENODEV;
+
+ for (i = 0; i < count; i++) {
+ u32 state;
+
+ lpi = &pr->power.lpi_states[i + 1];
+ /*
+ * Only bits[31:0] represent a PSCI power_state while
+ * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
+ */
+ state = lpi->address;
+ if (!psci_power_state_is_valid(state)) {
+ pr_warn("Invalid PSCI power state %#x\n", state);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
int acpi_processor_ffh_lpi_probe(unsigned int cpu)
{
- return arm_cpuidle_init(cpu);
+ return psci_acpi_cpu_init_idle(cpu);
}
int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
{
+ u32 state = lpi->address;
+
if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags))
- return CPU_PM_CPU_IDLE_ENTER_RETENTION(arm_cpuidle_suspend,
- lpi->index);
+ return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(psci_cpu_suspend_enter,
+ lpi->index, state);
else
- return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, lpi->index);
+ return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
+ lpi->index, state);
}
#endif
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 876055e37352..05933c065732 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -33,7 +33,7 @@
DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
static struct cpuinfo_arm64 boot_cpu_data;
-static char *icache_policy_str[] = {
+static const char *icache_policy_str[] = {
[0 ... ICACHE_POLICY_PIPT] = "RESERVED/UNKNOWN",
[ICACHE_POLICY_VIPT] = "VIPT",
[ICACHE_POLICY_PIPT] = "PIPT",
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index f8719bd30850..48222a4760c2 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -207,16 +207,16 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr)
list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
- rcu_read_lock();
-
+ /*
+ * Since single-step exception disables interrupt, this function is
+ * entirely not preemptible, and we can use rcu list safely here.
+ */
list_for_each_entry_rcu(hook, list, node) {
retval = hook->fn(regs, esr);
if (retval == DBG_HOOK_HANDLED)
break;
}
- rcu_read_unlock();
-
return retval;
}
NOKPROBE_SYMBOL(call_step_hook);
@@ -305,14 +305,16 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr)
list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
- rcu_read_lock();
+ /*
+ * Since brk exception disables interrupt, this function is
+ * entirely not preemptible, and we can use rcu list safely here.
+ */
list_for_each_entry_rcu(hook, list, node) {
unsigned int comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
if ((comment & ~hook->mask) == hook->imm)
fn = hook->fn;
}
- rcu_read_unlock();
return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
}
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 9cdc4592da3e..84a822748c84 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -30,9 +30,9 @@
* Context tracking subsystem. Used to instrument transitions
* between user and kernel mode.
*/
- .macro ct_user_exit
+ .macro ct_user_exit_irqoff
#ifdef CONFIG_CONTEXT_TRACKING
- bl context_tracking_user_exit
+ bl enter_from_user_mode
#endif
.endm
@@ -586,10 +586,8 @@ el1_sync:
b.eq el1_ia
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el1_undef
- cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
- b.eq el1_sp_pc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
- b.eq el1_sp_pc
+ b.eq el1_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1
b.eq el1_undef
cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
@@ -611,9 +609,11 @@ el1_da:
bl do_mem_abort
kernel_exit 1
-el1_sp_pc:
+el1_pc:
/*
- * Stack or PC alignment exception handling
+ * PC alignment exception handling. We don't handle SP alignment faults,
+ * since we will have hit a recursive exception when trying to push the
+ * initial pt_regs.
*/
mrs x0, far_el1
inherit_daif pstate=x23, tmp=x2
@@ -732,9 +732,9 @@ el0_sync:
ccmp x24, #ESR_ELx_EC_WFx, #4, ne
b.eq el0_sys
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
- b.eq el0_sp_pc
+ b.eq el0_sp
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
- b.eq el0_sp_pc
+ b.eq el0_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
@@ -758,7 +758,7 @@ el0_sync_compat:
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
- b.eq el0_sp_pc
+ b.eq el0_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
@@ -792,8 +792,8 @@ el0_cp15:
/*
* Trapped CP15 (MRC, MCR, MRRC, MCRR) instructions
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, x25
mov x1, sp
bl do_cp15instr
@@ -805,8 +805,8 @@ el0_da:
* Data abort handling
*/
mrs x26, far_el1
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
clear_address_tag x0, x26
mov x1, x25
mov x2, sp
@@ -818,11 +818,11 @@ el0_ia:
*/
mrs x26, far_el1
gic_prio_kentry_setup tmp=x0
+ ct_user_exit_irqoff
enable_da_f
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
- ct_user_exit
mov x0, x26
mov x1, x25
mov x2, sp
@@ -832,8 +832,8 @@ el0_fpsimd_acc:
/*
* Floating Point or Advanced SIMD access
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, x25
mov x1, sp
bl do_fpsimd_acc
@@ -842,8 +842,8 @@ el0_sve_acc:
/*
* Scalable Vector Extension access
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, x25
mov x1, sp
bl do_sve_acc
@@ -852,23 +852,27 @@ el0_fpsimd_exc:
/*
* Floating Point, Advanced SIMD or SVE exception
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, x25
mov x1, sp
bl do_fpsimd_exc
b ret_to_user
+el0_sp:
+ ldr x26, [sp, #S_SP]
+ b el0_sp_pc
+el0_pc:
+ mrs x26, far_el1
el0_sp_pc:
/*
* Stack or PC alignment exception handling
*/
- mrs x26, far_el1
gic_prio_kentry_setup tmp=x0
+ ct_user_exit_irqoff
enable_da_f
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
- ct_user_exit
mov x0, x26
mov x1, x25
mov x2, sp
@@ -878,8 +882,8 @@ el0_undef:
/*
* Undefined instruction
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, sp
bl do_undefinstr
b ret_to_user
@@ -887,8 +891,8 @@ el0_sys:
/*
* System instructions, for trapped cache maintenance instructions
*/
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, x25
mov x1, sp
bl do_sysinstr
@@ -898,17 +902,18 @@ el0_dbg:
* Debug exception handling
*/
tbnz x24, #0, el0_inv // EL0 only
+ mrs x24, far_el1
gic_prio_kentry_setup tmp=x3
- mrs x0, far_el1
+ ct_user_exit_irqoff
+ mov x0, x24
mov x1, x25
mov x2, sp
bl do_debug_exception
enable_da_f
- ct_user_exit
b ret_to_user
el0_inv:
+ ct_user_exit_irqoff
enable_daif
- ct_user_exit
mov x0, sp
mov x1, #BAD_SYNC
mov x2, x25
@@ -921,13 +926,13 @@ el0_irq:
kernel_entry 0
el0_irq_naked:
gic_prio_irq_setup pmr=x20, tmp=x0
+ ct_user_exit_irqoff
enable_da_f
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
- ct_user_exit
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
tbz x22, #55, 1f
bl do_el0_irq_bp_hardening
@@ -954,13 +959,14 @@ ENDPROC(el1_error)
el0_error:
kernel_entry 0
el0_error_naked:
- mrs x1, esr_el1
+ mrs x25, esr_el1
gic_prio_kentry_setup tmp=x2
+ ct_user_exit_irqoff
enable_dbg
mov x0, sp
+ mov x1, x25
bl do_serror
enable_da_f
- ct_user_exit
b ret_to_user
ENDPROC(el0_error)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index eec4776ae5f0..37d3912cfe06 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -406,6 +406,18 @@ static __uint128_t arm64_cpu_to_le128(__uint128_t x)
#define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)
+static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
+ unsigned int vq)
+{
+ unsigned int i;
+ __uint128_t *p;
+
+ for (i = 0; i < SVE_NUM_ZREGS; ++i) {
+ p = (__uint128_t *)ZREG(sst, vq, i);
+ *p = arm64_cpu_to_le128(fst->vregs[i]);
+ }
+}
+
/*
* Transfer the FPSIMD state in task->thread.uw.fpsimd_state to
* task->thread.sve_state.
@@ -423,17 +435,12 @@ static void fpsimd_to_sve(struct task_struct *task)
unsigned int vq;
void *sst = task->thread.sve_state;
struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
- unsigned int i;
- __uint128_t *p;
if (!system_supports_sve())
return;
vq = sve_vq_from_vl(task->thread.sve_vl);
- for (i = 0; i < 32; ++i) {
- p = (__uint128_t *)ZREG(sst, vq, i);
- *p = arm64_cpu_to_le128(fst->vregs[i]);
- }
+ __fpsimd_to_sve(sst, fst, vq);
}
/*
@@ -459,7 +466,7 @@ static void sve_to_fpsimd(struct task_struct *task)
return;
vq = sve_vq_from_vl(task->thread.sve_vl);
- for (i = 0; i < 32; ++i) {
+ for (i = 0; i < SVE_NUM_ZREGS; ++i) {
p = (__uint128_t const *)ZREG(sst, vq, i);
fst->vregs[i] = arm64_le128_to_cpu(*p);
}
@@ -550,8 +557,6 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
unsigned int vq;
void *sst = task->thread.sve_state;
struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
- unsigned int i;
- __uint128_t *p;
if (!test_tsk_thread_flag(task, TIF_SVE))
return;
@@ -559,11 +564,7 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
vq = sve_vq_from_vl(task->thread.sve_vl);
memset(sst, 0, SVE_SIG_REGS_SIZE(vq));
-
- for (i = 0; i < 32; ++i) {
- p = (__uint128_t *)ZREG(sst, vq, i);
- *p = arm64_cpu_to_le128(fst->vregs[i]);
- }
+ __fpsimd_to_sve(sst, fst, vq);
}
int sve_set_vector_length(struct task_struct *task,
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index 1285c7b2947f..171773257974 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -73,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
if (offset < -SZ_128M || offset >= SZ_128M) {
#ifdef CONFIG_ARM64_MODULE_PLTS
- struct plt_entry trampoline;
+ struct plt_entry trampoline, *dst;
struct module *mod;
/*
@@ -106,23 +106,27 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
* to check if the actual opcodes are in fact identical,
* regardless of the offset in memory so use memcmp() instead.
*/
- trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
- if (memcmp(mod->arch.ftrace_trampoline, &trampoline,
- sizeof(trampoline))) {
- if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
+ dst = mod->arch.ftrace_trampoline;
+ trampoline = get_plt_entry(addr, dst);
+ if (memcmp(dst, &trampoline, sizeof(trampoline))) {
+ if (plt_entry_is_initialized(dst)) {
pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
return -EINVAL;
}
/* point the trampoline to our ftrace entry point */
module_disable_ro(mod);
- *mod->arch.ftrace_trampoline = trampoline;
+ *dst = trampoline;
module_enable_ro(mod, true);
- /* update trampoline before patching in the branch */
- smp_wmb();
+ /*
+ * Ensure updated trampoline is visible to instruction
+ * fetch before we patch in the branch.
+ */
+ __flush_icache_range((unsigned long)&dst[0],
+ (unsigned long)&dst[1]);
}
- addr = (unsigned long)(void *)mod->arch.ftrace_trampoline;
+ addr = (unsigned long)dst;
#else /* CONFIG_ARM64_MODULE_PLTS */
return -EINVAL;
#endif /* CONFIG_ARM64_MODULE_PLTS */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2cdacd1c141b..989b1944cb71 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -102,6 +102,8 @@ pe_header:
* x23 stext() .. start_kernel() physical misalignment/KASLR offset
* x28 __create_page_tables() callee preserved temp register
* x19/x20 __primary_switch() callee preserved temp registers
+ * x24 __primary_switch() .. relocate_kernel()
+ * current RELR displacement
*/
ENTRY(stext)
bl preserve_boot_args
@@ -308,15 +310,15 @@ __create_page_tables:
adrp x0, idmap_pg_dir
adrp x3, __idmap_text_start // __pa(__idmap_text_start)
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+#ifdef CONFIG_ARM64_VA_BITS_52
mrs_s x6, SYS_ID_AA64MMFR2_EL1
and x6, x6, #(0xf << ID_AA64MMFR2_LVA_SHIFT)
mov x5, #52
cbnz x6, 1f
#endif
- mov x5, #VA_BITS
+ mov x5, #VA_BITS_MIN
1:
- adr_l x6, vabits_user
+ adr_l x6, vabits_actual
str x5, [x6]
dmb sy
dc ivac, x6 // Invalidate potentially stale cache line
@@ -724,14 +726,22 @@ __secondary_switched:
adr_l x0, secondary_data
ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack
+ cbz x1, __secondary_too_slow
mov sp, x1
ldr x2, [x0, #CPU_BOOT_TASK]
+ cbz x2, __secondary_too_slow
msr sp_el0, x2
mov x29, #0
mov x30, #0
b secondary_start_kernel
ENDPROC(__secondary_switched)
+__secondary_too_slow:
+ wfe
+ wfi
+ b __secondary_too_slow
+ENDPROC(__secondary_too_slow)
+
/*
* The booting CPU updates the failed status @__early_cpu_boot_status,
* with MMU turned off.
@@ -772,7 +782,7 @@ ENTRY(__enable_mmu)
phys_to_ttbr x1, x1
phys_to_ttbr x2, x2
msr ttbr0_el1, x2 // load TTBR0
- offset_ttbr1 x1
+ offset_ttbr1 x1, x3
msr ttbr1_el1, x1 // load TTBR1
isb
msr sctlr_el1, x0
@@ -789,8 +799,8 @@ ENTRY(__enable_mmu)
ENDPROC(__enable_mmu)
ENTRY(__cpu_secondary_check52bitva)
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
- ldr_l x0, vabits_user
+#ifdef CONFIG_ARM64_VA_BITS_52
+ ldr_l x0, vabits_actual
cmp x0, #52
b.ne 2f
@@ -834,14 +844,93 @@ __relocate_kernel:
0: cmp x9, x10
b.hs 1f
- ldp x11, x12, [x9], #24
- ldr x13, [x9, #-8]
- cmp w12, #R_AARCH64_RELATIVE
+ ldp x12, x13, [x9], #24
+ ldr x14, [x9, #-8]
+ cmp w13, #R_AARCH64_RELATIVE
b.ne 0b
- add x13, x13, x23 // relocate
- str x13, [x11, x23]
+ add x14, x14, x23 // relocate
+ str x14, [x12, x23]
b 0b
-1: ret
+
+1:
+#ifdef CONFIG_RELR
+ /*
+ * Apply RELR relocations.
+ *
+ * RELR is a compressed format for storing relative relocations. The
+ * encoded sequence of entries looks like:
+ * [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ]
+ *
+ * i.e. start with an address, followed by any number of bitmaps. The
+ * address entry encodes 1 relocation. The subsequent bitmap entries
+ * encode up to 63 relocations each, at subsequent offsets following
+ * the last address entry.
+ *
+ * The bitmap entries must have 1 in the least significant bit. The
+ * assumption here is that an address cannot have 1 in lsb. Odd
+ * addresses are not supported. Any odd addresses are stored in the RELA
+ * section, which is handled above.
+ *
+ * Excluding the least significant bit in the bitmap, each non-zero
+ * bit in the bitmap represents a relocation to be applied to
+ * a corresponding machine word that follows the base address
+ * word. The second least significant bit represents the machine
+ * word immediately following the initial address, and each bit
+ * that follows represents the next word, in linear order. As such,
+ * a single bitmap can encode up to 63 relocations in a 64-bit object.
+ *
+ * In this implementation we store the address of the next RELR table
+ * entry in x9, the address being relocated by the current address or
+ * bitmap entry in x13 and the address being relocated by the current
+ * bit in x14.
+ *
+ * Because addends are stored in place in the binary, RELR relocations
+ * cannot be applied idempotently. We use x24 to keep track of the
+ * currently applied displacement so that we can correctly relocate if
+ * __relocate_kernel is called twice with non-zero displacements (i.e.
+ * if there is both a physical misalignment and a KASLR displacement).
+ */
+ ldr w9, =__relr_offset // offset to reloc table
+ ldr w10, =__relr_size // size of reloc table
+ add x9, x9, x11 // __va(.relr)
+ add x10, x9, x10 // __va(.relr) + sizeof(.relr)
+
+ sub x15, x23, x24 // delta from previous offset
+ cbz x15, 7f // nothing to do if unchanged
+ mov x24, x23 // save new offset
+
+2: cmp x9, x10
+ b.hs 7f
+ ldr x11, [x9], #8
+ tbnz x11, #0, 3f // branch to handle bitmaps
+ add x13, x11, x23
+ ldr x12, [x13] // relocate address entry
+ add x12, x12, x15
+ str x12, [x13], #8 // adjust to start of bitmap
+ b 2b
+
+3: mov x14, x13
+4: lsr x11, x11, #1
+ cbz x11, 6f
+ tbz x11, #0, 5f // skip bit if not set
+ ldr x12, [x14] // relocate bit
+ add x12, x12, x15
+ str x12, [x14]
+
+5: add x14, x14, #8 // move to next bit's address
+ b 4b
+
+6: /*
+ * Move to the next bitmap's address. 8 is the word size, and 63 is the
+ * number of significant bits in a bitmap entry.
+ */
+ add x13, x13, #(8 * 63)
+ b 2b
+
+7:
+#endif
+ ret
+
ENDPROC(__relocate_kernel)
#endif
@@ -854,6 +943,9 @@ __primary_switch:
adrp x1, init_pg_dir
bl __enable_mmu
#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RELR
+ mov x24, #0 // no RELR displacement yet
+#endif
bl __relocate_kernel
#ifdef CONFIG_RANDOMIZE_BASE
ldr x8, =__primary_switched
diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S
index 2f4a2ce7264b..38bcd4d4e43b 100644
--- a/arch/arm64/kernel/hibernate-asm.S
+++ b/arch/arm64/kernel/hibernate-asm.S
@@ -22,14 +22,14 @@
* Even switching to our copied tables will cause a changed output address at
* each stage of the walk.
*/
-.macro break_before_make_ttbr_switch zero_page, page_table, tmp
+.macro break_before_make_ttbr_switch zero_page, page_table, tmp, tmp2
phys_to_ttbr \tmp, \zero_page
msr ttbr1_el1, \tmp
isb
tlbi vmalle1
dsb nsh
phys_to_ttbr \tmp, \page_table
- offset_ttbr1 \tmp
+ offset_ttbr1 \tmp, \tmp2
msr ttbr1_el1, \tmp
isb
.endm
@@ -70,7 +70,7 @@ ENTRY(swsusp_arch_suspend_exit)
* We execute from ttbr0, change ttbr1 to our copied linear map tables
* with a break-before-make via the zero page
*/
- break_before_make_ttbr_switch x5, x0, x6
+ break_before_make_ttbr_switch x5, x0, x6, x8
mov x21, x1
mov x30, x2
@@ -101,7 +101,7 @@ ENTRY(swsusp_arch_suspend_exit)
dsb ish /* wait for PoU cleaning to finish */
/* switch to the restored kernels page tables */
- break_before_make_ttbr_switch x25, x21, x6
+ break_before_make_ttbr_switch x25, x21, x6, x8
ic ialluis
dsb ish
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 9341fcc6e809..e0a7fce0e01c 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -496,7 +496,7 @@ int swsusp_arch_resume(void)
rc = -ENOMEM;
goto out;
}
- rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
+ rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, PAGE_END);
if (rc)
goto out;
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index dceb84520948..38ee1514cd9c 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -536,13 +536,18 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
/* Aligned */
break;
case 1:
- /* Allow single byte watchpoint. */
- if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
- break;
case 2:
/* Allow halfword watchpoints and breakpoints. */
if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
break;
+
+ /* Fallthrough */
+ case 3:
+ /* Allow single byte watchpoint. */
+ if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
+ break;
+
+ /* Fallthrough */
default:
return -EINVAL;
}
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
new file mode 100644
index 000000000000..25a2a9b479c2
--- /dev/null
+++ b/arch/arm64/kernel/image-vars.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Linker script variables to be set after section resolution, as
+ * ld.lld does not like variables assigned before SECTIONS is processed.
+ */
+#ifndef __ARM64_KERNEL_IMAGE_VARS_H
+#define __ARM64_KERNEL_IMAGE_VARS_H
+
+#ifndef LINKER_SCRIPT
+#error This file should only be included in vmlinux.lds.S
+#endif
+
+#ifdef CONFIG_EFI
+
+__efistub_stext_offset = stext - _text;
+
+/*
+ * The EFI stub has its own symbol namespace prefixed by __efistub_, to
+ * isolate it from the kernel proper. The following symbols are legally
+ * accessed by the stub, so provide some aliases to make them accessible.
+ * Only include data symbols here, or text symbols of functions that are
+ * guaranteed to be safe when executed at another offset than they were
+ * linked at. The routines below are all implemented in assembler in a
+ * position independent manner
+ */
+__efistub_memcmp = __pi_memcmp;
+__efistub_memchr = __pi_memchr;
+__efistub_memcpy = __pi_memcpy;
+__efistub_memmove = __pi_memmove;
+__efistub_memset = __pi_memset;
+__efistub_strlen = __pi_strlen;
+__efistub_strnlen = __pi_strnlen;
+__efistub_strcmp = __pi_strcmp;
+__efistub_strncmp = __pi_strncmp;
+__efistub_strrchr = __pi_strrchr;
+__efistub___flush_dcache_area = __pi___flush_dcache_area;
+
+#ifdef CONFIG_KASAN
+__efistub___memcpy = __pi_memcpy;
+__efistub___memmove = __pi_memmove;
+__efistub___memset = __pi_memset;
+#endif
+
+__efistub__text = _text;
+__efistub__end = _end;
+__efistub__edata = _edata;
+__efistub_screen_info = screen_info;
+
+#endif
+
+#endif /* __ARM64_KERNEL_IMAGE_VARS_H */
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index 2b85c0d6fa3d..c7d38c660372 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -65,46 +65,4 @@
DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \
DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
-#ifdef CONFIG_EFI
-
-/*
- * Use ABSOLUTE() to avoid ld.lld treating this as a relative symbol:
- * https://github.com/ClangBuiltLinux/linux/issues/561
- */
-__efistub_stext_offset = ABSOLUTE(stext - _text);
-
-/*
- * The EFI stub has its own symbol namespace prefixed by __efistub_, to
- * isolate it from the kernel proper. The following symbols are legally
- * accessed by the stub, so provide some aliases to make them accessible.
- * Only include data symbols here, or text symbols of functions that are
- * guaranteed to be safe when executed at another offset than they were
- * linked at. The routines below are all implemented in assembler in a
- * position independent manner
- */
-__efistub_memcmp = __pi_memcmp;
-__efistub_memchr = __pi_memchr;
-__efistub_memcpy = __pi_memcpy;
-__efistub_memmove = __pi_memmove;
-__efistub_memset = __pi_memset;
-__efistub_strlen = __pi_strlen;
-__efistub_strnlen = __pi_strnlen;
-__efistub_strcmp = __pi_strcmp;
-__efistub_strncmp = __pi_strncmp;
-__efistub_strrchr = __pi_strrchr;
-__efistub___flush_dcache_area = __pi___flush_dcache_area;
-
-#ifdef CONFIG_KASAN
-__efistub___memcpy = __pi_memcpy;
-__efistub___memmove = __pi_memmove;
-__efistub___memset = __pi_memset;
-#endif
-
-__efistub__text = _text;
-__efistub__end = _end;
-__efistub__edata = _edata;
-__efistub_screen_info = screen_info;
-
-#endif
-
#endif /* __ARM64_KERNEL_IMAGE_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 84b059ed04fc..d801a7094076 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -26,7 +26,7 @@
#define AARCH64_INSN_N_BIT BIT(22)
#define AARCH64_INSN_LSL_12 BIT(22)
-static int aarch64_insn_encoding_class[] = {
+static const int aarch64_insn_encoding_class[] = {
AARCH64_INSN_CLS_UNKNOWN,
AARCH64_INSN_CLS_UNKNOWN,
AARCH64_INSN_CLS_UNKNOWN,
diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 708051655ad9..416f537bf614 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -62,9 +62,6 @@ out:
return default_cmdline;
}
-extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size,
- pgprot_t prot);
-
/*
* This routine will be executed with the kernel mapped at its default virtual
* address, and if it returns successfully, the kernel will be remapped, and
@@ -93,7 +90,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
* attempt at mapping the FDT in setup_machine()
*/
early_fixmap_init();
- fdt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
+ fdt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
if (!fdt)
return 0;
@@ -116,15 +113,15 @@ u64 __init kaslr_early_init(u64 dt_phys)
/*
* OK, so we are proceeding with KASLR enabled. Calculate a suitable
* kernel image offset from the seed. Let's place the kernel in the
- * middle half of the VMALLOC area (VA_BITS - 2), and stay clear of
+ * middle half of the VMALLOC area (VA_BITS_MIN - 2), and stay clear of
* the lower and upper quarters to avoid colliding with other
* allocations.
* Even if we could randomize at page granularity for 16k and 64k pages,
* let's always round to 2 MB so we don't interfere with the ability to
* map using contiguous PTEs
*/
- mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1);
- offset = BIT(VA_BITS - 3) + (seed & mask);
+ mask = ((1UL << (VA_BITS_MIN - 2)) - 1) & ~(SZ_2M - 1);
+ offset = BIT(VA_BITS_MIN - 3) + (seed & mask);
/* use the top 16 bits to randomize the linear region */
memstart_offset_seed = seed >> 48;
diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index 2514fd6f12cb..29a9428486a5 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -84,7 +84,7 @@ static void *image_load(struct kimage *image,
kbuf.buffer = kernel;
kbuf.bufsz = kernel_len;
- kbuf.mem = 0;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
kbuf.memsz = le64_to_cpu(h->image_size);
text_offset = le64_to_cpu(h->text_offset);
kbuf.buf_align = MIN_KIMG_ALIGN;
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 58871333737a..7b08bf9499b6 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -27,6 +27,8 @@
#define FDT_PROP_INITRD_END "linux,initrd-end"
#define FDT_PROP_BOOTARGS "bootargs"
#define FDT_PROP_KASLR_SEED "kaslr-seed"
+#define FDT_PROP_RNG_SEED "rng-seed"
+#define RNG_SEED_SIZE 128
const struct kexec_file_ops * const kexec_file_loaders[] = {
&kexec_image_ops,
@@ -102,6 +104,19 @@ static int setup_dtb(struct kimage *image,
FDT_PROP_KASLR_SEED);
}
+ /* add rng-seed */
+ if (rng_is_initialized()) {
+ u8 rng_seed[RNG_SEED_SIZE];
+ get_random_bytes(rng_seed, RNG_SEED_SIZE);
+ ret = fdt_setprop(dtb, off, FDT_PROP_RNG_SEED, rng_seed,
+ RNG_SEED_SIZE);
+ if (ret)
+ goto out;
+ } else {
+ pr_notice("RNG is not initialised: omitting \"%s\" property\n",
+ FDT_PROP_RNG_SEED);
+ }
+
out:
if (ret)
return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL;
@@ -110,7 +125,8 @@ out:
}
/*
- * More space needed so that we can add initrd, bootargs and kaslr-seed.
+ * More space needed so that we can add initrd, bootargs, kaslr-seed, and
+ * rng-seed.
*/
#define DTB_EXTRA_SPACE 0x1000
@@ -177,7 +193,7 @@ int load_other_segments(struct kimage *image,
if (initrd) {
kbuf.buffer = initrd;
kbuf.bufsz = initrd_len;
- kbuf.mem = 0;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
kbuf.memsz = initrd_len;
kbuf.buf_align = 0;
/* within 1GB-aligned window of up to 32GB in size */
@@ -204,7 +220,7 @@ int load_other_segments(struct kimage *image,
dtb_len = fdt_totalsize(dtb);
kbuf.buffer = dtb;
kbuf.bufsz = dtb_len;
- kbuf.mem = 0;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
kbuf.memsz = dtb_len;
/* not across 2MB boundary */
kbuf.buf_align = SZ_2M;
diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c
index 044c0ae4d6c8..b182442b87a3 100644
--- a/arch/arm64/kernel/module-plts.c
+++ b/arch/arm64/kernel/module-plts.c
@@ -302,7 +302,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
/* sort by type, symbol index and addend */
sort(rels, numrels, sizeof(Elf64_Rela), cmp_rela, NULL);
- if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0)
+ if (!str_has_prefix(secstrings + dstsec->sh_name, ".init"))
core_plts += count_plts(syms, rels, numrels,
sechdrs[i].sh_info, dstsec);
else
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 46e643e30708..03ff15bffbb6 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -314,18 +314,21 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
/* MOVW instruction relocations. */
case R_AARCH64_MOVW_UABS_G0_NC:
overflow_check = false;
+ /* Fall through */
case R_AARCH64_MOVW_UABS_G0:
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
AARCH64_INSN_IMM_MOVKZ);
break;
case R_AARCH64_MOVW_UABS_G1_NC:
overflow_check = false;
+ /* Fall through */
case R_AARCH64_MOVW_UABS_G1:
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
AARCH64_INSN_IMM_MOVKZ);
break;
case R_AARCH64_MOVW_UABS_G2_NC:
overflow_check = false;
+ /* Fall through */
case R_AARCH64_MOVW_UABS_G2:
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
AARCH64_INSN_IMM_MOVKZ);
@@ -393,6 +396,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_AARCH64_ADR_PREL_PG_HI21_NC:
overflow_check = false;
+ /* Fall through */
case R_AARCH64_ADR_PREL_PG_HI21:
ovf = reloc_insn_adrp(me, sechdrs, loc, val);
if (ovf && ovf != -ERANGE)
diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index 9d63514b9836..b0e03e052dd1 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -154,12 +154,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
return;
}
- frame.fp = regs->regs[29];
- frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
-
+ start_backtrace(&frame, regs->regs[29], regs->pc);
walk_stackframe(current, &frame, callchain_trace, entry);
}
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 96e90e270042..a0b4f1bca491 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
+#include <linux/smp.h>
/* ARMv8 Cortex-A53 specific event types. */
#define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2
@@ -157,7 +158,6 @@ armv8pmu_events_sysfs_show(struct device *dev,
return sprintf(page, "event=0x%03llx\n", pmu_attr->id);
}
-#define ARMV8_EVENT_ATTR_RESOLVE(m) #m
#define ARMV8_EVENT_ATTR(name, config) \
PMU_EVENT_ATTR(name, armv8_event_attr_##name, \
config, armv8pmu_events_sysfs_show)
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index bd5dfffca272..c4452827419b 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -21,6 +21,7 @@
#include <asm/ptrace.h>
#include <asm/cacheflush.h>
#include <asm/debug-monitors.h>
+#include <asm/daifflags.h>
#include <asm/system_misc.h>
#include <asm/insn.h>
#include <linux/uaccess.h>
@@ -168,33 +169,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
}
/*
- * When PSTATE.D is set (masked), then software step exceptions can not be
- * generated.
- * SPSR's D bit shows the value of PSTATE.D immediately before the
- * exception was taken. PSTATE.D is set while entering into any exception
- * mode, however software clears it for any normal (none-debug-exception)
- * mode in the exception entry. Therefore, when we are entering into kprobe
- * breakpoint handler from any normal mode then SPSR.D bit is already
- * cleared, however it is set when we are entering from any debug exception
- * mode.
- * Since we always need to generate single step exception after a kprobe
- * breakpoint exception therefore we need to clear it unconditionally, when
- * we become sure that the current breakpoint exception is for kprobe.
- */
-static void __kprobes
-spsr_set_debug_flag(struct pt_regs *regs, int mask)
-{
- unsigned long spsr = regs->pstate;
-
- if (mask)
- spsr |= PSR_D_BIT;
- else
- spsr &= ~PSR_D_BIT;
-
- regs->pstate = spsr;
-}
-
-/*
* Interrupts need to be disabled before single-step mode is set, and not
* reenabled until after single-step mode ends.
* Without disabling interrupt on local CPU, there is a chance of
@@ -205,17 +179,17 @@ spsr_set_debug_flag(struct pt_regs *regs, int mask)
static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
struct pt_regs *regs)
{
- kcb->saved_irqflag = regs->pstate;
+ kcb->saved_irqflag = regs->pstate & DAIF_MASK;
regs->pstate |= PSR_I_BIT;
+ /* Unmask PSTATE.D for enabling software step exceptions. */
+ regs->pstate &= ~PSR_D_BIT;
}
static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
struct pt_regs *regs)
{
- if (kcb->saved_irqflag & PSR_I_BIT)
- regs->pstate |= PSR_I_BIT;
- else
- regs->pstate &= ~PSR_I_BIT;
+ regs->pstate &= ~DAIF_MASK;
+ regs->pstate |= kcb->saved_irqflag;
}
static void __kprobes
@@ -252,8 +226,6 @@ static void __kprobes setup_singlestep(struct kprobe *p,
set_ss_context(kcb, slot); /* mark pending ss */
- spsr_set_debug_flag(regs, 0);
-
/* IRQs and single stepping do not mix well. */
kprobes_save_local_irqflag(kcb, regs);
kernel_enable_single_step(regs);
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 6a869d9f304f..03689c0beb34 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
+#include <linux/sysctl.h>
#include <linux/unistd.h>
#include <linux/user.h>
#include <linux/delay.h>
@@ -38,6 +39,7 @@
#include <trace/events/power.h>
#include <linux/percpu.h>
#include <linux/thread_info.h>
+#include <linux/prctl.h>
#include <asm/alternative.h>
#include <asm/arch_gicv3.h>
@@ -307,11 +309,18 @@ static void tls_thread_flush(void)
}
}
+static void flush_tagged_addr_state(void)
+{
+ if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI))
+ clear_thread_flag(TIF_TAGGED_ADDR);
+}
+
void flush_thread(void)
{
fpsimd_flush_thread();
tls_thread_flush();
flush_ptrace_hw_breakpoint(current);
+ flush_tagged_addr_state();
}
void release_thread(struct task_struct *dead_task)
@@ -398,7 +407,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
childregs->pstate |= PSR_UAO_BIT;
if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE)
- childregs->pstate |= PSR_SSBS_BIT;
+ set_ssbs_bit(childregs);
if (system_uses_irq_prio_masking())
childregs->pmr_save = GIC_PRIO_IRQON;
@@ -443,6 +452,32 @@ void uao_thread_switch(struct task_struct *next)
}
/*
+ * Force SSBS state on context-switch, since it may be lost after migrating
+ * from a CPU which treats the bit as RES0 in a heterogeneous system.
+ */
+static void ssbs_thread_switch(struct task_struct *next)
+{
+ struct pt_regs *regs = task_pt_regs(next);
+
+ /*
+ * Nothing to do for kernel threads, but 'regs' may be junk
+ * (e.g. idle task) so check the flags and bail early.
+ */
+ if (unlikely(next->flags & PF_KTHREAD))
+ return;
+
+ /* If the mitigation is enabled, then we leave SSBS clear. */
+ if ((arm64_get_ssbd_state() == ARM64_SSBD_FORCE_ENABLE) ||
+ test_tsk_thread_flag(next, TIF_SSBD))
+ return;
+
+ if (compat_user_mode(regs))
+ set_compat_ssbs_bit(regs);
+ else if (user_mode(regs))
+ set_ssbs_bit(regs);
+}
+
+/*
* We store our current task in sp_el0, which is clobbered by userspace. Keep a
* shadow copy so that we can restore this upon entry from userspace.
*
@@ -471,6 +506,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
entry_task_switch(next);
uao_thread_switch(next);
ptrauth_thread_switch(next);
+ ssbs_thread_switch(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
@@ -498,11 +534,8 @@ unsigned long get_wchan(struct task_struct *p)
if (!stack_page)
return 0;
- frame.fp = thread_saved_fp(p);
- frame.pc = thread_saved_pc(p);
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
+ start_backtrace(&frame, thread_saved_fp(p), thread_saved_pc(p));
+
do {
if (unwind_frame(p, &frame))
goto out;
@@ -541,3 +574,70 @@ void arch_setup_new_exec(void)
ptrauth_thread_init_user(current);
}
+
+#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
+/*
+ * Control the relaxed ABI allowing tagged user addresses into the kernel.
+ */
+static unsigned int tagged_addr_disabled;
+
+long set_tagged_addr_ctrl(unsigned long arg)
+{
+ if (is_compat_task())
+ return -EINVAL;
+ if (arg & ~PR_TAGGED_ADDR_ENABLE)
+ return -EINVAL;
+
+ /*
+ * Do not allow the enabling of the tagged address ABI if globally
+ * disabled via sysctl abi.tagged_addr_disabled.
+ */
+ if (arg & PR_TAGGED_ADDR_ENABLE && tagged_addr_disabled)
+ return -EINVAL;
+
+ update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE);
+
+ return 0;
+}
+
+long get_tagged_addr_ctrl(void)
+{
+ if (is_compat_task())
+ return -EINVAL;
+
+ if (test_thread_flag(TIF_TAGGED_ADDR))
+ return PR_TAGGED_ADDR_ENABLE;
+
+ return 0;
+}
+
+/*
+ * Global sysctl to disable the tagged user addresses support. This control
+ * only prevents the tagged address ABI enabling via prctl() and does not
+ * disable it for tasks that already opted in to the relaxed ABI.
+ */
+static int zero;
+static int one = 1;
+
+static struct ctl_table tagged_addr_sysctl_table[] = {
+ {
+ .procname = "tagged_addr_disabled",
+ .mode = 0644,
+ .data = &tagged_addr_disabled,
+ .maxlen = sizeof(int),
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ { }
+};
+
+static int __init tagged_addr_init(void)
+{
+ if (!register_sysctl("abi", tagged_addr_sysctl_table))
+ return -EINVAL;
+ return 0;
+}
+
+core_initcall(tagged_addr_init);
+#endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 85ee7d07889e..c9f72b2665f1 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -46,6 +46,11 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
}
#ifdef CONFIG_HOTPLUG_CPU
+static bool cpu_psci_cpu_can_disable(unsigned int cpu)
+{
+ return !psci_tos_resident_on(cpu);
+}
+
static int cpu_psci_cpu_disable(unsigned int cpu)
{
/* Fail early if we don't have CPU_OFF support */
@@ -105,14 +110,11 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
const struct cpu_operations cpu_psci_ops = {
.name = "psci",
-#ifdef CONFIG_CPU_IDLE
- .cpu_init_idle = psci_cpu_init_idle,
- .cpu_suspend = psci_cpu_suspend_enter,
-#endif
.cpu_init = cpu_psci_cpu_init,
.cpu_prepare = cpu_psci_cpu_prepare,
.cpu_boot = cpu_psci_cpu_boot,
#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_can_disable = cpu_psci_cpu_can_disable,
.cpu_disable = cpu_psci_cpu_disable,
.cpu_die = cpu_psci_cpu_die,
.cpu_kill = cpu_psci_cpu_kill,
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 3cf3b135027e..21176d02e21a 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -870,7 +870,7 @@ static int sve_set(struct task_struct *target,
goto out;
/*
- * Apart from PT_SVE_REGS_MASK, all PT_SVE_* flags are consumed by
+ * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by
* sve_set_vector_length(), which will also validate them for us:
*/
ret = sve_set_vector_length(target, header.vl,
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index b21cba90f82d..a5e8b3b9d798 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -8,6 +8,7 @@
#include <linux/export.h>
#include <linux/ftrace.h>
+#include <linux/kprobes.h>
#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
@@ -29,6 +30,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
return 0;
}
}
+NOKPROBE_SYMBOL(save_return_addr);
void *return_address(unsigned int level)
{
@@ -38,12 +40,9 @@ void *return_address(unsigned int level)
data.level = level + 2;
data.addr = NULL;
- frame.fp = (unsigned long)__builtin_frame_address(0);
- frame.pc = (unsigned long)return_address; /* dummy */
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
-
+ start_backtrace(&frame,
+ (unsigned long)__builtin_frame_address(0),
+ (unsigned long)return_address);
walk_stackframe(current, &frame, save_return_addr, &data);
if (!data.level)
@@ -52,3 +51,4 @@ void *return_address(unsigned int level)
return NULL;
}
EXPORT_SYMBOL_GPL(return_address);
+NOKPROBE_SYMBOL(return_address);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 9c4bad7d7131..56f664561754 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -170,9 +170,13 @@ static void __init smp_build_mpidr_hash(void)
static void __init setup_machine_fdt(phys_addr_t dt_phys)
{
- void *dt_virt = fixmap_remap_fdt(dt_phys);
+ int size;
+ void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
const char *name;
+ if (dt_virt)
+ memblock_reserve(dt_phys, size);
+
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
pr_crit("\n"
"Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n"
@@ -184,6 +188,9 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
cpu_relax();
}
+ /* Early fixups are done, map the FDT as read-only now */
+ fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);
+
name = of_flat_dt_get_machine_name();
if (!name)
return;
@@ -357,6 +364,15 @@ void __init setup_arch(char **cmdline_p)
}
}
+static inline bool cpu_can_disable(unsigned int cpu)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+ if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_can_disable)
+ return cpu_ops[cpu]->cpu_can_disable(cpu);
+#endif
+ return false;
+}
+
static int __init topology_init(void)
{
int i;
@@ -366,7 +382,7 @@ static int __init topology_init(void)
for_each_possible_cpu(i) {
struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
- cpu->hotpluggable = 1;
+ cpu->hotpluggable = cpu_can_disable(i);
register_cpu(cpu, i);
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index ea90d3bd9253..dc9fe879c279 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -123,7 +123,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
* time out.
*/
wait_for_completion_timeout(&cpu_running,
- msecs_to_jiffies(1000));
+ msecs_to_jiffies(5000));
if (!cpu_online(cpu)) {
pr_crit("CPU%u: failed to come online\n", cpu);
@@ -136,6 +136,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
secondary_data.task = NULL;
secondary_data.stack = NULL;
+ __flush_dcache_area(&secondary_data, sizeof(secondary_data));
status = READ_ONCE(secondary_data.status);
if (ret && status) {
@@ -146,14 +147,15 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
default:
pr_err("CPU%u: failed in unknown state : 0x%lx\n",
cpu, status);
+ cpus_stuck_in_kernel++;
break;
case CPU_KILL_ME:
if (!op_cpu_kill(cpu)) {
pr_crit("CPU%u: died during early boot\n", cpu);
break;
}
- /* Fall through */
pr_crit("CPU%u: may not have shut down cleanly\n", cpu);
+ /* Fall through */
case CPU_STUCK_IN_KERNEL:
pr_crit("CPU%u: is stuck in kernel\n", cpu);
if (status & CPU_STUCK_REASON_52_BIT_VA)
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 76c2739ba8a4..c8a3fee00c11 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -19,7 +19,7 @@
#include <asm/smp_plat.h>
extern void secondary_holding_pen(void);
-volatile unsigned long __section(".mmuoff.data.read")
+volatile unsigned long __section(.mmuoff.data.read)
secondary_holding_pen_release = INVALID_HWID;
static phys_addr_t cpu_release_addr[NR_CPUS];
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 62d395151abe..a336cb124320 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/ftrace.h>
+#include <linux/kprobes.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
@@ -29,9 +30,18 @@
* ldp x29, x30, [sp]
* add sp, sp, #0x10
*/
+
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
{
unsigned long fp = frame->fp;
+ struct stack_info info;
if (fp & 0xf)
return -EINVAL;
@@ -39,11 +49,40 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
if (!tsk)
tsk = current;
- if (!on_accessible_stack(tsk, fp, NULL))
+ if (!on_accessible_stack(tsk, fp, &info))
+ return -EINVAL;
+
+ if (test_bit(info.type, frame->stacks_done))
return -EINVAL;
+ /*
+ * As stacks grow downward, any valid record on the same stack must be
+ * at a strictly higher address than the prior record.
+ *
+ * Stacks can nest in several valid orders, e.g.
+ *
+ * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
+ * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+ *
+ * ... but the nesting itself is strict. Once we transition from one
+ * stack to another, it's never valid to unwind back to that first
+ * stack.
+ */
+ if (info.type == frame->prev_type) {
+ if (fp <= frame->prev_fp)
+ return -EINVAL;
+ } else {
+ set_bit(frame->prev_type, frame->stacks_done);
+ }
+
+ /*
+ * Record this frame record's values and location. The prev_fp and
+ * prev_type are only meaningful to the next unwind_frame() invocation.
+ */
frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
+ frame->prev_fp = fp;
+ frame->prev_type = info.type;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if (tsk->ret_stack &&
@@ -73,6 +112,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
return 0;
}
+NOKPROBE_SYMBOL(unwind_frame);
void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
int (*fn)(struct stackframe *, void *), void *data)
@@ -87,6 +127,7 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
break;
}
}
+NOKPROBE_SYMBOL(walk_stackframe);
#ifdef CONFIG_STACKTRACE
struct stack_trace_data {
@@ -122,12 +163,7 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
data.skip = trace->skip;
data.no_sched_functions = 0;
- frame.fp = regs->regs[29];
- frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
-
+ start_backtrace(&frame, regs->regs[29], regs->pc);
walk_stackframe(current, &frame, save_trace, &data);
}
EXPORT_SYMBOL_GPL(save_stack_trace_regs);
@@ -146,17 +182,15 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
data.no_sched_functions = nosched;
if (tsk != current) {
- frame.fp = thread_saved_fp(tsk);
- frame.pc = thread_saved_pc(tsk);
+ start_backtrace(&frame, thread_saved_fp(tsk),
+ thread_saved_pc(tsk));
} else {
/* We don't want this function nor the caller */
data.skip += 2;
- frame.fp = (unsigned long)__builtin_frame_address(0);
- frame.pc = (unsigned long)__save_stack_trace;
+ start_backtrace(&frame,
+ (unsigned long)__builtin_frame_address(0),
+ (unsigned long)__save_stack_trace);
}
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
walk_stackframe(tsk, &frame, save_trace, &data);
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 9f25aedeac9d..0b2946414dc9 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -38,11 +38,8 @@ unsigned long profile_pc(struct pt_regs *regs)
if (!in_lock_functions(regs->pc))
return regs->pc;
- frame.fp = regs->regs[29];
- frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
+ start_backtrace(&frame, regs->regs[29], regs->pc);
+
do {
int ret = unwind_frame(NULL, &frame);
if (ret < 0)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 0825c4a856e3..fa9528dfd0ce 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -14,250 +14,13 @@
#include <linux/acpi.h>
#include <linux/arch_topology.h>
#include <linux/cacheinfo.h>
-#include <linux/cpu.h>
-#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/percpu.h>
-#include <linux/node.h>
-#include <linux/nodemask.h>
-#include <linux/of.h>
-#include <linux/sched.h>
-#include <linux/sched/topology.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/string.h>
#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/topology.h>
-static int __init get_cpu_for_node(struct device_node *node)
-{
- struct device_node *cpu_node;
- int cpu;
-
- cpu_node = of_parse_phandle(node, "cpu", 0);
- if (!cpu_node)
- return -1;
-
- cpu = of_cpu_node_to_id(cpu_node);
- if (cpu >= 0)
- topology_parse_cpu_capacity(cpu_node, cpu);
- else
- pr_crit("Unable to find CPU node for %pOF\n", cpu_node);
-
- of_node_put(cpu_node);
- return cpu;
-}
-
-static int __init parse_core(struct device_node *core, int package_id,
- int core_id)
-{
- char name[10];
- bool leaf = true;
- int i = 0;
- int cpu;
- struct device_node *t;
-
- do {
- snprintf(name, sizeof(name), "thread%d", i);
- t = of_get_child_by_name(core, name);
- if (t) {
- leaf = false;
- cpu = get_cpu_for_node(t);
- if (cpu >= 0) {
- cpu_topology[cpu].package_id = package_id;
- cpu_topology[cpu].core_id = core_id;
- cpu_topology[cpu].thread_id = i;
- } else {
- pr_err("%pOF: Can't get CPU for thread\n",
- t);
- of_node_put(t);
- return -EINVAL;
- }
- of_node_put(t);
- }
- i++;
- } while (t);
-
- cpu = get_cpu_for_node(core);
- if (cpu >= 0) {
- if (!leaf) {
- pr_err("%pOF: Core has both threads and CPU\n",
- core);
- return -EINVAL;
- }
-
- cpu_topology[cpu].package_id = package_id;
- cpu_topology[cpu].core_id = core_id;
- } else if (leaf) {
- pr_err("%pOF: Can't get CPU for leaf core\n", core);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int __init parse_cluster(struct device_node *cluster, int depth)
-{
- char name[10];
- bool leaf = true;
- bool has_cores = false;
- struct device_node *c;
- static int package_id __initdata;
- int core_id = 0;
- int i, ret;
-
- /*
- * First check for child clusters; we currently ignore any
- * information about the nesting of clusters and present the
- * scheduler with a flat list of them.
- */
- i = 0;
- do {
- snprintf(name, sizeof(name), "cluster%d", i);
- c = of_get_child_by_name(cluster, name);
- if (c) {
- leaf = false;
- ret = parse_cluster(c, depth + 1);
- of_node_put(c);
- if (ret != 0)
- return ret;
- }
- i++;
- } while (c);
-
- /* Now check for cores */
- i = 0;
- do {
- snprintf(name, sizeof(name), "core%d", i);
- c = of_get_child_by_name(cluster, name);
- if (c) {
- has_cores = true;
-
- if (depth == 0) {
- pr_err("%pOF: cpu-map children should be clusters\n",
- c);
- of_node_put(c);
- return -EINVAL;
- }
-
- if (leaf) {
- ret = parse_core(c, package_id, core_id++);
- } else {
- pr_err("%pOF: Non-leaf cluster with core %s\n",
- cluster, name);
- ret = -EINVAL;
- }
-
- of_node_put(c);
- if (ret != 0)
- return ret;
- }
- i++;
- } while (c);
-
- if (leaf && !has_cores)
- pr_warn("%pOF: empty cluster\n", cluster);
-
- if (leaf)
- package_id++;
-
- return 0;
-}
-
-static int __init parse_dt_topology(void)
-{
- struct device_node *cn, *map;
- int ret = 0;
- int cpu;
-
- cn = of_find_node_by_path("/cpus");
- if (!cn) {
- pr_err("No CPU information found in DT\n");
- return 0;
- }
-
- /*
- * When topology is provided cpu-map is essentially a root
- * cluster with restricted subnodes.
- */
- map = of_get_child_by_name(cn, "cpu-map");
- if (!map)
- goto out;
-
- ret = parse_cluster(map, 0);
- if (ret != 0)
- goto out_map;
-
- topology_normalize_cpu_scale();
-
- /*
- * Check that all cores are in the topology; the SMP code will
- * only mark cores described in the DT as possible.
- */
- for_each_possible_cpu(cpu)
- if (cpu_topology[cpu].package_id == -1)
- ret = -EINVAL;
-
-out_map:
- of_node_put(map);
-out:
- of_node_put(cn);
- return ret;
-}
-
-/*
- * cpu topology table
- */
-struct cpu_topology cpu_topology[NR_CPUS];
-EXPORT_SYMBOL_GPL(cpu_topology);
-
-const struct cpumask *cpu_coregroup_mask(int cpu)
-{
- const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu));
-
- /* Find the smaller of NUMA, core or LLC siblings */
- if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) {
- /* not numa in package, lets use the package siblings */
- core_mask = &cpu_topology[cpu].core_sibling;
- }
- if (cpu_topology[cpu].llc_id != -1) {
- if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask))
- core_mask = &cpu_topology[cpu].llc_sibling;
- }
-
- return core_mask;
-}
-
-static void update_siblings_masks(unsigned int cpuid)
-{
- struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
- int cpu;
-
- /* update core and thread sibling masks */
- for_each_online_cpu(cpu) {
- cpu_topo = &cpu_topology[cpu];
-
- if (cpuid_topo->llc_id == cpu_topo->llc_id) {
- cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
- cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
- }
-
- if (cpuid_topo->package_id != cpu_topo->package_id)
- continue;
-
- cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
- cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
-
- if (cpuid_topo->core_id != cpu_topo->core_id)
- continue;
-
- cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
- cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
- }
-}
-
void store_cpu_topology(unsigned int cpuid)
{
struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
@@ -296,60 +59,31 @@ topology_populated:
update_siblings_masks(cpuid);
}
-static void clear_cpu_topology(int cpu)
-{
- struct cpu_topology *cpu_topo = &cpu_topology[cpu];
-
- cpumask_clear(&cpu_topo->llc_sibling);
- cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
-
- cpumask_clear(&cpu_topo->core_sibling);
- cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
- cpumask_clear(&cpu_topo->thread_sibling);
- cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
-}
-
-static void __init reset_cpu_topology(void)
-{
- unsigned int cpu;
-
- for_each_possible_cpu(cpu) {
- struct cpu_topology *cpu_topo = &cpu_topology[cpu];
-
- cpu_topo->thread_id = -1;
- cpu_topo->core_id = 0;
- cpu_topo->package_id = -1;
- cpu_topo->llc_id = -1;
-
- clear_cpu_topology(cpu);
- }
-}
-
-void remove_cpu_topology(unsigned int cpu)
+#ifdef CONFIG_ACPI
+static bool __init acpi_cpu_is_threaded(int cpu)
{
- int sibling;
+ int is_threaded = acpi_pptt_cpu_is_thread(cpu);
- for_each_cpu(sibling, topology_core_cpumask(cpu))
- cpumask_clear_cpu(cpu, topology_core_cpumask(sibling));
- for_each_cpu(sibling, topology_sibling_cpumask(cpu))
- cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
- for_each_cpu(sibling, topology_llc_cpumask(cpu))
- cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling));
+ /*
+ * if the PPTT doesn't have thread information, assume a homogeneous
+ * machine and return the current CPU's thread state.
+ */
+ if (is_threaded < 0)
+ is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
- clear_cpu_topology(cpu);
+ return !!is_threaded;
}
-#ifdef CONFIG_ACPI
/*
* Propagate the topology information of the processor_topology_node tree to the
* cpu_topology array.
*/
-static int __init parse_acpi_topology(void)
+int __init parse_acpi_topology(void)
{
- bool is_threaded;
int cpu, topology_id;
- is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
+ if (acpi_disabled)
+ return 0;
for_each_possible_cpu(cpu) {
int i, cache_id;
@@ -358,7 +92,7 @@ static int __init parse_acpi_topology(void)
if (topology_id < 0)
return topology_id;
- if (is_threaded) {
+ if (acpi_cpu_is_threaded(cpu)) {
cpu_topology[cpu].thread_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 1);
cpu_topology[cpu].core_id = topology_id;
@@ -384,24 +118,6 @@ static int __init parse_acpi_topology(void)
return 0;
}
-
-#else
-static inline int __init parse_acpi_topology(void)
-{
- return -EINVAL;
-}
#endif
-void __init init_cpu_topology(void)
-{
- reset_cpu_topology();
- /*
- * Discard anything that was parsed if we hit an error so we
- * don't use partial information.
- */
- if (!acpi_disabled && parse_acpi_topology())
- reset_cpu_topology();
- else if (of_have_populated_dt() && parse_dt_topology())
- reset_cpu_topology();
-}
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8c03456dade6..34739e80211b 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -7,9 +7,11 @@
*/
#include <linux/bug.h>
+#include <linux/context_tracking.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/kallsyms.h>
+#include <linux/kprobes.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>
@@ -100,18 +102,17 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
return;
if (tsk == current) {
- frame.fp = (unsigned long)__builtin_frame_address(0);
- frame.pc = (unsigned long)dump_backtrace;
+ start_backtrace(&frame,
+ (unsigned long)__builtin_frame_address(0),
+ (unsigned long)dump_backtrace);
} else {
/*
* task blocked in __switch_to
*/
- frame.fp = thread_saved_fp(tsk);
- frame.pc = thread_saved_pc(tsk);
+ start_backtrace(&frame,
+ thread_saved_fp(tsk),
+ thread_saved_pc(tsk));
}
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- frame.graph = 0;
-#endif
printk("Call trace:\n");
do {
@@ -512,7 +513,7 @@ struct sys64_hook {
void (*handler)(unsigned int esr, struct pt_regs *regs);
};
-static struct sys64_hook sys64_hooks[] = {
+static const struct sys64_hook sys64_hooks[] = {
{
.esr_mask = ESR_ELx_SYS64_ISS_EL0_CACHE_OP_MASK,
.esr_val = ESR_ELx_SYS64_ISS_EL0_CACHE_OP_VAL,
@@ -637,7 +638,7 @@ static void compat_cntfrq_read_handler(unsigned int esr, struct pt_regs *regs)
arm64_compat_skip_faulting_instruction(regs, 4);
}
-static struct sys64_hook cp15_32_hooks[] = {
+static const struct sys64_hook cp15_32_hooks[] = {
{
.esr_mask = ESR_ELx_CP15_32_ISS_SYS_MASK,
.esr_val = ESR_ELx_CP15_32_ISS_SYS_CNTFRQ,
@@ -657,7 +658,7 @@ static void compat_cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
arm64_compat_skip_faulting_instruction(regs, 4);
}
-static struct sys64_hook cp15_64_hooks[] = {
+static const struct sys64_hook cp15_64_hooks[] = {
{
.esr_mask = ESR_ELx_CP15_64_ISS_SYS_MASK,
.esr_val = ESR_ELx_CP15_64_ISS_SYS_CNTVCT,
@@ -668,7 +669,7 @@ static struct sys64_hook cp15_64_hooks[] = {
asmlinkage void __exception do_cp15instr(unsigned int esr, struct pt_regs *regs)
{
- struct sys64_hook *hook, *hook_base;
+ const struct sys64_hook *hook, *hook_base;
if (!cp15_cond_valid(esr, regs)) {
/*
@@ -708,7 +709,7 @@ asmlinkage void __exception do_cp15instr(unsigned int esr, struct pt_regs *regs)
asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs)
{
- struct sys64_hook *hook;
+ const struct sys64_hook *hook;
for (hook = sys64_hooks; hook->handler; hook++)
if ((hook->esr_mask & esr) == hook->esr_val) {
@@ -734,6 +735,7 @@ static const char *esr_class_str[] = {
[ESR_ELx_EC_CP14_LS] = "CP14 LDC/STC",
[ESR_ELx_EC_FP_ASIMD] = "ASIMD",
[ESR_ELx_EC_CP10_ID] = "CP10 MRC/VMRS",
+ [ESR_ELx_EC_PAC] = "PAC",
[ESR_ELx_EC_CP14_64] = "CP14 MCRR/MRRC",
[ESR_ELx_EC_ILL] = "PSTATE.IL",
[ESR_ELx_EC_SVC32] = "SVC (AArch32)",
@@ -744,6 +746,7 @@ static const char *esr_class_str[] = {
[ESR_ELx_EC_SMC64] = "SMC (AArch64)",
[ESR_ELx_EC_SYS64] = "MSR/MRS (AArch64)",
[ESR_ELx_EC_SVE] = "SVE",
+ [ESR_ELx_EC_ERET] = "ERET/ERETAA/ERETAB",
[ESR_ELx_EC_IMP_DEF] = "EL3 IMP DEF",
[ESR_ELx_EC_IABT_LOW] = "IABT (lower EL)",
[ESR_ELx_EC_IABT_CUR] = "IABT (current EL)",
@@ -900,6 +903,13 @@ asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
nmi_exit();
}
+asmlinkage void enter_from_user_mode(void)
+{
+ CT_WARN_ON(ct_state() != CONTEXT_USER);
+ user_exit_irqoff();
+}
+NOKPROBE_SYMBOL(enter_from_user_mode);
+
void __pte_error(const char *file, int line, unsigned long val)
{
pr_err("%s:%d: bad pte %016lx.\n", file, line, val);
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 4ab863045188..dd2514bb1511 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -32,10 +32,10 @@ UBSAN_SANITIZE := n
OBJECT_FILES_NON_STANDARD := y
KCOV_INSTRUMENT := n
-ifeq ($(c-gettimeofday-y),)
CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny
-else
-CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -include $(c-gettimeofday-y)
+
+ifneq ($(c-gettimeofday-y),)
+ CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
endif
# Clang versions less than 8 do not support -mcmodel=tiny
@@ -57,8 +57,7 @@ $(obj)/vdso.o : $(obj)/vdso.so
# Link rule for the .so file, .lds has to be first
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
- $(call if_changed,ld)
- $(call if_changed,vdso_check)
+ $(call if_changed,vdsold_and_vdso_check)
# Strip rule for the .so file
$(obj)/%.so: OBJCOPYFLAGS := -S
@@ -74,8 +73,8 @@ include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
$(call if_changed,vdsosym)
# Actual build commands
-quiet_cmd_vdsocc = VDSOCC $@
- cmd_vdsocc = $(CC) $(a_flags) $(c_flags) -c -o $@ $<
+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 $@
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index 60a4c6239712..1fba0776ed40 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -144,8 +144,7 @@ $(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/$(munge) FORCE
# Link rule for the .so file, .lds has to be first
$(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE
- $(call if_changed,vdsold)
- $(call if_changed,vdso_check)
+ $(call if_changed,vdsold_and_vdso_check)
# Compilation rules for the vDSO sources
$(c-obj-vdso): %.o: %.c FORCE
@@ -156,14 +155,17 @@ $(asm-obj-vdso): %.o: %.S FORCE
$(call if_changed_dep,vdsoas)
# Actual build commands
-quiet_cmd_vdsold = VDSOL $@
+quiet_cmd_vdsold_and_vdso_check = LD32 $@
+ cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+
+quiet_cmd_vdsold = LD32 $@
cmd_vdsold = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_LDFLAGS) \
-Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
-quiet_cmd_vdsocc = VDSOC $@
+quiet_cmd_vdsocc = CC32 $@
cmd_vdsocc = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) -c -o $@ $<
-quiet_cmd_vdsocc_gettimeofday = VDSOC_GTD $@
+quiet_cmd_vdsocc_gettimeofday = CC32 $@
cmd_vdsocc_gettimeofday = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) $(VDSO_CFLAGS_gettimeofday_o) -c -o $@ $<
-quiet_cmd_vdsoas = VDSOA $@
+quiet_cmd_vdsoas = AS32 $@
cmd_vdsoas = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_AFLAGS) -c -o $@ $<
quiet_cmd_vdsomunge = MUNGE $@
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 7fa008374907..aa76f7259668 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -200,6 +200,15 @@ SECTIONS
__rela_offset = ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR);
__rela_size = SIZEOF(.rela.dyn);
+#ifdef CONFIG_RELR
+ .relr.dyn : ALIGN(8) {
+ *(.relr.dyn)
+ }
+
+ __relr_offset = ABSOLUTE(ADDR(.relr.dyn) - KIMAGE_VADDR);
+ __relr_size = SIZEOF(.relr.dyn);
+#endif
+
. = ALIGN(SEGMENT_ALIGN);
__initdata_end = .;
__init_end = .;
@@ -245,6 +254,8 @@ SECTIONS
HEAD_SYMBOLS
}
+#include "image-vars.h"
+
/*
* The HYP init code and ID map text can't be longer than a page each,
* and should not cross a page boundary.
diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c
index 26781da3ad3e..0fc9872a1467 100644
--- a/arch/arm64/kvm/hyp/debug-sr.c
+++ b/arch/arm64/kvm/hyp/debug-sr.c
@@ -18,40 +18,70 @@
#define save_debug(ptr,reg,nr) \
switch (nr) { \
case 15: ptr[15] = read_debug(reg, 15); \
+ /* Fall through */ \
case 14: ptr[14] = read_debug(reg, 14); \
+ /* Fall through */ \
case 13: ptr[13] = read_debug(reg, 13); \
+ /* Fall through */ \
case 12: ptr[12] = read_debug(reg, 12); \
+ /* Fall through */ \
case 11: ptr[11] = read_debug(reg, 11); \
+ /* Fall through */ \
case 10: ptr[10] = read_debug(reg, 10); \
+ /* Fall through */ \
case 9: ptr[9] = read_debug(reg, 9); \
+ /* Fall through */ \
case 8: ptr[8] = read_debug(reg, 8); \
+ /* Fall through */ \
case 7: ptr[7] = read_debug(reg, 7); \
+ /* Fall through */ \
case 6: ptr[6] = read_debug(reg, 6); \
+ /* Fall through */ \
case 5: ptr[5] = read_debug(reg, 5); \
+ /* Fall through */ \
case 4: ptr[4] = read_debug(reg, 4); \
+ /* Fall through */ \
case 3: ptr[3] = read_debug(reg, 3); \
+ /* Fall through */ \
case 2: ptr[2] = read_debug(reg, 2); \
+ /* Fall through */ \
case 1: ptr[1] = read_debug(reg, 1); \
+ /* Fall through */ \
default: ptr[0] = read_debug(reg, 0); \
}
#define restore_debug(ptr,reg,nr) \
switch (nr) { \
case 15: write_debug(ptr[15], reg, 15); \
+ /* Fall through */ \
case 14: write_debug(ptr[14], reg, 14); \
+ /* Fall through */ \
case 13: write_debug(ptr[13], reg, 13); \
+ /* Fall through */ \
case 12: write_debug(ptr[12], reg, 12); \
+ /* Fall through */ \
case 11: write_debug(ptr[11], reg, 11); \
+ /* Fall through */ \
case 10: write_debug(ptr[10], reg, 10); \
+ /* Fall through */ \
case 9: write_debug(ptr[9], reg, 9); \
+ /* Fall through */ \
case 8: write_debug(ptr[8], reg, 8); \
+ /* Fall through */ \
case 7: write_debug(ptr[7], reg, 7); \
+ /* Fall through */ \
case 6: write_debug(ptr[6], reg, 6); \
+ /* Fall through */ \
case 5: write_debug(ptr[5], reg, 5); \
+ /* Fall through */ \
case 4: write_debug(ptr[4], reg, 4); \
+ /* Fall through */ \
case 3: write_debug(ptr[3], reg, 3); \
+ /* Fall through */ \
case 2: write_debug(ptr[2], reg, 2); \
+ /* Fall through */ \
case 1: write_debug(ptr[1], reg, 1); \
+ /* Fall through */ \
default: write_debug(ptr[0], reg, 0); \
}
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index adaf266d8de8..bd978ad71936 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -264,7 +264,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar)
tmp = read_sysreg(par_el1);
write_sysreg(par, par_el1);
- if (unlikely(tmp & 1))
+ if (unlikely(tmp & SYS_PAR_EL1_F))
return false; /* Translation failed, back to guest */
/* Convert PAR to HPFAR format */
diff --git a/arch/arm64/kvm/regmap.c b/arch/arm64/kvm/regmap.c
index 0d60e4f0af66..a900181e3867 100644
--- a/arch/arm64/kvm/regmap.c
+++ b/arch/arm64/kvm/regmap.c
@@ -178,13 +178,18 @@ void vcpu_write_spsr32(struct kvm_vcpu *vcpu, unsigned long v)
switch (spsr_idx) {
case KVM_SPSR_SVC:
write_sysreg_el1(v, SYS_SPSR);
+ break;
case KVM_SPSR_ABT:
write_sysreg(v, spsr_abt);
+ break;
case KVM_SPSR_UND:
write_sysreg(v, spsr_und);
+ break;
case KVM_SPSR_IRQ:
write_sysreg(v, spsr_irq);
+ break;
case KVM_SPSR_FIQ:
write_sysreg(v, spsr_fiq);
+ break;
}
}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f26e181d881c..2071260a275b 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -632,7 +632,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
*/
val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
| (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
- __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+ __vcpu_sys_reg(vcpu, r->reg) = val;
}
static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
@@ -981,13 +981,13 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
/* 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)), \
- trap_bvr, reset_bvr, n, 0, get_bvr, set_bvr }, \
+ trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr }, \
{ SYS_DESC(SYS_DBGBCRn_EL1(n)), \
- trap_bcr, reset_bcr, n, 0, get_bcr, set_bcr }, \
+ trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr }, \
{ SYS_DESC(SYS_DBGWVRn_EL1(n)), \
- trap_wvr, reset_wvr, n, 0, get_wvr, set_wvr }, \
+ trap_wvr, reset_wvr, 0, 0, get_wvr, set_wvr }, \
{ SYS_DESC(SYS_DBGWCRn_EL1(n)), \
- trap_wcr, reset_wcr, n, 0, get_wcr, set_wcr }
+ trap_wcr, reset_wcr, 0, 0, get_wcr, set_wcr }
/* Macro to expand the PMEVCNTRn_EL0 register */
#define PMU_PMEVCNTR_EL0(n) \
@@ -1540,7 +1540,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
{ SYS_DESC(SYS_CTR_EL0), access_ctr },
- { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
+ { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
{ SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
{ SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
{ SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
@@ -2254,13 +2254,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
}
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
- const struct sys_reg_desc *table, size_t num)
+ const struct sys_reg_desc *table, size_t num,
+ unsigned long *bmap)
{
unsigned long i;
for (i = 0; i < num; i++)
- if (table[i].reset)
+ if (table[i].reset) {
+ int reg = table[i].reg;
+
table[i].reset(vcpu, &table[i]);
+ if (reg > 0 && reg < NR_SYS_REGS)
+ set_bit(reg, bmap);
+ }
}
/**
@@ -2774,18 +2780,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
{
size_t num;
const struct sys_reg_desc *table;
-
- /* Catch someone adding a register without putting in reset entry. */
- memset(&vcpu->arch.ctxt.sys_regs, 0x42, sizeof(vcpu->arch.ctxt.sys_regs));
+ DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
/* Generic chip reset first (so target could override). */
- reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+ reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
table = get_target_table(vcpu->arch.target, true, &num);
- reset_sys_reg_descs(vcpu, table, num);
+ reset_sys_reg_descs(vcpu, table, num, bmap);
for (num = 1; num < NR_SYS_REGS; num++) {
- if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+ if (WARN(!test_bit(num, bmap),
"Didn't reset __vcpu_sys_reg(%zi)\n", num))
break;
}
diff --git a/arch/arm64/kvm/va_layout.c b/arch/arm64/kvm/va_layout.c
index acd8084f1f2c..2cf7d4b606c3 100644
--- a/arch/arm64/kvm/va_layout.c
+++ b/arch/arm64/kvm/va_layout.c
@@ -29,25 +29,25 @@ static void compute_layout(void)
int kva_msb;
/* Where is my RAM region? */
- hyp_va_msb = idmap_addr & BIT(VA_BITS - 1);
- hyp_va_msb ^= BIT(VA_BITS - 1);
+ hyp_va_msb = idmap_addr & BIT(vabits_actual - 1);
+ hyp_va_msb ^= BIT(vabits_actual - 1);
kva_msb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^
(u64)(high_memory - 1));
- if (kva_msb == (VA_BITS - 1)) {
+ if (kva_msb == (vabits_actual - 1)) {
/*
* No space in the address, let's compute the mask so
- * that it covers (VA_BITS - 1) bits, and the region
+ * that it covers (vabits_actual - 1) bits, and the region
* bit. The tag stays set to zero.
*/
- va_mask = BIT(VA_BITS - 1) - 1;
+ va_mask = BIT(vabits_actual - 1) - 1;
va_mask |= hyp_va_msb;
} else {
/*
* We do have some free bits to insert a random tag.
* Hyp VAs are now created from kernel linear map VAs
- * using the following formula (with V == VA_BITS):
+ * using the following formula (with V == vabits_actual):
*
* 63 ... V | V-1 | V-2 .. tag_lsb | tag_lsb - 1 .. 0
* ---------------------------------------------------------
@@ -55,7 +55,7 @@ static void compute_layout(void)
*/
tag_lsb = kva_msb;
va_mask = GENMASK_ULL(tag_lsb - 1, 0);
- tag_val = get_random_long() & GENMASK_ULL(VA_BITS - 2, tag_lsb);
+ tag_val = get_random_long() & GENMASK_ULL(vabits_actual - 2, tag_lsb);
tag_val |= hyp_va_msb;
tag_val >>= tag_lsb;
}
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
index 33c2a4abda04..c21b936dc01d 100644
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -11,25 +11,8 @@ CFLAGS_REMOVE_xor-neon.o += -mgeneral-regs-only
CFLAGS_xor-neon.o += -ffreestanding
endif
-# Tell the compiler to treat all general purpose registers (with the
-# exception of the IP registers, which are already handled by the caller
-# in case of a PLT) as callee-saved, which allows for efficient runtime
-# patching of the bl instruction in the caller with an atomic instruction
-# when supported by the CPU. Result and argument registers are handled
-# correctly, based on the function prototype.
-lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o
-CFLAGS_atomic_ll_sc.o := -ffixed-x1 -ffixed-x2 \
- -ffixed-x3 -ffixed-x4 -ffixed-x5 -ffixed-x6 \
- -ffixed-x7 -fcall-saved-x8 -fcall-saved-x9 \
- -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12 \
- -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \
- -fcall-saved-x18 -fomit-frame-pointer
-CFLAGS_REMOVE_atomic_ll_sc.o := $(CC_FLAGS_FTRACE)
-GCOV_PROFILE_atomic_ll_sc.o := n
-KASAN_SANITIZE_atomic_ll_sc.o := n
-KCOV_INSTRUMENT_atomic_ll_sc.o := n
-UBSAN_SANITIZE_atomic_ll_sc.o := n
-
lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
obj-$(CONFIG_CRC32) += crc32.o
+
+obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
diff --git a/arch/arm64/lib/atomic_ll_sc.c b/arch/arm64/lib/atomic_ll_sc.c
deleted file mode 100644
index b0c538b0da28..000000000000
--- a/arch/arm64/lib/atomic_ll_sc.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <asm/atomic.h>
-#define __ARM64_IN_ATOMIC_IMPL
-#include <asm/atomic_ll_sc.h>
diff --git a/arch/arm64/lib/error-inject.c b/arch/arm64/lib/error-inject.c
new file mode 100644
index 000000000000..ed15021da3ed
--- /dev/null
+++ b/arch/arm64/lib/error-inject.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/error-injection.h>
+#include <linux/kprobes.h>
+
+void override_function_with_return(struct pt_regs *regs)
+{
+ /*
+ * 'regs' represents the state on entry of a predefined function in
+ * the kernel/module and which is captured on a kprobe.
+ *
+ * When kprobe returns back from exception it will override the end
+ * of probed function and directly return to the predefined
+ * function's caller.
+ */
+ instruction_pointer_set(regs, procedure_link_pointer(regs));
+}
+NOKPROBE_SYMBOL(override_function_with_return);
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 1d3f0b5a9940..bd2b039f43a6 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -14,9 +14,7 @@
pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
unsigned long attrs)
{
- if (!dev_is_dma_coherent(dev) || (attrs & DMA_ATTR_WRITE_COMBINE))
- return pgprot_writecombine(prot);
- return prot;
+ return pgprot_writecombine(prot);
}
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 82b3a7fdb4a6..93f9f77582ae 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -25,9 +25,20 @@
#include <asm/pgtable-hwdef.h>
#include <asm/ptdump.h>
-static const struct addr_marker address_markers[] = {
+
+enum address_markers_idx {
+ PAGE_OFFSET_NR = 0,
+ PAGE_END_NR,
#ifdef CONFIG_KASAN
- { KASAN_SHADOW_START, "Kasan shadow start" },
+ KASAN_START_NR,
+#endif
+};
+
+static struct addr_marker address_markers[] = {
+ { PAGE_OFFSET, "Linear Mapping start" },
+ { 0 /* PAGE_END */, "Linear Mapping end" },
+#ifdef CONFIG_KASAN
+ { 0 /* KASAN_SHADOW_START */, "Kasan shadow start" },
{ KASAN_SHADOW_END, "Kasan shadow end" },
#endif
{ MODULES_VADDR, "Modules start" },
@@ -42,7 +53,6 @@ static const struct addr_marker address_markers[] = {
{ VMEMMAP_START, "vmemmap start" },
{ VMEMMAP_START + VMEMMAP_SIZE, "vmemmap end" },
#endif
- { PAGE_OFFSET, "Linear mapping" },
{ -1, NULL },
};
@@ -376,7 +386,7 @@ static void ptdump_initialize(void)
static struct ptdump_info kernel_ptdump_info = {
.mm = &init_mm,
.markers = address_markers,
- .base_addr = VA_START,
+ .base_addr = PAGE_OFFSET,
};
void ptdump_check_wx(void)
@@ -390,7 +400,7 @@ void ptdump_check_wx(void)
.check_wx = true,
};
- walk_pgd(&st, &init_mm, VA_START);
+ walk_pgd(&st, &init_mm, PAGE_OFFSET);
note_page(&st, 0, 0, 0);
if (st.wx_pages || st.uxn_pages)
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",
@@ -401,6 +411,10 @@ void ptdump_check_wx(void)
static int ptdump_init(void)
{
+ address_markers[PAGE_END_NR].start_address = PAGE_END;
+#ifdef CONFIG_KASAN
+ address_markers[KASAN_START_NR].start_address = KASAN_SHADOW_START;
+#endif
ptdump_initialize();
ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables");
return 0;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 9568c116ac7f..115d7a0e4b08 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -8,6 +8,7 @@
*/
#include <linux/acpi.h>
+#include <linux/bitfield.h>
#include <linux/extable.h>
#include <linux/signal.h>
#include <linux/mm.h>
@@ -86,8 +87,8 @@ static void mem_abort_decode(unsigned int esr)
pr_alert("Mem abort info:\n");
pr_alert(" ESR = 0x%08x\n", esr);
- pr_alert(" Exception class = %s, IL = %u bits\n",
- esr_get_class_string(esr),
+ pr_alert(" EC = 0x%02lx: %s, IL = %u bits\n",
+ ESR_ELx_EC(esr), esr_get_class_string(esr),
(esr & ESR_ELx_IL) ? 32 : 16);
pr_alert(" SET = %lu, FnV = %lu\n",
(esr & ESR_ELx_SET_MASK) >> ESR_ELx_SET_SHIFT,
@@ -109,7 +110,7 @@ static inline bool is_ttbr0_addr(unsigned long addr)
static inline bool is_ttbr1_addr(unsigned long addr)
{
/* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */
- return arch_kasan_reset_tag(addr) >= VA_START;
+ return arch_kasan_reset_tag(addr) >= PAGE_OFFSET;
}
/*
@@ -138,10 +139,9 @@ static void show_pte(unsigned long addr)
return;
}
- pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp=%016lx\n",
+ pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n",
mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K,
- mm == &init_mm ? VA_BITS : (int)vabits_user,
- (unsigned long)virt_to_phys(mm->pgd));
+ vabits_actual, (unsigned long)virt_to_phys(mm->pgd));
pgdp = pgd_offset(mm, addr);
pgd = READ_ONCE(*pgdp);
pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd));
@@ -242,6 +242,34 @@ static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr,
return false;
}
+static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr,
+ unsigned int esr,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+ u64 par, dfsc;
+
+ if (ESR_ELx_EC(esr) != ESR_ELx_EC_DABT_CUR ||
+ (esr & ESR_ELx_FSC_TYPE) != ESR_ELx_FSC_FAULT)
+ return false;
+
+ local_irq_save(flags);
+ asm volatile("at s1e1r, %0" :: "r" (addr));
+ isb();
+ par = read_sysreg(par_el1);
+ local_irq_restore(flags);
+
+ if (!(par & SYS_PAR_EL1_F))
+ return false;
+
+ /*
+ * If we got a different type of fault from the AT instruction,
+ * treat the translation fault as spurious.
+ */
+ dfsc = FIELD_PREP(SYS_PAR_EL1_FST, par);
+ return (dfsc & ESR_ELx_FSC_TYPE) != ESR_ELx_FSC_FAULT;
+}
+
static void die_kernel_fault(const char *msg, unsigned long addr,
unsigned int esr, struct pt_regs *regs)
{
@@ -270,6 +298,10 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
return;
+ if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs),
+ "Ignoring spurious kernel translation fault at virtual address %016lx\n", addr))
+ return;
+
if (is_el1_permission_fault(addr, esr, regs)) {
if (esr & ESR_ELx_WNR)
msg = "write to read-only memory";
@@ -777,6 +809,53 @@ void __init hook_debug_fault_code(int nr,
debug_fault_info[nr].name = name;
}
+/*
+ * In debug exception context, we explicitly disable preemption despite
+ * having interrupts disabled.
+ * This serves two purposes: it makes it much less likely that we would
+ * accidentally schedule in exception context and it will force a warning
+ * if we somehow manage to schedule by accident.
+ */
+static void debug_exception_enter(struct pt_regs *regs)
+{
+ /*
+ * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
+ * already disabled to preserve the last enabled/disabled addresses.
+ */
+ if (interrupts_enabled(regs))
+ trace_hardirqs_off();
+
+ if (user_mode(regs)) {
+ RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
+ } else {
+ /*
+ * We might have interrupted pretty much anything. In
+ * fact, if we're a debug exception, we can even interrupt
+ * NMI processing. We don't want this code makes in_nmi()
+ * to return true, but we need to notify RCU.
+ */
+ rcu_nmi_enter();
+ }
+
+ preempt_disable();
+
+ /* This code is a bit fragile. Test it. */
+ RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
+}
+NOKPROBE_SYMBOL(debug_exception_enter);
+
+static void debug_exception_exit(struct pt_regs *regs)
+{
+ preempt_enable_no_resched();
+
+ if (!user_mode(regs))
+ rcu_nmi_exit();
+
+ if (interrupts_enabled(regs))
+ trace_hardirqs_on();
+}
+NOKPROBE_SYMBOL(debug_exception_exit);
+
#ifdef CONFIG_ARM64_ERRATUM_1463225
DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa);
@@ -817,12 +896,7 @@ asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint,
if (cortex_a76_erratum_1463225_debug_handler(regs))
return;
- /*
- * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
- * already disabled to preserve the last enabled/disabled addresses.
- */
- if (interrupts_enabled(regs))
- trace_hardirqs_off();
+ debug_exception_enter(regs);
if (user_mode(regs) && !is_ttbr0_addr(pc))
arm64_apply_bp_hardening();
@@ -832,7 +906,6 @@ asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint,
inf->sig, inf->code, (void __user *)pc, esr);
}
- if (interrupts_enabled(regs))
- trace_hardirqs_on();
+ debug_exception_exit(regs);
}
NOKPROBE_SYMBOL(do_debug_exception);
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3c795278def..45c00a54909c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -50,6 +50,12 @@
s64 memstart_addr __ro_after_init = -1;
EXPORT_SYMBOL(memstart_addr);
+s64 physvirt_offset __ro_after_init;
+EXPORT_SYMBOL(physvirt_offset);
+
+struct page *vmemmap __ro_after_init;
+EXPORT_SYMBOL(vmemmap);
+
phys_addr_t arm64_dma_phys_limit __ro_after_init;
#ifdef CONFIG_KEXEC_CORE
@@ -301,7 +307,7 @@ static void __init fdt_enforce_memory_region(void)
void __init arm64_memblock_init(void)
{
- const s64 linear_region_size = -(s64)PAGE_OFFSET;
+ const s64 linear_region_size = BIT(vabits_actual - 1);
/* Handle linux,usable-memory-range property */
fdt_enforce_memory_region();
@@ -310,18 +316,25 @@ void __init arm64_memblock_init(void)
memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX);
/*
- * Ensure that the linear region takes up exactly half of the kernel
- * virtual address space. This way, we can distinguish a linear address
- * from a kernel/module/vmalloc address by testing a single bit.
- */
- BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1));
-
- /*
* Select a suitable value for the base of physical memory.
*/
memstart_addr = round_down(memblock_start_of_DRAM(),
ARM64_MEMSTART_ALIGN);
+ physvirt_offset = PHYS_OFFSET - PAGE_OFFSET;
+
+ vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT));
+
+ /*
+ * If we are running with a 52-bit kernel VA config on a system that
+ * does not support it, we have to offset our vmemmap and physvirt_offset
+ * s.t. we avoid the 52-bit portion of the direct linear map
+ */
+ if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) {
+ vmemmap += (_PAGE_OFFSET(48) - _PAGE_OFFSET(52)) >> PAGE_SHIFT;
+ physvirt_offset = PHYS_OFFSET - _PAGE_OFFSET(48);
+ }
+
/*
* Remove the memory that we will not be able to cover with the
* linear mapping. Take care not to clip the kernel which may be
@@ -570,8 +583,12 @@ void free_initmem(void)
#ifdef CONFIG_BLK_DEV_INITRD
void __init free_initrd_mem(unsigned long start, unsigned long end)
{
+ unsigned long aligned_start, aligned_end;
+
+ aligned_start = __virt_to_phys(start) & PAGE_MASK;
+ aligned_end = PAGE_ALIGN(__virt_to_phys(end));
+ memblock_free(aligned_start, aligned_end - aligned_start);
free_reserved_area((void *)start, (void *)end, 0, "initrd");
- memblock_free(__virt_to_phys(start), end - start);
}
#endif
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index fdb595a5d65f..9be71bee902c 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -69,7 +69,7 @@ void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot)
}
EXPORT_SYMBOL(__ioremap);
-void __iounmap(volatile void __iomem *io_addr)
+void iounmap(volatile void __iomem *io_addr)
{
unsigned long addr = (unsigned long)io_addr & PAGE_MASK;
@@ -80,7 +80,7 @@ void __iounmap(volatile void __iomem *io_addr)
if (is_vmalloc_addr((void *)addr))
vunmap((void *)addr);
}
-EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(iounmap);
void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
{
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 6cf97b904ebb..f87a32484ea8 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -156,7 +156,8 @@ asmlinkage void __init kasan_early_init(void)
{
BUILD_BUG_ON(KASAN_SHADOW_OFFSET !=
KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT)));
- BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE));
+ BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS), PGDIR_SIZE));
+ BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS_MIN), PGDIR_SIZE));
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE));
kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE,
true);
@@ -225,10 +226,10 @@ void __init kasan_init(void)
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
early_pfn_to_nid(virt_to_pfn(lm_alias(_text))));
- kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
- (void *)mod_shadow_start);
+ kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
+ (void *)mod_shadow_start);
kasan_populate_early_shadow((void *)kimg_shadow_end,
- kasan_mem_to_shadow((void *)PAGE_OFFSET));
+ (void *)KASAN_SHADOW_END);
if (kimg_shadow_start > mod_shadow_end)
kasan_populate_early_shadow((void *)mod_shadow_end,
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 750a69dde39b..53dc6f24cfb7 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -40,8 +40,9 @@
u64 idmap_t0sz = TCR_T0SZ(VA_BITS);
u64 idmap_ptrs_per_pgd = PTRS_PER_PGD;
-u64 vabits_user __ro_after_init;
-EXPORT_SYMBOL(vabits_user);
+
+u64 __section(".mmuoff.data.write") vabits_actual;
+EXPORT_SYMBOL(vabits_actual);
u64 kimage_voffset __ro_after_init;
EXPORT_SYMBOL(kimage_voffset);
@@ -398,7 +399,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
phys_addr_t size, pgprot_t prot)
{
- if (virt < VMALLOC_START) {
+ if ((virt >= PAGE_END) && (virt < VMALLOC_START)) {
pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
&phys, virt);
return;
@@ -425,7 +426,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
static void update_mapping_prot(phys_addr_t phys, unsigned long virt,
phys_addr_t size, pgprot_t prot)
{
- if (virt < VMALLOC_START) {
+ if ((virt >= PAGE_END) && (virt < VMALLOC_START)) {
pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n",
&phys, virt);
return;
@@ -646,6 +647,8 @@ static void __init map_kernel(pgd_t *pgdp)
set_pgd(pgd_offset_raw(pgdp, FIXADDR_START),
READ_ONCE(*pgd_offset_k(FIXADDR_START)));
} else if (CONFIG_PGTABLE_LEVELS > 3) {
+ pgd_t *bm_pgdp;
+ pud_t *bm_pudp;
/*
* The fixmap shares its top level pgd entry with the kernel
* mapping. This can really only occur when we are running
@@ -653,9 +656,9 @@ static void __init map_kernel(pgd_t *pgdp)
* entry instead.
*/
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
- pud_populate(&init_mm,
- pud_set_fixmap_offset(pgdp, FIXADDR_START),
- lm_alias(bm_pmd));
+ bm_pgdp = pgd_offset_raw(pgdp, FIXADDR_START);
+ bm_pudp = pud_set_fixmap_offset(bm_pgdp, FIXADDR_START);
+ pud_populate(&init_mm, bm_pudp, lm_alias(bm_pmd));
pud_clear_fixmap();
} else {
BUG();
@@ -876,7 +879,7 @@ void __set_fixmap(enum fixed_addresses idx,
}
}
-void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
+void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
{
const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
int offset;
@@ -929,19 +932,6 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
return dt_virt;
}
-void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
-{
- void *dt_virt;
- int size;
-
- dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);
- if (!dt_virt)
- return NULL;
-
- memblock_reserve(dt_phys, size);
- return dt_virt;
-}
-
int __init arch_ioremap_p4d_supported(void)
{
return 0;
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 4f241cc7cc3b..4decf1659700 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -29,7 +29,7 @@ static __init int numa_parse_early_param(char *opt)
{
if (!opt)
return -EINVAL;
- if (!strncmp(opt, "off", 3))
+ if (str_has_prefix(opt, "off"))
numa_off = true;
return 0;
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 03c53f16ee77..9ce7bd9d4d9c 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -128,7 +128,6 @@ int set_memory_nx(unsigned long addr, int numpages)
__pgprot(PTE_PXN),
__pgprot(0));
}
-EXPORT_SYMBOL_GPL(set_memory_nx);
int set_memory_x(unsigned long addr, int numpages)
{
@@ -136,7 +135,6 @@ int set_memory_x(unsigned long addr, int numpages)
__pgprot(0),
__pgprot(PTE_PXN));
}
-EXPORT_SYMBOL_GPL(set_memory_x);
int set_memory_valid(unsigned long addr, int numpages, int enable)
{
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 7dbf2be470f6..a1e0592d1fbc 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -168,7 +168,7 @@ ENDPROC(cpu_do_switch_mm)
.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
adrp \tmp1, empty_zero_page
phys_to_ttbr \tmp2, \tmp1
- offset_ttbr1 \tmp2
+ offset_ttbr1 \tmp2, \tmp1
msr ttbr1_el1, \tmp2
isb
tlbi vmalle1
@@ -187,7 +187,7 @@ ENTRY(idmap_cpu_replace_ttbr1)
__idmap_cpu_set_reserved_ttbr1 x1, x3
- offset_ttbr1 x0
+ offset_ttbr1 x0, x3
msr ttbr1_el1, x0
isb
@@ -286,6 +286,15 @@ skip_pgd:
msr sctlr_el1, x18
isb
+ /*
+ * Invalidate the local I-cache so that any instructions fetched
+ * speculatively from the PoC are discarded, since they may have
+ * been dynamically patched at the PoU.
+ */
+ ic iallu
+ dsb nsh
+ isb
+
/* Set the flag to zero to indicate that we're all done */
str wzr, [flag_ptr]
ret
@@ -362,7 +371,7 @@ __idmap_kpti_secondary:
cbnz w18, 1b
/* All done, act like nothing happened */
- offset_ttbr1 swapper_ttb
+ offset_ttbr1 swapper_ttb, x18
msr ttbr1_el1, swapper_ttb
isb
ret
@@ -438,10 +447,11 @@ ENTRY(__cpu_setup)
TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS
tcr_clear_errata_bits x10, x9, x5
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
- ldr_l x9, vabits_user
+#ifdef CONFIG_ARM64_VA_BITS_52
+ ldr_l x9, vabits_actual
sub x9, xzr, x9
add x9, x9, #64
+ tcr_set_t1sz x10, x9
#else
ldr_l x9, idmap_t0sz
#endif
diff --git a/arch/csky/include/uapi/asm/byteorder.h b/arch/csky/include/uapi/asm/byteorder.h
index b079ec715cdf..d150cd664873 100644
--- a/arch/csky/include/uapi/asm/byteorder.h
+++ b/arch/csky/include/uapi/asm/byteorder.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#ifndef __ASM_CSKY_BYTEORDER_H
diff --git a/arch/csky/include/uapi/asm/cachectl.h b/arch/csky/include/uapi/asm/cachectl.h
index ddf2f39aa925..ed7fad1ea20d 100644
--- a/arch/csky/include/uapi/asm/cachectl.h
+++ b/arch/csky/include/uapi/asm/cachectl.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __ASM_CSKY_CACHECTL_H
#define __ASM_CSKY_CACHECTL_H
diff --git a/arch/csky/include/uapi/asm/perf_regs.h b/arch/csky/include/uapi/asm/perf_regs.h
index ee323d818592..49d4e147a559 100644
--- a/arch/csky/include/uapi/asm/perf_regs.h
+++ b/arch/csky/include/uapi/asm/perf_regs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
#ifndef _ASM_CSKY_PERF_REGS_H
diff --git a/arch/csky/include/uapi/asm/ptrace.h b/arch/csky/include/uapi/asm/ptrace.h
index 4e248d5b86ef..66b2268e324e 100644
--- a/arch/csky/include/uapi/asm/ptrace.h
+++ b/arch/csky/include/uapi/asm/ptrace.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#ifndef _CSKY_PTRACE_H
diff --git a/arch/csky/include/uapi/asm/sigcontext.h b/arch/csky/include/uapi/asm/sigcontext.h
index e81e7ff11e36..670c020f2cb8 100644
--- a/arch/csky/include/uapi/asm/sigcontext.h
+++ b/arch/csky/include/uapi/asm/sigcontext.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#ifndef __ASM_CSKY_SIGCONTEXT_H
diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h
index ec60e49cea66..211c983c7282 100644
--- a/arch/csky/include/uapi/asm/unistd.h
+++ b/arch/csky/include/uapi/asm/unistd.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 7468d8e50467..9711cf730929 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -10,12 +10,14 @@ config IA64
bool
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
- select ACPI if (!IA64_HP_SIM)
- select ARCH_SUPPORTS_ACPI if (!IA64_HP_SIM)
+ select ACPI
+ select ACPI_NUMA if NUMA
+ select ARCH_SUPPORTS_ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
- select FORCE_PCI if (!IA64_HP_SIM)
+ select FORCE_PCI
select PCI_DOMAINS if PCI
+ select PCI_MSI
select PCI_SYSCALL if PCI
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_EXIT_THREAD
@@ -30,8 +32,8 @@ config IA64
select HAVE_ARCH_TRACEHOOK
select HAVE_MEMBLOCK_NODE_MAP
select HAVE_VIRT_CPU_ACCOUNTING
- select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
- select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
+ select ARCH_HAS_DMA_COHERENT_TO_PFN
+ select ARCH_HAS_SYNC_DMA_FOR_CPU
select VIRT_TO_BUS
select GENERIC_IRQ_PROBE
select GENERIC_PENDING_IRQ if SMP
@@ -45,6 +47,7 @@ config IA64
select ARCH_THREAD_STACK_ALLOCATOR
select ARCH_CLOCKSOURCE_DATA
select GENERIC_TIME_VSYSCALL
+ select SWIOTLB
select SYSCTL_ARCH_UNALIGN_NO_WARN
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
@@ -52,6 +55,7 @@ config IA64
select HAVE_ARCH_AUDITSYSCALL
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
+ select NUMA if !FLATMEM
default y
help
The Itanium Processor Family is Intel's 64-bit successor to
@@ -66,7 +70,6 @@ config 64BIT
config ZONE_DMA32
def_bool y
- depends on !IA64_SGI_SN2
config QUICKLIST
bool
@@ -121,87 +124,6 @@ config AUDIT_ARCH
default y
choice
- prompt "System type"
- default IA64_GENERIC
-
-config IA64_GENERIC
- bool "generic"
- select NUMA
- select ACPI_NUMA
- select SWIOTLB
- select PCI_MSI
- help
- This selects the system type of your hardware. A "generic" kernel
- will run on any supported IA-64 system. However, if you configure
- a kernel for your specific system, it will be faster and smaller.
-
- generic For any supported IA-64 system
- DIG-compliant For DIG ("Developer's Interface Guide") compliant systems
- DIG+Intel+IOMMU For DIG systems with Intel IOMMU
- HP-zx1/sx1000 For HP systems
- HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices.
- SGI-SN2 For SGI Altix systems
- SGI-UV For SGI UV systems
- Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/>
-
- If you don't know what to do, choose "generic".
-
-config IA64_DIG
- bool "DIG-compliant"
- select SWIOTLB
-
-config IA64_DIG_VTD
- bool "DIG+Intel+IOMMU"
- select INTEL_IOMMU
- select PCI_MSI
-
-config IA64_HP_ZX1
- bool "HP-zx1/sx1000"
- help
- Build a kernel that runs on HP zx1 and sx1000 systems. This adds
- support for the HP I/O MMU.
-
-config IA64_HP_ZX1_SWIOTLB
- bool "HP-zx1/sx1000 with software I/O TLB"
- select SWIOTLB
- help
- Build a kernel that runs on HP zx1 and sx1000 systems even when they
- have broken PCI devices which cannot DMA to full 32 bits. Apart
- from support for the HP I/O MMU, this includes support for the software
- I/O TLB, which allows supporting the broken devices at the expense of
- wasting some kernel memory (about 2MB by default).
-
-config IA64_SGI_SN2
- bool "SGI-SN2"
- select NUMA
- select ACPI_NUMA
- help
- Selecting this option will optimize the kernel for use on sn2 based
- systems, but the resulting kernel binary will not run on other
- types of ia64 systems. If you have an SGI Altix system, it's safe
- to select this option. If in doubt, select ia64 generic support
- instead.
-
-config IA64_SGI_UV
- bool "SGI-UV"
- select NUMA
- select ACPI_NUMA
- select SWIOTLB
- help
- Selecting this option will optimize the kernel for use on UV based
- systems, but the resulting kernel binary will not run on other
- types of ia64 systems. If you have an SGI UV system, it's safe
- to select this option. If in doubt, select ia64 generic support
- instead.
-
-config IA64_HP_SIM
- bool "Ski-simulator"
- select SWIOTLB
- depends on !PM
-
-endchoice
-
-choice
prompt "Processor type"
default ITANIUM
@@ -252,14 +174,7 @@ config IA64_PAGE_SIZE_64KB
endchoice
-if IA64_HP_SIM
-config HZ
- default 32
-endif
-
-if !IA64_HP_SIM
source "kernel/Kconfig.hz"
-endif
config IA64_BRL_EMU
bool
@@ -272,17 +187,26 @@ config IA64_L1_CACHE_SHIFT
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"
+ 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 IOSAPIC
- bool
- depends on !IA64_HP_SIM
- default y
-
config FORCE_MAX_ZONEORDER
int "MAX_ORDER (11 - 17)" if !HUGETLB_PAGE
range 11 17 if !HUGETLB_PAGE
@@ -381,14 +305,13 @@ config ARCH_SPARSEMEM_ENABLE
select SPARSEMEM_VMEMMAP_ENABLE
config ARCH_DISCONTIGMEM_DEFAULT
- def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB)
+ def_bool y
depends on ARCH_DISCONTIGMEM_ENABLE
config NUMA
bool "NUMA support"
- depends on !IA64_HP_SIM && !FLATMEM
- default y if IA64_SGI_SN2
- select ACPI_NUMA if ACPI
+ depends on !FLATMEM
+ select SMP
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
Access). This option is for configuring high-end multiprocessor
@@ -409,7 +332,7 @@ config NODES_SHIFT
config VIRTUAL_MEM_MAP
bool "Virtual mem map"
depends on !SPARSEMEM
- default y if !IA64_HP_SIM
+ default y
help
Say Y to compile the kernel with support for a virtual mem map.
This code also only takes effect if a memory hole of greater than
@@ -472,9 +395,6 @@ config IA64_MC_ERR_INJECT
If you're unsure, do not select this option.
-config SGI_SN
- def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
-
config IA64_ESI
bool "ESI (Extensible SAL Interface) support"
help
@@ -493,11 +413,9 @@ config IA64_HP_AML_NFW
the "force" module parameter, e.g., with the "aml_nfw.force"
kernel command line option.
-source "drivers/sn/Kconfig"
-
config KEXEC
bool "kexec system call"
- depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+ depends on !SMP || HOTPLUG_CPU
select KEXEC_CORE
help
kexec is a system call that implements the ability to shutdown your
@@ -515,7 +433,7 @@ config KEXEC
config CRASH_DUMP
bool "kernel crash dumps"
- depends on IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+ depends on IA64_MCA_RECOVERY && (!SMP || HOTPLUG_CPU)
help
Generate crash dump after being started by kexec.
@@ -537,8 +455,6 @@ endif
endmenu
-source "arch/ia64/hp/sim/Kconfig"
-
config MSPEC
tristate "Memory special operations driver"
depends on IA64
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index 1371efc9b005..40ca23bd228d 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -14,7 +14,7 @@ config IA64_GRANULE_16MB
config IA64_GRANULE_64MB
bool "64MB"
- depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_SGI_SN2)
+ depends on BROKEN
endchoice
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 171290f9f1de..e0bb2b6aaa35 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -39,29 +39,23 @@ $(error Sorry, you need a newer version of the assember, one that is built from
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
endif
+quiet_cmd_gzip = GZIP $@
+cmd_gzip = cat $(real-prereqs) | gzip -n -f -9 > $@
+
+quiet_cmd_objcopy = OBJCOPY $@
+cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
+
KBUILD_CFLAGS += $(cflags-y)
head-y := arch/ia64/kernel/head.o
libs-y += arch/ia64/lib/
core-y += arch/ia64/kernel/ arch/ia64/mm/
-core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
-core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/
-core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
-core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
-core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
-core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/
-drivers-$(CONFIG_PCI) += arch/ia64/pci/
-drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
-drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ arch/ia64/uv/
+drivers-y += arch/ia64/pci/ arch/ia64/hp/common/
drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/
-boot := arch/ia64/hp/sim/boot
-
-PHONY += boot compressed check
+PHONY += compressed check
all: compressed unwcheck
@@ -69,22 +63,21 @@ compressed: vmlinux.gz
vmlinuz: vmlinux.gz
-vmlinux.gz: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) $@
+vmlinux.gz: vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
unwcheck: vmlinux
-$(Q)READELF=$(READELF) $(PYTHON) $(srctree)/arch/ia64/scripts/unwcheck.py $<
archclean:
- $(Q)$(MAKE) $(clean)=$(boot)
archheaders:
$(Q)$(MAKE) $(build)=arch/ia64/kernel/syscalls all
-CLEAN_FILES += vmlinux.gz bootloader
-
-boot: lib/lib.a vmlinux
- $(Q)$(MAKE) $(build)=$(boot) $@
+CLEAN_FILES += vmlinux.gz
install: vmlinux.gz
sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
@@ -92,7 +85,6 @@ install: vmlinux.gz
define archhelp
echo '* compressed - Build compressed kernel image'
echo ' install - Install compressed kernel image'
- echo ' boot - Build vmlinux and bootloader for Ski simulator'
echo '* unwcheck - Check vmlinux for invalid unwind info'
endef
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index b6bda1838629..b630bd7351c4 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -7,7 +7,6 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_SGI_PARTITION=y
-CONFIG_IA64_DIG=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 81f686dee53c..661d90b3e148 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -44,14 +44,12 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_SGI_IOC4=y
CONFIG_SGI_XP=m
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_GENERIC=y
CONFIG_BLK_DEV_CMD64X=y
CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_SGIIOC4=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
@@ -90,16 +88,11 @@ CONFIG_IGB=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_GAMEPORT=m
CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SGI_SNSC=y
-CONFIG_SGI_TIOCX=y
-CONFIG_SGI_MBCS=m
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_SERIAL_SGI_L1_CONSOLE=y
-CONFIG_SERIAL_SGI_IOC4=y
# CONFIG_HW_RANDOM is not set
CONFIG_EFI_RTC=y
CONFIG_RAW_DRIVER=m
@@ -107,7 +100,6 @@ CONFIG_HPET=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
CONFIG_AGP_HP_ZX1=m
-CONFIG_AGP_SGI_TIOCA=m
CONFIG_DRM=m
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 5b4fcdd51457..7844e6a956a4 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -19,7 +19,6 @@ CONFIG_SPARSEMEM_MANUAL=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
-CONFIG_SGI_IOC3=y
CONFIG_EFI_VARS=y
CONFIG_BINFMT_MISC=m
CONFIG_ACPI_BUTTON=m
@@ -37,14 +36,12 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_SGI_IOC4=y
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_GENERIC=y
CONFIG_BLK_DEV_CMD64X=y
CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_SGIIOC4=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
@@ -79,17 +76,11 @@ CONFIG_E1000=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_GAMEPORT=m
CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SGI_SNSC=y
-CONFIG_SGI_TIOCX=y
-CONFIG_SGI_MBCS=m
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_SERIAL_SGI_L1_CONSOLE=y
-CONFIG_SERIAL_SGI_IOC4=y
-CONFIG_SERIAL_SGI_IOC3=y
# CONFIG_HW_RANDOM is not set
CONFIG_EFI_RTC=y
CONFIG_RAW_DRIVER=m
@@ -97,7 +88,6 @@ CONFIG_HPET=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
CONFIG_AGP_HP_ZX1=m
-CONFIG_AGP_SGI_TIOCA=m
CONFIG_DRM=m
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
diff --git a/arch/ia64/configs/sim_defconfig b/arch/ia64/configs/sim_defconfig
deleted file mode 100644
index f0f69fdbddae..000000000000
--- a/arch/ia64/configs/sim_defconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_IA64_HP_SIM=y
-CONFIG_MCKINLEY=y
-CONFIG_IA64_PAGE_SIZE_64KB=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=64
-CONFIG_PREEMPT=y
-CONFIG_IA64_PALINFO=m
-CONFIG_EFI_VARS=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IPV6 is not set
-# CONFIG_STANDALONE is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_EFI_RTC=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_HP_SIMETH=y
-CONFIG_HP_SIMSERIAL=y
-CONFIG_HP_SIMSERIAL_CONSOLE=y
-CONFIG_HP_SIMSCSI=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_PROC_KCORE=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 192ed157c9ce..1d6e2a01452b 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -12,7 +12,6 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_SGI_PARTITION=y
-CONFIG_IA64_DIG=y
CONFIG_MCKINLEY=y
CONFIG_IA64_PAGE_SIZE_64KB=y
CONFIG_IA64_CYCLONE=y
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index b504c8e2fd52..8c92e095f8bb 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -4,7 +4,6 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_PARTITION_ADVANCED=y
-CONFIG_IA64_HP_ZX1=y
CONFIG_MCKINLEY=y
CONFIG_SMP=y
CONFIG_NR_CPUS=16
diff --git a/arch/ia64/dig/Makefile b/arch/ia64/dig/Makefile
deleted file mode 100644
index e7f830825470..000000000000
--- a/arch/ia64/dig/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# ia64/platform/dig/Makefile
-#
-# Copyright (C) 1999 Silicon Graphics, Inc.
-# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
-#
-
-obj-y := setup.o
-ifeq ($(CONFIG_INTEL_IOMMU), y)
-obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o
-else
-obj-$(CONFIG_IA64_GENERIC) += machvec.o
-endif
-
diff --git a/arch/ia64/dig/machvec.c b/arch/ia64/dig/machvec.c
deleted file mode 100644
index 0c55bdafb473..000000000000
--- a/arch/ia64/dig/machvec.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACHVEC_PLATFORM_NAME dig
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/dig/machvec_vtd.c b/arch/ia64/dig/machvec_vtd.c
deleted file mode 100644
index 7cd3eb471cad..000000000000
--- a/arch/ia64/dig/machvec_vtd.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACHVEC_PLATFORM_NAME dig_vtd
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c
deleted file mode 100644
index cc14fdce6db6..000000000000
--- a/arch/ia64/dig/setup.c
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Platform dependent support for DIG64 platforms.
- *
- * Copyright (C) 1999 Intel Corp.
- * Copyright (C) 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/string.h>
-#include <linux/screen_info.h>
-#include <linux/console.h>
-#include <linux/timex.h>
-#include <linux/sched.h>
-#include <linux/root_dev.h>
-
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/setup.h>
-
-void __init
-dig_setup (char **cmdline_p)
-{
- unsigned int orig_x, orig_y, num_cols, num_rows, font_height;
-
- /*
- * 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 = Root_SDA2; /* default to second partition on first drive */
-
-#ifdef CONFIG_SMP
- init_smp_config();
-#endif
-
- 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 "dig_setup: 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 */
-}
diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile
index 6026308f9a62..11a56ed38229 100644
--- a/arch/ia64/hp/common/Makefile
+++ b/arch/ia64/hp/common/Makefile
@@ -6,7 +6,5 @@
# Copyright (C) Alex Williamson (alex_williamson@hp.com)
#
-obj-y := sba_iommu.o
-obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += hwsw_iommu.o
-obj-$(CONFIG_IA64_GENERIC) += hwsw_iommu.o
+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/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
deleted file mode 100644
index 8840ed97712f..000000000000
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
- * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * This is a pseudo I/O MMU which dispatches to the hardware I/O MMU
- * whenever possible. We assume that the hardware I/O MMU requires
- * full 32-bit addressability, as is the case, e.g., for HP zx1-based
- * systems (there, the I/O MMU window is mapped at 3-4GB). If a
- * device doesn't provide full 32-bit addressability, we fall back on
- * the sw I/O TLB. This is good enough to let us support broken
- * hardware such as soundcards which have a DMA engine that can
- * address only 28 bits.
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/swiotlb.h>
-#include <linux/export.h>
-#include <asm/machvec.h>
-
-extern const struct dma_map_ops sba_dma_ops;
-
-/* swiotlb declarations & definitions: */
-extern int swiotlb_late_init_with_default_size (size_t size);
-
-/*
- * Note: we need to make the determination of whether or not to use
- * the sw I/O TLB based purely on the device structure. Anything else
- * would be unreliable or would be too intrusive.
- */
-static inline int use_swiotlb(struct device *dev)
-{
- return dev && dev->dma_mask &&
- !sba_dma_ops.dma_supported(dev, *dev->dma_mask);
-}
-
-const struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
-{
- if (use_swiotlb(dev))
- return NULL;
- return &sba_dma_ops;
-}
-EXPORT_SYMBOL(hwsw_dma_get_ops);
-
-void __init
-hwsw_init (void)
-{
- /* default to a smallish 2MB sw I/O TLB */
- if (swiotlb_late_init_with_default_size (2 * (1<<20)) != 0) {
-#ifdef CONFIG_IA64_GENERIC
- /* Better to have normal DMA than panic */
- printk(KERN_WARNING "%s: Failed to initialize software I/O TLB,"
- " reverting to hpzx1 platform vector\n", __func__);
- machvec_init("hpzx1");
-#else
- panic("Unable to initialize software I/O TLB services");
-#endif
- }
-}
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 3d24cc43385b..a7eff5e6d260 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -35,6 +35,7 @@
#include <linux/iommu-helper.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
+#include <linux/swiotlb.h>
#include <asm/delay.h> /* ia64_get_itc() */
#include <asm/io.h>
@@ -43,8 +44,6 @@
#include <asm/acpi-ext.h>
-extern int swiotlb_late_init_with_default_size (size_t size);
-
#define PFX "IOC: "
/*
@@ -251,12 +250,8 @@ static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t);
static u64 prefetch_spill_page;
#endif
-#ifdef CONFIG_PCI
-# define GET_IOC(dev) ((dev_is_pci(dev)) \
+#define GET_IOC(dev) ((dev_is_pci(dev)) \
? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL)
-#else
-# define GET_IOC(dev) NULL
-#endif
/*
** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
@@ -1741,9 +1736,7 @@ ioc_sac_init(struct ioc *ioc)
controller->iommu = ioc;
sac->sysdata = controller;
sac->dma_mask = 0xFFFFFFFFUL;
-#ifdef CONFIG_PCI
sac->dev.bus = &pci_bus_type;
-#endif
ioc->sac_only_dev = sac;
}
@@ -2062,27 +2055,33 @@ static int __init acpi_sba_ioc_init_acpi(void)
/* 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,
+};
+
static int __init
sba_init(void)
{
- if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
- return 0;
-
-#if defined(CONFIG_IA64_GENERIC)
- /* 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 the swiotlb.
+ /*
+ * 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()) {
- dma_ops = NULL;
- if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
- panic("Unable to initialize software I/O TLB:"
- " Try machvec=dig boot option");
- machvec_init("dig");
+ if (is_kdump_kernel())
return 0;
- }
-#endif
/*
* ioc_found should be populated by the acpi_sba_ioc_handler's .attach()
@@ -2091,43 +2090,18 @@ sba_init(void)
while (ioc_found)
acpi_sba_ioc_add(ioc_found);
- if (!ioc_list) {
-#ifdef CONFIG_IA64_GENERIC
- /*
- * If we didn't find something sba_iommu can claim, we
- * need to setup the swiotlb and switch to the dig machvec.
- */
- dma_ops = NULL;
- if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
- panic("Unable to find SBA IOMMU or initialize "
- "software I/O TLB: Try machvec=dig boot option");
- machvec_init("dig");
-#else
- panic("Unable to find SBA IOMMU: Try a generic or DIG kernel");
-#endif
+ if (!ioc_list)
return 0;
- }
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
- /*
- * hpzx1_swiotlb needs to have a fairly small swiotlb bounce
- * buffer setup to support devices with smaller DMA masks than
- * sba_iommu can handle.
- */
- if (ia64_platform_is("hpzx1_swiotlb")) {
- extern void hwsw_init(void);
-
- hwsw_init();
- }
-#endif
-
-#ifdef CONFIG_PCI
{
struct pci_bus *b = NULL;
while ((b = pci_find_next_bus(b)) != NULL)
sba_connect_bus(b);
}
-#endif
+
+ /* no need for swiotlb with the iommu */
+ swiotlb_exit();
+ dma_ops = &sba_dma_ops;
#ifdef CONFIG_PROC_FS
ioc_proc_init();
@@ -2144,12 +2118,6 @@ nosbagart(char *str)
return 1;
}
-static int sba_dma_supported (struct device *dev, u64 mask)
-{
- /* make sure it's at least 32bit capable */
- return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL);
-}
-
__setup("nosbagart", nosbagart);
static int __init
@@ -2174,18 +2142,3 @@ sba_page_override(char *str)
}
__setup("sbapagesize=",sba_page_override);
-
-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,
-};
-
-void sba_dma_init(void)
-{
- dma_ops = &sba_dma_ops;
-}
diff --git a/arch/ia64/hp/sim/Kconfig b/arch/ia64/hp/sim/Kconfig
deleted file mode 100644
index 56fb4f1d4f7c..000000000000
--- a/arch/ia64/hp/sim/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-menu "HP Simulator drivers"
- depends on IA64_HP_SIM || IA64_GENERIC
-
-config HP_SIMETH
- bool "Simulated Ethernet "
- depends on NET
-
-config HP_SIMSERIAL
- bool "Simulated serial driver support"
- depends on TTY
-
-config HP_SIMSERIAL_CONSOLE
- bool "Console for HP simulator"
- depends on HP_SIMSERIAL
-
-config HP_SIMSCSI
- bool "Simulated SCSI disk"
- depends on SCSI=y
-
-endmenu
-
diff --git a/arch/ia64/hp/sim/Makefile b/arch/ia64/hp/sim/Makefile
deleted file mode 100644
index 0224a13d2c5b..000000000000
--- a/arch/ia64/hp/sim/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# ia64/platform/hp/sim/Makefile
-#
-# Copyright (C) 2002 Hewlett-Packard Co.
-# David Mosberger-Tang <davidm@hpl.hp.com>
-# Copyright (C) 1999 Silicon Graphics, Inc.
-# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
-#
-
-obj-y := hpsim_irq.o hpsim_setup.o hpsim.o
-obj-$(CONFIG_IA64_GENERIC) += hpsim_machvec.o
-
-obj-$(CONFIG_HP_SIMETH) += simeth.o
-obj-$(CONFIG_HP_SIMSERIAL) += simserial.o
-obj-$(CONFIG_HP_SIMSERIAL_CONSOLE) += hpsim_console.o
-obj-$(CONFIG_HP_SIMSCSI) += simscsi.o
diff --git a/arch/ia64/hp/sim/boot/Makefile b/arch/ia64/hp/sim/boot/Makefile
deleted file mode 100644
index df6e9968c845..000000000000
--- a/arch/ia64/hp/sim/boot/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# ia64/boot/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) 1998, 2003 by David Mosberger-Tang <davidm@hpl.hp.com>
-#
-
-targets-$(CONFIG_IA64_HP_SIM) += bootloader
-targets := vmlinux.bin vmlinux.gz $(targets-y)
-
-quiet_cmd_cptotop = LN $@
- cmd_cptotop = ln -f $< $@
-
-vmlinux.gz: $(obj)/vmlinux.gz $(addprefix $(obj)/,$(targets-y))
- $(call cmd,cptotop)
- @echo ' Kernel: $@ is ready'
-
-boot: bootloader
-
-bootloader: $(obj)/bootloader
- $(call cmd,cptotop)
-
-$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,gzip)
-
-$(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
-
-
-LDFLAGS_bootloader = -static -T
-
-$(obj)/bootloader: $(src)/bootloader.lds $(obj)/bootloader.o $(obj)/boot_head.o $(obj)/fw-emu.o \
- lib/lib.a arch/ia64/lib/lib.a FORCE
- $(call if_changed,ld)
diff --git a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S
deleted file mode 100644
index a7d178fb41e8..000000000000
--- a/arch/ia64/hp/sim/boot/boot_head.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <asm/asmmacro.h>
-#include <asm/pal.h>
-
- .bss
- .align 16
-stack_mem:
- .skip 16834
-
- .text
-
-/* This needs to be defined because lib/string.c:strlcat() calls it in case of error... */
-GLOBAL_ENTRY(printk)
- break 0
-END(printk)
-
-GLOBAL_ENTRY(_start)
- .prologue
- .save rp, r0
- .body
- movl gp = __gp
- movl sp = stack_mem+16384-16
- bsw.1
- br.call.sptk.many rp=start_bootloader
-0: nop 0 /* dummy nop to make unwinding work */
-END(_start)
-
-/*
- * Set a break point on this function so that symbols are available to set breakpoints in
- * the kernel being debugged.
- */
-GLOBAL_ENTRY(debug_break)
- br.ret.sptk.many b0
-END(debug_break)
-
-GLOBAL_ENTRY(ssc)
- .regstk 5,0,0,0
- mov r15=in4
- break 0x80001
- br.ret.sptk.many b0
-END(ssc)
-
-GLOBAL_ENTRY(jmp_to_kernel)
- .regstk 2,0,0,0
- mov r28=in0
- mov b7=in1
- br.sptk.few b7
-END(jmp_to_kernel)
-
-/*
- * r28 contains the index of the PAL function
- * r29--31 the args
- * Return values in ret0--3 (r8--11)
- */
-GLOBAL_ENTRY(pal_emulator_static)
- mov r8=-1
- mov r9=256
- ;;
- cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */
-(p6) br.cond.sptk.few static
- ;;
- mov r9=512
- ;;
- cmp.gtu p6,p7=r9,r28
-(p6) br.cond.sptk.few stacked
- ;;
-static: cmp.eq p6,p7=PAL_PTCE_INFO,r28
-(p7) br.cond.sptk.few 1f
- ;;
- mov r8=0 /* status = 0 */
- movl r9=0x100000000 /* tc.base */
- movl r10=0x0000000200000003 /* count[0], count[1] */
- movl r11=0x1000000000002000 /* stride[0], stride[1] */
- br.cond.sptk.few rp
-1: cmp.eq p6,p7=PAL_FREQ_RATIOS,r28
-(p7) br.cond.sptk.few 1f
- mov r8=0 /* status = 0 */
- movl r9 =0x100000064 /* proc_ratio (1/100) */
- movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
- movl r11=0x100000064 /* itc_ratio<<32 (1/100) */
- ;;
-1: cmp.eq p6,p7=PAL_RSE_INFO,r28
-(p7) br.cond.sptk.few 1f
- mov r8=0 /* status = 0 */
- mov r9=96 /* num phys stacked */
- mov r10=0 /* hints */
- mov r11=0
- br.cond.sptk.few rp
-1: cmp.eq p6,p7=PAL_CACHE_FLUSH,r28 /* PAL_CACHE_FLUSH */
-(p7) br.cond.sptk.few 1f
- mov r9=ar.lc
- movl r8=524288 /* flush 512k million cache lines (16MB) */
- ;;
- mov ar.lc=r8
- movl r8=0xe000000000000000
- ;;
-.loop: fc r8
- add r8=32,r8
- br.cloop.sptk.few .loop
- sync.i
- ;;
- srlz.i
- ;;
- mov ar.lc=r9
- mov r8=r0
- ;;
-1: cmp.eq p6,p7=PAL_PERF_MON_INFO,r28
-(p7) br.cond.sptk.few 1f
- mov r8=0 /* status = 0 */
- movl r9 =0x08122f04 /* generic=4 width=47 retired=8 cycles=18 */
- mov r10=0 /* reserved */
- mov r11=0 /* reserved */
- mov r16=0xffff /* implemented PMC */
- mov r17=0x3ffff /* implemented PMD */
- add r18=8,r29 /* second index */
- ;;
- st8 [r29]=r16,16 /* store implemented PMC */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
- st8 [r29]=r0,16 /* clear remaining bits */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
- st8 [r29]=r17,16 /* store implemented PMD */
- st8 [r18]=r0,16 /* clear remaining bits */
- mov r16=0xf0 /* cycles count capable PMC */
- ;;
- st8 [r29]=r0,16 /* clear remaining bits */
- st8 [r18]=r0,16 /* clear remaining bits */
- mov r17=0xf0 /* retired bundles capable PMC */
- ;;
- st8 [r29]=r16,16 /* store cycles capable */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
- st8 [r29]=r0,16 /* clear remaining bits */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
- st8 [r29]=r17,16 /* store retired bundle capable */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
- st8 [r29]=r0,16 /* clear remaining bits */
- st8 [r18]=r0,16 /* clear remaining bits */
- ;;
-1: cmp.eq p6,p7=PAL_VM_SUMMARY,r28
-(p7) br.cond.sptk.few 1f
- mov r8=0 /* status = 0 */
- movl r9=0x2044040020F1865 /* num_tc_levels=2, num_unique_tcs=4 */
- /* max_itr_entry=64, max_dtr_entry=64 */
- /* hash_tag_id=2, max_pkr=15 */
- /* key_size=24, phys_add_size=50, vw=1 */
- movl r10=0x183C /* rid_size=24, impl_va_msb=60 */
- ;;
-1: cmp.eq p6,p7=PAL_MEM_ATTRIB,r28
-(p7) br.cond.sptk.few 1f
- mov r8=0 /* status = 0 */
- mov r9=0x80|0x01 /* NatPage|WB */
- ;;
-1: br.cond.sptk.few rp
-stacked:
- br.ret.sptk.few rp
-END(pal_emulator_static)
diff --git a/arch/ia64/hp/sim/boot/bootloader.c b/arch/ia64/hp/sim/boot/bootloader.c
deleted file mode 100644
index 6d804608dc81..000000000000
--- a/arch/ia64/hp/sim/boot/bootloader.c
+++ /dev/null
@@ -1,175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/ia64/hp/sim/boot/bootloader.c
- *
- * Loads an ELF kernel.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 01/07/99 S.Eranian modified to pass command line arguments to kernel
- */
-struct task_struct; /* forward declaration for elf.h */
-
-#include <linux/elf.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/elf.h>
-#include <asm/intrinsics.h>
-#include <asm/pal.h>
-#include <asm/pgtable.h>
-#include <asm/sal.h>
-
-#include "ssc.h"
-
-struct disk_req {
- unsigned long addr;
- unsigned len;
-};
-
-struct disk_stat {
- int fd;
- unsigned count;
-};
-
-extern void jmp_to_kernel (unsigned long bp, unsigned long e_entry);
-extern struct ia64_boot_param *sys_fw_init (const char *args, int arglen);
-extern void debug_break (void);
-
-static void
-cons_write (const char *buf)
-{
- unsigned long ch;
-
- while ((ch = *buf++) != '\0') {
- ssc(ch, 0, 0, 0, SSC_PUTCHAR);
- if (ch == '\n')
- ssc('\r', 0, 0, 0, SSC_PUTCHAR);
- }
-}
-
-#define MAX_ARGS 32
-
-void
-start_bootloader (void)
-{
- static char mem[4096];
- static char buffer[1024];
- unsigned long off;
- int fd, i;
- struct disk_req req;
- struct disk_stat stat;
- struct elfhdr *elf;
- struct elf_phdr *elf_phdr; /* program header */
- unsigned long e_entry, e_phoff, e_phnum;
- register struct ia64_boot_param *bp;
- char *kpath, *args;
- long arglen = 0;
-
- ssc(0, 0, 0, 0, SSC_CONSOLE_INIT);
-
- /*
- * S.Eranian: extract the commandline argument from the simulator
- *
- * The expected format is as follows:
- *
- * kernelname args...
- *
- * Both are optional but you can't have the second one without the first.
- */
- arglen = ssc((long) buffer, 0, 0, 0, SSC_GET_ARGS);
-
- kpath = "vmlinux";
- args = buffer;
- if (arglen > 0) {
- kpath = buffer;
- while (*args != ' ' && *args != '\0')
- ++args, --arglen;
- if (*args == ' ')
- *args++ = '\0', --arglen;
- }
-
- if (arglen <= 0) {
- args = "";
- arglen = 1;
- }
-
- fd = ssc((long) kpath, 1, 0, 0, SSC_OPEN);
-
- if (fd < 0) {
- cons_write(kpath);
- cons_write(": file not found, reboot now\n");
- for(;;);
- }
- stat.fd = fd;
- off = 0;
-
- req.len = sizeof(mem);
- req.addr = (long) mem;
- ssc(fd, 1, (long) &req, off, SSC_READ);
- ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
-
- elf = (struct elfhdr *) mem;
- if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) != 0) {
- cons_write("not an ELF file\n");
- return;
- }
- if (elf->e_type != ET_EXEC) {
- cons_write("not an ELF executable\n");
- return;
- }
- if (!elf_check_arch(elf)) {
- cons_write("kernel not for this processor\n");
- return;
- }
-
- e_entry = elf->e_entry;
- e_phnum = elf->e_phnum;
- e_phoff = elf->e_phoff;
-
- cons_write("loading ");
- cons_write(kpath);
- cons_write("...\n");
-
- for (i = 0; i < e_phnum; ++i) {
- req.len = sizeof(*elf_phdr);
- req.addr = (long) mem;
- ssc(fd, 1, (long) &req, e_phoff, SSC_READ);
- ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
- if (stat.count != sizeof(*elf_phdr)) {
- cons_write("failed to read phdr\n");
- return;
- }
- e_phoff += sizeof(*elf_phdr);
-
- elf_phdr = (struct elf_phdr *) mem;
-
- if (elf_phdr->p_type != PT_LOAD)
- continue;
-
- req.len = elf_phdr->p_filesz;
- req.addr = __pa(elf_phdr->p_paddr);
- ssc(fd, 1, (long) &req, elf_phdr->p_offset, SSC_READ);
- ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
- memset((char *)__pa(elf_phdr->p_paddr) + elf_phdr->p_filesz, 0,
- elf_phdr->p_memsz - elf_phdr->p_filesz);
- }
- ssc(fd, 0, 0, 0, SSC_CLOSE);
-
- cons_write("starting kernel...\n");
-
- /* fake an I/O base address: */
- ia64_setreg(_IA64_REG_AR_KR0, 0xffffc000000UL);
-
- bp = sys_fw_init(args, arglen);
-
- ssc(0, (long) kpath, 0, 0, SSC_LOAD_SYMBOLS);
-
- debug_break();
- jmp_to_kernel((unsigned long) bp, e_entry);
-
- cons_write("kernel returned!\n");
- ssc(-1, 0, 0, 0, SSC_EXIT);
-}
diff --git a/arch/ia64/hp/sim/boot/bootloader.lds b/arch/ia64/hp/sim/boot/bootloader.lds
deleted file mode 100644
index f3f284d6514c..000000000000
--- a/arch/ia64/hp/sim/boot/bootloader.lds
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-OUTPUT_FORMAT("elf64-ia64-little")
-OUTPUT_ARCH(ia64)
-ENTRY(_start)
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0x100000;
-
- _text = .;
- .text : { *(__ivt_section) *(.text) }
- _etext = .;
-
- /* Global data */
- _data = .;
- .rodata : { *(.rodata) *(.rodata.*) }
- .data : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
- __gp = ALIGN (8) + 0x200000;
- .got : { *(.got.plt) *(.got) }
- /* 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 : { *(.sdata) }
- _edata = .;
-
- __bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
- .bss : { *(.bss) *(COMMON) }
- . = ALIGN(64 / 8);
- __bss_stop = .;
- _end = . ;
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
- /* These must appear regardless of . */
-}
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
deleted file mode 100644
index 517fb2822e04..000000000000
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ /dev/null
@@ -1,374 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * PAL & SAL emulation.
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#ifdef CONFIG_PCI
-# include <linux/pci.h>
-#endif
-
-#include <linux/efi.h>
-#include <asm/io.h>
-#include <asm/pal.h>
-#include <asm/sal.h>
-#include <asm/setup.h>
-
-#include "ssc.h"
-
-#define MB (1024*1024UL)
-
-#define SIMPLE_MEMMAP 1
-
-#if SIMPLE_MEMMAP
-# define NUM_MEM_DESCS 4
-#else
-# define NUM_MEM_DESCS 16
-#endif
-
-static char fw_mem[( sizeof(struct ia64_boot_param)
- + sizeof(efi_system_table_t)
- + sizeof(efi_runtime_services_t)
- + 1*sizeof(efi_config_table_t)
- + sizeof(struct ia64_sal_systab)
- + sizeof(struct ia64_sal_desc_entry_point)
- + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
- + 1024)] __attribute__ ((aligned (8)));
-
-#define SECS_PER_HOUR (60 * 60)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-/* Compute the `struct tm' representation of *T,
- offset OFFSET seconds east of UTC,
- and store year, yday, mon, mday, wday, hour, min, sec into *TP.
- Return nonzero if successful. */
-int
-offtime (unsigned long t, efi_time_t *tp)
-{
- const unsigned short int __mon_yday[2][13] =
- {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
- long int days, rem, y;
- const unsigned short int *ip;
-
- days = t / SECS_PER_DAY;
- rem = t % SECS_PER_DAY;
- while (rem < 0) {
- rem += SECS_PER_DAY;
- --days;
- }
- while (rem >= SECS_PER_DAY) {
- rem -= SECS_PER_DAY;
- ++days;
- }
- tp->hour = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- tp->minute = rem / 60;
- tp->second = rem % 60;
- /* January 1, 1970 was a Thursday. */
- y = 1970;
-
-# define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-# define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
-# define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
- while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
- /* Guess a corrected year, assuming 365 days per year. */
- long int yg = y + days / 365 - (days % 365 < 0);
-
- /* Adjust DAYS and Y to match the guessed year. */
- days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- y = yg;
- }
- tp->year = y;
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
- tp->month = y + 1;
- tp->day = days + 1;
- return 1;
-}
-
-extern void pal_emulator_static (void);
-
-/* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
-
-#define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
-
-#define REG_OFFSET(addr) (0x00000000000000FF & (addr))
-#define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr))
-#define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr))
-
-static efi_status_t
-fw_efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
-{
-#if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
- struct {
- int tv_sec; /* must be 32bits to work */
- int tv_usec;
- } tv32bits;
-
- ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD);
-
- memset(tm, 0, sizeof(*tm));
- offtime(tv32bits.tv_sec, tm);
-
- if (tc)
- memset(tc, 0, sizeof(*tc));
-#else
-# error Not implemented yet...
-#endif
- return EFI_SUCCESS;
-}
-
-static void
-efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
-{
-#if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
- ssc(status, 0, 0, 0, SSC_EXIT);
-#else
-# error Not implemented yet...
-#endif
-}
-
-static efi_status_t
-efi_unimplemented (void)
-{
- return EFI_UNSUPPORTED;
-}
-
-static struct sal_ret_values
-sal_emulator (long index, unsigned long in1, unsigned long in2,
- unsigned long in3, unsigned long in4, unsigned long in5,
- unsigned long in6, unsigned long in7)
-{
- long r9 = 0;
- long r10 = 0;
- long r11 = 0;
- long status;
-
- /*
- * Don't do a "switch" here since that gives us code that
- * isn't self-relocatable.
- */
- status = 0;
- if (index == SAL_FREQ_BASE) {
- if (in1 == SAL_FREQ_BASE_PLATFORM)
- r9 = 200000000;
- else if (in1 == SAL_FREQ_BASE_INTERVAL_TIMER) {
- /*
- * Is this supposed to be the cr.itc frequency
- * or something platform specific? The SAL
- * doc ain't exactly clear on this...
- */
- r9 = 700000000;
- } else if (in1 == SAL_FREQ_BASE_REALTIME_CLOCK)
- r9 = 1;
- else
- status = -1;
- } else if (index == SAL_SET_VECTORS) {
- ;
- } else if (index == SAL_GET_STATE_INFO) {
- ;
- } else if (index == SAL_GET_STATE_INFO_SIZE) {
- ;
- } else if (index == SAL_CLEAR_STATE_INFO) {
- ;
- } else if (index == SAL_MC_RENDEZ) {
- ;
- } else if (index == SAL_MC_SET_PARAMS) {
- ;
- } else if (index == SAL_CACHE_FLUSH) {
- ;
- } else if (index == SAL_CACHE_INIT) {
- ;
-#ifdef CONFIG_PCI
- } else if (index == SAL_PCI_CONFIG_READ) {
- /*
- * in1 contains the PCI configuration address and in2
- * the size of the read. The value that is read is
- * returned via the general register r9.
- */
- outl(BUILD_CMD(in1), 0xCF8);
- if (in2 == 1) /* Reading byte */
- r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3)));
- else if (in2 == 2) /* Reading word */
- r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2)));
- else /* Reading dword */
- r9 = inl(0xCFC);
- status = PCIBIOS_SUCCESSFUL;
- } else if (index == SAL_PCI_CONFIG_WRITE) {
- /*
- * in1 contains the PCI configuration address, in2 the
- * size of the write, and in3 the actual value to be
- * written out.
- */
- outl(BUILD_CMD(in1), 0xCF8);
- if (in2 == 1) /* Writing byte */
- outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3)));
- else if (in2 == 2) /* Writing word */
- outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2)));
- else /* Writing dword */
- outl(in3, 0xCFC);
- status = PCIBIOS_SUCCESSFUL;
-#endif /* CONFIG_PCI */
- } else if (index == SAL_UPDATE_PAL) {
- ;
- } else {
- status = -1;
- }
- return ((struct sal_ret_values) {status, r9, r10, r11});
-}
-
-struct ia64_boot_param *
-sys_fw_init (const char *args, int arglen)
-{
- efi_system_table_t *efi_systab;
- efi_runtime_services_t *efi_runtime;
- efi_config_table_t *efi_tables;
- struct ia64_sal_systab *sal_systab;
- efi_memory_desc_t *efi_memmap, *md;
- unsigned long *pal_desc, *sal_desc;
- struct ia64_sal_desc_entry_point *sal_ed;
- struct ia64_boot_param *bp;
- unsigned char checksum = 0;
- char *cp, *cmd_line;
- int i = 0;
-# define MAKE_MD(typ, attr, start, end) \
- do { \
- md = efi_memmap + i++; \
- md->type = typ; \
- md->pad = 0; \
- md->phys_addr = start; \
- md->virt_addr = 0; \
- md->num_pages = (end - start) >> 12; \
- md->attribute = attr; \
- } while (0)
-
- memset(fw_mem, 0, sizeof(fw_mem));
-
- pal_desc = (unsigned long *) &pal_emulator_static;
- sal_desc = (unsigned long *) &sal_emulator;
-
- cp = fw_mem;
- efi_systab = (void *) cp; cp += sizeof(*efi_systab);
- efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
- efi_tables = (void *) cp; cp += sizeof(*efi_tables);
- sal_systab = (void *) cp; cp += sizeof(*sal_systab);
- sal_ed = (void *) cp; cp += sizeof(*sal_ed);
- efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
- bp = (void *) cp; cp += sizeof(*bp);
- cmd_line = (void *) cp;
-
- if (args) {
- if (arglen >= 1024)
- arglen = 1023;
- memcpy(cmd_line, args, arglen);
- } else {
- arglen = 0;
- }
- cmd_line[arglen] = '\0';
-
- memset(efi_systab, 0, sizeof(*efi_systab));
- efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
- efi_systab->hdr.revision = ((1 << 16) | 00);
- efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
- efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0");
- efi_systab->fw_revision = 1;
- efi_systab->runtime = (void *) __pa(efi_runtime);
- efi_systab->nr_tables = 1;
- efi_systab->tables = __pa(efi_tables);
-
- efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
- efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
- efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
- efi_runtime->get_time = (void *)__pa(&fw_efi_get_time);
- efi_runtime->set_time = (void *)__pa(&efi_unimplemented);
- efi_runtime->get_wakeup_time = (void *)__pa(&efi_unimplemented);
- efi_runtime->set_wakeup_time = (void *)__pa(&efi_unimplemented);
- efi_runtime->set_virtual_address_map = (void *)__pa(&efi_unimplemented);
- efi_runtime->get_variable = (void *)__pa(&efi_unimplemented);
- efi_runtime->get_next_variable = (void *)__pa(&efi_unimplemented);
- efi_runtime->set_variable = (void *)__pa(&efi_unimplemented);
- efi_runtime->get_next_high_mono_count = (void *)__pa(&efi_unimplemented);
- efi_runtime->reset_system = (void *)__pa(&efi_reset_system);
-
- efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
- efi_tables->table = __pa(sal_systab);
-
- /* fill in the SAL system table: */
- memcpy(sal_systab->signature, "SST_", 4);
- sal_systab->size = sizeof(*sal_systab);
- sal_systab->sal_rev_minor = 1;
- sal_systab->sal_rev_major = 0;
- sal_systab->entry_count = 1;
-
-#ifdef CONFIG_IA64_GENERIC
- strcpy(sal_systab->oem_id, "Generic");
- strcpy(sal_systab->product_id, "IA-64 system");
-#endif
-
-#ifdef CONFIG_IA64_HP_SIM
- strcpy(sal_systab->oem_id, "Hewlett-Packard");
- strcpy(sal_systab->product_id, "HP-simulator");
-#endif
-
- /* fill in an entry point: */
- sal_ed->type = SAL_DESC_ENTRY_POINT;
- sal_ed->pal_proc = __pa(pal_desc[0]);
- sal_ed->sal_proc = __pa(sal_desc[0]);
- sal_ed->gp = __pa(sal_desc[1]);
-
- for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
- checksum += *cp;
-
- sal_systab->checksum = -checksum;
-
-#if SIMPLE_MEMMAP
- /* simulate free memory at physical address zero */
- MAKE_MD(EFI_BOOT_SERVICES_DATA, EFI_MEMORY_WB, 0*MB, 1*MB);
- MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB, 1*MB, 2*MB);
- MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 2*MB, 130*MB);
- MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 4096*MB, 4128*MB);
-#else
- MAKE_MD( 4, 0x9, 0x0000000000000000, 0x0000000000001000);
- MAKE_MD( 7, 0x9, 0x0000000000001000, 0x000000000008a000);
- MAKE_MD( 4, 0x9, 0x000000000008a000, 0x00000000000a0000);
- MAKE_MD( 5, 0x8000000000000009, 0x00000000000c0000, 0x0000000000100000);
- MAKE_MD( 7, 0x9, 0x0000000000100000, 0x0000000004400000);
- MAKE_MD( 2, 0x9, 0x0000000004400000, 0x0000000004be5000);
- MAKE_MD( 7, 0x9, 0x0000000004be5000, 0x000000007f77e000);
- MAKE_MD( 6, 0x8000000000000009, 0x000000007f77e000, 0x000000007fb94000);
- MAKE_MD( 6, 0x8000000000000009, 0x000000007fb94000, 0x000000007fb95000);
- MAKE_MD( 6, 0x8000000000000009, 0x000000007fb95000, 0x000000007fc00000);
- MAKE_MD(13, 0x8000000000000009, 0x000000007fc00000, 0x000000007fc3a000);
- MAKE_MD( 7, 0x9, 0x000000007fc3a000, 0x000000007fea0000);
- MAKE_MD( 5, 0x8000000000000009, 0x000000007fea0000, 0x000000007fea8000);
- MAKE_MD( 7, 0x9, 0x000000007fea8000, 0x000000007feab000);
- MAKE_MD( 5, 0x8000000000000009, 0x000000007feab000, 0x000000007ffff000);
- MAKE_MD( 7, 0x9, 0x00000000ff400000, 0x0000000104000000);
-#endif
-
- bp->efi_systab = __pa(&fw_mem);
- bp->efi_memmap = __pa(efi_memmap);
- bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
- bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
- bp->efi_memdesc_version = 1;
- bp->command_line = __pa(cmd_line);
- bp->console_info.num_cols = 80;
- bp->console_info.num_rows = 25;
- bp->console_info.orig_x = 0;
- bp->console_info.orig_y = 24;
- bp->fpswa = 0;
-
- return bp;
-}
diff --git a/arch/ia64/hp/sim/boot/ssc.h b/arch/ia64/hp/sim/boot/ssc.h
deleted file mode 100644
index 88752c7509e0..000000000000
--- a/arch/ia64/hp/sim/boot/ssc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-#ifndef ssc_h
-#define ssc_h
-
-/* Simulator system calls: */
-
-#define SSC_CONSOLE_INIT 20
-#define SSC_GETCHAR 21
-#define SSC_PUTCHAR 31
-#define SSC_OPEN 50
-#define SSC_CLOSE 51
-#define SSC_READ 52
-#define SSC_WRITE 53
-#define SSC_GET_COMPLETION 54
-#define SSC_WAIT_COMPLETION 55
-#define SSC_CONNECT_INTERRUPT 58
-#define SSC_GENERATE_INTERRUPT 59
-#define SSC_SET_PERIODIC_INTERRUPT 60
-#define SSC_GET_RTC 65
-#define SSC_EXIT 66
-#define SSC_LOAD_SYMBOLS 69
-#define SSC_GET_TOD 74
-
-#define SSC_GET_ARGS 75
-
-/*
- * Simulator system call.
- */
-extern long ssc (long arg0, long arg1, long arg2, long arg3, int nr);
-
-#endif /* ssc_h */
diff --git a/arch/ia64/hp/sim/hpsim.S b/arch/ia64/hp/sim/hpsim.S
deleted file mode 100644
index 44b4d53e1689..000000000000
--- a/arch/ia64/hp/sim/hpsim.S
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/asmmacro.h>
-
-/*
- * Simulator system call.
- */
-GLOBAL_ENTRY(ia64_ssc)
- mov r15=r36
- break 0x80001
- br.ret.sptk.many rp
-END(ia64_ssc)
diff --git a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c
deleted file mode 100644
index bffd9f67a8a1..000000000000
--- a/arch/ia64/hp/sim/hpsim_console.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Platform dependent support for HP simulator.
- *
- * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/kdev_t.h>
-#include <linux/console.h>
-
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/pal.h>
-#include <asm/machvec.h>
-#include <asm/pgtable.h>
-#include <asm/sal.h>
-#include <asm/hpsim.h>
-
-#include "hpsim_ssc.h"
-
-static int simcons_init (struct console *, char *);
-static void simcons_write (struct console *, const char *, unsigned);
-static struct tty_driver *simcons_console_device (struct console *, int *);
-
-static struct console hpsim_cons = {
- .name = "simcons",
- .write = simcons_write,
- .device = simcons_console_device,
- .setup = simcons_init,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int
-simcons_init (struct console *cons, char *options)
-{
- return 0;
-}
-
-static void
-simcons_write (struct console *cons, const char *buf, unsigned count)
-{
- unsigned long ch;
-
- while (count-- > 0) {
- ch = *buf++;
- ia64_ssc(ch, 0, 0, 0, SSC_PUTCHAR);
- if (ch == '\n')
- ia64_ssc('\r', 0, 0, 0, SSC_PUTCHAR);
- }
-}
-
-static struct tty_driver *simcons_console_device (struct console *c, int *index)
-{
- *index = c->index;
- return hp_simserial_driver;
-}
-
-int simcons_register(void)
-{
- if (!ia64_platform_is("hpsim"))
- return 1;
-
- if (hpsim_cons.flags & CON_ENABLED)
- return 1;
-
- register_console(&hpsim_cons);
- return 0;
-}
diff --git a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c
deleted file mode 100644
index 2f1cc59650ab..000000000000
--- a/arch/ia64/hp/sim/hpsim_irq.c
+++ /dev/null
@@ -1,76 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Platform dependent support for HP simulator.
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/irq.h>
-
-#include "hpsim_ssc.h"
-
-static unsigned int
-hpsim_irq_startup(struct irq_data *data)
-{
- return 0;
-}
-
-static void
-hpsim_irq_noop(struct irq_data *data)
-{
-}
-
-static int
-hpsim_set_affinity_noop(struct irq_data *d, const struct cpumask *b, bool f)
-{
- return 0;
-}
-
-static struct irq_chip irq_type_hp_sim = {
- .name = "hpsim",
- .irq_startup = hpsim_irq_startup,
- .irq_shutdown = hpsim_irq_noop,
- .irq_enable = hpsim_irq_noop,
- .irq_disable = hpsim_irq_noop,
- .irq_ack = hpsim_irq_noop,
- .irq_set_affinity = hpsim_set_affinity_noop,
-};
-
-static void hpsim_irq_set_chip(int irq)
-{
- struct irq_chip *chip = irq_get_chip(irq);
-
- if (chip == &no_irq_chip)
- irq_set_chip(irq, &irq_type_hp_sim);
-}
-
-static void hpsim_connect_irq(int intr, int irq)
-{
- ia64_ssc(intr, irq, 0, 0, SSC_CONNECT_INTERRUPT);
-}
-
-int hpsim_get_irq(int intr)
-{
- int irq = assign_irq_vector(AUTO_ASSIGN);
-
- if (irq >= 0) {
- hpsim_irq_set_chip(irq);
- irq_set_handler(irq, handle_simple_irq);
- hpsim_connect_irq(intr, irq);
- }
-
- return irq;
-}
-
-void __init
-hpsim_irq_init (void)
-{
- int i;
-
- for_each_active_irq(i)
- hpsim_irq_set_chip(i);
-}
diff --git a/arch/ia64/hp/sim/hpsim_machvec.c b/arch/ia64/hp/sim/hpsim_machvec.c
deleted file mode 100644
index c21419359185..000000000000
--- a/arch/ia64/hp/sim/hpsim_machvec.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACHVEC_PLATFORM_NAME hpsim
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpsim.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/hp/sim/hpsim_setup.c b/arch/ia64/hp/sim/hpsim_setup.c
deleted file mode 100644
index 41d21d51dc4d..000000000000
--- a/arch/ia64/hp/sim/hpsim_setup.c
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Platform dependent support for HP simulator.
- *
- * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
- */
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/param.h>
-#include <linux/root_dev.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/pal.h>
-#include <asm/machvec.h>
-#include <asm/pgtable.h>
-#include <asm/sal.h>
-#include <asm/hpsim.h>
-
-#include "hpsim_ssc.h"
-
-void
-ia64_ctl_trace (long on)
-{
- ia64_ssc(on, 0, 0, 0, SSC_CTL_TRACE);
-}
-
-void __init
-hpsim_setup (char **cmdline_p)
-{
- ROOT_DEV = Root_SDA1; /* default to first SCSI drive */
-
- simcons_register();
-}
diff --git a/arch/ia64/hp/sim/hpsim_ssc.h b/arch/ia64/hp/sim/hpsim_ssc.h
deleted file mode 100644
index 6fd97a487811..000000000000
--- a/arch/ia64/hp/sim/hpsim_ssc.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Platform dependent support for HP simulator.
- *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
- */
-#ifndef _IA64_PLATFORM_HPSIM_SSC_H
-#define _IA64_PLATFORM_HPSIM_SSC_H
-
-/* Simulator system calls: */
-
-#define SSC_CONSOLE_INIT 20
-#define SSC_GETCHAR 21
-#define SSC_PUTCHAR 31
-#define SSC_CONNECT_INTERRUPT 58
-#define SSC_GENERATE_INTERRUPT 59
-#define SSC_SET_PERIODIC_INTERRUPT 60
-#define SSC_GET_RTC 65
-#define SSC_EXIT 66
-#define SSC_LOAD_SYMBOLS 69
-#define SSC_GET_TOD 74
-#define SSC_CTL_TRACE 76
-
-#define SSC_NETDEV_PROBE 100
-#define SSC_NETDEV_SEND 101
-#define SSC_NETDEV_RECV 102
-#define SSC_NETDEV_ATTACH 103
-#define SSC_NETDEV_DETACH 104
-
-/*
- * Simulator system call.
- */
-extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
-
-#endif /* _IA64_PLATFORM_HPSIM_SSC_H */
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
deleted file mode 100644
index f39ef2b4ed72..000000000000
--- a/arch/ia64/hp/sim/simeth.c
+++ /dev/null
@@ -1,510 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Simulated Ethernet Driver
- *
- * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <linux/skbuff.h>
-#include <linux/notifier.h>
-#include <linux/bitops.h>
-#include <asm/irq.h>
-#include <asm/hpsim.h>
-
-#include "hpsim_ssc.h"
-
-#define SIMETH_RECV_MAX 10
-
-/*
- * Maximum possible received frame for Ethernet.
- * We preallocate an sk_buff of that size to avoid costly
- * memcpy for temporary buffer into sk_buff. We do basically
- * what's done in other drivers, like eepro with a ring.
- * The difference is, of course, that we don't have real DMA !!!
- */
-#define SIMETH_FRAME_SIZE ETH_FRAME_LEN
-
-
-#define NETWORK_INTR 8
-
-struct simeth_local {
- struct net_device_stats stats;
- int simfd; /* descriptor in the simulator */
-};
-
-static int simeth_probe1(void);
-static int simeth_open(struct net_device *dev);
-static int simeth_close(struct net_device *dev);
-static int simeth_tx(struct sk_buff *skb, struct net_device *dev);
-static int simeth_rx(struct net_device *dev);
-static struct net_device_stats *simeth_get_stats(struct net_device *dev);
-static irqreturn_t simeth_interrupt(int irq, void *dev_id);
-static void set_multicast_list(struct net_device *dev);
-static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr);
-
-static char *simeth_version="0.3";
-
-/*
- * This variable is used to establish a mapping between the Linux/ia64 kernel
- * and the host linux kernel.
- *
- * As of today, we support only one card, even though most of the code
- * is ready for many more. The mapping is then:
- * linux/ia64 -> linux/x86
- * eth0 -> eth1
- *
- * In the future, we some string operations, we could easily support up
- * to 10 cards (0-9).
- *
- * The default mapping can be changed on the kernel command line by
- * specifying simeth=ethX (or whatever string you want).
- */
-static char *simeth_device="eth0"; /* default host interface to use */
-
-
-
-static volatile unsigned int card_count; /* how many cards "found" so far */
-static int simeth_debug; /* set to 1 to get debug information */
-
-/*
- * Used to catch IFF_UP & IFF_DOWN events
- */
-static struct notifier_block simeth_dev_notifier = {
- simeth_device_event,
- NULL
-};
-
-
-/*
- * Function used when using a kernel command line option.
- *
- * Format: simeth=interface_name (like eth0)
- */
-static int __init
-simeth_setup(char *str)
-{
- simeth_device = str;
- return 1;
-}
-
-__setup("simeth=", simeth_setup);
-
-/*
- * Function used to probe for simeth devices when not installed
- * as a loadable module
- */
-
-int __init
-simeth_probe (void)
-{
- int r;
-
- printk(KERN_INFO "simeth: v%s\n", simeth_version);
-
- r = simeth_probe1();
-
- if (r == 0) register_netdevice_notifier(&simeth_dev_notifier);
-
- return r;
-}
-
-static inline int
-netdev_probe(char *name, unsigned char *ether)
-{
- return ia64_ssc(__pa(name), __pa(ether), 0,0, SSC_NETDEV_PROBE);
-}
-
-
-static inline int
-netdev_attach(int fd, int irq, unsigned int ipaddr)
-{
- /* this puts the host interface in the right mode (start interrupting) */
- return ia64_ssc(fd, ipaddr, 0,0, SSC_NETDEV_ATTACH);
-}
-
-
-static inline int
-netdev_detach(int fd)
-{
- /*
- * inactivate the host interface (don't interrupt anymore) */
- return ia64_ssc(fd, 0,0,0, SSC_NETDEV_DETACH);
-}
-
-static inline int
-netdev_send(int fd, unsigned char *buf, unsigned int len)
-{
- return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_SEND);
-}
-
-static inline int
-netdev_read(int fd, unsigned char *buf, unsigned int len)
-{
- return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV);
-}
-
-static const struct net_device_ops simeth_netdev_ops = {
- .ndo_open = simeth_open,
- .ndo_stop = simeth_close,
- .ndo_start_xmit = simeth_tx,
- .ndo_get_stats = simeth_get_stats,
- .ndo_set_rx_mode = set_multicast_list, /* not yet used */
-
-};
-
-/*
- * Function shared with module code, so cannot be in init section
- *
- * So far this function "detects" only one card (test_&_set) but could
- * be extended easily.
- *
- * Return:
- * - -ENODEV is no device found
- * - -ENOMEM is no more memory
- * - 0 otherwise
- */
-static int
-simeth_probe1(void)
-{
- unsigned char mac_addr[ETH_ALEN];
- struct simeth_local *local;
- struct net_device *dev;
- int fd, err, rc;
-
- /*
- * XXX Fix me
- * let's support just one card for now
- */
- if (test_and_set_bit(0, &card_count))
- return -ENODEV;
-
- /*
- * check with the simulator for the device
- */
- fd = netdev_probe(simeth_device, mac_addr);
- if (fd == -1)
- return -ENODEV;
-
- dev = alloc_etherdev(sizeof(struct simeth_local));
- if (!dev)
- return -ENOMEM;
-
- memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr));
-
- local = netdev_priv(dev);
- local->simfd = fd; /* keep track of underlying file descriptor */
-
- dev->netdev_ops = &simeth_netdev_ops;
-
- err = register_netdev(dev);
- if (err) {
- free_netdev(dev);
- return err;
- }
-
- /*
- * attach the interrupt in the simulator, this does enable interrupts
- * until a netdev_attach() is called
- */
- if ((rc = hpsim_get_irq(NETWORK_INTR)) < 0)
- panic("%s: out of interrupt vectors!\n", __func__);
- dev->irq = rc;
-
- printk(KERN_INFO "%s: hosteth=%s simfd=%d, HwAddr=%pm, IRQ %d\n",
- dev->name, simeth_device, local->simfd, dev->dev_addr, dev->irq);
-
- return 0;
-}
-
-/*
- * actually binds the device to an interrupt vector
- */
-static int
-simeth_open(struct net_device *dev)
-{
- if (request_irq(dev->irq, simeth_interrupt, 0, "simeth", dev)) {
- printk(KERN_WARNING "simeth: unable to get IRQ %d.\n", dev->irq);
- return -EAGAIN;
- }
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/* copied from lapbether.c */
-static __inline__ int dev_is_ethdev(struct net_device *dev)
-{
- return ( dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5));
-}
-
-
-/*
- * Handler for IFF_UP or IFF_DOWN
- *
- * The reason for that is that we don't want to be interrupted when the
- * interface is down. There is no way to unconnect in the simualtor. Instead
- * we use this function to shutdown packet processing in the frame filter
- * in the simulator. Thus no interrupts are generated
- *
- *
- * That's also the place where we pass the IP address of this device to the
- * simulator so that that we can start filtering packets for it
- *
- * There may be a better way of doing this, but I don't know which yet.
- */
-static int
-simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- struct simeth_local *local;
- struct in_device *in_dev;
- struct in_ifaddr **ifap = NULL;
- struct in_ifaddr *ifa = NULL;
- int r;
-
-
- if ( ! dev ) {
- printk(KERN_WARNING "simeth_device_event dev=0\n");
- return NOTIFY_DONE;
- }
-
- if (dev_net(dev) != &init_net)
- return NOTIFY_DONE;
-
- if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
-
- /*
- * Check whether or not it's for an ethernet device
- *
- * XXX Fixme: This works only as long as we support one
- * type of ethernet device.
- */
- if ( !dev_is_ethdev(dev) ) return NOTIFY_DONE;
-
- if ((in_dev=dev->ip_ptr) != NULL) {
- for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
- if (strcmp(dev->name, ifa->ifa_label) == 0) break;
- }
- if ( ifa == NULL ) {
- printk(KERN_ERR "simeth_open: can't find device %s's ifa\n", dev->name);
- return NOTIFY_DONE;
- }
-
- printk(KERN_INFO "simeth_device_event: %s ipaddr=0x%x\n",
- dev->name, ntohl(ifa->ifa_local));
-
- /*
- * XXX Fix me
- * if the device was up, and we're simply reconfiguring it, not sure
- * we get DOWN then UP.
- */
-
- local = netdev_priv(dev);
- /* now do it for real */
- r = event == NETDEV_UP ?
- netdev_attach(local->simfd, dev->irq, ntohl(ifa->ifa_local)):
- netdev_detach(local->simfd);
-
- printk(KERN_INFO "simeth: netdev_attach/detach: event=%s ->%d\n",
- event == NETDEV_UP ? "attach":"detach", r);
-
- return NOTIFY_DONE;
-}
-
-static int
-simeth_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
-
- free_irq(dev->irq, dev);
-
- return 0;
-}
-
-/*
- * Only used for debug
- */
-static void
-frame_print(unsigned char *from, unsigned char *frame, int len)
-{
- int i;
-
- printk("%s: (%d) %02x", from, len, frame[0] & 0xff);
- for(i=1; i < 6; i++ ) {
- printk(":%02x", frame[i] &0xff);
- }
- printk(" %2x", frame[6] &0xff);
- for(i=7; i < 12; i++ ) {
- printk(":%02x", frame[i] &0xff);
- }
- printk(" [%02x%02x]\n", frame[12], frame[13]);
-
- for(i=14; i < len; i++ ) {
- printk("%02x ", frame[i] &0xff);
- if ( (i%10)==0) printk("\n");
- }
- printk("\n");
-}
-
-
-/*
- * Function used to transmit of frame, very last one on the path before
- * going to the simulator.
- */
-static int
-simeth_tx(struct sk_buff *skb, struct net_device *dev)
-{
- struct simeth_local *local = netdev_priv(dev);
-
-#if 0
- /* ensure we have at least ETH_ZLEN bytes (min frame size) */
- unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- /* Where do the extra padding bytes comes from inthe skbuff ? */
-#else
- /* the real driver in the host system is going to take care of that
- * or maybe it's the NIC itself.
- */
- unsigned int length = skb->len;
-#endif
-
- local->stats.tx_bytes += skb->len;
- local->stats.tx_packets++;
-
-
- if (simeth_debug > 5) frame_print("simeth_tx", skb->data, length);
-
- netdev_send(local->simfd, skb->data, length);
-
- /*
- * we are synchronous on write, so we don't simulate a
- * trasnmit complete interrupt, thus we don't need to arm a tx
- */
-
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
-}
-
-static inline struct sk_buff *
-make_new_skb(struct net_device *dev)
-{
- struct sk_buff *nskb;
-
- /*
- * The +2 is used to make sure that the IP header is nicely
- * aligned (on 4byte boundary I assume 14+2=16)
- */
- nskb = dev_alloc_skb(SIMETH_FRAME_SIZE + 2);
- if ( nskb == NULL ) {
- printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name);
- return NULL;
- }
-
- skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */
-
- skb_put(nskb,SIMETH_FRAME_SIZE);
-
- return nskb;
-}
-
-/*
- * called from interrupt handler to process a received frame
- */
-static int
-simeth_rx(struct net_device *dev)
-{
- struct simeth_local *local;
- struct sk_buff *skb;
- int len;
- int rcv_count = SIMETH_RECV_MAX;
-
- local = netdev_priv(dev);
- /*
- * the loop concept has been borrowed from other drivers
- * looks to me like it's a throttling thing to avoid pushing to many
- * packets at one time into the stack. Making sure we can process them
- * upstream and make forward progress overall
- */
- do {
- if ( (skb=make_new_skb(dev)) == NULL ) {
- printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name);
- local->stats.rx_dropped++;
- return 0;
- }
- /*
- * Read only one frame at a time
- */
- len = netdev_read(local->simfd, skb->data, SIMETH_FRAME_SIZE);
- if ( len == 0 ) {
- if ( simeth_debug > 0 ) printk(KERN_WARNING "%s: count=%d netdev_read=0\n",
- dev->name, SIMETH_RECV_MAX-rcv_count);
- break;
- }
-#if 0
- /*
- * XXX Fix me
- * Should really do a csum+copy here
- */
- skb_copy_to_linear_data(skb, frame, len);
-#endif
- skb->protocol = eth_type_trans(skb, dev);
-
- if ( simeth_debug > 6 ) frame_print("simeth_rx", skb->data, len);
-
- /*
- * push the packet up & trigger software interrupt
- */
- netif_rx(skb);
-
- local->stats.rx_packets++;
- local->stats.rx_bytes += len;
-
- } while ( --rcv_count );
-
- return len; /* 0 = nothing left to read, otherwise, we can try again */
-}
-
-/*
- * Interrupt handler (Yes, we can do it too !!!)
- */
-static irqreturn_t
-simeth_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
-
- /*
- * very simple loop because we get interrupts only when receiving
- */
- while (simeth_rx(dev));
- return IRQ_HANDLED;
-}
-
-static struct net_device_stats *
-simeth_get_stats(struct net_device *dev)
-{
- struct simeth_local *local = netdev_priv(dev);
-
- return &local->stats;
-}
-
-/* fake multicast ability */
-static void
-set_multicast_list(struct net_device *dev)
-{
- printk(KERN_WARNING "%s: set_multicast_list called\n", dev->name);
-}
-
-__initcall(simeth_probe);
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
deleted file mode 100644
index 0a8a74271173..000000000000
--- a/arch/ia64/hp/sim/simscsi.c
+++ /dev/null
@@ -1,373 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Simulated SCSI driver.
- *
- * Copyright (C) 1999, 2001-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 02/01/15 David Mosberger Updated for v2.5.1
- * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33
- */
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <asm/irq.h>
-#include "hpsim_ssc.h"
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-
-#define DEBUG_SIMSCSI 0
-
-#define SIMSCSI_REQ_QUEUE_LEN 64
-#define DEFAULT_SIMSCSI_ROOT "/var/ski-disks/sd"
-
-/* Simulator system calls: */
-
-#define SSC_OPEN 50
-#define SSC_CLOSE 51
-#define SSC_READ 52
-#define SSC_WRITE 53
-#define SSC_GET_COMPLETION 54
-#define SSC_WAIT_COMPLETION 55
-
-#define SSC_WRITE_ACCESS 2
-#define SSC_READ_ACCESS 1
-
-#if DEBUG_SIMSCSI
- int simscsi_debug;
-# define DBG simscsi_debug
-#else
-# define DBG 0
-#endif
-
-static struct Scsi_Host *host;
-
-static void simscsi_interrupt (unsigned long val);
-static DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0);
-
-struct disk_req {
- unsigned long addr;
- unsigned len;
-};
-
-struct disk_stat {
- int fd;
- unsigned count;
-};
-
-static int desc[16] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-static struct queue_entry {
- struct scsi_cmnd *sc;
-} queue[SIMSCSI_REQ_QUEUE_LEN];
-
-static int rd, wr;
-static atomic_t num_reqs = ATOMIC_INIT(0);
-
-/* base name for default disks */
-static char *simscsi_root = DEFAULT_SIMSCSI_ROOT;
-
-#define MAX_ROOT_LEN 128
-
-/*
- * used to setup a new base for disk images
- * to use /foo/bar/disk[a-z] as disk images
- * you have to specify simscsi=/foo/bar/disk on the command line
- */
-static int __init
-simscsi_setup (char *s)
-{
- /* XXX Fix me we may need to strcpy() ? */
- if (strlen(s) > MAX_ROOT_LEN) {
- printk(KERN_ERR "simscsi_setup: prefix too long---using default %s\n",
- simscsi_root);
- } else
- simscsi_root = s;
- return 1;
-}
-
-__setup("simscsi=", simscsi_setup);
-
-static void
-simscsi_interrupt (unsigned long val)
-{
- struct scsi_cmnd *sc;
-
- while ((sc = queue[rd].sc) != NULL) {
- atomic_dec(&num_reqs);
- queue[rd].sc = NULL;
- if (DBG)
- printk("simscsi_interrupt: done with %u\n",
- sc->request->tag);
- (*sc->scsi_done)(sc);
- rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN;
- }
-}
-
-static int
-simscsi_biosparam (struct scsi_device *sdev, struct block_device *n,
- sector_t capacity, int ip[])
-{
- ip[0] = 64; /* heads */
- ip[1] = 32; /* sectors */
- ip[2] = capacity >> 11; /* cylinders */
- return 0;
-}
-
-static void
-simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset)
-{
- int i;
- struct scatterlist *sl;
- struct disk_stat stat;
- struct disk_req req;
-
- stat.fd = desc[sc->device->id];
-
- scsi_for_each_sg(sc, sl, scsi_sg_count(sc), i) {
- req.addr = __pa(sg_virt(sl));
- req.len = sl->length;
- if (DBG)
- printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n",
- mode == SSC_READ ? "read":"write", req.addr, offset,
- scsi_sg_count(sc) - i, sl->length);
- ia64_ssc(stat.fd, 1, __pa(&req), offset, mode);
- ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
-
- /* should not happen in our case */
- if (stat.count != req.len) {
- sc->result = DID_ERROR << 16;
- return;
- }
- offset += sl->length;
- }
- sc->result = GOOD;
-}
-
-/*
- * function handling both READ_6/WRITE_6 (non-scatter/gather mode)
- * commands.
- * Added 02/26/99 S.Eranian
- */
-static void
-simscsi_readwrite6 (struct scsi_cmnd *sc, int mode)
-{
- unsigned long offset;
-
- offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512;
- simscsi_sg_readwrite(sc, mode, offset);
-}
-
-static size_t
-simscsi_get_disk_size (int fd)
-{
- struct disk_stat stat;
- size_t bit, sectors = 0;
- struct disk_req req;
- char buf[512];
-
- /*
- * This is a bit kludgey: the simulator doesn't provide a
- * direct way of determining the disk size, so we do a binary
- * search, assuming a maximum disk size of 128GB.
- */
- for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) {
- req.addr = __pa(&buf);
- req.len = sizeof(buf);
- ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
- stat.fd = fd;
- ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
- if (stat.count == sizeof(buf))
- sectors |= bit;
- }
- return sectors - 1; /* return last valid sector number */
-}
-
-static void
-simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
-{
- unsigned long offset;
-
- offset = (((unsigned long)sc->cmnd[2] << 24)
- | ((unsigned long)sc->cmnd[3] << 16)
- | ((unsigned long)sc->cmnd[4] << 8)
- | ((unsigned long)sc->cmnd[5] << 0))*512UL;
- simscsi_sg_readwrite(sc, mode, offset);
-}
-
-static int
-simscsi_queuecommand_lck (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
-{
- unsigned int target_id = sc->device->id;
- char fname[MAX_ROOT_LEN+16];
- size_t disk_size;
- char *buf;
- char localbuf[36];
-#if DEBUG_SIMSCSI
- register long sp asm ("sp");
-
- if (DBG)
- printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%u,sp=%lx,done=%p\n",
- target_id, sc->cmnd[0], sc->request->tag, sp, done);
-#endif
-
- sc->result = DID_BAD_TARGET << 16;
- sc->scsi_done = done;
- if (target_id <= 15 && sc->device->lun == 0) {
- switch (sc->cmnd[0]) {
- case INQUIRY:
- if (scsi_bufflen(sc) < 35) {
- break;
- }
- sprintf (fname, "%s%c", simscsi_root, 'a' + target_id);
- desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
- 0, 0, SSC_OPEN);
- if (desc[target_id] < 0) {
- /* disk doesn't exist... */
- break;
- }
- buf = localbuf;
- buf[0] = 0; /* magnetic disk */
- buf[1] = 0; /* not a removable medium */
- buf[2] = 2; /* SCSI-2 compliant device */
- buf[3] = 2; /* SCSI-2 response data format */
- buf[4] = 31; /* additional length (bytes) */
- buf[5] = 0; /* reserved */
- buf[6] = 0; /* reserved */
- buf[7] = 0; /* various flags */
- memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28);
- scsi_sg_copy_from_buffer(sc, buf, 36);
- sc->result = GOOD;
- break;
-
- case TEST_UNIT_READY:
- sc->result = GOOD;
- break;
-
- case READ_6:
- if (desc[target_id] < 0 )
- break;
- simscsi_readwrite6(sc, SSC_READ);
- break;
-
- case READ_10:
- if (desc[target_id] < 0 )
- break;
- simscsi_readwrite10(sc, SSC_READ);
- break;
-
- case WRITE_6:
- if (desc[target_id] < 0)
- break;
- simscsi_readwrite6(sc, SSC_WRITE);
- break;
-
- case WRITE_10:
- if (desc[target_id] < 0)
- break;
- simscsi_readwrite10(sc, SSC_WRITE);
- break;
-
- case READ_CAPACITY:
- if (desc[target_id] < 0 || scsi_bufflen(sc) < 8) {
- break;
- }
- buf = localbuf;
- disk_size = simscsi_get_disk_size(desc[target_id]);
-
- buf[0] = (disk_size >> 24) & 0xff;
- buf[1] = (disk_size >> 16) & 0xff;
- buf[2] = (disk_size >> 8) & 0xff;
- buf[3] = (disk_size >> 0) & 0xff;
- /* set block size of 512 bytes: */
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 2;
- buf[7] = 0;
- scsi_sg_copy_from_buffer(sc, buf, 8);
- sc->result = GOOD;
- break;
-
- case MODE_SENSE:
- case MODE_SENSE_10:
- /* sd.c uses this to determine whether disk does write-caching. */
- scsi_sg_copy_from_buffer(sc, (char *)empty_zero_page,
- PAGE_SIZE);
- sc->result = GOOD;
- break;
-
- case START_STOP:
- printk(KERN_ERR "START_STOP\n");
- break;
-
- default:
- panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]);
- }
- }
- if (sc->result == DID_BAD_TARGET) {
- sc->result |= DRIVER_SENSE << 24;
- sc->sense_buffer[0] = 0x70;
- sc->sense_buffer[2] = 0x00;
- }
- if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) {
- panic("Attempt to queue command while command is pending!!");
- }
- atomic_inc(&num_reqs);
- queue[wr].sc = sc;
- wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN;
-
- tasklet_schedule(&simscsi_tasklet);
- return 0;
-}
-
-static DEF_SCSI_QCMD(simscsi_queuecommand)
-
-static int
-simscsi_host_reset (struct scsi_cmnd *sc)
-{
- printk(KERN_ERR "simscsi_host_reset: not implemented\n");
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .name = "simulated SCSI host adapter",
- .proc_name = "simscsi",
- .queuecommand = simscsi_queuecommand,
- .eh_host_reset_handler = simscsi_host_reset,
- .bios_param = simscsi_biosparam,
- .can_queue = SIMSCSI_REQ_QUEUE_LEN,
- .this_id = -1,
- .sg_tablesize = SG_ALL,
- .max_sectors = 1024,
- .cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN,
- .dma_boundary = PAGE_SIZE - 1,
-};
-
-static int __init
-simscsi_init(void)
-{
- int error;
-
- host = scsi_host_alloc(&driver_template, 0);
- if (!host)
- return -ENOMEM;
-
- error = scsi_add_host(host, NULL);
- if (error)
- goto free_host;
- scsi_scan_host(host);
- return 0;
-
- free_host:
- scsi_host_put(host);
- return error;
-}
-device_initcall(simscsi_init);
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
deleted file mode 100644
index 1a338e541334..000000000000
--- a/arch/ia64/hp/sim/simserial.c
+++ /dev/null
@@ -1,521 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Simulated Serial Driver (fake serial)
- *
- * This driver is mostly used for bringup purposes and will go away.
- * It has a strong dependency on the system console. All outputs
- * are rerouted to the same facility as the one used by printk which, in our
- * case means sys_sim.c console (goes via the simulator).
- *
- * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/sched/debug.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/capability.h>
-#include <linux/circ_buf.h>
-#include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/uaccess.h>
-
-#include <asm/hpsim.h>
-
-#include "hpsim_ssc.h"
-
-#undef SIMSERIAL_DEBUG /* define this to get some debug information */
-
-#define KEYBOARD_INTR 3 /* must match with simulator! */
-
-#define NR_PORTS 1 /* only one port for now */
-
-struct serial_state {
- struct tty_port port;
- struct circ_buf xmit;
- int irq;
- int x_char;
-};
-
-static struct serial_state rs_table[NR_PORTS];
-
-struct tty_driver *hp_simserial_driver;
-
-static struct console *console;
-
-static void receive_chars(struct tty_port *port)
-{
- unsigned char ch;
- static unsigned char seen_esc = 0;
-
- while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) {
- if (ch == 27 && seen_esc == 0) {
- seen_esc = 1;
- continue;
- } else if (seen_esc == 1 && ch == 'O') {
- seen_esc = 2;
- continue;
- } else if (seen_esc == 2) {
- if (ch == 'P') /* F1 */
- show_state();
-#ifdef CONFIG_MAGIC_SYSRQ
- if (ch == 'S') { /* F4 */
- do {
- ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
- } while (!ch);
- handle_sysrq(ch);
- }
-#endif
- seen_esc = 0;
- continue;
- }
- seen_esc = 0;
-
- if (tty_insert_flip_char(port, ch, TTY_NORMAL) == 0)
- break;
- }
- tty_flip_buffer_push(port);
-}
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
-{
- struct serial_state *info = dev_id;
-
- receive_chars(&info->port);
-
- return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-static int rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct serial_state *info = tty->driver_data;
- unsigned long flags;
-
- if (!info->xmit.buf)
- return 0;
-
- local_irq_save(flags);
- if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
- local_irq_restore(flags);
- return 0;
- }
- info->xmit.buf[info->xmit.head] = ch;
- info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
- local_irq_restore(flags);
- return 1;
-}
-
-static void transmit_chars(struct tty_struct *tty, struct serial_state *info,
- int *intr_done)
-{
- int count;
- unsigned long flags;
-
- local_irq_save(flags);
-
- if (info->x_char) {
- char c = info->x_char;
-
- console->write(console, &c, 1);
-
- info->x_char = 0;
-
- goto out;
- }
-
- if (info->xmit.head == info->xmit.tail || tty->stopped) {
-#ifdef SIMSERIAL_DEBUG
- printk("transmit_chars: head=%d, tail=%d, stopped=%d\n",
- info->xmit.head, info->xmit.tail, tty->stopped);
-#endif
- goto out;
- }
- /*
- * We removed the loop and try to do it in to chunks. We need
- * 2 operations maximum because it's a ring buffer.
- *
- * First from current to tail if possible.
- * Then from the beginning of the buffer until necessary
- */
-
- count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
- SERIAL_XMIT_SIZE - info->xmit.tail);
- console->write(console, info->xmit.buf+info->xmit.tail, count);
-
- info->xmit.tail = (info->xmit.tail+count) & (SERIAL_XMIT_SIZE-1);
-
- /*
- * We have more at the beginning of the buffer
- */
- count = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if (count) {
- console->write(console, info->xmit.buf, count);
- info->xmit.tail += count;
- }
-out:
- local_irq_restore(flags);
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
- struct serial_state *info = tty->driver_data;
-
- if (info->xmit.head == info->xmit.tail || tty->stopped ||
- !info->xmit.buf)
- return;
-
- transmit_chars(tty, info, NULL);
-}
-
-static int rs_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- struct serial_state *info = tty->driver_data;
- int c, ret = 0;
- unsigned long flags;
-
- if (!info->xmit.buf)
- return 0;
-
- local_irq_save(flags);
- while (1) {
- c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0) {
- break;
- }
- memcpy(info->xmit.buf + info->xmit.head, buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- buf += c;
- count -= c;
- ret += c;
- }
- local_irq_restore(flags);
- /*
- * Hey, we transmit directly from here in our case
- */
- if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) &&
- !tty->stopped)
- transmit_chars(tty, info, NULL);
-
- return ret;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
- struct serial_state *info = tty->driver_data;
-
- return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
- struct serial_state *info = tty->driver_data;
-
- return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
- struct serial_state *info = tty->driver_data;
- unsigned long flags;
-
- local_irq_save(flags);
- info->xmit.head = info->xmit.tail = 0;
- local_irq_restore(flags);
-
- tty_wakeup(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_send_xchar(struct tty_struct *tty, char ch)
-{
- struct serial_state *info = tty->driver_data;
-
- info->x_char = ch;
- if (ch) {
- /*
- * I guess we could call console->write() directly but
- * let's do that for now.
- */
- transmit_chars(tty, info, NULL);
- }
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
- if (I_IXOFF(tty))
- rs_send_xchar(tty, STOP_CHAR(tty));
-
- printk(KERN_INFO "simrs_throttle called\n");
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
- struct serial_state *info = tty->driver_data;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- rs_send_xchar(tty, START_CHAR(tty));
- }
- printk(KERN_INFO "simrs_unthrottle called\n");
-}
-
-static int rs_setserial(struct tty_struct *tty, struct serial_struct *ss)
-{
- return 0;
-}
-
-static int rs_getserial(struct tty_struct *tty, struct serial_struct *ss)
-{
- return 0;
-}
-
-static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
- if ((cmd != TIOCSERCONFIG) && (cmd != TIOCMIWAIT)) {
- if (tty_io_error(tty))
- return -EIO;
- }
-
- switch (cmd) {
- case TIOCMIWAIT:
- return 0;
- case TIOCSERCONFIG:
- case TIOCSERGETLSR: /* Get line status register */
- return -EINVAL;
- }
- return -ENOIOCTLCMD;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct tty_port *port)
-{
- struct serial_state *info = container_of(port, struct serial_state,
- port);
- unsigned long flags;
-
- local_irq_save(flags);
- if (info->irq)
- free_irq(info->irq, info);
-
- if (info->xmit.buf) {
- free_page((unsigned long) info->xmit.buf);
- info->xmit.buf = NULL;
- }
- local_irq_restore(flags);
-}
-
-static void rs_close(struct tty_struct *tty, struct file * filp)
-{
- struct serial_state *info = tty->driver_data;
-
- tty_port_close(&info->port, tty, filp);
-}
-
-static void rs_hangup(struct tty_struct *tty)
-{
- struct serial_state *info = tty->driver_data;
-
- rs_flush_buffer(tty);
- tty_port_hangup(&info->port);
-}
-
-static int activate(struct tty_port *port, struct tty_struct *tty)
-{
- struct serial_state *state = container_of(port, struct serial_state,
- port);
- unsigned long flags, page;
- int retval = 0;
-
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- local_irq_save(flags);
-
- if (state->xmit.buf)
- free_page(page);
- else
- state->xmit.buf = (unsigned char *) page;
-
- if (state->irq) {
- retval = request_irq(state->irq, rs_interrupt_single, 0,
- "simserial", state);
- if (retval)
- goto errout;
- }
-
- state->xmit.head = state->xmit.tail = 0;
-errout:
- local_irq_restore(flags);
- return retval;
-}
-
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_open(struct tty_struct *tty, struct file * filp)
-{
- struct serial_state *info = rs_table + tty->index;
- struct tty_port *port = &info->port;
-
- tty->driver_data = info;
- port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- /*
- * figure out which console to use (should be one already)
- */
- console = console_drivers;
- while (console) {
- if ((console->flags & CON_ENABLED) && console->write) break;
- console = console->next;
- }
-
- return tty_port_open(port, tty, filp);
-}
-
-/*
- * /proc fs routines....
- */
-
-static int rs_proc_show(struct seq_file *m, void *v)
-{
- int i;
-
- seq_printf(m, "simserinfo:1.0\n");
- for (i = 0; i < NR_PORTS; i++)
- seq_printf(m, "%d: uart:16550 port:3F8 irq:%d\n",
- i, rs_table[i].irq);
- return 0;
-}
-
-static const struct tty_operations hp_ops = {
- .open = rs_open,
- .close = rs_close,
- .write = rs_write,
- .put_char = rs_put_char,
- .flush_chars = rs_flush_chars,
- .write_room = rs_write_room,
- .chars_in_buffer = rs_chars_in_buffer,
- .flush_buffer = rs_flush_buffer,
- .ioctl = rs_ioctl,
- .throttle = rs_throttle,
- .unthrottle = rs_unthrottle,
- .send_xchar = rs_send_xchar,
- .set_serial = rs_setserial,
- .get_serial = rs_getserial,
- .hangup = rs_hangup,
- .proc_show = rs_proc_show,
-};
-
-static const struct tty_port_operations hp_port_ops = {
- .activate = activate,
- .shutdown = shutdown,
-};
-
-static int __init simrs_init(void)
-{
- struct serial_state *state;
- int retval;
-
- if (!ia64_platform_is("hpsim"))
- return -ENODEV;
-
- hp_simserial_driver = alloc_tty_driver(NR_PORTS);
- if (!hp_simserial_driver)
- return -ENOMEM;
-
- printk(KERN_INFO "SimSerial driver with no serial options enabled\n");
-
- /* Initialize the tty_driver structure */
-
- hp_simserial_driver->driver_name = "simserial";
- hp_simserial_driver->name = "ttyS";
- hp_simserial_driver->major = TTY_MAJOR;
- hp_simserial_driver->minor_start = 64;
- hp_simserial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- hp_simserial_driver->subtype = SERIAL_TYPE_NORMAL;
- hp_simserial_driver->init_termios = tty_std_termios;
- hp_simserial_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- hp_simserial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(hp_simserial_driver, &hp_ops);
-
- state = rs_table;
- tty_port_init(&state->port);
- state->port.ops = &hp_port_ops;
- state->port.close_delay = 0; /* XXX really 0? */
-
- retval = hpsim_get_irq(KEYBOARD_INTR);
- if (retval < 0) {
- printk(KERN_ERR "%s: out of interrupt vectors!\n",
- __func__);
- goto err_free_tty;
- }
-
- state->irq = retval;
-
- /* the port is imaginary */
- printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq);
-
- tty_port_link_device(&state->port, hp_simserial_driver, 0);
- retval = tty_register_driver(hp_simserial_driver);
- if (retval) {
- printk(KERN_ERR "Couldn't register simserial driver\n");
- goto err_free_tty;
- }
-
- return 0;
-err_free_tty:
- put_tty_driver(hp_simserial_driver);
- tty_port_destroy(&state->port);
- return retval;
-}
-
-#ifndef MODULE
-__initcall(simrs_init);
-#endif
diff --git a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile
deleted file mode 100644
index 46b37d820b59..000000000000
--- a/arch/ia64/hp/zx1/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# ia64/hp/zx1/Makefile
-#
-# Copyright (C) 2002 Hewlett Packard
-# Copyright (C) Alex Williamson (alex_williamson@hp.com)
-#
-
-obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o hpzx1_swiotlb_machvec.o
diff --git a/arch/ia64/hp/zx1/hpzx1_machvec.c b/arch/ia64/hp/zx1/hpzx1_machvec.c
deleted file mode 100644
index 32518b0f923e..000000000000
--- a/arch/ia64/hp/zx1/hpzx1_machvec.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACHVEC_PLATFORM_NAME hpzx1
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpzx1.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c b/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c
deleted file mode 100644
index 4392a96b3c58..000000000000
--- a/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#define MACHVEC_PLATFORM_NAME hpzx1_swiotlb
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpzx1_swiotlb.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h
index 0ea569040c5b..f886d4dc9d55 100644
--- a/arch/ia64/include/asm/acpi.h
+++ b/arch/ia64/include/asm/acpi.h
@@ -17,7 +17,7 @@
#include <linux/numa.h>
#include <asm/numa.h>
-#ifdef CONFIG_ACPI
+
extern int acpi_lapic;
#define acpi_disabled 0 /* ACPI always enabled on IA64 */
#define acpi_noirq 0 /* ACPI always enabled on IA64 */
@@ -28,34 +28,10 @@ static inline bool acpi_has_cpu_in_madt(void)
{
return !!acpi_lapic;
}
-#endif
+
#define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
static inline void disable_acpi(void) { }
-#ifdef CONFIG_IA64_GENERIC
-const char *acpi_get_sysname (void);
-#else
-static inline const char *acpi_get_sysname (void)
-{
-# if defined (CONFIG_IA64_HP_SIM)
- return "hpsim";
-# elif defined (CONFIG_IA64_HP_ZX1)
- return "hpzx1";
-# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
- return "hpzx1_swiotlb";
-# elif defined (CONFIG_IA64_SGI_SN2)
- return "sn2";
-# elif defined (CONFIG_IA64_SGI_UV)
- return "uv";
-# elif defined (CONFIG_IA64_DIG)
- return "dig";
-# elif defined(CONFIG_IA64_DIG_VTD)
- return "dig_vtd";
-# else
-# error Unknown platform. Fix acpi.c.
-# endif
-}
-#endif
int acpi_request_vector (u32 int_type);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index f7ec71e4001e..a5d9d788eede 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -6,17 +6,11 @@
* Copyright (C) 2003-2004 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
-#include <asm/machvec.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-debug.h>
-
extern const struct dma_map_ops *dma_ops;
-extern struct ia64_machine_vector ia64_mv;
-extern void set_iommu_machvec(void);
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
{
- return platform_dma_get_ops(NULL);
+ 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
index 23604d6a2cb2..59625e9c1f9c 100644
--- a/arch/ia64/include/asm/dma.h
+++ b/arch/ia64/include/asm/dma.h
@@ -12,11 +12,7 @@
extern unsigned long MAX_DMA_ADDRESS;
-#ifdef CONFIG_PCI
- extern int isa_dma_bridge_buggy;
-#else
-# define isa_dma_bridge_buggy (0)
-#endif
+extern int isa_dma_bridge_buggy;
#define free_dma(x)
diff --git a/arch/ia64/include/asm/hpsim.h b/arch/ia64/include/asm/hpsim.h
deleted file mode 100644
index 00fbd5cc8ab8..000000000000
--- a/arch/ia64/include/asm/hpsim.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASMIA64_HPSIM_H
-#define _ASMIA64_HPSIM_H
-
-#ifndef CONFIG_HP_SIMSERIAL_CONSOLE
-static inline int simcons_register(void) { return 1; }
-#else
-int simcons_register(void);
-#endif
-
-struct tty_driver;
-extern struct tty_driver *hp_simserial_driver;
-
-extern int hpsim_get_irq(int intr);
-void ia64_ctl_trace(long on);
-
-#endif
diff --git a/arch/ia64/include/asm/hw_irq.h b/arch/ia64/include/asm/hw_irq.h
index 5dd3c6485c3a..e6385c7bdeb0 100644
--- a/arch/ia64/include/asm/hw_irq.h
+++ b/arch/ia64/include/asm/hw_irq.h
@@ -12,7 +12,6 @@
#include <linux/types.h>
#include <linux/profile.h>
-#include <asm/machvec.h>
#include <asm/ptrace.h>
#include <asm/smp.h>
@@ -56,7 +55,7 @@ typedef u8 ia64_vector;
extern int ia64_first_device_vector;
extern int ia64_last_device_vector;
-#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_DIG))
+#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
@@ -127,7 +126,7 @@ extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
extern void ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action);
extern void destroy_and_reserve_irq (unsigned int irq);
-#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG))
+#ifdef CONFIG_SMP
extern int irq_prepare_move(int irq, int cpu);
extern void irq_complete_move(unsigned int irq);
#else
@@ -137,26 +136,10 @@ static inline void irq_complete_move(unsigned int irq) {}
static inline void ia64_native_resend_irq(unsigned int vector)
{
- platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
}
/*
- * Default implementations for the irq-descriptor API:
- */
-#ifndef CONFIG_IA64_GENERIC
-static inline ia64_vector __ia64_irq_to_vector(int irq)
-{
- return irq_cfg[irq].vector;
-}
-
-static inline unsigned int
-__ia64_local_vector_to_irq (ia64_vector vec)
-{
- return __this_cpu_read(vector_irq[vec]);
-}
-#endif
-
-/*
* 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
@@ -170,7 +153,7 @@ __ia64_local_vector_to_irq (ia64_vector vec)
static inline ia64_vector
irq_to_vector (int irq)
{
- return platform_irq_to_vector(irq);
+ return irq_cfg[irq].vector;
}
/*
@@ -181,7 +164,7 @@ irq_to_vector (int irq)
static inline unsigned int
local_vector_to_irq (ia64_vector vec)
{
- return platform_local_vector_to_irq(vec);
+ return __this_cpu_read(vector_irq[vec]);
}
#endif /* _ASM_IA64_HW_IRQ_H */
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index a511d62d447a..54e70c21352a 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -71,7 +71,6 @@ extern unsigned int num_io_spaces;
#define HAVE_ARCH_PIO_SIZE
#include <asm/intrinsics.h>
-#include <asm/machvec.h>
#include <asm/page.h>
#include <asm-generic/iomap.h>
@@ -129,25 +128,6 @@ __ia64_mk_io_addr (unsigned long port)
return (void *) (space->mmio_base | offset);
}
-#define __ia64_inb ___ia64_inb
-#define __ia64_inw ___ia64_inw
-#define __ia64_inl ___ia64_inl
-#define __ia64_outb ___ia64_outb
-#define __ia64_outw ___ia64_outw
-#define __ia64_outl ___ia64_outl
-#define __ia64_readb ___ia64_readb
-#define __ia64_readw ___ia64_readw
-#define __ia64_readl ___ia64_readl
-#define __ia64_readq ___ia64_readq
-#define __ia64_readb_relaxed ___ia64_readb
-#define __ia64_readw_relaxed ___ia64_readw
-#define __ia64_readl_relaxed ___ia64_readl
-#define __ia64_readq_relaxed ___ia64_readq
-#define __ia64_writeb ___ia64_writeb
-#define __ia64_writew ___ia64_writew
-#define __ia64_writel ___ia64_writel
-#define __ia64_writeq ___ia64_writeq
-
/*
* 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
@@ -156,8 +136,8 @@ __ia64_mk_io_addr (unsigned long port)
* during optimization, which is why we use "volatile" pointers.
*/
-static inline unsigned int
-___ia64_inb (unsigned long port)
+#define inb inb
+static inline unsigned int inb(unsigned long port)
{
volatile unsigned char *addr = __ia64_mk_io_addr(port);
unsigned char ret;
@@ -167,8 +147,8 @@ ___ia64_inb (unsigned long port)
return ret;
}
-static inline unsigned int
-___ia64_inw (unsigned long port)
+#define inw inw
+static inline unsigned int inw(unsigned long port)
{
volatile unsigned short *addr = __ia64_mk_io_addr(port);
unsigned short ret;
@@ -178,8 +158,8 @@ ___ia64_inw (unsigned long port)
return ret;
}
-static inline unsigned int
-___ia64_inl (unsigned long port)
+#define inl inl
+static inline unsigned int inl(unsigned long port)
{
volatile unsigned int *addr = __ia64_mk_io_addr(port);
unsigned int ret;
@@ -189,8 +169,8 @@ ___ia64_inl (unsigned long port)
return ret;
}
-static inline void
-___ia64_outb (unsigned char val, unsigned long port)
+#define outb outb
+static inline void outb(unsigned char val, unsigned long port)
{
volatile unsigned char *addr = __ia64_mk_io_addr(port);
@@ -198,8 +178,8 @@ ___ia64_outb (unsigned char val, unsigned long port)
__ia64_mf_a();
}
-static inline void
-___ia64_outw (unsigned short val, unsigned long port)
+#define outw outw
+static inline void outw(unsigned short val, unsigned long port)
{
volatile unsigned short *addr = __ia64_mk_io_addr(port);
@@ -207,8 +187,8 @@ ___ia64_outw (unsigned short val, unsigned long port)
__ia64_mf_a();
}
-static inline void
-___ia64_outl (unsigned int val, unsigned long port)
+#define outl outl
+static inline void outl(unsigned int val, unsigned long port)
{
volatile unsigned int *addr = __ia64_mk_io_addr(port);
@@ -216,199 +196,63 @@ ___ia64_outl (unsigned int val, unsigned long port)
__ia64_mf_a();
}
-static inline void
-__insb (unsigned long port, void *dst, unsigned long count)
+#define insb insb
+static inline void insb(unsigned long port, void *dst, unsigned long count)
{
unsigned char *dp = dst;
while (count--)
- *dp++ = platform_inb(port);
+ *dp++ = inb(port);
}
-static inline void
-__insw (unsigned long port, void *dst, unsigned long count)
+#define insw insw
+static inline void insw(unsigned long port, void *dst, unsigned long count)
{
unsigned short *dp = dst;
while (count--)
- put_unaligned(platform_inw(port), dp++);
+ put_unaligned(inw(port), dp++);
}
-static inline void
-__insl (unsigned long port, void *dst, unsigned long count)
+#define insl insl
+static inline void insl(unsigned long port, void *dst, unsigned long count)
{
unsigned int *dp = dst;
while (count--)
- put_unaligned(platform_inl(port), dp++);
+ put_unaligned(inl(port), dp++);
}
-static inline void
-__outsb (unsigned long port, const void *src, unsigned long count)
+#define outsb outsb
+static inline void outsb(unsigned long port, const void *src,
+ unsigned long count)
{
const unsigned char *sp = src;
while (count--)
- platform_outb(*sp++, port);
+ outb(*sp++, port);
}
-static inline void
-__outsw (unsigned long port, const void *src, unsigned long count)
+#define outsw outsw
+static inline void outsw(unsigned long port, const void *src,
+ unsigned long count)
{
const unsigned short *sp = src;
while (count--)
- platform_outw(get_unaligned(sp++), port);
+ outw(get_unaligned(sp++), port);
}
-static inline void
-__outsl (unsigned long port, const void *src, unsigned long count)
+#define outsl outsl
+static inline void outsl(unsigned long port, const void *src,
+ unsigned long count)
{
const unsigned int *sp = src;
while (count--)
- platform_outl(get_unaligned(sp++), port);
+ outl(get_unaligned(sp++), port);
}
-/*
- * Unfortunately, some platforms are broken and do not follow the IA-64 architecture
- * specification regarding legacy I/O support. Thus, we have to make these operations
- * platform dependent...
- */
-#define __inb platform_inb
-#define __inw platform_inw
-#define __inl platform_inl
-#define __outb platform_outb
-#define __outw platform_outw
-#define __outl platform_outl
-
-#define inb(p) __inb(p)
-#define inw(p) __inw(p)
-#define inl(p) __inl(p)
-#define insb(p,d,c) __insb(p,d,c)
-#define insw(p,d,c) __insw(p,d,c)
-#define insl(p,d,c) __insl(p,d,c)
-#define outb(v,p) __outb(v,p)
-#define outw(v,p) __outw(v,p)
-#define outl(v,p) __outl(v,p)
-#define outsb(p,s,c) __outsb(p,s,c)
-#define outsw(p,s,c) __outsw(p,s,c)
-#define outsl(p,s,c) __outsl(p,s,c)
-
-/*
- * The address passed to these functions are ioremap()ped already.
- *
- * We need these to be machine vectors since some platforms don't provide
- * DMA coherence via PIO reads (PCI drivers and the spec imply that this is
- * a good idea). Writes are ok though for all existing ia64 platforms (and
- * hopefully it'll stay that way).
- */
-static inline unsigned char
-___ia64_readb (const volatile void __iomem *addr)
-{
- return *(volatile unsigned char __force *)addr;
-}
-
-static inline unsigned short
-___ia64_readw (const volatile void __iomem *addr)
-{
- return *(volatile unsigned short __force *)addr;
-}
-
-static inline unsigned int
-___ia64_readl (const volatile void __iomem *addr)
-{
- return *(volatile unsigned int __force *) addr;
-}
-
-static inline unsigned long
-___ia64_readq (const volatile void __iomem *addr)
-{
- return *(volatile unsigned long __force *) addr;
-}
-
-static inline void
-__writeb (unsigned char val, volatile void __iomem *addr)
-{
- *(volatile unsigned char __force *) addr = val;
-}
-
-static inline void
-__writew (unsigned short val, volatile void __iomem *addr)
-{
- *(volatile unsigned short __force *) addr = val;
-}
-
-static inline void
-__writel (unsigned int val, volatile void __iomem *addr)
-{
- *(volatile unsigned int __force *) addr = val;
-}
-
-static inline void
-__writeq (unsigned long val, volatile void __iomem *addr)
-{
- *(volatile unsigned long __force *) addr = val;
-}
-
-#define __readb platform_readb
-#define __readw platform_readw
-#define __readl platform_readl
-#define __readq platform_readq
-#define __readb_relaxed platform_readb_relaxed
-#define __readw_relaxed platform_readw_relaxed
-#define __readl_relaxed platform_readl_relaxed
-#define __readq_relaxed platform_readq_relaxed
-
-#define readb(a) __readb((a))
-#define readw(a) __readw((a))
-#define readl(a) __readl((a))
-#define readq(a) __readq((a))
-#define readb_relaxed(a) __readb_relaxed((a))
-#define readw_relaxed(a) __readw_relaxed((a))
-#define readl_relaxed(a) __readl_relaxed((a))
-#define readq_relaxed(a) __readq_relaxed((a))
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_readq readq
-#define __raw_readb_relaxed readb_relaxed
-#define __raw_readw_relaxed readw_relaxed
-#define __raw_readl_relaxed readl_relaxed
-#define __raw_readq_relaxed readq_relaxed
-#define writeb(v,a) __writeb((v), (a))
-#define writew(v,a) __writew((v), (a))
-#define writel(v,a) __writel((v), (a))
-#define writeq(v,a) __writeq((v), (a))
-#define writeb_relaxed(v,a) __writeb((v), (a))
-#define writew_relaxed(v,a) __writew((v), (a))
-#define writel_relaxed(v,a) __writel((v), (a))
-#define writeq_relaxed(v,a) __writeq((v), (a))
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-#define __raw_writeq writeq
-
-#ifndef inb_p
-# define inb_p inb
-#endif
-#ifndef inw_p
-# define inw_p inw
-#endif
-#ifndef inl_p
-# define inl_p inl
-#endif
-
-#ifndef outb_p
-# define outb_p outb
-#endif
-#ifndef outw_p
-# define outw_p outw
-#endif
-#ifndef outl_p
-# define outl_p outl
-#endif
-
# ifdef __KERNEL__
extern void __iomem * ioremap(unsigned long offset, unsigned long size);
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h
index 7429a72f3f92..7904f591a79b 100644
--- a/arch/ia64/include/asm/iommu.h
+++ b/arch/ia64/include/asm/iommu.h
@@ -8,13 +8,10 @@
extern void no_iommu_init(void);
#ifdef CONFIG_INTEL_IOMMU
extern int force_iommu, no_iommu;
-extern int iommu_pass_through;
extern int iommu_detected;
#else
-#define iommu_pass_through (0)
#define no_iommu (1)
#define iommu_detected (0)
#endif
-extern void machvec_init(const char *name);
#endif
diff --git a/arch/ia64/include/asm/iosapic.h b/arch/ia64/include/asm/iosapic.h
index f48556cb8afc..a91aeb413e17 100644
--- a/arch/ia64/include/asm/iosapic.h
+++ b/arch/ia64/include/asm/iosapic.h
@@ -52,8 +52,6 @@
#ifndef __ASSEMBLY__
-#ifdef CONFIG_IOSAPIC
-
#define NR_IOSAPICS 256
#define iosapic_pcat_compat_init ia64_native_iosapic_pcat_compat_init
@@ -103,16 +101,6 @@ extern int __init iosapic_register_platform_intr (u32 int_type,
#ifdef CONFIG_NUMA
extern void map_iosapic_to_node (unsigned int, int);
#endif
-#else
-#define iosapic_system_init(pcat_compat) do { } while (0)
-#define iosapic_init(address,gsi_base) (-EINVAL)
-#define iosapic_remove(gsi_base) (-ENODEV)
-#define iosapic_register_intr(gsi,polarity,trigger) (gsi)
-#define iosapic_unregister_intr(irq) do { } while (0)
-#define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger) do { } while (0)
-#define iosapic_register_platform_intr(type,gsi,pmi,eid,id, \
- polarity,trigger) (gsi)
-#endif
# endif /* !__ASSEMBLY__ */
#endif /* __ASM_IA64_IOSAPIC_H */
diff --git a/arch/ia64/include/asm/irq.h b/arch/ia64/include/asm/irq.h
index 8b84a55ed38a..5acf52e90872 100644
--- a/arch/ia64/include/asm/irq.h
+++ b/arch/ia64/include/asm/irq.h
@@ -28,9 +28,6 @@ irq_canonicalize (int irq)
}
extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
-bool is_affinity_mask_valid(const struct cpumask *cpumask);
-
-#define is_affinity_mask_valid is_affinity_mask_valid
int create_irq(void);
void destroy_irq(unsigned int irq);
diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h
deleted file mode 100644
index beae261fbcb4..000000000000
--- a/arch/ia64/include/asm/machvec.h
+++ /dev/null
@@ -1,347 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Machine vector for IA-64.
- *
- * Copyright (C) 1999 Silicon Graphics, Inc.
- * Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
- * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
- * Copyright (C) 1999-2001, 2003-2004 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _ASM_IA64_MACHVEC_H
-#define _ASM_IA64_MACHVEC_H
-
-#include <linux/types.h>
-
-/* forward declarations: */
-struct device;
-struct pt_regs;
-struct scatterlist;
-struct page;
-struct mm_struct;
-struct pci_bus;
-struct task_struct;
-struct pci_dev;
-struct msi_desc;
-
-typedef void ia64_mv_setup_t (char **);
-typedef void ia64_mv_cpu_init_t (void);
-typedef void ia64_mv_irq_init_t (void);
-typedef void ia64_mv_send_ipi_t (int, int, int, int);
-typedef void ia64_mv_timer_interrupt_t (int, void *);
-typedef void ia64_mv_global_tlb_purge_t (struct mm_struct *, unsigned long, unsigned long, unsigned long);
-typedef u8 ia64_mv_irq_to_vector (int);
-typedef unsigned int ia64_mv_local_vector_to_irq (u8);
-typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *);
-typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
- u8 size);
-typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
- u8 size);
-typedef void ia64_mv_migrate_t(struct task_struct * task);
-typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *);
-typedef void ia64_mv_kernel_launch_event_t(void);
-
-/* DMA-mapping interface: */
-typedef void ia64_mv_dma_init (void);
-typedef const struct dma_map_ops *ia64_mv_dma_get_ops(struct device *);
-
-/*
- * WARNING: The legacy I/O space is _architected_. Platforms are
- * expected to follow this architected model (see Section 10.7 in the
- * IA-64 Architecture Software Developer's Manual). Unfortunately,
- * some broken machines do not follow that model, which is why we have
- * to make the inX/outX operations part of the machine vector.
- * Platform designers should follow the architected model whenever
- * possible.
- */
-typedef unsigned int ia64_mv_inb_t (unsigned long);
-typedef unsigned int ia64_mv_inw_t (unsigned long);
-typedef unsigned int ia64_mv_inl_t (unsigned long);
-typedef void ia64_mv_outb_t (unsigned char, unsigned long);
-typedef void ia64_mv_outw_t (unsigned short, unsigned long);
-typedef void ia64_mv_outl_t (unsigned int, unsigned long);
-typedef void ia64_mv_mmiowb_t (void);
-typedef unsigned char ia64_mv_readb_t (const volatile void __iomem *);
-typedef unsigned short ia64_mv_readw_t (const volatile void __iomem *);
-typedef unsigned int ia64_mv_readl_t (const volatile void __iomem *);
-typedef unsigned long ia64_mv_readq_t (const volatile void __iomem *);
-typedef unsigned char ia64_mv_readb_relaxed_t (const volatile void __iomem *);
-typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
-typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
-typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
-
-typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *);
-typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
-
-static inline void
-machvec_noop (void)
-{
-}
-
-static inline void
-machvec_noop_task (struct task_struct *task)
-{
-}
-
-static inline void
-machvec_noop_bus (struct pci_bus *bus)
-{
-}
-
-extern void machvec_setup (char **);
-extern void machvec_timer_interrupt (int, void *);
-
-# if defined (CONFIG_IA64_HP_SIM)
-# include <asm/machvec_hpsim.h>
-# elif defined (CONFIG_IA64_DIG)
-# include <asm/machvec_dig.h>
-# elif defined(CONFIG_IA64_DIG_VTD)
-# include <asm/machvec_dig_vtd.h>
-# elif defined (CONFIG_IA64_HP_ZX1)
-# include <asm/machvec_hpzx1.h>
-# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
-# include <asm/machvec_hpzx1_swiotlb.h>
-# elif defined (CONFIG_IA64_SGI_SN2)
-# include <asm/machvec_sn2.h>
-# elif defined (CONFIG_IA64_SGI_UV)
-# include <asm/machvec_uv.h>
-# elif defined (CONFIG_IA64_GENERIC)
-
-# ifdef MACHVEC_PLATFORM_HEADER
-# include MACHVEC_PLATFORM_HEADER
-# else
-# define ia64_platform_name ia64_mv.name
-# define platform_setup ia64_mv.setup
-# define platform_cpu_init ia64_mv.cpu_init
-# define platform_irq_init ia64_mv.irq_init
-# define platform_send_ipi ia64_mv.send_ipi
-# define platform_timer_interrupt ia64_mv.timer_interrupt
-# define platform_global_tlb_purge ia64_mv.global_tlb_purge
-# define platform_dma_init ia64_mv.dma_init
-# define platform_dma_get_ops ia64_mv.dma_get_ops
-# define platform_irq_to_vector ia64_mv.irq_to_vector
-# define platform_local_vector_to_irq ia64_mv.local_vector_to_irq
-# define platform_pci_get_legacy_mem ia64_mv.pci_get_legacy_mem
-# define platform_pci_legacy_read ia64_mv.pci_legacy_read
-# define platform_pci_legacy_write ia64_mv.pci_legacy_write
-# define platform_inb ia64_mv.inb
-# define platform_inw ia64_mv.inw
-# define platform_inl ia64_mv.inl
-# define platform_outb ia64_mv.outb
-# define platform_outw ia64_mv.outw
-# define platform_outl ia64_mv.outl
-# define platform_mmiowb ia64_mv.mmiowb
-# define platform_readb ia64_mv.readb
-# define platform_readw ia64_mv.readw
-# define platform_readl ia64_mv.readl
-# define platform_readq ia64_mv.readq
-# define platform_readb_relaxed ia64_mv.readb_relaxed
-# define platform_readw_relaxed ia64_mv.readw_relaxed
-# define platform_readl_relaxed ia64_mv.readl_relaxed
-# define platform_readq_relaxed ia64_mv.readq_relaxed
-# define platform_migrate ia64_mv.migrate
-# define platform_setup_msi_irq ia64_mv.setup_msi_irq
-# define platform_teardown_msi_irq ia64_mv.teardown_msi_irq
-# define platform_pci_fixup_bus ia64_mv.pci_fixup_bus
-# define platform_kernel_launch_event ia64_mv.kernel_launch_event
-# endif
-
-/* __attribute__((__aligned__(16))) is required to make size of the
- * structure multiple of 16 bytes.
- * This will fillup the holes created because of section 3.3.1 in
- * Software Conventions guide.
- */
-struct ia64_machine_vector {
- const char *name;
- ia64_mv_setup_t *setup;
- ia64_mv_cpu_init_t *cpu_init;
- ia64_mv_irq_init_t *irq_init;
- ia64_mv_send_ipi_t *send_ipi;
- ia64_mv_timer_interrupt_t *timer_interrupt;
- ia64_mv_global_tlb_purge_t *global_tlb_purge;
- ia64_mv_dma_init *dma_init;
- ia64_mv_dma_get_ops *dma_get_ops;
- ia64_mv_irq_to_vector *irq_to_vector;
- ia64_mv_local_vector_to_irq *local_vector_to_irq;
- ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
- ia64_mv_pci_legacy_read_t *pci_legacy_read;
- ia64_mv_pci_legacy_write_t *pci_legacy_write;
- ia64_mv_inb_t *inb;
- ia64_mv_inw_t *inw;
- ia64_mv_inl_t *inl;
- ia64_mv_outb_t *outb;
- ia64_mv_outw_t *outw;
- ia64_mv_outl_t *outl;
- ia64_mv_mmiowb_t *mmiowb;
- ia64_mv_readb_t *readb;
- ia64_mv_readw_t *readw;
- ia64_mv_readl_t *readl;
- ia64_mv_readq_t *readq;
- ia64_mv_readb_relaxed_t *readb_relaxed;
- ia64_mv_readw_relaxed_t *readw_relaxed;
- ia64_mv_readl_relaxed_t *readl_relaxed;
- ia64_mv_readq_relaxed_t *readq_relaxed;
- ia64_mv_migrate_t *migrate;
- ia64_mv_setup_msi_irq_t *setup_msi_irq;
- ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
- ia64_mv_pci_fixup_bus_t *pci_fixup_bus;
- ia64_mv_kernel_launch_event_t *kernel_launch_event;
-} __attribute__((__aligned__(16))); /* align attrib? see above comment */
-
-#define MACHVEC_INIT(name) \
-{ \
- #name, \
- platform_setup, \
- platform_cpu_init, \
- platform_irq_init, \
- platform_send_ipi, \
- platform_timer_interrupt, \
- platform_global_tlb_purge, \
- platform_dma_init, \
- platform_dma_get_ops, \
- platform_irq_to_vector, \
- platform_local_vector_to_irq, \
- platform_pci_get_legacy_mem, \
- platform_pci_legacy_read, \
- platform_pci_legacy_write, \
- platform_inb, \
- platform_inw, \
- platform_inl, \
- platform_outb, \
- platform_outw, \
- platform_outl, \
- platform_mmiowb, \
- platform_readb, \
- platform_readw, \
- platform_readl, \
- platform_readq, \
- platform_readb_relaxed, \
- platform_readw_relaxed, \
- platform_readl_relaxed, \
- platform_readq_relaxed, \
- platform_migrate, \
- platform_setup_msi_irq, \
- platform_teardown_msi_irq, \
- platform_pci_fixup_bus, \
- platform_kernel_launch_event \
-}
-
-extern struct ia64_machine_vector ia64_mv;
-extern void machvec_init (const char *name);
-extern void machvec_init_from_cmdline(const char *cmdline);
-
-# else
-# error Unknown configuration. Update arch/ia64/include/asm/machvec.h.
-# endif /* CONFIG_IA64_GENERIC */
-
-extern void swiotlb_dma_init(void);
-extern const struct dma_map_ops *dma_get_ops(struct device *);
-
-/*
- * Define default versions so we can extend machvec for new platforms without having
- * to update the machvec files for all existing platforms.
- */
-#ifndef platform_setup
-# define platform_setup machvec_setup
-#endif
-#ifndef platform_cpu_init
-# define platform_cpu_init machvec_noop
-#endif
-#ifndef platform_irq_init
-# define platform_irq_init machvec_noop
-#endif
-
-#ifndef platform_send_ipi
-# define platform_send_ipi ia64_send_ipi /* default to architected version */
-#endif
-#ifndef platform_timer_interrupt
-# define platform_timer_interrupt machvec_timer_interrupt
-#endif
-#ifndef platform_global_tlb_purge
-# define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */
-#endif
-#ifndef platform_kernel_launch_event
-# define platform_kernel_launch_event machvec_noop
-#endif
-#ifndef platform_dma_init
-# define platform_dma_init swiotlb_dma_init
-#endif
-#ifndef platform_dma_get_ops
-# define platform_dma_get_ops dma_get_ops
-#endif
-#ifndef platform_irq_to_vector
-# define platform_irq_to_vector __ia64_irq_to_vector
-#endif
-#ifndef platform_local_vector_to_irq
-# define platform_local_vector_to_irq __ia64_local_vector_to_irq
-#endif
-#ifndef platform_pci_get_legacy_mem
-# define platform_pci_get_legacy_mem ia64_pci_get_legacy_mem
-#endif
-#ifndef platform_pci_legacy_read
-# define platform_pci_legacy_read ia64_pci_legacy_read
-extern int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size);
-#endif
-#ifndef platform_pci_legacy_write
-# define platform_pci_legacy_write ia64_pci_legacy_write
-extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size);
-#endif
-#ifndef platform_inb
-# define platform_inb __ia64_inb
-#endif
-#ifndef platform_inw
-# define platform_inw __ia64_inw
-#endif
-#ifndef platform_inl
-# define platform_inl __ia64_inl
-#endif
-#ifndef platform_outb
-# define platform_outb __ia64_outb
-#endif
-#ifndef platform_outw
-# define platform_outw __ia64_outw
-#endif
-#ifndef platform_outl
-# define platform_outl __ia64_outl
-#endif
-#ifndef platform_mmiowb
-# define platform_mmiowb __ia64_mmiowb
-#endif
-#ifndef platform_readb
-# define platform_readb __ia64_readb
-#endif
-#ifndef platform_readw
-# define platform_readw __ia64_readw
-#endif
-#ifndef platform_readl
-# define platform_readl __ia64_readl
-#endif
-#ifndef platform_readq
-# define platform_readq __ia64_readq
-#endif
-#ifndef platform_readb_relaxed
-# define platform_readb_relaxed __ia64_readb_relaxed
-#endif
-#ifndef platform_readw_relaxed
-# define platform_readw_relaxed __ia64_readw_relaxed
-#endif
-#ifndef platform_readl_relaxed
-# define platform_readl_relaxed __ia64_readl_relaxed
-#endif
-#ifndef platform_readq_relaxed
-# define platform_readq_relaxed __ia64_readq_relaxed
-#endif
-#ifndef platform_migrate
-# define platform_migrate machvec_noop_task
-#endif
-#ifndef platform_setup_msi_irq
-# define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
-#endif
-#ifndef platform_teardown_msi_irq
-# define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
-#endif
-#ifndef platform_pci_fixup_bus
-# define platform_pci_fixup_bus machvec_noop_bus
-#endif
-
-#endif /* _ASM_IA64_MACHVEC_H */
diff --git a/arch/ia64/include/asm/machvec_dig.h b/arch/ia64/include/asm/machvec_dig.h
deleted file mode 100644
index bc230f69faeb..000000000000
--- a/arch/ia64/include/asm/machvec_dig.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MACHVEC_DIG_h
-#define _ASM_IA64_MACHVEC_DIG_h
-
-extern ia64_mv_setup_t dig_setup;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "dig"
-#define platform_setup dig_setup
-
-#endif /* _ASM_IA64_MACHVEC_DIG_h */
diff --git a/arch/ia64/include/asm/machvec_dig_vtd.h b/arch/ia64/include/asm/machvec_dig_vtd.h
deleted file mode 100644
index bb44eb9039dd..000000000000
--- a/arch/ia64/include/asm/machvec_dig_vtd.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h
-#define _ASM_IA64_MACHVEC_DIG_VTD_h
-
-extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_dma_init pci_iommu_alloc;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "dig_vtd"
-#define platform_setup dig_setup
-#define platform_dma_init pci_iommu_alloc
-
-#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */
diff --git a/arch/ia64/include/asm/machvec_hpsim.h b/arch/ia64/include/asm/machvec_hpsim.h
deleted file mode 100644
index 056f8405822e..000000000000
--- a/arch/ia64/include/asm/machvec_hpsim.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MACHVEC_HPSIM_h
-#define _ASM_IA64_MACHVEC_HPSIM_h
-
-extern ia64_mv_setup_t hpsim_setup;
-extern ia64_mv_irq_init_t hpsim_irq_init;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "hpsim"
-#define platform_setup hpsim_setup
-#define platform_irq_init hpsim_irq_init
-
-#endif /* _ASM_IA64_MACHVEC_HPSIM_h */
diff --git a/arch/ia64/include/asm/machvec_hpzx1.h b/arch/ia64/include/asm/machvec_hpzx1.h
deleted file mode 100644
index 5299ac38bfb6..000000000000
--- a/arch/ia64/include/asm/machvec_hpzx1.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MACHVEC_HPZX1_h
-#define _ASM_IA64_MACHVEC_HPZX1_h
-
-extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_dma_init sba_dma_init;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "hpzx1"
-#define platform_setup dig_setup
-#define platform_dma_init sba_dma_init
-
-#endif /* _ASM_IA64_MACHVEC_HPZX1_h */
diff --git a/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h b/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h
deleted file mode 100644
index 5aec6a008c61..000000000000
--- a/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
-#define _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
-
-extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_dma_get_ops hwsw_dma_get_ops;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "hpzx1_swiotlb"
-#define platform_setup dig_setup
-#define platform_dma_init machvec_noop
-#define platform_dma_get_ops hwsw_dma_get_ops
-
-#endif /* _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h */
diff --git a/arch/ia64/include/asm/machvec_init.h b/arch/ia64/include/asm/machvec_init.h
deleted file mode 100644
index 2aafb69a3787..000000000000
--- a/arch/ia64/include/asm/machvec_init.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/iommu.h>
-#include <asm/machvec.h>
-
-extern ia64_mv_send_ipi_t ia64_send_ipi;
-extern ia64_mv_global_tlb_purge_t ia64_global_tlb_purge;
-extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
-extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
-extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
-extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read;
-extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write;
-
-extern ia64_mv_inb_t __ia64_inb;
-extern ia64_mv_inw_t __ia64_inw;
-extern ia64_mv_inl_t __ia64_inl;
-extern ia64_mv_outb_t __ia64_outb;
-extern ia64_mv_outw_t __ia64_outw;
-extern ia64_mv_outl_t __ia64_outl;
-extern ia64_mv_mmiowb_t __ia64_mmiowb;
-extern ia64_mv_readb_t __ia64_readb;
-extern ia64_mv_readw_t __ia64_readw;
-extern ia64_mv_readl_t __ia64_readl;
-extern ia64_mv_readq_t __ia64_readq;
-extern ia64_mv_readb_t __ia64_readb_relaxed;
-extern ia64_mv_readw_t __ia64_readw_relaxed;
-extern ia64_mv_readl_t __ia64_readl_relaxed;
-extern ia64_mv_readq_t __ia64_readq_relaxed;
-
-#define MACHVEC_HELPER(name) \
- struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec"))) \
- = MACHVEC_INIT(name);
-
-#define MACHVEC_DEFINE(name) MACHVEC_HELPER(name)
-
-MACHVEC_DEFINE(MACHVEC_PLATFORM_NAME)
diff --git a/arch/ia64/include/asm/machvec_sn2.h b/arch/ia64/include/asm/machvec_sn2.h
deleted file mode 100644
index a243e4fb4877..000000000000
--- a/arch/ia64/include/asm/machvec_sn2.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2002-2003,2006 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#ifndef _ASM_IA64_MACHVEC_SN2_H
-#define _ASM_IA64_MACHVEC_SN2_H
-
-extern ia64_mv_setup_t sn_setup;
-extern ia64_mv_cpu_init_t sn_cpu_init;
-extern ia64_mv_irq_init_t sn_irq_init;
-extern ia64_mv_send_ipi_t sn2_send_IPI;
-extern ia64_mv_timer_interrupt_t sn_timer_interrupt;
-extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge;
-extern ia64_mv_irq_to_vector sn_irq_to_vector;
-extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
-extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem;
-extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read;
-extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write;
-extern ia64_mv_inb_t __sn_inb;
-extern ia64_mv_inw_t __sn_inw;
-extern ia64_mv_inl_t __sn_inl;
-extern ia64_mv_outb_t __sn_outb;
-extern ia64_mv_outw_t __sn_outw;
-extern ia64_mv_outl_t __sn_outl;
-extern ia64_mv_mmiowb_t __sn_mmiowb;
-extern ia64_mv_readb_t __sn_readb;
-extern ia64_mv_readw_t __sn_readw;
-extern ia64_mv_readl_t __sn_readl;
-extern ia64_mv_readq_t __sn_readq;
-extern ia64_mv_readb_t __sn_readb_relaxed;
-extern ia64_mv_readw_t __sn_readw_relaxed;
-extern ia64_mv_readl_t __sn_readl_relaxed;
-extern ia64_mv_readq_t __sn_readq_relaxed;
-extern ia64_mv_dma_init sn_dma_init;
-extern ia64_mv_migrate_t sn_migrate;
-extern ia64_mv_kernel_launch_event_t sn_kernel_launch_event;
-extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
-extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
-extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus;
-
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "sn2"
-#define platform_setup sn_setup
-#define platform_cpu_init sn_cpu_init
-#define platform_irq_init sn_irq_init
-#define platform_send_ipi sn2_send_IPI
-#define platform_timer_interrupt sn_timer_interrupt
-#define platform_global_tlb_purge sn2_global_tlb_purge
-#define platform_pci_fixup sn_pci_fixup
-#define platform_inb __sn_inb
-#define platform_inw __sn_inw
-#define platform_inl __sn_inl
-#define platform_outb __sn_outb
-#define platform_outw __sn_outw
-#define platform_outl __sn_outl
-#define platform_mmiowb __sn_mmiowb
-#define platform_readb __sn_readb
-#define platform_readw __sn_readw
-#define platform_readl __sn_readl
-#define platform_readq __sn_readq
-#define platform_readb_relaxed __sn_readb_relaxed
-#define platform_readw_relaxed __sn_readw_relaxed
-#define platform_readl_relaxed __sn_readl_relaxed
-#define platform_readq_relaxed __sn_readq_relaxed
-#define platform_irq_to_vector sn_irq_to_vector
-#define platform_local_vector_to_irq sn_local_vector_to_irq
-#define platform_pci_get_legacy_mem sn_pci_get_legacy_mem
-#define platform_pci_legacy_read sn_pci_legacy_read
-#define platform_pci_legacy_write sn_pci_legacy_write
-#define platform_dma_init sn_dma_init
-#define platform_migrate sn_migrate
-#define platform_kernel_launch_event sn_kernel_launch_event
-#ifdef CONFIG_PCI_MSI
-#define platform_setup_msi_irq sn_setup_msi_irq
-#define platform_teardown_msi_irq sn_teardown_msi_irq
-#else
-#define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
-#define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
-#endif
-#define platform_pci_fixup_bus sn_pci_fixup_bus
-
-#include <asm/sn/io.h>
-
-#endif /* _ASM_IA64_MACHVEC_SN2_H */
diff --git a/arch/ia64/include/asm/machvec_uv.h b/arch/ia64/include/asm/machvec_uv.h
deleted file mode 100644
index 2c50853f35ac..000000000000
--- a/arch/ia64/include/asm/machvec_uv.h
+++ /dev/null
@@ -1,26 +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.
- */
-
-#ifndef _ASM_IA64_MACHVEC_UV_H
-#define _ASM_IA64_MACHVEC_UV_H
-
-extern ia64_mv_setup_t uv_setup;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure. When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name "uv"
-#define platform_setup uv_setup
-
-#endif /* _ASM_IA64_MACHVEC_UV_H */
diff --git a/arch/ia64/include/asm/mmiowb.h b/arch/ia64/include/asm/mmiowb.h
index 297b85ac84a0..d67aab4ea3b4 100644
--- a/arch/ia64/include/asm/mmiowb.h
+++ b/arch/ia64/include/asm/mmiowb.h
@@ -3,22 +3,14 @@
#ifndef _ASM_IA64_MMIOWB_H
#define _ASM_IA64_MMIOWB_H
-#include <asm/machvec.h>
-
/**
- * ___ia64_mmiowb - I/O write barrier
+ * 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.
*/
-static inline void ___ia64_mmiowb(void)
-{
- ia64_mfa();
-}
-
-#define __ia64_mmiowb ___ia64_mmiowb
-#define mmiowb() platform_mmiowb()
+#define mmiowb() ia64_mfa()
#include <asm-generic/mmiowb.h>
diff --git a/arch/ia64/include/asm/mmzone.h b/arch/ia64/include/asm/mmzone.h
index e0de61709cf1..767201f66c93 100644
--- a/arch/ia64/include/asm/mmzone.h
+++ b/arch/ia64/include/asm/mmzone.h
@@ -27,16 +27,9 @@ static inline int pfn_to_nid(unsigned long pfn)
return nid;
}
-#ifdef CONFIG_IA64_DIG /* DIG systems are small */
-# define MAX_PHYSNODE_ID 8
-# define NR_NODE_MEMBLKS (MAX_NUMNODES * 8)
-#else /* sn2 is the biggest case, so we use that if !DIG */
-# define MAX_PHYSNODE_ID 2048
-# define NR_NODE_MEMBLKS (MAX_NUMNODES * 4)
-#endif
-
-#else /* CONFIG_NUMA */
-# define NR_NODE_MEMBLKS (MAX_NUMNODES * 4)
+#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/pci.h b/arch/ia64/include/asm/pci.h
index 780e8744ba85..8c163d1d0189 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -39,9 +39,9 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state);
-#define pci_get_legacy_mem platform_pci_get_legacy_mem
-#define pci_legacy_read platform_pci_legacy_read
-#define pci_legacy_write platform_pci_legacy_write
+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;
@@ -69,7 +69,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
}
-#ifdef CONFIG_INTEL_IOMMU
-extern void pci_iommu_alloc(void);
-#endif
#endif /* _ASM_IA64_PCI_H */
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index c91ef98ed6bf..95a2ec37400f 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -679,8 +679,6 @@ enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
void default_idle(void);
-#define ia64_platform_is(x) (strcmp(x, ia64_platform_name) == 0)
-
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_IA64_PROCESSOR_H */
diff --git a/arch/ia64/include/asm/sal.h b/arch/ia64/include/asm/sal.h
index 588f33156da6..08f5b6aaed73 100644
--- a/arch/ia64/include/asm/sal.h
+++ b/arch/ia64/include/asm/sal.h
@@ -43,6 +43,7 @@
#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. */
diff --git a/arch/ia64/include/asm/sn/acpi.h b/arch/ia64/include/asm/sn/acpi.h
deleted file mode 100644
index fd480db25565..000000000000
--- a/arch/ia64/include/asm/sn/acpi.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) 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_ACPI_H
-#define _ASM_IA64_SN_ACPI_H
-
-extern int sn_acpi_rev;
-#define SN_ACPI_BASE_SUPPORT() (sn_acpi_rev >= 0x20101)
-
-#endif /* _ASM_IA64_SN_ACPI_H */
diff --git a/arch/ia64/include/asm/sn/addrs.h b/arch/ia64/include/asm/sn/addrs.h
deleted file mode 100644
index e715c794b186..000000000000
--- a/arch/ia64/include/asm/sn/addrs.h
+++ /dev/null
@@ -1,299 +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-1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_ADDRS_H
-#define _ASM_IA64_SN_ADDRS_H
-
-#include <asm/percpu.h>
-#include <asm/sn/types.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/pda.h>
-
-/*
- * Memory/SHUB Address Format:
- * +-+---------+--+--------------+
- * |0| NASID |AS| NodeOffset |
- * +-+---------+--+--------------+
- *
- * NASID: (low NASID bit is 0) Memory and SHUB MMRs
- * AS: 2-bit Address Space Identifier. Used only if low NASID bit is 0
- * 00: Local Resources and MMR space
- * Top bit of NodeOffset
- * 0: Local resources space
- * node id:
- * 0: IA64/NT compatibility space
- * 2: Local MMR Space
- * 4: Local memory, regardless of local node id
- * 1: Global MMR space
- * 01: GET space.
- * 10: AMO space.
- * 11: Cacheable memory space.
- *
- * NodeOffset: byte offset
- *
- *
- * TIO address format:
- * +-+----------+--+--------------+
- * |0| NASID |AS| Nodeoffset |
- * +-+----------+--+--------------+
- *
- * NASID: (low NASID bit is 1) TIO
- * AS: 2-bit Chiplet Identifier
- * 00: TIO LB (Indicates TIO MMR access.)
- * 01: TIO ICE (indicates coretalk space access.)
- *
- * NodeOffset: top bit must be set.
- *
- *
- * Note that in both of the above address formats, the low
- * NASID bit indicates if the reference is to the SHUB or TIO MMRs.
- */
-
-
-/*
- * Define basic shift & mask constants for manipulating NASIDs and AS values.
- */
-#define NASID_BITMASK (sn_hub_info->nasid_bitmask)
-#define NASID_SHIFT (sn_hub_info->nasid_shift)
-#define AS_SHIFT (sn_hub_info->as_shift)
-#define AS_BITMASK 0x3UL
-
-#define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT)
-#define AS_MASK ((u64)AS_BITMASK << AS_SHIFT)
-
-
-/*
- * AS values. These are the same on both SHUB1 & SHUB2.
- */
-#define AS_GET_VAL 1UL
-#define AS_AMO_VAL 2UL
-#define AS_CAC_VAL 3UL
-#define AS_GET_SPACE (AS_GET_VAL << AS_SHIFT)
-#define AS_AMO_SPACE (AS_AMO_VAL << AS_SHIFT)
-#define AS_CAC_SPACE (AS_CAC_VAL << AS_SHIFT)
-
-
-/*
- * Virtual Mode Local & Global MMR space.
- */
-#define SH1_LOCAL_MMR_OFFSET 0x8000000000UL
-#define SH2_LOCAL_MMR_OFFSET 0x0200000000UL
-#define LOCAL_MMR_OFFSET (is_shub2() ? SH2_LOCAL_MMR_OFFSET : SH1_LOCAL_MMR_OFFSET)
-#define LOCAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | LOCAL_MMR_OFFSET)
-#define LOCAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | LOCAL_MMR_OFFSET)
-
-#define SH1_GLOBAL_MMR_OFFSET 0x0800000000UL
-#define SH2_GLOBAL_MMR_OFFSET 0x0300000000UL
-#define GLOBAL_MMR_OFFSET (is_shub2() ? SH2_GLOBAL_MMR_OFFSET : SH1_GLOBAL_MMR_OFFSET)
-#define GLOBAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | GLOBAL_MMR_OFFSET)
-
-/*
- * Physical mode addresses
- */
-#define GLOBAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | GLOBAL_MMR_OFFSET)
-
-
-/*
- * Clear region & AS bits.
- */
-#define TO_PHYS_MASK (~(RGN_BITS | AS_MASK))
-
-
-/*
- * Misc NASID manipulation.
- */
-#define NASID_SPACE(n) ((u64)(n) << NASID_SHIFT)
-#define REMOTE_ADDR(n,a) (NASID_SPACE(n) | (a))
-#define NODE_OFFSET(x) ((x) & (NODE_ADDRSPACE_SIZE - 1))
-#define NODE_ADDRSPACE_SIZE (1UL << AS_SHIFT)
-#define NASID_GET(x) (int) (((u64) (x) >> NASID_SHIFT) & NASID_BITMASK)
-#define LOCAL_MMR_ADDR(a) (LOCAL_MMR_SPACE | (a))
-#define GLOBAL_MMR_ADDR(n,a) (GLOBAL_MMR_SPACE | REMOTE_ADDR(n,a))
-#define GLOBAL_MMR_PHYS_ADDR(n,a) (GLOBAL_PHYS_MMR_SPACE | REMOTE_ADDR(n,a))
-#define GLOBAL_CAC_ADDR(n,a) (CAC_BASE | REMOTE_ADDR(n,a))
-#define CHANGE_NASID(n,x) ((void *)(((u64)(x) & ~NASID_MASK) | NASID_SPACE(n)))
-#define IS_TIO_NASID(n) ((n) & 1)
-
-
-/* non-II mmr's start at top of big window space (4G) */
-#define BWIN_TOP 0x0000000100000000UL
-
-/*
- * general address defines
- */
-#define CAC_BASE (PAGE_OFFSET | AS_CAC_SPACE)
-#define AMO_BASE (__IA64_UNCACHED_OFFSET | AS_AMO_SPACE)
-#define AMO_PHYS_BASE (RGN_BASE(RGN_HPAGE) | AS_AMO_SPACE)
-#define GET_BASE (PAGE_OFFSET | AS_GET_SPACE)
-
-/*
- * Convert Memory addresses between various addressing modes.
- */
-#define TO_PHYS(x) (TO_PHYS_MASK & (x))
-#define TO_CAC(x) (CAC_BASE | TO_PHYS(x))
-#ifdef CONFIG_SGI_SN
-#define TO_AMO(x) (AMO_BASE | TO_PHYS(x))
-#define TO_GET(x) (GET_BASE | TO_PHYS(x))
-#else
-#define TO_AMO(x) ({ BUG(); x; })
-#define TO_GET(x) ({ BUG(); x; })
-#endif
-
-/*
- * Covert from processor physical address to II/TIO physical address:
- * II - squeeze out the AS bits
- * TIO- requires a chiplet id in bits 38-39. For DMA to memory,
- * the chiplet id is zero. If we implement TIO-TIO dma, we might need
- * to insert a chiplet id into this macro. However, it is our belief
- * right now that this chiplet id will be ICE, which is also zero.
- */
-#define SH1_TIO_PHYS_TO_DMA(x) \
- ((((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x))
-
-#define SH2_NETWORK_BANK_OFFSET(x) \
- ((u64)(x) & ((1UL << (sn_hub_info->nasid_shift - 4)) -1))
-
-#define SH2_NETWORK_BANK_SELECT(x) \
- ((((u64)(x) & (0x3UL << (sn_hub_info->nasid_shift - 4))) \
- >> (sn_hub_info->nasid_shift - 4)) << 36)
-
-#define SH2_NETWORK_ADDRESS(x) \
- (SH2_NETWORK_BANK_OFFSET(x) | SH2_NETWORK_BANK_SELECT(x))
-
-#define SH2_TIO_PHYS_TO_DMA(x) \
- (((u64)(NASID_GET(x)) << 40) | SH2_NETWORK_ADDRESS(x))
-
-#define PHYS_TO_TIODMA(x) \
- (is_shub1() ? SH1_TIO_PHYS_TO_DMA(x) : SH2_TIO_PHYS_TO_DMA(x))
-
-#define PHYS_TO_DMA(x) \
- ((((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x))
-
-
-/*
- * Macros to test for address type.
- */
-#define IS_AMO_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_BASE)
-#define IS_AMO_PHYS_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_PHYS_BASE)
-
-
-/*
- * The following definitions pertain to the IO special address
- * space. They define the location of the big and little windows
- * of any given node.
- */
-#define BWIN_SIZE_BITS 29 /* big window size: 512M */
-#define TIO_BWIN_SIZE_BITS 30 /* big window size: 1G */
-#define NODE_SWIN_BASE(n, w) ((w == 0) ? NODE_BWIN_BASE((n), SWIN0_BIGWIN) \
- : RAW_NODE_SWIN_BASE(n, w))
-#define TIO_SWIN_BASE(n, w) (TIO_IO_BASE(n) + \
- ((u64) (w) << TIO_SWIN_SIZE_BITS))
-#define NODE_IO_BASE(n) (GLOBAL_MMR_SPACE | NASID_SPACE(n))
-#define TIO_IO_BASE(n) (__IA64_UNCACHED_OFFSET | NASID_SPACE(n))
-#define BWIN_SIZE (1UL << BWIN_SIZE_BITS)
-#define NODE_BWIN_BASE0(n) (NODE_IO_BASE(n) + BWIN_SIZE)
-#define NODE_BWIN_BASE(n, w) (NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS))
-#define RAW_NODE_SWIN_BASE(n, w) (NODE_IO_BASE(n) + ((u64) (w) << SWIN_SIZE_BITS))
-#define BWIN_WIDGET_MASK 0x7
-#define BWIN_WINDOWNUM(x) (((x) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK)
-#define SH1_IS_BIG_WINDOW_ADDR(x) ((x) & BWIN_TOP)
-
-#define TIO_BWIN_WINDOW_SELECT_MASK 0x7
-#define TIO_BWIN_WINDOWNUM(x) (((x) >> TIO_BWIN_SIZE_BITS) & TIO_BWIN_WINDOW_SELECT_MASK)
-
-#define TIO_HWIN_SHIFT_BITS 33
-#define TIO_HWIN(x) (NODE_OFFSET(x) >> TIO_HWIN_SHIFT_BITS)
-
-/*
- * The following definitions pertain to the IO special address
- * space. They define the location of the big and little windows
- * of any given node.
- */
-
-#define SWIN_SIZE_BITS 24
-#define SWIN_WIDGET_MASK 0xF
-
-#define TIO_SWIN_SIZE_BITS 28
-#define TIO_SWIN_SIZE (1UL << TIO_SWIN_SIZE_BITS)
-#define TIO_SWIN_WIDGET_MASK 0x3
-
-/*
- * Convert smallwindow address to xtalk address.
- *
- * 'addr' can be physical or virtual address, but will be converted
- * to Xtalk address in the range 0 -> SWINZ_SIZEMASK
- */
-#define SWIN_WIDGETNUM(x) (((x) >> SWIN_SIZE_BITS) & SWIN_WIDGET_MASK)
-#define TIO_SWIN_WIDGETNUM(x) (((x) >> TIO_SWIN_SIZE_BITS) & TIO_SWIN_WIDGET_MASK)
-
-
-/*
- * The following macros produce the correct base virtual address for
- * the hub registers. The REMOTE_HUB_* macro produce
- * the address for the specified hub's registers. The intent is
- * that the appropriate PI, MD, NI, or II register would be substituted
- * for x.
- *
- * WARNING:
- * When certain Hub chip workaround are defined, it's not sufficient
- * to dereference the *_HUB_ADDR() macros. You should instead use
- * HUB_L() and HUB_S() if you must deal with pointers to hub registers.
- * Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S().
- * They're always safe.
- */
-/* Shub1 TIO & MMR addressing macros */
-#define SH1_TIO_IOSPACE_ADDR(n,x) \
- GLOBAL_MMR_ADDR(n,x)
-
-#define SH1_REMOTE_BWIN_MMR(n,x) \
- GLOBAL_MMR_ADDR(n,x)
-
-#define SH1_REMOTE_SWIN_MMR(n,x) \
- (NODE_SWIN_BASE(n,1) + 0x800000UL + (x))
-
-#define SH1_REMOTE_MMR(n,x) \
- (SH1_IS_BIG_WINDOW_ADDR(x) ? SH1_REMOTE_BWIN_MMR(n,x) : \
- SH1_REMOTE_SWIN_MMR(n,x))
-
-/* Shub1 TIO & MMR addressing macros */
-#define SH2_TIO_IOSPACE_ADDR(n,x) \
- ((__IA64_UNCACHED_OFFSET | REMOTE_ADDR(n,x) | 1UL << (NASID_SHIFT - 2)))
-
-#define SH2_REMOTE_MMR(n,x) \
- GLOBAL_MMR_ADDR(n,x)
-
-
-/* TIO & MMR addressing macros that work on both shub1 & shub2 */
-#define TIO_IOSPACE_ADDR(n,x) \
- ((u64 *)(is_shub1() ? SH1_TIO_IOSPACE_ADDR(n,x) : \
- SH2_TIO_IOSPACE_ADDR(n,x)))
-
-#define SH_REMOTE_MMR(n,x) \
- (is_shub1() ? SH1_REMOTE_MMR(n,x) : SH2_REMOTE_MMR(n,x))
-
-#define REMOTE_HUB_ADDR(n,x) \
- (IS_TIO_NASID(n) ? ((volatile u64*)TIO_IOSPACE_ADDR(n,x)) : \
- ((volatile u64*)SH_REMOTE_MMR(n,x)))
-
-
-#define HUB_L(x) (*((volatile typeof(*x) *)x))
-#define HUB_S(x,d) (*((volatile typeof(*x) *)x) = (d))
-
-#define REMOTE_HUB_L(n, a) HUB_L(REMOTE_HUB_ADDR((n), (a)))
-#define REMOTE_HUB_S(n, a, d) HUB_S(REMOTE_HUB_ADDR((n), (a)), (d))
-
-/*
- * Coretalk address breakdown
- */
-#define CTALK_NASID_SHFT 40
-#define CTALK_NASID_MASK (0x3FFFULL << CTALK_NASID_SHFT)
-#define CTALK_CID_SHFT 38
-#define CTALK_CID_MASK (0x3ULL << CTALK_CID_SHFT)
-#define CTALK_NODE_OFFSET 0x3FFFFFFFFF
-
-#endif /* _ASM_IA64_SN_ADDRS_H */
diff --git a/arch/ia64/include/asm/sn/arch.h b/arch/ia64/include/asm/sn/arch.h
deleted file mode 100644
index 31eb784866f8..000000000000
--- a/arch/ia64/include/asm/sn/arch.h
+++ /dev/null
@@ -1,86 +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 specific setup.
- *
- * Copyright (C) 1995-1997,1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- */
-#ifndef _ASM_IA64_SN_ARCH_H
-#define _ASM_IA64_SN_ARCH_H
-
-#include <linux/numa.h>
-#include <asm/types.h>
-#include <asm/percpu.h>
-#include <asm/sn/types.h>
-#include <asm/sn/sn_cpuid.h>
-
-/*
- * This is the maximum number of NUMALINK nodes that can be part of a single
- * SSI kernel. This number includes C-brick, M-bricks, and TIOs. Nodes in
- * remote partitions are NOT included in this number.
- * The number of compact nodes cannot exceed size of a coherency domain.
- * The purpose of this define is to specify a node count that includes
- * all C/M/TIO nodes in an SSI system.
- *
- * SGI system can currently support up to 256 C/M nodes plus additional TIO nodes.
- *
- * Note: ACPI20 has an architectural limit of 256 nodes. When we upgrade
- * to ACPI3.0, this limit will be removed. The notion of "compact nodes"
- * should be deleted and TIOs should be included in MAX_NUMNODES.
- */
-#define MAX_TIO_NODES MAX_NUMNODES
-#define MAX_COMPACT_NODES (MAX_NUMNODES + MAX_TIO_NODES)
-
-/*
- * Maximum number of nodes in all partitions and in all coherency domains.
- * This is the total number of nodes accessible in the numalink fabric. It
- * includes all C & M bricks, plus all TIOs.
- *
- * This value is also the value of the maximum number of NASIDs in the numalink
- * fabric.
- */
-#define MAX_NUMALINK_NODES 16384
-
-/*
- * The following defines attributes of the HUB chip. These attributes are
- * frequently referenced. They are kept in the per-cpu data areas of each cpu.
- * They are kept together in a struct to minimize cache misses.
- */
-struct sn_hub_info_s {
- u8 shub2;
- u8 nasid_shift;
- u8 as_shift;
- u8 shub_1_1_found;
- u16 nasid_bitmask;
-};
-DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
-#define sn_hub_info this_cpu_ptr(&__sn_hub_info)
-#define is_shub2() (sn_hub_info->shub2)
-#define is_shub1() (sn_hub_info->shub2 == 0)
-
-/*
- * Use this macro to test if shub 1.1 wars should be enabled
- */
-#define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found)
-
-
-/*
- * Compact node ID to nasid mappings kept in the per-cpu data areas of each
- * cpu.
- */
-DECLARE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]);
-#define sn_cnodeid_to_nasid this_cpu_ptr(&__sn_cnodeid_to_nasid[0])
-
-
-extern u8 sn_partition_id;
-extern u8 sn_system_size;
-extern u8 sn_sharing_domain_size;
-extern u8 sn_region_size;
-
-extern void sn_flush_all_caches(long addr, long bytes);
-extern bool sn_cpu_disable_allowed(int cpu);
-
-#endif /* _ASM_IA64_SN_ARCH_H */
diff --git a/arch/ia64/include/asm/sn/bte.h b/arch/ia64/include/asm/sn/bte.h
deleted file mode 100644
index cd71ab5faf62..000000000000
--- a/arch/ia64/include/asm/sn/bte.h
+++ /dev/null
@@ -1,236 +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-2007 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-
-#ifndef _ASM_IA64_SN_BTE_H
-#define _ASM_IA64_SN_BTE_H
-
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/cache.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/types.h>
-#include <asm/sn/shub_mmr.h>
-
-struct nodepda_s;
-
-#define IBCT_NOTIFY (0x1UL << 4)
-#define IBCT_ZFIL_MODE (0x1UL << 0)
-
-/* #define BTE_DEBUG */
-/* #define BTE_DEBUG_VERBOSE */
-
-#ifdef BTE_DEBUG
-# define BTE_PRINTK(x) printk x /* Terse */
-# ifdef BTE_DEBUG_VERBOSE
-# define BTE_PRINTKV(x) printk x /* Verbose */
-# else
-# define BTE_PRINTKV(x)
-# endif /* BTE_DEBUG_VERBOSE */
-#else
-# define BTE_PRINTK(x)
-# define BTE_PRINTKV(x)
-#endif /* BTE_DEBUG */
-
-
-/* BTE status register only supports 16 bits for length field */
-#define BTE_LEN_BITS (16)
-#define BTE_LEN_MASK ((1 << BTE_LEN_BITS) - 1)
-#define BTE_MAX_XFER (BTE_LEN_MASK << L1_CACHE_SHIFT)
-
-
-/* Define hardware */
-#define BTES_PER_NODE (is_shub2() ? 4 : 2)
-#define MAX_BTES_PER_NODE 4
-
-#define BTE2OFF_CTRL 0
-#define BTE2OFF_SRC (SH2_BT_ENG_SRC_ADDR_0 - SH2_BT_ENG_CSR_0)
-#define BTE2OFF_DEST (SH2_BT_ENG_DEST_ADDR_0 - SH2_BT_ENG_CSR_0)
-#define BTE2OFF_NOTIFY (SH2_BT_ENG_NOTIF_ADDR_0 - SH2_BT_ENG_CSR_0)
-
-#define BTE_BASE_ADDR(interface) \
- (is_shub2() ? (interface == 0) ? SH2_BT_ENG_CSR_0 : \
- (interface == 1) ? SH2_BT_ENG_CSR_1 : \
- (interface == 2) ? SH2_BT_ENG_CSR_2 : \
- SH2_BT_ENG_CSR_3 \
- : (interface == 0) ? IIO_IBLS0 : IIO_IBLS1)
-
-#define BTE_SOURCE_ADDR(base) \
- (is_shub2() ? base + (BTE2OFF_SRC/8) \
- : base + (BTEOFF_SRC/8))
-
-#define BTE_DEST_ADDR(base) \
- (is_shub2() ? base + (BTE2OFF_DEST/8) \
- : base + (BTEOFF_DEST/8))
-
-#define BTE_CTRL_ADDR(base) \
- (is_shub2() ? base + (BTE2OFF_CTRL/8) \
- : base + (BTEOFF_CTRL/8))
-
-#define BTE_NOTIF_ADDR(base) \
- (is_shub2() ? base + (BTE2OFF_NOTIFY/8) \
- : base + (BTEOFF_NOTIFY/8))
-
-/* Define hardware modes */
-#define BTE_NOTIFY IBCT_NOTIFY
-#define BTE_NORMAL BTE_NOTIFY
-#define BTE_ZERO_FILL (BTE_NOTIFY | IBCT_ZFIL_MODE)
-/* Use a reserved bit to let the caller specify a wait for any BTE */
-#define BTE_WACQUIRE 0x4000
-/* Use the BTE on the node with the destination memory */
-#define BTE_USE_DEST (BTE_WACQUIRE << 1)
-/* Use any available BTE interface on any node for the transfer */
-#define BTE_USE_ANY (BTE_USE_DEST << 1)
-/* macro to force the IBCT0 value valid */
-#define BTE_VALID_MODE(x) ((x) & (IBCT_NOTIFY | IBCT_ZFIL_MODE))
-
-#define BTE_ACTIVE (IBLS_BUSY | IBLS_ERROR)
-#define BTE_WORD_AVAILABLE (IBLS_BUSY << 1)
-#define BTE_WORD_BUSY (~BTE_WORD_AVAILABLE)
-
-/*
- * Some macros to simplify reading.
- * Start with macros to locate the BTE control registers.
- */
-#define BTE_LNSTAT_LOAD(_bte) \
- HUB_L(_bte->bte_base_addr)
-#define BTE_LNSTAT_STORE(_bte, _x) \
- HUB_S(_bte->bte_base_addr, (_x))
-#define BTE_SRC_STORE(_bte, _x) \
-({ \
- u64 __addr = ((_x) & ~AS_MASK); \
- if (is_shub2()) \
- __addr = SH2_TIO_PHYS_TO_DMA(__addr); \
- HUB_S(_bte->bte_source_addr, __addr); \
-})
-#define BTE_DEST_STORE(_bte, _x) \
-({ \
- u64 __addr = ((_x) & ~AS_MASK); \
- if (is_shub2()) \
- __addr = SH2_TIO_PHYS_TO_DMA(__addr); \
- HUB_S(_bte->bte_destination_addr, __addr); \
-})
-#define BTE_CTRL_STORE(_bte, _x) \
- HUB_S(_bte->bte_control_addr, (_x))
-#define BTE_NOTIF_STORE(_bte, _x) \
-({ \
- u64 __addr = ia64_tpa((_x) & ~AS_MASK); \
- if (is_shub2()) \
- __addr = SH2_TIO_PHYS_TO_DMA(__addr); \
- HUB_S(_bte->bte_notify_addr, __addr); \
-})
-
-#define BTE_START_TRANSFER(_bte, _len, _mode) \
- is_shub2() ? BTE_CTRL_STORE(_bte, IBLS_BUSY | (_mode << 24) | _len) \
- : BTE_LNSTAT_STORE(_bte, _len); \
- BTE_CTRL_STORE(_bte, _mode)
-
-/* Possible results from bte_copy and bte_unaligned_copy */
-/* The following error codes map into the BTE hardware codes
- * IIO_ICRB_ECODE_* (in shubio.h). The hardware uses
- * an error code of 0 (IIO_ICRB_ECODE_DERR), but we want zero
- * to mean BTE_SUCCESS, so add one (BTEFAIL_OFFSET) to the error
- * codes to give the following error codes.
- */
-#define BTEFAIL_OFFSET 1
-
-typedef enum {
- BTE_SUCCESS, /* 0 is success */
- BTEFAIL_DIR, /* Directory error due to IIO access*/
- BTEFAIL_POISON, /* poison error on IO access (write to poison page) */
- BTEFAIL_WERR, /* Write error (ie WINV to a Read only line) */
- BTEFAIL_ACCESS, /* access error (protection violation) */
- BTEFAIL_PWERR, /* Partial Write Error */
- BTEFAIL_PRERR, /* Partial Read Error */
- BTEFAIL_TOUT, /* CRB Time out */
- BTEFAIL_XTERR, /* Incoming xtalk pkt had error bit */
- BTEFAIL_NOTAVAIL, /* BTE not available */
-} bte_result_t;
-
-#define BTEFAIL_SH2_RESP_SHORT 0x1 /* bit 000001 */
-#define BTEFAIL_SH2_RESP_LONG 0x2 /* bit 000010 */
-#define BTEFAIL_SH2_RESP_DSP 0x4 /* bit 000100 */
-#define BTEFAIL_SH2_RESP_ACCESS 0x8 /* bit 001000 */
-#define BTEFAIL_SH2_CRB_TO 0x10 /* bit 010000 */
-#define BTEFAIL_SH2_NACK_LIMIT 0x20 /* bit 100000 */
-#define BTEFAIL_SH2_ALL 0x3F /* bit 111111 */
-
-#define BTE_ERR_BITS 0x3FUL
-#define BTE_ERR_SHIFT 36
-#define BTE_ERR_MASK (BTE_ERR_BITS << BTE_ERR_SHIFT)
-
-#define BTE_ERROR_RETRY(value) \
- (is_shub2() ? (value != BTEFAIL_SH2_CRB_TO) \
- : (value != BTEFAIL_TOUT))
-
-/*
- * On shub1 BTE_ERR_MASK will always be false, so no need for is_shub2()
- */
-#define BTE_SHUB2_ERROR(_status) \
- ((_status & BTE_ERR_MASK) \
- ? (((_status >> BTE_ERR_SHIFT) & BTE_ERR_BITS) | IBLS_ERROR) \
- : _status)
-
-#define BTE_GET_ERROR_STATUS(_status) \
- (BTE_SHUB2_ERROR(_status) & ~IBLS_ERROR)
-
-#define BTE_VALID_SH2_ERROR(value) \
- ((value >= BTEFAIL_SH2_RESP_SHORT) && (value <= BTEFAIL_SH2_ALL))
-
-/*
- * Structure defining a bte. An instance of this
- * structure is created in the nodepda for each
- * bte on that node (as defined by BTES_PER_NODE)
- * This structure contains everything necessary
- * to work with a BTE.
- */
-struct bteinfo_s {
- volatile u64 notify ____cacheline_aligned;
- u64 *bte_base_addr ____cacheline_aligned;
- u64 *bte_source_addr;
- u64 *bte_destination_addr;
- u64 *bte_control_addr;
- u64 *bte_notify_addr;
- spinlock_t spinlock;
- cnodeid_t bte_cnode; /* cnode */
- int bte_error_count; /* Number of errors encountered */
- int bte_num; /* 0 --> BTE0, 1 --> BTE1 */
- int cleanup_active; /* Interface is locked for cleanup */
- volatile bte_result_t bh_error; /* error while processing */
- volatile u64 *most_rcnt_na;
- struct bteinfo_s *btes_to_try[MAX_BTES_PER_NODE];
-};
-
-
-/*
- * Function prototypes (functions defined in bte.c, used elsewhere)
- */
-extern bte_result_t bte_copy(u64, u64, u64, u64, void *);
-extern bte_result_t bte_unaligned_copy(u64, u64, u64, u64);
-extern void bte_error_handler(struct nodepda_s *);
-
-#define bte_zero(dest, len, mode, notification) \
- bte_copy(0, dest, len, ((mode) | BTE_ZERO_FILL), notification)
-
-/*
- * The following is the preferred way of calling bte_unaligned_copy
- * If the copy is fully cache line aligned, then bte_copy is
- * used instead. Since bte_copy is inlined, this saves a call
- * stack. NOTE: bte_copy is called synchronously and does block
- * until the transfer is complete. In order to get the asynch
- * version of bte_copy, you must perform this check yourself.
- */
-#define BTE_UNALIGNED_COPY(src, dest, len, mode) \
- (((len & (L1_CACHE_BYTES - 1)) || \
- (src & (L1_CACHE_BYTES - 1)) || \
- (dest & (L1_CACHE_BYTES - 1))) ? \
- bte_unaligned_copy(src, dest, len, mode) : \
- bte_copy(src, dest, len, mode, NULL))
-
-
-#endif /* _ASM_IA64_SN_BTE_H */
diff --git a/arch/ia64/include/asm/sn/clksupport.h b/arch/ia64/include/asm/sn/clksupport.h
deleted file mode 100644
index d340c365a824..000000000000
--- a/arch/ia64/include/asm/sn/clksupport.h
+++ /dev/null
@@ -1,28 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * This file contains definitions for accessing a platform supported high resolution
- * clock. The clock is monitonically increasing and can be accessed from any node
- * in the system. The clock is synchronized across nodes - all nodes see the
- * same value.
- *
- * RTC_COUNTER_ADDR - contains the address of the counter
- *
- */
-
-#ifndef _ASM_IA64_SN_CLKSUPPORT_H
-#define _ASM_IA64_SN_CLKSUPPORT_H
-
-extern unsigned long sn_rtc_cycles_per_second;
-
-#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC))
-
-#define rtc_time() (*RTC_COUNTER_ADDR)
-
-#endif /* _ASM_IA64_SN_CLKSUPPORT_H */
diff --git a/arch/ia64/include/asm/sn/geo.h b/arch/ia64/include/asm/sn/geo.h
deleted file mode 100644
index f083c9434066..000000000000
--- a/arch/ia64/include/asm/sn/geo.h
+++ /dev/null
@@ -1,132 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_GEO_H
-#define _ASM_IA64_SN_GEO_H
-
-/* The geoid_t implementation below is based loosely on the pcfg_t
- implementation in sys/SN/promcfg.h. */
-
-/* Type declaractions */
-
-/* Size of a geoid_t structure (must be before decl. of geoid_u) */
-#define GEOID_SIZE 8 /* Would 16 be better? The size can
- be different on different platforms. */
-
-#define MAX_SLOTS 0xf /* slots per module */
-#define MAX_SLABS 0xf /* slabs per slot */
-
-typedef unsigned char geo_type_t;
-
-/* Fields common to all substructures */
-typedef struct geo_common_s {
- moduleid_t module; /* The module (box) this h/w lives in */
- geo_type_t type; /* What type of h/w is named by this geoid_t */
- slabid_t slab:4; /* slab (ASIC), 0 .. 15 within slot */
- slotid_t slot:4; /* slot (Blade), 0 .. 15 within module */
-} geo_common_t;
-
-/* Additional fields for particular types of hardware */
-typedef struct geo_node_s {
- geo_common_t common; /* No additional fields needed */
-} geo_node_t;
-
-typedef struct geo_rtr_s {
- geo_common_t common; /* No additional fields needed */
-} geo_rtr_t;
-
-typedef struct geo_iocntl_s {
- geo_common_t common; /* No additional fields needed */
-} geo_iocntl_t;
-
-typedef struct geo_pcicard_s {
- geo_iocntl_t common;
- char bus; /* Bus/widget number */
- char slot; /* PCI slot number */
-} geo_pcicard_t;
-
-/* Subcomponents of a node */
-typedef struct geo_cpu_s {
- geo_node_t node;
- char slice; /* Which CPU on the node */
-} geo_cpu_t;
-
-typedef struct geo_mem_s {
- geo_node_t node;
- char membus; /* The memory bus on the node */
- char memslot; /* The memory slot on the bus */
-} geo_mem_t;
-
-
-typedef union geoid_u {
- geo_common_t common;
- geo_node_t node;
- geo_iocntl_t iocntl;
- geo_pcicard_t pcicard;
- geo_rtr_t rtr;
- geo_cpu_t cpu;
- geo_mem_t mem;
- char padsize[GEOID_SIZE];
-} geoid_t;
-
-
-/* Preprocessor macros */
-
-#define GEO_MAX_LEN 48 /* max. formatted length, plus some pad:
- module/001c07/slab/5/node/memory/2/slot/4 */
-
-/* Values for geo_type_t */
-#define GEO_TYPE_INVALID 0
-#define GEO_TYPE_MODULE 1
-#define GEO_TYPE_NODE 2
-#define GEO_TYPE_RTR 3
-#define GEO_TYPE_IOCNTL 4
-#define GEO_TYPE_IOCARD 5
-#define GEO_TYPE_CPU 6
-#define GEO_TYPE_MEM 7
-#define GEO_TYPE_MAX (GEO_TYPE_MEM+1)
-
-/* Parameter for hwcfg_format_geoid_compt() */
-#define GEO_COMPT_MODULE 1
-#define GEO_COMPT_SLAB 2
-#define GEO_COMPT_IOBUS 3
-#define GEO_COMPT_IOSLOT 4
-#define GEO_COMPT_CPU 5
-#define GEO_COMPT_MEMBUS 6
-#define GEO_COMPT_MEMSLOT 7
-
-#define GEO_INVALID_STR "<invalid>"
-
-#define INVALID_NASID ((nasid_t)-1)
-#define INVALID_CNODEID ((cnodeid_t)-1)
-#define INVALID_PNODEID ((pnodeid_t)-1)
-#define INVALID_SLAB (slabid_t)-1
-#define INVALID_SLOT (slotid_t)-1
-#define INVALID_MODULE ((moduleid_t)-1)
-
-static inline slabid_t geo_slab(geoid_t g)
-{
- return (g.common.type == GEO_TYPE_INVALID) ?
- INVALID_SLAB : g.common.slab;
-}
-
-static inline slotid_t geo_slot(geoid_t g)
-{
- return (g.common.type == GEO_TYPE_INVALID) ?
- INVALID_SLOT : g.common.slot;
-}
-
-static inline moduleid_t geo_module(geoid_t g)
-{
- return (g.common.type == GEO_TYPE_INVALID) ?
- INVALID_MODULE : g.common.module;
-}
-
-extern geoid_t cnodeid_get_geoid(cnodeid_t cnode);
-
-#endif /* _ASM_IA64_SN_GEO_H */
diff --git a/arch/ia64/include/asm/sn/intr.h b/arch/ia64/include/asm/sn/intr.h
index e0487aa97418..3885a77b21df 100644
--- a/arch/ia64/include/asm/sn/intr.h
+++ b/arch/ia64/include/asm/sn/intr.h
@@ -9,60 +9,7 @@
#ifndef _ASM_IA64_SN_INTR_H
#define _ASM_IA64_SN_INTR_H
-#include <linux/rcupdate.h>
-#include <asm/sn/types.h>
-
-#define SGI_UART_VECTOR 0xe9
-
-/* Reserved IRQs : Note, not to exceed IA64_SN2_FIRST_DEVICE_VECTOR */
#define SGI_XPC_ACTIVATE 0x30
-#define SGI_II_ERROR 0x31
-#define SGI_XBOW_ERROR 0x32
-#define SGI_PCIASIC_ERROR 0x33
-#define SGI_ACPI_SCI_INT 0x34
-#define SGI_TIOCA_ERROR 0x35
-#define SGI_TIO_ERROR 0x36
-#define SGI_TIOCX_ERROR 0x37
-#define SGI_MMTIMER_VECTOR 0x38
#define SGI_XPC_NOTIFY 0xe7
-#define IA64_SN2_FIRST_DEVICE_VECTOR 0x3c
-#define IA64_SN2_LAST_DEVICE_VECTOR 0xe6
-
-#define SN2_IRQ_RESERVED 0x1
-#define SN2_IRQ_CONNECTED 0x2
-#define SN2_IRQ_SHARED 0x4
-
-// The SN PROM irq struct
-struct sn_irq_info {
- struct sn_irq_info *irq_next; /* deprecated DO NOT USE */
- short irq_nasid; /* Nasid IRQ is assigned to */
- int irq_slice; /* slice IRQ is assigned to */
- int irq_cpuid; /* kernel logical cpuid */
- int irq_irq; /* the IRQ number */
- int irq_int_bit; /* Bridge interrupt pin */
- /* <0 means MSI */
- u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */
- int irq_bridge_type;/* pciio asic type (pciio.h) */
- void *irq_bridge; /* bridge generating irq */
- void *irq_pciioinfo; /* associated pciio_info_t */
- int irq_last_intr; /* For Shub lb lost intr WAR */
- int irq_cookie; /* unique cookie */
- int irq_flags; /* flags */
- int irq_share_cnt; /* num devices sharing IRQ */
- struct list_head list; /* list of sn_irq_info structs */
- struct rcu_head rcu; /* rcu callback list */
-};
-
-extern void sn_send_IPI_phys(int, long, int, int);
-extern u64 sn_intr_alloc(nasid_t, int,
- struct sn_irq_info *,
- int, nasid_t, int);
-extern void sn_intr_free(nasid_t, int, struct sn_irq_info *);
-extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int);
-extern void sn_set_err_irq_affinity(unsigned int);
-extern struct list_head **sn_irq_lh;
-
-#define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
-
#endif /* _ASM_IA64_SN_INTR_H */
diff --git a/arch/ia64/include/asm/sn/io.h b/arch/ia64/include/asm/sn/io.h
deleted file mode 100644
index 41c73a735628..000000000000
--- a/arch/ia64/include/asm/sn/io.h
+++ /dev/null
@@ -1,274 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_SN_IO_H
-#define _ASM_SN_IO_H
-#include <linux/compiler.h>
-#include <asm/intrinsics.h>
-
-extern void * sn_io_addr(unsigned long port) __attribute_const__; /* Forward definition */
-extern void __sn_mmiowb(void); /* Forward definition */
-
-extern int num_cnodes;
-
-#define __sn_mf_a() ia64_mfa()
-
-extern void sn_dma_flush(unsigned long);
-
-#define __sn_inb ___sn_inb
-#define __sn_inw ___sn_inw
-#define __sn_inl ___sn_inl
-#define __sn_outb ___sn_outb
-#define __sn_outw ___sn_outw
-#define __sn_outl ___sn_outl
-#define __sn_readb ___sn_readb
-#define __sn_readw ___sn_readw
-#define __sn_readl ___sn_readl
-#define __sn_readq ___sn_readq
-#define __sn_readb_relaxed ___sn_readb_relaxed
-#define __sn_readw_relaxed ___sn_readw_relaxed
-#define __sn_readl_relaxed ___sn_readl_relaxed
-#define __sn_readq_relaxed ___sn_readq_relaxed
-
-/*
- * Convenience macros for setting/clearing bits using the above accessors
- */
-
-#define __sn_setq_relaxed(addr, val) \
- writeq((__sn_readq_relaxed(addr) | (val)), (addr))
-#define __sn_clrq_relaxed(addr, val) \
- writeq((__sn_readq_relaxed(addr) & ~(val)), (addr))
-
-/*
- * The following routines are SN Platform specific, called when
- * a reference is made to inX/outX set macros. SN Platform
- * inX set of macros ensures that Posted DMA writes on the
- * Bridge is flushed.
- *
- * The routines should be self explainatory.
- */
-
-static inline unsigned int
-___sn_inb (unsigned long port)
-{
- volatile unsigned char *addr;
- unsigned char ret = -1;
-
- if ((addr = sn_io_addr(port))) {
- ret = *addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- }
- return ret;
-}
-
-static inline unsigned int
-___sn_inw (unsigned long port)
-{
- volatile unsigned short *addr;
- unsigned short ret = -1;
-
- if ((addr = sn_io_addr(port))) {
- ret = *addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- }
- return ret;
-}
-
-static inline unsigned int
-___sn_inl (unsigned long port)
-{
- volatile unsigned int *addr;
- unsigned int ret = -1;
-
- if ((addr = sn_io_addr(port))) {
- ret = *addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- }
- return ret;
-}
-
-static inline void
-___sn_outb (unsigned char val, unsigned long port)
-{
- volatile unsigned char *addr;
-
- if ((addr = sn_io_addr(port))) {
- *addr = val;
- __sn_mmiowb();
- }
-}
-
-static inline void
-___sn_outw (unsigned short val, unsigned long port)
-{
- volatile unsigned short *addr;
-
- if ((addr = sn_io_addr(port))) {
- *addr = val;
- __sn_mmiowb();
- }
-}
-
-static inline void
-___sn_outl (unsigned int val, unsigned long port)
-{
- volatile unsigned int *addr;
-
- if ((addr = sn_io_addr(port))) {
- *addr = val;
- __sn_mmiowb();
- }
-}
-
-/*
- * The following routines are SN Platform specific, called when
- * a reference is made to readX/writeX set macros. SN Platform
- * readX set of macros ensures that Posted DMA writes on the
- * Bridge is flushed.
- *
- * The routines should be self explainatory.
- */
-
-static inline unsigned char
-___sn_readb (const volatile void __iomem *addr)
-{
- unsigned char val;
-
- val = *(volatile unsigned char __force *)addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- return val;
-}
-
-static inline unsigned short
-___sn_readw (const volatile void __iomem *addr)
-{
- unsigned short val;
-
- val = *(volatile unsigned short __force *)addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- return val;
-}
-
-static inline unsigned int
-___sn_readl (const volatile void __iomem *addr)
-{
- unsigned int val;
-
- val = *(volatile unsigned int __force *)addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- return val;
-}
-
-static inline unsigned long
-___sn_readq (const volatile void __iomem *addr)
-{
- unsigned long val;
-
- val = *(volatile unsigned long __force *)addr;
- __sn_mf_a();
- sn_dma_flush((unsigned long)addr);
- return val;
-}
-
-/*
- * For generic and SN2 kernels, we have a set of fast access
- * PIO macros. These macros are provided on SN Platform
- * because the normal inX and readX macros perform an
- * additional task of flushing Post DMA request on the Bridge.
- *
- * These routines should be self explainatory.
- */
-
-static inline unsigned int
-sn_inb_fast (unsigned long port)
-{
- volatile unsigned char *addr = (unsigned char *)port;
- unsigned char ret;
-
- ret = *addr;
- __sn_mf_a();
- return ret;
-}
-
-static inline unsigned int
-sn_inw_fast (unsigned long port)
-{
- volatile unsigned short *addr = (unsigned short *)port;
- unsigned short ret;
-
- ret = *addr;
- __sn_mf_a();
- return ret;
-}
-
-static inline unsigned int
-sn_inl_fast (unsigned long port)
-{
- volatile unsigned int *addr = (unsigned int *)port;
- unsigned int ret;
-
- ret = *addr;
- __sn_mf_a();
- return ret;
-}
-
-static inline unsigned char
-___sn_readb_relaxed (const volatile void __iomem *addr)
-{
- return *(volatile unsigned char __force *)addr;
-}
-
-static inline unsigned short
-___sn_readw_relaxed (const volatile void __iomem *addr)
-{
- return *(volatile unsigned short __force *)addr;
-}
-
-static inline unsigned int
-___sn_readl_relaxed (const volatile void __iomem *addr)
-{
- return *(volatile unsigned int __force *) addr;
-}
-
-static inline unsigned long
-___sn_readq_relaxed (const volatile void __iomem *addr)
-{
- return *(volatile unsigned long __force *) addr;
-}
-
-struct pci_dev;
-
-static inline int
-sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long *addr, int vchan)
-{
-
- if (vchan > 1) {
- return -1;
- }
-
- if (!(*addr >> 32)) /* Using a mask here would be cleaner */
- return 0; /* but this generates better code */
-
- if (vchan == 1) {
- /* Set Bit 57 */
- *addr |= (1UL << 57);
- } else {
- /* Clear Bit 57 */
- *addr &= ~(1UL << 57);
- }
-
- return 0;
-}
-
-#endif /* _ASM_SN_IO_H */
diff --git a/arch/ia64/include/asm/sn/ioc3.h b/arch/ia64/include/asm/sn/ioc3.h
deleted file mode 100644
index d4a524951df3..000000000000
--- a/arch/ia64/include/asm/sn/ioc3.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2005 Silicon Graphics, Inc.
- */
-#ifndef IA64_SN_IOC3_H
-#define IA64_SN_IOC3_H
-
-/* serial port register map */
-struct ioc3_serialregs {
- uint32_t sscr;
- uint32_t stpir;
- uint32_t stcir;
- uint32_t srpir;
- uint32_t srcir;
- uint32_t srtr;
- uint32_t shadow;
-};
-
-/* SUPERIO uart register map */
-struct ioc3_uartregs {
- char iu_lcr;
- union {
- char iir; /* read only */
- char fcr; /* write only */
- } u3;
- union {
- char ier; /* DLAB == 0 */
- char dlm; /* DLAB == 1 */
- } u2;
- union {
- char rbr; /* read only, DLAB == 0 */
- char thr; /* write only, DLAB == 0 */
- char dll; /* DLAB == 1 */
- } u1;
- char iu_scr;
- char iu_msr;
- char iu_lsr;
- char iu_mcr;
-};
-
-#define iu_rbr u1.rbr
-#define iu_thr u1.thr
-#define iu_dll u1.dll
-#define iu_ier u2.ier
-#define iu_dlm u2.dlm
-#define iu_iir u3.iir
-#define iu_fcr u3.fcr
-
-struct ioc3_sioregs {
- char fill[0x170];
- struct ioc3_uartregs uartb;
- struct ioc3_uartregs uarta;
-};
-
-/* PCI IO/mem space register map */
-struct ioc3 {
- uint32_t pci_id;
- uint32_t pci_scr;
- uint32_t pci_rev;
- uint32_t pci_lat;
- uint32_t pci_addr;
- uint32_t pci_err_addr_l;
- uint32_t pci_err_addr_h;
-
- uint32_t sio_ir;
- /* these registers are read-only for general kernel code. To
- * modify them use the functions in ioc3.c
- */
- uint32_t sio_ies;
- uint32_t sio_iec;
- uint32_t sio_cr;
- uint32_t int_out;
- uint32_t mcr;
- uint32_t gpcr_s;
- uint32_t gpcr_c;
- uint32_t gpdr;
- uint32_t gppr[9];
- char fill[0x4c];
-
- /* serial port registers */
- uint32_t sbbr_h;
- uint32_t sbbr_l;
-
- struct ioc3_serialregs port_a;
- struct ioc3_serialregs port_b;
- char fill1[0x1ff10];
- /* superio registers */
- struct ioc3_sioregs sregs;
-};
-
-/* These don't exist on the ioc3 serial card... */
-#define eier fill1[8]
-#define eisr fill1[4]
-
-#define PCI_LAT 0xc /* Latency Timer */
-#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */
-#define UARTA_BASE 0x178
-#define UARTB_BASE 0x170
-
-
-/* bitmasks for serial RX status byte */
-#define RXSB_OVERRUN 0x01 /* char(s) lost */
-#define RXSB_PAR_ERR 0x02 /* parity error */
-#define RXSB_FRAME_ERR 0x04 /* framing error */
-#define RXSB_BREAK 0x08 /* break character */
-#define RXSB_CTS 0x10 /* state of CTS */
-#define RXSB_DCD 0x20 /* state of DCD */
-#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */
-#define RXSB_DATA_VALID 0x80 /* FRAME_ERR PAR_ERR & BREAK valid */
-
-/* bitmasks for serial TX control byte */
-#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */
-#define TXCB_INVALID 0x00 /* byte is invalid */
-#define TXCB_VALID 0x40 /* byte is valid */
-#define TXCB_MCR 0x80 /* data<7:0> to modem cntrl register */
-#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */
-
-/* bitmasks for SBBR_L */
-#define SBBR_L_SIZE 0x00000001 /* 0 1KB rings, 1 4KB rings */
-
-/* bitmasks for SSCR_<A:B> */
-#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */
-#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
-#define SSCR_HFC_EN 0x00020000 /* h/w flow cntrl enabled */
-#define SSCR_RX_RING_DCD 0x00040000 /* postRX record on delta-DCD */
-#define SSCR_RX_RING_CTS 0x00080000 /* postRX record on delta-CTS */
-#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */
-#define SSCR_DIAG 0x00200000 /* bypass clock divider */
-#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */
-#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */
-#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */
-#define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/
-#define SSCR_RESET 0x80000000 /* reset DMA channels */
-
-/* all producer/consumer pointers are the same bitfield */
-#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */
-#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */
-#define PROD_CONS_PTR_OFF 3
-
-/* bitmasks for SRCIR_<A:B> */
-#define SRCIR_ARM 0x80000000 /* arm RX timer */
-
-/* bitmasks for SHADOW_<A:B> */
-#define SHADOW_DR 0x00000001 /* data ready */
-#define SHADOW_OE 0x00000002 /* overrun error */
-#define SHADOW_PE 0x00000004 /* parity error */
-#define SHADOW_FE 0x00000008 /* framing error */
-#define SHADOW_BI 0x00000010 /* break interrupt */
-#define SHADOW_THRE 0x00000020 /* transmit holding reg empty */
-#define SHADOW_TEMT 0x00000040 /* transmit shift reg empty */
-#define SHADOW_RFCE 0x00000080 /* char in RX fifo has error */
-#define SHADOW_DCTS 0x00010000 /* delta clear to send */
-#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */
-#define SHADOW_CTS 0x00100000 /* clear to send */
-#define SHADOW_DCD 0x00800000 /* data carrier detect */
-#define SHADOW_DTR 0x01000000 /* data terminal ready */
-#define SHADOW_RTS 0x02000000 /* request to send */
-#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
-#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
-#define SHADOW_LOOP 0x10000000 /* loopback enabled */
-
-/* bitmasks for SRTR_<A:B> */
-#define SRTR_CNT 0x00000fff /* reload value for RX timer */
-#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */
-#define SRTR_CNT_VAL_SHIFT 16
-#define SRTR_HZ 16000 /* SRTR clock frequency */
-
-/* bitmasks for SIO_IR, SIO_IEC and SIO_IES */
-#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */
-#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */
-#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */
-#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */
-#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */
-#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */
-#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */
-#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */
-#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */
-#define SIO_IR_SB_TX_MT 0x00000200
-#define SIO_IR_SB_RX_FULL 0x00000400
-#define SIO_IR_SB_RX_HIGH 0x00000800
-#define SIO_IR_SB_RX_TIMER 0x00001000
-#define SIO_IR_SB_DELTA_DCD 0x00002000
-#define SIO_IR_SB_DELTA_CTS 0x00004000
-#define SIO_IR_SB_INT 0x00008000
-#define SIO_IR_SB_TX_EXPLICIT 0x00010000
-#define SIO_IR_SB_MEMERR 0x00020000
-#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */
-#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */
-#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */
-#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */
-#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */
-#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */
-#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */
-#define SIO_IR_GEN_INT_SHIFT 28
-
-/* per device interrupt masks */
-#define SIO_IR_SA (SIO_IR_SA_TX_MT | \
- SIO_IR_SA_RX_FULL | \
- SIO_IR_SA_RX_HIGH | \
- SIO_IR_SA_RX_TIMER | \
- SIO_IR_SA_DELTA_DCD | \
- SIO_IR_SA_DELTA_CTS | \
- SIO_IR_SA_INT | \
- SIO_IR_SA_TX_EXPLICIT | \
- SIO_IR_SA_MEMERR)
-
-#define SIO_IR_SB (SIO_IR_SB_TX_MT | \
- SIO_IR_SB_RX_FULL | \
- SIO_IR_SB_RX_HIGH | \
- SIO_IR_SB_RX_TIMER | \
- SIO_IR_SB_DELTA_DCD | \
- SIO_IR_SB_DELTA_CTS | \
- SIO_IR_SB_INT | \
- SIO_IR_SB_TX_EXPLICIT | \
- SIO_IR_SB_MEMERR)
-
-#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \
- SIO_IR_PP_INTB | SIO_IR_PP_MEMERR)
-#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1)
-
-/* bitmasks for SIO_CR */
-#define SIO_CR_CMD_PULSE_SHIFT 15
-#define SIO_CR_SER_A_BASE_SHIFT 1
-#define SIO_CR_SER_B_BASE_SHIFT 8
-#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */
-#define SIO_CR_ARB_DIAG_TXA 0x00000000
-#define SIO_CR_ARB_DIAG_RXA 0x00080000
-#define SIO_CR_ARB_DIAG_TXB 0x00100000
-#define SIO_CR_ARB_DIAG_RXB 0x00180000
-#define SIO_CR_ARB_DIAG_PP 0x00200000
-#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */
-
-/* defs for some of the generic I/O pins */
-#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */
-#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */
-#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */
-
-#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */
-#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrling uartb modeselect */
-#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrling uarta modeselect */
-
-#endif /* IA64_SN_IOC3_H */
diff --git a/arch/ia64/include/asm/sn/klconfig.h b/arch/ia64/include/asm/sn/klconfig.h
deleted file mode 100644
index bcbf209d63be..000000000000
--- a/arch/ia64/include/asm/sn/klconfig.h
+++ /dev/null
@@ -1,246 +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.
- *
- * Derived from IRIX <sys/SN/klconfig.h>.
- *
- * Copyright (C) 1992-1997,1999,2001-2004 Silicon Graphics, Inc. All Rights Reserved.
- * Copyright (C) 1999 by Ralf Baechle
- */
-#ifndef _ASM_IA64_SN_KLCONFIG_H
-#define _ASM_IA64_SN_KLCONFIG_H
-
-/*
- * The KLCONFIG structures store info about the various BOARDs found
- * during Hardware Discovery. In addition, it stores info about the
- * components found on the BOARDs.
- */
-
-typedef s32 klconf_off_t;
-
-
-/* Functions/macros needed to use this structure */
-
-typedef struct kl_config_hdr {
- char pad[20];
- klconf_off_t ch_board_info; /* the link list of boards */
- char pad0[88];
-} kl_config_hdr_t;
-
-
-#define NODE_OFFSET_TO_LBOARD(nasid,off) (lboard_t*)(GLOBAL_CAC_ADDR((nasid), (off)))
-
-/*
- * The KLCONFIG area is organized as a LINKED LIST of BOARDs. A BOARD
- * can be either 'LOCAL' or 'REMOTE'. LOCAL means it is attached to
- * the LOCAL/current NODE. REMOTE means it is attached to a different
- * node.(TBD - Need a way to treat ROUTER boards.)
- *
- * There are 2 different structures to represent these boards -
- * lboard - Local board, rboard - remote board. These 2 structures
- * can be arbitrarily mixed in the LINKED LIST of BOARDs. (Refer
- * Figure below). The first byte of the rboard or lboard structure
- * is used to find out its type - no unions are used.
- * If it is a lboard, then the config info of this board will be found
- * on the local node. (LOCAL NODE BASE + offset value gives pointer to
- * the structure.
- * If it is a rboard, the local structure contains the node number
- * and the offset of the beginning of the LINKED LIST on the remote node.
- * The details of the hardware on a remote node can be built locally,
- * if required, by reading the LINKED LIST on the remote node and
- * ignoring all the rboards on that node.
- *
- * The local node uses the REMOTE NODE NUMBER + OFFSET to point to the
- * First board info on the remote node. The remote node list is
- * traversed as the local list, using the REMOTE BASE ADDRESS and not
- * the local base address and ignoring all rboard values.
- *
- *
- KLCONFIG
-
- +------------+ +------------+ +------------+ +------------+
- | lboard | +-->| lboard | +-->| rboard | +-->| lboard |
- +------------+ | +------------+ | +------------+ | +------------+
- | board info | | | board info | | |errinfo,bptr| | | board info |
- +------------+ | +------------+ | +------------+ | +------------+
- | offset |--+ | offset |--+ | offset |--+ |offset=NULL |
- +------------+ +------------+ +------------+ +------------+
-
-
- +------------+
- | board info |
- +------------+ +--------------------------------+
- | compt 1 |------>| type, rev, diaginfo, size ... | (CPU)
- +------------+ +--------------------------------+
- | compt 2 |--+
- +------------+ | +--------------------------------+
- | ... | +--->| type, rev, diaginfo, size ... | (MEM_BANK)
- +------------+ +--------------------------------+
- | errinfo |--+
- +------------+ | +--------------------------------+
- +--->|r/l brd errinfo,compt err flags |
- +--------------------------------+
-
- *
- * Each BOARD consists of COMPONENTs and the BOARD structure has
- * pointers (offsets) to its COMPONENT structure.
- * The COMPONENT structure has version info, size and speed info, revision,
- * error info and the NIC info. This structure can accommodate any
- * BOARD with arbitrary COMPONENT composition.
- *
- * The ERRORINFO part of each BOARD has error information
- * that describes errors about the BOARD itself. It also has flags to
- * indicate the COMPONENT(s) on the board that have errors. The error
- * information specific to the COMPONENT is present in the respective
- * COMPONENT structure.
- *
- * The ERRORINFO structure is also treated like a COMPONENT, ie. the
- * BOARD has pointers(offset) to the ERRORINFO structure. The rboard
- * structure also has a pointer to the ERRORINFO structure. This is
- * the place to store ERRORINFO about a REMOTE NODE, if the HUB on
- * that NODE is not working or if the REMOTE MEMORY is BAD. In cases where
- * only the CPU of the REMOTE NODE is disabled, the ERRORINFO pointer can
- * be a NODE NUMBER, REMOTE OFFSET combination, pointing to error info
- * which is present on the REMOTE NODE.(TBD)
- * REMOTE ERRINFO can be stored on any of the nearest nodes
- * or on all the nearest nodes.(TBD)
- * Like BOARD structures, REMOTE ERRINFO structures can be built locally
- * using the rboard errinfo pointer.
- *
- * In order to get useful information from this Data organization, a set of
- * interface routines are provided (TBD). The important thing to remember while
- * manipulating the structures, is that, the NODE number information should
- * be used. If the NODE is non-zero (remote) then each offset should
- * be added to the REMOTE BASE ADDR else it should be added to the LOCAL BASE ADDR.
- * This includes offsets for BOARDS, COMPONENTS and ERRORINFO.
- *
- * Note that these structures do not provide much info about connectivity.
- * That info will be part of HWGRAPH, which is an extension of the cfg_t
- * data structure. (ref IP27prom/cfg.h) It has to be extended to include
- * the IO part of the Network(TBD).
- *
- * The data structures below define the above concepts.
- */
-
-
-/*
- * BOARD classes
- */
-
-#define KLCLASS_MASK 0xf0
-#define KLCLASS_NONE 0x00
-#define KLCLASS_NODE 0x10 /* CPU, Memory and HUB board */
-#define KLCLASS_CPU KLCLASS_NODE
-#define KLCLASS_IO 0x20 /* BaseIO, 4 ch SCSI, ethernet, FDDI
- and the non-graphics widget boards */
-#define KLCLASS_ROUTER 0x30 /* Router board */
-#define KLCLASS_MIDPLANE 0x40 /* We need to treat this as a board
- so that we can record error info */
-#define KLCLASS_IOBRICK 0x70 /* IP35 iobrick */
-#define KLCLASS_MAX 8 /* Bump this if a new CLASS is added */
-
-#define KLCLASS(_x) ((_x) & KLCLASS_MASK)
-
-
-/*
- * board types
- */
-
-#define KLTYPE_MASK 0x0f
-#define KLTYPE(_x) ((_x) & KLTYPE_MASK)
-
-#define KLTYPE_SNIA (KLCLASS_CPU | 0x1)
-#define KLTYPE_TIO (KLCLASS_CPU | 0x2)
-
-#define KLTYPE_ROUTER (KLCLASS_ROUTER | 0x1)
-#define KLTYPE_META_ROUTER (KLCLASS_ROUTER | 0x3)
-#define KLTYPE_REPEATER_ROUTER (KLCLASS_ROUTER | 0x4)
-
-#define KLTYPE_IOBRICK_XBOW (KLCLASS_MIDPLANE | 0x2)
-
-#define KLTYPE_IOBRICK (KLCLASS_IOBRICK | 0x0)
-#define KLTYPE_NBRICK (KLCLASS_IOBRICK | 0x4)
-#define KLTYPE_PXBRICK (KLCLASS_IOBRICK | 0x6)
-#define KLTYPE_IXBRICK (KLCLASS_IOBRICK | 0x7)
-#define KLTYPE_CGBRICK (KLCLASS_IOBRICK | 0x8)
-#define KLTYPE_OPUSBRICK (KLCLASS_IOBRICK | 0x9)
-#define KLTYPE_SABRICK (KLCLASS_IOBRICK | 0xa)
-#define KLTYPE_IABRICK (KLCLASS_IOBRICK | 0xb)
-#define KLTYPE_PABRICK (KLCLASS_IOBRICK | 0xc)
-#define KLTYPE_GABRICK (KLCLASS_IOBRICK | 0xd)
-
-
-/*
- * board structures
- */
-
-#define MAX_COMPTS_PER_BRD 24
-
-typedef struct lboard_s {
- klconf_off_t brd_next_any; /* Next BOARD */
- unsigned char struct_type; /* type of structure, local or remote */
- unsigned char brd_type; /* type+class */
- unsigned char brd_sversion; /* version of this structure */
- unsigned char brd_brevision; /* board revision */
- unsigned char brd_promver; /* board prom version, if any */
- unsigned char brd_flags; /* Enabled, Disabled etc */
- unsigned char brd_slot; /* slot number */
- unsigned short brd_debugsw; /* Debug switches */
- geoid_t brd_geoid; /* geo id */
- partid_t brd_partition; /* Partition number */
- unsigned short brd_diagval; /* diagnostic value */
- unsigned short brd_diagparm; /* diagnostic parameter */
- unsigned char brd_inventory; /* inventory history */
- unsigned char brd_numcompts; /* Number of components */
- nic_t brd_nic; /* Number in CAN */
- nasid_t brd_nasid; /* passed parameter */
- klconf_off_t brd_compts[MAX_COMPTS_PER_BRD]; /* pointers to COMPONENTS */
- klconf_off_t brd_errinfo; /* Board's error information */
- struct lboard_s *brd_parent; /* Logical parent for this brd */
- char pad0[4];
- unsigned char brd_confidence; /* confidence that the board is bad */
- nasid_t brd_owner; /* who owns this board */
- unsigned char brd_nic_flags; /* To handle 8 more NICs */
- char pad1[24]; /* future expansion */
- char brd_name[32];
- nasid_t brd_next_same_host; /* host of next brd w/same nasid */
- klconf_off_t brd_next_same; /* Next BOARD with same nasid */
-} lboard_t;
-
-/*
- * Generic info structure. This stores common info about a
- * component.
- */
-
-typedef struct klinfo_s { /* Generic info */
- unsigned char struct_type; /* type of this structure */
- unsigned char struct_version; /* version of this structure */
- unsigned char flags; /* Enabled, disabled etc */
- unsigned char revision; /* component revision */
- unsigned short diagval; /* result of diagnostics */
- unsigned short diagparm; /* diagnostic parameter */
- unsigned char inventory; /* previous inventory status */
- unsigned short partid; /* widget part number */
- nic_t nic; /* MUst be aligned properly */
- unsigned char physid; /* physical id of component */
- unsigned int virtid; /* virtual id as seen by system */
- unsigned char widid; /* Widget id - if applicable */
- nasid_t nasid; /* node number - from parent */
- char pad1; /* pad out structure. */
- char pad2; /* pad out structure. */
- void *data;
- klconf_off_t errinfo; /* component specific errors */
- unsigned short pad3; /* pci fields have moved over to */
- unsigned short pad4; /* klbri_t */
-} klinfo_t ;
-
-
-static inline lboard_t *find_lboard_next(lboard_t * brd)
-{
- if (brd && brd->brd_next_any)
- return NODE_OFFSET_TO_LBOARD(NASID_GET(brd), brd->brd_next_any);
- return NULL;
-}
-
-#endif /* _ASM_IA64_SN_KLCONFIG_H */
diff --git a/arch/ia64/include/asm/sn/l1.h b/arch/ia64/include/asm/sn/l1.h
deleted file mode 100644
index 344bf44bb356..000000000000
--- a/arch/ia64/include/asm/sn/l1.h
+++ /dev/null
@@ -1,51 +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-2004 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#ifndef _ASM_IA64_SN_L1_H
-#define _ASM_IA64_SN_L1_H
-
-/* brick type response codes */
-#define L1_BRICKTYPE_PX 0x23 /* # */
-#define L1_BRICKTYPE_PE 0x25 /* % */
-#define L1_BRICKTYPE_N_p0 0x26 /* & */
-#define L1_BRICKTYPE_IP45 0x34 /* 4 */
-#define L1_BRICKTYPE_IP41 0x35 /* 5 */
-#define L1_BRICKTYPE_TWISTER 0x36 /* 6 */ /* IP53 & ROUTER */
-#define L1_BRICKTYPE_IX 0x3d /* = */
-#define L1_BRICKTYPE_IP34 0x61 /* a */
-#define L1_BRICKTYPE_GA 0x62 /* b */
-#define L1_BRICKTYPE_C 0x63 /* c */
-#define L1_BRICKTYPE_OPUS_TIO 0x66 /* f */
-#define L1_BRICKTYPE_I 0x69 /* i */
-#define L1_BRICKTYPE_N 0x6e /* n */
-#define L1_BRICKTYPE_OPUS 0x6f /* o */
-#define L1_BRICKTYPE_P 0x70 /* p */
-#define L1_BRICKTYPE_R 0x72 /* r */
-#define L1_BRICKTYPE_CHI_CG 0x76 /* v */
-#define L1_BRICKTYPE_X 0x78 /* x */
-#define L1_BRICKTYPE_X2 0x79 /* y */
-#define L1_BRICKTYPE_SA 0x5e /* ^ */
-#define L1_BRICKTYPE_PA 0x6a /* j */
-#define L1_BRICKTYPE_IA 0x6b /* k */
-#define L1_BRICKTYPE_ATHENA 0x2b /* + */
-#define L1_BRICKTYPE_DAYTONA 0x7a /* z */
-#define L1_BRICKTYPE_1932 0x2c /* . */
-#define L1_BRICKTYPE_191010 0x2e /* , */
-
-/* board type response codes */
-#define L1_BOARDTYPE_IP69 0x0100 /* CA */
-#define L1_BOARDTYPE_IP63 0x0200 /* CB */
-#define L1_BOARDTYPE_BASEIO 0x0300 /* IB */
-#define L1_BOARDTYPE_PCIE2SLOT 0x0400 /* IC */
-#define L1_BOARDTYPE_PCIX3SLOT 0x0500 /* ID */
-#define L1_BOARDTYPE_PCIXPCIE4SLOT 0x0600 /* IE */
-#define L1_BOARDTYPE_ABACUS 0x0700 /* AB */
-#define L1_BOARDTYPE_DAYTONA 0x0800 /* AD */
-#define L1_BOARDTYPE_INVAL (-1) /* invalid brick type */
-
-#endif /* _ASM_IA64_SN_L1_H */
diff --git a/arch/ia64/include/asm/sn/leds.h b/arch/ia64/include/asm/sn/leds.h
deleted file mode 100644
index 66cf8c4d92c9..000000000000
--- a/arch/ia64/include/asm/sn/leds.h
+++ /dev/null
@@ -1,33 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_LEDS_H
-#define _ASM_IA64_SN_LEDS_H
-
-#include <asm/sn/addrs.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/shub_mmr.h>
-
-#define LED0 (LOCAL_MMR_ADDR(SH_REAL_JUNK_BUS_LED0))
-#define LED_CPU_SHIFT 16
-
-#define LED_CPU_HEARTBEAT 0x01
-#define LED_CPU_ACTIVITY 0x02
-#define LED_ALWAYS_SET 0x00
-
-/*
- * Basic macros for flashing the LEDS on an SGI SN.
- */
-
-static __inline__ void
-set_led_bits(u8 value, u8 mask)
-{
- pda->led_state = (pda->led_state & ~mask) | (value & mask);
- *pda->led_address = (short) pda->led_state;
-}
-
-#endif /* _ASM_IA64_SN_LEDS_H */
-
diff --git a/arch/ia64/include/asm/sn/module.h b/arch/ia64/include/asm/sn/module.h
deleted file mode 100644
index 734e980ece2f..000000000000
--- a/arch/ia64/include/asm/sn/module.h
+++ /dev/null
@@ -1,127 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_MODULE_H
-#define _ASM_IA64_SN_MODULE_H
-
-/* parameter for format_module_id() */
-#define MODULE_FORMAT_BRIEF 1
-#define MODULE_FORMAT_LONG 2
-#define MODULE_FORMAT_LCD 3
-
-/*
- * Module id format
- *
- * 31-16 Rack ID (encoded class, group, number - 16-bit unsigned int)
- * 15-8 Brick type (8-bit ascii character)
- * 7-0 Bay (brick position in rack (0-63) - 8-bit unsigned int)
- *
- */
-
-/*
- * Macros for getting the brick type
- */
-#define MODULE_BTYPE_MASK 0xff00
-#define MODULE_BTYPE_SHFT 8
-#define MODULE_GET_BTYPE(_m) (((_m) & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT)
-#define MODULE_BT_TO_CHAR(_b) ((char)(_b))
-#define MODULE_GET_BTCHAR(_m) (MODULE_BT_TO_CHAR(MODULE_GET_BTYPE(_m)))
-
-/*
- * Macros for getting the rack ID.
- */
-#define MODULE_RACK_MASK 0xffff0000
-#define MODULE_RACK_SHFT 16
-#define MODULE_GET_RACK(_m) (((_m) & MODULE_RACK_MASK) >> MODULE_RACK_SHFT)
-
-/*
- * Macros for getting the brick position
- */
-#define MODULE_BPOS_MASK 0x00ff
-#define MODULE_BPOS_SHFT 0
-#define MODULE_GET_BPOS(_m) (((_m) & MODULE_BPOS_MASK) >> MODULE_BPOS_SHFT)
-
-/*
- * Macros for encoding and decoding rack IDs
- * A rack number consists of three parts:
- * class (0==CPU/mixed, 1==I/O), group, number
- *
- * Rack number is stored just as it is displayed on the screen:
- * a 3-decimal-digit number.
- */
-#define RACK_CLASS_DVDR 100
-#define RACK_GROUP_DVDR 10
-#define RACK_NUM_DVDR 1
-
-#define RACK_CREATE_RACKID(_c, _g, _n) ((_c) * RACK_CLASS_DVDR + \
- (_g) * RACK_GROUP_DVDR + (_n) * RACK_NUM_DVDR)
-
-#define RACK_GET_CLASS(_r) ((_r) / RACK_CLASS_DVDR)
-#define RACK_GET_GROUP(_r) (((_r) - RACK_GET_CLASS(_r) * \
- RACK_CLASS_DVDR) / RACK_GROUP_DVDR)
-#define RACK_GET_NUM(_r) (((_r) - RACK_GET_CLASS(_r) * \
- RACK_CLASS_DVDR - RACK_GET_GROUP(_r) * \
- RACK_GROUP_DVDR) / RACK_NUM_DVDR)
-
-/*
- * Macros for encoding and decoding rack IDs
- * A rack number consists of three parts:
- * class 1 bit, 0==CPU/mixed, 1==I/O
- * group 2 bits for CPU/mixed, 3 bits for I/O
- * number 3 bits for CPU/mixed, 2 bits for I/O (1 based)
- */
-#define RACK_GROUP_BITS(_r) (RACK_GET_CLASS(_r) ? 3 : 2)
-#define RACK_NUM_BITS(_r) (RACK_GET_CLASS(_r) ? 2 : 3)
-
-#define RACK_CLASS_MASK(_r) 0x20
-#define RACK_CLASS_SHFT(_r) 5
-#define RACK_ADD_CLASS(_r, _c) \
- ((_r) |= (_c) << RACK_CLASS_SHFT(_r) & RACK_CLASS_MASK(_r))
-
-#define RACK_GROUP_SHFT(_r) RACK_NUM_BITS(_r)
-#define RACK_GROUP_MASK(_r) \
- ( (((unsigned)1<<RACK_GROUP_BITS(_r)) - 1) << RACK_GROUP_SHFT(_r) )
-#define RACK_ADD_GROUP(_r, _g) \
- ((_r) |= (_g) << RACK_GROUP_SHFT(_r) & RACK_GROUP_MASK(_r))
-
-#define RACK_NUM_SHFT(_r) 0
-#define RACK_NUM_MASK(_r) \
- ( (((unsigned)1<<RACK_NUM_BITS(_r)) - 1) << RACK_NUM_SHFT(_r) )
-#define RACK_ADD_NUM(_r, _n) \
- ((_r) |= ((_n) - 1) << RACK_NUM_SHFT(_r) & RACK_NUM_MASK(_r))
-
-
-/*
- * Brick type definitions
- */
-#define MAX_BRICK_TYPES 256 /* brick type is stored as uchar */
-
-extern char brick_types[];
-
-#define MODULE_CBRICK 0
-#define MODULE_RBRICK 1
-#define MODULE_IBRICK 2
-#define MODULE_KBRICK 3
-#define MODULE_XBRICK 4
-#define MODULE_DBRICK 5
-#define MODULE_PBRICK 6
-#define MODULE_NBRICK 7
-#define MODULE_PEBRICK 8
-#define MODULE_PXBRICK 9
-#define MODULE_IXBRICK 10
-#define MODULE_CGBRICK 11
-#define MODULE_OPUSBRICK 12
-#define MODULE_SABRICK 13 /* TIO BringUp Brick */
-#define MODULE_IABRICK 14
-#define MODULE_PABRICK 15
-#define MODULE_GABRICK 16
-#define MODULE_OPUS_TIO 17 /* OPUS TIO Riser */
-
-extern char brick_types[];
-extern void format_module_id(char *, moduleid_t, int);
-
-#endif /* _ASM_IA64_SN_MODULE_H */
diff --git a/arch/ia64/include/asm/sn/mspec.h b/arch/ia64/include/asm/sn/mspec.h
deleted file mode 100644
index c1d3c50c3223..000000000000
--- a/arch/ia64/include/asm/sn/mspec.h
+++ /dev/null
@@ -1,59 +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) 2001-2008 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_MSPEC_H
-#define _ASM_IA64_SN_MSPEC_H
-
-#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */
-
-#define FETCHOP_LOAD 0
-#define FETCHOP_INCREMENT 8
-#define FETCHOP_DECREMENT 16
-#define FETCHOP_CLEAR 24
-
-#define FETCHOP_STORE 0
-#define FETCHOP_AND 24
-#define FETCHOP_OR 32
-
-#define FETCHOP_CLEAR_CACHE 56
-
-#define FETCHOP_LOAD_OP(addr, op) ( \
- *(volatile long *)((char*) (addr) + (op)))
-
-#define FETCHOP_STORE_OP(addr, op, x) ( \
- *(volatile long *)((char*) (addr) + (op)) = (long) (x))
-
-#ifdef __KERNEL__
-
-/*
- * Each Atomic Memory Operation (amo, formerly known as fetchop)
- * variable is 64 bytes long. The first 8 bytes are used. The
- * remaining 56 bytes are unaddressable due to the operation taking
- * that portion of the address.
- *
- * NOTE: The amo structure _MUST_ be placed in either the first or second
- * half of the cache line. The cache line _MUST NOT_ be used for anything
- * other than additional amo entries. This is because there are two
- * addresses which reference the same physical cache line. One will
- * be a cached entry with the memory type bits all set. This address
- * may be loaded into processor cache. The amo will be referenced
- * uncached via the memory special memory type. If any portion of the
- * cached cache-line is modified, when that line is flushed, it will
- * overwrite the uncached value in physical memory and lead to
- * inconsistency.
- */
-struct amo {
- u64 variable;
- u64 unused[7];
-};
-
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_IA64_SN_MSPEC_H */
diff --git a/arch/ia64/include/asm/sn/nodepda.h b/arch/ia64/include/asm/sn/nodepda.h
deleted file mode 100644
index 7c8b4710f071..000000000000
--- a/arch/ia64/include/asm/sn/nodepda.h
+++ /dev/null
@@ -1,82 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_NODEPDA_H
-#define _ASM_IA64_SN_NODEPDA_H
-
-
-#include <asm/irq.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/bte.h>
-
-/*
- * NUMA Node-Specific Data structures are defined in this file.
- * In particular, this is the location of the node PDA.
- * A pointer to the right node PDA is saved in each CPU PDA.
- */
-
-/*
- * Node-specific data structure.
- *
- * One of these structures is allocated on each node of a NUMA system.
- *
- * This structure provides a convenient way of keeping together
- * all per-node data structures.
- */
-struct phys_cpuid {
- short nasid;
- char subnode;
- char slice;
-};
-
-struct nodepda_s {
- void *pdinfo; /* Platform-dependent per-node info */
-
- /*
- * The BTEs on this node are shared by the local cpus
- */
- struct bteinfo_s bte_if[MAX_BTES_PER_NODE]; /* Virtual Interface */
- struct timer_list bte_recovery_timer;
- spinlock_t bte_recovery_lock;
-
- /*
- * Array of pointers to the nodepdas for each node.
- */
- struct nodepda_s *pernode_pdaindr[MAX_COMPACT_NODES];
-
- /*
- * Array of physical cpu identifiers. Indexed by cpuid.
- */
- struct phys_cpuid phys_cpuid[NR_CPUS];
- spinlock_t ptc_lock ____cacheline_aligned_in_smp;
-};
-
-typedef struct nodepda_s nodepda_t;
-
-/*
- * Access Functions for node PDA.
- * Since there is one nodepda for each node, we need a convenient mechanism
- * to access these nodepdas without cluttering code with #ifdefs.
- * The next set of definitions provides this.
- * Routines are expected to use
- *
- * sn_nodepda - to access node PDA for the node on which code is running
- * NODEPDA(cnodeid) - to access node PDA for cnodeid
- */
-
-DECLARE_PER_CPU(struct nodepda_s *, __sn_nodepda);
-#define sn_nodepda __this_cpu_read(__sn_nodepda)
-#define NODEPDA(cnodeid) (sn_nodepda->pernode_pdaindr[cnodeid])
-
-/*
- * Check if given a compact node id the corresponding node has all the
- * cpus disabled.
- */
-#define is_headless_node(cnodeid) (nr_cpus_node(cnodeid) == 0)
-
-#endif /* _ASM_IA64_SN_NODEPDA_H */
diff --git a/arch/ia64/include/asm/sn/pcibr_provider.h b/arch/ia64/include/asm/sn/pcibr_provider.h
deleted file mode 100644
index da205b7cdaac..000000000000
--- a/arch/ia64/include/asm/sn/pcibr_provider.h
+++ /dev/null
@@ -1,150 +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_PCI_PCIBR_PROVIDER_H
-#define _ASM_IA64_SN_PCI_PCIBR_PROVIDER_H
-
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibus_provider_defs.h>
-
-/* Workarounds */
-#define PV907516 (1 << 1) /* TIOCP: Don't write the write buffer flush reg */
-
-#define BUSTYPE_MASK 0x1
-
-/* Macros given a pcibus structure */
-#define IS_PCIX(ps) ((ps)->pbi_bridge_mode & BUSTYPE_MASK)
-#define IS_PCI_BRIDGE_ASIC(asic) (asic == PCIIO_ASIC_TYPE_PIC || \
- asic == PCIIO_ASIC_TYPE_TIOCP)
-#define IS_PIC_SOFT(ps) (ps->pbi_bridge_type == PCIBR_BRIDGETYPE_PIC)
-#define IS_TIOCP_SOFT(ps) (ps->pbi_bridge_type == PCIBR_BRIDGETYPE_TIOCP)
-
-
-/*
- * The different PCI Bridge types supported on the SGI Altix platforms
- */
-#define PCIBR_BRIDGETYPE_UNKNOWN -1
-#define PCIBR_BRIDGETYPE_PIC 2
-#define PCIBR_BRIDGETYPE_TIOCP 3
-
-/*
- * Bridge 64bit Direct Map Attributes
- */
-#define PCI64_ATTR_PREF (1ull << 59)
-#define PCI64_ATTR_PREC (1ull << 58)
-#define PCI64_ATTR_VIRTUAL (1ull << 57)
-#define PCI64_ATTR_BAR (1ull << 56)
-#define PCI64_ATTR_SWAP (1ull << 55)
-#define PCI64_ATTR_VIRTUAL1 (1ull << 54)
-
-#define PCI32_LOCAL_BASE 0
-#define PCI32_MAPPED_BASE 0x40000000
-#define PCI32_DIRECT_BASE 0x80000000
-
-#define IS_PCI32_MAPPED(x) ((u64)(x) < PCI32_DIRECT_BASE && \
- (u64)(x) >= PCI32_MAPPED_BASE)
-#define IS_PCI32_DIRECT(x) ((u64)(x) >= PCI32_MAPPED_BASE)
-
-
-/*
- * Bridge PMU Address Transaltion Entry Attibutes
- */
-#define PCI32_ATE_V (0x1 << 0)
-#define PCI32_ATE_CO (0x1 << 1) /* PIC ASIC ONLY */
-#define PCI32_ATE_PIO (0x1 << 1) /* TIOCP ASIC ONLY */
-#define PCI32_ATE_MSI (0x1 << 2)
-#define PCI32_ATE_PREF (0x1 << 3)
-#define PCI32_ATE_BAR (0x1 << 4)
-#define PCI32_ATE_ADDR_SHFT 12
-
-#define MINIMAL_ATES_REQUIRED(addr, size) \
- (IOPG(IOPGOFF(addr) + (size) - 1) == IOPG((size) - 1))
-
-#define MINIMAL_ATE_FLAG(addr, size) \
- (MINIMAL_ATES_REQUIRED((u64)addr, size) ? 1 : 0)
-
-/* bit 29 of the pci address is the SWAP bit */
-#define ATE_SWAPSHIFT 29
-#define ATE_SWAP_ON(x) ((x) |= (1 << ATE_SWAPSHIFT))
-#define ATE_SWAP_OFF(x) ((x) &= ~(1 << ATE_SWAPSHIFT))
-
-/*
- * I/O page size
- */
-#if PAGE_SIZE < 16384
-#define IOPFNSHIFT 12 /* 4K per mapped page */
-#else
-#define IOPFNSHIFT 14 /* 16K per mapped page */
-#endif
-
-#define IOPGSIZE (1 << IOPFNSHIFT)
-#define IOPG(x) ((x) >> IOPFNSHIFT)
-#define IOPGOFF(x) ((x) & (IOPGSIZE-1))
-
-#define PCIBR_DEV_SWAP_DIR (1ull << 19)
-#define PCIBR_CTRL_PAGE_SIZE (0x1 << 21)
-
-/*
- * PMU resources.
- */
-struct ate_resource{
- u64 *ate;
- u64 num_ate;
- u64 lowest_free_index;
-};
-
-struct pcibus_info {
- struct pcibus_bussoft pbi_buscommon; /* common header */
- u32 pbi_moduleid;
- short pbi_bridge_type;
- short pbi_bridge_mode;
-
- struct ate_resource pbi_int_ate_resource;
- u64 pbi_int_ate_size;
-
- u64 pbi_dir_xbase;
- char pbi_hub_xid;
-
- u64 pbi_devreg[8];
-
- u32 pbi_valid_devices;
- u32 pbi_enabled_devices;
-
- spinlock_t pbi_lock;
-};
-
-extern int pcibr_init_provider(void);
-extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *);
-extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type);
-extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type);
-extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
-
-/*
- * prototypes for the bridge asic register access routines in pcibr_reg.c
- */
-extern void pcireg_control_bit_clr(struct pcibus_info *, u64);
-extern void pcireg_control_bit_set(struct pcibus_info *, u64);
-extern u64 pcireg_tflush_get(struct pcibus_info *);
-extern u64 pcireg_intr_status_get(struct pcibus_info *);
-extern void pcireg_intr_enable_bit_clr(struct pcibus_info *, u64);
-extern void pcireg_intr_enable_bit_set(struct pcibus_info *, u64);
-extern void pcireg_intr_addr_addr_set(struct pcibus_info *, int, u64);
-extern void pcireg_force_intr_set(struct pcibus_info *, int);
-extern u64 pcireg_wrb_flush_get(struct pcibus_info *, int);
-extern void pcireg_int_ate_set(struct pcibus_info *, int, u64);
-extern u64 __iomem * pcireg_int_ate_addr(struct pcibus_info *, int);
-extern void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info);
-extern void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info);
-extern int pcibr_ate_alloc(struct pcibus_info *, int);
-extern void pcibr_ate_free(struct pcibus_info *, int);
-extern void ate_write(struct pcibus_info *, int, int, u64);
-extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
- void *resp, char **ssdt);
-extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
- int action, void *resp);
-extern u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus);
-#endif
diff --git a/arch/ia64/include/asm/sn/pcibus_provider_defs.h b/arch/ia64/include/asm/sn/pcibus_provider_defs.h
deleted file mode 100644
index 8f7c83d0f6d3..000000000000
--- a/arch/ia64/include/asm/sn/pcibus_provider_defs.h
+++ /dev/null
@@ -1,68 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
-#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
-
-/*
- * SN pci asic types. Do not ever renumber these or reuse values. The
- * values must agree with what prom thinks they are.
- */
-
-#define PCIIO_ASIC_TYPE_UNKNOWN 0
-#define PCIIO_ASIC_TYPE_PPB 1
-#define PCIIO_ASIC_TYPE_PIC 2
-#define PCIIO_ASIC_TYPE_TIOCP 3
-#define PCIIO_ASIC_TYPE_TIOCA 4
-#define PCIIO_ASIC_TYPE_TIOCE 5
-
-#define PCIIO_ASIC_MAX_TYPES 6
-
-/*
- * Common pciio bus provider data. There should be one of these as the
- * first field in any pciio based provider soft structure (e.g. pcibr_soft
- * tioca_soft, etc).
- */
-
-struct pcibus_bussoft {
- u32 bs_asic_type; /* chipset type */
- u32 bs_xid; /* xwidget id */
- u32 bs_persist_busnum; /* Persistent Bus Number */
- u32 bs_persist_segment; /* Segment Number */
- u64 bs_legacy_io; /* legacy io pio addr */
- u64 bs_legacy_mem; /* legacy mem pio addr */
- u64 bs_base; /* widget base */
- struct xwidget_info *bs_xwidget_info;
-};
-
-struct pci_controller;
-/*
- * SN pci bus indirection
- */
-
-struct sn_pcibus_provider {
- dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t, int flags);
- dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags);
- void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
- void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
- void (*force_interrupt)(struct sn_irq_info *);
- void (*target_interrupt)(struct sn_irq_info *);
-};
-
-/*
- * Flags used by the map interfaces
- * bits 3:0 specifies format of passed in address
- * bit 4 specifies that address is to be used for MSI
- */
-
-#define SN_DMA_ADDRTYPE(x) ((x) & 0xf)
-#define SN_DMA_ADDR_PHYS 1 /* address is an xio address. */
-#define SN_DMA_ADDR_XIO 2 /* address is phys memory */
-#define SN_DMA_MSI 0x10 /* Bus address is to be used for MSI */
-
-extern struct sn_pcibus_provider *sn_pci_provider[];
-#endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
diff --git a/arch/ia64/include/asm/sn/pcidev.h b/arch/ia64/include/asm/sn/pcidev.h
deleted file mode 100644
index 1c2382cea807..000000000000
--- a/arch/ia64/include/asm/sn/pcidev.h
+++ /dev/null
@@ -1,85 +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_PCI_PCIDEV_H
-#define _ASM_IA64_SN_PCI_PCIDEV_H
-
-#include <linux/pci.h>
-
-/*
- * In ia64, pci_dev->sysdata must be a *pci_controller. To provide access to
- * the pcidev_info structs for all devices under a controller, we keep a
- * list of pcidev_info under pci_controller->platform_data.
- */
-struct sn_platform_data {
- void *provider_soft;
- struct list_head pcidev_info;
-};
-
-#define SN_PLATFORM_DATA(busdev) \
- ((struct sn_platform_data *)(PCI_CONTROLLER(busdev)->platform_data))
-
-#define SN_PCIDEV_INFO(dev) sn_pcidev_info_get(dev)
-
-/*
- * Given a pci_bus, return the sn pcibus_bussoft struct. Note that
- * this only works for root busses, not for busses represented by PPB's.
- */
-
-#define SN_PCIBUS_BUSSOFT(pci_bus) \
- ((struct pcibus_bussoft *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
-
-#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
- ((struct pcibus_info *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
-/*
- * Given a struct pci_dev, return the sn pcibus_bussoft struct. Note
- * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
- * due to possible PPB's in the path.
- */
-
-#define SN_PCIDEV_BUSSOFT(pci_dev) \
- (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info)
-
-#define SN_PCIDEV_BUSPROVIDER(pci_dev) \
- (SN_PCIDEV_INFO(pci_dev)->pdi_provider)
-
-#define PCIIO_BUS_NONE 255 /* bus 255 reserved */
-#define PCIIO_SLOT_NONE 255
-#define PCIIO_FUNC_NONE 255
-#define PCIIO_VENDOR_ID_NONE (-1)
-
-struct pcidev_info {
- u64 pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */
- u64 pdi_slot_host_handle; /* Bus and devfn Host pci_dev */
-
- struct pcibus_bussoft *pdi_pcibus_info; /* Kernel common bus soft */
- struct pcidev_info *pdi_host_pcidev_info; /* Kernel Host pci_dev */
- struct pci_dev *pdi_linux_pcidev; /* Kernel pci_dev */
-
- struct sn_irq_info *pdi_sn_irq_info;
- struct sn_pcibus_provider *pdi_provider; /* sn pci ops */
- struct pci_dev *host_pci_dev; /* host bus link */
- struct list_head pdi_list; /* List of pcidev_info */
-};
-
-extern void sn_irq_fixup(struct pci_dev *pci_dev,
- struct sn_irq_info *sn_irq_info);
-extern void sn_irq_unfixup(struct pci_dev *pci_dev);
-extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
-extern void sn_bus_fixup(struct pci_bus *);
-extern void sn_acpi_bus_fixup(struct pci_bus *);
-extern void sn_common_bus_fixup(struct pci_bus *, struct pcibus_bussoft *);
-extern void sn_bus_store_sysdata(struct pci_dev *dev);
-extern void sn_bus_free_sysdata(void);
-extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
-extern void sn_io_slot_fixup(struct pci_dev *);
-extern void sn_acpi_slot_fixup(struct pci_dev *);
-extern void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *,
- struct sn_irq_info *);
-extern void sn_pci_unfixup_slot(struct pci_dev *dev);
-extern void sn_irq_lh_init(void);
-#endif /* _ASM_IA64_SN_PCI_PCIDEV_H */
diff --git a/arch/ia64/include/asm/sn/pda.h b/arch/ia64/include/asm/sn/pda.h
deleted file mode 100644
index 22ae358c8d16..000000000000
--- a/arch/ia64/include/asm/sn/pda.h
+++ /dev/null
@@ -1,68 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PDA_H
-#define _ASM_IA64_SN_PDA_H
-
-#include <linux/cache.h>
-#include <asm/percpu.h>
-
-
-/*
- * CPU-specific data structure.
- *
- * One of these structures is allocated for each cpu of a NUMA system.
- *
- * This structure provides a convenient way of keeping together
- * all SN per-cpu data structures.
- */
-
-typedef struct pda_s {
-
- /*
- * Support for SN LEDs
- */
- volatile short *led_address;
- u8 led_state;
- u8 hb_state; /* supports blinking heartbeat leds */
- unsigned int hb_count;
-
- unsigned int idle_flag;
-
- volatile unsigned long *bedrock_rev_id;
- volatile unsigned long *pio_write_status_addr;
- unsigned long pio_write_status_val;
- volatile unsigned long *pio_shub_war_cam_addr;
-
- unsigned long sn_in_service_ivecs[4];
- int sn_lb_int_war_ticks;
- int sn_last_irq;
- int sn_first_irq;
-} pda_t;
-
-
-#define CACHE_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
-
-/*
- * PDA
- * Per-cpu private data area for each cpu. The PDA is located immediately after
- * the IA64 cpu_data area. A full page is allocated for the cp_data area for each
- * cpu but only a small amout of the page is actually used. We put the SNIA PDA
- * in the same page as the cpu_data area. Note that there is a check in the setup
- * code to verify that we don't overflow the page.
- *
- * Seems like we should should cache-line align the pda so that any changes in the
- * size of the cpu_data area don't change cache layout. Should we align to 32, 64, 128
- * or 512 boundary. Each has merits. For now, pick 128 but should be revisited later.
- */
-DECLARE_PER_CPU(struct pda_s, pda_percpu);
-
-#define pda (&__ia64_per_cpu_var(pda_percpu))
-
-#define pdacpu(cpu) (&per_cpu(pda_percpu, cpu))
-
-#endif /* _ASM_IA64_SN_PDA_H */
diff --git a/arch/ia64/include/asm/sn/pic.h b/arch/ia64/include/asm/sn/pic.h
deleted file mode 100644
index 5f9da5fd6e56..000000000000
--- a/arch/ia64/include/asm/sn/pic.h
+++ /dev/null
@@ -1,261 +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-2003 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PIC_H
-#define _ASM_IA64_SN_PCI_PIC_H
-
-/*
- * PIC AS DEVICE ZERO
- * ------------------
- *
- * PIC handles PCI/X busses. PCI/X requires that the 'bridge' (i.e. PIC)
- * be designated as 'device 0'. That is a departure from earlier SGI
- * PCI bridges. Because of that we use config space 1 to access the
- * config space of the first actual PCI device on the bus.
- * Here's what the PIC manual says:
- *
- * The current PCI-X bus specification now defines that the parent
- * hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC
- * reduced the total number of devices from 8 to 4 and removed the
- * device registers and windows, now only supporting devices 0,1,2, and
- * 3. PIC did leave all 8 configuration space windows. The reason was
- * there was nothing to gain by removing them. Here in lies the problem.
- * The device numbering we do using 0 through 3 is unrelated to the device
- * numbering which PCI-X requires in configuration space. In the past we
- * correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc.
- * PCI-X requires we start a 1, not 0 and currently the PX brick
- * does associate our:
- *
- * device 0 with configuration space window 1,
- * device 1 with configuration space window 2,
- * device 2 with configuration space window 3,
- * device 3 with configuration space window 4.
- *
- * The net effect is that all config space access are off-by-one with
- * relation to other per-slot accesses on the PIC.
- * Here is a table that shows some of that:
- *
- * Internal Slot#
- * |
- * | 0 1 2 3
- * ----------|---------------------------------------
- * config | 0x21000 0x22000 0x23000 0x24000
- * |
- * even rrb | 0[0] n/a 1[0] n/a [] == implied even/odd
- * |
- * odd rrb | n/a 0[1] n/a 1[1]
- * |
- * int dev | 00 01 10 11
- * |
- * ext slot# | 1 2 3 4
- * ----------|---------------------------------------
- */
-
-#define PIC_ATE_TARGETID_SHFT 8
-#define PIC_HOST_INTR_ADDR 0x0000FFFFFFFFFFFFUL
-#define PIC_PCI64_ATTR_TARG_SHFT 60
-
-
-/*****************************************************************************
- *********************** PIC MMR structure mapping ***************************
- *****************************************************************************/
-
-/* NOTE: PIC WAR. PV#854697. PIC does not allow writes just to [31:0]
- * of a 64-bit register. When writing PIC registers, always write the
- * entire 64 bits.
- */
-
-struct pic {
-
- /* 0x000000-0x00FFFF -- Local Registers */
-
- /* 0x000000-0x000057 -- Standard Widget Configuration */
- u64 p_wid_id; /* 0x000000 */
- u64 p_wid_stat; /* 0x000008 */
- u64 p_wid_err_upper; /* 0x000010 */
- u64 p_wid_err_lower; /* 0x000018 */
- #define p_wid_err p_wid_err_lower
- u64 p_wid_control; /* 0x000020 */
- u64 p_wid_req_timeout; /* 0x000028 */
- u64 p_wid_int_upper; /* 0x000030 */
- u64 p_wid_int_lower; /* 0x000038 */
- #define p_wid_int p_wid_int_lower
- u64 p_wid_err_cmdword; /* 0x000040 */
- u64 p_wid_llp; /* 0x000048 */
- u64 p_wid_tflush; /* 0x000050 */
-
- /* 0x000058-0x00007F -- Bridge-specific Widget Configuration */
- u64 p_wid_aux_err; /* 0x000058 */
- u64 p_wid_resp_upper; /* 0x000060 */
- u64 p_wid_resp_lower; /* 0x000068 */
- #define p_wid_resp p_wid_resp_lower
- u64 p_wid_tst_pin_ctrl; /* 0x000070 */
- u64 p_wid_addr_lkerr; /* 0x000078 */
-
- /* 0x000080-0x00008F -- PMU & MAP */
- u64 p_dir_map; /* 0x000080 */
- u64 _pad_000088; /* 0x000088 */
-
- /* 0x000090-0x00009F -- SSRAM */
- u64 p_map_fault; /* 0x000090 */
- u64 _pad_000098; /* 0x000098 */
-
- /* 0x0000A0-0x0000AF -- Arbitration */
- u64 p_arb; /* 0x0000A0 */
- u64 _pad_0000A8; /* 0x0000A8 */
-
- /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
- u64 p_ate_parity_err; /* 0x0000B0 */
- u64 _pad_0000B8; /* 0x0000B8 */
-
- /* 0x0000C0-0x0000FF -- PCI/GIO */
- u64 p_bus_timeout; /* 0x0000C0 */
- u64 p_pci_cfg; /* 0x0000C8 */
- u64 p_pci_err_upper; /* 0x0000D0 */
- u64 p_pci_err_lower; /* 0x0000D8 */
- #define p_pci_err p_pci_err_lower
- u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */
-
- /* 0x000100-0x0001FF -- Interrupt */
- u64 p_int_status; /* 0x000100 */
- u64 p_int_enable; /* 0x000108 */
- u64 p_int_rst_stat; /* 0x000110 */
- u64 p_int_mode; /* 0x000118 */
- u64 p_int_device; /* 0x000120 */
- u64 p_int_host_err; /* 0x000128 */
- u64 p_int_addr[8]; /* 0x0001{30,,,68} */
- u64 p_err_int_view; /* 0x000170 */
- u64 p_mult_int; /* 0x000178 */
- u64 p_force_always[8]; /* 0x0001{80,,,B8} */
- u64 p_force_pin[8]; /* 0x0001{C0,,,F8} */
-
- /* 0x000200-0x000298 -- Device */
- u64 p_device[4]; /* 0x0002{00,,,18} */
- u64 _pad_000220[4]; /* 0x0002{20,,,38} */
- u64 p_wr_req_buf[4]; /* 0x0002{40,,,58} */
- u64 _pad_000260[4]; /* 0x0002{60,,,78} */
- u64 p_rrb_map[2]; /* 0x0002{80,,,88} */
- #define p_even_resp p_rrb_map[0] /* 0x000280 */
- #define p_odd_resp p_rrb_map[1] /* 0x000288 */
- u64 p_resp_status; /* 0x000290 */
- u64 p_resp_clear; /* 0x000298 */
-
- u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */
-
- /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
- struct {
- u64 upper; /* 0x0003{00,,,F0} */
- u64 lower; /* 0x0003{08,,,F8} */
- } p_buf_addr_match[16];
-
- /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
- struct {
- u64 flush_w_touch; /* 0x000{400,,,5C0} */
- u64 flush_wo_touch; /* 0x000{408,,,5C8} */
- u64 inflight; /* 0x000{410,,,5D0} */
- u64 prefetch; /* 0x000{418,,,5D8} */
- u64 total_pci_retry; /* 0x000{420,,,5E0} */
- u64 max_pci_retry; /* 0x000{428,,,5E8} */
- u64 max_latency; /* 0x000{430,,,5F0} */
- u64 clear_all; /* 0x000{438,,,5F8} */
- } p_buf_count[8];
-
-
- /* 0x000600-0x0009FF -- PCI/X registers */
- u64 p_pcix_bus_err_addr; /* 0x000600 */
- u64 p_pcix_bus_err_attr; /* 0x000608 */
- u64 p_pcix_bus_err_data; /* 0x000610 */
- u64 p_pcix_pio_split_addr; /* 0x000618 */
- u64 p_pcix_pio_split_attr; /* 0x000620 */
- u64 p_pcix_dma_req_err_attr; /* 0x000628 */
- u64 p_pcix_dma_req_err_addr; /* 0x000630 */
- u64 p_pcix_timeout; /* 0x000638 */
-
- u64 _pad_000640[120]; /* 0x000{640,,,9F8} */
-
- /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
- struct {
- u64 p_buf_addr; /* 0x000{A00,,,AF0} */
- u64 p_buf_attr; /* 0X000{A08,,,AF8} */
- } p_pcix_read_buf_64[16];
-
- struct {
- u64 p_buf_addr; /* 0x000{B00,,,BE0} */
- u64 p_buf_attr; /* 0x000{B08,,,BE8} */
- u64 p_buf_valid; /* 0x000{B10,,,BF0} */
- u64 __pad1; /* 0x000{B18,,,BF8} */
- } p_pcix_write_buf_64[8];
-
- /* End of Local Registers -- Start of Address Map space */
-
- char _pad_000c00[0x010000 - 0x000c00];
-
- /* 0x010000-0x011fff -- Internal ATE RAM (Auto Parity Generation) */
- u64 p_int_ate_ram[1024]; /* 0x010000-0x011fff */
-
- /* 0x012000-0x013fff -- Internal ATE RAM (Manual Parity Generation) */
- u64 p_int_ate_ram_mp[1024]; /* 0x012000-0x013fff */
-
- char _pad_014000[0x18000 - 0x014000];
-
- /* 0x18000-0x197F8 -- PIC Write Request Ram */
- u64 p_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
- u64 p_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
- u64 p_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
-
- char _pad_019800[0x20000 - 0x019800];
-
- /* 0x020000-0x027FFF -- PCI Device Configuration Spaces */
- union {
- u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
- u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
- u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
- u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
- union {
- u8 c[0x100 / 1];
- u16 s[0x100 / 2];
- u32 l[0x100 / 4];
- u64 d[0x100 / 8];
- } f[8];
- } p_type0_cfg_dev[8]; /* 0x02{0000,,,7FFF} */
-
- /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
- union {
- u8 c[0x1000 / 1]; /* 0x028000-0x029000 */
- u16 s[0x1000 / 2]; /* 0x028000-0x029000 */
- u32 l[0x1000 / 4]; /* 0x028000-0x029000 */
- u64 d[0x1000 / 8]; /* 0x028000-0x029000 */
- union {
- u8 c[0x100 / 1];
- u16 s[0x100 / 2];
- u32 l[0x100 / 4];
- u64 d[0x100 / 8];
- } f[8];
- } p_type1_cfg; /* 0x028000-0x029000 */
-
- char _pad_029000[0x030000-0x029000];
-
- /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
- union {
- u8 c[8 / 1];
- u16 s[8 / 2];
- u32 l[8 / 4];
- u64 d[8 / 8];
- } p_pci_iack; /* 0x030000-0x030007 */
-
- char _pad_030007[0x040000-0x030008];
-
- /* 0x040000-0x030007 -- PCIX Special Cycle */
- union {
- u8 c[8 / 1];
- u16 s[8 / 2];
- u32 l[8 / 4];
- u64 d[8 / 8];
- } p_pcix_cycle; /* 0x040000-0x040007 */
-};
-
-#endif /* _ASM_IA64_SN_PCI_PIC_H */
diff --git a/arch/ia64/include/asm/sn/rw_mmr.h b/arch/ia64/include/asm/sn/rw_mmr.h
deleted file mode 100644
index 2d78f4c5a45e..000000000000
--- a/arch/ia64/include/asm/sn/rw_mmr.h
+++ /dev/null
@@ -1,28 +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) 2002-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-#ifndef _ASM_IA64_SN_RW_MMR_H
-#define _ASM_IA64_SN_RW_MMR_H
-
-
-/*
- * This file that access MMRs via uncached physical addresses.
- * pio_phys_read_mmr - read an MMR
- * pio_phys_write_mmr - write an MMR
- * pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
- * Second MMR will be skipped if address is NULL
- *
- * Addresses passed to these routines should be uncached physical addresses
- * ie., 0x80000....
- */
-
-
-extern long pio_phys_read_mmr(volatile long *mmr);
-extern void pio_phys_write_mmr(volatile long *mmr, long val);
-extern void pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2);
-
-#endif /* _ASM_IA64_SN_RW_MMR_H */
diff --git a/arch/ia64/include/asm/sn/shub_mmr.h b/arch/ia64/include/asm/sn/shub_mmr.h
deleted file mode 100644
index a84d870f4294..000000000000
--- a/arch/ia64/include/asm/sn/shub_mmr.h
+++ /dev/null
@@ -1,502 +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) 2001-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_SHUB_MMR_H
-#define _ASM_IA64_SN_SHUB_MMR_H
-
-/* ==================================================================== */
-/* Register "SH_IPI_INT" */
-/* SHub Inter-Processor Interrupt Registers */
-/* ==================================================================== */
-#define SH1_IPI_INT __IA64_UL_CONST(0x0000000110000380)
-#define SH2_IPI_INT __IA64_UL_CONST(0x0000000010000380)
-
-/* SH_IPI_INT_TYPE */
-/* Description: Type of Interrupt: 0=INT, 2=PMI, 4=NMI, 5=INIT */
-#define SH_IPI_INT_TYPE_SHFT 0
-#define SH_IPI_INT_TYPE_MASK __IA64_UL_CONST(0x0000000000000007)
-
-/* SH_IPI_INT_AGT */
-/* Description: Agent, must be 0 for SHub */
-#define SH_IPI_INT_AGT_SHFT 3
-#define SH_IPI_INT_AGT_MASK __IA64_UL_CONST(0x0000000000000008)
-
-/* SH_IPI_INT_PID */
-/* Description: Processor ID, same setting as on targeted McKinley */
-#define SH_IPI_INT_PID_SHFT 4
-#define SH_IPI_INT_PID_MASK __IA64_UL_CONST(0x00000000000ffff0)
-
-/* SH_IPI_INT_BASE */
-/* Description: Optional interrupt vector area, 2MB aligned */
-#define SH_IPI_INT_BASE_SHFT 21
-#define SH_IPI_INT_BASE_MASK __IA64_UL_CONST(0x0003ffffffe00000)
-
-/* SH_IPI_INT_IDX */
-/* Description: Targeted McKinley interrupt vector */
-#define SH_IPI_INT_IDX_SHFT 52
-#define SH_IPI_INT_IDX_MASK __IA64_UL_CONST(0x0ff0000000000000)
-
-/* SH_IPI_INT_SEND */
-/* Description: Send Interrupt Message to PI, This generates a puls */
-#define SH_IPI_INT_SEND_SHFT 63
-#define SH_IPI_INT_SEND_MASK __IA64_UL_CONST(0x8000000000000000)
-
-/* ==================================================================== */
-/* Register "SH_EVENT_OCCURRED" */
-/* SHub Interrupt Event Occurred */
-/* ==================================================================== */
-#define SH1_EVENT_OCCURRED __IA64_UL_CONST(0x0000000110010000)
-#define SH1_EVENT_OCCURRED_ALIAS __IA64_UL_CONST(0x0000000110010008)
-#define SH2_EVENT_OCCURRED __IA64_UL_CONST(0x0000000010010000)
-#define SH2_EVENT_OCCURRED_ALIAS __IA64_UL_CONST(0x0000000010010008)
-
-/* ==================================================================== */
-/* Register "SH_PI_CAM_CONTROL" */
-/* CRB CAM MMR Access Control */
-/* ==================================================================== */
-#define SH1_PI_CAM_CONTROL __IA64_UL_CONST(0x0000000120050300)
-
-/* ==================================================================== */
-/* Register "SH_SHUB_ID" */
-/* SHub ID Number */
-/* ==================================================================== */
-#define SH1_SHUB_ID __IA64_UL_CONST(0x0000000110060580)
-#define SH1_SHUB_ID_REVISION_SHFT 28
-#define SH1_SHUB_ID_REVISION_MASK __IA64_UL_CONST(0x00000000f0000000)
-
-/* ==================================================================== */
-/* Register "SH_RTC" */
-/* Real-time Clock */
-/* ==================================================================== */
-#define SH1_RTC __IA64_UL_CONST(0x00000001101c0000)
-#define SH2_RTC __IA64_UL_CONST(0x00000002101c0000)
-#define SH_RTC_MASK __IA64_UL_CONST(0x007fffffffffffff)
-
-/* ==================================================================== */
-/* Register "SH_PIO_WRITE_STATUS_0|1" */
-/* PIO Write Status for CPU 0 & 1 */
-/* ==================================================================== */
-#define SH1_PIO_WRITE_STATUS_0 __IA64_UL_CONST(0x0000000120070200)
-#define SH1_PIO_WRITE_STATUS_1 __IA64_UL_CONST(0x0000000120070280)
-#define SH2_PIO_WRITE_STATUS_0 __IA64_UL_CONST(0x0000000020070200)
-#define SH2_PIO_WRITE_STATUS_1 __IA64_UL_CONST(0x0000000020070280)
-#define SH2_PIO_WRITE_STATUS_2 __IA64_UL_CONST(0x0000000020070300)
-#define SH2_PIO_WRITE_STATUS_3 __IA64_UL_CONST(0x0000000020070380)
-
-/* SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK */
-/* Description: Deadlock response detected */
-#define SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT 1
-#define SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK \
- __IA64_UL_CONST(0x0000000000000002)
-
-/* SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT */
-/* Description: Count of currently pending PIO writes */
-#define SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_SHFT 56
-#define SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK \
- __IA64_UL_CONST(0x3f00000000000000)
-
-/* ==================================================================== */
-/* Register "SH_PIO_WRITE_STATUS_0_ALIAS" */
-/* ==================================================================== */
-#define SH1_PIO_WRITE_STATUS_0_ALIAS __IA64_UL_CONST(0x0000000120070208)
-#define SH2_PIO_WRITE_STATUS_0_ALIAS __IA64_UL_CONST(0x0000000020070208)
-
-/* ==================================================================== */
-/* Register "SH_EVENT_OCCURRED" */
-/* SHub Interrupt Event Occurred */
-/* ==================================================================== */
-/* SH_EVENT_OCCURRED_UART_INT */
-/* Description: Pending Junk Bus UART Interrupt */
-#define SH_EVENT_OCCURRED_UART_INT_SHFT 20
-#define SH_EVENT_OCCURRED_UART_INT_MASK __IA64_UL_CONST(0x0000000000100000)
-
-/* SH_EVENT_OCCURRED_IPI_INT */
-/* Description: Pending IPI Interrupt */
-#define SH_EVENT_OCCURRED_IPI_INT_SHFT 28
-#define SH_EVENT_OCCURRED_IPI_INT_MASK __IA64_UL_CONST(0x0000000010000000)
-
-/* SH_EVENT_OCCURRED_II_INT0 */
-/* Description: Pending II 0 Interrupt */
-#define SH_EVENT_OCCURRED_II_INT0_SHFT 29
-#define SH_EVENT_OCCURRED_II_INT0_MASK __IA64_UL_CONST(0x0000000020000000)
-
-/* SH_EVENT_OCCURRED_II_INT1 */
-/* Description: Pending II 1 Interrupt */
-#define SH_EVENT_OCCURRED_II_INT1_SHFT 30
-#define SH_EVENT_OCCURRED_II_INT1_MASK __IA64_UL_CONST(0x0000000040000000)
-
-/* SH2_EVENT_OCCURRED_EXTIO_INT2 */
-/* Description: Pending SHUB 2 EXT IO INT2 */
-#define SH2_EVENT_OCCURRED_EXTIO_INT2_SHFT 33
-#define SH2_EVENT_OCCURRED_EXTIO_INT2_MASK __IA64_UL_CONST(0x0000000200000000)
-
-/* SH2_EVENT_OCCURRED_EXTIO_INT3 */
-/* Description: Pending SHUB 2 EXT IO INT3 */
-#define SH2_EVENT_OCCURRED_EXTIO_INT3_SHFT 34
-#define SH2_EVENT_OCCURRED_EXTIO_INT3_MASK __IA64_UL_CONST(0x0000000400000000)
-
-#define SH_ALL_INT_MASK \
- (SH_EVENT_OCCURRED_UART_INT_MASK | SH_EVENT_OCCURRED_IPI_INT_MASK | \
- SH_EVENT_OCCURRED_II_INT0_MASK | SH_EVENT_OCCURRED_II_INT1_MASK | \
- SH_EVENT_OCCURRED_II_INT1_MASK | SH2_EVENT_OCCURRED_EXTIO_INT2_MASK | \
- SH2_EVENT_OCCURRED_EXTIO_INT3_MASK)
-
-
-/* ==================================================================== */
-/* LEDS */
-/* ==================================================================== */
-#define SH1_REAL_JUNK_BUS_LED0 0x7fed00000UL
-#define SH1_REAL_JUNK_BUS_LED1 0x7fed10000UL
-#define SH1_REAL_JUNK_BUS_LED2 0x7fed20000UL
-#define SH1_REAL_JUNK_BUS_LED3 0x7fed30000UL
-
-#define SH2_REAL_JUNK_BUS_LED0 0xf0000000UL
-#define SH2_REAL_JUNK_BUS_LED1 0xf0010000UL
-#define SH2_REAL_JUNK_BUS_LED2 0xf0020000UL
-#define SH2_REAL_JUNK_BUS_LED3 0xf0030000UL
-
-/* ==================================================================== */
-/* Register "SH1_PTC_0" */
-/* Puge Translation Cache Message Configuration Information */
-/* ==================================================================== */
-#define SH1_PTC_0 __IA64_UL_CONST(0x00000001101a0000)
-
-/* SH1_PTC_0_A */
-/* Description: Type */
-#define SH1_PTC_0_A_SHFT 0
-
-/* SH1_PTC_0_PS */
-/* Description: Page Size */
-#define SH1_PTC_0_PS_SHFT 2
-
-/* SH1_PTC_0_RID */
-/* Description: Region ID */
-#define SH1_PTC_0_RID_SHFT 8
-
-/* SH1_PTC_0_START */
-/* Description: Start */
-#define SH1_PTC_0_START_SHFT 63
-
-/* ==================================================================== */
-/* Register "SH1_PTC_1" */
-/* Puge Translation Cache Message Configuration Information */
-/* ==================================================================== */
-#define SH1_PTC_1 __IA64_UL_CONST(0x00000001101a0080)
-
-/* SH1_PTC_1_START */
-/* Description: PTC_1 Start */
-#define SH1_PTC_1_START_SHFT 63
-
-/* ==================================================================== */
-/* Register "SH2_PTC" */
-/* Puge Translation Cache Message Configuration Information */
-/* ==================================================================== */
-#define SH2_PTC __IA64_UL_CONST(0x0000000170000000)
-
-/* SH2_PTC_A */
-/* Description: Type */
-#define SH2_PTC_A_SHFT 0
-
-/* SH2_PTC_PS */
-/* Description: Page Size */
-#define SH2_PTC_PS_SHFT 2
-
-/* SH2_PTC_RID */
-/* Description: Region ID */
-#define SH2_PTC_RID_SHFT 4
-
-/* SH2_PTC_START */
-/* Description: Start */
-#define SH2_PTC_START_SHFT 63
-
-/* SH2_PTC_ADDR_RID */
-/* Description: Region ID */
-#define SH2_PTC_ADDR_SHFT 4
-#define SH2_PTC_ADDR_MASK __IA64_UL_CONST(0x1ffffffffffff000)
-
-/* ==================================================================== */
-/* Register "SH_RTC1_INT_CONFIG" */
-/* SHub RTC 1 Interrupt Config Registers */
-/* ==================================================================== */
-
-#define SH1_RTC1_INT_CONFIG __IA64_UL_CONST(0x0000000110001480)
-#define SH2_RTC1_INT_CONFIG __IA64_UL_CONST(0x0000000010001480)
-#define SH_RTC1_INT_CONFIG_MASK __IA64_UL_CONST(0x0ff3ffffffefffff)
-#define SH_RTC1_INT_CONFIG_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC1_INT_CONFIG_TYPE */
-/* Description: Type of Interrupt: 0=INT, 2=PMI, 4=NMI, 5=INIT */
-#define SH_RTC1_INT_CONFIG_TYPE_SHFT 0
-#define SH_RTC1_INT_CONFIG_TYPE_MASK __IA64_UL_CONST(0x0000000000000007)
-
-/* SH_RTC1_INT_CONFIG_AGT */
-/* Description: Agent, must be 0 for SHub */
-#define SH_RTC1_INT_CONFIG_AGT_SHFT 3
-#define SH_RTC1_INT_CONFIG_AGT_MASK __IA64_UL_CONST(0x0000000000000008)
-
-/* SH_RTC1_INT_CONFIG_PID */
-/* Description: Processor ID, same setting as on targeted McKinley */
-#define SH_RTC1_INT_CONFIG_PID_SHFT 4
-#define SH_RTC1_INT_CONFIG_PID_MASK __IA64_UL_CONST(0x00000000000ffff0)
-
-/* SH_RTC1_INT_CONFIG_BASE */
-/* Description: Optional interrupt vector area, 2MB aligned */
-#define SH_RTC1_INT_CONFIG_BASE_SHFT 21
-#define SH_RTC1_INT_CONFIG_BASE_MASK __IA64_UL_CONST(0x0003ffffffe00000)
-
-/* SH_RTC1_INT_CONFIG_IDX */
-/* Description: Targeted McKinley interrupt vector */
-#define SH_RTC1_INT_CONFIG_IDX_SHFT 52
-#define SH_RTC1_INT_CONFIG_IDX_MASK __IA64_UL_CONST(0x0ff0000000000000)
-
-/* ==================================================================== */
-/* Register "SH_RTC1_INT_ENABLE" */
-/* SHub RTC 1 Interrupt Enable Registers */
-/* ==================================================================== */
-
-#define SH1_RTC1_INT_ENABLE __IA64_UL_CONST(0x0000000110001500)
-#define SH2_RTC1_INT_ENABLE __IA64_UL_CONST(0x0000000010001500)
-#define SH_RTC1_INT_ENABLE_MASK __IA64_UL_CONST(0x0000000000000001)
-#define SH_RTC1_INT_ENABLE_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC1_INT_ENABLE_RTC1_ENABLE */
-/* Description: Enable RTC 1 Interrupt */
-#define SH_RTC1_INT_ENABLE_RTC1_ENABLE_SHFT 0
-#define SH_RTC1_INT_ENABLE_RTC1_ENABLE_MASK \
- __IA64_UL_CONST(0x0000000000000001)
-
-/* ==================================================================== */
-/* Register "SH_RTC2_INT_CONFIG" */
-/* SHub RTC 2 Interrupt Config Registers */
-/* ==================================================================== */
-
-#define SH1_RTC2_INT_CONFIG __IA64_UL_CONST(0x0000000110001580)
-#define SH2_RTC2_INT_CONFIG __IA64_UL_CONST(0x0000000010001580)
-#define SH_RTC2_INT_CONFIG_MASK __IA64_UL_CONST(0x0ff3ffffffefffff)
-#define SH_RTC2_INT_CONFIG_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC2_INT_CONFIG_TYPE */
-/* Description: Type of Interrupt: 0=INT, 2=PMI, 4=NMI, 5=INIT */
-#define SH_RTC2_INT_CONFIG_TYPE_SHFT 0
-#define SH_RTC2_INT_CONFIG_TYPE_MASK __IA64_UL_CONST(0x0000000000000007)
-
-/* SH_RTC2_INT_CONFIG_AGT */
-/* Description: Agent, must be 0 for SHub */
-#define SH_RTC2_INT_CONFIG_AGT_SHFT 3
-#define SH_RTC2_INT_CONFIG_AGT_MASK __IA64_UL_CONST(0x0000000000000008)
-
-/* SH_RTC2_INT_CONFIG_PID */
-/* Description: Processor ID, same setting as on targeted McKinley */
-#define SH_RTC2_INT_CONFIG_PID_SHFT 4
-#define SH_RTC2_INT_CONFIG_PID_MASK __IA64_UL_CONST(0x00000000000ffff0)
-
-/* SH_RTC2_INT_CONFIG_BASE */
-/* Description: Optional interrupt vector area, 2MB aligned */
-#define SH_RTC2_INT_CONFIG_BASE_SHFT 21
-#define SH_RTC2_INT_CONFIG_BASE_MASK __IA64_UL_CONST(0x0003ffffffe00000)
-
-/* SH_RTC2_INT_CONFIG_IDX */
-/* Description: Targeted McKinley interrupt vector */
-#define SH_RTC2_INT_CONFIG_IDX_SHFT 52
-#define SH_RTC2_INT_CONFIG_IDX_MASK __IA64_UL_CONST(0x0ff0000000000000)
-
-/* ==================================================================== */
-/* Register "SH_RTC2_INT_ENABLE" */
-/* SHub RTC 2 Interrupt Enable Registers */
-/* ==================================================================== */
-
-#define SH1_RTC2_INT_ENABLE __IA64_UL_CONST(0x0000000110001600)
-#define SH2_RTC2_INT_ENABLE __IA64_UL_CONST(0x0000000010001600)
-#define SH_RTC2_INT_ENABLE_MASK __IA64_UL_CONST(0x0000000000000001)
-#define SH_RTC2_INT_ENABLE_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC2_INT_ENABLE_RTC2_ENABLE */
-/* Description: Enable RTC 2 Interrupt */
-#define SH_RTC2_INT_ENABLE_RTC2_ENABLE_SHFT 0
-#define SH_RTC2_INT_ENABLE_RTC2_ENABLE_MASK \
- __IA64_UL_CONST(0x0000000000000001)
-
-/* ==================================================================== */
-/* Register "SH_RTC3_INT_CONFIG" */
-/* SHub RTC 3 Interrupt Config Registers */
-/* ==================================================================== */
-
-#define SH1_RTC3_INT_CONFIG __IA64_UL_CONST(0x0000000110001680)
-#define SH2_RTC3_INT_CONFIG __IA64_UL_CONST(0x0000000010001680)
-#define SH_RTC3_INT_CONFIG_MASK __IA64_UL_CONST(0x0ff3ffffffefffff)
-#define SH_RTC3_INT_CONFIG_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC3_INT_CONFIG_TYPE */
-/* Description: Type of Interrupt: 0=INT, 2=PMI, 4=NMI, 5=INIT */
-#define SH_RTC3_INT_CONFIG_TYPE_SHFT 0
-#define SH_RTC3_INT_CONFIG_TYPE_MASK __IA64_UL_CONST(0x0000000000000007)
-
-/* SH_RTC3_INT_CONFIG_AGT */
-/* Description: Agent, must be 0 for SHub */
-#define SH_RTC3_INT_CONFIG_AGT_SHFT 3
-#define SH_RTC3_INT_CONFIG_AGT_MASK __IA64_UL_CONST(0x0000000000000008)
-
-/* SH_RTC3_INT_CONFIG_PID */
-/* Description: Processor ID, same setting as on targeted McKinley */
-#define SH_RTC3_INT_CONFIG_PID_SHFT 4
-#define SH_RTC3_INT_CONFIG_PID_MASK __IA64_UL_CONST(0x00000000000ffff0)
-
-/* SH_RTC3_INT_CONFIG_BASE */
-/* Description: Optional interrupt vector area, 2MB aligned */
-#define SH_RTC3_INT_CONFIG_BASE_SHFT 21
-#define SH_RTC3_INT_CONFIG_BASE_MASK __IA64_UL_CONST(0x0003ffffffe00000)
-
-/* SH_RTC3_INT_CONFIG_IDX */
-/* Description: Targeted McKinley interrupt vector */
-#define SH_RTC3_INT_CONFIG_IDX_SHFT 52
-#define SH_RTC3_INT_CONFIG_IDX_MASK __IA64_UL_CONST(0x0ff0000000000000)
-
-/* ==================================================================== */
-/* Register "SH_RTC3_INT_ENABLE" */
-/* SHub RTC 3 Interrupt Enable Registers */
-/* ==================================================================== */
-
-#define SH1_RTC3_INT_ENABLE __IA64_UL_CONST(0x0000000110001700)
-#define SH2_RTC3_INT_ENABLE __IA64_UL_CONST(0x0000000010001700)
-#define SH_RTC3_INT_ENABLE_MASK __IA64_UL_CONST(0x0000000000000001)
-#define SH_RTC3_INT_ENABLE_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_RTC3_INT_ENABLE_RTC3_ENABLE */
-/* Description: Enable RTC 3 Interrupt */
-#define SH_RTC3_INT_ENABLE_RTC3_ENABLE_SHFT 0
-#define SH_RTC3_INT_ENABLE_RTC3_ENABLE_MASK \
- __IA64_UL_CONST(0x0000000000000001)
-
-/* SH_EVENT_OCCURRED_RTC1_INT */
-/* Description: Pending RTC 1 Interrupt */
-#define SH_EVENT_OCCURRED_RTC1_INT_SHFT 24
-#define SH_EVENT_OCCURRED_RTC1_INT_MASK __IA64_UL_CONST(0x0000000001000000)
-
-/* SH_EVENT_OCCURRED_RTC2_INT */
-/* Description: Pending RTC 2 Interrupt */
-#define SH_EVENT_OCCURRED_RTC2_INT_SHFT 25
-#define SH_EVENT_OCCURRED_RTC2_INT_MASK __IA64_UL_CONST(0x0000000002000000)
-
-/* SH_EVENT_OCCURRED_RTC3_INT */
-/* Description: Pending RTC 3 Interrupt */
-#define SH_EVENT_OCCURRED_RTC3_INT_SHFT 26
-#define SH_EVENT_OCCURRED_RTC3_INT_MASK __IA64_UL_CONST(0x0000000004000000)
-
-/* ==================================================================== */
-/* Register "SH_IPI_ACCESS" */
-/* CPU interrupt Access Permission Bits */
-/* ==================================================================== */
-
-#define SH1_IPI_ACCESS __IA64_UL_CONST(0x0000000110060480)
-#define SH2_IPI_ACCESS0 __IA64_UL_CONST(0x0000000010060c00)
-#define SH2_IPI_ACCESS1 __IA64_UL_CONST(0x0000000010060c80)
-#define SH2_IPI_ACCESS2 __IA64_UL_CONST(0x0000000010060d00)
-#define SH2_IPI_ACCESS3 __IA64_UL_CONST(0x0000000010060d80)
-
-/* ==================================================================== */
-/* Register "SH_INT_CMPB" */
-/* RTC Compare Value for Processor B */
-/* ==================================================================== */
-
-#define SH1_INT_CMPB __IA64_UL_CONST(0x00000001101b0080)
-#define SH2_INT_CMPB __IA64_UL_CONST(0x00000000101b0080)
-#define SH_INT_CMPB_MASK __IA64_UL_CONST(0x007fffffffffffff)
-#define SH_INT_CMPB_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_INT_CMPB_REAL_TIME_CMPB */
-/* Description: Real Time Clock Compare */
-#define SH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
-#define SH_INT_CMPB_REAL_TIME_CMPB_MASK __IA64_UL_CONST(0x007fffffffffffff)
-
-/* ==================================================================== */
-/* Register "SH_INT_CMPC" */
-/* RTC Compare Value for Processor C */
-/* ==================================================================== */
-
-#define SH1_INT_CMPC __IA64_UL_CONST(0x00000001101b0100)
-#define SH2_INT_CMPC __IA64_UL_CONST(0x00000000101b0100)
-#define SH_INT_CMPC_MASK __IA64_UL_CONST(0x007fffffffffffff)
-#define SH_INT_CMPC_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_INT_CMPC_REAL_TIME_CMPC */
-/* Description: Real Time Clock Compare */
-#define SH_INT_CMPC_REAL_TIME_CMPC_SHFT 0
-#define SH_INT_CMPC_REAL_TIME_CMPC_MASK __IA64_UL_CONST(0x007fffffffffffff)
-
-/* ==================================================================== */
-/* Register "SH_INT_CMPD" */
-/* RTC Compare Value for Processor D */
-/* ==================================================================== */
-
-#define SH1_INT_CMPD __IA64_UL_CONST(0x00000001101b0180)
-#define SH2_INT_CMPD __IA64_UL_CONST(0x00000000101b0180)
-#define SH_INT_CMPD_MASK __IA64_UL_CONST(0x007fffffffffffff)
-#define SH_INT_CMPD_INIT __IA64_UL_CONST(0x0000000000000000)
-
-/* SH_INT_CMPD_REAL_TIME_CMPD */
-/* Description: Real Time Clock Compare */
-#define SH_INT_CMPD_REAL_TIME_CMPD_SHFT 0
-#define SH_INT_CMPD_REAL_TIME_CMPD_MASK __IA64_UL_CONST(0x007fffffffffffff)
-
-/* ==================================================================== */
-/* Register "SH_MD_DQLP_MMR_DIR_PRIVEC0" */
-/* privilege vector for acc=0 */
-/* ==================================================================== */
-#define SH1_MD_DQLP_MMR_DIR_PRIVEC0 __IA64_UL_CONST(0x0000000100030300)
-
-/* ==================================================================== */
-/* Register "SH_MD_DQRP_MMR_DIR_PRIVEC0" */
-/* privilege vector for acc=0 */
-/* ==================================================================== */
-#define SH1_MD_DQRP_MMR_DIR_PRIVEC0 __IA64_UL_CONST(0x0000000100050300)
-
-/* ==================================================================== */
-/* Some MMRs are functionally identical (or close enough) on both SHUB1 */
-/* and SHUB2 that it makes sense to define a geberic name for the MMR. */
-/* It is acceptable to use (for example) SH_IPI_INT to reference the */
-/* the IPI MMR. The value of SH_IPI_INT is determined at runtime based */
-/* on the type of the SHUB. Do not use these #defines in performance */
-/* critical code or loops - there is a small performance penalty. */
-/* ==================================================================== */
-#define shubmmr(a,b) (is_shub2() ? a##2_##b : a##1_##b)
-
-#define SH_REAL_JUNK_BUS_LED0 shubmmr(SH, REAL_JUNK_BUS_LED0)
-#define SH_IPI_INT shubmmr(SH, IPI_INT)
-#define SH_EVENT_OCCURRED shubmmr(SH, EVENT_OCCURRED)
-#define SH_EVENT_OCCURRED_ALIAS shubmmr(SH, EVENT_OCCURRED_ALIAS)
-#define SH_RTC shubmmr(SH, RTC)
-#define SH_RTC1_INT_CONFIG shubmmr(SH, RTC1_INT_CONFIG)
-#define SH_RTC1_INT_ENABLE shubmmr(SH, RTC1_INT_ENABLE)
-#define SH_RTC2_INT_CONFIG shubmmr(SH, RTC2_INT_CONFIG)
-#define SH_RTC2_INT_ENABLE shubmmr(SH, RTC2_INT_ENABLE)
-#define SH_RTC3_INT_CONFIG shubmmr(SH, RTC3_INT_CONFIG)
-#define SH_RTC3_INT_ENABLE shubmmr(SH, RTC3_INT_ENABLE)
-#define SH_INT_CMPB shubmmr(SH, INT_CMPB)
-#define SH_INT_CMPC shubmmr(SH, INT_CMPC)
-#define SH_INT_CMPD shubmmr(SH, INT_CMPD)
-
-/* ========================================================================== */
-/* Register "SH2_BT_ENG_CSR_0" */
-/* Engine 0 Control and Status Register */
-/* ========================================================================== */
-
-#define SH2_BT_ENG_CSR_0 __IA64_UL_CONST(0x0000000030040000)
-#define SH2_BT_ENG_SRC_ADDR_0 __IA64_UL_CONST(0x0000000030040080)
-#define SH2_BT_ENG_DEST_ADDR_0 __IA64_UL_CONST(0x0000000030040100)
-#define SH2_BT_ENG_NOTIF_ADDR_0 __IA64_UL_CONST(0x0000000030040180)
-
-/* ========================================================================== */
-/* BTE interfaces 1-3 */
-/* ========================================================================== */
-
-#define SH2_BT_ENG_CSR_1 __IA64_UL_CONST(0x0000000030050000)
-#define SH2_BT_ENG_CSR_2 __IA64_UL_CONST(0x0000000030060000)
-#define SH2_BT_ENG_CSR_3 __IA64_UL_CONST(0x0000000030070000)
-
-#endif /* _ASM_IA64_SN_SHUB_MMR_H */
diff --git a/arch/ia64/include/asm/sn/shubio.h b/arch/ia64/include/asm/sn/shubio.h
deleted file mode 100644
index 8a1ec139f977..000000000000
--- a/arch/ia64/include/asm/sn/shubio.h
+++ /dev/null
@@ -1,3358 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_SHUBIO_H
-#define _ASM_IA64_SN_SHUBIO_H
-
-#define HUB_WIDGET_ID_MAX 0xf
-#define IIO_NUM_ITTES 7
-#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
-
-#define IIO_WID 0x00400000 /* Crosstalk Widget Identification */
- /* This register is also accessible from
- * Crosstalk at address 0x0. */
-#define IIO_WSTAT 0x00400008 /* Crosstalk Widget Status */
-#define IIO_WCR 0x00400020 /* Crosstalk Widget Control Register */
-#define IIO_ILAPR 0x00400100 /* IO Local Access Protection Register */
-#define IIO_ILAPO 0x00400108 /* IO Local Access Protection Override */
-#define IIO_IOWA 0x00400110 /* IO Outbound Widget Access */
-#define IIO_IIWA 0x00400118 /* IO Inbound Widget Access */
-#define IIO_IIDEM 0x00400120 /* IO Inbound Device Error Mask */
-#define IIO_ILCSR 0x00400128 /* IO LLP Control and Status Register */
-#define IIO_ILLR 0x00400130 /* IO LLP Log Register */
-#define IIO_IIDSR 0x00400138 /* IO Interrupt Destination */
-
-#define IIO_IGFX0 0x00400140 /* IO Graphics Node-Widget Map 0 */
-#define IIO_IGFX1 0x00400148 /* IO Graphics Node-Widget Map 1 */
-
-#define IIO_ISCR0 0x00400150 /* IO Scratch Register 0 */
-#define IIO_ISCR1 0x00400158 /* IO Scratch Register 1 */
-
-#define IIO_ITTE1 0x00400160 /* IO Translation Table Entry 1 */
-#define IIO_ITTE2 0x00400168 /* IO Translation Table Entry 2 */
-#define IIO_ITTE3 0x00400170 /* IO Translation Table Entry 3 */
-#define IIO_ITTE4 0x00400178 /* IO Translation Table Entry 4 */
-#define IIO_ITTE5 0x00400180 /* IO Translation Table Entry 5 */
-#define IIO_ITTE6 0x00400188 /* IO Translation Table Entry 6 */
-#define IIO_ITTE7 0x00400190 /* IO Translation Table Entry 7 */
-
-#define IIO_IPRB0 0x00400198 /* IO PRB Entry 0 */
-#define IIO_IPRB8 0x004001A0 /* IO PRB Entry 8 */
-#define IIO_IPRB9 0x004001A8 /* IO PRB Entry 9 */
-#define IIO_IPRBA 0x004001B0 /* IO PRB Entry A */
-#define IIO_IPRBB 0x004001B8 /* IO PRB Entry B */
-#define IIO_IPRBC 0x004001C0 /* IO PRB Entry C */
-#define IIO_IPRBD 0x004001C8 /* IO PRB Entry D */
-#define IIO_IPRBE 0x004001D0 /* IO PRB Entry E */
-#define IIO_IPRBF 0x004001D8 /* IO PRB Entry F */
-
-#define IIO_IXCC 0x004001E0 /* IO Crosstalk Credit Count Timeout */
-#define IIO_IMEM 0x004001E8 /* IO Miscellaneous Error Mask */
-#define IIO_IXTT 0x004001F0 /* IO Crosstalk Timeout Threshold */
-#define IIO_IECLR 0x004001F8 /* IO Error Clear Register */
-#define IIO_IBCR 0x00400200 /* IO BTE Control Register */
-
-#define IIO_IXSM 0x00400208 /* IO Crosstalk Spurious Message */
-#define IIO_IXSS 0x00400210 /* IO Crosstalk Spurious Sideband */
-
-#define IIO_ILCT 0x00400218 /* IO LLP Channel Test */
-
-#define IIO_IIEPH1 0x00400220 /* IO Incoming Error Packet Header, Part 1 */
-#define IIO_IIEPH2 0x00400228 /* IO Incoming Error Packet Header, Part 2 */
-
-#define IIO_ISLAPR 0x00400230 /* IO SXB Local Access Protection Regster */
-#define IIO_ISLAPO 0x00400238 /* IO SXB Local Access Protection Override */
-
-#define IIO_IWI 0x00400240 /* IO Wrapper Interrupt Register */
-#define IIO_IWEL 0x00400248 /* IO Wrapper Error Log Register */
-#define IIO_IWC 0x00400250 /* IO Wrapper Control Register */
-#define IIO_IWS 0x00400258 /* IO Wrapper Status Register */
-#define IIO_IWEIM 0x00400260 /* IO Wrapper Error Interrupt Masking Register */
-
-#define IIO_IPCA 0x00400300 /* IO PRB Counter Adjust */
-
-#define IIO_IPRTE0_A 0x00400308 /* IO PIO Read Address Table Entry 0, Part A */
-#define IIO_IPRTE1_A 0x00400310 /* IO PIO Read Address Table Entry 1, Part A */
-#define IIO_IPRTE2_A 0x00400318 /* IO PIO Read Address Table Entry 2, Part A */
-#define IIO_IPRTE3_A 0x00400320 /* IO PIO Read Address Table Entry 3, Part A */
-#define IIO_IPRTE4_A 0x00400328 /* IO PIO Read Address Table Entry 4, Part A */
-#define IIO_IPRTE5_A 0x00400330 /* IO PIO Read Address Table Entry 5, Part A */
-#define IIO_IPRTE6_A 0x00400338 /* IO PIO Read Address Table Entry 6, Part A */
-#define IIO_IPRTE7_A 0x00400340 /* IO PIO Read Address Table Entry 7, Part A */
-
-#define IIO_IPRTE0_B 0x00400348 /* IO PIO Read Address Table Entry 0, Part B */
-#define IIO_IPRTE1_B 0x00400350 /* IO PIO Read Address Table Entry 1, Part B */
-#define IIO_IPRTE2_B 0x00400358 /* IO PIO Read Address Table Entry 2, Part B */
-#define IIO_IPRTE3_B 0x00400360 /* IO PIO Read Address Table Entry 3, Part B */
-#define IIO_IPRTE4_B 0x00400368 /* IO PIO Read Address Table Entry 4, Part B */
-#define IIO_IPRTE5_B 0x00400370 /* IO PIO Read Address Table Entry 5, Part B */
-#define IIO_IPRTE6_B 0x00400378 /* IO PIO Read Address Table Entry 6, Part B */
-#define IIO_IPRTE7_B 0x00400380 /* IO PIO Read Address Table Entry 7, Part B */
-
-#define IIO_IPDR 0x00400388 /* IO PIO Deallocation Register */
-#define IIO_ICDR 0x00400390 /* IO CRB Entry Deallocation Register */
-#define IIO_IFDR 0x00400398 /* IO IOQ FIFO Depth Register */
-#define IIO_IIAP 0x004003A0 /* IO IIQ Arbitration Parameters */
-#define IIO_ICMR 0x004003A8 /* IO CRB Management Register */
-#define IIO_ICCR 0x004003B0 /* IO CRB Control Register */
-#define IIO_ICTO 0x004003B8 /* IO CRB Timeout */
-#define IIO_ICTP 0x004003C0 /* IO CRB Timeout Prescalar */
-
-#define IIO_ICRB0_A 0x00400400 /* IO CRB Entry 0_A */
-#define IIO_ICRB0_B 0x00400408 /* IO CRB Entry 0_B */
-#define IIO_ICRB0_C 0x00400410 /* IO CRB Entry 0_C */
-#define IIO_ICRB0_D 0x00400418 /* IO CRB Entry 0_D */
-#define IIO_ICRB0_E 0x00400420 /* IO CRB Entry 0_E */
-
-#define IIO_ICRB1_A 0x00400430 /* IO CRB Entry 1_A */
-#define IIO_ICRB1_B 0x00400438 /* IO CRB Entry 1_B */
-#define IIO_ICRB1_C 0x00400440 /* IO CRB Entry 1_C */
-#define IIO_ICRB1_D 0x00400448 /* IO CRB Entry 1_D */
-#define IIO_ICRB1_E 0x00400450 /* IO CRB Entry 1_E */
-
-#define IIO_ICRB2_A 0x00400460 /* IO CRB Entry 2_A */
-#define IIO_ICRB2_B 0x00400468 /* IO CRB Entry 2_B */
-#define IIO_ICRB2_C 0x00400470 /* IO CRB Entry 2_C */
-#define IIO_ICRB2_D 0x00400478 /* IO CRB Entry 2_D */
-#define IIO_ICRB2_E 0x00400480 /* IO CRB Entry 2_E */
-
-#define IIO_ICRB3_A 0x00400490 /* IO CRB Entry 3_A */
-#define IIO_ICRB3_B 0x00400498 /* IO CRB Entry 3_B */
-#define IIO_ICRB3_C 0x004004a0 /* IO CRB Entry 3_C */
-#define IIO_ICRB3_D 0x004004a8 /* IO CRB Entry 3_D */
-#define IIO_ICRB3_E 0x004004b0 /* IO CRB Entry 3_E */
-
-#define IIO_ICRB4_A 0x004004c0 /* IO CRB Entry 4_A */
-#define IIO_ICRB4_B 0x004004c8 /* IO CRB Entry 4_B */
-#define IIO_ICRB4_C 0x004004d0 /* IO CRB Entry 4_C */
-#define IIO_ICRB4_D 0x004004d8 /* IO CRB Entry 4_D */
-#define IIO_ICRB4_E 0x004004e0 /* IO CRB Entry 4_E */
-
-#define IIO_ICRB5_A 0x004004f0 /* IO CRB Entry 5_A */
-#define IIO_ICRB5_B 0x004004f8 /* IO CRB Entry 5_B */
-#define IIO_ICRB5_C 0x00400500 /* IO CRB Entry 5_C */
-#define IIO_ICRB5_D 0x00400508 /* IO CRB Entry 5_D */
-#define IIO_ICRB5_E 0x00400510 /* IO CRB Entry 5_E */
-
-#define IIO_ICRB6_A 0x00400520 /* IO CRB Entry 6_A */
-#define IIO_ICRB6_B 0x00400528 /* IO CRB Entry 6_B */
-#define IIO_ICRB6_C 0x00400530 /* IO CRB Entry 6_C */
-#define IIO_ICRB6_D 0x00400538 /* IO CRB Entry 6_D */
-#define IIO_ICRB6_E 0x00400540 /* IO CRB Entry 6_E */
-
-#define IIO_ICRB7_A 0x00400550 /* IO CRB Entry 7_A */
-#define IIO_ICRB7_B 0x00400558 /* IO CRB Entry 7_B */
-#define IIO_ICRB7_C 0x00400560 /* IO CRB Entry 7_C */
-#define IIO_ICRB7_D 0x00400568 /* IO CRB Entry 7_D */
-#define IIO_ICRB7_E 0x00400570 /* IO CRB Entry 7_E */
-
-#define IIO_ICRB8_A 0x00400580 /* IO CRB Entry 8_A */
-#define IIO_ICRB8_B 0x00400588 /* IO CRB Entry 8_B */
-#define IIO_ICRB8_C 0x00400590 /* IO CRB Entry 8_C */
-#define IIO_ICRB8_D 0x00400598 /* IO CRB Entry 8_D */
-#define IIO_ICRB8_E 0x004005a0 /* IO CRB Entry 8_E */
-
-#define IIO_ICRB9_A 0x004005b0 /* IO CRB Entry 9_A */
-#define IIO_ICRB9_B 0x004005b8 /* IO CRB Entry 9_B */
-#define IIO_ICRB9_C 0x004005c0 /* IO CRB Entry 9_C */
-#define IIO_ICRB9_D 0x004005c8 /* IO CRB Entry 9_D */
-#define IIO_ICRB9_E 0x004005d0 /* IO CRB Entry 9_E */
-
-#define IIO_ICRBA_A 0x004005e0 /* IO CRB Entry A_A */
-#define IIO_ICRBA_B 0x004005e8 /* IO CRB Entry A_B */
-#define IIO_ICRBA_C 0x004005f0 /* IO CRB Entry A_C */
-#define IIO_ICRBA_D 0x004005f8 /* IO CRB Entry A_D */
-#define IIO_ICRBA_E 0x00400600 /* IO CRB Entry A_E */
-
-#define IIO_ICRBB_A 0x00400610 /* IO CRB Entry B_A */
-#define IIO_ICRBB_B 0x00400618 /* IO CRB Entry B_B */
-#define IIO_ICRBB_C 0x00400620 /* IO CRB Entry B_C */
-#define IIO_ICRBB_D 0x00400628 /* IO CRB Entry B_D */
-#define IIO_ICRBB_E 0x00400630 /* IO CRB Entry B_E */
-
-#define IIO_ICRBC_A 0x00400640 /* IO CRB Entry C_A */
-#define IIO_ICRBC_B 0x00400648 /* IO CRB Entry C_B */
-#define IIO_ICRBC_C 0x00400650 /* IO CRB Entry C_C */
-#define IIO_ICRBC_D 0x00400658 /* IO CRB Entry C_D */
-#define IIO_ICRBC_E 0x00400660 /* IO CRB Entry C_E */
-
-#define IIO_ICRBD_A 0x00400670 /* IO CRB Entry D_A */
-#define IIO_ICRBD_B 0x00400678 /* IO CRB Entry D_B */
-#define IIO_ICRBD_C 0x00400680 /* IO CRB Entry D_C */
-#define IIO_ICRBD_D 0x00400688 /* IO CRB Entry D_D */
-#define IIO_ICRBD_E 0x00400690 /* IO CRB Entry D_E */
-
-#define IIO_ICRBE_A 0x004006a0 /* IO CRB Entry E_A */
-#define IIO_ICRBE_B 0x004006a8 /* IO CRB Entry E_B */
-#define IIO_ICRBE_C 0x004006b0 /* IO CRB Entry E_C */
-#define IIO_ICRBE_D 0x004006b8 /* IO CRB Entry E_D */
-#define IIO_ICRBE_E 0x004006c0 /* IO CRB Entry E_E */
-
-#define IIO_ICSML 0x00400700 /* IO CRB Spurious Message Low */
-#define IIO_ICSMM 0x00400708 /* IO CRB Spurious Message Middle */
-#define IIO_ICSMH 0x00400710 /* IO CRB Spurious Message High */
-
-#define IIO_IDBSS 0x00400718 /* IO Debug Submenu Select */
-
-#define IIO_IBLS0 0x00410000 /* IO BTE Length Status 0 */
-#define IIO_IBSA0 0x00410008 /* IO BTE Source Address 0 */
-#define IIO_IBDA0 0x00410010 /* IO BTE Destination Address 0 */
-#define IIO_IBCT0 0x00410018 /* IO BTE Control Terminate 0 */
-#define IIO_IBNA0 0x00410020 /* IO BTE Notification Address 0 */
-#define IIO_IBIA0 0x00410028 /* IO BTE Interrupt Address 0 */
-#define IIO_IBLS1 0x00420000 /* IO BTE Length Status 1 */
-#define IIO_IBSA1 0x00420008 /* IO BTE Source Address 1 */
-#define IIO_IBDA1 0x00420010 /* IO BTE Destination Address 1 */
-#define IIO_IBCT1 0x00420018 /* IO BTE Control Terminate 1 */
-#define IIO_IBNA1 0x00420020 /* IO BTE Notification Address 1 */
-#define IIO_IBIA1 0x00420028 /* IO BTE Interrupt Address 1 */
-
-#define IIO_IPCR 0x00430000 /* IO Performance Control */
-#define IIO_IPPR 0x00430008 /* IO Performance Profiling */
-
-/************************************************************************
- * *
- * Description: This register echoes some information from the *
- * LB_REV_ID register. It is available through Crosstalk as described *
- * above. The REV_NUM and MFG_NUM fields receive their values from *
- * the REVISION and MANUFACTURER fields in the LB_REV_ID register. *
- * The PART_NUM field's value is the Crosstalk device ID number that *
- * Steve Miller assigned to the SHub chip. *
- * *
- ************************************************************************/
-
-typedef union ii_wid_u {
- u64 ii_wid_regval;
- struct {
- u64 w_rsvd_1:1;
- u64 w_mfg_num:11;
- u64 w_part_num:16;
- u64 w_rev_num:4;
- u64 w_rsvd:32;
- } ii_wid_fld_s;
-} ii_wid_u_t;
-
-/************************************************************************
- * *
- * The fields in this register are set upon detection of an error *
- * and cleared by various mechanisms, as explained in the *
- * description. *
- * *
- ************************************************************************/
-
-typedef union ii_wstat_u {
- u64 ii_wstat_regval;
- struct {
- u64 w_pending:4;
- u64 w_xt_crd_to:1;
- u64 w_xt_tail_to:1;
- u64 w_rsvd_3:3;
- u64 w_tx_mx_rty:1;
- u64 w_rsvd_2:6;
- u64 w_llp_tx_cnt:8;
- u64 w_rsvd_1:8;
- u64 w_crazy:1;
- u64 w_rsvd:31;
- } ii_wstat_fld_s;
-} ii_wstat_u_t;
-
-/************************************************************************
- * *
- * Description: This is a read-write enabled register. It controls *
- * various aspects of the Crosstalk flow control. *
- * *
- ************************************************************************/
-
-typedef union ii_wcr_u {
- u64 ii_wcr_regval;
- struct {
- u64 w_wid:4;
- u64 w_tag:1;
- u64 w_rsvd_1:8;
- u64 w_dst_crd:3;
- u64 w_f_bad_pkt:1;
- u64 w_dir_con:1;
- u64 w_e_thresh:5;
- u64 w_rsvd:41;
- } ii_wcr_fld_s;
-} ii_wcr_u_t;
-
-/************************************************************************
- * *
- * Description: This register's value is a bit vector that guards *
- * access to local registers within the II as well as to external *
- * Crosstalk widgets. Each bit in the register corresponds to a *
- * particular region in the system; a region consists of one, two or *
- * four nodes (depending on the value of the REGION_SIZE field in the *
- * LB_REV_ID register, which is documented in Section 8.3.1.1). The *
- * protection provided by this register applies to PIO read *
- * operations as well as PIO write operations. The II will perform a *
- * PIO read or write request only if the bit for the requestor's *
- * region is set; otherwise, the II will not perform the requested *
- * operation and will return an error response. When a PIO read or *
- * write request targets an external Crosstalk widget, then not only *
- * must the bit for the requestor's region be set in the ILAPR, but *
- * also the target widget's bit in the IOWA register must be set in *
- * order for the II to perform the requested operation; otherwise, *
- * the II will return an error response. Hence, the protection *
- * provided by the IOWA register supplements the protection provided *
- * by the ILAPR for requests that target external Crosstalk widgets. *
- * This register itself can be accessed only by the nodes whose *
- * region ID bits are enabled in this same register. It can also be *
- * accessed through the IAlias space by the local processors. *
- * The reset value of this register allows access by all nodes. *
- * *
- ************************************************************************/
-
-typedef union ii_ilapr_u {
- u64 ii_ilapr_regval;
- struct {
- u64 i_region:64;
- } ii_ilapr_fld_s;
-} ii_ilapr_u_t;
-
-/************************************************************************
- * *
- * Description: A write to this register of the 64-bit value *
- * "SGIrules" in ASCII, will cause the bit in the ILAPR register *
- * corresponding to the region of the requestor to be set (allow *
- * access). A write of any other value will be ignored. Access *
- * protection for this register is "SGIrules". *
- * This register can also be accessed through the IAlias space. *
- * However, this access will not change the access permissions in the *
- * ILAPR. *
- * *
- ************************************************************************/
-
-typedef union ii_ilapo_u {
- u64 ii_ilapo_regval;
- struct {
- u64 i_io_ovrride:64;
- } ii_ilapo_fld_s;
-} ii_ilapo_u_t;
-
-/************************************************************************
- * *
- * This register qualifies all the PIO and Graphics writes launched *
- * from the SHUB towards a widget. *
- * *
- ************************************************************************/
-
-typedef union ii_iowa_u {
- u64 ii_iowa_regval;
- struct {
- u64 i_w0_oac:1;
- u64 i_rsvd_1:7;
- u64 i_wx_oac:8;
- u64 i_rsvd:48;
- } ii_iowa_fld_s;
-} ii_iowa_u_t;
-
-/************************************************************************
- * *
- * Description: This register qualifies all the requests launched *
- * from a widget towards the Shub. This register is intended to be *
- * used by software in case of misbehaving widgets. *
- * *
- * *
- ************************************************************************/
-
-typedef union ii_iiwa_u {
- u64 ii_iiwa_regval;
- struct {
- u64 i_w0_iac:1;
- u64 i_rsvd_1:7;
- u64 i_wx_iac:8;
- u64 i_rsvd:48;
- } ii_iiwa_fld_s;
-} ii_iiwa_u_t;
-
-/************************************************************************
- * *
- * Description: This register qualifies all the operations launched *
- * from a widget towards the SHub. It allows individual access *
- * control for up to 8 devices per widget. A device refers to *
- * individual DMA master hosted by a widget. *
- * The bits in each field of this register are cleared by the Shub *
- * upon detection of an error which requires the device to be *
- * disabled. These fields assume that 0=TNUM=7 (i.e., Bridge-centric *
- * Crosstalk). Whether or not a device has access rights to this *
- * Shub is determined by an AND of the device enable bit in the *
- * appropriate field of this register and the corresponding bit in *
- * the Wx_IAC field (for the widget which this device belongs to). *
- * The bits in this field are set by writing a 1 to them. Incoming *
- * replies from Crosstalk are not subject to this access control *
- * mechanism. *
- * *
- ************************************************************************/
-
-typedef union ii_iidem_u {
- u64 ii_iidem_regval;
- struct {
- u64 i_w8_dxs:8;
- u64 i_w9_dxs:8;
- u64 i_wa_dxs:8;
- u64 i_wb_dxs:8;
- u64 i_wc_dxs:8;
- u64 i_wd_dxs:8;
- u64 i_we_dxs:8;
- u64 i_wf_dxs:8;
- } ii_iidem_fld_s;
-} ii_iidem_u_t;
-
-/************************************************************************
- * *
- * This register contains the various programmable fields necessary *
- * for controlling and observing the LLP signals. *
- * *
- ************************************************************************/
-
-typedef union ii_ilcsr_u {
- u64 ii_ilcsr_regval;
- struct {
- u64 i_nullto:6;
- u64 i_rsvd_4:2;
- u64 i_wrmrst:1;
- u64 i_rsvd_3:1;
- u64 i_llp_en:1;
- u64 i_bm8:1;
- u64 i_llp_stat:2;
- u64 i_remote_power:1;
- u64 i_rsvd_2:1;
- u64 i_maxrtry:10;
- u64 i_d_avail_sel:2;
- u64 i_rsvd_1:4;
- u64 i_maxbrst:10;
- u64 i_rsvd:22;
-
- } ii_ilcsr_fld_s;
-} ii_ilcsr_u_t;
-
-/************************************************************************
- * *
- * This is simply a status registers that monitors the LLP error *
- * rate. *
- * *
- ************************************************************************/
-
-typedef union ii_illr_u {
- u64 ii_illr_regval;
- struct {
- u64 i_sn_cnt:16;
- u64 i_cb_cnt:16;
- u64 i_rsvd:32;
- } ii_illr_fld_s;
-} ii_illr_u_t;
-
-/************************************************************************
- * *
- * Description: All II-detected non-BTE error interrupts are *
- * specified via this register. *
- * NOTE: The PI interrupt register address is hardcoded in the II. If *
- * PI_ID==0, then the II sends an interrupt request (Duplonet PWRI *
- * packet) to address offset 0x0180_0090 within the local register *
- * address space of PI0 on the node specified by the NODE field. If *
- * PI_ID==1, then the II sends the interrupt request to address *
- * offset 0x01A0_0090 within the local register address space of PI1 *
- * on the node specified by the NODE field. *
- * *
- ************************************************************************/
-
-typedef union ii_iidsr_u {
- u64 ii_iidsr_regval;
- struct {
- u64 i_level:8;
- u64 i_pi_id:1;
- u64 i_node:11;
- u64 i_rsvd_3:4;
- u64 i_enable:1;
- u64 i_rsvd_2:3;
- u64 i_int_sent:2;
- u64 i_rsvd_1:2;
- u64 i_pi0_forward_int:1;
- u64 i_pi1_forward_int:1;
- u64 i_rsvd:30;
- } ii_iidsr_fld_s;
-} ii_iidsr_u_t;
-
-/************************************************************************
- * *
- * There are two instances of this register. This register is used *
- * for matching up the incoming responses from the graphics widget to *
- * the processor that initiated the graphics operation. The *
- * write-responses are converted to graphics credits and returned to *
- * the processor so that the processor interface can manage the flow *
- * control. *
- * *
- ************************************************************************/
-
-typedef union ii_igfx0_u {
- u64 ii_igfx0_regval;
- struct {
- u64 i_w_num:4;
- u64 i_pi_id:1;
- u64 i_n_num:12;
- u64 i_p_num:1;
- u64 i_rsvd:46;
- } ii_igfx0_fld_s;
-} ii_igfx0_u_t;
-
-/************************************************************************
- * *
- * There are two instances of this register. This register is used *
- * for matching up the incoming responses from the graphics widget to *
- * the processor that initiated the graphics operation. The *
- * write-responses are converted to graphics credits and returned to *
- * the processor so that the processor interface can manage the flow *
- * control. *
- * *
- ************************************************************************/
-
-typedef union ii_igfx1_u {
- u64 ii_igfx1_regval;
- struct {
- u64 i_w_num:4;
- u64 i_pi_id:1;
- u64 i_n_num:12;
- u64 i_p_num:1;
- u64 i_rsvd:46;
- } ii_igfx1_fld_s;
-} ii_igfx1_u_t;
-
-/************************************************************************
- * *
- * There are two instances of this registers. These registers are *
- * used as scratch registers for software use. *
- * *
- ************************************************************************/
-
-typedef union ii_iscr0_u {
- u64 ii_iscr0_regval;
- struct {
- u64 i_scratch:64;
- } ii_iscr0_fld_s;
-} ii_iscr0_u_t;
-
-/************************************************************************
- * *
- * There are two instances of this registers. These registers are *
- * used as scratch registers for software use. *
- * *
- ************************************************************************/
-
-typedef union ii_iscr1_u {
- u64 ii_iscr1_regval;
- struct {
- u64 i_scratch:64;
- } ii_iscr1_fld_s;
-} ii_iscr1_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a Shub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the SHub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the Shub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte1_u {
- u64 ii_itte1_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte1_fld_s;
-} ii_itte1_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a Shub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the Shub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the Shub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte2_u {
- u64 ii_itte2_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte2_fld_s;
-} ii_itte2_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a Shub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the Shub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the SHub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte3_u {
- u64 ii_itte3_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte3_fld_s;
-} ii_itte3_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a SHub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the SHub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the SHub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte4_u {
- u64 ii_itte4_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte4_fld_s;
-} ii_itte4_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a SHub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the Shub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the Shub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte5_u {
- u64 ii_itte5_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte5_fld_s;
-} ii_itte5_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a Shub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the Shub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the Shub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte6_u {
- u64 ii_itte6_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte6_fld_s;
-} ii_itte6_u_t;
-
-/************************************************************************
- * *
- * Description: There are seven instances of translation table entry *
- * registers. Each register maps a Shub Big Window to a 48-bit *
- * address on Crosstalk. *
- * For M-mode (128 nodes, 8 GBytes/node), SysAD[31:29] (Big Window *
- * number) are used to select one of these 7 registers. The Widget *
- * number field is then derived from the W_NUM field for synthesizing *
- * a Crosstalk packet. The 5 bits of OFFSET are concatenated with *
- * SysAD[28:0] to form Crosstalk[33:0]. The upper Crosstalk[47:34] *
- * are padded with zeros. Although the maximum Crosstalk space *
- * addressable by the Shub is thus the lower 16 GBytes per widget *
- * (M-mode), however only <SUP >7</SUP>/<SUB >32nds</SUB> of this *
- * space can be accessed. *
- * For the N-mode (256 nodes, 4 GBytes/node), SysAD[30:28] (Big *
- * Window number) are used to select one of these 7 registers. The *
- * Widget number field is then derived from the W_NUM field for *
- * synthesizing a Crosstalk packet. The 5 bits of OFFSET are *
- * concatenated with SysAD[27:0] to form Crosstalk[33:0]. The IOSP *
- * field is used as Crosstalk[47], and remainder of the Crosstalk *
- * address bits (Crosstalk[46:34]) are always zero. While the maximum *
- * Crosstalk space addressable by the SHub is thus the lower *
- * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *
- * of this space can be accessed. *
- * *
- ************************************************************************/
-
-typedef union ii_itte7_u {
- u64 ii_itte7_regval;
- struct {
- u64 i_offset:5;
- u64 i_rsvd_1:3;
- u64 i_w_num:4;
- u64 i_iosp:1;
- u64 i_rsvd:51;
- } ii_itte7_fld_s;
-} ii_itte7_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprb0_u {
- u64 ii_iprb0_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprb0_fld_s;
-} ii_iprb0_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprb8_u {
- u64 ii_iprb8_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprb8_fld_s;
-} ii_iprb8_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprb9_u {
- u64 ii_iprb9_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprb9_fld_s;
-} ii_iprb9_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * *
- * *
- ************************************************************************/
-
-typedef union ii_iprba_u {
- u64 ii_iprba_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprba_fld_s;
-} ii_iprba_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprbb_u {
- u64 ii_iprbb_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprbb_fld_s;
-} ii_iprbb_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprbc_u {
- u64 ii_iprbc_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprbc_fld_s;
-} ii_iprbc_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprbd_u {
- u64 ii_iprbd_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprbd_fld_s;
-} ii_iprbd_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of SHub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprbe_u {
- u64 ii_iprbe_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprbe_fld_s;
-} ii_iprbe_u_t;
-
-/************************************************************************
- * *
- * Description: There are 9 instances of this register, one per *
- * actual widget in this implementation of Shub and Crossbow. *
- * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *
- * refers to Crossbow's internal space. *
- * This register contains the state elements per widget that are *
- * necessary to manage the PIO flow control on Crosstalk and on the *
- * Router Network. See the PIO Flow Control chapter for a complete *
- * description of this register *
- * The SPUR_WR bit requires some explanation. When this register is *
- * written, the new value of the C field is captured in an internal *
- * register so the hardware can remember what the programmer wrote *
- * into the credit counter. The SPUR_WR bit sets whenever the C field *
- * increments above this stored value, which indicates that there *
- * have been more responses received than requests sent. The SPUR_WR *
- * bit cannot be cleared until a value is written to the IPRBx *
- * register; the write will correct the C field and capture its new *
- * value in the internal register. Even if IECLR[E_PRB_x] is set, the *
- * SPUR_WR bit will persist if IPRBx hasn't yet been written. *
- * . *
- * *
- ************************************************************************/
-
-typedef union ii_iprbf_u {
- u64 ii_iprbf_regval;
- struct {
- u64 i_c:8;
- u64 i_na:14;
- u64 i_rsvd_2:2;
- u64 i_nb:14;
- u64 i_rsvd_1:2;
- u64 i_m:2;
- u64 i_f:1;
- u64 i_of_cnt:5;
- u64 i_error:1;
- u64 i_rd_to:1;
- u64 i_spur_wr:1;
- u64 i_spur_rd:1;
- u64 i_rsvd:11;
- u64 i_mult_err:1;
- } ii_iprbe_fld_s;
-} ii_iprbf_u_t;
-
-/************************************************************************
- * *
- * This register specifies the timeout value to use for monitoring *
- * Crosstalk credits which are used outbound to Crosstalk. An *
- * internal counter called the Crosstalk Credit Timeout Counter *
- * increments every 128 II clocks. The counter starts counting *
- * anytime the credit count drops below a threshold, and resets to *
- * zero (stops counting) anytime the credit count is at or above the *
- * threshold. The threshold is 1 credit in direct connect mode and 2 *
- * in Crossbow connect mode. When the internal Crosstalk Credit *
- * Timeout Counter reaches the value programmed in this register, a *
- * Crosstalk Credit Timeout has occurred. The internal counter is not *
- * readable from software, and stops counting at its maximum value, *
- * so it cannot cause more than one interrupt. *
- * *
- ************************************************************************/
-
-typedef union ii_ixcc_u {
- u64 ii_ixcc_regval;
- struct {
- u64 i_time_out:26;
- u64 i_rsvd:38;
- } ii_ixcc_fld_s;
-} ii_ixcc_u_t;
-
-/************************************************************************
- * *
- * Description: This register qualifies all the PIO and DMA *
- * operations launched from widget 0 towards the SHub. In *
- * addition, it also qualifies accesses by the BTE streams. *
- * The bits in each field of this register are cleared by the SHub *
- * upon detection of an error which requires widget 0 or the BTE *
- * streams to be terminated. Whether or not widget x has access *
- * rights to this SHub is determined by an AND of the device *
- * enable bit in the appropriate field of this register and bit 0 in *
- * the Wx_IAC field. The bits in this field are set by writing a 1 to *
- * them. Incoming replies from Crosstalk are not subject to this *
- * access control mechanism. *
- * *
- ************************************************************************/
-
-typedef union ii_imem_u {
- u64 ii_imem_regval;
- struct {
- u64 i_w0_esd:1;
- u64 i_rsvd_3:3;
- u64 i_b0_esd:1;
- u64 i_rsvd_2:3;
- u64 i_b1_esd:1;
- u64 i_rsvd_1:3;
- u64 i_clr_precise:1;
- u64 i_rsvd:51;
- } ii_imem_fld_s;
-} ii_imem_u_t;
-
-/************************************************************************
- * *
- * Description: This register specifies the timeout value to use for *
- * monitoring Crosstalk tail flits coming into the Shub in the *
- * TAIL_TO field. An internal counter associated with this register *
- * is incremented every 128 II internal clocks (7 bits). The counter *
- * starts counting anytime a header micropacket is received and stops *
- * counting (and resets to zero) any time a micropacket with a Tail *
- * bit is received. Once the counter reaches the threshold value *
- * programmed in this register, it generates an interrupt to the *
- * processor that is programmed into the IIDSR. The counter saturates *
- * (does not roll over) at its maximum value, so it cannot cause *
- * another interrupt until after it is cleared. *
- * The register also contains the Read Response Timeout values. The *
- * Prescalar is 23 bits, and counts II clocks. An internal counter *
- * increments on every II clock and when it reaches the value in the *
- * Prescalar field, all IPRTE registers with their valid bits set *
- * have their Read Response timers bumped. Whenever any of them match *
- * the value in the RRSP_TO field, a Read Response Timeout has *
- * occurred, and error handling occurs as described in the Error *
- * Handling section of this document. *
- * *
- ************************************************************************/
-
-typedef union ii_ixtt_u {
- u64 ii_ixtt_regval;
- struct {
- u64 i_tail_to:26;
- u64 i_rsvd_1:6;
- u64 i_rrsp_ps:23;
- u64 i_rrsp_to:5;
- u64 i_rsvd:4;
- } ii_ixtt_fld_s;
-} ii_ixtt_u_t;
-
-/************************************************************************
- * *
- * Writing a 1 to the fields of this register clears the appropriate *
- * error bits in other areas of SHub. Note that when the *
- * E_PRB_x bits are used to clear error bits in PRB registers, *
- * SPUR_RD and SPUR_WR may persist, because they require additional *
- * action to clear them. See the IPRBx and IXSS Register *
- * specifications. *
- * *
- ************************************************************************/
-
-typedef union ii_ieclr_u {
- u64 ii_ieclr_regval;
- struct {
- u64 i_e_prb_0:1;
- u64 i_rsvd:7;
- u64 i_e_prb_8:1;
- u64 i_e_prb_9:1;
- u64 i_e_prb_a:1;
- u64 i_e_prb_b:1;
- u64 i_e_prb_c:1;
- u64 i_e_prb_d:1;
- u64 i_e_prb_e:1;
- u64 i_e_prb_f:1;
- u64 i_e_crazy:1;
- u64 i_e_bte_0:1;
- u64 i_e_bte_1:1;
- u64 i_reserved_1:10;
- u64 i_spur_rd_hdr:1;
- u64 i_cam_intr_to:1;
- u64 i_cam_overflow:1;
- u64 i_cam_read_miss:1;
- u64 i_ioq_rep_underflow:1;
- u64 i_ioq_req_underflow:1;
- u64 i_ioq_rep_overflow:1;
- u64 i_ioq_req_overflow:1;
- u64 i_iiq_rep_overflow:1;
- u64 i_iiq_req_overflow:1;
- u64 i_ii_xn_rep_cred_overflow:1;
- u64 i_ii_xn_req_cred_overflow:1;
- u64 i_ii_xn_invalid_cmd:1;
- u64 i_xn_ii_invalid_cmd:1;
- u64 i_reserved_2:21;
- } ii_ieclr_fld_s;
-} ii_ieclr_u_t;
-
-/************************************************************************
- * *
- * This register controls both BTEs. SOFT_RESET is intended for *
- * recovery after an error. COUNT controls the total number of CRBs *
- * that both BTEs (combined) can use, which affects total BTE *
- * bandwidth. *
- * *
- ************************************************************************/
-
-typedef union ii_ibcr_u {
- u64 ii_ibcr_regval;
- struct {
- u64 i_count:4;
- u64 i_rsvd_1:4;
- u64 i_soft_reset:1;
- u64 i_rsvd:55;
- } ii_ibcr_fld_s;
-} ii_ibcr_u_t;
-
-/************************************************************************
- * *
- * This register contains the header of a spurious read response *
- * received from Crosstalk. A spurious read response is defined as a *
- * read response received by II from a widget for which (1) the SIDN *
- * has a value between 1 and 7, inclusive (II never sends requests to *
- * these widgets (2) there is no valid IPRTE register which *
- * corresponds to the TNUM, or (3) the widget indicated in SIDN is *
- * not the same as the widget recorded in the IPRTE register *
- * referenced by the TNUM. If this condition is true, and if the *
- * IXSS[VALID] bit is clear, then the header of the spurious read *
- * response is capture in IXSM and IXSS, and IXSS[VALID] is set. The *
- * errant header is thereby captured, and no further spurious read *
- * respones are captured until IXSS[VALID] is cleared by setting the *
- * appropriate bit in IECLR. Every time a spurious read response is *
- * detected, the SPUR_RD bit of the PRB corresponding to the incoming *
- * message's SIDN field is set. This always happens, regardless of *
- * whether a header is captured. The programmer should check *
- * IXSM[SIDN] to determine which widget sent the spurious response, *
- * because there may be more than one SPUR_RD bit set in the PRB *
- * registers. The widget indicated by IXSM[SIDN] was the first *
- * spurious read response to be received since the last time *
- * IXSS[VALID] was clear. The SPUR_RD bit of the corresponding PRB *
- * will be set. Any SPUR_RD bits in any other PRB registers indicate *
- * spurious messages from other widets which were detected after the *
- * header was captured.. *
- * *
- ************************************************************************/
-
-typedef union ii_ixsm_u {
- u64 ii_ixsm_regval;
- struct {
- u64 i_byte_en:32;
- u64 i_reserved:1;
- u64 i_tag:3;
- u64 i_alt_pactyp:4;
- u64 i_bo:1;
- u64 i_error:1;
- u64 i_vbpm:1;
- u64 i_gbr:1;
- u64 i_ds:2;
- u64 i_ct:1;
- u64 i_tnum:5;
- u64 i_pactyp:4;
- u64 i_sidn:4;
- u64 i_didn:4;
- } ii_ixsm_fld_s;
-} ii_ixsm_u_t;
-
-/************************************************************************
- * *
- * This register contains the sideband bits of a spurious read *
- * response received from Crosstalk. *
- * *
- ************************************************************************/
-
-typedef union ii_ixss_u {
- u64 ii_ixss_regval;
- struct {
- u64 i_sideband:8;
- u64 i_rsvd:55;
- u64 i_valid:1;
- } ii_ixss_fld_s;
-} ii_ixss_u_t;
-
-/************************************************************************
- * *
- * This register enables software to access the II LLP's test port. *
- * Refer to the LLP 2.5 documentation for an explanation of the test *
- * port. Software can write to this register to program the values *
- * for the control fields (TestErrCapture, TestClear, TestFlit, *
- * TestMask and TestSeed). Similarly, software can read from this *
- * register to obtain the values of the test port's status outputs *
- * (TestCBerr, TestValid and TestData). *
- * *
- ************************************************************************/
-
-typedef union ii_ilct_u {
- u64 ii_ilct_regval;
- struct {
- u64 i_test_seed:20;
- u64 i_test_mask:8;
- u64 i_test_data:20;
- u64 i_test_valid:1;
- u64 i_test_cberr:1;
- u64 i_test_flit:3;
- u64 i_test_clear:1;
- u64 i_test_err_capture:1;
- u64 i_rsvd:9;
- } ii_ilct_fld_s;
-} ii_ilct_u_t;
-
-/************************************************************************
- * *
- * If the II detects an illegal incoming Duplonet packet (request or *
- * reply) when VALID==0 in the IIEPH1 register, then it saves the *
- * contents of the packet's header flit in the IIEPH1 and IIEPH2 *
- * registers, sets the VALID bit in IIEPH1, clears the OVERRUN bit, *
- * and assigns a value to the ERR_TYPE field which indicates the *
- * specific nature of the error. The II recognizes four different *
- * types of errors: short request packets (ERR_TYPE==2), short reply *
- * packets (ERR_TYPE==3), long request packets (ERR_TYPE==4) and long *
- * reply packets (ERR_TYPE==5). The encodings for these types of *
- * errors were chosen to be consistent with the same types of errors *
- * indicated by the ERR_TYPE field in the LB_ERROR_HDR1 register (in *
- * the LB unit). If the II detects an illegal incoming Duplonet *
- * packet when VALID==1 in the IIEPH1 register, then it merely sets *
- * the OVERRUN bit to indicate that a subsequent error has happened, *
- * and does nothing further. *
- * *
- ************************************************************************/
-
-typedef union ii_iieph1_u {
- u64 ii_iieph1_regval;
- struct {
- u64 i_command:7;
- u64 i_rsvd_5:1;
- u64 i_suppl:14;
- u64 i_rsvd_4:1;
- u64 i_source:14;
- u64 i_rsvd_3:1;
- u64 i_err_type:4;
- u64 i_rsvd_2:4;
- u64 i_overrun:1;
- u64 i_rsvd_1:3;
- u64 i_valid:1;
- u64 i_rsvd:13;
- } ii_iieph1_fld_s;
-} ii_iieph1_u_t;
-
-/************************************************************************
- * *
- * This register holds the Address field from the header flit of an *
- * incoming erroneous Duplonet packet, along with the tail bit which *
- * accompanied this header flit. This register is essentially an *
- * extension of IIEPH1. Two registers were necessary because the 64 *
- * bits available in only a single register were insufficient to *
- * capture the entire header flit of an erroneous packet. *
- * *
- ************************************************************************/
-
-typedef union ii_iieph2_u {
- u64 ii_iieph2_regval;
- struct {
- u64 i_rsvd_0:3;
- u64 i_address:47;
- u64 i_rsvd_1:10;
- u64 i_tail:1;
- u64 i_rsvd:3;
- } ii_iieph2_fld_s;
-} ii_iieph2_u_t;
-
-/******************************/
-
-/************************************************************************
- * *
- * This register's value is a bit vector that guards access from SXBs *
- * to local registers within the II as well as to external Crosstalk *
- * widgets *
- * *
- ************************************************************************/
-
-typedef union ii_islapr_u {
- u64 ii_islapr_regval;
- struct {
- u64 i_region:64;
- } ii_islapr_fld_s;
-} ii_islapr_u_t;
-
-/************************************************************************
- * *
- * A write to this register of the 56-bit value "Pup+Bun" will cause *
- * the bit in the ISLAPR register corresponding to the region of the *
- * requestor to be set (access allowed). (
- * *
- ************************************************************************/
-
-typedef union ii_islapo_u {
- u64 ii_islapo_regval;
- struct {
- u64 i_io_sbx_ovrride:56;
- u64 i_rsvd:8;
- } ii_islapo_fld_s;
-} ii_islapo_u_t;
-
-/************************************************************************
- * *
- * Determines how long the wrapper will wait aftr an interrupt is *
- * initially issued from the II before it times out the outstanding *
- * interrupt and drops it from the interrupt queue. *
- * *
- ************************************************************************/
-
-typedef union ii_iwi_u {
- u64 ii_iwi_regval;
- struct {
- u64 i_prescale:24;
- u64 i_rsvd:8;
- u64 i_timeout:8;
- u64 i_rsvd1:8;
- u64 i_intrpt_retry_period:8;
- u64 i_rsvd2:8;
- } ii_iwi_fld_s;
-} ii_iwi_u_t;
-
-/************************************************************************
- * *
- * Log errors which have occurred in the II wrapper. The errors are *
- * cleared by writing to the IECLR register. *
- * *
- ************************************************************************/
-
-typedef union ii_iwel_u {
- u64 ii_iwel_regval;
- struct {
- u64 i_intr_timed_out:1;
- u64 i_rsvd:7;
- u64 i_cam_overflow:1;
- u64 i_cam_read_miss:1;
- u64 i_rsvd1:2;
- u64 i_ioq_rep_underflow:1;
- u64 i_ioq_req_underflow:1;
- u64 i_ioq_rep_overflow:1;
- u64 i_ioq_req_overflow:1;
- u64 i_iiq_rep_overflow:1;
- u64 i_iiq_req_overflow:1;
- u64 i_rsvd2:6;
- u64 i_ii_xn_rep_cred_over_under:1;
- u64 i_ii_xn_req_cred_over_under:1;
- u64 i_rsvd3:6;
- u64 i_ii_xn_invalid_cmd:1;
- u64 i_xn_ii_invalid_cmd:1;
- u64 i_rsvd4:30;
- } ii_iwel_fld_s;
-} ii_iwel_u_t;
-
-/************************************************************************
- * *
- * Controls the II wrapper. *
- * *
- ************************************************************************/
-
-typedef union ii_iwc_u {
- u64 ii_iwc_regval;
- struct {
- u64 i_dma_byte_swap:1;
- u64 i_rsvd:3;
- u64 i_cam_read_lines_reset:1;
- u64 i_rsvd1:3;
- u64 i_ii_xn_cred_over_under_log:1;
- u64 i_rsvd2:19;
- u64 i_xn_rep_iq_depth:5;
- u64 i_rsvd3:3;
- u64 i_xn_req_iq_depth:5;
- u64 i_rsvd4:3;
- u64 i_iiq_depth:6;
- u64 i_rsvd5:12;
- u64 i_force_rep_cred:1;
- u64 i_force_req_cred:1;
- } ii_iwc_fld_s;
-} ii_iwc_u_t;
-
-/************************************************************************
- * *
- * Status in the II wrapper. *
- * *
- ************************************************************************/
-
-typedef union ii_iws_u {
- u64 ii_iws_regval;
- struct {
- u64 i_xn_rep_iq_credits:5;
- u64 i_rsvd:3;
- u64 i_xn_req_iq_credits:5;
- u64 i_rsvd1:51;
- } ii_iws_fld_s;
-} ii_iws_u_t;
-
-/************************************************************************
- * *
- * Masks errors in the IWEL register. *
- * *
- ************************************************************************/
-
-typedef union ii_iweim_u {
- u64 ii_iweim_regval;
- struct {
- u64 i_intr_timed_out:1;
- u64 i_rsvd:7;
- u64 i_cam_overflow:1;
- u64 i_cam_read_miss:1;
- u64 i_rsvd1:2;
- u64 i_ioq_rep_underflow:1;
- u64 i_ioq_req_underflow:1;
- u64 i_ioq_rep_overflow:1;
- u64 i_ioq_req_overflow:1;
- u64 i_iiq_rep_overflow:1;
- u64 i_iiq_req_overflow:1;
- u64 i_rsvd2:6;
- u64 i_ii_xn_rep_cred_overflow:1;
- u64 i_ii_xn_req_cred_overflow:1;
- u64 i_rsvd3:6;
- u64 i_ii_xn_invalid_cmd:1;
- u64 i_xn_ii_invalid_cmd:1;
- u64 i_rsvd4:30;
- } ii_iweim_fld_s;
-} ii_iweim_u_t;
-
-/************************************************************************
- * *
- * A write to this register causes a particular field in the *
- * corresponding widget's PRB entry to be adjusted up or down by 1. *
- * This counter should be used when recovering from error and reset *
- * conditions. Note that software would be capable of causing *
- * inadvertent overflow or underflow of these counters. *
- * *
- ************************************************************************/
-
-typedef union ii_ipca_u {
- u64 ii_ipca_regval;
- struct {
- u64 i_wid:4;
- u64 i_adjust:1;
- u64 i_rsvd_1:3;
- u64 i_field:2;
- u64 i_rsvd:54;
- } ii_ipca_fld_s;
-} ii_ipca_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte0a_u {
- u64 ii_iprte0a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte0a_fld_s;
-} ii_iprte0a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte1a_u {
- u64 ii_iprte1a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte1a_fld_s;
-} ii_iprte1a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte2a_u {
- u64 ii_iprte2a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte2a_fld_s;
-} ii_iprte2a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte3a_u {
- u64 ii_iprte3a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte3a_fld_s;
-} ii_iprte3a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte4a_u {
- u64 ii_iprte4a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte4a_fld_s;
-} ii_iprte4a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte5a_u {
- u64 ii_iprte5a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte5a_fld_s;
-} ii_iprte5a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte6a_u {
- u64 ii_iprte6a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprte6a_fld_s;
-} ii_iprte6a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte7a_u {
- u64 ii_iprte7a_regval;
- struct {
- u64 i_rsvd_1:54;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } ii_iprtea7_fld_s;
-} ii_iprte7a_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte0b_u {
- u64 ii_iprte0b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte0b_fld_s;
-} ii_iprte0b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte1b_u {
- u64 ii_iprte1b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte1b_fld_s;
-} ii_iprte1b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte2b_u {
- u64 ii_iprte2b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte2b_fld_s;
-} ii_iprte2b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte3b_u {
- u64 ii_iprte3b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte3b_fld_s;
-} ii_iprte3b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte4b_u {
- u64 ii_iprte4b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte4b_fld_s;
-} ii_iprte4b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte5b_u {
- u64 ii_iprte5b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte5b_fld_s;
-} ii_iprte5b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte6b_u {
- u64 ii_iprte6b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
-
- } ii_iprte6b_fld_s;
-} ii_iprte6b_u_t;
-
-/************************************************************************
- * *
- * There are 8 instances of this register. This register contains *
- * the information that the II has to remember once it has launched a *
- * PIO Read operation. The contents are used to form the correct *
- * Router Network packet and direct the Crosstalk reply to the *
- * appropriate processor. *
- * *
- ************************************************************************/
-
-typedef union ii_iprte7b_u {
- u64 ii_iprte7b_regval;
- struct {
- u64 i_rsvd_1:3;
- u64 i_address:47;
- u64 i_init:3;
- u64 i_source:11;
- } ii_iprte7b_fld_s;
-} ii_iprte7b_u_t;
-
-/************************************************************************
- * *
- * Description: SHub II contains a feature which did not exist in *
- * the Hub which automatically cleans up after a Read Response *
- * timeout, including deallocation of the IPRTE and recovery of IBuf *
- * space. The inclusion of this register in SHub is for backward *
- * compatibility *
- * A write to this register causes an entry from the table of *
- * outstanding PIO Read Requests to be freed and returned to the *
- * stack of free entries. This register is used in handling the *
- * timeout errors that result in a PIO Reply never returning from *
- * Crosstalk. *
- * Note that this register does not affect the contents of the IPRTE *
- * registers. The Valid bits in those registers have to be *
- * specifically turned off by software. *
- * *
- ************************************************************************/
-
-typedef union ii_ipdr_u {
- u64 ii_ipdr_regval;
- struct {
- u64 i_te:3;
- u64 i_rsvd_1:1;
- u64 i_pnd:1;
- u64 i_init_rpcnt:1;
- u64 i_rsvd:58;
- } ii_ipdr_fld_s;
-} ii_ipdr_u_t;
-
-/************************************************************************
- * *
- * A write to this register causes a CRB entry to be returned to the *
- * queue of free CRBs. The entry should have previously been cleared *
- * (mark bit) via backdoor access to the pertinent CRB entry. This *
- * register is used in the last step of handling the errors that are *
- * captured and marked in CRB entries. Briefly: 1) first error for *
- * DMA write from a particular device, and first error for a *
- * particular BTE stream, lead to a marked CRB entry, and processor *
- * interrupt, 2) software reads the error information captured in the *
- * CRB entry, and presumably takes some corrective action, 3) *
- * software clears the mark bit, and finally 4) software writes to *
- * the ICDR register to return the CRB entry to the list of free CRB *
- * entries. *
- * *
- ************************************************************************/
-
-typedef union ii_icdr_u {
- u64 ii_icdr_regval;
- struct {
- u64 i_crb_num:4;
- u64 i_pnd:1;
- u64 i_rsvd:59;
- } ii_icdr_fld_s;
-} ii_icdr_u_t;
-
-/************************************************************************
- * *
- * This register provides debug access to two FIFOs inside of II. *
- * Both IOQ_MAX* fields of this register contain the instantaneous *
- * depth (in units of the number of available entries) of the *
- * associated IOQ FIFO. A read of this register will return the *
- * number of free entries on each FIFO at the time of the read. So *
- * when a FIFO is idle, the associated field contains the maximum *
- * depth of the FIFO. This register is writable for debug reasons *
- * and is intended to be written with the maximum desired FIFO depth *
- * while the FIFO is idle. Software must assure that II is idle when *
- * this register is written. If there are any active entries in any *
- * of these FIFOs when this register is written, the results are *
- * undefined. *
- * *
- ************************************************************************/
-
-typedef union ii_ifdr_u {
- u64 ii_ifdr_regval;
- struct {
- u64 i_ioq_max_rq:7;
- u64 i_set_ioq_rq:1;
- u64 i_ioq_max_rp:7;
- u64 i_set_ioq_rp:1;
- u64 i_rsvd:48;
- } ii_ifdr_fld_s;
-} ii_ifdr_u_t;
-
-/************************************************************************
- * *
- * This register allows the II to become sluggish in removing *
- * messages from its inbound queue (IIQ). This will cause messages to *
- * back up in either virtual channel. Disabling the "molasses" mode *
- * subsequently allows the II to be tested under stress. In the *
- * sluggish ("Molasses") mode, the localized effects of congestion *
- * can be observed. *
- * *
- ************************************************************************/
-
-typedef union ii_iiap_u {
- u64 ii_iiap_regval;
- struct {
- u64 i_rq_mls:6;
- u64 i_rsvd_1:2;
- u64 i_rp_mls:6;
- u64 i_rsvd:50;
- } ii_iiap_fld_s;
-} ii_iiap_u_t;
-
-/************************************************************************
- * *
- * This register allows several parameters of CRB operation to be *
- * set. Note that writing to this register can have catastrophic side *
- * effects, if the CRB is not quiescent, i.e. if the CRB is *
- * processing protocol messages when the write occurs. *
- * *
- ************************************************************************/
-
-typedef union ii_icmr_u {
- u64 ii_icmr_regval;
- struct {
- u64 i_sp_msg:1;
- u64 i_rd_hdr:1;
- u64 i_rsvd_4:2;
- u64 i_c_cnt:4;
- u64 i_rsvd_3:4;
- u64 i_clr_rqpd:1;
- u64 i_clr_rppd:1;
- u64 i_rsvd_2:2;
- u64 i_fc_cnt:4;
- u64 i_crb_vld:15;
- u64 i_crb_mark:15;
- u64 i_rsvd_1:2;
- u64 i_precise:1;
- u64 i_rsvd:11;
- } ii_icmr_fld_s;
-} ii_icmr_u_t;
-
-/************************************************************************
- * *
- * This register allows control of the table portion of the CRB *
- * logic via software. Control operations from this register have *
- * priority over all incoming Crosstalk or BTE requests. *
- * *
- ************************************************************************/
-
-typedef union ii_iccr_u {
- u64 ii_iccr_regval;
- struct {
- u64 i_crb_num:4;
- u64 i_rsvd_1:4;
- u64 i_cmd:8;
- u64 i_pending:1;
- u64 i_rsvd:47;
- } ii_iccr_fld_s;
-} ii_iccr_u_t;
-
-/************************************************************************
- * *
- * This register allows the maximum timeout value to be programmed. *
- * *
- ************************************************************************/
-
-typedef union ii_icto_u {
- u64 ii_icto_regval;
- struct {
- u64 i_timeout:8;
- u64 i_rsvd:56;
- } ii_icto_fld_s;
-} ii_icto_u_t;
-
-/************************************************************************
- * *
- * This register allows the timeout prescalar to be programmed. An *
- * internal counter is associated with this register. When the *
- * internal counter reaches the value of the PRESCALE field, the *
- * timer registers in all valid CRBs are incremented (CRBx_D[TIMEOUT] *
- * field). The internal counter resets to zero, and then continues *
- * counting. *
- * *
- ************************************************************************/
-
-typedef union ii_ictp_u {
- u64 ii_ictp_regval;
- struct {
- u64 i_prescale:24;
- u64 i_rsvd:40;
- } ii_ictp_fld_s;
-} ii_ictp_u_t;
-
-/************************************************************************
- * *
- * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *
- * used for Crosstalk operations (both cacheline and partial *
- * operations) or BTE/IO. Because the CRB entries are very wide, five *
- * registers (_A to _E) are required to read and write each entry. *
- * The CRB Entry registers can be conceptualized as rows and columns *
- * (illustrated in the table above). Each row contains the 4 *
- * registers required for a single CRB Entry. The first doubleword *
- * (column) for each entry is labeled A, and the second doubleword *
- * (higher address) is labeled B, the third doubleword is labeled C, *
- * the fourth doubleword is labeled D and the fifth doubleword is *
- * labeled E. All CRB entries have their addresses on a quarter *
- * cacheline aligned boundary. *
- * Upon reset, only the following fields are initialized: valid *
- * (VLD), priority count, timeout, timeout valid, and context valid. *
- * All other bits should be cleared by software before use (after *
- * recovering any potential error state from before the reset). *
- * The following four tables summarize the format for the four *
- * registers that are used for each ICRB# Entry. *
- * *
- ************************************************************************/
-
-typedef union ii_icrb0_a_u {
- u64 ii_icrb0_a_regval;
- struct {
- u64 ia_iow:1;
- u64 ia_vld:1;
- u64 ia_addr:47;
- u64 ia_tnum:5;
- u64 ia_sidn:4;
- u64 ia_rsvd:6;
- } ii_icrb0_a_fld_s;
-} ii_icrb0_a_u_t;
-
-/************************************************************************
- * *
- * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *
- * used for Crosstalk operations (both cacheline and partial *
- * operations) or BTE/IO. Because the CRB entries are very wide, five *
- * registers (_A to _E) are required to read and write each entry. *
- * *
- ************************************************************************/
-
-typedef union ii_icrb0_b_u {
- u64 ii_icrb0_b_regval;
- struct {
- u64 ib_xt_err:1;
- u64 ib_mark:1;
- u64 ib_ln_uce:1;
- u64 ib_errcode:3;
- u64 ib_error:1;
- u64 ib_stall__bte_1:1;
- u64 ib_stall__bte_0:1;
- u64 ib_stall__intr:1;
- u64 ib_stall_ib:1;
- u64 ib_intvn:1;
- u64 ib_wb:1;
- u64 ib_hold:1;
- u64 ib_ack:1;
- u64 ib_resp:1;
- u64 ib_ack_cnt:11;
- u64 ib_rsvd:7;
- u64 ib_exc:5;
- u64 ib_init:3;
- u64 ib_imsg:8;
- u64 ib_imsgtype:2;
- u64 ib_use_old:1;
- u64 ib_rsvd_1:11;
- } ii_icrb0_b_fld_s;
-} ii_icrb0_b_u_t;
-
-/************************************************************************
- * *
- * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *
- * used for Crosstalk operations (both cacheline and partial *
- * operations) or BTE/IO. Because the CRB entries are very wide, five *
- * registers (_A to _E) are required to read and write each entry. *
- * *
- ************************************************************************/
-
-typedef union ii_icrb0_c_u {
- u64 ii_icrb0_c_regval;
- struct {
- u64 ic_source:15;
- u64 ic_size:2;
- u64 ic_ct:1;
- u64 ic_bte_num:1;
- u64 ic_gbr:1;
- u64 ic_resprqd:1;
- u64 ic_bo:1;
- u64 ic_suppl:15;
- u64 ic_rsvd:27;
- } ii_icrb0_c_fld_s;
-} ii_icrb0_c_u_t;
-
-/************************************************************************
- * *
- * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *
- * used for Crosstalk operations (both cacheline and partial *
- * operations) or BTE/IO. Because the CRB entries are very wide, five *
- * registers (_A to _E) are required to read and write each entry. *
- * *
- ************************************************************************/
-
-typedef union ii_icrb0_d_u {
- u64 ii_icrb0_d_regval;
- struct {
- u64 id_pa_be:43;
- u64 id_bte_op:1;
- u64 id_pr_psc:4;
- u64 id_pr_cnt:4;
- u64 id_sleep:1;
- u64 id_rsvd:11;
- } ii_icrb0_d_fld_s;
-} ii_icrb0_d_u_t;
-
-/************************************************************************
- * *
- * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *
- * used for Crosstalk operations (both cacheline and partial *
- * operations) or BTE/IO. Because the CRB entries are very wide, five *
- * registers (_A to _E) are required to read and write each entry. *
- * *
- ************************************************************************/
-
-typedef union ii_icrb0_e_u {
- u64 ii_icrb0_e_regval;
- struct {
- u64 ie_timeout:8;
- u64 ie_context:15;
- u64 ie_rsvd:1;
- u64 ie_tvld:1;
- u64 ie_cvld:1;
- u64 ie_rsvd_0:38;
- } ii_icrb0_e_fld_s;
-} ii_icrb0_e_u_t;
-
-/************************************************************************
- * *
- * This register contains the lower 64 bits of the header of the *
- * spurious message captured by II. Valid when the SP_MSG bit in ICMR *
- * register is set. *
- * *
- ************************************************************************/
-
-typedef union ii_icsml_u {
- u64 ii_icsml_regval;
- struct {
- u64 i_tt_addr:47;
- u64 i_newsuppl_ex:14;
- u64 i_reserved:2;
- u64 i_overflow:1;
- } ii_icsml_fld_s;
-} ii_icsml_u_t;
-
-/************************************************************************
- * *
- * This register contains the middle 64 bits of the header of the *
- * spurious message captured by II. Valid when the SP_MSG bit in ICMR *
- * register is set. *
- * *
- ************************************************************************/
-
-typedef union ii_icsmm_u {
- u64 ii_icsmm_regval;
- struct {
- u64 i_tt_ack_cnt:11;
- u64 i_reserved:53;
- } ii_icsmm_fld_s;
-} ii_icsmm_u_t;
-
-/************************************************************************
- * *
- * This register contains the microscopic state, all the inputs to *
- * the protocol table, captured with the spurious message. Valid when *
- * the SP_MSG bit in the ICMR register is set. *
- * *
- ************************************************************************/
-
-typedef union ii_icsmh_u {
- u64 ii_icsmh_regval;
- struct {
- u64 i_tt_vld:1;
- u64 i_xerr:1;
- u64 i_ft_cwact_o:1;
- u64 i_ft_wact_o:1;
- u64 i_ft_active_o:1;
- u64 i_sync:1;
- u64 i_mnusg:1;
- u64 i_mnusz:1;
- u64 i_plusz:1;
- u64 i_plusg:1;
- u64 i_tt_exc:5;
- u64 i_tt_wb:1;
- u64 i_tt_hold:1;
- u64 i_tt_ack:1;
- u64 i_tt_resp:1;
- u64 i_tt_intvn:1;
- u64 i_g_stall_bte1:1;
- u64 i_g_stall_bte0:1;
- u64 i_g_stall_il:1;
- u64 i_g_stall_ib:1;
- u64 i_tt_imsg:8;
- u64 i_tt_imsgtype:2;
- u64 i_tt_use_old:1;
- u64 i_tt_respreqd:1;
- u64 i_tt_bte_num:1;
- u64 i_cbn:1;
- u64 i_match:1;
- u64 i_rpcnt_lt_34:1;
- u64 i_rpcnt_ge_34:1;
- u64 i_rpcnt_lt_18:1;
- u64 i_rpcnt_ge_18:1;
- u64 i_rpcnt_lt_2:1;
- u64 i_rpcnt_ge_2:1;
- u64 i_rqcnt_lt_18:1;
- u64 i_rqcnt_ge_18:1;
- u64 i_rqcnt_lt_2:1;
- u64 i_rqcnt_ge_2:1;
- u64 i_tt_device:7;
- u64 i_tt_init:3;
- u64 i_reserved:5;
- } ii_icsmh_fld_s;
-} ii_icsmh_u_t;
-
-/************************************************************************
- * *
- * The Shub DEBUG unit provides a 3-bit selection signal to the *
- * II core and a 3-bit selection signal to the fsbclk domain in the II *
- * wrapper. *
- * *
- ************************************************************************/
-
-typedef union ii_idbss_u {
- u64 ii_idbss_regval;
- struct {
- u64 i_iioclk_core_submenu:3;
- u64 i_rsvd:5;
- u64 i_fsbclk_wrapper_submenu:3;
- u64 i_rsvd_1:5;
- u64 i_iioclk_menu:5;
- u64 i_rsvd_2:43;
- } ii_idbss_fld_s;
-} ii_idbss_u_t;
-
-/************************************************************************
- * *
- * Description: This register is used to set up the length for a *
- * transfer and then to monitor the progress of that transfer. This *
- * register needs to be initialized before a transfer is started. A *
- * legitimate write to this register will set the Busy bit, clear the *
- * Error bit, and initialize the length to the value desired. *
- * While the transfer is in progress, hardware will decrement the *
- * length field with each successful block that is copied. Once the *
- * transfer completes, hardware will clear the Busy bit. The length *
- * field will also contain the number of cache lines left to be *
- * transferred. *
- * *
- ************************************************************************/
-
-typedef union ii_ibls0_u {
- u64 ii_ibls0_regval;
- struct {
- u64 i_length:16;
- u64 i_error:1;
- u64 i_rsvd_1:3;
- u64 i_busy:1;
- u64 i_rsvd:43;
- } ii_ibls0_fld_s;
-} ii_ibls0_u_t;
-
-/************************************************************************
- * *
- * This register should be loaded before a transfer is started. The *
- * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *
- * address as described in Section 1.3, Figure2 and Figure3. Since *
- * the bottom 7 bits of the address are always taken to be zero, BTE *
- * transfers are always cacheline-aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibsa0_u {
- u64 ii_ibsa0_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:42;
- u64 i_rsvd:15;
- } ii_ibsa0_fld_s;
-} ii_ibsa0_u_t;
-
-/************************************************************************
- * *
- * This register should be loaded before a transfer is started. The *
- * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *
- * address as described in Section 1.3, Figure2 and Figure3. Since *
- * the bottom 7 bits of the address are always taken to be zero, BTE *
- * transfers are always cacheline-aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibda0_u {
- u64 ii_ibda0_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:42;
- u64 i_rsvd:15;
- } ii_ibda0_fld_s;
-} ii_ibda0_u_t;
-
-/************************************************************************
- * *
- * Writing to this register sets up the attributes of the transfer *
- * and initiates the transfer operation. Reading this register has *
- * the side effect of terminating any transfer in progress. Note: *
- * stopping a transfer midstream could have an adverse impact on the *
- * other BTE. If a BTE stream has to be stopped (due to error *
- * handling for example), both BTE streams should be stopped and *
- * their transfers discarded. *
- * *
- ************************************************************************/
-
-typedef union ii_ibct0_u {
- u64 ii_ibct0_regval;
- struct {
- u64 i_zerofill:1;
- u64 i_rsvd_2:3;
- u64 i_notify:1;
- u64 i_rsvd_1:3;
- u64 i_poison:1;
- u64 i_rsvd:55;
- } ii_ibct0_fld_s;
-} ii_ibct0_u_t;
-
-/************************************************************************
- * *
- * This register contains the address to which the WINV is sent. *
- * This address has to be cache line aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibna0_u {
- u64 ii_ibna0_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:42;
- u64 i_rsvd:15;
- } ii_ibna0_fld_s;
-} ii_ibna0_u_t;
-
-/************************************************************************
- * *
- * This register contains the programmable level as well as the node *
- * ID and PI unit of the processor to which the interrupt will be *
- * sent. *
- * *
- ************************************************************************/
-
-typedef union ii_ibia0_u {
- u64 ii_ibia0_regval;
- struct {
- u64 i_rsvd_2:1;
- u64 i_node_id:11;
- u64 i_rsvd_1:4;
- u64 i_level:7;
- u64 i_rsvd:41;
- } ii_ibia0_fld_s;
-} ii_ibia0_u_t;
-
-/************************************************************************
- * *
- * Description: This register is used to set up the length for a *
- * transfer and then to monitor the progress of that transfer. This *
- * register needs to be initialized before a transfer is started. A *
- * legitimate write to this register will set the Busy bit, clear the *
- * Error bit, and initialize the length to the value desired. *
- * While the transfer is in progress, hardware will decrement the *
- * length field with each successful block that is copied. Once the *
- * transfer completes, hardware will clear the Busy bit. The length *
- * field will also contain the number of cache lines left to be *
- * transferred. *
- * *
- ************************************************************************/
-
-typedef union ii_ibls1_u {
- u64 ii_ibls1_regval;
- struct {
- u64 i_length:16;
- u64 i_error:1;
- u64 i_rsvd_1:3;
- u64 i_busy:1;
- u64 i_rsvd:43;
- } ii_ibls1_fld_s;
-} ii_ibls1_u_t;
-
-/************************************************************************
- * *
- * This register should be loaded before a transfer is started. The *
- * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *
- * address as described in Section 1.3, Figure2 and Figure3. Since *
- * the bottom 7 bits of the address are always taken to be zero, BTE *
- * transfers are always cacheline-aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibsa1_u {
- u64 ii_ibsa1_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:33;
- u64 i_rsvd:24;
- } ii_ibsa1_fld_s;
-} ii_ibsa1_u_t;
-
-/************************************************************************
- * *
- * This register should be loaded before a transfer is started. The *
- * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *
- * address as described in Section 1.3, Figure2 and Figure3. Since *
- * the bottom 7 bits of the address are always taken to be zero, BTE *
- * transfers are always cacheline-aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibda1_u {
- u64 ii_ibda1_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:33;
- u64 i_rsvd:24;
- } ii_ibda1_fld_s;
-} ii_ibda1_u_t;
-
-/************************************************************************
- * *
- * Writing to this register sets up the attributes of the transfer *
- * and initiates the transfer operation. Reading this register has *
- * the side effect of terminating any transfer in progress. Note: *
- * stopping a transfer midstream could have an adverse impact on the *
- * other BTE. If a BTE stream has to be stopped (due to error *
- * handling for example), both BTE streams should be stopped and *
- * their transfers discarded. *
- * *
- ************************************************************************/
-
-typedef union ii_ibct1_u {
- u64 ii_ibct1_regval;
- struct {
- u64 i_zerofill:1;
- u64 i_rsvd_2:3;
- u64 i_notify:1;
- u64 i_rsvd_1:3;
- u64 i_poison:1;
- u64 i_rsvd:55;
- } ii_ibct1_fld_s;
-} ii_ibct1_u_t;
-
-/************************************************************************
- * *
- * This register contains the address to which the WINV is sent. *
- * This address has to be cache line aligned. *
- * *
- ************************************************************************/
-
-typedef union ii_ibna1_u {
- u64 ii_ibna1_regval;
- struct {
- u64 i_rsvd_1:7;
- u64 i_addr:33;
- u64 i_rsvd:24;
- } ii_ibna1_fld_s;
-} ii_ibna1_u_t;
-
-/************************************************************************
- * *
- * This register contains the programmable level as well as the node *
- * ID and PI unit of the processor to which the interrupt will be *
- * sent. *
- * *
- ************************************************************************/
-
-typedef union ii_ibia1_u {
- u64 ii_ibia1_regval;
- struct {
- u64 i_pi_id:1;
- u64 i_node_id:8;
- u64 i_rsvd_1:7;
- u64 i_level:7;
- u64 i_rsvd:41;
- } ii_ibia1_fld_s;
-} ii_ibia1_u_t;
-
-/************************************************************************
- * *
- * This register defines the resources that feed information into *
- * the two performance counters located in the IO Performance *
- * Profiling Register. There are 17 different quantities that can be *
- * measured. Given these 17 different options, the two performance *
- * counters have 15 of them in common; menu selections 0 through 0xE *
- * are identical for each performance counter. As for the other two *
- * options, one is available from one performance counter and the *
- * other is available from the other performance counter. Hence, the *
- * II supports all 17*16=272 possible combinations of quantities to *
- * measure. *
- * *
- ************************************************************************/
-
-typedef union ii_ipcr_u {
- u64 ii_ipcr_regval;
- struct {
- u64 i_ippr0_c:4;
- u64 i_ippr1_c:4;
- u64 i_icct:8;
- u64 i_rsvd:48;
- } ii_ipcr_fld_s;
-} ii_ipcr_u_t;
-
-/************************************************************************
- * *
- * *
- * *
- ************************************************************************/
-
-typedef union ii_ippr_u {
- u64 ii_ippr_regval;
- struct {
- u64 i_ippr0:32;
- u64 i_ippr1:32;
- } ii_ippr_fld_s;
-} ii_ippr_u_t;
-
-/************************************************************************
- * *
- * The following defines which were not formed into structures are *
- * probably identical to another register, and the name of the *
- * register is provided against each of these registers. This *
- * information needs to be checked carefully *
- * *
- * IIO_ICRB1_A IIO_ICRB0_A *
- * IIO_ICRB1_B IIO_ICRB0_B *
- * IIO_ICRB1_C IIO_ICRB0_C *
- * IIO_ICRB1_D IIO_ICRB0_D *
- * IIO_ICRB1_E IIO_ICRB0_E *
- * IIO_ICRB2_A IIO_ICRB0_A *
- * IIO_ICRB2_B IIO_ICRB0_B *
- * IIO_ICRB2_C IIO_ICRB0_C *
- * IIO_ICRB2_D IIO_ICRB0_D *
- * IIO_ICRB2_E IIO_ICRB0_E *
- * IIO_ICRB3_A IIO_ICRB0_A *
- * IIO_ICRB3_B IIO_ICRB0_B *
- * IIO_ICRB3_C IIO_ICRB0_C *
- * IIO_ICRB3_D IIO_ICRB0_D *
- * IIO_ICRB3_E IIO_ICRB0_E *
- * IIO_ICRB4_A IIO_ICRB0_A *
- * IIO_ICRB4_B IIO_ICRB0_B *
- * IIO_ICRB4_C IIO_ICRB0_C *
- * IIO_ICRB4_D IIO_ICRB0_D *
- * IIO_ICRB4_E IIO_ICRB0_E *
- * IIO_ICRB5_A IIO_ICRB0_A *
- * IIO_ICRB5_B IIO_ICRB0_B *
- * IIO_ICRB5_C IIO_ICRB0_C *
- * IIO_ICRB5_D IIO_ICRB0_D *
- * IIO_ICRB5_E IIO_ICRB0_E *
- * IIO_ICRB6_A IIO_ICRB0_A *
- * IIO_ICRB6_B IIO_ICRB0_B *
- * IIO_ICRB6_C IIO_ICRB0_C *
- * IIO_ICRB6_D IIO_ICRB0_D *
- * IIO_ICRB6_E IIO_ICRB0_E *
- * IIO_ICRB7_A IIO_ICRB0_A *
- * IIO_ICRB7_B IIO_ICRB0_B *
- * IIO_ICRB7_C IIO_ICRB0_C *
- * IIO_ICRB7_D IIO_ICRB0_D *
- * IIO_ICRB7_E IIO_ICRB0_E *
- * IIO_ICRB8_A IIO_ICRB0_A *
- * IIO_ICRB8_B IIO_ICRB0_B *
- * IIO_ICRB8_C IIO_ICRB0_C *
- * IIO_ICRB8_D IIO_ICRB0_D *
- * IIO_ICRB8_E IIO_ICRB0_E *
- * IIO_ICRB9_A IIO_ICRB0_A *
- * IIO_ICRB9_B IIO_ICRB0_B *
- * IIO_ICRB9_C IIO_ICRB0_C *
- * IIO_ICRB9_D IIO_ICRB0_D *
- * IIO_ICRB9_E IIO_ICRB0_E *
- * IIO_ICRBA_A IIO_ICRB0_A *
- * IIO_ICRBA_B IIO_ICRB0_B *
- * IIO_ICRBA_C IIO_ICRB0_C *
- * IIO_ICRBA_D IIO_ICRB0_D *
- * IIO_ICRBA_E IIO_ICRB0_E *
- * IIO_ICRBB_A IIO_ICRB0_A *
- * IIO_ICRBB_B IIO_ICRB0_B *
- * IIO_ICRBB_C IIO_ICRB0_C *
- * IIO_ICRBB_D IIO_ICRB0_D *
- * IIO_ICRBB_E IIO_ICRB0_E *
- * IIO_ICRBC_A IIO_ICRB0_A *
- * IIO_ICRBC_B IIO_ICRB0_B *
- * IIO_ICRBC_C IIO_ICRB0_C *
- * IIO_ICRBC_D IIO_ICRB0_D *
- * IIO_ICRBC_E IIO_ICRB0_E *
- * IIO_ICRBD_A IIO_ICRB0_A *
- * IIO_ICRBD_B IIO_ICRB0_B *
- * IIO_ICRBD_C IIO_ICRB0_C *
- * IIO_ICRBD_D IIO_ICRB0_D *
- * IIO_ICRBD_E IIO_ICRB0_E *
- * IIO_ICRBE_A IIO_ICRB0_A *
- * IIO_ICRBE_B IIO_ICRB0_B *
- * IIO_ICRBE_C IIO_ICRB0_C *
- * IIO_ICRBE_D IIO_ICRB0_D *
- * IIO_ICRBE_E IIO_ICRB0_E *
- * *
- ************************************************************************/
-
-/*
- * Slightly friendlier names for some common registers.
- */
-#define IIO_WIDGET IIO_WID /* Widget identification */
-#define IIO_WIDGET_STAT IIO_WSTAT /* Widget status register */
-#define IIO_WIDGET_CTRL IIO_WCR /* Widget control register */
-#define IIO_PROTECT IIO_ILAPR /* IO interface protection */
-#define IIO_PROTECT_OVRRD IIO_ILAPO /* IO protect override */
-#define IIO_OUTWIDGET_ACCESS IIO_IOWA /* Outbound widget access */
-#define IIO_INWIDGET_ACCESS IIO_IIWA /* Inbound widget access */
-#define IIO_INDEV_ERR_MASK IIO_IIDEM /* Inbound device error mask */
-#define IIO_LLP_CSR IIO_ILCSR /* LLP control and status */
-#define IIO_LLP_LOG IIO_ILLR /* LLP log */
-#define IIO_XTALKCC_TOUT IIO_IXCC /* Xtalk credit count timeout */
-#define IIO_XTALKTT_TOUT IIO_IXTT /* Xtalk tail timeout */
-#define IIO_IO_ERR_CLR IIO_IECLR /* IO error clear */
-#define IIO_IGFX_0 IIO_IGFX0
-#define IIO_IGFX_1 IIO_IGFX1
-#define IIO_IBCT_0 IIO_IBCT0
-#define IIO_IBCT_1 IIO_IBCT1
-#define IIO_IBLS_0 IIO_IBLS0
-#define IIO_IBLS_1 IIO_IBLS1
-#define IIO_IBSA_0 IIO_IBSA0
-#define IIO_IBSA_1 IIO_IBSA1
-#define IIO_IBDA_0 IIO_IBDA0
-#define IIO_IBDA_1 IIO_IBDA1
-#define IIO_IBNA_0 IIO_IBNA0
-#define IIO_IBNA_1 IIO_IBNA1
-#define IIO_IBIA_0 IIO_IBIA0
-#define IIO_IBIA_1 IIO_IBIA1
-#define IIO_IOPRB_0 IIO_IPRB0
-
-#define IIO_PRTE_A(_x) (IIO_IPRTE0_A + (8 * (_x)))
-#define IIO_PRTE_B(_x) (IIO_IPRTE0_B + (8 * (_x)))
-#define IIO_NUM_PRTES 8 /* Total number of PRB table entries */
-#define IIO_WIDPRTE_A(x) IIO_PRTE_A(((x) - 8)) /* widget ID to its PRTE num */
-#define IIO_WIDPRTE_B(x) IIO_PRTE_B(((x) - 8)) /* widget ID to its PRTE num */
-
-#define IIO_NUM_IPRBS 9
-
-#define IIO_LLP_CSR_IS_UP 0x00002000
-#define IIO_LLP_CSR_LLP_STAT_MASK 0x00003000
-#define IIO_LLP_CSR_LLP_STAT_SHFT 12
-
-#define IIO_LLP_CB_MAX 0xffff /* in ILLR CB_CNT, Max Check Bit errors */
-#define IIO_LLP_SN_MAX 0xffff /* in ILLR SN_CNT, Max Sequence Number errors */
-
-/* key to IIO_PROTECT_OVRRD */
-#define IIO_PROTECT_OVRRD_KEY 0x53474972756c6573ull /* "SGIrules" */
-
-/* BTE register names */
-#define IIO_BTE_STAT_0 IIO_IBLS_0 /* Also BTE length/status 0 */
-#define IIO_BTE_SRC_0 IIO_IBSA_0 /* Also BTE source address 0 */
-#define IIO_BTE_DEST_0 IIO_IBDA_0 /* Also BTE dest. address 0 */
-#define IIO_BTE_CTRL_0 IIO_IBCT_0 /* Also BTE control/terminate 0 */
-#define IIO_BTE_NOTIFY_0 IIO_IBNA_0 /* Also BTE notification 0 */
-#define IIO_BTE_INT_0 IIO_IBIA_0 /* Also BTE interrupt 0 */
-#define IIO_BTE_OFF_0 0 /* Base offset from BTE 0 regs. */
-#define IIO_BTE_OFF_1 (IIO_IBLS_1 - IIO_IBLS_0) /* Offset from base to BTE 1 */
-
-/* BTE register offsets from base */
-#define BTEOFF_STAT 0
-#define BTEOFF_SRC (IIO_BTE_SRC_0 - IIO_BTE_STAT_0)
-#define BTEOFF_DEST (IIO_BTE_DEST_0 - IIO_BTE_STAT_0)
-#define BTEOFF_CTRL (IIO_BTE_CTRL_0 - IIO_BTE_STAT_0)
-#define BTEOFF_NOTIFY (IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0)
-#define BTEOFF_INT (IIO_BTE_INT_0 - IIO_BTE_STAT_0)
-
-/* names used in shub diags */
-#define IIO_BASE_BTE0 IIO_IBLS_0
-#define IIO_BASE_BTE1 IIO_IBLS_1
-
-/*
- * Macro which takes the widget number, and returns the
- * IO PRB address of that widget.
- * value _x is expected to be a widget number in the range
- * 0, 8 - 0xF
- */
-#define IIO_IOPRB(_x) (IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \
- (_x) : \
- (_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )
-
-/* GFX Flow Control Node/Widget Register */
-#define IIO_IGFX_W_NUM_BITS 4 /* size of widget num field */
-#define IIO_IGFX_W_NUM_MASK ((1<<IIO_IGFX_W_NUM_BITS)-1)
-#define IIO_IGFX_W_NUM_SHIFT 0
-#define IIO_IGFX_PI_NUM_BITS 1 /* size of PI num field */
-#define IIO_IGFX_PI_NUM_MASK ((1<<IIO_IGFX_PI_NUM_BITS)-1)
-#define IIO_IGFX_PI_NUM_SHIFT 4
-#define IIO_IGFX_N_NUM_BITS 8 /* size of node num field */
-#define IIO_IGFX_N_NUM_MASK ((1<<IIO_IGFX_N_NUM_BITS)-1)
-#define IIO_IGFX_N_NUM_SHIFT 5
-#define IIO_IGFX_P_NUM_BITS 1 /* size of processor num field */
-#define IIO_IGFX_P_NUM_MASK ((1<<IIO_IGFX_P_NUM_BITS)-1)
-#define IIO_IGFX_P_NUM_SHIFT 16
-#define IIO_IGFX_INIT(widget, pi, node, cpu) (\
- (((widget) & IIO_IGFX_W_NUM_MASK) << IIO_IGFX_W_NUM_SHIFT) | \
- (((pi) & IIO_IGFX_PI_NUM_MASK)<< IIO_IGFX_PI_NUM_SHIFT)| \
- (((node) & IIO_IGFX_N_NUM_MASK) << IIO_IGFX_N_NUM_SHIFT) | \
- (((cpu) & IIO_IGFX_P_NUM_MASK) << IIO_IGFX_P_NUM_SHIFT))
-
-/* Scratch registers (all bits available) */
-#define IIO_SCRATCH_REG0 IIO_ISCR0
-#define IIO_SCRATCH_REG1 IIO_ISCR1
-#define IIO_SCRATCH_MASK 0xffffffffffffffffUL
-
-#define IIO_SCRATCH_BIT0_0 0x0000000000000001UL
-#define IIO_SCRATCH_BIT0_1 0x0000000000000002UL
-#define IIO_SCRATCH_BIT0_2 0x0000000000000004UL
-#define IIO_SCRATCH_BIT0_3 0x0000000000000008UL
-#define IIO_SCRATCH_BIT0_4 0x0000000000000010UL
-#define IIO_SCRATCH_BIT0_5 0x0000000000000020UL
-#define IIO_SCRATCH_BIT0_6 0x0000000000000040UL
-#define IIO_SCRATCH_BIT0_7 0x0000000000000080UL
-#define IIO_SCRATCH_BIT0_8 0x0000000000000100UL
-#define IIO_SCRATCH_BIT0_9 0x0000000000000200UL
-#define IIO_SCRATCH_BIT0_A 0x0000000000000400UL
-
-#define IIO_SCRATCH_BIT1_0 0x0000000000000001UL
-#define IIO_SCRATCH_BIT1_1 0x0000000000000002UL
-/* IO Translation Table Entries */
-#define IIO_NUM_ITTES 7 /* ITTEs numbered 0..6 */
- /* Hw manuals number them 1..7! */
-/*
- * IIO_IMEM Register fields.
- */
-#define IIO_IMEM_W0ESD 0x1UL /* Widget 0 shut down due to error */
-#define IIO_IMEM_B0ESD (1UL << 4) /* BTE 0 shut down due to error */
-#define IIO_IMEM_B1ESD (1UL << 8) /* BTE 1 Shut down due to error */
-
-/*
- * As a permanent workaround for a bug in the PI side of the shub, we've
- * redefined big window 7 as small window 0.
- XXX does this still apply for SN1??
- */
-#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
-
-/*
- * Use the top big window as a surrogate for the first small window
- */
-#define SWIN0_BIGWIN HUB_NUM_BIG_WINDOW
-
-#define ILCSR_WARM_RESET 0x100
-
-/*
- * CRB manipulation macros
- * The CRB macros are slightly complicated, since there are up to
- * four registers associated with each CRB entry.
- */
-#define IIO_NUM_CRBS 15 /* Number of CRBs */
-#define IIO_NUM_PC_CRBS 4 /* Number of partial cache CRBs */
-#define IIO_ICRB_OFFSET 8
-#define IIO_ICRB_0 IIO_ICRB0_A
-#define IIO_ICRB_ADDR_SHFT 2 /* Shift to get proper address */
-/* XXX - This is now tuneable:
- #define IIO_FIRST_PC_ENTRY 12
- */
-
-#define IIO_ICRB_A(_x) ((u64)(IIO_ICRB_0 + (6 * IIO_ICRB_OFFSET * (_x))))
-#define IIO_ICRB_B(_x) ((u64)((char *)IIO_ICRB_A(_x) + 1*IIO_ICRB_OFFSET))
-#define IIO_ICRB_C(_x) ((u64)((char *)IIO_ICRB_A(_x) + 2*IIO_ICRB_OFFSET))
-#define IIO_ICRB_D(_x) ((u64)((char *)IIO_ICRB_A(_x) + 3*IIO_ICRB_OFFSET))
-#define IIO_ICRB_E(_x) ((u64)((char *)IIO_ICRB_A(_x) + 4*IIO_ICRB_OFFSET))
-
-#define TNUM_TO_WIDGET_DEV(_tnum) (_tnum & 0x7)
-
-/*
- * values for "ecode" field
- */
-#define IIO_ICRB_ECODE_DERR 0 /* Directory error due to IIO access */
-#define IIO_ICRB_ECODE_PERR 1 /* Poison error on IO access */
-#define IIO_ICRB_ECODE_WERR 2 /* Write error by IIO access
- * e.g. WINV to a Read only line. */
-#define IIO_ICRB_ECODE_AERR 3 /* Access error caused by IIO access */
-#define IIO_ICRB_ECODE_PWERR 4 /* Error on partial write */
-#define IIO_ICRB_ECODE_PRERR 5 /* Error on partial read */
-#define IIO_ICRB_ECODE_TOUT 6 /* CRB timeout before deallocating */
-#define IIO_ICRB_ECODE_XTERR 7 /* Incoming xtalk pkt had error bit */
-
-/*
- * Values for field imsgtype
- */
-#define IIO_ICRB_IMSGT_XTALK 0 /* Incoming message from Xtalk */
-#define IIO_ICRB_IMSGT_BTE 1 /* Incoming message from BTE */
-#define IIO_ICRB_IMSGT_SN1NET 2 /* Incoming message from SN1 net */
-#define IIO_ICRB_IMSGT_CRB 3 /* Incoming message from CRB ??? */
-
-/*
- * values for field initiator.
- */
-#define IIO_ICRB_INIT_XTALK 0 /* Message originated in xtalk */
-#define IIO_ICRB_INIT_BTE0 0x1 /* Message originated in BTE 0 */
-#define IIO_ICRB_INIT_SN1NET 0x2 /* Message originated in SN1net */
-#define IIO_ICRB_INIT_CRB 0x3 /* Message originated in CRB ? */
-#define IIO_ICRB_INIT_BTE1 0x5 /* MEssage originated in BTE 1 */
-
-/*
- * Number of credits Hub widget has while sending req/response to
- * xbow.
- * Value of 3 is required by Xbow 1.1
- * We may be able to increase this to 4 with Xbow 1.2.
- */
-#define HUBII_XBOW_CREDIT 3
-#define HUBII_XBOW_REV2_CREDIT 4
-
-/*
- * Number of credits that xtalk devices should use when communicating
- * with a SHub (depth of SHub's queue).
- */
-#define HUB_CREDIT 4
-
-/*
- * Some IIO_PRB fields
- */
-#define IIO_PRB_MULTI_ERR (1LL << 63)
-#define IIO_PRB_SPUR_RD (1LL << 51)
-#define IIO_PRB_SPUR_WR (1LL << 50)
-#define IIO_PRB_RD_TO (1LL << 49)
-#define IIO_PRB_ERROR (1LL << 48)
-
-/*************************************************************************
-
- Some of the IIO field masks and shifts are defined here.
- This is in order to maintain compatibility in SN0 and SN1 code
-
-**************************************************************************/
-
-/*
- * ICMR register fields
- * (Note: the IIO_ICMR_P_CNT and IIO_ICMR_PC_VLD from Hub are not
- * present in SHub)
- */
-
-#define IIO_ICMR_CRB_VLD_SHFT 20
-#define IIO_ICMR_CRB_VLD_MASK (0x7fffUL << IIO_ICMR_CRB_VLD_SHFT)
-
-#define IIO_ICMR_FC_CNT_SHFT 16
-#define IIO_ICMR_FC_CNT_MASK (0xf << IIO_ICMR_FC_CNT_SHFT)
-
-#define IIO_ICMR_C_CNT_SHFT 4
-#define IIO_ICMR_C_CNT_MASK (0xf << IIO_ICMR_C_CNT_SHFT)
-
-#define IIO_ICMR_PRECISE (1UL << 52)
-#define IIO_ICMR_CLR_RPPD (1UL << 13)
-#define IIO_ICMR_CLR_RQPD (1UL << 12)
-
-/*
- * IIO PIO Deallocation register field masks : (IIO_IPDR)
- XXX present but not needed in bedrock? See the manual.
- */
-#define IIO_IPDR_PND (1 << 4)
-
-/*
- * IIO CRB deallocation register field masks: (IIO_ICDR)
- */
-#define IIO_ICDR_PND (1 << 4)
-
-/*
- * IO BTE Length/Status (IIO_IBLS) register bit field definitions
- */
-#define IBLS_BUSY (0x1UL << 20)
-#define IBLS_ERROR_SHFT 16
-#define IBLS_ERROR (0x1UL << IBLS_ERROR_SHFT)
-#define IBLS_LENGTH_MASK 0xffff
-
-/*
- * IO BTE Control/Terminate register (IBCT) register bit field definitions
- */
-#define IBCT_POISON (0x1UL << 8)
-#define IBCT_NOTIFY (0x1UL << 4)
-#define IBCT_ZFIL_MODE (0x1UL << 0)
-
-/*
- * IIO Incoming Error Packet Header (IIO_IIEPH1/IIO_IIEPH2)
- */
-#define IIEPH1_VALID (1UL << 44)
-#define IIEPH1_OVERRUN (1UL << 40)
-#define IIEPH1_ERR_TYPE_SHFT 32
-#define IIEPH1_ERR_TYPE_MASK 0xf
-#define IIEPH1_SOURCE_SHFT 20
-#define IIEPH1_SOURCE_MASK 11
-#define IIEPH1_SUPPL_SHFT 8
-#define IIEPH1_SUPPL_MASK 11
-#define IIEPH1_CMD_SHFT 0
-#define IIEPH1_CMD_MASK 7
-
-#define IIEPH2_TAIL (1UL << 40)
-#define IIEPH2_ADDRESS_SHFT 0
-#define IIEPH2_ADDRESS_MASK 38
-
-#define IIEPH1_ERR_SHORT_REQ 2
-#define IIEPH1_ERR_SHORT_REPLY 3
-#define IIEPH1_ERR_LONG_REQ 4
-#define IIEPH1_ERR_LONG_REPLY 5
-
-/*
- * IO Error Clear register bit field definitions
- */
-#define IECLR_PI1_FWD_INT (1UL << 31) /* clear PI1_FORWARD_INT in iidsr */
-#define IECLR_PI0_FWD_INT (1UL << 30) /* clear PI0_FORWARD_INT in iidsr */
-#define IECLR_SPUR_RD_HDR (1UL << 29) /* clear valid bit in ixss reg */
-#define IECLR_BTE1 (1UL << 18) /* clear bte error 1 */
-#define IECLR_BTE0 (1UL << 17) /* clear bte error 0 */
-#define IECLR_CRAZY (1UL << 16) /* clear crazy bit in wstat reg */
-#define IECLR_PRB_F (1UL << 15) /* clear err bit in PRB_F reg */
-#define IECLR_PRB_E (1UL << 14) /* clear err bit in PRB_E reg */
-#define IECLR_PRB_D (1UL << 13) /* clear err bit in PRB_D reg */
-#define IECLR_PRB_C (1UL << 12) /* clear err bit in PRB_C reg */
-#define IECLR_PRB_B (1UL << 11) /* clear err bit in PRB_B reg */
-#define IECLR_PRB_A (1UL << 10) /* clear err bit in PRB_A reg */
-#define IECLR_PRB_9 (1UL << 9) /* clear err bit in PRB_9 reg */
-#define IECLR_PRB_8 (1UL << 8) /* clear err bit in PRB_8 reg */
-#define IECLR_PRB_0 (1UL << 0) /* clear err bit in PRB_0 reg */
-
-/*
- * IIO CRB control register Fields: IIO_ICCR
- */
-#define IIO_ICCR_PENDING 0x10000
-#define IIO_ICCR_CMD_MASK 0xFF
-#define IIO_ICCR_CMD_SHFT 7
-#define IIO_ICCR_CMD_NOP 0x0 /* No Op */
-#define IIO_ICCR_CMD_WAKE 0x100 /* Reactivate CRB entry and process */
-#define IIO_ICCR_CMD_TIMEOUT 0x200 /* Make CRB timeout & mark invalid */
-#define IIO_ICCR_CMD_EJECT 0x400 /* Contents of entry written to memory
- * via a WB
- */
-#define IIO_ICCR_CMD_FLUSH 0x800
-
-/*
- *
- * CRB Register description.
- *
- * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- *
- * Many of the fields in CRB are status bits used by hardware
- * for implementation of the protocol. It's very dangerous to
- * mess around with the CRB registers.
- *
- * It's OK to read the CRB registers and try to make sense out of the
- * fields in CRB.
- *
- * Updating CRB requires all activities in Hub IIO to be quiesced.
- * otherwise, a write to CRB could corrupt other CRB entries.
- * CRBs are here only as a back door peek to shub IIO's status.
- * Quiescing implies no dmas no PIOs
- * either directly from the cpu or from sn0net.
- * this is not something that can be done easily. So, AVOID updating
- * CRBs.
- */
-
-/*
- * Easy access macros for CRBs, all 5 registers (A-E)
- */
-typedef ii_icrb0_a_u_t icrba_t;
-#define a_sidn ii_icrb0_a_fld_s.ia_sidn
-#define a_tnum ii_icrb0_a_fld_s.ia_tnum
-#define a_addr ii_icrb0_a_fld_s.ia_addr
-#define a_valid ii_icrb0_a_fld_s.ia_vld
-#define a_iow ii_icrb0_a_fld_s.ia_iow
-#define a_regvalue ii_icrb0_a_regval
-
-typedef ii_icrb0_b_u_t icrbb_t;
-#define b_use_old ii_icrb0_b_fld_s.ib_use_old
-#define b_imsgtype ii_icrb0_b_fld_s.ib_imsgtype
-#define b_imsg ii_icrb0_b_fld_s.ib_imsg
-#define b_initiator ii_icrb0_b_fld_s.ib_init
-#define b_exc ii_icrb0_b_fld_s.ib_exc
-#define b_ackcnt ii_icrb0_b_fld_s.ib_ack_cnt
-#define b_resp ii_icrb0_b_fld_s.ib_resp
-#define b_ack ii_icrb0_b_fld_s.ib_ack
-#define b_hold ii_icrb0_b_fld_s.ib_hold
-#define b_wb ii_icrb0_b_fld_s.ib_wb
-#define b_intvn ii_icrb0_b_fld_s.ib_intvn
-#define b_stall_ib ii_icrb0_b_fld_s.ib_stall_ib
-#define b_stall_int ii_icrb0_b_fld_s.ib_stall__intr
-#define b_stall_bte_0 ii_icrb0_b_fld_s.ib_stall__bte_0
-#define b_stall_bte_1 ii_icrb0_b_fld_s.ib_stall__bte_1
-#define b_error ii_icrb0_b_fld_s.ib_error
-#define b_ecode ii_icrb0_b_fld_s.ib_errcode
-#define b_lnetuce ii_icrb0_b_fld_s.ib_ln_uce
-#define b_mark ii_icrb0_b_fld_s.ib_mark
-#define b_xerr ii_icrb0_b_fld_s.ib_xt_err
-#define b_regvalue ii_icrb0_b_regval
-
-typedef ii_icrb0_c_u_t icrbc_t;
-#define c_suppl ii_icrb0_c_fld_s.ic_suppl
-#define c_barrop ii_icrb0_c_fld_s.ic_bo
-#define c_doresp ii_icrb0_c_fld_s.ic_resprqd
-#define c_gbr ii_icrb0_c_fld_s.ic_gbr
-#define c_btenum ii_icrb0_c_fld_s.ic_bte_num
-#define c_cohtrans ii_icrb0_c_fld_s.ic_ct
-#define c_xtsize ii_icrb0_c_fld_s.ic_size
-#define c_source ii_icrb0_c_fld_s.ic_source
-#define c_regvalue ii_icrb0_c_regval
-
-typedef ii_icrb0_d_u_t icrbd_t;
-#define d_sleep ii_icrb0_d_fld_s.id_sleep
-#define d_pricnt ii_icrb0_d_fld_s.id_pr_cnt
-#define d_pripsc ii_icrb0_d_fld_s.id_pr_psc
-#define d_bteop ii_icrb0_d_fld_s.id_bte_op
-#define d_bteaddr ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names */
-#define d_benable ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names */
-#define d_regvalue ii_icrb0_d_regval
-
-typedef ii_icrb0_e_u_t icrbe_t;
-#define icrbe_ctxtvld ii_icrb0_e_fld_s.ie_cvld
-#define icrbe_toutvld ii_icrb0_e_fld_s.ie_tvld
-#define icrbe_context ii_icrb0_e_fld_s.ie_context
-#define icrbe_timeout ii_icrb0_e_fld_s.ie_timeout
-#define e_regvalue ii_icrb0_e_regval
-
-/* Number of widgets supported by shub */
-#define HUB_NUM_WIDGET 9
-#define HUB_WIDGET_ID_MIN 0x8
-#define HUB_WIDGET_ID_MAX 0xf
-
-#define HUB_WIDGET_PART_NUM 0xc120
-#define MAX_HUBS_PER_XBOW 2
-
-/* A few more #defines for backwards compatibility */
-#define iprb_t ii_iprb0_u_t
-#define iprb_regval ii_iprb0_regval
-#define iprb_mult_err ii_iprb0_fld_s.i_mult_err
-#define iprb_spur_rd ii_iprb0_fld_s.i_spur_rd
-#define iprb_spur_wr ii_iprb0_fld_s.i_spur_wr
-#define iprb_rd_to ii_iprb0_fld_s.i_rd_to
-#define iprb_ovflow ii_iprb0_fld_s.i_of_cnt
-#define iprb_error ii_iprb0_fld_s.i_error
-#define iprb_ff ii_iprb0_fld_s.i_f
-#define iprb_mode ii_iprb0_fld_s.i_m
-#define iprb_bnakctr ii_iprb0_fld_s.i_nb
-#define iprb_anakctr ii_iprb0_fld_s.i_na
-#define iprb_xtalkctr ii_iprb0_fld_s.i_c
-
-#define LNK_STAT_WORKING 0x2 /* LLP is working */
-
-#define IIO_WSTAT_ECRAZY (1ULL << 32) /* Hub gone crazy */
-#define IIO_WSTAT_TXRETRY (1ULL << 9) /* Hub Tx Retry timeout */
-#define IIO_WSTAT_TXRETRY_MASK 0x7F /* should be 0xFF?? */
-#define IIO_WSTAT_TXRETRY_SHFT 16
-#define IIO_WSTAT_TXRETRY_CNT(w) (((w) >> IIO_WSTAT_TXRETRY_SHFT) & \
- IIO_WSTAT_TXRETRY_MASK)
-
-/* Number of II perf. counters we can multiplex at once */
-
-#define IO_PERF_SETS 32
-
-/* Bit for the widget in inbound access register */
-#define IIO_IIWA_WIDGET(_w) ((u64)(1ULL << _w))
-/* Bit for the widget in outbound access register */
-#define IIO_IOWA_WIDGET(_w) ((u64)(1ULL << _w))
-
-/* NOTE: The following define assumes that we are going to get
- * widget numbers from 8 thru F and the device numbers within
- * widget from 0 thru 7.
- */
-#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((u64)(1ULL << (8 * ((w) - 8) + (d))))
-
-/* IO Interrupt Destination Register */
-#define IIO_IIDSR_SENT_SHIFT 28
-#define IIO_IIDSR_SENT_MASK 0x30000000
-#define IIO_IIDSR_ENB_SHIFT 24
-#define IIO_IIDSR_ENB_MASK 0x01000000
-#define IIO_IIDSR_NODE_SHIFT 9
-#define IIO_IIDSR_NODE_MASK 0x000ff700
-#define IIO_IIDSR_PI_ID_SHIFT 8
-#define IIO_IIDSR_PI_ID_MASK 0x00000100
-#define IIO_IIDSR_LVL_SHIFT 0
-#define IIO_IIDSR_LVL_MASK 0x000000ff
-
-/* Xtalk timeout threshold register (IIO_IXTT) */
-#define IXTT_RRSP_TO_SHFT 55 /* read response timeout */
-#define IXTT_RRSP_TO_MASK (0x1FULL << IXTT_RRSP_TO_SHFT)
-#define IXTT_RRSP_PS_SHFT 32 /* read responsed TO prescalar */
-#define IXTT_RRSP_PS_MASK (0x7FFFFFULL << IXTT_RRSP_PS_SHFT)
-#define IXTT_TAIL_TO_SHFT 0 /* tail timeout counter threshold */
-#define IXTT_TAIL_TO_MASK (0x3FFFFFFULL << IXTT_TAIL_TO_SHFT)
-
-/*
- * The IO LLP control status register and widget control register
- */
-
-typedef union hubii_wcr_u {
- u64 wcr_reg_value;
- struct {
- u64 wcr_widget_id:4, /* LLP crossbar credit */
- wcr_tag_mode:1, /* Tag mode */
- wcr_rsvd1:8, /* Reserved */
- wcr_xbar_crd:3, /* LLP crossbar credit */
- wcr_f_bad_pkt:1, /* Force bad llp pkt enable */
- wcr_dir_con:1, /* widget direct connect */
- wcr_e_thresh:5, /* elasticity threshold */
- wcr_rsvd:41; /* unused */
- } wcr_fields_s;
-} hubii_wcr_t;
-
-#define iwcr_dir_con wcr_fields_s.wcr_dir_con
-
-/* The structures below are defined to extract and modify the ii
-performance registers */
-
-/* io_perf_sel allows the caller to specify what tests will be
- performed */
-
-typedef union io_perf_sel {
- u64 perf_sel_reg;
- struct {
- u64 perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48;
- } perf_sel_bits;
-} io_perf_sel_t;
-
-/* io_perf_cnt is to extract the count from the shub registers. Due to
- hardware problems there is only one counter, not two. */
-
-typedef union io_perf_cnt {
- u64 perf_cnt;
- struct {
- u64 perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32;
- } perf_cnt_bits;
-
-} io_perf_cnt_t;
-
-typedef union iprte_a {
- u64 entry;
- struct {
- u64 i_rsvd_1:3;
- u64 i_addr:38;
- u64 i_init:3;
- u64 i_source:8;
- u64 i_rsvd:2;
- u64 i_widget:4;
- u64 i_to_cnt:5;
- u64 i_vld:1;
- } iprte_fields;
-} iprte_a_t;
-
-#endif /* _ASM_IA64_SN_SHUBIO_H */
diff --git a/arch/ia64/include/asm/sn/simulator.h b/arch/ia64/include/asm/sn/simulator.h
deleted file mode 100644
index c2611f6cfe33..000000000000
--- a/arch/ia64/include/asm/sn/simulator.h
+++ /dev/null
@@ -1,25 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_SIMULATOR_H
-#define _ASM_IA64_SN_SIMULATOR_H
-
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_SGI_UV)
-#define SNMAGIC 0xaeeeeeee8badbeefL
-#define IS_MEDUSA() ({long sn; asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); sn == SNMAGIC;})
-
-#define SIMULATOR_SLEEP() asm("nop.i 0x8beef")
-#define IS_RUNNING_ON_SIMULATOR() (sn_prom_type)
-#define IS_RUNNING_ON_FAKE_PROM() (sn_prom_type == 2)
-extern int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
-#else
-#define IS_MEDUSA() 0
-#define SIMULATOR_SLEEP()
-#define IS_RUNNING_ON_SIMULATOR() 0
-#endif
-
-#endif /* _ASM_IA64_SN_SIMULATOR_H */
diff --git a/arch/ia64/include/asm/sn/sn2/sn_hwperf.h b/arch/ia64/include/asm/sn/sn2/sn_hwperf.h
deleted file mode 100644
index e61ebac38cdd..000000000000
--- a/arch/ia64/include/asm/sn/sn2/sn_hwperf.h
+++ /dev/null
@@ -1,242 +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) 2004 Silicon Graphics, Inc. All rights reserved.
- *
- * Data types used by the SN_SAL_HWPERF_OP SAL call for monitoring
- * SGI Altix node and router hardware
- *
- * Mark Goodwin <markgw@sgi.com> Mon Aug 30 12:23:46 EST 2004
- */
-
-#ifndef SN_HWPERF_H
-#define SN_HWPERF_H
-
-/*
- * object structure. SN_HWPERF_ENUM_OBJECTS and SN_HWPERF_GET_CPU_INFO
- * return an array of these. Do not change this without also
- * changing the corresponding SAL code.
- */
-#define SN_HWPERF_MAXSTRING 128
-struct sn_hwperf_object_info {
- u32 id;
- union {
- struct {
- u64 this_part:1;
- u64 is_shared:1;
- } fields;
- struct {
- u64 flags;
- u64 reserved;
- } b;
- } f;
- char name[SN_HWPERF_MAXSTRING];
- char location[SN_HWPERF_MAXSTRING];
- u32 ports;
-};
-
-#define sn_hwp_this_part f.fields.this_part
-#define sn_hwp_is_shared f.fields.is_shared
-#define sn_hwp_flags f.b.flags
-
-/* macros for object classification */
-#define SN_HWPERF_IS_NODE(x) ((x) && strstr((x)->name, "SHub"))
-#define SN_HWPERF_IS_NODE_SHUB2(x) ((x) && strstr((x)->name, "SHub 2."))
-#define SN_HWPERF_IS_IONODE(x) ((x) && strstr((x)->name, "TIO"))
-#define SN_HWPERF_IS_NL3ROUTER(x) ((x) && strstr((x)->name, "NL3Router"))
-#define SN_HWPERF_IS_NL4ROUTER(x) ((x) && strstr((x)->name, "NL4Router"))
-#define SN_HWPERF_IS_OLDROUTER(x) ((x) && strstr((x)->name, "Router"))
-#define SN_HWPERF_IS_ROUTER(x) (SN_HWPERF_IS_NL3ROUTER(x) || \
- SN_HWPERF_IS_NL4ROUTER(x) || \
- SN_HWPERF_IS_OLDROUTER(x))
-#define SN_HWPERF_FOREIGN(x) ((x) && !(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
-#define SN_HWPERF_SAME_OBJTYPE(x,y) ((SN_HWPERF_IS_NODE(x) && SN_HWPERF_IS_NODE(y)) ||\
- (SN_HWPERF_IS_IONODE(x) && SN_HWPERF_IS_IONODE(y)) ||\
- (SN_HWPERF_IS_ROUTER(x) && SN_HWPERF_IS_ROUTER(y)))
-
-/* numa port structure, SN_HWPERF_ENUM_PORTS returns an array of these */
-struct sn_hwperf_port_info {
- u32 port;
- u32 conn_id;
- u32 conn_port;
-};
-
-/* for HWPERF_{GET,SET}_MMRS */
-struct sn_hwperf_data {
- u64 addr;
- u64 data;
-};
-
-/* user ioctl() argument, see below */
-struct sn_hwperf_ioctl_args {
- u64 arg; /* argument, usually an object id */
- u64 sz; /* size of transfer */
- void *ptr; /* pointer to source/target */
- u32 v0; /* second return value */
-};
-
-/*
- * For SN_HWPERF_{GET,SET}_MMRS and SN_HWPERF_OBJECT_DISTANCE,
- * sn_hwperf_ioctl_args.arg can be used to specify a CPU on which
- * to call SAL, and whether to use an interprocessor interrupt
- * or task migration in order to do so. If the CPU specified is
- * SN_HWPERF_ARG_ANY_CPU, then the current CPU will be used.
- */
-#define SN_HWPERF_ARG_ANY_CPU 0x7fffffffUL
-#define SN_HWPERF_ARG_CPU_MASK 0x7fffffff00000000ULL
-#define SN_HWPERF_ARG_USE_IPI_MASK 0x8000000000000000ULL
-#define SN_HWPERF_ARG_OBJID_MASK 0x00000000ffffffffULL
-
-/*
- * ioctl requests on the "sn_hwperf" misc device that call SAL.
- */
-#define SN_HWPERF_OP_MEM_COPYIN 0x1000
-#define SN_HWPERF_OP_MEM_COPYOUT 0x2000
-#define SN_HWPERF_OP_MASK 0x0fff
-
-/*
- * Determine mem requirement.
- * arg don't care
- * sz 8
- * p pointer to u64 integer
- */
-#define SN_HWPERF_GET_HEAPSIZE 1
-
-/*
- * Install mem for SAL drvr
- * arg don't care
- * sz sizeof buffer pointed to by p
- * p pointer to buffer for scratch area
- */
-#define SN_HWPERF_INSTALL_HEAP 2
-
-/*
- * Determine number of objects
- * arg don't care
- * sz 8
- * p pointer to u64 integer
- */
-#define SN_HWPERF_OBJECT_COUNT (10|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Determine object "distance", relative to a cpu. This operation can
- * execute on a designated logical cpu number, using either an IPI or
- * via task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
- * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
- *
- * arg bitmap of IPI flag, cpu number and object id
- * sz 8
- * p pointer to u64 integer
- */
-#define SN_HWPERF_OBJECT_DISTANCE (11|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Enumerate objects. Special case if sz == 8, returns the required
- * buffer size.
- * arg don't care
- * sz sizeof buffer pointed to by p
- * p pointer to array of struct sn_hwperf_object_info
- */
-#define SN_HWPERF_ENUM_OBJECTS (12|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Enumerate NumaLink ports for an object. Special case if sz == 8,
- * returns the required buffer size.
- * arg object id
- * sz sizeof buffer pointed to by p
- * p pointer to array of struct sn_hwperf_port_info
- */
-#define SN_HWPERF_ENUM_PORTS (13|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * SET/GET memory mapped registers. These operations can execute
- * on a designated logical cpu number, using either an IPI or via
- * task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
- * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
- *
- * arg bitmap of ipi flag, cpu number and object id
- * sz sizeof buffer pointed to by p
- * p pointer to array of struct sn_hwperf_data
- */
-#define SN_HWPERF_SET_MMRS (14|SN_HWPERF_OP_MEM_COPYIN)
-#define SN_HWPERF_GET_MMRS (15|SN_HWPERF_OP_MEM_COPYOUT| \
- SN_HWPERF_OP_MEM_COPYIN)
-/*
- * Lock a shared object
- * arg object id
- * sz don't care
- * p don't care
- */
-#define SN_HWPERF_ACQUIRE 16
-
-/*
- * Unlock a shared object
- * arg object id
- * sz don't care
- * p don't care
- */
-#define SN_HWPERF_RELEASE 17
-
-/*
- * Break a lock on a shared object
- * arg object id
- * sz don't care
- * p don't care
- */
-#define SN_HWPERF_FORCE_RELEASE 18
-
-/*
- * ioctl requests on "sn_hwperf" that do not call SAL
- */
-
-/*
- * get cpu info as an array of hwperf_object_info_t.
- * id is logical CPU number, name is description, location
- * is geoid (e.g. 001c04#1c). Special case if sz == 8,
- * returns the required buffer size.
- *
- * arg don't care
- * sz sizeof buffer pointed to by p
- * p pointer to array of struct sn_hwperf_object_info
- */
-#define SN_HWPERF_GET_CPU_INFO (100|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Given an object id, return it's node number (aka cnode).
- * arg object id
- * sz 8
- * p pointer to u64 integer
- */
-#define SN_HWPERF_GET_OBJ_NODE (101|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Given a node number (cnode), return it's nasid.
- * arg ordinal node number (aka cnodeid)
- * sz 8
- * p pointer to u64 integer
- */
-#define SN_HWPERF_GET_NODE_NASID (102|SN_HWPERF_OP_MEM_COPYOUT)
-
-/*
- * Given a node id, determine the id of the nearest node with CPUs
- * and the id of the nearest node that has memory. The argument
- * node would normally be a "headless" node, e.g. an "IO node".
- * Return 0 on success.
- */
-extern int sn_hwperf_get_nearest_node(cnodeid_t node,
- cnodeid_t *near_mem, cnodeid_t *near_cpu);
-
-/* return codes */
-#define SN_HWPERF_OP_OK 0
-#define SN_HWPERF_OP_NOMEM 1
-#define SN_HWPERF_OP_NO_PERM 2
-#define SN_HWPERF_OP_IO_ERROR 3
-#define SN_HWPERF_OP_BUSY 4
-#define SN_HWPERF_OP_RECONFIGURE 253
-#define SN_HWPERF_OP_INVAL 254
-
-int sn_topology_open(struct inode *inode, struct file *file);
-int sn_topology_release(struct inode *inode, struct file *file);
-#endif /* SN_HWPERF_H */
diff --git a/arch/ia64/include/asm/sn/sn_cpuid.h b/arch/ia64/include/asm/sn/sn_cpuid.h
deleted file mode 100644
index a676dd9ace3e..000000000000
--- a/arch/ia64/include/asm/sn/sn_cpuid.h
+++ /dev/null
@@ -1,132 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-
-#ifndef _ASM_IA64_SN_SN_CPUID_H
-#define _ASM_IA64_SN_SN_CPUID_H
-
-#include <linux/smp.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/pda.h>
-#include <asm/intrinsics.h>
-
-
-/*
- * Functions for converting between cpuids, nodeids and NASIDs.
- *
- * These are for SGI platforms only.
- *
- */
-
-
-
-
-/*
- * Definitions of terms (these definitions are for IA64 ONLY. Other architectures
- * use cpuid/cpunum quite defferently):
- *
- * CPUID - a number in range of 0..NR_CPUS-1 that uniquely identifies
- * the cpu. The value cpuid has no significance on IA64 other than
- * the boot cpu is 0.
- * smp_processor_id() returns the cpuid of the current cpu.
- *
- * CPU_PHYSICAL_ID (also known as HARD_PROCESSOR_ID)
- * This is the same as 31:24 of the processor LID register
- * hard_smp_processor_id()- cpu_physical_id of current processor
- * cpu_physical_id(cpuid) - convert a <cpuid> to a <physical_cpuid>
- * cpu_logical_id(phy_id) - convert a <physical_cpuid> to a <cpuid>
- * * not real efficient - don't use in perf critical code
- *
- * SLICE - a number in the range of 0 - 3 (typically) that represents the
- * cpu number on a brick.
- *
- * SUBNODE - (almost obsolete) the number of the FSB that a cpu is
- * connected to. This is also the same as the PI number. Usually 0 or 1.
- *
- * NOTE!!!: the value of the bits in the cpu physical id (SAPICid or LID) of a cpu has no
- * significance. The SAPIC id (LID) is a 16-bit cookie that has meaning only to the PROM.
- *
- *
- * The macros convert between cpu physical ids & slice/nasid/cnodeid.
- * These terms are described below:
- *
- *
- * Brick
- * ----- ----- ----- ----- CPU
- * | 0 | | 1 | | 0 | | 1 | SLICE
- * ----- ----- ----- -----
- * | | | |
- * | | | |
- * 0 | | 2 0 | | 2 FSB SLOT
- * ------- -------
- * | |
- * | |
- * | |
- * ------------ -------------
- * | | | |
- * | SHUB | | SHUB | NASID (0..MAX_NASIDS)
- * | |----- | | CNODEID (0..num_compact_nodes-1)
- * | | | |
- * | | | |
- * ------------ -------------
- * | |
- *
- *
- */
-
-#define get_node_number(addr) NASID_GET(addr)
-
-/*
- * NOTE: on non-MP systems, only cpuid 0 exists
- */
-
-extern short physical_node_map[]; /* indexed by nasid to get cnode */
-
-/*
- * Macros for retrieving info about current cpu
- */
-#define get_nasid() (sn_nodepda->phys_cpuid[smp_processor_id()].nasid)
-#define get_subnode() (sn_nodepda->phys_cpuid[smp_processor_id()].subnode)
-#define get_slice() (sn_nodepda->phys_cpuid[smp_processor_id()].slice)
-#define get_cnode() (sn_nodepda->phys_cpuid[smp_processor_id()].cnode)
-#define get_sapicid() ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
-
-/*
- * Macros for retrieving info about an arbitrary cpu
- * cpuid - logical cpu id
- */
-#define cpuid_to_nasid(cpuid) (sn_nodepda->phys_cpuid[cpuid].nasid)
-#define cpuid_to_subnode(cpuid) (sn_nodepda->phys_cpuid[cpuid].subnode)
-#define cpuid_to_slice(cpuid) (sn_nodepda->phys_cpuid[cpuid].slice)
-
-
-/*
- * Dont use the following in performance critical code. They require scans
- * of potentially large tables.
- */
-extern int nasid_slice_to_cpuid(int, int);
-
-/*
- * cnodeid_to_nasid - convert a cnodeid to a NASID
- */
-#define cnodeid_to_nasid(cnodeid) (sn_cnodeid_to_nasid[cnodeid])
-
-/*
- * nasid_to_cnodeid - convert a NASID to a cnodeid
- */
-#define nasid_to_cnodeid(nasid) (physical_node_map[nasid])
-
-/*
- * partition_coherence_id - get the coherence ID of the current partition
- */
-extern u8 sn_coherency_id;
-#define partition_coherence_id() (sn_coherency_id)
-
-#endif /* _ASM_IA64_SN_SN_CPUID_H */
-
diff --git a/arch/ia64/include/asm/sn/sn_feature_sets.h b/arch/ia64/include/asm/sn/sn_feature_sets.h
deleted file mode 100644
index 8e83ac117ace..000000000000
--- a/arch/ia64/include/asm/sn/sn_feature_sets.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _ASM_IA64_SN_FEATURE_SETS_H
-#define _ASM_IA64_SN_FEATURE_SETS_H
-
-/*
- * SN PROM Features
- *
- * 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) 2005-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-
-/* --------------------- PROM Features -----------------------------*/
-extern int sn_prom_feature_available(int id);
-
-#define MAX_PROM_FEATURE_SETS 2
-
-/*
- * The following defines features that may or may not be supported by the
- * current PROM. The OS uses sn_prom_feature_available(feature) to test for
- * the presence of a PROM feature. Down rev (old) PROMs will always test
- * "false" for new features.
- *
- * Use:
- * if (sn_prom_feature_available(PRF_XXX))
- * ...
- */
-
-#define PRF_PAL_CACHE_FLUSH_SAFE 0
-#define PRF_DEVICE_FLUSH_LIST 1
-#define PRF_HOTPLUG_SUPPORT 2
-#define PRF_CPU_DISABLE_SUPPORT 3
-
-/* --------------------- OS Features -------------------------------*/
-
-/*
- * The following defines OS features that are optionally present in
- * the operating system.
- * During boot, PROM is notified of these features via a series of calls:
- *
- * ia64_sn_set_os_feature(feature1);
- *
- * Once enabled, a feature cannot be disabled.
- *
- * By default, features are disabled unless explicitly enabled.
- *
- * These defines must be kept in sync with the corresponding
- * PROM definitions in feature_sets.h.
- */
-#define OSF_MCA_SLV_TO_OS_INIT_SLV 0
-#define OSF_FEAT_LOG_SBES 1
-#define OSF_ACPI_ENABLE 2
-#define OSF_PCISEGMENT_ENABLE 3
-
-
-#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
diff --git a/arch/ia64/include/asm/sn/sn_sal.h b/arch/ia64/include/asm/sn/sn_sal.h
index 1f5ff470a5a1..d437aa43343b 100644
--- a/arch/ia64/include/asm/sn/sn_sal.h
+++ b/arch/ia64/include/asm/sn/sn_sal.h
@@ -11,140 +11,17 @@
* Copyright (c) 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
-
+#include <linux/types.h>
#include <asm/sal.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/shub_mmr.h>
// SGI Specific Calls
-#define SN_SAL_POD_MODE 0x02000001
-#define SN_SAL_SYSTEM_RESET 0x02000002
-#define SN_SAL_PROBE 0x02000003
-#define SN_SAL_GET_MASTER_NASID 0x02000004
-#define SN_SAL_GET_KLCONFIG_ADDR 0x02000005
-#define SN_SAL_LOG_CE 0x02000006
-#define SN_SAL_REGISTER_CE 0x02000007
#define SN_SAL_GET_PARTITION_ADDR 0x02000009
-#define SN_SAL_XP_ADDR_REGION 0x0200000f
-#define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010
-#define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011
-#define SN_SAL_PRINT_ERROR 0x02000012
-#define SN_SAL_REGISTER_PMI_HANDLER 0x02000014
-#define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant
-#define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant
-#define SN_SAL_GET_SAPIC_INFO 0x0200001d
-#define SN_SAL_GET_SN_INFO 0x0200001e
-#define SN_SAL_CONSOLE_PUTC 0x02000021
-#define SN_SAL_CONSOLE_GETC 0x02000022
-#define SN_SAL_CONSOLE_PUTS 0x02000023
-#define SN_SAL_CONSOLE_GETS 0x02000024
-#define SN_SAL_CONSOLE_GETS_TIMEOUT 0x02000025
-#define SN_SAL_CONSOLE_POLL 0x02000026
-#define SN_SAL_CONSOLE_INTR 0x02000027
-#define SN_SAL_CONSOLE_PUTB 0x02000028
-#define SN_SAL_CONSOLE_XMIT_CHARS 0x0200002a
-#define SN_SAL_CONSOLE_READC 0x0200002b
-#define SN_SAL_SYSCTL_OP 0x02000030
-#define SN_SAL_SYSCTL_MODID_GET 0x02000031
-#define SN_SAL_SYSCTL_GET 0x02000032
-#define SN_SAL_SYSCTL_IOBRICK_MODULE_GET 0x02000033
-#define SN_SAL_SYSCTL_IO_PORTSPEED_GET 0x02000035
-#define SN_SAL_SYSCTL_SLAB_GET 0x02000036
-#define SN_SAL_BUS_CONFIG 0x02000037
-#define SN_SAL_SYS_SERIAL_GET 0x02000038
-#define SN_SAL_PARTITION_SERIAL_GET 0x02000039
-#define SN_SAL_SYSCTL_PARTITION_GET 0x0200003a
-#define SN_SAL_SYSTEM_POWER_DOWN 0x0200003b
-#define SN_SAL_GET_MASTER_BASEIO_NASID 0x0200003c
-#define SN_SAL_COHERENCE 0x0200003d
#define SN_SAL_MEMPROTECT 0x0200003e
-#define SN_SAL_SYSCTL_FRU_CAPTURE 0x0200003f
-
-#define SN_SAL_SYSCTL_IOBRICK_PCI_OP 0x02000042 // reentrant
-#define SN_SAL_IROUTER_OP 0x02000043
-#define SN_SAL_SYSCTL_EVENT 0x02000044
-#define SN_SAL_IOIF_INTERRUPT 0x0200004a
-#define SN_SAL_HWPERF_OP 0x02000050 // lock
-#define SN_SAL_IOIF_ERROR_INTERRUPT 0x02000051
-#define SN_SAL_IOIF_PCI_SAFE 0x02000052
-#define SN_SAL_IOIF_SLOT_ENABLE 0x02000053
-#define SN_SAL_IOIF_SLOT_DISABLE 0x02000054
-#define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055
-#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
-#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
-#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated
-#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a
-
-#define SN_SAL_IOIF_INIT 0x0200005f
-#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
-#define SN_SAL_BTE_RECOVER 0x02000061
-#define SN_SAL_RESERVED_DO_NOT_USE 0x02000062
-#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000064
-
-#define SN_SAL_GET_PROM_FEATURE_SET 0x02000065
-#define SN_SAL_SET_OS_FEATURE_SET 0x02000066
-#define SN_SAL_INJECT_ERROR 0x02000067
-#define SN_SAL_SET_CPU_NUMBER 0x02000068
-#define SN_SAL_KERNEL_LAUNCH_EVENT 0x02000069
#define SN_SAL_WATCHLIST_ALLOC 0x02000070
#define SN_SAL_WATCHLIST_FREE 0x02000071
/*
- * Service-specific constants
- */
-
-/* Console interrupt manipulation */
- /* action codes */
-#define SAL_CONSOLE_INTR_OFF 0 /* turn the interrupt off */
-#define SAL_CONSOLE_INTR_ON 1 /* turn the interrupt on */
-#define SAL_CONSOLE_INTR_STATUS 2 /* retrieve the interrupt status */
- /* interrupt specification & status return codes */
-#define SAL_CONSOLE_INTR_XMIT 1 /* output interrupt */
-#define SAL_CONSOLE_INTR_RECV 2 /* input interrupt */
-
-/* interrupt handling */
-#define SAL_INTR_ALLOC 1
-#define SAL_INTR_FREE 2
-#define SAL_INTR_REDIRECT 3
-
-/*
- * operations available on the generic SN_SAL_SYSCTL_OP
- * runtime service
- */
-#define SAL_SYSCTL_OP_IOBOARD 0x0001 /* retrieve board type */
-#define SAL_SYSCTL_OP_TIO_JLCK_RST 0x0002 /* issue TIO clock reset */
-
-/*
- * IRouter (i.e. generalized system controller) operations
- */
-#define SAL_IROUTER_OPEN 0 /* open a subchannel */
-#define SAL_IROUTER_CLOSE 1 /* close a subchannel */
-#define SAL_IROUTER_SEND 2 /* send part of an IRouter packet */
-#define SAL_IROUTER_RECV 3 /* receive part of an IRouter packet */
-#define SAL_IROUTER_INTR_STATUS 4 /* check the interrupt status for
- * an open subchannel
- */
-#define SAL_IROUTER_INTR_ON 5 /* enable an interrupt */
-#define SAL_IROUTER_INTR_OFF 6 /* disable an interrupt */
-#define SAL_IROUTER_INIT 7 /* initialize IRouter driver */
-
-/* IRouter interrupt mask bits */
-#define SAL_IROUTER_INTR_XMIT SAL_CONSOLE_INTR_XMIT
-#define SAL_IROUTER_INTR_RECV SAL_CONSOLE_INTR_RECV
-
-/*
- * Error Handling Features
- */
-#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV 0x1 // obsolete
-#define SAL_ERR_FEAT_LOG_SBES 0x2 // obsolete
-#define SAL_ERR_FEAT_MFR_OVERRIDE 0x4
-#define SAL_ERR_FEAT_SBE_THRESHOLD 0xffff0000
-
-/*
* SAL Error Codes
*/
#define SALRET_MORE_PASSES 1
@@ -153,458 +30,6 @@
#define SALRET_INVALID_ARG (-2)
#define SALRET_ERROR (-3)
-#define SN_SAL_FAKE_PROM 0x02009999
-
-/**
- * sn_sal_revision - get the SGI SAL revision number
- *
- * The SGI PROM stores its version in the sal_[ab]_rev_(major|minor).
- * This routine simply extracts the major and minor values and
- * presents them in a u32 format.
- *
- * For example, version 4.05 would be represented at 0x0405.
- */
-static inline u32
-sn_sal_rev(void)
-{
- struct ia64_sal_systab *systab = __va(efi.sal_systab);
-
- return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
-}
-
-/*
- * Returns the master console nasid, if the call fails, return an illegal
- * value.
- */
-static inline u64
-ia64_sn_get_console_nasid(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL(ret_stuff, SN_SAL_GET_MASTER_NASID, 0, 0, 0, 0, 0, 0, 0);
-
- if (ret_stuff.status < 0)
- return ret_stuff.status;
-
- /* Master console nasid is in 'v0' */
- return ret_stuff.v0;
-}
-
-/*
- * Returns the master baseio nasid, if the call fails, return an illegal
- * value.
- */
-static inline u64
-ia64_sn_get_master_baseio_nasid(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL(ret_stuff, SN_SAL_GET_MASTER_BASEIO_NASID, 0, 0, 0, 0, 0, 0, 0);
-
- if (ret_stuff.status < 0)
- return ret_stuff.status;
-
- /* Master baseio nasid is in 'v0' */
- return ret_stuff.v0;
-}
-
-static inline void *
-ia64_sn_get_klconfig_addr(nasid_t nasid)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR, (u64)nasid, 0, 0, 0, 0, 0, 0);
- return ret_stuff.v0 ? __va(ret_stuff.v0) : NULL;
-}
-
-/*
- * Returns the next console character.
- */
-static inline u64
-ia64_sn_console_getc(int *ch)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_GETC, 0, 0, 0, 0, 0, 0, 0);
-
- /* character is in 'v0' */
- *ch = (int)ret_stuff.v0;
-
- return ret_stuff.status;
-}
-
-/*
- * Read a character from the SAL console device, after a previous interrupt
- * or poll operation has given us to know that a character is available
- * to be read.
- */
-static inline u64
-ia64_sn_console_readc(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_READC, 0, 0, 0, 0, 0, 0, 0);
-
- /* character is in 'v0' */
- return ret_stuff.v0;
-}
-
-/*
- * Sends the given character to the console.
- */
-static inline u64
-ia64_sn_console_putc(char ch)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (u64)ch, 0, 0, 0, 0, 0, 0);
-
- return ret_stuff.status;
-}
-
-/*
- * Sends the given buffer to the console.
- */
-static inline u64
-ia64_sn_console_putb(const char *buf, int len)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (u64)buf, (u64)len, 0, 0, 0, 0, 0);
-
- if ( ret_stuff.status == 0 ) {
- return ret_stuff.v0;
- }
- return (u64)0;
-}
-
-/*
- * Print a platform error record
- */
-static inline u64
-ia64_sn_plat_specific_err_print(int (*hook)(const char*, ...), char *rec)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (u64)hook, (u64)rec, 0, 0, 0, 0, 0);
-
- return ret_stuff.status;
-}
-
-/*
- * Check for Platform errors
- */
-static inline u64
-ia64_sn_plat_cpei_handler(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_LOG_CE, 0, 0, 0, 0, 0, 0, 0);
-
- return ret_stuff.status;
-}
-
-/*
- * Set Error Handling Features (Obsolete)
- */
-static inline u64
-ia64_sn_plat_set_error_handling_features(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_REENTRANT(ret_stuff, SN_SAL_SET_ERROR_HANDLING_FEATURES,
- SAL_ERR_FEAT_LOG_SBES,
- 0, 0, 0, 0, 0, 0);
-
- return ret_stuff.status;
-}
-
-/*
- * Checks for console input.
- */
-static inline u64
-ia64_sn_console_check(int *result)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_POLL, 0, 0, 0, 0, 0, 0, 0);
-
- /* result is in 'v0' */
- *result = (int)ret_stuff.v0;
-
- return ret_stuff.status;
-}
-
-/*
- * Checks console interrupt status
- */
-static inline u64
-ia64_sn_console_intr_status(void)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR,
- 0, SAL_CONSOLE_INTR_STATUS,
- 0, 0, 0, 0, 0);
-
- if (ret_stuff.status == 0) {
- return ret_stuff.v0;
- }
-
- return 0;
-}
-
-/*
- * Enable an interrupt on the SAL console device.
- */
-static inline void
-ia64_sn_console_intr_enable(u64 intr)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR,
- intr, SAL_CONSOLE_INTR_ON,
- 0, 0, 0, 0, 0);
-}
-
-/*
- * Disable an interrupt on the SAL console device.
- */
-static inline void
-ia64_sn_console_intr_disable(u64 intr)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR,
- intr, SAL_CONSOLE_INTR_OFF,
- 0, 0, 0, 0, 0);
-}
-
-/*
- * Sends a character buffer to the console asynchronously.
- */
-static inline u64
-ia64_sn_console_xmit_chars(char *buf, int len)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_XMIT_CHARS,
- (u64)buf, (u64)len,
- 0, 0, 0, 0, 0);
-
- if (ret_stuff.status == 0) {
- return ret_stuff.v0;
- }
-
- return 0;
-}
-
-/*
- * Returns the iobrick module Id
- */
-static inline u64
-ia64_sn_sysctl_iobrick_module_get(nasid_t nasid, int *result)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SYSCTL_IOBRICK_MODULE_GET, nasid, 0, 0, 0, 0, 0, 0);
-
- /* result is in 'v0' */
- *result = (int)ret_stuff.v0;
-
- return ret_stuff.status;
-}
-
-/**
- * ia64_sn_pod_mode - call the SN_SAL_POD_MODE function
- *
- * SN_SAL_POD_MODE actually takes an argument, but it's always
- * 0 when we call it from the kernel, so we don't have to expose
- * it to the caller.
- */
-static inline u64
-ia64_sn_pod_mode(void)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_REENTRANT(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0);
- if (isrv.status)
- return 0;
- return isrv.v0;
-}
-
-/**
- * ia64_sn_probe_mem - read from memory safely
- * @addr: address to probe
- * @size: number bytes to read (1,2,4,8)
- * @data_ptr: address to store value read by probe (-1 returned if probe fails)
- *
- * Call into the SAL to do a memory read. If the read generates a machine
- * check, this routine will recover gracefully and return -1 to the caller.
- * @addr is usually a kernel virtual address in uncached space (i.e. the
- * address starts with 0xc), but if called in physical mode, @addr should
- * be a physical address.
- *
- * Return values:
- * 0 - probe successful
- * 1 - probe failed (generated MCA)
- * 2 - Bad arg
- * <0 - PAL error
- */
-static inline u64
-ia64_sn_probe_mem(long addr, long size, void *data_ptr)
-{
- struct ia64_sal_retval isrv;
-
- SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0);
-
- if (data_ptr) {
- switch (size) {
- case 1:
- *((u8*)data_ptr) = (u8)isrv.v0;
- break;
- case 2:
- *((u16*)data_ptr) = (u16)isrv.v0;
- break;
- case 4:
- *((u32*)data_ptr) = (u32)isrv.v0;
- break;
- case 8:
- *((u64*)data_ptr) = (u64)isrv.v0;
- break;
- default:
- isrv.status = 2;
- }
- }
- return isrv.status;
-}
-
-/*
- * Retrieve the system serial number as an ASCII string.
- */
-static inline u64
-ia64_sn_sys_serial_get(char *buf)
-{
- struct ia64_sal_retval ret_stuff;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SYS_SERIAL_GET, buf, 0, 0, 0, 0, 0, 0);
- return ret_stuff.status;
-}
-
-extern char sn_system_serial_number_string[];
-extern u64 sn_partition_serial_number;
-
-static inline char *
-sn_system_serial_number(void) {
- if (sn_system_serial_number_string[0]) {
- return(sn_system_serial_number_string);
- } else {
- ia64_sn_sys_serial_get(sn_system_serial_number_string);
- return(sn_system_serial_number_string);
- }
-}
-
-
-/*
- * Returns a unique id number for this system and partition (suitable for
- * use with license managers), based in part on the system serial number.
- */
-static inline u64
-ia64_sn_partition_serial_get(void)
-{
- struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall_reentrant(&ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0,
- 0, 0, 0, 0, 0, 0);
- if (ret_stuff.status != 0)
- return 0;
- return ret_stuff.v0;
-}
-
-static inline u64
-sn_partition_serial_number_val(void) {
- if (unlikely(sn_partition_serial_number == 0)) {
- sn_partition_serial_number = ia64_sn_partition_serial_get();
- }
- return sn_partition_serial_number;
-}
-
-/*
- * Returns the partition id of the nasid passed in as an argument,
- * or INVALID_PARTID if the partition id cannot be retrieved.
- */
-static inline partid_t
-ia64_sn_sysctl_partition_get(nasid_t nasid)
-{
- struct ia64_sal_retval ret_stuff;
- SAL_CALL(ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,
- 0, 0, 0, 0, 0, 0);
- if (ret_stuff.status != 0)
- return -1;
- return ((partid_t)ret_stuff.v0);
-}
-
/*
* Returns the physical address of the partition's reserved page through
* an iterative number of calls.
@@ -634,96 +59,6 @@ sn_partition_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
}
/*
- * Register or unregister a physical address range being referenced across
- * a partition boundary for which certain SAL errors should be scanned for,
- * cleaned up and ignored. This is of value for kernel partitioning code only.
- * Values for the operation argument:
- * 1 = register this address range with SAL
- * 0 = unregister this address range with SAL
- *
- * SAL maintains a reference count on an address range in case it is registered
- * multiple times.
- *
- * On success, returns the reference count of the address range after the SAL
- * call has performed the current registration/unregistration. Returns a
- * negative value if an error occurred.
- */
-static inline int
-sn_register_xp_addr_region(u64 paddr, u64 len, int operation)
-{
- struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall(&ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len,
- (u64)operation, 0, 0, 0, 0);
- return ret_stuff.status;
-}
-
-/*
- * Register or unregister an instruction range for which SAL errors should
- * be ignored. If an error occurs while in the registered range, SAL jumps
- * to return_addr after ignoring the error. Values for the operation argument:
- * 1 = register this instruction range with SAL
- * 0 = unregister this instruction range with SAL
- *
- * Returns 0 on success, or a negative value if an error occurred.
- */
-static inline int
-sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr,
- int virtual, int operation)
-{
- struct ia64_sal_retval ret_stuff;
- u64 call;
- if (virtual) {
- call = SN_SAL_NO_FAULT_ZONE_VIRTUAL;
- } else {
- call = SN_SAL_NO_FAULT_ZONE_PHYSICAL;
- }
- ia64_sal_oemcall(&ret_stuff, call, start_addr, end_addr, return_addr,
- (u64)1, 0, 0, 0);
- return ret_stuff.status;
-}
-
-/*
- * Register or unregister a function to handle a PMI received by a CPU.
- * Before calling the registered handler, SAL sets r1 to the value that
- * was passed in as the global_pointer.
- *
- * If the handler pointer is NULL, then the currently registered handler
- * will be unregistered.
- *
- * Returns 0 on success, or a negative value if an error occurred.
- */
-static inline int
-sn_register_pmi_handler(u64 handler, u64 global_pointer)
-{
- struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall(&ret_stuff, SN_SAL_REGISTER_PMI_HANDLER, handler,
- global_pointer, 0, 0, 0, 0, 0);
- return ret_stuff.status;
-}
-
-/*
- * Change or query the coherence domain for this partition. Each cpu-based
- * nasid is represented by a bit in an array of 64-bit words:
- * 0 = not in this partition's coherency domain
- * 1 = in this partition's coherency domain
- *
- * It is not possible for the local system's nasids to be removed from
- * the coherency domain. Purpose of the domain arguments:
- * new_domain = set the coherence domain to the given nasids
- * old_domain = return the current coherence domain
- *
- * Returns 0 on success, or a negative value if an error occurred.
- */
-static inline int
-sn_change_coherence(u64 *new_domain, u64 *old_domain)
-{
- struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
- (u64)old_domain, 0, 0, 0, 0, 0);
- return ret_stuff.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.
@@ -744,450 +79,6 @@ sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
#define SN_MEMPROT_ACCESS_CLASS_6 0x084080
#define SN_MEMPROT_ACCESS_CLASS_7 0x021080
-/*
- * Turns off system power.
- */
-static inline void
-ia64_sn_power_down(void)
-{
- struct ia64_sal_retval ret_stuff;
- SAL_CALL(ret_stuff, SN_SAL_SYSTEM_POWER_DOWN, 0, 0, 0, 0, 0, 0, 0);
- while(1)
- cpu_relax();
- /* never returns */
-}
-
-/**
- * ia64_sn_fru_capture - tell the system controller to capture hw state
- *
- * This routine will call the SAL which will tell the system controller(s)
- * to capture hw mmr information from each SHub in the system.
- */
-static inline u64
-ia64_sn_fru_capture(void)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SN_SAL_SYSCTL_FRU_CAPTURE, 0, 0, 0, 0, 0, 0, 0);
- if (isrv.status)
- return 0;
- return isrv.v0;
-}
-
-/*
- * Performs an operation on a PCI bus or slot -- power up, power down
- * or reset.
- */
-static inline u64
-ia64_sn_sysctl_iobrick_pci_op(nasid_t n, u64 connection_type,
- u64 bus, char slot,
- u64 action)
-{
- struct ia64_sal_retval rv = {0, 0, 0, 0};
-
- SAL_CALL_NOLOCK(rv, SN_SAL_SYSCTL_IOBRICK_PCI_OP, connection_type, n, action,
- bus, (u64) slot, 0, 0);
- if (rv.status)
- return rv.v0;
- return 0;
-}
-
-
-/*
- * Open a subchannel for sending arbitrary data to the system
- * controller network via the system controller device associated with
- * 'nasid'. Return the subchannel number or a negative error code.
- */
-static inline int
-ia64_sn_irtr_open(nasid_t nasid)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_OPEN, nasid,
- 0, 0, 0, 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Close system controller subchannel 'subch' previously opened on 'nasid'.
- */
-static inline int
-ia64_sn_irtr_close(nasid_t nasid, int subch)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_CLOSE,
- (u64) nasid, (u64) subch, 0, 0, 0, 0);
- return (int) rv.status;
-}
-
-/*
- * Read data from system controller associated with 'nasid' on
- * subchannel 'subch'. The buffer to be filled is pointed to by
- * 'buf', and its capacity is in the integer pointed to by 'len'. The
- * referent of 'len' is set to the number of bytes read by the SAL
- * call. The return value is either SALRET_OK (for bytes read) or
- * SALRET_ERROR (for error or "no data available").
- */
-static inline int
-ia64_sn_irtr_recv(nasid_t nasid, int subch, char *buf, int *len)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_RECV,
- (u64) nasid, (u64) subch, (u64) buf, (u64) len,
- 0, 0);
- return (int) rv.status;
-}
-
-/*
- * Write data to the system controller network via the system
- * controller associated with 'nasid' on suchannel 'subch'. The
- * buffer to be written out is pointed to by 'buf', and 'len' is the
- * number of bytes to be written. The return value is either the
- * number of bytes written (which could be zero) or a negative error
- * code.
- */
-static inline int
-ia64_sn_irtr_send(nasid_t nasid, int subch, char *buf, int len)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_SEND,
- (u64) nasid, (u64) subch, (u64) buf, (u64) len,
- 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Check whether any interrupts are pending for the system controller
- * associated with 'nasid' and its subchannel 'subch'. The return
- * value is a mask of pending interrupts (SAL_IROUTER_INTR_XMIT and/or
- * SAL_IROUTER_INTR_RECV).
- */
-static inline int
-ia64_sn_irtr_intr(nasid_t nasid, int subch)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_STATUS,
- (u64) nasid, (u64) subch, 0, 0, 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Enable the interrupt indicated by the intr parameter (either
- * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
- */
-static inline int
-ia64_sn_irtr_intr_enable(nasid_t nasid, int subch, u64 intr)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_ON,
- (u64) nasid, (u64) subch, intr, 0, 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Disable the interrupt indicated by the intr parameter (either
- * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
- */
-static inline int
-ia64_sn_irtr_intr_disable(nasid_t nasid, int subch, u64 intr)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_OFF,
- (u64) nasid, (u64) subch, intr, 0, 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Set up a node as the point of contact for system controller
- * environmental event delivery.
- */
-static inline int
-ia64_sn_sysctl_event_init(nasid_t nasid)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_EVENT, (u64) nasid,
- 0, 0, 0, 0, 0, 0);
- return (int) rv.v0;
-}
-
-/*
- * Ask the system controller on the specified nasid to reset
- * the CX corelet clock. Only valid on TIO nodes.
- */
-static inline int
-ia64_sn_sysctl_tio_clock_reset(nasid_t nasid)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_TIO_JLCK_RST,
- nasid, 0, 0, 0, 0, 0);
- if (rv.status != 0)
- return (int)rv.status;
- if (rv.v0 != 0)
- return (int)rv.v0;
-
- return 0;
-}
-
-/*
- * Get the associated ioboard type for a given nasid.
- */
-static inline long
-ia64_sn_sysctl_ioboard_get(nasid_t nasid, u16 *ioboard)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_REENTRANT(isrv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_IOBOARD,
- nasid, 0, 0, 0, 0, 0);
- if (isrv.v0 != 0) {
- *ioboard = isrv.v0;
- return isrv.status;
- }
- if (isrv.v1 != 0) {
- *ioboard = isrv.v1;
- return isrv.status;
- }
-
- return isrv.status;
-}
-
-/**
- * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
- * @nasid: NASID of node to read
- * @index: FIT entry index to be retrieved (0..n)
- * @fitentry: 16 byte buffer where FIT entry will be stored.
- * @banbuf: optional buffer for retrieving banner
- * @banlen: length of banner buffer
- *
- * Access to the physical PROM chips needs to be serialized since reads and
- * writes can't occur at the same time, so we need to call into the SAL when
- * we want to look at the FIT entries on the chips.
- *
- * Returns:
- * %SALRET_OK if ok
- * %SALRET_INVALID_ARG if index too big
- * %SALRET_NOT_IMPLEMENTED if running on older PROM
- * ??? if nasid invalid OR banner buffer not large enough
- */
-static inline int
-ia64_sn_get_fit_compt(u64 nasid, u64 index, void *fitentry, void *banbuf,
- u64 banlen)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_GET_FIT_COMPT, nasid, index, fitentry,
- banbuf, banlen, 0, 0);
- return (int) rv.status;
-}
-
-/*
- * Initialize the SAL components of the system controller
- * communication driver; specifically pass in a sizable buffer that
- * can be used for allocation of subchannel queues as new subchannels
- * are opened. "buf" points to the buffer, and "len" specifies its
- * length.
- */
-static inline int
-ia64_sn_irtr_init(nasid_t nasid, void *buf, int len)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INIT,
- (u64) nasid, (u64) buf, (u64) len, 0, 0, 0);
- return (int) rv.status;
-}
-
-/*
- * Returns the nasid, subnode & slice corresponding to a SAPIC ID
- *
- * In:
- * arg0 - SN_SAL_GET_SAPIC_INFO
- * arg1 - sapicid (lid >> 16)
- * Out:
- * v0 - nasid
- * v1 - subnode
- * v2 - slice
- */
-static inline u64
-ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SAPIC_INFO, sapicid, 0, 0, 0, 0, 0, 0);
-
-/***** BEGIN HACK - temp til old proms no longer supported ********/
- if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
- if (nasid) *nasid = sapicid & 0xfff;
- if (subnode) *subnode = (sapicid >> 13) & 1;
- if (slice) *slice = (sapicid >> 12) & 3;
- return 0;
- }
-/***** END HACK *******/
-
- if (ret_stuff.status < 0)
- return ret_stuff.status;
-
- if (nasid) *nasid = (int) ret_stuff.v0;
- if (subnode) *subnode = (int) ret_stuff.v1;
- if (slice) *slice = (int) ret_stuff.v2;
- return 0;
-}
-
-/*
- * Returns information about the HUB/SHUB.
- * In:
- * arg0 - SN_SAL_GET_SN_INFO
- * arg1 - 0 (other values reserved for future use)
- * Out:
- * v0
- * [7:0] - shub type (0=shub1, 1=shub2)
- * [15:8] - Log2 max number of nodes in entire system (includes
- * C-bricks, I-bricks, etc)
- * [23:16] - Log2 of nodes per sharing domain
- * [31:24] - partition ID
- * [39:32] - coherency_id
- * [47:40] - regionsize
- * v1
- * [15:0] - nasid mask (ex., 0x7ff for 11 bit nasid)
- * [23:15] - bit position of low nasid bit
- */
-static inline u64
-ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift,
- u8 *systemsize, u8 *sharing_domain_size, u8 *partid, u8 *coher, u8 *reg)
-{
- struct ia64_sal_retval ret_stuff;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- ret_stuff.v1 = 0;
- ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0);
-
-/***** BEGIN HACK - temp til old proms no longer supported ********/
- if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
- int nasid = get_sapicid() & 0xfff;
-#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL
-#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48
- if (shubtype) *shubtype = 0;
- if (nasid_bitmask) *nasid_bitmask = 0x7ff;
- if (nasid_shift) *nasid_shift = 38;
- if (systemsize) *systemsize = 10;
- if (sharing_domain_size) *sharing_domain_size = 8;
- if (partid) *partid = ia64_sn_sysctl_partition_get(nasid);
- if (coher) *coher = nasid >> 9;
- if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >>
- SH_SHUB_ID_NODES_PER_BIT_SHFT;
- return 0;
- }
-/***** END HACK *******/
-
- if (ret_stuff.status < 0)
- return ret_stuff.status;
-
- if (shubtype) *shubtype = ret_stuff.v0 & 0xff;
- if (systemsize) *systemsize = (ret_stuff.v0 >> 8) & 0xff;
- if (sharing_domain_size) *sharing_domain_size = (ret_stuff.v0 >> 16) & 0xff;
- if (partid) *partid = (ret_stuff.v0 >> 24) & 0xff;
- if (coher) *coher = (ret_stuff.v0 >> 32) & 0xff;
- if (reg) *reg = (ret_stuff.v0 >> 40) & 0xff;
- if (nasid_bitmask) *nasid_bitmask = (ret_stuff.v1 & 0xffff);
- if (nasid_shift) *nasid_shift = (ret_stuff.v1 >> 16) & 0xff;
- return 0;
-}
-
-/*
- * This is the access point to the Altix PROM hardware performance
- * and status monitoring interface. For info on using this, see
- * arch/ia64/include/asm/sn/sn2/sn_hwperf.h
- */
-static inline int
-ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
- u64 a3, u64 a4, int *v0)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_HWPERF_OP, (u64)nasid,
- opcode, a0, a1, a2, a3, a4);
- if (v0)
- *v0 = (int) rv.v0;
- return (int) rv.status;
-}
-
-static inline int
-ia64_sn_ioif_get_pci_topology(u64 buf, u64 len)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, buf, len, 0, 0, 0, 0, 0);
- return (int) rv.status;
-}
-
-/*
- * BTE error recovery is implemented in SAL
- */
-static inline int
-ia64_sn_bte_recovery(nasid_t nasid)
-{
- struct ia64_sal_retval rv;
-
- rv.status = 0;
- SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, (u64)nasid, 0, 0, 0, 0, 0, 0);
- if (rv.status == SALRET_NOT_IMPLEMENTED)
- return 0;
- return (int) rv.status;
-}
-
-static inline int
-ia64_sn_is_fake_prom(void)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_FAKE_PROM, 0, 0, 0, 0, 0, 0, 0);
- return (rv.status == 0);
-}
-
-static inline int
-ia64_sn_get_prom_feature_set(int set, unsigned long *feature_set)
-{
- struct ia64_sal_retval rv;
-
- SAL_CALL_NOLOCK(rv, SN_SAL_GET_PROM_FEATURE_SET, set, 0, 0, 0, 0, 0, 0);
- if (rv.status != 0)
- return rv.status;
- *feature_set = rv.v0;
- return 0;
-}
-
-static inline int
-ia64_sn_set_os_feature(int feature)
-{
- struct ia64_sal_retval rv;
-
- SAL_CALL_NOLOCK(rv, SN_SAL_SET_OS_FEATURE_SET, feature, 0, 0, 0, 0, 0, 0);
- return rv.status;
-}
-
-static inline int
-sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
-{
- struct ia64_sal_retval ret_stuff;
-
- ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
- (u64)ecc, 0, 0, 0, 0);
- return ret_stuff.status;
-}
-
-static inline int
-ia64_sn_set_cpu_number(int cpu)
-{
- struct ia64_sal_retval rv;
-
- SAL_CALL_NOLOCK(rv, SN_SAL_SET_CPU_NUMBER, cpu, 0, 0, 0, 0, 0, 0);
- return rv.status;
-}
-static inline int
-ia64_sn_kernel_launch_event(void)
-{
- struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_KERNEL_LAUNCH_EVENT, 0, 0, 0, 0, 0, 0, 0);
- return rv.status;
-}
-
union sn_watchlist_u {
u64 val;
struct {
diff --git a/arch/ia64/include/asm/sn/tioca.h b/arch/ia64/include/asm/sn/tioca.h
deleted file mode 100644
index 666222d7f0f6..000000000000
--- a/arch/ia64/include/asm/sn/tioca.h
+++ /dev/null
@@ -1,596 +0,0 @@
-#ifndef _ASM_IA64_SN_TIO_TIOCA_H
-#define _ASM_IA64_SN_TIO_TIOCA_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.
- *
- * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-
-#define TIOCA_PART_NUM 0xE020
-#define TIOCA_MFGR_NUM 0x24
-#define TIOCA_REV_A 0x1
-
-/*
- * Register layout for TIO:CA. See below for bitmasks for each register.
- */
-
-struct tioca {
- u64 ca_id; /* 0x000000 */
- u64 ca_control1; /* 0x000008 */
- u64 ca_control2; /* 0x000010 */
- u64 ca_status1; /* 0x000018 */
- u64 ca_status2; /* 0x000020 */
- u64 ca_gart_aperature; /* 0x000028 */
- u64 ca_gfx_detach; /* 0x000030 */
- u64 ca_inta_dest_addr; /* 0x000038 */
- u64 ca_intb_dest_addr; /* 0x000040 */
- u64 ca_err_int_dest_addr; /* 0x000048 */
- u64 ca_int_status; /* 0x000050 */
- u64 ca_int_status_alias; /* 0x000058 */
- u64 ca_mult_error; /* 0x000060 */
- u64 ca_mult_error_alias; /* 0x000068 */
- u64 ca_first_error; /* 0x000070 */
- u64 ca_int_mask; /* 0x000078 */
- u64 ca_crm_pkterr_type; /* 0x000080 */
- u64 ca_crm_pkterr_type_alias; /* 0x000088 */
- u64 ca_crm_ct_error_detail_1; /* 0x000090 */
- u64 ca_crm_ct_error_detail_2; /* 0x000098 */
- u64 ca_crm_tnumto; /* 0x0000A0 */
- u64 ca_gart_err; /* 0x0000A8 */
- u64 ca_pcierr_type; /* 0x0000B0 */
- u64 ca_pcierr_addr; /* 0x0000B8 */
-
- u64 ca_pad_0000C0[3]; /* 0x0000{C0..D0} */
-
- u64 ca_pci_rd_buf_flush; /* 0x0000D8 */
- u64 ca_pci_dma_addr_extn; /* 0x0000E0 */
- u64 ca_agp_dma_addr_extn; /* 0x0000E8 */
- u64 ca_force_inta; /* 0x0000F0 */
- u64 ca_force_intb; /* 0x0000F8 */
- u64 ca_debug_vector_sel; /* 0x000100 */
- u64 ca_debug_mux_core_sel; /* 0x000108 */
- u64 ca_debug_mux_pci_sel; /* 0x000110 */
- u64 ca_debug_domain_sel; /* 0x000118 */
-
- u64 ca_pad_000120[28]; /* 0x0001{20..F8} */
-
- u64 ca_gart_ptr_table; /* 0x200 */
- u64 ca_gart_tlb_addr[8]; /* 0x2{08..40} */
-};
-
-/*
- * Mask/shift definitions for TIO:CA registers. The convention here is
- * to mainly use the names as they appear in the "TIO AEGIS Programmers'
- * Reference" with a CA_ prefix added. Some exceptions were made to fix
- * duplicate field names or to generalize fields that are common to
- * different registers (ca_debug_mux_core_sel and ca_debug_mux_pci_sel for
- * example).
- *
- * Fields consisting of a single bit have a single #define have a single
- * macro declaration to mask the bit. Fields consisting of multiple bits
- * have two declarations: one to mask the proper bits in a register, and
- * a second with the suffix "_SHFT" to identify how far the mask needs to
- * be shifted right to get its base value.
- */
-
-/* ==== ca_control1 */
-#define CA_SYS_BIG_END (1ull << 0)
-#define CA_DMA_AGP_SWAP (1ull << 1)
-#define CA_DMA_PCI_SWAP (1ull << 2)
-#define CA_PIO_IO_SWAP (1ull << 3)
-#define CA_PIO_MEM_SWAP (1ull << 4)
-#define CA_GFX_WR_SWAP (1ull << 5)
-#define CA_AGP_FW_ENABLE (1ull << 6)
-#define CA_AGP_CAL_CYCLE (0x7ull << 7)
-#define CA_AGP_CAL_CYCLE_SHFT 7
-#define CA_AGP_CAL_PRSCL_BYP (1ull << 10)
-#define CA_AGP_INIT_CAL_ENB (1ull << 11)
-#define CA_INJ_ADDR_PERR (1ull << 12)
-#define CA_INJ_DATA_PERR (1ull << 13)
- /* bits 15:14 unused */
-#define CA_PCIM_IO_NBE_AD (0x7ull << 16)
-#define CA_PCIM_IO_NBE_AD_SHFT 16
-#define CA_PCIM_FAST_BTB_ENB (1ull << 19)
- /* bits 23:20 unused */
-#define CA_PIO_ADDR_OFFSET (0xffull << 24)
-#define CA_PIO_ADDR_OFFSET_SHFT 24
- /* bits 35:32 unused */
-#define CA_AGPDMA_OP_COMBDELAY (0x1full << 36)
-#define CA_AGPDMA_OP_COMBDELAY_SHFT 36
- /* bit 41 unused */
-#define CA_AGPDMA_OP_ENB_COMBDELAY (1ull << 42)
-#define CA_PCI_INT_LPCNT (0xffull << 44)
-#define CA_PCI_INT_LPCNT_SHFT 44
- /* bits 63:52 unused */
-
-/* ==== ca_control2 */
-#define CA_AGP_LATENCY_TO (0xffull << 0)
-#define CA_AGP_LATENCY_TO_SHFT 0
-#define CA_PCI_LATENCY_TO (0xffull << 8)
-#define CA_PCI_LATENCY_TO_SHFT 8
-#define CA_PCI_MAX_RETRY (0x3ffull << 16)
-#define CA_PCI_MAX_RETRY_SHFT 16
- /* bits 27:26 unused */
-#define CA_RT_INT_EN (0x3ull << 28)
-#define CA_RT_INT_EN_SHFT 28
-#define CA_MSI_INT_ENB (1ull << 30)
-#define CA_PCI_ARB_ERR_ENB (1ull << 31)
-#define CA_GART_MEM_PARAM (0x3ull << 32)
-#define CA_GART_MEM_PARAM_SHFT 32
-#define CA_GART_RD_PREFETCH_ENB (1ull << 34)
-#define CA_GART_WR_PREFETCH_ENB (1ull << 35)
-#define CA_GART_FLUSH_TLB (1ull << 36)
- /* bits 39:37 unused */
-#define CA_CRM_TNUMTO_PERIOD (0x1fffull << 40)
-#define CA_CRM_TNUMTO_PERIOD_SHFT 40
- /* bits 55:53 unused */
-#define CA_CRM_TNUMTO_ENB (1ull << 56)
-#define CA_CRM_PRESCALER_BYP (1ull << 57)
- /* bits 59:58 unused */
-#define CA_CRM_MAX_CREDIT (0x7ull << 60)
-#define CA_CRM_MAX_CREDIT_SHFT 60
- /* bit 63 unused */
-
-/* ==== ca_status1 */
-#define CA_CORELET_ID (0x3ull << 0)
-#define CA_CORELET_ID_SHFT 0
-#define CA_INTA_N (1ull << 2)
-#define CA_INTB_N (1ull << 3)
-#define CA_CRM_CREDIT_AVAIL (0x7ull << 4)
-#define CA_CRM_CREDIT_AVAIL_SHFT 4
- /* bit 7 unused */
-#define CA_CRM_SPACE_AVAIL (0x7full << 8)
-#define CA_CRM_SPACE_AVAIL_SHFT 8
- /* bit 15 unused */
-#define CA_GART_TLB_VAL (0xffull << 16)
-#define CA_GART_TLB_VAL_SHFT 16
- /* bits 63:24 unused */
-
-/* ==== ca_status2 */
-#define CA_GFX_CREDIT_AVAIL (0xffull << 0)
-#define CA_GFX_CREDIT_AVAIL_SHFT 0
-#define CA_GFX_OPQ_AVAIL (0xffull << 8)
-#define CA_GFX_OPQ_AVAIL_SHFT 8
-#define CA_GFX_WRBUFF_AVAIL (0xffull << 16)
-#define CA_GFX_WRBUFF_AVAIL_SHFT 16
-#define CA_ADMA_OPQ_AVAIL (0xffull << 24)
-#define CA_ADMA_OPQ_AVAIL_SHFT 24
-#define CA_ADMA_WRBUFF_AVAIL (0xffull << 32)
-#define CA_ADMA_WRBUFF_AVAIL_SHFT 32
-#define CA_ADMA_RDBUFF_AVAIL (0x7full << 40)
-#define CA_ADMA_RDBUFF_AVAIL_SHFT 40
-#define CA_PCI_PIO_OP_STAT (1ull << 47)
-#define CA_PDMA_OPQ_AVAIL (0xfull << 48)
-#define CA_PDMA_OPQ_AVAIL_SHFT 48
-#define CA_PDMA_WRBUFF_AVAIL (0xfull << 52)
-#define CA_PDMA_WRBUFF_AVAIL_SHFT 52
-#define CA_PDMA_RDBUFF_AVAIL (0x3ull << 56)
-#define CA_PDMA_RDBUFF_AVAIL_SHFT 56
- /* bits 63:58 unused */
-
-/* ==== ca_gart_aperature */
-#define CA_GART_AP_ENB_AGP (1ull << 0)
-#define CA_GART_PAGE_SIZE (1ull << 1)
-#define CA_GART_AP_ENB_PCI (1ull << 2)
- /* bits 11:3 unused */
-#define CA_GART_AP_SIZE (0x3ffull << 12)
-#define CA_GART_AP_SIZE_SHFT 12
-#define CA_GART_AP_BASE (0x3ffffffffffull << 22)
-#define CA_GART_AP_BASE_SHFT 22
-
-/* ==== ca_inta_dest_addr
- ==== ca_intb_dest_addr
- ==== ca_err_int_dest_addr */
- /* bits 2:0 unused */
-#define CA_INT_DEST_ADDR (0x7ffffffffffffull << 3)
-#define CA_INT_DEST_ADDR_SHFT 3
- /* bits 55:54 unused */
-#define CA_INT_DEST_VECT (0xffull << 56)
-#define CA_INT_DEST_VECT_SHFT 56
-
-/* ==== ca_int_status */
-/* ==== ca_int_status_alias */
-/* ==== ca_mult_error */
-/* ==== ca_mult_error_alias */
-/* ==== ca_first_error */
-/* ==== ca_int_mask */
-#define CA_PCI_ERR (1ull << 0)
- /* bits 3:1 unused */
-#define CA_GART_FETCH_ERR (1ull << 4)
-#define CA_GFX_WR_OVFLW (1ull << 5)
-#define CA_PIO_REQ_OVFLW (1ull << 6)
-#define CA_CRM_PKTERR (1ull << 7)
-#define CA_CRM_DVERR (1ull << 8)
-#define CA_TNUMTO (1ull << 9)
-#define CA_CXM_RSP_CRED_OVFLW (1ull << 10)
-#define CA_CXM_REQ_CRED_OVFLW (1ull << 11)
-#define CA_PIO_INVALID_ADDR (1ull << 12)
-#define CA_PCI_ARB_TO (1ull << 13)
-#define CA_AGP_REQ_OFLOW (1ull << 14)
-#define CA_SBA_TYPE1_ERR (1ull << 15)
- /* bit 16 unused */
-#define CA_INTA (1ull << 17)
-#define CA_INTB (1ull << 18)
-#define CA_MULT_INTA (1ull << 19)
-#define CA_MULT_INTB (1ull << 20)
-#define CA_GFX_CREDIT_OVFLW (1ull << 21)
- /* bits 63:22 unused */
-
-/* ==== ca_crm_pkterr_type */
-/* ==== ca_crm_pkterr_type_alias */
-#define CA_CRM_PKTERR_SBERR_HDR (1ull << 0)
-#define CA_CRM_PKTERR_DIDN (1ull << 1)
-#define CA_CRM_PKTERR_PACTYPE (1ull << 2)
-#define CA_CRM_PKTERR_INV_TNUM (1ull << 3)
-#define CA_CRM_PKTERR_ADDR_RNG (1ull << 4)
-#define CA_CRM_PKTERR_ADDR_ALGN (1ull << 5)
-#define CA_CRM_PKTERR_HDR_PARAM (1ull << 6)
-#define CA_CRM_PKTERR_CW_ERR (1ull << 7)
-#define CA_CRM_PKTERR_SBERR_NH (1ull << 8)
-#define CA_CRM_PKTERR_EARLY_TERM (1ull << 9)
-#define CA_CRM_PKTERR_EARLY_TAIL (1ull << 10)
-#define CA_CRM_PKTERR_MSSNG_TAIL (1ull << 11)
-#define CA_CRM_PKTERR_MSSNG_HDR (1ull << 12)
- /* bits 15:13 unused */
-#define CA_FIRST_CRM_PKTERR_SBERR_HDR (1ull << 16)
-#define CA_FIRST_CRM_PKTERR_DIDN (1ull << 17)
-#define CA_FIRST_CRM_PKTERR_PACTYPE (1ull << 18)
-#define CA_FIRST_CRM_PKTERR_INV_TNUM (1ull << 19)
-#define CA_FIRST_CRM_PKTERR_ADDR_RNG (1ull << 20)
-#define CA_FIRST_CRM_PKTERR_ADDR_ALGN (1ull << 21)
-#define CA_FIRST_CRM_PKTERR_HDR_PARAM (1ull << 22)
-#define CA_FIRST_CRM_PKTERR_CW_ERR (1ull << 23)
-#define CA_FIRST_CRM_PKTERR_SBERR_NH (1ull << 24)
-#define CA_FIRST_CRM_PKTERR_EARLY_TERM (1ull << 25)
-#define CA_FIRST_CRM_PKTERR_EARLY_TAIL (1ull << 26)
-#define CA_FIRST_CRM_PKTERR_MSSNG_TAIL (1ull << 27)
-#define CA_FIRST_CRM_PKTERR_MSSNG_HDR (1ull << 28)
- /* bits 63:29 unused */
-
-/* ==== ca_crm_ct_error_detail_1 */
-#define CA_PKT_TYPE (0xfull << 0)
-#define CA_PKT_TYPE_SHFT 0
-#define CA_SRC_ID (0x3ull << 4)
-#define CA_SRC_ID_SHFT 4
-#define CA_DATA_SZ (0x3ull << 6)
-#define CA_DATA_SZ_SHFT 6
-#define CA_TNUM (0xffull << 8)
-#define CA_TNUM_SHFT 8
-#define CA_DW_DATA_EN (0xffull << 16)
-#define CA_DW_DATA_EN_SHFT 16
-#define CA_GFX_CRED (0xffull << 24)
-#define CA_GFX_CRED_SHFT 24
-#define CA_MEM_RD_PARAM (0x3ull << 32)
-#define CA_MEM_RD_PARAM_SHFT 32
-#define CA_PIO_OP (1ull << 34)
-#define CA_CW_ERR (1ull << 35)
- /* bits 62:36 unused */
-#define CA_VALID (1ull << 63)
-
-/* ==== ca_crm_ct_error_detail_2 */
- /* bits 2:0 unused */
-#define CA_PKT_ADDR (0x1fffffffffffffull << 3)
-#define CA_PKT_ADDR_SHFT 3
- /* bits 63:56 unused */
-
-/* ==== ca_crm_tnumto */
-#define CA_CRM_TNUMTO_VAL (0xffull << 0)
-#define CA_CRM_TNUMTO_VAL_SHFT 0
-#define CA_CRM_TNUMTO_WR (1ull << 8)
- /* bits 63:9 unused */
-
-/* ==== ca_gart_err */
-#define CA_GART_ERR_SOURCE (0x3ull << 0)
-#define CA_GART_ERR_SOURCE_SHFT 0
- /* bits 3:2 unused */
-#define CA_GART_ERR_ADDR (0xfffffffffull << 4)
-#define CA_GART_ERR_ADDR_SHFT 4
- /* bits 63:40 unused */
-
-/* ==== ca_pcierr_type */
-#define CA_PCIERR_DATA (0xffffffffull << 0)
-#define CA_PCIERR_DATA_SHFT 0
-#define CA_PCIERR_ENB (0xfull << 32)
-#define CA_PCIERR_ENB_SHFT 32
-#define CA_PCIERR_CMD (0xfull << 36)
-#define CA_PCIERR_CMD_SHFT 36
-#define CA_PCIERR_A64 (1ull << 40)
-#define CA_PCIERR_SLV_SERR (1ull << 41)
-#define CA_PCIERR_SLV_WR_PERR (1ull << 42)
-#define CA_PCIERR_SLV_RD_PERR (1ull << 43)
-#define CA_PCIERR_MST_SERR (1ull << 44)
-#define CA_PCIERR_MST_WR_PERR (1ull << 45)
-#define CA_PCIERR_MST_RD_PERR (1ull << 46)
-#define CA_PCIERR_MST_MABT (1ull << 47)
-#define CA_PCIERR_MST_TABT (1ull << 48)
-#define CA_PCIERR_MST_RETRY_TOUT (1ull << 49)
-
-#define CA_PCIERR_TYPES \
- (CA_PCIERR_A64|CA_PCIERR_SLV_SERR| \
- CA_PCIERR_SLV_WR_PERR|CA_PCIERR_SLV_RD_PERR| \
- CA_PCIERR_MST_SERR|CA_PCIERR_MST_WR_PERR|CA_PCIERR_MST_RD_PERR| \
- CA_PCIERR_MST_MABT|CA_PCIERR_MST_TABT|CA_PCIERR_MST_RETRY_TOUT)
-
- /* bits 63:50 unused */
-
-/* ==== ca_pci_dma_addr_extn */
-#define CA_UPPER_NODE_OFFSET (0x3full << 0)
-#define CA_UPPER_NODE_OFFSET_SHFT 0
- /* bits 7:6 unused */
-#define CA_CHIPLET_ID (0x3ull << 8)
-#define CA_CHIPLET_ID_SHFT 8
- /* bits 11:10 unused */
-#define CA_PCI_DMA_NODE_ID (0xffffull << 12)
-#define CA_PCI_DMA_NODE_ID_SHFT 12
- /* bits 27:26 unused */
-#define CA_PCI_DMA_PIO_MEM_TYPE (1ull << 28)
- /* bits 63:29 unused */
-
-
-/* ==== ca_agp_dma_addr_extn */
- /* bits 19:0 unused */
-#define CA_AGP_DMA_NODE_ID (0xffffull << 20)
-#define CA_AGP_DMA_NODE_ID_SHFT 20
- /* bits 27:26 unused */
-#define CA_AGP_DMA_PIO_MEM_TYPE (1ull << 28)
- /* bits 63:29 unused */
-
-/* ==== ca_debug_vector_sel */
-#define CA_DEBUG_MN_VSEL (0xfull << 0)
-#define CA_DEBUG_MN_VSEL_SHFT 0
-#define CA_DEBUG_PP_VSEL (0xfull << 4)
-#define CA_DEBUG_PP_VSEL_SHFT 4
-#define CA_DEBUG_GW_VSEL (0xfull << 8)
-#define CA_DEBUG_GW_VSEL_SHFT 8
-#define CA_DEBUG_GT_VSEL (0xfull << 12)
-#define CA_DEBUG_GT_VSEL_SHFT 12
-#define CA_DEBUG_PD_VSEL (0xfull << 16)
-#define CA_DEBUG_PD_VSEL_SHFT 16
-#define CA_DEBUG_AD_VSEL (0xfull << 20)
-#define CA_DEBUG_AD_VSEL_SHFT 20
-#define CA_DEBUG_CX_VSEL (0xfull << 24)
-#define CA_DEBUG_CX_VSEL_SHFT 24
-#define CA_DEBUG_CR_VSEL (0xfull << 28)
-#define CA_DEBUG_CR_VSEL_SHFT 28
-#define CA_DEBUG_BA_VSEL (0xfull << 32)
-#define CA_DEBUG_BA_VSEL_SHFT 32
-#define CA_DEBUG_PE_VSEL (0xfull << 36)
-#define CA_DEBUG_PE_VSEL_SHFT 36
-#define CA_DEBUG_BO_VSEL (0xfull << 40)
-#define CA_DEBUG_BO_VSEL_SHFT 40
-#define CA_DEBUG_BI_VSEL (0xfull << 44)
-#define CA_DEBUG_BI_VSEL_SHFT 44
-#define CA_DEBUG_AS_VSEL (0xfull << 48)
-#define CA_DEBUG_AS_VSEL_SHFT 48
-#define CA_DEBUG_PS_VSEL (0xfull << 52)
-#define CA_DEBUG_PS_VSEL_SHFT 52
-#define CA_DEBUG_PM_VSEL (0xfull << 56)
-#define CA_DEBUG_PM_VSEL_SHFT 56
- /* bits 63:60 unused */
-
-/* ==== ca_debug_mux_core_sel */
-/* ==== ca_debug_mux_pci_sel */
-#define CA_DEBUG_MSEL0 (0x7ull << 0)
-#define CA_DEBUG_MSEL0_SHFT 0
- /* bit 3 unused */
-#define CA_DEBUG_NSEL0 (0x7ull << 4)
-#define CA_DEBUG_NSEL0_SHFT 4
- /* bit 7 unused */
-#define CA_DEBUG_MSEL1 (0x7ull << 8)
-#define CA_DEBUG_MSEL1_SHFT 8
- /* bit 11 unused */
-#define CA_DEBUG_NSEL1 (0x7ull << 12)
-#define CA_DEBUG_NSEL1_SHFT 12
- /* bit 15 unused */
-#define CA_DEBUG_MSEL2 (0x7ull << 16)
-#define CA_DEBUG_MSEL2_SHFT 16
- /* bit 19 unused */
-#define CA_DEBUG_NSEL2 (0x7ull << 20)
-#define CA_DEBUG_NSEL2_SHFT 20
- /* bit 23 unused */
-#define CA_DEBUG_MSEL3 (0x7ull << 24)
-#define CA_DEBUG_MSEL3_SHFT 24
- /* bit 27 unused */
-#define CA_DEBUG_NSEL3 (0x7ull << 28)
-#define CA_DEBUG_NSEL3_SHFT 28
- /* bit 31 unused */
-#define CA_DEBUG_MSEL4 (0x7ull << 32)
-#define CA_DEBUG_MSEL4_SHFT 32
- /* bit 35 unused */
-#define CA_DEBUG_NSEL4 (0x7ull << 36)
-#define CA_DEBUG_NSEL4_SHFT 36
- /* bit 39 unused */
-#define CA_DEBUG_MSEL5 (0x7ull << 40)
-#define CA_DEBUG_MSEL5_SHFT 40
- /* bit 43 unused */
-#define CA_DEBUG_NSEL5 (0x7ull << 44)
-#define CA_DEBUG_NSEL5_SHFT 44
- /* bit 47 unused */
-#define CA_DEBUG_MSEL6 (0x7ull << 48)
-#define CA_DEBUG_MSEL6_SHFT 48
- /* bit 51 unused */
-#define CA_DEBUG_NSEL6 (0x7ull << 52)
-#define CA_DEBUG_NSEL6_SHFT 52
- /* bit 55 unused */
-#define CA_DEBUG_MSEL7 (0x7ull << 56)
-#define CA_DEBUG_MSEL7_SHFT 56
- /* bit 59 unused */
-#define CA_DEBUG_NSEL7 (0x7ull << 60)
-#define CA_DEBUG_NSEL7_SHFT 60
- /* bit 63 unused */
-
-
-/* ==== ca_debug_domain_sel */
-#define CA_DEBUG_DOMAIN_L (1ull << 0)
-#define CA_DEBUG_DOMAIN_H (1ull << 1)
- /* bits 63:2 unused */
-
-/* ==== ca_gart_ptr_table */
-#define CA_GART_PTR_VAL (1ull << 0)
- /* bits 11:1 unused */
-#define CA_GART_PTR_ADDR (0xfffffffffffull << 12)
-#define CA_GART_PTR_ADDR_SHFT 12
- /* bits 63:56 unused */
-
-/* ==== ca_gart_tlb_addr[0-7] */
-#define CA_GART_TLB_ADDR (0xffffffffffffffull << 0)
-#define CA_GART_TLB_ADDR_SHFT 0
- /* bits 62:56 unused */
-#define CA_GART_TLB_ENTRY_VAL (1ull << 63)
-
-/*
- * PIO address space ranges for TIO:CA
- */
-
-/* CA internal registers */
-#define CA_PIO_ADMIN 0x00000000
-#define CA_PIO_ADMIN_LEN 0x00010000
-
-/* GFX Write Buffer - Diagnostics */
-#define CA_PIO_GFX 0x00010000
-#define CA_PIO_GFX_LEN 0x00010000
-
-/* AGP DMA Write Buffer - Diagnostics */
-#define CA_PIO_AGP_DMAWRITE 0x00020000
-#define CA_PIO_AGP_DMAWRITE_LEN 0x00010000
-
-/* AGP DMA READ Buffer - Diagnostics */
-#define CA_PIO_AGP_DMAREAD 0x00030000
-#define CA_PIO_AGP_DMAREAD_LEN 0x00010000
-
-/* PCI Config Type 0 */
-#define CA_PIO_PCI_TYPE0_CONFIG 0x01000000
-#define CA_PIO_PCI_TYPE0_CONFIG_LEN 0x01000000
-
-/* PCI Config Type 1 */
-#define CA_PIO_PCI_TYPE1_CONFIG 0x02000000
-#define CA_PIO_PCI_TYPE1_CONFIG_LEN 0x01000000
-
-/* PCI I/O Cycles - mapped to PCI Address 0x00000000-0x04ffffff */
-#define CA_PIO_PCI_IO 0x03000000
-#define CA_PIO_PCI_IO_LEN 0x05000000
-
-/* PCI MEM Cycles - mapped to PCI with CA_PIO_ADDR_OFFSET of ca_control1 */
-/* use Fast Write if enabled and coretalk packet type is a GFX request */
-#define CA_PIO_PCI_MEM_OFFSET 0x08000000
-#define CA_PIO_PCI_MEM_OFFSET_LEN 0x08000000
-
-/* PCI MEM Cycles - mapped to PCI Address 0x00000000-0xbfffffff */
-/* use Fast Write if enabled and coretalk packet type is a GFX request */
-#define CA_PIO_PCI_MEM 0x40000000
-#define CA_PIO_PCI_MEM_LEN 0xc0000000
-
-/*
- * DMA space
- *
- * The CA aperature (ie. bus address range) mapped by the GART is segmented into
- * two parts. The lower portion of the aperature is used for mapping 32 bit
- * PCI addresses which are managed by the dma interfaces in this file. The
- * upper poprtion of the aperature is used for mapping 48 bit AGP addresses.
- * The AGP portion of the aperature is managed by the agpgart_be.c driver
- * in drivers/linux/agp. There are ca-specific hooks in that driver to
- * manipulate the gart, but management of the AGP portion of the aperature
- * is the responsibility of that driver.
- *
- * CA allows three main types of DMA mapping:
- *
- * PCI 64-bit Managed by this driver
- * PCI 32-bit Managed by this driver
- * AGP 48-bit Managed by hooks in the /dev/agpgart driver
- *
- * All of the above can optionally be remapped through the GART. The following
- * table lists the combinations of addressing types and GART remapping that
- * is currently supported by the driver (h/w supports all, s/w limits this):
- *
- * PCI64 PCI32 AGP48
- * GART no yes yes
- * Direct yes yes no
- *
- * GART remapping of PCI64 is not done because there is no need to. The
- * 64 bit PCI address holds all of the information necessary to target any
- * memory in the system.
- *
- * AGP48 is always mapped through the GART. Management of the AGP48 portion
- * of the aperature is the responsibility of code in the agpgart_be driver.
- *
- * The non-64 bit bus address space will currently be partitioned like this:
- *
- * 0xffff_ffff_ffff +--------
- * | AGP48 direct
- * | Space managed by this driver
- * CA_AGP_DIRECT_BASE +--------
- * | AGP GART mapped (gfx aperature)
- * | Space managed by /dev/agpgart driver
- * | This range is exposed to the agpgart
- * | driver as the "graphics aperature"
- * CA_AGP_MAPPED_BASE +-----
- * | PCI GART mapped
- * | Space managed by this driver
- * CA_PCI32_MAPPED_BASE +----
- * | PCI32 direct
- * | Space managed by this driver
- * 0xC000_0000 +--------
- * (CA_PCI32_DIRECT_BASE)
- *
- * The bus address range CA_PCI32_MAPPED_BASE through CA_AGP_DIRECT_BASE
- * is what we call the CA aperature. Addresses falling in this range will
- * be remapped using the GART.
- *
- * The bus address range CA_AGP_MAPPED_BASE through CA_AGP_DIRECT_BASE
- * is what we call the graphics aperature. This is a subset of the CA
- * aperature and is under the control of the agpgart_be driver.
- *
- * CA_PCI32_MAPPED_BASE, CA_AGP_MAPPED_BASE, and CA_AGP_DIRECT_BASE are
- * somewhat arbitrary values. The known constraints on choosing these is:
- *
- * 1) CA_AGP_DIRECT_BASE-CA_PCI32_MAPPED_BASE+1 (the CA aperature size)
- * must be one of the values supported by the ca_gart_aperature register.
- * Currently valid values are: 4MB through 4096MB in powers of 2 increments
- *
- * 2) CA_AGP_DIRECT_BASE-CA_AGP_MAPPED_BASE+1 (the gfx aperature size)
- * must be in MB units since that's what the agpgart driver assumes.
- */
-
-/*
- * Define Bus DMA ranges. These are configurable (see constraints above)
- * and will probably need tuning based on experience.
- */
-
-
-/*
- * 11/24/03
- * CA has an addressing glitch w.r.t. PCI direct 32 bit DMA that makes it
- * generally unusable. The problem is that for PCI direct 32
- * DMA's, all 32 bits of the bus address are used to form the lower 32 bits
- * of the coretalk address, and coretalk bits 38:32 come from a register.
- * Since only PCI bus addresses 0xC0000000-0xFFFFFFFF (1GB) are available
- * for DMA (the rest is allocated to PIO), host node addresses need to be
- * such that their lower 32 bits fall in the 0xC0000000-0xffffffff range
- * as well. So there can be no PCI32 direct DMA below 3GB!! For this
- * reason we set the CA_PCI32_DIRECT_SIZE to 0 which essentially makes
- * tioca_dma_direct32() a noop but preserves the code flow should this issue
- * be fixed in a respin.
- *
- * For now, all PCI32 DMA's must be mapped through the GART.
- */
-
-#define CA_PCI32_DIRECT_BASE 0xC0000000UL /* BASE not configurable */
-#define CA_PCI32_DIRECT_SIZE 0x00000000UL /* 0 MB */
-
-#define CA_PCI32_MAPPED_BASE 0xC0000000UL
-#define CA_PCI32_MAPPED_SIZE 0x40000000UL /* 2GB */
-
-#define CA_AGP_MAPPED_BASE 0x80000000UL
-#define CA_AGP_MAPPED_SIZE 0x40000000UL /* 2GB */
-
-#define CA_AGP_DIRECT_BASE 0x40000000UL /* 2GB */
-#define CA_AGP_DIRECT_SIZE 0x40000000UL
-
-#define CA_APERATURE_BASE (CA_AGP_MAPPED_BASE)
-#define CA_APERATURE_SIZE (CA_AGP_MAPPED_SIZE+CA_PCI32_MAPPED_SIZE)
-
-#endif /* _ASM_IA64_SN_TIO_TIOCA_H */
diff --git a/arch/ia64/include/asm/sn/tioca_provider.h b/arch/ia64/include/asm/sn/tioca_provider.h
deleted file mode 100644
index 9a820ac61be3..000000000000
--- a/arch/ia64/include/asm/sn/tioca_provider.h
+++ /dev/null
@@ -1,207 +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) 2003-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H
-#define _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H
-
-#include <asm/sn/tioca.h>
-
-/*
- * WAR enables
- * Defines for individual WARs. Each is a bitmask of applicable
- * part revision numbers. (1 << 1) == rev A, (1 << 2) == rev B,
- * (3 << 1) == (rev A or rev B), etc
- */
-
-#define TIOCA_WAR_ENABLED(pv, tioca_common) \
- ((1 << tioca_common->ca_rev) & pv)
-
- /* TIO:ICE:FRZ:Freezer loses a PIO data ucred on PIO RD RSP with CW error */
-#define PV907908 (1 << 1)
- /* ATI config space problems after BIOS execution starts */
-#define PV908234 (1 << 1)
- /* CA:AGPDMA write request data mismatch with ABC1CL merge */
-#define PV895469 (1 << 1)
- /* TIO:CA TLB invalidate of written GART entries possibly not occurring in CA*/
-#define PV910244 (1 << 1)
-
-struct tioca_dmamap{
- struct list_head cad_list; /* headed by ca_list */
-
- dma_addr_t cad_dma_addr; /* Linux dma handle */
- uint cad_gart_entry; /* start entry in ca_gart_pagemap */
- uint cad_gart_size; /* #entries for this map */
-};
-
-/*
- * Kernel only fields. Prom may look at this stuff for debugging only.
- * Access this structure through the ca_kernel_private ptr.
- */
-
-struct tioca_common ;
-
-struct tioca_kernel {
- struct tioca_common *ca_common; /* tioca this belongs to */
- struct list_head ca_list; /* list of all ca's */
- struct list_head ca_dmamaps;
- spinlock_t ca_lock; /* Kernel lock */
- cnodeid_t ca_closest_node;
- struct list_head *ca_devices; /* bus->devices */
-
- /*
- * General GART stuff
- */
- u64 ca_ap_size; /* size of aperature in bytes */
- u32 ca_gart_entries; /* # u64 entries in gart */
- u32 ca_ap_pagesize; /* aperature page size in bytes */
- u64 ca_ap_bus_base; /* bus address of CA aperature */
- u64 ca_gart_size; /* gart size in bytes */
- u64 *ca_gart; /* gart table vaddr */
- u64 ca_gart_coretalk_addr; /* gart coretalk addr */
- u8 ca_gart_iscoherent; /* used in tioca_tlbflush */
-
- /* PCI GART convenience values */
- u64 ca_pciap_base; /* pci aperature bus base address */
- u64 ca_pciap_size; /* pci aperature size (bytes) */
- u64 ca_pcigart_base; /* gfx GART bus base address */
- u64 *ca_pcigart; /* gfx GART vm address */
- u32 ca_pcigart_entries;
- u32 ca_pcigart_start; /* PCI start index in ca_gart */
- void *ca_pcigart_pagemap;
-
- /* AGP GART convenience values */
- u64 ca_gfxap_base; /* gfx aperature bus base address */
- u64 ca_gfxap_size; /* gfx aperature size (bytes) */
- u64 ca_gfxgart_base; /* gfx GART bus base address */
- u64 *ca_gfxgart; /* gfx GART vm address */
- u32 ca_gfxgart_entries;
- u32 ca_gfxgart_start; /* agpgart start index in ca_gart */
-};
-
-/*
- * Common tioca info shared between kernel and prom
- *
- * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES
- * TO THE PROM VERSION.
- */
-
-struct tioca_common {
- struct pcibus_bussoft ca_common; /* common pciio header */
-
- u32 ca_rev;
- u32 ca_closest_nasid;
-
- u64 ca_prom_private;
- u64 ca_kernel_private;
-};
-
-/**
- * tioca_paddr_to_gart - Convert an SGI coretalk address to a CA GART entry
- * @paddr: page address to convert
- *
- * Convert a system [coretalk] address to a GART entry. GART entries are
- * formed using the following:
- *
- * data = ( (1<<63) | ( (REMAP_NODE_ID << 40) | (MD_CHIPLET_ID << 38) |
- * (REMAP_SYS_ADDR) ) >> 12 )
- *
- * DATA written to 1 GART TABLE Entry in system memory is remapped system
- * addr for 1 page
- *
- * The data is for coretalk address format right shifted 12 bits with a
- * valid bit.
- *
- * GART_TABLE_ENTRY [ 25:0 ] -- REMAP_SYS_ADDRESS[37:12].
- * GART_TABLE_ENTRY [ 27:26 ] -- SHUB MD chiplet id.
- * GART_TABLE_ENTRY [ 41:28 ] -- REMAP_NODE_ID.
- * GART_TABLE_ENTRY [ 63 ] -- Valid Bit
- */
-static inline u64
-tioca_paddr_to_gart(unsigned long paddr)
-{
- /*
- * We are assuming right now that paddr already has the correct
- * format since the address from xtalk_dmaXXX should already have
- * NODE_ID, CHIPLET_ID, and SYS_ADDR in the correct locations.
- */
-
- return ((paddr) >> 12) | (1UL << 63);
-}
-
-/**
- * tioca_physpage_to_gart - Map a host physical page for SGI CA based DMA
- * @page_addr: system page address to map
- */
-
-static inline unsigned long
-tioca_physpage_to_gart(u64 page_addr)
-{
- u64 coretalk_addr;
-
- coretalk_addr = PHYS_TO_TIODMA(page_addr);
- if (!coretalk_addr) {
- return 0;
- }
-
- return tioca_paddr_to_gart(coretalk_addr);
-}
-
-/**
- * tioca_tlbflush - invalidate cached SGI CA GART TLB entries
- * @tioca_kernel: CA context
- *
- * Invalidate tlb entries for a given CA GART. Main complexity is to account
- * for revA bug.
- */
-static inline void
-tioca_tlbflush(struct tioca_kernel *tioca_kernel)
-{
- volatile u64 tmp;
- volatile struct tioca __iomem *ca_base;
- struct tioca_common *tioca_common;
-
- tioca_common = tioca_kernel->ca_common;
- ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
-
- /*
- * Explicit flushes not needed if GART is in cached mode
- */
- if (tioca_kernel->ca_gart_iscoherent) {
- if (TIOCA_WAR_ENABLED(PV910244, tioca_common)) {
- /*
- * PV910244: RevA CA needs explicit flushes.
- * Need to put GART into uncached mode before
- * flushing otherwise the explicit flush is ignored.
- *
- * Alternate WAR would be to leave GART cached and
- * touch every CL aligned GART entry.
- */
-
- __sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
- __sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
- __sn_setq_relaxed(&ca_base->ca_control2,
- (0x2ull << CA_GART_MEM_PARAM_SHFT));
- tmp = __sn_readq_relaxed(&ca_base->ca_control2);
- }
-
- return;
- }
-
- /*
- * Gart in uncached mode ... need an explicit flush.
- */
-
- __sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
- tmp = __sn_readq_relaxed(&ca_base->ca_control2);
-}
-
-extern u32 tioca_gart_found;
-extern struct list_head tioca_list;
-extern int tioca_init_provider(void);
-extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern);
-#endif /* _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H */
diff --git a/arch/ia64/include/asm/sn/tioce.h b/arch/ia64/include/asm/sn/tioce.h
deleted file mode 100644
index 6eae8ada90f0..000000000000
--- a/arch/ia64/include/asm/sn/tioce.h
+++ /dev/null
@@ -1,760 +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) 2003-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef __ASM_IA64_SN_TIOCE_H__
-#define __ASM_IA64_SN_TIOCE_H__
-
-/* CE ASIC part & mfgr information */
-#define TIOCE_PART_NUM 0xCE00
-#define TIOCE_SRC_ID 0x01
-#define TIOCE_REV_A 0x1
-
-/* CE Virtual PPB Vendor/Device IDs */
-#define CE_VIRT_PPB_VENDOR_ID 0x10a9
-#define CE_VIRT_PPB_DEVICE_ID 0x4002
-
-/* CE Host Bridge Vendor/Device IDs */
-#define CE_HOST_BRIDGE_VENDOR_ID 0x10a9
-#define CE_HOST_BRIDGE_DEVICE_ID 0x4001
-
-
-#define TIOCE_NUM_M40_ATES 4096
-#define TIOCE_NUM_M3240_ATES 2048
-#define TIOCE_NUM_PORTS 2
-
-/*
- * Register layout for TIOCE. MMR offsets are shown at the far right of the
- * structure definition.
- */
-typedef volatile struct tioce {
- /*
- * ADMIN : Administration Registers
- */
- u64 ce_adm_id; /* 0x000000 */
- u64 ce_pad_000008; /* 0x000008 */
- u64 ce_adm_dyn_credit_status; /* 0x000010 */
- u64 ce_adm_last_credit_status; /* 0x000018 */
- u64 ce_adm_credit_limit; /* 0x000020 */
- u64 ce_adm_force_credit; /* 0x000028 */
- u64 ce_adm_control; /* 0x000030 */
- u64 ce_adm_mmr_chn_timeout; /* 0x000038 */
- u64 ce_adm_ssp_ure_timeout; /* 0x000040 */
- u64 ce_adm_ssp_dre_timeout; /* 0x000048 */
- u64 ce_adm_ssp_debug_sel; /* 0x000050 */
- u64 ce_adm_int_status; /* 0x000058 */
- u64 ce_adm_int_status_alias; /* 0x000060 */
- u64 ce_adm_int_mask; /* 0x000068 */
- u64 ce_adm_int_pending; /* 0x000070 */
- u64 ce_adm_force_int; /* 0x000078 */
- u64 ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */
- u64 ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */
- u64 ce_adm_error_summary; /* 0x000100 */
- u64 ce_adm_error_summary_alias; /* 0x000108 */
- u64 ce_adm_error_mask; /* 0x000110 */
- u64 ce_adm_first_error; /* 0x000118 */
- u64 ce_adm_error_overflow; /* 0x000120 */
- u64 ce_adm_error_overflow_alias; /* 0x000128 */
- u64 ce_pad_000130[2]; /* 0x000130 -- 0x000138 */
- u64 ce_adm_tnum_error; /* 0x000140 */
- u64 ce_adm_mmr_err_detail; /* 0x000148 */
- u64 ce_adm_msg_sram_perr_detail; /* 0x000150 */
- u64 ce_adm_bap_sram_perr_detail; /* 0x000158 */
- u64 ce_adm_ce_sram_perr_detail; /* 0x000160 */
- u64 ce_adm_ce_credit_oflow_detail; /* 0x000168 */
- u64 ce_adm_tx_link_idle_max_timer; /* 0x000170 */
- u64 ce_adm_pcie_debug_sel; /* 0x000178 */
- u64 ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */
-
- u64 ce_adm_pcie_debug_sel_top; /* 0x000200 */
- u64 ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */
- u64 ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */
- u64 ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */
- u64 ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */
- u64 ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */
- u64 ce_adm_pcie_trig_compare_top; /* 0x000230 */
- u64 ce_adm_pcie_trig_compare_en_top; /* 0x000238 */
- u64 ce_adm_ssp_debug_sel_top; /* 0x000240 */
- u64 ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */
- u64 ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */
- u64 ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */
- u64 ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */
- u64 ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */
- u64 ce_adm_ssp_trig_compare_top; /* 0x000270 */
- u64 ce_adm_ssp_trig_compare_en_top; /* 0x000278 */
- u64 ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */
-
- u64 ce_adm_bap_ctrl; /* 0x000400 */
- u64 ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */
-
- u64 ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */
- u64 ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */
-
- u64 ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */
- u64 ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */
-
- u64 ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */
- u64 ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */
-
- u64 ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */
-
- /*
- * LSI : LSI's PCI Express Link Registers (Link#1 and Link#2)
- * Link#1 MMRs at start at 0x002000, Link#2 MMRs at 0x003000
- * NOTE: the comment offsets at far right: let 'z' = {2 or 3}
- */
- #define ce_lsi(link_num) ce_lsi[link_num-1]
- struct ce_lsi_reg {
- u64 ce_lsi_lpu_id; /* 0x00z000 */
- u64 ce_lsi_rst; /* 0x00z008 */
- u64 ce_lsi_dbg_stat; /* 0x00z010 */
- u64 ce_lsi_dbg_cfg; /* 0x00z018 */
- u64 ce_lsi_ltssm_ctrl; /* 0x00z020 */
- u64 ce_lsi_lk_stat; /* 0x00z028 */
- u64 ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */
- u64 ce_lsi_int_and_stat; /* 0x00z040 */
- u64 ce_lsi_int_mask; /* 0x00z048 */
- u64 ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */
- u64 ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */
- u64 ce_pad_00z108; /* 0x00z108 */
- u64 ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */
- u64 ce_pad_00z118; /* 0x00z118 */
- u64 ce_lsi_lk_perf_cnt1; /* 0x00z120 */
- u64 ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */
- u64 ce_lsi_lk_perf_cnt2; /* 0x00z130 */
- u64 ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */
- u64 ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */
- u64 ce_lsi_lk_lyr_cfg; /* 0x00z200 */
- u64 ce_lsi_lk_lyr_status; /* 0x00z208 */
- u64 ce_lsi_lk_lyr_int_stat; /* 0x00z210 */
- u64 ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */
- u64 ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */
- u64 ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */
- u64 ce_lsi_fc_upd_ctl; /* 0x00z240 */
- u64 ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */
- u64 ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */
- u64 ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */
- u64 ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */
- u64 ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */
- u64 ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */
- u64 ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */
- u64 ce_lsi_rply_tmr_thr; /* 0x00z410 */
- u64 ce_lsi_rply_tmr; /* 0x00z418 */
- u64 ce_lsi_rply_num_stat; /* 0x00z420 */
- u64 ce_lsi_rty_buf_max_addr; /* 0x00z428 */
- u64 ce_lsi_rty_fifo_ptr; /* 0x00z430 */
- u64 ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */
- u64 ce_lsi_rty_fifo_cred; /* 0x00z440 */
- u64 ce_lsi_seq_cnt; /* 0x00z448 */
- u64 ce_lsi_ack_sent_seq_num; /* 0x00z450 */
- u64 ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */
- u64 ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */
- u64 ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */
- u64 ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */
- u64 ce_pad_00z478; /* 0x00z478 */
- u64 ce_lsi_mem_addr_ctl; /* 0x00z480 */
- u64 ce_lsi_mem_d_ld0; /* 0x00z488 */
- u64 ce_lsi_mem_d_ld1; /* 0x00z490 */
- u64 ce_lsi_mem_d_ld2; /* 0x00z498 */
- u64 ce_lsi_mem_d_ld3; /* 0x00z4A0 */
- u64 ce_lsi_mem_d_ld4; /* 0x00z4A8 */
- u64 ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */
- u64 ce_lsi_rty_d_cnt; /* 0x00z4C0 */
- u64 ce_lsi_seq_buf_cnt; /* 0x00z4C8 */
- u64 ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */
- u64 ce_pad_00z4D8; /* 0x00z4D8 */
- u64 ce_lsi_ack_lat_thr; /* 0x00z4E0 */
- u64 ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */
- u64 ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */
- u64 ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */
- u64 ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */
- u64 ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */
- u64 ce_lsi_phy_lyr_cfg; /* 0x00z600 */
- u64 ce_pad_00z608; /* 0x00z608 */
- u64 ce_lsi_phy_lyr_int_stat; /* 0x00z610 */
- u64 ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */
- u64 ce_lsi_phy_lyr_int_mask; /* 0x00z620 */
- u64 ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */
- u64 ce_lsi_rcv_phy_cfg; /* 0x00z680 */
- u64 ce_lsi_rcv_phy_stat1; /* 0x00z688 */
- u64 ce_lsi_rcv_phy_stat2; /* 0x00z690 */
- u64 ce_lsi_rcv_phy_stat3; /* 0x00z698 */
- u64 ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */
- u64 ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */
- u64 ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */
- u64 ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */
- u64 ce_lsi_tx_phy_cfg; /* 0x00z700 */
- u64 ce_lsi_tx_phy_stat; /* 0x00z708 */
- u64 ce_lsi_tx_phy_int_stat; /* 0x00z710 */
- u64 ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */
- u64 ce_lsi_tx_phy_int_mask; /* 0x00z720 */
- u64 ce_lsi_tx_phy_stat2; /* 0x00z728 */
- u64 ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */
- u64 ce_lsi_ltssm_cfg1; /* 0x00z780 */
- u64 ce_lsi_ltssm_cfg2; /* 0x00z788 */
- u64 ce_lsi_ltssm_cfg3; /* 0x00z790 */
- u64 ce_lsi_ltssm_cfg4; /* 0x00z798 */
- u64 ce_lsi_ltssm_cfg5; /* 0x00z7A0 */
- u64 ce_lsi_ltssm_stat1; /* 0x00z7A8 */
- u64 ce_lsi_ltssm_stat2; /* 0x00z7B0 */
- u64 ce_lsi_ltssm_int_stat; /* 0x00z7B8 */
- u64 ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */
- u64 ce_lsi_ltssm_int_mask; /* 0x00z7C8 */
- u64 ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */
- u64 ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */
- u64 ce_lsi_gb_cfg1; /* 0x00z800 */
- u64 ce_lsi_gb_cfg2; /* 0x00z808 */
- u64 ce_lsi_gb_cfg3; /* 0x00z810 */
- u64 ce_lsi_gb_cfg4; /* 0x00z818 */
- u64 ce_lsi_gb_stat; /* 0x00z820 */
- u64 ce_lsi_gb_int_stat; /* 0x00z828 */
- u64 ce_lsi_gb_int_stat_test; /* 0x00z830 */
- u64 ce_lsi_gb_int_mask; /* 0x00z838 */
- u64 ce_lsi_gb_pwr_dn1; /* 0x00z840 */
- u64 ce_lsi_gb_pwr_dn2; /* 0x00z848 */
- u64 ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */
- } ce_lsi[2];
-
- u64 ce_pad_004000[10]; /* 0x004000 -- 0x004048 */
-
- /*
- * CRM: Coretalk Receive Module Registers
- */
- u64 ce_crm_debug_mux; /* 0x004050 */
- u64 ce_pad_004058; /* 0x004058 */
- u64 ce_crm_ssp_err_cmd_wrd; /* 0x004060 */
- u64 ce_crm_ssp_err_addr; /* 0x004068 */
- u64 ce_crm_ssp_err_syn; /* 0x004070 */
-
- u64 ce_pad_004078[499]; /* 0x004078 -- 0x005008 */
-
- /*
- * CXM: Coretalk Xmit Module Registers
- */
- u64 ce_cxm_dyn_credit_status; /* 0x005010 */
- u64 ce_cxm_last_credit_status; /* 0x005018 */
- u64 ce_cxm_credit_limit; /* 0x005020 */
- u64 ce_cxm_force_credit; /* 0x005028 */
- u64 ce_cxm_disable_bypass; /* 0x005030 */
- u64 ce_pad_005038[3]; /* 0x005038 -- 0x005048 */
- u64 ce_cxm_debug_mux; /* 0x005050 */
-
- u64 ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */
-
- /*
- * DTL: Downstream Transaction Layer Regs (Link#1 and Link#2)
- * DTL: Link#1 MMRs at start at 0x006000, Link#2 MMRs at 0x008000
- * DTL: the comment offsets at far right: let 'y' = {6 or 8}
- *
- * UTL: Downstream Transaction Layer Regs (Link#1 and Link#2)
- * UTL: Link#1 MMRs at start at 0x007000, Link#2 MMRs at 0x009000
- * UTL: the comment offsets at far right: let 'z' = {7 or 9}
- */
- #define ce_dtl(link_num) ce_dtl_utl[link_num-1]
- #define ce_utl(link_num) ce_dtl_utl[link_num-1]
- struct ce_dtl_utl_reg {
- /* DTL */
- u64 ce_dtl_dtdr_credit_limit; /* 0x00y000 */
- u64 ce_dtl_dtdr_credit_force; /* 0x00y008 */
- u64 ce_dtl_dyn_credit_status; /* 0x00y010 */
- u64 ce_dtl_dtl_last_credit_stat; /* 0x00y018 */
- u64 ce_dtl_dtl_ctrl; /* 0x00y020 */
- u64 ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */
- u64 ce_dtl_debug_sel; /* 0x00y050 */
- u64 ce_pad_00y058[501]; /* 0x00y058 -- 0x00yFF8 */
-
- /* UTL */
- u64 ce_utl_utl_ctrl; /* 0x00z000 */
- u64 ce_utl_debug_sel; /* 0x00z008 */
- u64 ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */
- } ce_dtl_utl[2];
-
- u64 ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */
-
- /*
- * URE: Upstream Request Engine
- */
- u64 ce_ure_dyn_credit_status; /* 0x00B010 */
- u64 ce_ure_last_credit_status; /* 0x00B018 */
- u64 ce_ure_credit_limit; /* 0x00B020 */
- u64 ce_pad_00B028; /* 0x00B028 */
- u64 ce_ure_control; /* 0x00B030 */
- u64 ce_ure_status; /* 0x00B038 */
- u64 ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */
- u64 ce_ure_debug_sel; /* 0x00B050 */
- u64 ce_ure_pcie_debug_sel; /* 0x00B058 */
- u64 ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */
- u64 ce_ure_ssp_err_addr; /* 0x00B068 */
- u64 ce_ure_page_map; /* 0x00B070 */
- u64 ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */
- u64 ce_ure_pipe_sel1; /* 0x00B088 */
- u64 ce_ure_pipe_mask1; /* 0x00B090 */
- u64 ce_ure_pipe_sel2; /* 0x00B098 */
- u64 ce_ure_pipe_mask2; /* 0x00B0A0 */
- u64 ce_ure_pcie1_credits_sent; /* 0x00B0A8 */
- u64 ce_ure_pcie1_credits_used; /* 0x00B0B0 */
- u64 ce_ure_pcie1_credit_limit; /* 0x00B0B8 */
- u64 ce_ure_pcie2_credits_sent; /* 0x00B0C0 */
- u64 ce_ure_pcie2_credits_used; /* 0x00B0C8 */
- u64 ce_ure_pcie2_credit_limit; /* 0x00B0D0 */
- u64 ce_ure_pcie_force_credit; /* 0x00B0D8 */
- u64 ce_ure_rd_tnum_val; /* 0x00B0E0 */
- u64 ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */
- u64 ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */
- u64 ce_ure_rd_tnum_error; /* 0x00B0F8 */
- u64 ce_ure_rd_tnum_first_cl; /* 0x00B100 */
- u64 ce_ure_rd_tnum_link_buf; /* 0x00B108 */
- u64 ce_ure_wr_tnum_val; /* 0x00B110 */
- u64 ce_ure_sram_err_addr0; /* 0x00B118 */
- u64 ce_ure_sram_err_addr1; /* 0x00B120 */
- u64 ce_ure_sram_err_addr2; /* 0x00B128 */
- u64 ce_ure_sram_rd_addr0; /* 0x00B130 */
- u64 ce_ure_sram_rd_addr1; /* 0x00B138 */
- u64 ce_ure_sram_rd_addr2; /* 0x00B140 */
- u64 ce_ure_sram_wr_addr0; /* 0x00B148 */
- u64 ce_ure_sram_wr_addr1; /* 0x00B150 */
- u64 ce_ure_sram_wr_addr2; /* 0x00B158 */
- u64 ce_ure_buf_flush10; /* 0x00B160 */
- u64 ce_ure_buf_flush11; /* 0x00B168 */
- u64 ce_ure_buf_flush12; /* 0x00B170 */
- u64 ce_ure_buf_flush13; /* 0x00B178 */
- u64 ce_ure_buf_flush20; /* 0x00B180 */
- u64 ce_ure_buf_flush21; /* 0x00B188 */
- u64 ce_ure_buf_flush22; /* 0x00B190 */
- u64 ce_ure_buf_flush23; /* 0x00B198 */
- u64 ce_ure_pcie_control1; /* 0x00B1A0 */
- u64 ce_ure_pcie_control2; /* 0x00B1A8 */
-
- u64 ce_pad_00B1B0[458]; /* 0x00B1B0 -- 0x00BFF8 */
-
- /* Upstream Data Buffer, Port1 */
- struct ce_ure_maint_ups_dat1_data {
- u64 data63_0[512]; /* 0x00C000 -- 0x00CFF8 */
- u64 data127_64[512]; /* 0x00D000 -- 0x00DFF8 */
- u64 parity[512]; /* 0x00E000 -- 0x00EFF8 */
- } ce_ure_maint_ups_dat1;
-
- /* Upstream Header Buffer, Port1 */
- struct ce_ure_maint_ups_hdr1_data {
- u64 data63_0[512]; /* 0x00F000 -- 0x00FFF8 */
- u64 data127_64[512]; /* 0x010000 -- 0x010FF8 */
- u64 parity[512]; /* 0x011000 -- 0x011FF8 */
- } ce_ure_maint_ups_hdr1;
-
- /* Upstream Data Buffer, Port2 */
- struct ce_ure_maint_ups_dat2_data {
- u64 data63_0[512]; /* 0x012000 -- 0x012FF8 */
- u64 data127_64[512]; /* 0x013000 -- 0x013FF8 */
- u64 parity[512]; /* 0x014000 -- 0x014FF8 */
- } ce_ure_maint_ups_dat2;
-
- /* Upstream Header Buffer, Port2 */
- struct ce_ure_maint_ups_hdr2_data {
- u64 data63_0[512]; /* 0x015000 -- 0x015FF8 */
- u64 data127_64[512]; /* 0x016000 -- 0x016FF8 */
- u64 parity[512]; /* 0x017000 -- 0x017FF8 */
- } ce_ure_maint_ups_hdr2;
-
- /* Downstream Data Buffer */
- struct ce_ure_maint_dns_dat_data {
- u64 data63_0[512]; /* 0x018000 -- 0x018FF8 */
- u64 data127_64[512]; /* 0x019000 -- 0x019FF8 */
- u64 parity[512]; /* 0x01A000 -- 0x01AFF8 */
- } ce_ure_maint_dns_dat;
-
- /* Downstream Header Buffer */
- struct ce_ure_maint_dns_hdr_data {
- u64 data31_0[64]; /* 0x01B000 -- 0x01B1F8 */
- u64 data95_32[64]; /* 0x01B200 -- 0x01B3F8 */
- u64 parity[64]; /* 0x01B400 -- 0x01B5F8 */
- } ce_ure_maint_dns_hdr;
-
- /* RCI Buffer Data */
- struct ce_ure_maint_rci_data {
- u64 data41_0[64]; /* 0x01B600 -- 0x01B7F8 */
- u64 data69_42[64]; /* 0x01B800 -- 0x01B9F8 */
- } ce_ure_maint_rci;
-
- /* Response Queue */
- u64 ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */
-
- u64 ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */
-
- /* Admin Build-a-Packet Buffer */
- struct ce_adm_maint_bap_buf_data {
- u64 data63_0[258]; /* 0x024000 -- 0x024808 */
- u64 data127_64[258]; /* 0x024810 -- 0x025018 */
- u64 parity[258]; /* 0x025020 -- 0x025828 */
- } ce_adm_maint_bap_buf;
-
- u64 ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */
-
- /* URE: 40bit PMU ATE Buffer */ /* 0x030000 -- 0x037FF8 */
- u64 ce_ure_ate40[TIOCE_NUM_M40_ATES];
-
- /* URE: 32/40bit PMU ATE Buffer */ /* 0x038000 -- 0x03BFF8 */
- u64 ce_ure_ate3240[TIOCE_NUM_M3240_ATES];
-
- u64 ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */
-
- /*
- * DRE: Down Stream Request Engine
- */
- u64 ce_dre_dyn_credit_status1; /* 0x040010 */
- u64 ce_dre_dyn_credit_status2; /* 0x040018 */
- u64 ce_dre_last_credit_status1; /* 0x040020 */
- u64 ce_dre_last_credit_status2; /* 0x040028 */
- u64 ce_dre_credit_limit1; /* 0x040030 */
- u64 ce_dre_credit_limit2; /* 0x040038 */
- u64 ce_dre_force_credit1; /* 0x040040 */
- u64 ce_dre_force_credit2; /* 0x040048 */
- u64 ce_dre_debug_mux1; /* 0x040050 */
- u64 ce_dre_debug_mux2; /* 0x040058 */
- u64 ce_dre_ssp_err_cmd_wrd; /* 0x040060 */
- u64 ce_dre_ssp_err_addr; /* 0x040068 */
- u64 ce_dre_comp_err_cmd_wrd; /* 0x040070 */
- u64 ce_dre_comp_err_addr; /* 0x040078 */
- u64 ce_dre_req_status; /* 0x040080 */
- u64 ce_dre_config1; /* 0x040088 */
- u64 ce_dre_config2; /* 0x040090 */
- u64 ce_dre_config_req_status; /* 0x040098 */
- u64 ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */
- u64 ce_dre_dyn_fifo; /* 0x040100 */
- u64 ce_pad_040108[3]; /* 0x040108 -- 0x040118 */
- u64 ce_dre_last_fifo; /* 0x040120 */
-
- u64 ce_pad_040128[27]; /* 0x040128 -- 0x0401F8 */
-
- /* DRE Downstream Head Queue */
- struct ce_dre_maint_ds_head_queue {
- u64 data63_0[32]; /* 0x040200 -- 0x0402F8 */
- u64 data127_64[32]; /* 0x040300 -- 0x0403F8 */
- u64 parity[32]; /* 0x040400 -- 0x0404F8 */
- } ce_dre_maint_ds_head_q;
-
- u64 ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */
-
- /* DRE Downstream Data Queue */
- struct ce_dre_maint_ds_data_queue {
- u64 data63_0[256]; /* 0x041000 -- 0x0417F8 */
- u64 ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */
- u64 data127_64[256]; /* 0x042000 -- 0x0427F8 */
- u64 ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */
- u64 parity[256]; /* 0x043000 -- 0x0437F8 */
- u64 ce_pad_043800[256]; /* 0x043800 -- 0x043FF8 */
- } ce_dre_maint_ds_data_q;
-
- /* DRE URE Upstream Response Queue */
- struct ce_dre_maint_ure_us_rsp_queue {
- u64 data63_0[8]; /* 0x044000 -- 0x044038 */
- u64 ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */
- u64 data127_64[8]; /* 0x044100 -- 0x044138 */
- u64 ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */
- u64 parity[8]; /* 0x044200 -- 0x044238 */
- u64 ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */
- } ce_dre_maint_ure_us_rsp_q;
-
- u64 ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */
-
- u64 ce_end_of_struct; /* 0x044400 */
-} tioce_t;
-
-/* ce_lsiX_gb_cfg1 register bit masks & shifts */
-#define CE_LSI_GB_CFG1_RXL0S_THS_SHFT 0
-#define CE_LSI_GB_CFG1_RXL0S_THS_MASK (0xffULL << 0)
-#define CE_LSI_GB_CFG1_RXL0S_SMP_SHFT 8
-#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK (0xfULL << 8)
-#define CE_LSI_GB_CFG1_RXL0S_ADJ_SHFT 12
-#define CE_LSI_GB_CFG1_RXL0S_ADJ_MASK (0x7ULL << 12)
-#define CE_LSI_GB_CFG1_RXL0S_FLT_SHFT 15
-#define CE_LSI_GB_CFG1_RXL0S_FLT_MASK (0x1ULL << 15)
-#define CE_LSI_GB_CFG1_LPBK_SEL_SHFT 16
-#define CE_LSI_GB_CFG1_LPBK_SEL_MASK (0x3ULL << 16)
-#define CE_LSI_GB_CFG1_LPBK_EN_SHFT 18
-#define CE_LSI_GB_CFG1_LPBK_EN_MASK (0x1ULL << 18)
-#define CE_LSI_GB_CFG1_RVRS_LB_SHFT 19
-#define CE_LSI_GB_CFG1_RVRS_LB_MASK (0x1ULL << 19)
-#define CE_LSI_GB_CFG1_RVRS_CLK_SHFT 20
-#define CE_LSI_GB_CFG1_RVRS_CLK_MASK (0x3ULL << 20)
-#define CE_LSI_GB_CFG1_SLF_TS_SHFT 24
-#define CE_LSI_GB_CFG1_SLF_TS_MASK (0xfULL << 24)
-
-/* ce_adm_int_mask/ce_adm_int_status register bit defines */
-#define CE_ADM_INT_CE_ERROR_SHFT 0
-#define CE_ADM_INT_LSI1_IP_ERROR_SHFT 1
-#define CE_ADM_INT_LSI2_IP_ERROR_SHFT 2
-#define CE_ADM_INT_PCIE_ERROR_SHFT 3
-#define CE_ADM_INT_PORT1_HOTPLUG_EVENT_SHFT 4
-#define CE_ADM_INT_PORT2_HOTPLUG_EVENT_SHFT 5
-#define CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT 6
-#define CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT 7
-#define CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT 8
-#define CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT 9
-#define CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT 10
-#define CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT 11
-#define CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT 12
-#define CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT 13
-#define CE_ADM_INT_PCIE_MSG_SHFT 14 /*see int_dest_14*/
-#define CE_ADM_INT_PCIE_MSG_SLOT_0_SHFT 14
-#define CE_ADM_INT_PCIE_MSG_SLOT_1_SHFT 15
-#define CE_ADM_INT_PCIE_MSG_SLOT_2_SHFT 16
-#define CE_ADM_INT_PCIE_MSG_SLOT_3_SHFT 17
-#define CE_ADM_INT_PORT1_PM_PME_MSG_SHFT 22
-#define CE_ADM_INT_PORT2_PM_PME_MSG_SHFT 23
-
-/* ce_adm_force_int register bit defines */
-#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT 0
-#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT 1
-#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT 2
-#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT 3
-#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT 4
-#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT 5
-#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT 6
-#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT 7
-#define CE_ADM_FORCE_INT_ALWAYS_SHFT 8
-
-/* ce_adm_int_dest register bit masks & shifts */
-#define INTR_VECTOR_SHFT 56
-
-/* ce_adm_error_mask and ce_adm_error_summary register bit masks */
-#define CE_ADM_ERR_CRM_SSP_REQ_INVALID (0x1ULL << 0)
-#define CE_ADM_ERR_SSP_REQ_HEADER (0x1ULL << 1)
-#define CE_ADM_ERR_SSP_RSP_HEADER (0x1ULL << 2)
-#define CE_ADM_ERR_SSP_PROTOCOL_ERROR (0x1ULL << 3)
-#define CE_ADM_ERR_SSP_SBE (0x1ULL << 4)
-#define CE_ADM_ERR_SSP_MBE (0x1ULL << 5)
-#define CE_ADM_ERR_CXM_CREDIT_OFLOW (0x1ULL << 6)
-#define CE_ADM_ERR_DRE_SSP_REQ_INVAL (0x1ULL << 7)
-#define CE_ADM_ERR_SSP_REQ_LONG (0x1ULL << 8)
-#define CE_ADM_ERR_SSP_REQ_OFLOW (0x1ULL << 9)
-#define CE_ADM_ERR_SSP_REQ_SHORT (0x1ULL << 10)
-#define CE_ADM_ERR_SSP_REQ_SIDEBAND (0x1ULL << 11)
-#define CE_ADM_ERR_SSP_REQ_ADDR_ERR (0x1ULL << 12)
-#define CE_ADM_ERR_SSP_REQ_BAD_BE (0x1ULL << 13)
-#define CE_ADM_ERR_PCIE_COMPL_TIMEOUT (0x1ULL << 14)
-#define CE_ADM_ERR_PCIE_UNEXP_COMPL (0x1ULL << 15)
-#define CE_ADM_ERR_PCIE_ERR_COMPL (0x1ULL << 16)
-#define CE_ADM_ERR_DRE_CREDIT_OFLOW (0x1ULL << 17)
-#define CE_ADM_ERR_DRE_SRAM_PE (0x1ULL << 18)
-#define CE_ADM_ERR_SSP_RSP_INVALID (0x1ULL << 19)
-#define CE_ADM_ERR_SSP_RSP_LONG (0x1ULL << 20)
-#define CE_ADM_ERR_SSP_RSP_SHORT (0x1ULL << 21)
-#define CE_ADM_ERR_SSP_RSP_SIDEBAND (0x1ULL << 22)
-#define CE_ADM_ERR_URE_SSP_RSP_UNEXP (0x1ULL << 23)
-#define CE_ADM_ERR_URE_SSP_WR_REQ_TIMEOUT (0x1ULL << 24)
-#define CE_ADM_ERR_URE_SSP_RD_REQ_TIMEOUT (0x1ULL << 25)
-#define CE_ADM_ERR_URE_ATE3240_PAGE_FAULT (0x1ULL << 26)
-#define CE_ADM_ERR_URE_ATE40_PAGE_FAULT (0x1ULL << 27)
-#define CE_ADM_ERR_URE_CREDIT_OFLOW (0x1ULL << 28)
-#define CE_ADM_ERR_URE_SRAM_PE (0x1ULL << 29)
-#define CE_ADM_ERR_ADM_SSP_RSP_UNEXP (0x1ULL << 30)
-#define CE_ADM_ERR_ADM_SSP_REQ_TIMEOUT (0x1ULL << 31)
-#define CE_ADM_ERR_MMR_ACCESS_ERROR (0x1ULL << 32)
-#define CE_ADM_ERR_MMR_ADDR_ERROR (0x1ULL << 33)
-#define CE_ADM_ERR_ADM_CREDIT_OFLOW (0x1ULL << 34)
-#define CE_ADM_ERR_ADM_SRAM_PE (0x1ULL << 35)
-#define CE_ADM_ERR_DTL1_MIN_PDATA_CREDIT_ERR (0x1ULL << 36)
-#define CE_ADM_ERR_DTL1_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 37)
-#define CE_ADM_ERR_DTL1_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 38)
-#define CE_ADM_ERR_DTL1_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 39)
-#define CE_ADM_ERR_DTL1_COMP_HD_CRED_MAX_ERR (0x1ULL << 40)
-#define CE_ADM_ERR_DTL1_COMP_D_CRED_MAX_ERR (0x1ULL << 41)
-#define CE_ADM_ERR_DTL1_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 42)
-#define CE_ADM_ERR_DTL1_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 43)
-#define CE_ADM_ERR_DTL1_POSTED_HD_CRED_MAX_ERR (0x1ULL << 44)
-#define CE_ADM_ERR_DTL1_POSTED_D_CRED_MAX_ERR (0x1ULL << 45)
-#define CE_ADM_ERR_DTL2_MIN_PDATA_CREDIT_ERR (0x1ULL << 46)
-#define CE_ADM_ERR_DTL2_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 47)
-#define CE_ADM_ERR_DTL2_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 48)
-#define CE_ADM_ERR_DTL2_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 49)
-#define CE_ADM_ERR_DTL2_COMP_HD_CRED_MAX_ERR (0x1ULL << 50)
-#define CE_ADM_ERR_DTL2_COMP_D_CRED_MAX_ERR (0x1ULL << 51)
-#define CE_ADM_ERR_DTL2_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 52)
-#define CE_ADM_ERR_DTL2_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 53)
-#define CE_ADM_ERR_DTL2_POSTED_HD_CRED_MAX_ERR (0x1ULL << 54)
-#define CE_ADM_ERR_DTL2_POSTED_D_CRED_MAX_ERR (0x1ULL << 55)
-#define CE_ADM_ERR_PORT1_PCIE_COR_ERR (0x1ULL << 56)
-#define CE_ADM_ERR_PORT1_PCIE_NFAT_ERR (0x1ULL << 57)
-#define CE_ADM_ERR_PORT1_PCIE_FAT_ERR (0x1ULL << 58)
-#define CE_ADM_ERR_PORT2_PCIE_COR_ERR (0x1ULL << 59)
-#define CE_ADM_ERR_PORT2_PCIE_NFAT_ERR (0x1ULL << 60)
-#define CE_ADM_ERR_PORT2_PCIE_FAT_ERR (0x1ULL << 61)
-
-/* ce_adm_ure_ups_buf_barrier_flush register bit masks and shifts */
-#define FLUSH_SEL_PORT1_PIPE0_SHFT 0
-#define FLUSH_SEL_PORT1_PIPE1_SHFT 4
-#define FLUSH_SEL_PORT1_PIPE2_SHFT 8
-#define FLUSH_SEL_PORT1_PIPE3_SHFT 12
-#define FLUSH_SEL_PORT2_PIPE0_SHFT 16
-#define FLUSH_SEL_PORT2_PIPE1_SHFT 20
-#define FLUSH_SEL_PORT2_PIPE2_SHFT 24
-#define FLUSH_SEL_PORT2_PIPE3_SHFT 28
-
-/* ce_dre_config1 register bit masks and shifts */
-#define CE_DRE_RO_ENABLE (0x1ULL << 0)
-#define CE_DRE_DYN_RO_ENABLE (0x1ULL << 1)
-#define CE_DRE_SUP_CONFIG_COMP_ERROR (0x1ULL << 2)
-#define CE_DRE_SUP_IO_COMP_ERROR (0x1ULL << 3)
-#define CE_DRE_ADDR_MODE_SHFT 4
-
-/* ce_dre_config_req_status register bit masks */
-#define CE_DRE_LAST_CONFIG_COMPLETION (0x7ULL << 0)
-#define CE_DRE_DOWNSTREAM_CONFIG_ERROR (0x1ULL << 3)
-#define CE_DRE_CONFIG_COMPLETION_VALID (0x1ULL << 4)
-#define CE_DRE_CONFIG_REQUEST_ACTIVE (0x1ULL << 5)
-
-/* ce_ure_control register bit masks & shifts */
-#define CE_URE_RD_MRG_ENABLE (0x1ULL << 0)
-#define CE_URE_WRT_MRG_ENABLE1 (0x1ULL << 4)
-#define CE_URE_WRT_MRG_ENABLE2 (0x1ULL << 5)
-#define CE_URE_WRT_MRG_TIMER_SHFT 12
-#define CE_URE_WRT_MRG_TIMER_MASK (0x7FFULL << CE_URE_WRT_MRG_TIMER_SHFT)
-#define CE_URE_WRT_MRG_TIMER(x) (((u64)(x) << \
- CE_URE_WRT_MRG_TIMER_SHFT) & \
- CE_URE_WRT_MRG_TIMER_MASK)
-#define CE_URE_RSPQ_BYPASS_DISABLE (0x1ULL << 24)
-#define CE_URE_UPS_DAT1_PAR_DISABLE (0x1ULL << 32)
-#define CE_URE_UPS_HDR1_PAR_DISABLE (0x1ULL << 33)
-#define CE_URE_UPS_DAT2_PAR_DISABLE (0x1ULL << 34)
-#define CE_URE_UPS_HDR2_PAR_DISABLE (0x1ULL << 35)
-#define CE_URE_ATE_PAR_DISABLE (0x1ULL << 36)
-#define CE_URE_RCI_PAR_DISABLE (0x1ULL << 37)
-#define CE_URE_RSPQ_PAR_DISABLE (0x1ULL << 38)
-#define CE_URE_DNS_DAT_PAR_DISABLE (0x1ULL << 39)
-#define CE_URE_DNS_HDR_PAR_DISABLE (0x1ULL << 40)
-#define CE_URE_MALFORM_DISABLE (0x1ULL << 44)
-#define CE_URE_UNSUP_DISABLE (0x1ULL << 45)
-
-/* ce_ure_page_map register bit masks & shifts */
-#define CE_URE_ATE3240_ENABLE (0x1ULL << 0)
-#define CE_URE_ATE40_ENABLE (0x1ULL << 1)
-#define CE_URE_PAGESIZE_SHFT 4
-#define CE_URE_PAGESIZE_MASK (0x7ULL << CE_URE_PAGESIZE_SHFT)
-#define CE_URE_4K_PAGESIZE (0x0ULL << CE_URE_PAGESIZE_SHFT)
-#define CE_URE_16K_PAGESIZE (0x1ULL << CE_URE_PAGESIZE_SHFT)
-#define CE_URE_64K_PAGESIZE (0x2ULL << CE_URE_PAGESIZE_SHFT)
-#define CE_URE_128K_PAGESIZE (0x3ULL << CE_URE_PAGESIZE_SHFT)
-#define CE_URE_256K_PAGESIZE (0x4ULL << CE_URE_PAGESIZE_SHFT)
-
-/* ce_ure_pipe_sel register bit masks & shifts */
-#define PKT_TRAFIC_SHRT 16
-#define BUS_SRC_ID_SHFT 8
-#define DEV_SRC_ID_SHFT 3
-#define FNC_SRC_ID_SHFT 0
-#define CE_URE_TC_MASK (0x07ULL << PKT_TRAFIC_SHRT)
-#define CE_URE_BUS_MASK (0xFFULL << BUS_SRC_ID_SHFT)
-#define CE_URE_DEV_MASK (0x1FULL << DEV_SRC_ID_SHFT)
-#define CE_URE_FNC_MASK (0x07ULL << FNC_SRC_ID_SHFT)
-#define CE_URE_PIPE_BUS(b) (((u64)(b) << BUS_SRC_ID_SHFT) & \
- CE_URE_BUS_MASK)
-#define CE_URE_PIPE_DEV(d) (((u64)(d) << DEV_SRC_ID_SHFT) & \
- CE_URE_DEV_MASK)
-#define CE_URE_PIPE_FNC(f) (((u64)(f) << FNC_SRC_ID_SHFT) & \
- CE_URE_FNC_MASK)
-
-#define CE_URE_SEL1_SHFT 0
-#define CE_URE_SEL2_SHFT 20
-#define CE_URE_SEL3_SHFT 40
-#define CE_URE_SEL1_MASK (0x7FFFFULL << CE_URE_SEL1_SHFT)
-#define CE_URE_SEL2_MASK (0x7FFFFULL << CE_URE_SEL2_SHFT)
-#define CE_URE_SEL3_MASK (0x7FFFFULL << CE_URE_SEL3_SHFT)
-
-
-/* ce_ure_pipe_mask register bit masks & shifts */
-#define CE_URE_MASK1_SHFT 0
-#define CE_URE_MASK2_SHFT 20
-#define CE_URE_MASK3_SHFT 40
-#define CE_URE_MASK1_MASK (0x7FFFFULL << CE_URE_MASK1_SHFT)
-#define CE_URE_MASK2_MASK (0x7FFFFULL << CE_URE_MASK2_SHFT)
-#define CE_URE_MASK3_MASK (0x7FFFFULL << CE_URE_MASK3_SHFT)
-
-
-/* ce_ure_pcie_control1 register bit masks & shifts */
-#define CE_URE_SI (0x1ULL << 0)
-#define CE_URE_ELAL_SHFT 4
-#define CE_URE_ELAL_MASK (0x7ULL << CE_URE_ELAL_SHFT)
-#define CE_URE_ELAL_SET(n) (((u64)(n) << CE_URE_ELAL_SHFT) & \
- CE_URE_ELAL_MASK)
-#define CE_URE_ELAL1_SHFT 8
-#define CE_URE_ELAL1_MASK (0x7ULL << CE_URE_ELAL1_SHFT)
-#define CE_URE_ELAL1_SET(n) (((u64)(n) << CE_URE_ELAL1_SHFT) & \
- CE_URE_ELAL1_MASK)
-#define CE_URE_SCC (0x1ULL << 12)
-#define CE_URE_PN1_SHFT 16
-#define CE_URE_PN1_MASK (0xFFULL << CE_URE_PN1_SHFT)
-#define CE_URE_PN2_SHFT 24
-#define CE_URE_PN2_MASK (0xFFULL << CE_URE_PN2_SHFT)
-#define CE_URE_PN1_SET(n) (((u64)(n) << CE_URE_PN1_SHFT) & \
- CE_URE_PN1_MASK)
-#define CE_URE_PN2_SET(n) (((u64)(n) << CE_URE_PN2_SHFT) & \
- CE_URE_PN2_MASK)
-
-/* ce_ure_pcie_control2 register bit masks & shifts */
-#define CE_URE_ABP (0x1ULL << 0)
-#define CE_URE_PCP (0x1ULL << 1)
-#define CE_URE_MSP (0x1ULL << 2)
-#define CE_URE_AIP (0x1ULL << 3)
-#define CE_URE_PIP (0x1ULL << 4)
-#define CE_URE_HPS (0x1ULL << 5)
-#define CE_URE_HPC (0x1ULL << 6)
-#define CE_URE_SPLV_SHFT 7
-#define CE_URE_SPLV_MASK (0xFFULL << CE_URE_SPLV_SHFT)
-#define CE_URE_SPLV_SET(n) (((u64)(n) << CE_URE_SPLV_SHFT) & \
- CE_URE_SPLV_MASK)
-#define CE_URE_SPLS_SHFT 15
-#define CE_URE_SPLS_MASK (0x3ULL << CE_URE_SPLS_SHFT)
-#define CE_URE_SPLS_SET(n) (((u64)(n) << CE_URE_SPLS_SHFT) & \
- CE_URE_SPLS_MASK)
-#define CE_URE_PSN1_SHFT 19
-#define CE_URE_PSN1_MASK (0x1FFFULL << CE_URE_PSN1_SHFT)
-#define CE_URE_PSN2_SHFT 32
-#define CE_URE_PSN2_MASK (0x1FFFULL << CE_URE_PSN2_SHFT)
-#define CE_URE_PSN1_SET(n) (((u64)(n) << CE_URE_PSN1_SHFT) & \
- CE_URE_PSN1_MASK)
-#define CE_URE_PSN2_SET(n) (((u64)(n) << CE_URE_PSN2_SHFT) & \
- CE_URE_PSN2_MASK)
-
-/*
- * PIO address space ranges for CE
- */
-
-/* Local CE Registers Space */
-#define CE_PIO_MMR 0x00000000
-#define CE_PIO_MMR_LEN 0x04000000
-
-/* PCI Compatible Config Space */
-#define CE_PIO_CONFIG_SPACE 0x04000000
-#define CE_PIO_CONFIG_SPACE_LEN 0x04000000
-
-/* PCI I/O Space Alias */
-#define CE_PIO_IO_SPACE_ALIAS 0x08000000
-#define CE_PIO_IO_SPACE_ALIAS_LEN 0x08000000
-
-/* PCI Enhanced Config Space */
-#define CE_PIO_E_CONFIG_SPACE 0x10000000
-#define CE_PIO_E_CONFIG_SPACE_LEN 0x10000000
-
-/* PCI I/O Space */
-#define CE_PIO_IO_SPACE 0x100000000
-#define CE_PIO_IO_SPACE_LEN 0x100000000
-
-/* PCI MEM Space */
-#define CE_PIO_MEM_SPACE 0x200000000
-#define CE_PIO_MEM_SPACE_LEN TIO_HWIN_SIZE
-
-
-/*
- * CE PCI Enhanced Config Space shifts & masks
- */
-#define CE_E_CONFIG_BUS_SHFT 20
-#define CE_E_CONFIG_BUS_MASK (0xFF << CE_E_CONFIG_BUS_SHFT)
-#define CE_E_CONFIG_DEVICE_SHFT 15
-#define CE_E_CONFIG_DEVICE_MASK (0x1F << CE_E_CONFIG_DEVICE_SHFT)
-#define CE_E_CONFIG_FUNC_SHFT 12
-#define CE_E_CONFIG_FUNC_MASK (0x7 << CE_E_CONFIG_FUNC_SHFT)
-
-#endif /* __ASM_IA64_SN_TIOCE_H__ */
diff --git a/arch/ia64/include/asm/sn/tioce_provider.h b/arch/ia64/include/asm/sn/tioce_provider.h
deleted file mode 100644
index 32c32f30b099..000000000000
--- a/arch/ia64/include/asm/sn/tioce_provider.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) 2003-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_CE_PROVIDER_H
-#define _ASM_IA64_SN_CE_PROVIDER_H
-
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/tioce.h>
-
-/*
- * Common TIOCE structure shared between the prom and kernel
- *
- * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES TO THE
- * PROM VERSION.
- */
-struct tioce_common {
- struct pcibus_bussoft ce_pcibus; /* common pciio header */
-
- u32 ce_rev;
- u64 ce_kernel_private;
- u64 ce_prom_private;
-};
-
-struct tioce_kernel {
- struct tioce_common *ce_common;
- spinlock_t ce_lock;
- struct list_head ce_dmamap_list;
-
- u64 ce_ate40_shadow[TIOCE_NUM_M40_ATES];
- u64 ce_ate3240_shadow[TIOCE_NUM_M3240_ATES];
- u32 ce_ate3240_pagesize;
-
- u8 ce_port1_secondary;
-
- /* per-port resources */
- struct {
- int dirmap_refcnt;
- u64 dirmap_shadow;
- } ce_port[TIOCE_NUM_PORTS];
-};
-
-struct tioce_dmamap {
- struct list_head ce_dmamap_list; /* headed by tioce_kernel */
- u32 refcnt;
-
- u64 nbytes; /* # bytes mapped */
-
- u64 ct_start; /* coretalk start address */
- u64 pci_start; /* bus start address */
-
- u64 __iomem *ate_hw;/* hw ptr of first ate in map */
- u64 *ate_shadow; /* shadow ptr of firat ate */
- u16 ate_count; /* # ate's in the map */
-};
-
-extern int tioce_init_provider(void);
-
-#endif /* __ASM_IA64_SN_CE_PROVIDER_H */
diff --git a/arch/ia64/include/asm/sn/tiocp.h b/arch/ia64/include/asm/sn/tiocp.h
deleted file mode 100644
index e8ad0bb5b6c5..000000000000
--- a/arch/ia64/include/asm/sn/tiocp.h
+++ /dev/null
@@ -1,257 +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) 2003-2005 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_TIOCP_H
-#define _ASM_IA64_SN_PCI_TIOCP_H
-
-#define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL
-#define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60)
-#define TIOCP_PCI64_CMDTYPE_MSI (0x3ull << 60)
-
-
-/*****************************************************************************
- *********************** TIOCP MMR structure mapping ***************************
- *****************************************************************************/
-
-struct tiocp{
-
- /* 0x000000-0x00FFFF -- Local Registers */
-
- /* 0x000000-0x000057 -- (Legacy Widget Space) Configuration */
- u64 cp_id; /* 0x000000 */
- u64 cp_stat; /* 0x000008 */
- u64 cp_err_upper; /* 0x000010 */
- u64 cp_err_lower; /* 0x000018 */
- #define cp_err cp_err_lower
- u64 cp_control; /* 0x000020 */
- u64 cp_req_timeout; /* 0x000028 */
- u64 cp_intr_upper; /* 0x000030 */
- u64 cp_intr_lower; /* 0x000038 */
- #define cp_intr cp_intr_lower
- u64 cp_err_cmdword; /* 0x000040 */
- u64 _pad_000048; /* 0x000048 */
- u64 cp_tflush; /* 0x000050 */
-
- /* 0x000058-0x00007F -- Bridge-specific Configuration */
- u64 cp_aux_err; /* 0x000058 */
- u64 cp_resp_upper; /* 0x000060 */
- u64 cp_resp_lower; /* 0x000068 */
- #define cp_resp cp_resp_lower
- u64 cp_tst_pin_ctrl; /* 0x000070 */
- u64 cp_addr_lkerr; /* 0x000078 */
-
- /* 0x000080-0x00008F -- PMU & MAP */
- u64 cp_dir_map; /* 0x000080 */
- u64 _pad_000088; /* 0x000088 */
-
- /* 0x000090-0x00009F -- SSRAM */
- u64 cp_map_fault; /* 0x000090 */
- u64 _pad_000098; /* 0x000098 */
-
- /* 0x0000A0-0x0000AF -- Arbitration */
- u64 cp_arb; /* 0x0000A0 */
- u64 _pad_0000A8; /* 0x0000A8 */
-
- /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
- u64 cp_ate_parity_err; /* 0x0000B0 */
- u64 _pad_0000B8; /* 0x0000B8 */
-
- /* 0x0000C0-0x0000FF -- PCI/GIO */
- u64 cp_bus_timeout; /* 0x0000C0 */
- u64 cp_pci_cfg; /* 0x0000C8 */
- u64 cp_pci_err_upper; /* 0x0000D0 */
- u64 cp_pci_err_lower; /* 0x0000D8 */
- #define cp_pci_err cp_pci_err_lower
- u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */
-
- /* 0x000100-0x0001FF -- Interrupt */
- u64 cp_int_status; /* 0x000100 */
- u64 cp_int_enable; /* 0x000108 */
- u64 cp_int_rst_stat; /* 0x000110 */
- u64 cp_int_mode; /* 0x000118 */
- u64 cp_int_device; /* 0x000120 */
- u64 cp_int_host_err; /* 0x000128 */
- u64 cp_int_addr[8]; /* 0x0001{30,,,68} */
- u64 cp_err_int_view; /* 0x000170 */
- u64 cp_mult_int; /* 0x000178 */
- u64 cp_force_always[8]; /* 0x0001{80,,,B8} */
- u64 cp_force_pin[8]; /* 0x0001{C0,,,F8} */
-
- /* 0x000200-0x000298 -- Device */
- u64 cp_device[4]; /* 0x0002{00,,,18} */
- u64 _pad_000220[4]; /* 0x0002{20,,,38} */
- u64 cp_wr_req_buf[4]; /* 0x0002{40,,,58} */
- u64 _pad_000260[4]; /* 0x0002{60,,,78} */
- u64 cp_rrb_map[2]; /* 0x0002{80,,,88} */
- #define cp_even_resp cp_rrb_map[0] /* 0x000280 */
- #define cp_odd_resp cp_rrb_map[1] /* 0x000288 */
- u64 cp_resp_status; /* 0x000290 */
- u64 cp_resp_clear; /* 0x000298 */
-
- u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */
-
- /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
- struct {
- u64 upper; /* 0x0003{00,,,F0} */
- u64 lower; /* 0x0003{08,,,F8} */
- } cp_buf_addr_match[16];
-
- /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
- struct {
- u64 flush_w_touch; /* 0x000{400,,,5C0} */
- u64 flush_wo_touch; /* 0x000{408,,,5C8} */
- u64 inflight; /* 0x000{410,,,5D0} */
- u64 prefetch; /* 0x000{418,,,5D8} */
- u64 total_pci_retry; /* 0x000{420,,,5E0} */
- u64 max_pci_retry; /* 0x000{428,,,5E8} */
- u64 max_latency; /* 0x000{430,,,5F0} */
- u64 clear_all; /* 0x000{438,,,5F8} */
- } cp_buf_count[8];
-
-
- /* 0x000600-0x0009FF -- PCI/X registers */
- u64 cp_pcix_bus_err_addr; /* 0x000600 */
- u64 cp_pcix_bus_err_attr; /* 0x000608 */
- u64 cp_pcix_bus_err_data; /* 0x000610 */
- u64 cp_pcix_pio_split_addr; /* 0x000618 */
- u64 cp_pcix_pio_split_attr; /* 0x000620 */
- u64 cp_pcix_dma_req_err_attr; /* 0x000628 */
- u64 cp_pcix_dma_req_err_addr; /* 0x000630 */
- u64 cp_pcix_timeout; /* 0x000638 */
-
- u64 _pad_000640[24]; /* 0x000{640,,,6F8} */
-
- /* 0x000700-0x000737 -- Debug Registers */
- u64 cp_ct_debug_ctl; /* 0x000700 */
- u64 cp_br_debug_ctl; /* 0x000708 */
- u64 cp_mux3_debug_ctl; /* 0x000710 */
- u64 cp_mux4_debug_ctl; /* 0x000718 */
- u64 cp_mux5_debug_ctl; /* 0x000720 */
- u64 cp_mux6_debug_ctl; /* 0x000728 */
- u64 cp_mux7_debug_ctl; /* 0x000730 */
-
- u64 _pad_000738[89]; /* 0x000{738,,,9F8} */
-
- /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
- struct {
- u64 cp_buf_addr; /* 0x000{A00,,,AF0} */
- u64 cp_buf_attr; /* 0X000{A08,,,AF8} */
- } cp_pcix_read_buf_64[16];
-
- struct {
- u64 cp_buf_addr; /* 0x000{B00,,,BE0} */
- u64 cp_buf_attr; /* 0x000{B08,,,BE8} */
- u64 cp_buf_valid; /* 0x000{B10,,,BF0} */
- u64 __pad1; /* 0x000{B18,,,BF8} */
- } cp_pcix_write_buf_64[8];
-
- /* End of Local Registers -- Start of Address Map space */
-
- char _pad_000c00[0x010000 - 0x000c00];
-
- /* 0x010000-0x011FF8 -- Internal ATE RAM (Auto Parity Generation) */
- u64 cp_int_ate_ram[1024]; /* 0x010000-0x011FF8 */
-
- char _pad_012000[0x14000 - 0x012000];
-
- /* 0x014000-0x015FF8 -- Internal ATE RAM (Manual Parity Generation) */
- u64 cp_int_ate_ram_mp[1024]; /* 0x014000-0x015FF8 */
-
- char _pad_016000[0x18000 - 0x016000];
-
- /* 0x18000-0x197F8 -- TIOCP Write Request Ram */
- u64 cp_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
- u64 cp_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
- u64 cp_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
-
- char _pad_019800[0x1C000 - 0x019800];
-
- /* 0x1C000-0x1EFF8 -- TIOCP Read Response Ram */
- u64 cp_rd_resp_lower[512]; /* 0x1C000 - 0x1CFF8 */
- u64 cp_rd_resp_upper[512]; /* 0x1D000 - 0x1DFF8 */
- u64 cp_rd_resp_parity[512]; /* 0x1E000 - 0x1EFF8 */
-
- char _pad_01F000[0x20000 - 0x01F000];
-
- /* 0x020000-0x021FFF -- Host Device (CP) Configuration Space (not used) */
- char _pad_020000[0x021000 - 0x20000];
-
- /* 0x021000-0x027FFF -- PCI Device Configuration Spaces */
- union {
- u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
- u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
- u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
- u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
- union {
- u8 c[0x100 / 1];
- u16 s[0x100 / 2];
- u32 l[0x100 / 4];
- u64 d[0x100 / 8];
- } f[8];
- } cp_type0_cfg_dev[7]; /* 0x02{1000,,,7FFF} */
-
- /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
- union {
- u8 c[0x1000 / 1]; /* 0x028000-0x029000 */
- u16 s[0x1000 / 2]; /* 0x028000-0x029000 */
- u32 l[0x1000 / 4]; /* 0x028000-0x029000 */
- u64 d[0x1000 / 8]; /* 0x028000-0x029000 */
- union {
- u8 c[0x100 / 1];
- u16 s[0x100 / 2];
- u32 l[0x100 / 4];
- u64 d[0x100 / 8];
- } f[8];
- } cp_type1_cfg; /* 0x028000-0x029000 */
-
- char _pad_029000[0x030000-0x029000];
-
- /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
- union {
- u8 c[8 / 1];
- u16 s[8 / 2];
- u32 l[8 / 4];
- u64 d[8 / 8];
- } cp_pci_iack; /* 0x030000-0x030007 */
-
- char _pad_030007[0x040000-0x030008];
-
- /* 0x040000-0x040007 -- PCIX Special Cycle */
- union {
- u8 c[8 / 1];
- u16 s[8 / 2];
- u32 l[8 / 4];
- u64 d[8 / 8];
- } cp_pcix_cycle; /* 0x040000-0x040007 */
-
- char _pad_040007[0x200000-0x040008];
-
- /* 0x200000-0x7FFFFF -- PCI/GIO Device Spaces */
- union {
- u8 c[0x100000 / 1];
- u16 s[0x100000 / 2];
- u32 l[0x100000 / 4];
- u64 d[0x100000 / 8];
- } cp_devio_raw[6]; /* 0x200000-0x7FFFFF */
-
- #define cp_devio(n) cp_devio_raw[((n)<2)?(n*2):(n+2)]
-
- char _pad_800000[0xA00000-0x800000];
-
- /* 0xA00000-0xBFFFFF -- PCI/GIO Device Spaces w/flush */
- union {
- u8 c[0x100000 / 1];
- u16 s[0x100000 / 2];
- u32 l[0x100000 / 4];
- u64 d[0x100000 / 8];
- } cp_devio_raw_flush[6]; /* 0xA00000-0xBFFFFF */
-
- #define cp_devio_flush(n) cp_devio_raw_flush[((n)<2)?(n*2):(n+2)]
-
-};
-
-#endif /* _ASM_IA64_SN_PCI_TIOCP_H */
diff --git a/arch/ia64/include/asm/sn/tiocx.h b/arch/ia64/include/asm/sn/tiocx.h
deleted file mode 100644
index d29728492f36..000000000000
--- a/arch/ia64/include/asm/sn/tiocx.h
+++ /dev/null
@@ -1,72 +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) 2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_TIO_TIOCX_H
-#define _ASM_IA64_SN_TIO_TIOCX_H
-
-#ifdef __KERNEL__
-
-struct cx_id_s {
- unsigned int part_num;
- unsigned int mfg_num;
- int nasid;
-};
-
-struct cx_dev {
- struct cx_id_s cx_id;
- int bt; /* board/blade type */
- void *soft; /* driver specific */
- struct hubdev_info *hubdev;
- struct device dev;
- struct cx_drv *driver;
-};
-
-struct cx_device_id {
- unsigned int part_num;
- unsigned int mfg_num;
-};
-
-struct cx_drv {
- char *name;
- const struct cx_device_id *id_table;
- struct device_driver driver;
- int (*probe) (struct cx_dev * dev, const struct cx_device_id * id);
- int (*remove) (struct cx_dev * dev);
-};
-
-/* create DMA address by stripping AS bits */
-#define TIOCX_DMA_ADDR(a) (u64)((u64)(a) & 0xffffcfffffffffUL)
-
-#define TIOCX_TO_TIOCX_DMA_ADDR(a) (u64)(((u64)(a) & 0xfffffffff) | \
- ((((u64)(a)) & 0xffffc000000000UL) <<2))
-
-#define TIO_CE_ASIC_PARTNUM 0xce00
-#define TIOCX_CORELET 3
-
-/* These are taken from tio_mmr_as.h */
-#define TIO_ICE_FRZ_CFG TIO_MMR_ADDR_MOD(0x00000000b0008100UL)
-#define TIO_ICE_PMI_TX_CFG TIO_MMR_ADDR_MOD(0x00000000b000b100UL)
-#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3 TIO_MMR_ADDR_MOD(0x00000000b000be18UL)
-#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK 0x000000000000000fUL
-
-#define to_cx_dev(n) container_of(n, struct cx_dev, dev)
-#define to_cx_driver(drv) container_of(drv, struct cx_drv, driver)
-
-extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int);
-extern void tiocx_irq_free(struct sn_irq_info *);
-extern int cx_device_unregister(struct cx_dev *);
-extern int cx_device_register(nasid_t, int, int, struct hubdev_info *, int);
-extern int cx_driver_unregister(struct cx_drv *);
-extern int cx_driver_register(struct cx_drv *);
-extern u64 tiocx_dma_addr(u64 addr);
-extern u64 tiocx_swin_base(int nasid);
-extern void tiocx_mmr_store(int nasid, u64 offset, u64 value);
-extern u64 tiocx_mmr_load(int nasid, u64 offset);
-
-#endif // __KERNEL__
-#endif // _ASM_IA64_SN_TIO_TIOCX__
diff --git a/arch/ia64/include/asm/sn/types.h b/arch/ia64/include/asm/sn/types.h
deleted file mode 100644
index 8e04ee211e59..000000000000
--- a/arch/ia64/include/asm/sn/types.h
+++ /dev/null
@@ -1,26 +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) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved.
- * Copyright (C) 1999 by Ralf Baechle
- */
-#ifndef _ASM_IA64_SN_TYPES_H
-#define _ASM_IA64_SN_TYPES_H
-
-#include <linux/types.h>
-
-typedef unsigned long cpuid_t;
-typedef signed short nasid_t; /* node id in numa-as-id space */
-typedef signed char partid_t; /* partition ID type */
-typedef unsigned int moduleid_t; /* user-visible module number type */
-typedef unsigned int cmoduleid_t; /* kernel compact module id type */
-typedef unsigned char slotid_t; /* slot (blade) within module */
-typedef unsigned char slabid_t; /* slab (asic) within slot */
-typedef u64 nic_t;
-typedef unsigned long iopaddr_t;
-typedef unsigned long paddr_t;
-typedef short cnodeid_t;
-
-#endif /* _ASM_IA64_SN_TYPES_H */
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h
index b10f31ec522c..9011e90a6b97 100644
--- a/arch/ia64/include/asm/switch_to.h
+++ b/arch/ia64/include/asm/switch_to.h
@@ -69,7 +69,6 @@ extern void ia64_load_extra (struct task_struct *task);
if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) && \
(task_cpu(current) != \
task_thread_info(current)->last_cpu))) { \
- platform_migrate(current); \
task_thread_info(current)->last_cpu = task_cpu(current); \
} \
} while (0)
diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h
index 86ec034ba499..f1f257d632b3 100644
--- a/arch/ia64/include/asm/tlb.h
+++ b/arch/ia64/include/asm/tlb.h
@@ -45,7 +45,6 @@
#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
-#include <asm/machvec.h>
#include <asm-generic/tlb.h>
diff --git a/arch/ia64/include/asm/uv/uv.h b/arch/ia64/include/asm/uv/uv.h
index 71df93ee3bc0..48d4526bf4cd 100644
--- a/arch/ia64/include/asm/uv/uv.h
+++ b/arch/ia64/include/asm/uv/uv.h
@@ -2,12 +2,29 @@
#ifndef _ASM_IA64_UV_UV_H
#define _ASM_IA64_UV_UV_H
-#include <asm/sn/simulator.h>
+#ifdef CONFIG_IA64_SGI_UV
+extern bool ia64_is_uv;
static inline int is_uv_system(void)
{
- /* temporary support for running on hardware simulator */
- return IS_MEDUSA() || ia64_platform_is("uv");
+ 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/kernel/Makefile b/arch/ia64/kernel/Makefile
index 4ba05140b249..1a8df6669eee 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -10,15 +10,14 @@ endif
extra-y := head.o vmlinux.lds
obj-y := entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
- irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
+ irq_lsapic.o ivt.o pal.o patch.o process.o perfmon.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
+ unwind.o mca.o mca_asm.o topology.o dma-mapping.o iosapic.o acpi.o \
+ acpi-ext.o
-obj-$(CONFIG_ACPI) += acpi.o acpi-ext.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_PALINFO) += palinfo.o
-obj-$(CONFIG_IOSAPIC) += iosapic.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_NUMA) += numa.o
@@ -31,7 +30,7 @@ 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-$(CONFIG_PCI_MSI) += msi_ia64.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
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index c597ab5275b8..70d1587ddcd4 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -31,7 +31,6 @@
#include <acpi/processor.h>
#include <asm/io.h>
#include <asm/iosapic.h>
-#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/numa.h>
#include <asm/sal.h>
@@ -45,77 +44,6 @@ unsigned int acpi_cpei_phys_cpuid;
unsigned long acpi_wakeup_address = 0;
-#ifdef CONFIG_IA64_GENERIC
-static unsigned long __init acpi_find_rsdp(void)
-{
- unsigned long rsdp_phys = 0;
-
- if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
- rsdp_phys = efi.acpi20;
- else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
- printk(KERN_WARNING PREFIX
- "v1.0/r0.71 tables no longer supported\n");
- return rsdp_phys;
-}
-
-const char __init *
-acpi_get_sysname(void)
-{
- unsigned long rsdp_phys;
- struct acpi_table_rsdp *rsdp;
- struct acpi_table_xsdt *xsdt;
- struct acpi_table_header *hdr;
-#ifdef CONFIG_INTEL_IOMMU
- u64 i, nentries;
-#endif
-
- rsdp_phys = acpi_find_rsdp();
- if (!rsdp_phys) {
- printk(KERN_ERR
- "ACPI 2.0 RSDP not found, default to \"dig\"\n");
- return "dig";
- }
-
- rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys);
- if (strncmp(rsdp->signature, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)) {
- printk(KERN_ERR
- "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
- return "dig";
- }
-
- xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_physical_address);
- hdr = &xsdt->header;
- if (strncmp(hdr->signature, ACPI_SIG_XSDT, sizeof(ACPI_SIG_XSDT) - 1)) {
- printk(KERN_ERR
- "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
- return "dig";
- }
-
- if (!strcmp(hdr->oem_id, "HP")) {
- return "hpzx1";
- } else if (!strcmp(hdr->oem_id, "SGI")) {
- if (!strcmp(hdr->oem_table_id + 4, "UV"))
- return "uv";
- else
- return "sn2";
- }
-
-#ifdef CONFIG_INTEL_IOMMU
- /* Look for Intel IOMMU */
- nentries = (hdr->length - sizeof(*hdr)) /
- sizeof(xsdt->table_offset_entry[0]);
- for (i = 0; i < nentries; i++) {
- hdr = __va(xsdt->table_offset_entry[i]);
- if (strncmp(hdr->signature, ACPI_SIG_DMAR,
- sizeof(ACPI_SIG_DMAR) - 1) == 0)
- return "dig_vtd";
- }
-#endif
-
- return "dig";
-}
-#endif /* CONFIG_IA64_GENERIC */
-
#define ACPI_MAX_PLATFORM_INTERRUPTS 256
/* Array to record platform interrupt vectors for generic interrupt routing. */
@@ -407,7 +335,7 @@ get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
int pxm;
pxm = pa->proximity_domain_lo;
- if (ia64_platform_is("sn2") || acpi_srat_revision >= 2)
+ if (acpi_srat_revision >= 2)
pxm += pa->proximity_domain_hi[0] << 8;
return pxm;
}
@@ -418,7 +346,7 @@ get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
int pxm;
pxm = ma->proximity_domain;
- if (!ia64_platform_is("sn2") && acpi_srat_revision <= 1)
+ if (acpi_srat_revision <= 1)
pxm &= 0xff;
return pxm;
@@ -710,9 +638,8 @@ int __init acpi_boot_init(void)
if (acpi_table_parse_madt
(ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) {
- if (!ia64_platform_is("sn2"))
- printk(KERN_ERR PREFIX
- "Error parsing MADT - no IOSAPIC entries\n");
+ printk(KERN_ERR PREFIX
+ "Error parsing MADT - no IOSAPIC entries\n");
}
/* System-Level Interrupt Routing */
diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c
index ad7d9963de34..4a3262795890 100644
--- a/arch/ia64/kernel/dma-mapping.c
+++ b/arch/ia64/kernel/dma-mapping.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/dma-direct.h>
-#include <linux/swiotlb.h>
#include <linux/export.h>
/* Set this to 1 if there is a HW IOMMU in the system */
@@ -9,13 +8,6 @@ int iommu_detected __read_mostly;
const struct dma_map_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
-const struct dma_map_ops *dma_get_ops(struct device *dev)
-{
- return dma_ops;
-}
-EXPORT_SYMBOL(dma_get_ops);
-
-#ifdef CONFIG_SWIOTLB
void *arch_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
@@ -33,9 +25,3 @@ long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
{
return page_to_pfn(virt_to_page(cpu_addr));
}
-
-void __init swiotlb_dma_init(void)
-{
- swiotlb_init(1);
-}
-#endif
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 3795d18276c4..0a34dcc435c6 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -47,8 +47,11 @@
static __initdata unsigned long palo_phys;
+unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR;
+
static __initdata efi_config_table_type_t arch_tables[] = {
{PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys},
+ {SAL_SYSTEM_TABLE_GUID, "SALsystab", &sal_systab_phys},
{NULL_GUID, NULL, 0},
};
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index fe6e4946672e..fad4db20ce65 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -67,10 +67,7 @@
* 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. A
- * platform can implement platform_irq_to_vector(irq) and
- * platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
- * Please see also arch/ia64/include/asm/hw_irq.h for those APIs.
+ * systems, we use one-to-one mapping between IA-64 vector and IRQ.
*
* To sum up, there are three levels of mappings involved:
*
@@ -96,7 +93,6 @@
#include <asm/hw_irq.h>
#include <asm/io.h>
#include <asm/iosapic.h>
-#include <asm/machvec.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
@@ -646,10 +642,8 @@ get_target_cpu (unsigned int gsi, int irq)
if (!cpu_online(smp_processor_id()))
return cpu_physical_id(smp_processor_id());
-#ifdef CONFIG_ACPI
if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR)
return get_cpei_target_cpu();
-#endif
#ifdef CONFIG_NUMA
{
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 8ed81b252694..0a8e5e585edc 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -35,18 +35,6 @@ void ack_bad_irq(unsigned int irq)
printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
}
-#ifdef CONFIG_IA64_GENERIC
-ia64_vector __ia64_irq_to_vector(int irq)
-{
- return irq_cfg[irq].vector;
-}
-
-unsigned int __ia64_local_vector_to_irq (ia64_vector vec)
-{
- return __this_cpu_read(vector_irq[vec]);
-}
-#endif
-
/*
* Interrupt statistics:
*/
@@ -73,17 +61,6 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
irq_redir[irq] = (char) (redir & 0xff);
}
}
-
-bool is_affinity_mask_valid(const struct cpumask *cpumask)
-{
- if (ia64_platform_is("sn2")) {
- /* Only allow one CPU to be specified in the smp_affinity mask */
- if (cpumask_weight(cpumask) != 1)
- return false;
- }
- return true;
-}
-
#endif /* CONFIG_SMP */
int __init arch_early_irq_init(void)
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index ab87d6c25b15..f10208478131 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -37,7 +37,6 @@
#include <asm/intrinsics.h>
#include <asm/io.h>
#include <asm/hw_irq.h>
-#include <asm/machvec.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
@@ -53,7 +52,6 @@
#define IRQ_USED (1)
#define IRQ_RSVD (2)
-/* These can be overridden in platform_irq_init */
int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
@@ -250,7 +248,7 @@ void __setup_vector_irq(int cpu)
}
}
-#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG))
+#ifdef CONFIG_SMP
static enum vector_domain_type {
VECTOR_DOMAIN_NONE,
@@ -314,7 +312,7 @@ void irq_complete_move(unsigned irq)
cpumask_and(&cleanup_mask, &cfg->old_domain, cpu_online_mask);
cfg->move_cleanup_count = cpumask_weight(&cleanup_mask);
for_each_cpu(i, &cleanup_mask)
- platform_send_ipi(i, IA64_IRQ_MOVE_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(i, IA64_IRQ_MOVE_VECTOR, IA64_IPI_DM_INT, 0);
cfg->move_in_progress = 0;
}
@@ -634,21 +632,16 @@ ia64_native_register_ipi(void)
void __init
init_IRQ (void)
{
-#ifdef CONFIG_ACPI
acpi_boot_init();
-#endif
ia64_register_ipi();
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
#ifdef CONFIG_SMP
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)
if (vector_domain_type != VECTOR_DOMAIN_NONE)
register_percpu_irq(IA64_IRQ_MOVE_VECTOR, &irq_move_irqaction);
#endif
-#endif
#ifdef CONFIG_PERFMON
pfm_init_percpu();
#endif
- platform_irq_init();
}
void
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 5de801a2c0f0..b8356edbde65 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -979,32 +979,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
return ret;
}
-struct param_bsp_cfm {
- unsigned long ip;
- unsigned long *bsp;
- unsigned long cfm;
-};
-
-static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
-{
- unsigned long ip;
- struct param_bsp_cfm *lp = arg;
-
- do {
- unw_get_ip(info, &ip);
- if (ip == 0)
- break;
- if (ip == lp->ip) {
- unw_get_bsp(info, (unsigned long*)&lp->bsp);
- unw_get_cfm(info, (unsigned long*)&lp->cfm);
- return;
- }
- } while (unw_unwind(info) >= 0);
- lp->bsp = NULL;
- lp->cfm = 0;
- return;
-}
-
unsigned long arch_deref_entry_point(void *entry)
{
return ((struct fnptr *)entry)->ip;
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 3b1dd5496d08..efc9b568401c 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -127,7 +127,6 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
ia64_srlz_d();
while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
ia64_eoi();
- platform_kernel_launch_event();
rnk = (relocate_new_kernel_t)&code_addr;
(*rnk)(image->head, image->start, ia64_boot_param,
GRANULEROUNDDOWN((unsigned long) pal_addr));
diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
deleted file mode 100644
index ebd82535f51b..000000000000
--- a/arch/ia64/kernel/machvec.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <asm/machvec.h>
-
-#ifdef CONFIG_IA64_GENERIC
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/page.h>
-
-struct ia64_machine_vector ia64_mv = {
- .mmiowb = ___ia64_mmiowb
-};
-EXPORT_SYMBOL(ia64_mv);
-
-static struct ia64_machine_vector * __init
-lookup_machvec (const char *name)
-{
- extern struct ia64_machine_vector machvec_start[];
- extern struct ia64_machine_vector machvec_end[];
- struct ia64_machine_vector *mv;
-
- for (mv = machvec_start; mv < machvec_end; ++mv)
- if (strcmp (mv->name, name) == 0)
- return mv;
-
- return 0;
-}
-
-void __init
-machvec_init (const char *name)
-{
- struct ia64_machine_vector *mv;
-
- if (!name)
- name = acpi_get_sysname();
- mv = lookup_machvec(name);
- if (!mv)
- panic("generic kernel failed to find machine vector for"
- " platform %s!", name);
-
- ia64_mv = *mv;
- printk(KERN_INFO "booting generic kernel on platform %s\n", name);
-}
-
-void __init
-machvec_init_from_cmdline(const char *cmdline)
-{
- char str[64];
- const char *start;
- char *end;
-
- if (! (start = strstr(cmdline, "machvec=")) )
- return machvec_init(NULL);
-
- strlcpy(str, start + strlen("machvec="), sizeof(str));
- if ( (end = strchr(str, ' ')) )
- *end = '\0';
-
- return machvec_init(str);
-}
-
-#endif /* CONFIG_IA64_GENERIC */
-
-void
-machvec_setup (char **arg)
-{
-}
-EXPORT_SYMBOL(machvec_setup);
-
-void
-machvec_timer_interrupt (int irq, void *dev_id)
-{
-}
-EXPORT_SYMBOL(machvec_timer_interrupt);
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 79190d877fa7..bf2cb9294795 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -91,7 +91,6 @@
#include <linux/gfp.h>
#include <asm/delay.h>
-#include <asm/machvec.h>
#include <asm/meminit.h>
#include <asm/page.h>
#include <asm/ptrace.h>
@@ -149,9 +148,7 @@ static ia64_mc_info_t ia64_mc_info;
#define CPE_HISTORY_LENGTH 5
#define CMC_HISTORY_LENGTH 5
-#ifdef CONFIG_ACPI
static struct timer_list cpe_poll_timer;
-#endif
static struct timer_list cmc_poll_timer;
/*
* This variable tells whether we are currently in polling mode.
@@ -532,8 +529,6 @@ int mca_recover_range(unsigned long addr)
}
EXPORT_SYMBOL_GPL(mca_recover_range);
-#ifdef CONFIG_ACPI
-
int cpe_vector = -1;
int ia64_cpe_irq = -1;
@@ -595,9 +590,6 @@ out:
return IRQ_HANDLED;
}
-#endif /* CONFIG_ACPI */
-
-#ifdef CONFIG_ACPI
/*
* ia64_mca_register_cpev
*
@@ -625,7 +617,6 @@ ia64_mca_register_cpev (int cpev)
IA64_MCA_DEBUG("%s: corrected platform error "
"vector %#x registered\n", __func__, cpev);
}
-#endif /* CONFIG_ACPI */
/*
* ia64_mca_cmc_vector_setup
@@ -744,7 +735,7 @@ ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused)
static void
ia64_mca_wakeup(int cpu)
{
- platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
}
/*
@@ -1490,7 +1481,7 @@ ia64_mca_cmc_int_caller(int cmc_irq, void *arg)
cpuid = cpumask_next(cpuid+1, cpu_online_mask);
if (cpuid < nr_cpu_ids) {
- platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
+ 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)) {
@@ -1523,7 +1514,7 @@ static void
ia64_mca_cmc_poll (struct timer_list *unused)
{
/* Trigger a CMC interrupt cascade */
- platform_send_ipi(cpumask_first(cpu_online_mask), IA64_CMCP_VECTOR,
+ ia64_send_ipi(cpumask_first(cpu_online_mask), IA64_CMCP_VECTOR,
IA64_IPI_DM_INT, 0);
}
@@ -1540,8 +1531,6 @@ ia64_mca_cmc_poll (struct timer_list *unused)
* Outputs
* handled
*/
-#ifdef CONFIG_ACPI
-
static irqreturn_t
ia64_mca_cpe_int_caller(int cpe_irq, void *arg)
{
@@ -1560,7 +1549,7 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg)
cpuid = cpumask_next(cpuid+1, cpu_online_mask);
if (cpuid < NR_CPUS) {
- platform_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
} else {
/*
* If a log was recorded, increase our polling frequency,
@@ -1600,12 +1589,10 @@ static void
ia64_mca_cpe_poll (struct timer_list *unused)
{
/* Trigger a CPE interrupt cascade */
- platform_send_ipi(cpumask_first(cpu_online_mask), IA64_CPEP_VECTOR,
+ ia64_send_ipi(cpumask_first(cpu_online_mask), IA64_CPEP_VECTOR,
IA64_IPI_DM_INT, 0);
}
-#endif /* CONFIG_ACPI */
-
static int
default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data)
{
@@ -1799,7 +1786,6 @@ static struct irqaction mca_wkup_irqaction = {
.name = "mca_wkup"
};
-#ifdef CONFIG_ACPI
static struct irqaction mca_cpe_irqaction = {
.handler = ia64_mca_cpe_int_handler,
.name = "cpe_hndlr"
@@ -1809,7 +1795,6 @@ static struct irqaction mca_cpep_irqaction = {
.handler = ia64_mca_cpe_int_caller,
.name = "cpe_poll"
};
-#endif /* CONFIG_ACPI */
/* 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
@@ -2081,10 +2066,8 @@ void __init ia64_mca_irq_init(void)
/* Setup the MCA wakeup interrupt vector */
register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-#ifdef CONFIG_ACPI
/* Setup the CPEI/P handler */
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-#endif
}
/*
@@ -2112,7 +2095,6 @@ ia64_mca_late_init(void)
ia64_mca_cpu_online, NULL);
IA64_MCA_DEBUG("%s: CMCI/P setup and enabled.\n", __func__);
-#ifdef CONFIG_ACPI
/* 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);
@@ -2143,7 +2125,6 @@ ia64_mca_late_init(void)
IA64_MCA_DEBUG("%s: CPEP setup and enabled.\n", __func__);
}
}
-#endif
return 0;
}
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index cd7972ede1d6..4d0ab323dee8 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <asm/delay.h>
-#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/sal.h>
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 326448f9df16..1a42ba885188 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -914,10 +914,14 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo
void
module_arch_cleanup (struct module *mod)
{
- if (mod->arch.init_unw_table)
+ if (mod->arch.init_unw_table) {
unw_remove_unwind_table(mod->arch.init_unw_table);
- if (mod->arch.core_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)
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 519d9432f407..df5c28f252e3 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -43,7 +43,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
}
#endif /* CONFIG_SMP */
-int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
struct msi_msg msg;
unsigned long dest_phys_id;
@@ -77,7 +77,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
return 0;
}
-void ia64_teardown_msi_irq(unsigned int irq)
+void arch_teardown_msi_irq(unsigned int irq)
{
destroy_irq(irq);
}
@@ -111,23 +111,6 @@ static struct irq_chip ia64_msi_chip = {
.irq_retrigger = ia64_msi_retrigger_irq,
};
-
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
-{
- if (platform_setup_msi_irq)
- return platform_setup_msi_irq(pdev, desc);
-
- return ia64_setup_msi_irq(pdev, desc);
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
- if (platform_teardown_msi_irq)
- return platform_teardown_msi_irq(irq);
-
- return ia64_teardown_msi_irq(irq);
-}
-
#ifdef CONFIG_INTEL_IOMMU
#ifdef CONFIG_SMP
static int dmar_msi_set_affinity(struct irq_data *data,
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index fe988c49f01c..c90221733c6b 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/dmar.h>
#include <asm/iommu.h>
-#include <asm/machvec.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <asm/page.h>
@@ -22,8 +21,6 @@ int force_iommu __read_mostly = 1;
int force_iommu __read_mostly;
#endif
-int iommu_pass_through;
-
static int __init pci_iommu_init(void)
{
if (iommu_detected)
@@ -34,24 +31,3 @@ static int __init pci_iommu_init(void)
/* Must execute after PCI subsystem */
fs_initcall(pci_iommu_init);
-
-void __init pci_iommu_alloc(void)
-{
- /*
- * The order of these functions is important for
- * fall-back/fail-over reasons
- */
- detect_intel_iommu();
-
-#ifdef CONFIG_SWIOTLB
- if (!iommu_detected) {
-#ifdef CONFIG_IA64_GENERIC
- printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
- machvec_init("dig");
- swiotlb_dma_init();
-#else
- panic("Unable to find Intel IOMMU");
-#endif /* CONFIG_IA64_GENERIC */
- }
-#endif /* CONFIG_SWIOTLB */
-}
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 9b2331ac10ce..c455ece977ad 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -110,13 +110,6 @@ check_versions (struct ia64_sal_systab *systab)
sal_revision = SAL_VERSION_CODE(2, 8);
sal_version = SAL_VERSION_CODE(0, 0);
}
-
- if (ia64_platform_is("sn2") && (sal_revision == SAL_VERSION_CODE(2, 9)))
- /*
- * SGI Altix has hard-coded version 2.9 in their prom
- * but they actually implement 3.2, so let's fix it here.
- */
- sal_revision = SAL_VERSION_CODE(3, 2);
}
static void __init
@@ -256,7 +249,7 @@ check_sal_cache_flush (void)
* Send ourselves a timer interrupt, wait until it's reported, and see
* if SAL_CACHE_FLUSH drops it.
*/
- platform_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0);
while (!ia64_get_irr(IA64_TIMER_VECTOR))
cpu_relax();
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index c9cfa760cd57..8eb276aac5ce 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -30,6 +30,7 @@
#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>
@@ -41,6 +42,7 @@
#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>
@@ -50,7 +52,6 @@
#include <linux/kexec.h>
#include <linux/crash_dump.h>
-#include <asm/machvec.h>
#include <asm/mca.h>
#include <asm/meminit.h>
#include <asm/page.h>
@@ -63,12 +64,14 @@
#include <asm/smp.h>
#include <asm/tlbflush.h>
#include <asm/unistd.h>
-#include <asm/hpsim.h>
+#include <asm/uv/uv.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);
@@ -260,11 +263,11 @@ __initcall(register_memory);
* 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 "sn2".
+ * over 4 GB is "uv".
*/
static int __init check_crashkernel_memory(unsigned long pbase, size_t size)
{
- if (ia64_platform_is("sn2") || ia64_platform_is("uv"))
+ if (is_uv_system())
return 1;
else
return pbase < (1UL << 32);
@@ -461,23 +464,44 @@ io_port_init (void)
static inline int __init
early_console_setup (char *cmdline)
{
- int earlycons = 0;
-
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
- {
- extern int sn_serial_console_early_setup(void);
- if (!sn_serial_console_early_setup())
- earlycons++;
- }
-#endif
#ifdef CONFIG_EFI_PCDP
if (!efi_setup_pcdp_console(cmdline))
- earlycons++;
+ return 0;
#endif
- if (!simcons_register())
- earlycons++;
+ 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;
+ }
- return (earlycons) ? 0 : -1;
+ 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
@@ -536,35 +560,25 @@ setup_arch (char **cmdline_p)
efi_init();
io_port_init();
-#ifdef CONFIG_IA64_GENERIC
- /* machvec needs to be parsed from the command line
- * before parse_early_param() is called to ensure
- * that ia64_mv is initialised before any command line
- * settings may cause console setup to occur
- */
- machvec_init_from_cmdline(*cmdline_p);
-#endif
-
+ uv_probe_system_type();
parse_early_param();
if (early_console_setup(*cmdline_p) == 0)
mark_bsp_online();
-#ifdef CONFIG_ACPI
/* Initialize the ACPI boot-time table parser */
acpi_table_init();
early_acpi_boot_init();
-# ifdef CONFIG_ACPI_NUMA
+#ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
acpi_numa_fixup();
-# ifdef CONFIG_ACPI_HOTPLUG_CPU
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
prefill_possible_map();
-# endif
+#endif
per_cpu_scan_finalize((cpumask_weight(&early_cpu_possible_map) == 0 ?
32 : cpumask_weight(&early_cpu_possible_map)),
additional_cpus > 0 ? additional_cpus : 0);
-# endif
-#endif /* CONFIG_APCI_BOOT */
+#endif /* CONFIG_ACPI_NUMA */
#ifdef CONFIG_SMP
smp_build_cpu_map();
@@ -572,7 +586,7 @@ setup_arch (char **cmdline_p)
find_memory();
/* process SAL system table: */
- ia64_sal_init(__va(efi.sal_systab));
+ ia64_sal_init(__va(sal_systab_phys));
#ifdef CONFIG_ITANIUM
ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist);
@@ -614,10 +628,21 @@ setup_arch (char **cmdline_p)
if (!nomca)
ia64_mca_init();
- platform_setup(cmdline_p);
-#ifndef CONFIG_IA64_HP_SIM
- check_sal_cache_flush();
+ /*
+ * 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 = Root_SDA2; /* default to second partition on first drive */
+
+ 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();
@@ -1046,7 +1071,6 @@ cpu_init (void)
ia64_patch_phys_stack_reg(num_phys_stacked*8 + 8);
max_num_phys_stacked = num_phys_stacked;
}
- platform_cpu_init();
}
void __init
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index e5044aed9452..d07ed65c9c6e 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -363,19 +363,19 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
if (unlikely(restart)) {
switch (errno) {
- case ERESTART_RESTARTBLOCK:
- case ERESTARTNOHAND:
+ case ERESTART_RESTARTBLOCK:
+ case ERESTARTNOHAND:
scr->pt.r8 = EINTR;
/* note: scr->pt.r10 is already -1 */
break;
-
- case ERESTARTSYS:
+ case ERESTARTSYS:
if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
scr->pt.r8 = EINTR;
/* note: scr->pt.r10 is already -1 */
break;
}
- case ERESTARTNOINTR:
+ /*FALLTHRU*/
+ case ERESTARTNOINTR:
ia64_decrement_ip(&scr->pt);
restart = 0; /* don't restart twice if handle_signal() fails... */
}
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 133b63355814..de35c54f033d 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -36,7 +36,6 @@
#include <linux/atomic.h>
#include <asm/current.h>
#include <asm/delay.h>
-#include <asm/machvec.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/page.h>
@@ -146,7 +145,7 @@ static inline void
send_IPI_single (int dest_cpu, int op)
{
set_bit(op, &per_cpu(ipi_operation, dest_cpu));
- platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
}
/*
@@ -213,7 +212,7 @@ kdump_smp_send_init(void)
for_each_online_cpu(cpu) {
if (cpu != self_cpu) {
if(kdump_status[cpu] == 0)
- platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
+ ia64_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
}
}
}
@@ -224,7 +223,7 @@ kdump_smp_send_init(void)
void
smp_send_reschedule (int cpu)
{
- platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
}
EXPORT_SYMBOL_GPL(smp_send_reschedule);
@@ -234,7 +233,7 @@ EXPORT_SYMBOL_GPL(smp_send_reschedule);
static void
smp_send_local_flush_tlb (int cpu)
{
- platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0);
}
void
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index d0474a0c67db..6501d9a9a21b 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -47,7 +47,6 @@
#include <asm/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/machvec.h>
#include <asm/mca.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -57,7 +56,6 @@
#include <asm/sal.h>
#include <asm/tlbflush.h>
#include <asm/unistd.h>
-#include <asm/sn/arch.h>
#define SMP_DEBUG 0
@@ -468,7 +466,7 @@ do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
set_brendez_area(cpu);
- platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
/*
* Wait 10s total for the AP to start
@@ -658,11 +656,6 @@ int __cpu_disable(void)
return (-EBUSY);
}
- if (ia64_platform_is("sn2")) {
- if (!sn_cpu_disable_allowed(cpu))
- return -EBUSY;
- }
-
set_cpu_online(cpu, false);
if (migrate_platform_irqs(cpu)) {
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 9ebe1d633abc..e14db25146c2 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -166,21 +166,3 @@ ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, u
force_successful_syscall_return();
return addr;
}
-
-#ifndef CONFIG_PCI
-
-asmlinkage long
-sys_pciconfig_read (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
- void *buf)
-{
- return -ENOSYS;
-}
-
-asmlinkage long
-sys_pciconfig_write (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
- void *buf)
-{
- return -ENOSYS;
-}
-
-#endif /* CONFIG_PCI */
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 4ecd81b0e8ec..1e95d32c8877 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -25,7 +25,6 @@
#include <linux/platform_device.h>
#include <linux/sched/cputime.h>
-#include <asm/machvec.h>
#include <asm/delay.h>
#include <asm/hw_irq.h>
#include <asm/ptrace.h>
@@ -167,8 +166,6 @@ timer_interrupt (int irq, void *dev_id)
return IRQ_HANDLED;
}
- platform_timer_interrupt(irq, dev_id);
-
new_itm = local_cpu_data->itm_next;
if (!time_after(ia64_get_itc(), new_itm))
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index e311ee13e61d..09fc385c2acd 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -42,7 +42,6 @@ EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
#ifdef CONFIG_HOTPLUG_CPU
int __ref arch_register_cpu(int num)
{
-#ifdef CONFIG_ACPI
/*
* If CPEI can be re-targeted or if this is not
* CPEI target, then it is hotpluggable
@@ -50,7 +49,6 @@ int __ref arch_register_cpu(int num)
if (can_cpei_retarget() || !is_cpu_cpei_target(num))
sysfs_cpus[num].cpu.hotpluggable = 1;
map_cpu_to_node(num, node_cpuid[num].nid);
-#endif
return register_cpu(&sysfs_cpus[num].cpu, num);
}
EXPORT_SYMBOL(arch_register_cpu);
@@ -58,9 +56,7 @@ EXPORT_SYMBOL(arch_register_cpu);
void __ref arch_unregister_cpu(int num)
{
unregister_cpu(&sysfs_cpus[num].cpu);
-#ifdef CONFIG_ACPI
unmap_cpu_from_node(num, cpu_to_node(num));
-#endif
}
EXPORT_SYMBOL(arch_unregister_cpu);
#else
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index eb7d5df59fa3..2d4e65ba5c3e 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1431,7 +1431,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (u.insn.x)
/* oops, really a semaphore op (cmpxchg, etc) */
goto failure;
- /* no break */
+ /*FALLTHRU*/
case LDS_IMM_OP:
case LDSA_IMM_OP:
case LDFS_OP:
@@ -1459,7 +1459,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (u.insn.x)
/* oops, really a semaphore op (cmpxchg, etc) */
goto failure;
- /* no break */
+ /*FALLTHRU*/
case LD_IMM_OP:
case LDA_IMM_OP:
case LDBIAS_IMM_OP:
@@ -1475,7 +1475,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (u.insn.x)
/* oops, really a semaphore op (cmpxchg, etc) */
goto failure;
- /* no break */
+ /*FALLTHRU*/
case ST_IMM_OP:
case STREL_IMM_OP:
ret = emulate_store_int(ifa, u.insn, regs);
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 16c6d377c502..3776ef225125 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -24,7 +24,6 @@
#include <asm/pgtable.h>
#include <linux/atomic.h>
#include <asm/tlbflush.h>
-#include <asm/sn/arch.h>
extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
@@ -129,10 +128,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
preempt_disable();
- if (ia64_platform_is("sn2"))
- sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE);
- else
- flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
+ flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
/* flush the just introduced uncached translation from the TLB */
local_flush_tlb_all();
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 0da58cf8e213..d9d4e21107cd 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -141,16 +141,6 @@ SECTIONS {
__end___mckinley_e9_bundles = .;
}
-#if defined(CONFIG_IA64_GENERIC)
- /* Machine Vector */
- . = ALIGN(16);
- .machvec : AT(ADDR(.machvec) - LOAD_OFFSET) {
- machvec_start = .;
- *(.machvec)
- machvec_end = .;
- }
-#endif
-
#ifdef CONFIG_SMP
. = ALIGN(PERCPU_PAGE_SIZE);
__cpu0_per_cpu = .;
diff --git a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
index d107eaf3790d..c3e02462ed16 100644
--- a/arch/ia64/lib/io.c
+++ b/arch/ia64/lib/io.c
@@ -49,117 +49,3 @@ void memset_io(volatile void __iomem *dst, int c, long count)
}
}
EXPORT_SYMBOL(memset_io);
-
-#ifdef CONFIG_IA64_GENERIC
-
-#undef __ia64_inb
-#undef __ia64_inw
-#undef __ia64_inl
-#undef __ia64_outb
-#undef __ia64_outw
-#undef __ia64_outl
-#undef __ia64_readb
-#undef __ia64_readw
-#undef __ia64_readl
-#undef __ia64_readq
-#undef __ia64_readb_relaxed
-#undef __ia64_readw_relaxed
-#undef __ia64_readl_relaxed
-#undef __ia64_readq_relaxed
-#undef __ia64_writeb
-#undef __ia64_writew
-#undef __ia64_writel
-#undef __ia64_writeq
-#undef __ia64_mmiowb
-
-unsigned int
-__ia64_inb (unsigned long port)
-{
- return ___ia64_inb(port);
-}
-
-unsigned int
-__ia64_inw (unsigned long port)
-{
- return ___ia64_inw(port);
-}
-
-unsigned int
-__ia64_inl (unsigned long port)
-{
- return ___ia64_inl(port);
-}
-
-void
-__ia64_outb (unsigned char val, unsigned long port)
-{
- ___ia64_outb(val, port);
-}
-
-void
-__ia64_outw (unsigned short val, unsigned long port)
-{
- ___ia64_outw(val, port);
-}
-
-void
-__ia64_outl (unsigned int val, unsigned long port)
-{
- ___ia64_outl(val, port);
-}
-
-unsigned char
-__ia64_readb (void __iomem *addr)
-{
- return ___ia64_readb (addr);
-}
-
-unsigned short
-__ia64_readw (void __iomem *addr)
-{
- return ___ia64_readw (addr);
-}
-
-unsigned int
-__ia64_readl (void __iomem *addr)
-{
- return ___ia64_readl (addr);
-}
-
-unsigned long
-__ia64_readq (void __iomem *addr)
-{
- return ___ia64_readq (addr);
-}
-
-unsigned char
-__ia64_readb_relaxed (void __iomem *addr)
-{
- return ___ia64_readb (addr);
-}
-
-unsigned short
-__ia64_readw_relaxed (void __iomem *addr)
-{
- return ___ia64_readw (addr);
-}
-
-unsigned int
-__ia64_readl_relaxed (void __iomem *addr)
-{
- return ___ia64_readl (addr);
-}
-
-unsigned long
-__ia64_readq_relaxed (void __iomem *addr)
-{
- return ___ia64_readq (addr);
-}
-
-void
-__ia64_mmiowb(void)
-{
- ___ia64_mmiowb();
-}
-
-#endif /* CONFIG_IA64_GENERIC */
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 05490dd073e6..921f3efe3538 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -396,8 +396,7 @@ static void __meminit scatter_node_data(void)
*
* 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. The active_cpus field of the per-node
- * structure gets setup by the platform_cpu_init() function later.
+ * to the local node data structure.
*/
static void __init initialize_pernode_data(void)
{
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index aae75fd7b810..678b98a09c85 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/dma-noncoherent.h>
+#include <linux/dmar.h>
#include <linux/efi.h>
#include <linux/elf.h>
#include <linux/memblock.h>
@@ -23,10 +24,10 @@
#include <linux/proc_fs.h>
#include <linux/bitops.h>
#include <linux/kexec.h>
+#include <linux/swiotlb.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/machvec.h>
#include <asm/numa.h>
#include <asm/patch.h>
#include <asm/pgalloc.h>
@@ -67,7 +68,6 @@ __ia64_sync_icache_dcache (pte_t pte)
set_bit(PG_arch_1, &page->flags); /* mark page as clean */
}
-#ifdef CONFIG_SWIOTLB
/*
* 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
@@ -82,7 +82,6 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
set_bit(PG_arch_1, &pfn_to_page(pfn)->flags);
} while (++pfn <= PHYS_PFN(paddr + size - 1));
}
-#endif
inline void
ia64_set_rbs_bot (void)
@@ -632,13 +631,17 @@ mem_init (void)
BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE);
BUG_ON(PTRS_PER_PTE * sizeof(pte_t) != PAGE_SIZE);
-#ifdef CONFIG_PCI
/*
- * 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.
+ * 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.
*/
- platform_dma_init();
+#ifdef CONFIG_INTEL_IOMMU
+ detect_intel_iommu();
+ if (!iommu_detected)
+#endif
+#ifdef CONFIG_SWIOTLB
+ swiotlb_init(1);
#endif
#ifdef CONFIG_FLATMEM
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 0714df1b7854..72cc568bc841 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -245,7 +245,8 @@ resetsema:
spinaphore_init(&ptcg_sem, max_purges);
}
-void
+#ifdef CONFIG_SMP
+static void
ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned long nbits)
{
@@ -282,6 +283,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
activate_context(active_mm);
}
}
+#endif /* CONFIG_SMP */
void
local_flush_tlb_all (void)
@@ -332,7 +334,7 @@ __flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
preempt_disable();
#ifdef CONFIG_SMP
if (mm != current->active_mm || cpumask_weight(mm_cpumask(mm)) != 1) {
- platform_global_tlb_purge(mm, start, end, nbits);
+ ia64_global_tlb_purge(mm, start, end, nbits);
preempt_enable();
return;
}
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c
index e1fa45b2148c..acb55a41260d 100644
--- a/arch/ia64/pci/fixup.c
+++ b/arch/ia64/pci/fixup.c
@@ -8,8 +8,7 @@
#include <linux/init.h>
#include <linux/vgaarb.h>
#include <linux/screen_info.h>
-
-#include <asm/machvec.h>
+#include <asm/uv/uv.h>
/*
* Fixup to mark boot BIOS video selected by BIOS before it changes
@@ -35,8 +34,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
u16 config;
struct resource *res;
- if ((strcmp(ia64_platform_name, "dig") != 0)
- && (strcmp(ia64_platform_name, "hpzx1") != 0))
+ if (is_uv_system())
return;
/* Maybe, this machine supports legacy memory map. */
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 165e561dc81a..211757e34198 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -24,7 +24,6 @@
#include <linux/memblock.h>
#include <linux/export.h>
-#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/io.h>
#include <asm/sal.h>
@@ -372,7 +371,6 @@ void pcibios_fixup_bus(struct pci_bus *b)
}
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
- platform_pci_fixup_bus(b);
}
void pcibios_add_bus(struct pci_bus *bus)
@@ -413,7 +411,7 @@ pcibios_disable_device (struct pci_dev *dev)
}
/**
- * ia64_pci_get_legacy_mem - generic legacy mem routine
+ * 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
@@ -424,7 +422,7 @@ pcibios_disable_device (struct pci_dev *dev)
* This is the ia64 generic version of this routine. Other platforms
* are free to override it with a machine vector.
*/
-char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
+char *pci_get_legacy_mem(struct pci_bus *bus)
{
return (char *)__IA64_UNCACHED_OFFSET;
}
@@ -473,7 +471,7 @@ pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
}
/**
- * ia64_pci_legacy_read - read from legacy I/O space
+ * pci_legacy_read - read from legacy I/O space
* @bus: bus to read
* @port: legacy port value
* @val: caller allocated storage for returned value
@@ -485,7 +483,7 @@ pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
* 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 ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
+int pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
{
int ret = size;
@@ -508,7 +506,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
}
/**
- * ia64_pci_legacy_write - perform a legacy I/O write
+ * pci_legacy_write - perform a legacy I/O write
* @bus: bus pointer
* @port: port to write
* @val: value to write
@@ -516,7 +514,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
*
* Simply writes @size bytes of @val to @port.
*/
-int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
+int pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
{
int ret = size;
diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile
deleted file mode 100644
index 79a7df02e812..000000000000
--- a/arch/ia64/sn/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# arch/ia64/sn/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) 2004 Silicon Graphics, Inc. All Rights Reserved.
-#
-# Makefile for the sn ia64 subplatform
-#
-
-obj-y += kernel/ pci/
diff --git a/arch/ia64/sn/include/ioerror.h b/arch/ia64/sn/include/ioerror.h
deleted file mode 100644
index e68f2b0789a7..000000000000
--- a/arch/ia64/sn/include/ioerror.h
+++ /dev/null
@@ -1,81 +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-2003 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_IOERROR_H
-#define _ASM_IA64_SN_IOERROR_H
-
-/*
- * IO error structure.
- *
- * This structure would expand to hold the information retrieved from
- * all IO related error registers.
- *
- * This structure is defined to hold all system specific
- * information related to a single error.
- *
- * This serves a couple of purpose.
- * - Error handling often involves translating one form of address to other
- * form. So, instead of having different data structures at each level,
- * we have a single structure, and the appropriate fields get filled in
- * at each layer.
- * - This provides a way to dump all error related information in any layer
- * of erorr handling (debugging aid).
- *
- * A second possibility is to allow each layer to define its own error
- * data structure, and fill in the proper fields. This has the advantage
- * of isolating the layers.
- * A big concern is the potential stack usage (and overflow), if each layer
- * defines these structures on stack (assuming we don't want to do kmalloc.
- *
- * Any layer wishing to pass extra information to a layer next to it in
- * error handling hierarchy, can do so as a separate parameter.
- */
-
-typedef struct io_error_s {
- /* Bit fields indicating which structure fields are valid */
- union {
- struct {
- unsigned ievb_errortype:1;
- unsigned ievb_widgetnum:1;
- unsigned ievb_widgetdev:1;
- unsigned ievb_srccpu:1;
- unsigned ievb_srcnode:1;
- unsigned ievb_errnode:1;
- unsigned ievb_sysioaddr:1;
- unsigned ievb_xtalkaddr:1;
- unsigned ievb_busspace:1;
- unsigned ievb_busaddr:1;
- unsigned ievb_vaddr:1;
- unsigned ievb_memaddr:1;
- unsigned ievb_epc:1;
- unsigned ievb_ef:1;
- unsigned ievb_tnum:1;
- } iev_b;
- unsigned iev_a;
- } ie_v;
-
- short ie_errortype; /* error type: extra info about error */
- short ie_widgetnum; /* Widget number that's in error */
- short ie_widgetdev; /* Device within widget in error */
- cpuid_t ie_srccpu; /* CPU on srcnode generating error */
- cnodeid_t ie_srcnode; /* Node which caused the error */
- cnodeid_t ie_errnode; /* Node where error was noticed */
- iopaddr_t ie_sysioaddr; /* Sys specific IO address */
- iopaddr_t ie_xtalkaddr; /* Xtalk (48bit) addr of Error */
- iopaddr_t ie_busspace; /* Bus specific address space */
- iopaddr_t ie_busaddr; /* Bus specific address */
- caddr_t ie_vaddr; /* Virtual address of error */
- iopaddr_t ie_memaddr; /* Physical memory address */
- caddr_t ie_epc; /* pc when error reported */
- caddr_t ie_ef; /* eframe when error reported */
- short ie_tnum; /* Xtalk TNUM field */
-} ioerror_t;
-
-#define IOERROR_INIT(e) do { (e)->ie_v.iev_a = 0; } while (0)
-#define IOERROR_SETVALUE(e,f,v) do { (e)->ie_ ## f = (v); (e)->ie_v.iev_b.ievb_ ## f = 1; } while (0)
-
-#endif /* _ASM_IA64_SN_IOERROR_H */
diff --git a/arch/ia64/sn/include/tio.h b/arch/ia64/sn/include/tio.h
deleted file mode 100644
index 6b2e7b75eb19..000000000000
--- a/arch/ia64/sn/include/tio.h
+++ /dev/null
@@ -1,41 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_TIO_H
-#define _ASM_IA64_SN_TIO_H
-
-#define TIO_MMR_ADDR_MOD
-
-#define TIO_NODE_ID TIO_MMR_ADDR_MOD(0x0000000090060e80)
-
-#define TIO_ITTE_BASE 0xb0008800 /* base of translation table entries */
-#define TIO_ITTE(bigwin) (TIO_ITTE_BASE + 8*(bigwin))
-
-#define TIO_ITTE_OFFSET_BITS 8 /* size of offset field */
-#define TIO_ITTE_OFFSET_MASK ((1<<TIO_ITTE_OFFSET_BITS)-1)
-#define TIO_ITTE_OFFSET_SHIFT 0
-
-#define TIO_ITTE_WIDGET_BITS 2 /* size of widget field */
-#define TIO_ITTE_WIDGET_MASK ((1<<TIO_ITTE_WIDGET_BITS)-1)
-#define TIO_ITTE_WIDGET_SHIFT 12
-#define TIO_ITTE_VALID_MASK 0x1
-#define TIO_ITTE_VALID_SHIFT 16
-
-#define TIO_ITTE_WIDGET(itte) \
- (((itte) >> TIO_ITTE_WIDGET_SHIFT) & TIO_ITTE_WIDGET_MASK)
-#define TIO_ITTE_VALID(itte) \
- (((itte) >> TIO_ITTE_VALID_SHIFT) & TIO_ITTE_VALID_MASK)
-
-#define TIO_ITTE_PUT(nasid, bigwin, widget, addr, valid) \
- REMOTE_HUB_S((nasid), TIO_ITTE(bigwin), \
- (((((addr) >> TIO_BWIN_SIZE_BITS) & \
- TIO_ITTE_OFFSET_MASK) << TIO_ITTE_OFFSET_SHIFT) | \
- (((widget) & TIO_ITTE_WIDGET_MASK) << TIO_ITTE_WIDGET_SHIFT)) | \
- (( (valid) & TIO_ITTE_VALID_MASK) << TIO_ITTE_VALID_SHIFT))
-
-#endif /* _ASM_IA64_SN_TIO_H */
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
deleted file mode 100644
index 8182583c762c..000000000000
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ /dev/null
@@ -1,91 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_XTALK_HUBDEV_H
-#define _ASM_IA64_SN_XTALK_HUBDEV_H
-
-#include "xtalk/xwidgetdev.h"
-
-#define HUB_WIDGET_ID_MAX 0xf
-#define DEV_PER_WIDGET (2*2*8)
-#define IIO_ITTE_WIDGET_BITS 4 /* size of widget field */
-#define IIO_ITTE_WIDGET_MASK ((1<<IIO_ITTE_WIDGET_BITS)-1)
-#define IIO_ITTE_WIDGET_SHIFT 8
-
-#define IIO_ITTE_WIDGET(itte) \
- (((itte) >> IIO_ITTE_WIDGET_SHIFT) & IIO_ITTE_WIDGET_MASK)
-
-/*
- * Use the top big window as a surrogate for the first small window
- */
-#define SWIN0_BIGWIN HUB_NUM_BIG_WINDOW
-#define IIO_NUM_ITTES 7
-#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
-
-/* This struct is shared between the PROM and the kernel.
- * Changes to this struct will require corresponding changes to the kernel.
- */
-struct sn_flush_device_common {
- int sfdl_bus;
- int sfdl_slot;
- int sfdl_pin;
- struct common_bar_list {
- unsigned long start;
- unsigned long end;
- } sfdl_bar_list[6];
- unsigned long sfdl_force_int_addr;
- unsigned long sfdl_flush_value;
- volatile unsigned long *sfdl_flush_addr;
- u32 sfdl_persistent_busnum;
- u32 sfdl_persistent_segment;
- struct pcibus_info *sfdl_pcibus_info;
-};
-
-/* This struct is kernel only and is not used by the PROM */
-struct sn_flush_device_kernel {
- spinlock_t sfdl_flush_lock;
- struct sn_flush_device_common *common;
-};
-
-/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included
- * for older official PROMs to function on the new kernel base. This struct
- * will be removed when the next official PROM release occurs. */
-
-struct sn_flush_device_war {
- struct sn_flush_device_common common;
- u32 filler; /* older PROMs expect the default size of a spinlock_t */
-};
-
-/*
- * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
- */
-struct sn_flush_nasid_entry {
- struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num
- u64 iio_itte[8];
-};
-
-struct hubdev_info {
- geoid_t hdi_geoid;
- short hdi_nasid;
- short hdi_peer_nasid; /* Dual Porting Peer */
-
- struct sn_flush_nasid_entry hdi_flush_nasid_list;
- struct xwidget_info hdi_xwidget_info[HUB_WIDGET_ID_MAX + 1];
-
-
- void *hdi_nodepda;
- void *hdi_node_vertex;
- u32 max_segment_number;
- u32 max_pcibus_number;
-};
-
-extern void hubdev_init_node(nodepda_t *, cnodeid_t);
-extern void hub_error_init(struct hubdev_info *);
-extern void ice_error_init(struct hubdev_info *);
-
-
-#endif /* _ASM_IA64_SN_XTALK_HUBDEV_H */
diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h
deleted file mode 100644
index 90f37a4133d0..000000000000
--- a/arch/ia64/sn/include/xtalk/xbow.h
+++ /dev/null
@@ -1,301 +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_XTALK_XBOW_H
-#define _ASM_IA64_SN_XTALK_XBOW_H
-
-#define XBOW_PORT_8 0x8
-#define XBOW_PORT_C 0xc
-#define XBOW_PORT_F 0xf
-
-#define MAX_XBOW_PORTS 8 /* number of ports on xbow chip */
-#define BASE_XBOW_PORT XBOW_PORT_8 /* Lowest external port */
-
-#define XBOW_CREDIT 4
-
-#define MAX_XBOW_NAME 16
-
-/* Register set for each xbow link */
-typedef volatile struct xb_linkregs_s {
-/*
- * we access these through synergy unswizzled space, so the address
- * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
- * That's why we put the register first and filler second.
- */
- u32 link_ibf;
- u32 filler0; /* filler for proper alignment */
- u32 link_control;
- u32 filler1;
- u32 link_status;
- u32 filler2;
- u32 link_arb_upper;
- u32 filler3;
- u32 link_arb_lower;
- u32 filler4;
- u32 link_status_clr;
- u32 filler5;
- u32 link_reset;
- u32 filler6;
- u32 link_aux_status;
- u32 filler7;
-} xb_linkregs_t;
-
-typedef volatile struct xbow_s {
- /* standard widget configuration 0x000000-0x000057 */
- struct widget_cfg xb_widget; /* 0x000000 */
-
- /* helper fieldnames for accessing bridge widget */
-
-#define xb_wid_id xb_widget.w_id
-#define xb_wid_stat xb_widget.w_status
-#define xb_wid_err_upper xb_widget.w_err_upper_addr
-#define xb_wid_err_lower xb_widget.w_err_lower_addr
-#define xb_wid_control xb_widget.w_control
-#define xb_wid_req_timeout xb_widget.w_req_timeout
-#define xb_wid_int_upper xb_widget.w_intdest_upper_addr
-#define xb_wid_int_lower xb_widget.w_intdest_lower_addr
-#define xb_wid_err_cmdword xb_widget.w_err_cmd_word
-#define xb_wid_llp xb_widget.w_llp_cfg
-#define xb_wid_stat_clr xb_widget.w_tflush
-
-/*
- * we access these through synergy unswizzled space, so the address
- * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
- * That's why we put the register first and filler second.
- */
- /* xbow-specific widget configuration 0x000058-0x0000FF */
- u32 xb_wid_arb_reload; /* 0x00005C */
- u32 _pad_000058;
- u32 xb_perf_ctr_a; /* 0x000064 */
- u32 _pad_000060;
- u32 xb_perf_ctr_b; /* 0x00006c */
- u32 _pad_000068;
- u32 xb_nic; /* 0x000074 */
- u32 _pad_000070;
-
- /* Xbridge only */
- u32 xb_w0_rst_fnc; /* 0x00007C */
- u32 _pad_000078;
- u32 xb_l8_rst_fnc; /* 0x000084 */
- u32 _pad_000080;
- u32 xb_l9_rst_fnc; /* 0x00008c */
- u32 _pad_000088;
- u32 xb_la_rst_fnc; /* 0x000094 */
- u32 _pad_000090;
- u32 xb_lb_rst_fnc; /* 0x00009c */
- u32 _pad_000098;
- u32 xb_lc_rst_fnc; /* 0x0000a4 */
- u32 _pad_0000a0;
- u32 xb_ld_rst_fnc; /* 0x0000ac */
- u32 _pad_0000a8;
- u32 xb_le_rst_fnc; /* 0x0000b4 */
- u32 _pad_0000b0;
- u32 xb_lf_rst_fnc; /* 0x0000bc */
- u32 _pad_0000b8;
- u32 xb_lock; /* 0x0000c4 */
- u32 _pad_0000c0;
- u32 xb_lock_clr; /* 0x0000cc */
- u32 _pad_0000c8;
- /* end of Xbridge only */
- u32 _pad_0000d0[12];
-
- /* Link Specific Registers, port 8..15 0x000100-0x000300 */
- xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS];
-} xbow_t;
-
-#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)]
-
-#define XB_FLAGS_EXISTS 0x1 /* device exists */
-#define XB_FLAGS_MASTER 0x2
-#define XB_FLAGS_SLAVE 0x0
-#define XB_FLAGS_GBR 0x4
-#define XB_FLAGS_16BIT 0x8
-#define XB_FLAGS_8BIT 0x0
-
-/* is widget port number valid? (based on version 7.0 of xbow spec) */
-#define XBOW_WIDGET_IS_VALID(wid) ((wid) >= XBOW_PORT_8 && (wid) <= XBOW_PORT_F)
-
-/* whether to use upper or lower arbitration register, given source widget id */
-#define XBOW_ARB_IS_UPPER(wid) ((wid) >= XBOW_PORT_8 && (wid) <= XBOW_PORT_B)
-#define XBOW_ARB_IS_LOWER(wid) ((wid) >= XBOW_PORT_C && (wid) <= XBOW_PORT_F)
-
-/* offset of arbitration register, given source widget id */
-#define XBOW_ARB_OFF(wid) (XBOW_ARB_IS_UPPER(wid) ? 0x1c : 0x24)
-
-#define XBOW_WID_ID WIDGET_ID
-#define XBOW_WID_STAT WIDGET_STATUS
-#define XBOW_WID_ERR_UPPER WIDGET_ERR_UPPER_ADDR
-#define XBOW_WID_ERR_LOWER WIDGET_ERR_LOWER_ADDR
-#define XBOW_WID_CONTROL WIDGET_CONTROL
-#define XBOW_WID_REQ_TO WIDGET_REQ_TIMEOUT
-#define XBOW_WID_INT_UPPER WIDGET_INTDEST_UPPER_ADDR
-#define XBOW_WID_INT_LOWER WIDGET_INTDEST_LOWER_ADDR
-#define XBOW_WID_ERR_CMDWORD WIDGET_ERR_CMD_WORD
-#define XBOW_WID_LLP WIDGET_LLP_CFG
-#define XBOW_WID_STAT_CLR WIDGET_TFLUSH
-#define XBOW_WID_ARB_RELOAD 0x5c
-#define XBOW_WID_PERF_CTR_A 0x64
-#define XBOW_WID_PERF_CTR_B 0x6c
-#define XBOW_WID_NIC 0x74
-
-/* Xbridge only */
-#define XBOW_W0_RST_FNC 0x00007C
-#define XBOW_L8_RST_FNC 0x000084
-#define XBOW_L9_RST_FNC 0x00008c
-#define XBOW_LA_RST_FNC 0x000094
-#define XBOW_LB_RST_FNC 0x00009c
-#define XBOW_LC_RST_FNC 0x0000a4
-#define XBOW_LD_RST_FNC 0x0000ac
-#define XBOW_LE_RST_FNC 0x0000b4
-#define XBOW_LF_RST_FNC 0x0000bc
-#define XBOW_RESET_FENCE(x) ((x) > 7 && (x) < 16) ? \
- (XBOW_W0_RST_FNC + ((x) - 7) * 8) : \
- ((x) == 0) ? XBOW_W0_RST_FNC : 0
-#define XBOW_LOCK 0x0000c4
-#define XBOW_LOCK_CLR 0x0000cc
-/* End of Xbridge only */
-
-/* used only in ide, but defined here within the reserved portion */
-/* of the widget0 address space (before 0xf4) */
-#define XBOW_WID_UNDEF 0xe4
-
-/* xbow link register set base, legal value for x is 0x8..0xf */
-#define XB_LINK_BASE 0x100
-#define XB_LINK_OFFSET 0x40
-#define XB_LINK_REG_BASE(x) (XB_LINK_BASE + ((x) & (MAX_XBOW_PORTS - 1)) * XB_LINK_OFFSET)
-
-#define XB_LINK_IBUF_FLUSH(x) (XB_LINK_REG_BASE(x) + 0x4)
-#define XB_LINK_CTRL(x) (XB_LINK_REG_BASE(x) + 0xc)
-#define XB_LINK_STATUS(x) (XB_LINK_REG_BASE(x) + 0x14)
-#define XB_LINK_ARB_UPPER(x) (XB_LINK_REG_BASE(x) + 0x1c)
-#define XB_LINK_ARB_LOWER(x) (XB_LINK_REG_BASE(x) + 0x24)
-#define XB_LINK_STATUS_CLR(x) (XB_LINK_REG_BASE(x) + 0x2c)
-#define XB_LINK_RESET(x) (XB_LINK_REG_BASE(x) + 0x34)
-#define XB_LINK_AUX_STATUS(x) (XB_LINK_REG_BASE(x) + 0x3c)
-
-/* link_control(x) */
-#define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */
-/* reserved: 0x40000000 */
-#define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */
-#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer
- level */
-#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8
- bit mode */
-#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP
- packet */
-#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit
- mask */
-#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit
- shift */
-#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination
- */
-#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input
- buffer */
-/* reserved: 0x0000fe00 */
-#define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */
-#define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */
-#define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */
-#define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */
-#define XB_CTRL_RCV_IE 0x00000010 /* receive */
-#define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */
-/* reserved: 0x00000004 */
-#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request
- timeout */
-#define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */
-
-/* link_status(x) */
-#define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE
-/* reserved: 0x7ff80000 */
-#define XB_STAT_MULTI_ERR 0x00040000 /* multi error */
-#define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE
-#define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE
-#define XB_STAT_BNDWDTH_ALLOC_ID_MSK 0x0000ff00 /* port bitmask */
-#define XB_STAT_RCV_CNT_OFLOW_ERR XB_CTRL_RCV_CNT_OFLOW_IE
-#define XB_STAT_XMT_CNT_OFLOW_ERR XB_CTRL_XMT_CNT_OFLOW_IE
-#define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE
-#define XB_STAT_RCV_ERR XB_CTRL_RCV_IE
-#define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE
-/* reserved: 0x00000004 */
-#define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE
-#define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE
-
-/* link_aux_status(x) */
-#define XB_AUX_STAT_RCV_CNT 0xff000000
-#define XB_AUX_STAT_XMT_CNT 0x00ff0000
-#define XB_AUX_STAT_TOUT_DST 0x0000ff00
-#define XB_AUX_LINKFAIL_RST_BAD 0x00000040
-#define XB_AUX_STAT_PRESENT 0x00000020
-#define XB_AUX_STAT_PORT_WIDTH 0x00000010
-/* reserved: 0x0000000f */
-
-/*
- * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper
- * register if (x) is 0x8..0xb, link_arb_lower if (x) is 0xc..0xf
- */
-#define XB_ARB_GBR_MSK 0x1f
-#define XB_ARB_RR_MSK 0x7
-#define XB_ARB_GBR_SHFT(x) (((x) & 0x3) * 8)
-#define XB_ARB_RR_SHFT(x) (((x) & 0x3) * 8 + 5)
-#define XB_ARB_GBR_CNT(reg,x) ((reg) >> XB_ARB_GBR_SHFT(x) & XB_ARB_GBR_MSK)
-#define XB_ARB_RR_CNT(reg,x) ((reg) >> XB_ARB_RR_SHFT(x) & XB_ARB_RR_MSK)
-
-/* XBOW_WID_STAT */
-#define XB_WID_STAT_LINK_INTR_SHFT (24)
-#define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT)
-#define XB_WID_STAT_LINK_INTR(x) \
- (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT))
-#define XB_WID_STAT_WIDGET0_INTR 0x00800000
-#define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */
-#define XB_WID_STAT_REG_ACC_ERR 0x00000020
-#define XB_WID_STAT_RECV_TOUT 0x00000010 /* Xbridge only */
-#define XB_WID_STAT_ARB_TOUT 0x00000008 /* Xbridge only */
-#define XB_WID_STAT_XTALK_ERR 0x00000004
-#define XB_WID_STAT_DST_TOUT 0x00000002 /* Xbridge only */
-#define XB_WID_STAT_MULTI_ERR 0x00000001
-
-#define XB_WID_STAT_SRCID_SHFT 6
-
-/* XBOW_WID_CONTROL */
-#define XB_WID_CTRL_REG_ACC_IE XB_WID_STAT_REG_ACC_ERR
-#define XB_WID_CTRL_RECV_TOUT XB_WID_STAT_RECV_TOUT
-#define XB_WID_CTRL_ARB_TOUT XB_WID_STAT_ARB_TOUT
-#define XB_WID_CTRL_XTALK_IE XB_WID_STAT_XTALK_ERR
-
-/* XBOW_WID_INT_UPPER */
-/* defined in xwidget.h for WIDGET_INTDEST_UPPER_ADDR */
-
-/* XBOW WIDGET part number, in the ID register */
-#define XBOW_WIDGET_PART_NUM 0x0 /* crossbow */
-#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */
-#define XBOW_WIDGET_MFGR_NUM 0x0
-#define XXBOW_WIDGET_MFGR_NUM 0x0
-#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */
-
-#define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */
-#define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */
-#define XBOW_REV_1_2 0x3 /* xbow rev 1.2 is "3" */
-#define XBOW_REV_1_3 0x4 /* xbow rev 1.3 is "4" */
-#define XBOW_REV_2_0 0x5 /* xbow rev 2.0 is "5" */
-
-#define XXBOW_PART_REV_1_0 (XXBOW_WIDGET_PART_NUM << 4 | 0x1 )
-#define XXBOW_PART_REV_2_0 (XXBOW_WIDGET_PART_NUM << 4 | 0x2 )
-
-/* XBOW_WID_ARB_RELOAD */
-#define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */
-
-#define IS_XBRIDGE_XBOW(wid) \
- (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \
- XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
-
-#define IS_PIC_XBOW(wid) \
- (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \
- XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
-
-#define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv)
-
-#endif /* _ASM_IA64_SN_XTALK_XBOW_H */
diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h
deleted file mode 100644
index 2800eda0fd68..000000000000
--- a/arch/ia64/sn/include/xtalk/xwidgetdev.h
+++ /dev/null
@@ -1,70 +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-2003 Silicon Graphics, Inc. All Rights Reserved.
- */
-#ifndef _ASM_IA64_SN_XTALK_XWIDGET_H
-#define _ASM_IA64_SN_XTALK_XWIDGET_H
-
-/* WIDGET_ID */
-#define WIDGET_REV_NUM 0xf0000000
-#define WIDGET_PART_NUM 0x0ffff000
-#define WIDGET_MFG_NUM 0x00000ffe
-#define WIDGET_REV_NUM_SHFT 28
-#define WIDGET_PART_NUM_SHFT 12
-#define WIDGET_MFG_NUM_SHFT 1
-
-#define XWIDGET_PART_NUM(widgetid) (((widgetid) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT)
-#define XWIDGET_REV_NUM(widgetid) (((widgetid) & WIDGET_REV_NUM) >> WIDGET_REV_NUM_SHFT)
-#define XWIDGET_MFG_NUM(widgetid) (((widgetid) & WIDGET_MFG_NUM) >> WIDGET_MFG_NUM_SHFT)
-#define XWIDGET_PART_REV_NUM(widgetid) ((XWIDGET_PART_NUM(widgetid) << 4) | \
- XWIDGET_REV_NUM(widgetid))
-#define XWIDGET_PART_REV_NUM_REV(partrev) (partrev & 0xf)
-
-/* widget configuration registers */
-struct widget_cfg{
- u32 w_id; /* 0x04 */
- u32 w_pad_0; /* 0x00 */
- u32 w_status; /* 0x0c */
- u32 w_pad_1; /* 0x08 */
- u32 w_err_upper_addr; /* 0x14 */
- u32 w_pad_2; /* 0x10 */
- u32 w_err_lower_addr; /* 0x1c */
- u32 w_pad_3; /* 0x18 */
- u32 w_control; /* 0x24 */
- u32 w_pad_4; /* 0x20 */
- u32 w_req_timeout; /* 0x2c */
- u32 w_pad_5; /* 0x28 */
- u32 w_intdest_upper_addr; /* 0x34 */
- u32 w_pad_6; /* 0x30 */
- u32 w_intdest_lower_addr; /* 0x3c */
- u32 w_pad_7; /* 0x38 */
- u32 w_err_cmd_word; /* 0x44 */
- u32 w_pad_8; /* 0x40 */
- u32 w_llp_cfg; /* 0x4c */
- u32 w_pad_9; /* 0x48 */
- u32 w_tflush; /* 0x54 */
- u32 w_pad_10; /* 0x50 */
-};
-
-/*
- * Crosstalk Widget Hardware Identification, as defined in the Crosstalk spec.
- */
-struct xwidget_hwid{
- int mfg_num;
- int rev_num;
- int part_num;
-};
-
-struct xwidget_info{
-
- struct xwidget_hwid xwi_hwid; /* Widget Identification */
- char xwi_masterxid; /* Hub's Widget Port Number */
- void *xwi_hubinfo; /* Hub's provider private info */
- u64 *xwi_hub_provider; /* prom provider functions */
- void *xwi_vertex;
-};
-
-#endif /* _ASM_IA64_SN_XTALK_XWIDGET_H */
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
deleted file mode 100644
index 9c349dd23265..000000000000
--- a/arch/ia64/sn/kernel/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# arch/ia64/sn/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) 1999,2001-2006,2008 Silicon Graphics, Inc. All Rights Reserved.
-#
-
-ccflags-y := -I $(srctree)/arch/ia64/sn/include
-
-obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
- huberror.o io_acpi_init.o io_common.o \
- io_init.o iomv.o klconflib.o pio_phys.o \
- sn2/
-obj-$(CONFIG_IA64_GENERIC) += machvec.o
-obj-$(CONFIG_SGI_TIOCX) += tiocx.o
-obj-$(CONFIG_PCI_MSI) += msi_sn.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
deleted file mode 100644
index 9900e6d4add6..000000000000
--- a/arch/ia64/sn/kernel/bte.c
+++ /dev/null
@@ -1,475 +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-2007 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/module.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/shubio.h>
-#include <asm/nodedata.h>
-#include <asm/delay.h>
-
-#include <linux/memblock.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <asm/sn/bte.h>
-
-#ifndef L1_CACHE_MASK
-#define L1_CACHE_MASK (L1_CACHE_BYTES - 1)
-#endif
-
-/* two interfaces on two btes */
-#define MAX_INTERFACES_TO_TRY 4
-#define MAX_NODES_TO_TRY 2
-
-static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface)
-{
- nodepda_t *tmp_nodepda;
-
- if (nasid_to_cnodeid(nasid) == -1)
- return (struct bteinfo_s *)NULL;
-
- tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid));
- return &tmp_nodepda->bte_if[interface];
-
-}
-
-static inline void bte_start_transfer(struct bteinfo_s *bte, u64 len, u64 mode)
-{
- if (is_shub2()) {
- BTE_CTRL_STORE(bte, (IBLS_BUSY | ((len) | (mode) << 24)));
- } else {
- BTE_LNSTAT_STORE(bte, len);
- BTE_CTRL_STORE(bte, mode);
- }
-}
-
-/************************************************************************
- * Block Transfer Engine copy related functions.
- *
- ***********************************************************************/
-
-/*
- * bte_copy(src, dest, len, mode, notification)
- *
- * Use the block transfer engine to move kernel memory from src to dest
- * using the assigned mode.
- *
- * Parameters:
- * src - physical address of the transfer source.
- * dest - physical address of the transfer destination.
- * len - number of bytes to transfer from source to dest.
- * mode - hardware defined. See reference information
- * for IBCT0/1 in the SHUB Programmers Reference
- * notification - kernel virtual address of the notification cache
- * line. If NULL, the default is used and
- * the bte_copy is synchronous.
- *
- * NOTE: This function requires src, dest, and len to
- * be cacheline aligned.
- */
-bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
-{
- u64 transfer_size;
- u64 transfer_stat;
- u64 notif_phys_addr;
- struct bteinfo_s *bte;
- bte_result_t bte_status;
- unsigned long irq_flags;
- unsigned long itc_end = 0;
- int nasid_to_try[MAX_NODES_TO_TRY];
- int my_nasid = cpuid_to_nasid(raw_smp_processor_id());
- int bte_if_index, nasid_index;
- int bte_first, btes_per_node = BTES_PER_NODE;
-
- BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n",
- src, dest, len, mode, notification));
-
- if (len == 0) {
- return BTE_SUCCESS;
- }
-
- BUG_ON(len & L1_CACHE_MASK);
- BUG_ON(src & L1_CACHE_MASK);
- BUG_ON(dest & L1_CACHE_MASK);
- BUG_ON(len > BTE_MAX_XFER);
-
- /*
- * Start with interface corresponding to cpu number
- */
- bte_first = raw_smp_processor_id() % btes_per_node;
-
- if (mode & BTE_USE_DEST) {
- /* try remote then local */
- nasid_to_try[0] = NASID_GET(dest);
- if (mode & BTE_USE_ANY) {
- nasid_to_try[1] = my_nasid;
- } else {
- nasid_to_try[1] = 0;
- }
- } else {
- /* try local then remote */
- nasid_to_try[0] = my_nasid;
- if (mode & BTE_USE_ANY) {
- nasid_to_try[1] = NASID_GET(dest);
- } else {
- nasid_to_try[1] = 0;
- }
- }
-
-retry_bteop:
- do {
- local_irq_save(irq_flags);
-
- bte_if_index = bte_first;
- nasid_index = 0;
-
- /* Attempt to lock one of the BTE interfaces. */
- while (nasid_index < MAX_NODES_TO_TRY) {
- bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index);
-
- if (bte == NULL) {
- nasid_index++;
- continue;
- }
-
- if (spin_trylock(&bte->spinlock)) {
- if (!(*bte->most_rcnt_na & BTE_WORD_AVAILABLE) ||
- (BTE_LNSTAT_LOAD(bte) & BTE_ACTIVE)) {
- /* Got the lock but BTE still busy */
- spin_unlock(&bte->spinlock);
- } else {
- /* we got the lock and it's not busy */
- break;
- }
- }
-
- bte_if_index = (bte_if_index + 1) % btes_per_node; /* Next interface */
- if (bte_if_index == bte_first) {
- /*
- * We've tried all interfaces on this node
- */
- nasid_index++;
- }
-
- bte = NULL;
- }
-
- if (bte != NULL) {
- break;
- }
-
- local_irq_restore(irq_flags);
-
- if (!(mode & BTE_WACQUIRE)) {
- return BTEFAIL_NOTAVAIL;
- }
- } while (1);
-
- if (notification == NULL) {
- /* User does not want to be notified. */
- bte->most_rcnt_na = &bte->notify;
- } else {
- bte->most_rcnt_na = notification;
- }
-
- /* Calculate the number of cache lines to transfer. */
- transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK);
-
- /* Initialize the notification to a known value. */
- *bte->most_rcnt_na = BTE_WORD_BUSY;
- notif_phys_addr = (u64)bte->most_rcnt_na;
-
- /* Set the source and destination registers */
- BTE_PRINTKV(("IBSA = 0x%lx)\n", src));
- BTE_SRC_STORE(bte, src);
- BTE_PRINTKV(("IBDA = 0x%lx)\n", dest));
- BTE_DEST_STORE(bte, dest);
-
- /* Set the notification register */
- BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr));
- BTE_NOTIF_STORE(bte, notif_phys_addr);
-
- /* Initiate the transfer */
- BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode)));
- bte_start_transfer(bte, transfer_size, BTE_VALID_MODE(mode));
-
- itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec);
-
- spin_unlock_irqrestore(&bte->spinlock, irq_flags);
-
- if (notification != NULL) {
- return BTE_SUCCESS;
- }
-
- while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) {
- cpu_relax();
- if (ia64_get_itc() > itc_end) {
- BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n",
- NASID_GET(bte->bte_base_addr), bte->bte_num,
- BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na) );
- bte->bte_error_count++;
- bte->bh_error = IBLS_ERROR;
- bte_error_handler(NODEPDA(bte->bte_cnode));
- *bte->most_rcnt_na = BTE_WORD_AVAILABLE;
- goto retry_bteop;
- }
- }
-
- BTE_PRINTKV((" Delay Done. IBLS = 0x%lx, most_rcnt_na = 0x%lx\n",
- BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na));
-
- if (transfer_stat & IBLS_ERROR) {
- bte_status = BTE_GET_ERROR_STATUS(transfer_stat);
- } else {
- bte_status = BTE_SUCCESS;
- }
- *bte->most_rcnt_na = BTE_WORD_AVAILABLE;
-
- BTE_PRINTK(("Returning status is 0x%lx and most_rcnt_na is 0x%lx\n",
- BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na));
-
- return bte_status;
-}
-
-EXPORT_SYMBOL(bte_copy);
-
-/*
- * bte_unaligned_copy(src, dest, len, mode)
- *
- * use the block transfer engine to move kernel
- * memory from src to dest using the assigned mode.
- *
- * Parameters:
- * src - physical address of the transfer source.
- * dest - physical address of the transfer destination.
- * len - number of bytes to transfer from source to dest.
- * mode - hardware defined. See reference information
- * for IBCT0/1 in the SGI documentation.
- *
- * NOTE: If the source, dest, and len are all cache line aligned,
- * then it would be _FAR_ preferable to use bte_copy instead.
- */
-bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
-{
- int destFirstCacheOffset;
- u64 headBteSource;
- u64 headBteLen;
- u64 headBcopySrcOffset;
- u64 headBcopyDest;
- u64 headBcopyLen;
- u64 footBteSource;
- u64 footBteLen;
- u64 footBcopyDest;
- u64 footBcopyLen;
- bte_result_t rv;
- char *bteBlock, *bteBlock_unaligned;
-
- if (len == 0) {
- return BTE_SUCCESS;
- }
-
- /* temporary buffer used during unaligned transfers */
- bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES, GFP_KERNEL);
- if (bteBlock_unaligned == NULL) {
- return BTEFAIL_NOTAVAIL;
- }
- bteBlock = (char *)L1_CACHE_ALIGN((u64) bteBlock_unaligned);
-
- headBcopySrcOffset = src & L1_CACHE_MASK;
- destFirstCacheOffset = dest & L1_CACHE_MASK;
-
- /*
- * At this point, the transfer is broken into
- * (up to) three sections. The first section is
- * from the start address to the first physical
- * cache line, the second is from the first physical
- * cache line to the last complete cache line,
- * and the third is from the last cache line to the
- * end of the buffer. The first and third sections
- * are handled by bte copying into a temporary buffer
- * and then bcopy'ing the necessary section into the
- * final location. The middle section is handled with
- * a standard bte copy.
- *
- * One nasty exception to the above rule is when the
- * source and destination are not symmetrically
- * mis-aligned. If the source offset from the first
- * cache line is different from the destination offset,
- * we make the first section be the entire transfer
- * and the bcopy the entire block into place.
- */
- if (headBcopySrcOffset == destFirstCacheOffset) {
-
- /*
- * Both the source and destination are the same
- * distance from a cache line boundary so we can
- * use the bte to transfer the bulk of the
- * data.
- */
- headBteSource = src & ~L1_CACHE_MASK;
- headBcopyDest = dest;
- if (headBcopySrcOffset) {
- headBcopyLen =
- (len >
- (L1_CACHE_BYTES -
- headBcopySrcOffset) ? L1_CACHE_BYTES
- - headBcopySrcOffset : len);
- headBteLen = L1_CACHE_BYTES;
- } else {
- headBcopyLen = 0;
- headBteLen = 0;
- }
-
- if (len > headBcopyLen) {
- footBcopyLen = (len - headBcopyLen) & L1_CACHE_MASK;
- footBteLen = L1_CACHE_BYTES;
-
- footBteSource = src + len - footBcopyLen;
- footBcopyDest = dest + len - footBcopyLen;
-
- if (footBcopyDest == (headBcopyDest + headBcopyLen)) {
- /*
- * We have two contiguous bcopy
- * blocks. Merge them.
- */
- headBcopyLen += footBcopyLen;
- headBteLen += footBteLen;
- } else if (footBcopyLen > 0) {
- rv = bte_copy(footBteSource,
- ia64_tpa((unsigned long)bteBlock),
- footBteLen, mode, NULL);
- if (rv != BTE_SUCCESS) {
- kfree(bteBlock_unaligned);
- return rv;
- }
-
- memcpy(__va(footBcopyDest),
- (char *)bteBlock, footBcopyLen);
- }
- } else {
- footBcopyLen = 0;
- footBteLen = 0;
- }
-
- if (len > (headBcopyLen + footBcopyLen)) {
- /* now transfer the middle. */
- rv = bte_copy((src + headBcopyLen),
- (dest +
- headBcopyLen),
- (len - headBcopyLen -
- footBcopyLen), mode, NULL);
- if (rv != BTE_SUCCESS) {
- kfree(bteBlock_unaligned);
- return rv;
- }
-
- }
- } else {
-
- /*
- * The transfer is not symmetric, we will
- * allocate a buffer large enough for all the
- * data, bte_copy into that buffer and then
- * bcopy to the destination.
- */
-
- headBcopySrcOffset = src & L1_CACHE_MASK;
- headBcopyDest = dest;
- headBcopyLen = len;
-
- headBteSource = src - headBcopySrcOffset;
- /* Add the leading and trailing bytes from source */
- headBteLen = L1_CACHE_ALIGN(len + headBcopySrcOffset);
- }
-
- if (headBcopyLen > 0) {
- rv = bte_copy(headBteSource,
- ia64_tpa((unsigned long)bteBlock), headBteLen,
- mode, NULL);
- if (rv != BTE_SUCCESS) {
- kfree(bteBlock_unaligned);
- return rv;
- }
-
- memcpy(__va(headBcopyDest), ((char *)bteBlock +
- headBcopySrcOffset), headBcopyLen);
- }
- kfree(bteBlock_unaligned);
- return BTE_SUCCESS;
-}
-
-EXPORT_SYMBOL(bte_unaligned_copy);
-
-/************************************************************************
- * Block Transfer Engine initialization functions.
- *
- ***********************************************************************/
-static void bte_recovery_timeout(struct timer_list *t)
-{
- struct nodepda_s *nodepda = from_timer(nodepda, t, bte_recovery_timer);
-
- bte_error_handler(nodepda);
-}
-
-/*
- * bte_init_node(nodepda, cnode)
- *
- * Initialize the nodepda structure with BTE base addresses and
- * spinlocks.
- */
-void bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
-{
- int i;
-
- /*
- * Indicate that all the block transfer engines on this node
- * are available.
- */
-
- /*
- * Allocate one bte_recover_t structure per node. It holds
- * the recovery lock for node. All the bte interface structures
- * will point at this one bte_recover structure to get the lock.
- */
- spin_lock_init(&mynodepda->bte_recovery_lock);
- timer_setup(&mynodepda->bte_recovery_timer, bte_recovery_timeout, 0);
-
- for (i = 0; i < BTES_PER_NODE; i++) {
- u64 *base_addr;
-
- /* Which link status register should we use? */
- base_addr = (u64 *)
- REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), BTE_BASE_ADDR(i));
- mynodepda->bte_if[i].bte_base_addr = base_addr;
- mynodepda->bte_if[i].bte_source_addr = BTE_SOURCE_ADDR(base_addr);
- mynodepda->bte_if[i].bte_destination_addr = BTE_DEST_ADDR(base_addr);
- mynodepda->bte_if[i].bte_control_addr = BTE_CTRL_ADDR(base_addr);
- mynodepda->bte_if[i].bte_notify_addr = BTE_NOTIF_ADDR(base_addr);
-
- /*
- * Initialize the notification and spinlock
- * so the first transfer can occur.
- */
- mynodepda->bte_if[i].most_rcnt_na =
- &(mynodepda->bte_if[i].notify);
- mynodepda->bte_if[i].notify = BTE_WORD_AVAILABLE;
- spin_lock_init(&mynodepda->bte_if[i].spinlock);
-
- mynodepda->bte_if[i].bte_cnode = cnode;
- mynodepda->bte_if[i].bte_error_count = 0;
- mynodepda->bte_if[i].bte_num = i;
- mynodepda->bte_if[i].cleanup_active = 0;
- mynodepda->bte_if[i].bh_error = 0;
- }
-
-}
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c
deleted file mode 100644
index d92786c09b34..000000000000
--- a/arch/ia64/sn/kernel/bte_error.c
+++ /dev/null
@@ -1,255 +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-2007 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <asm/sn/sn_sal.h>
-#include "ioerror.h"
-#include <asm/sn/addrs.h>
-#include <asm/sn/shubio.h>
-#include <asm/sn/geo.h>
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-#include <asm/sn/bte.h>
-#include <asm/param.h>
-
-/*
- * Bte error handling is done in two parts. The first captures
- * any crb related errors. Since there can be multiple crbs per
- * interface and multiple interfaces active, we need to wait until
- * all active crbs are completed. This is the first job of the
- * second part error handler. When all bte related CRBs are cleanly
- * completed, it resets the interfaces and gets them ready for new
- * transfers to be queued.
- */
-
-/*
- * Wait until all BTE related CRBs are completed
- * and then reset the interfaces.
- */
-static int shub1_bte_error_handler(struct nodepda_s *err_nodepda)
-{
- struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
- nasid_t nasid;
- int i;
- int valid_crbs;
- ii_imem_u_t imem; /* II IMEM Register */
- ii_icrb0_d_u_t icrbd; /* II CRB Register D */
- ii_ibcr_u_t ibcr;
- ii_icmr_u_t icmr;
- ii_ieclr_u_t ieclr;
-
- BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
- smp_processor_id()));
-
- if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
- (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
- BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
- smp_processor_id()));
- return 1;
- }
-
- /* Determine information about our hub */
- nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
-
- /*
- * A BTE transfer can use multiple CRBs. We need to make sure
- * that all the BTE CRBs are complete (or timed out) before
- * attempting to clean up the error. Resetting the BTE while
- * there are still BTE CRBs active will hang the BTE.
- * We should look at all the CRBs to see if they are allocated
- * to the BTE and see if they are still active. When none
- * are active, we can continue with the cleanup.
- *
- * We also want to make sure that the local NI port is up.
- * When a router resets the NI port can go down, while it
- * goes through the LLP handshake, but then comes back up.
- */
- icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
- if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
- /*
- * There are errors which still need to be cleaned up by
- * hubiio_crb_error_handler
- */
- mod_timer(recovery_timer, jiffies + (HZ * 5));
- BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
- smp_processor_id()));
- return 1;
- }
- if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
-
- valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
-
- for (i = 0; i < IIO_NUM_CRBS; i++) {
- if (!((1 << i) & valid_crbs)) {
- /* This crb was not marked as valid, ignore */
- continue;
- }
- icrbd.ii_icrb0_d_regval =
- REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
- if (icrbd.d_bteop) {
- mod_timer(recovery_timer, jiffies + (HZ * 5));
- BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
- err_nodepda, smp_processor_id(),
- i));
- return 1;
- }
- }
- }
-
- BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id()));
- /* Re-enable both bte interfaces */
- imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
- imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
- REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
-
- /* Clear BTE0/1 error bits */
- ieclr.ii_ieclr_regval = 0;
- if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
- ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
- if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
- ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
- REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
-
- /* Reinitialize both BTE state machines. */
- ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
- ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
- REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
-
- del_timer(recovery_timer);
- return 0;
-}
-
-/*
- * Wait until all BTE related CRBs are completed
- * and then reset the interfaces.
- */
-static int shub2_bte_error_handler(struct nodepda_s *err_nodepda)
-{
- struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
- struct bteinfo_s *bte;
- nasid_t nasid;
- u64 status;
- int i;
-
- nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
-
- /*
- * Verify that all the BTEs are complete
- */
- for (i = 0; i < BTES_PER_NODE; i++) {
- bte = &err_nodepda->bte_if[i];
- status = BTE_LNSTAT_LOAD(bte);
- if (status & IBLS_ERROR) {
- bte->bh_error = BTE_SHUB2_ERROR(status);
- continue;
- }
- if (!(status & IBLS_BUSY))
- continue;
- mod_timer(recovery_timer, jiffies + (HZ * 5));
- BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
- smp_processor_id()));
- return 1;
- }
- if (ia64_sn_bte_recovery(nasid))
- panic("bte_error_handler(): Fatal BTE Error");
-
- del_timer(recovery_timer);
- return 0;
-}
-
-/*
- * Wait until all BTE related CRBs are completed
- * and then reset the interfaces.
- */
-void bte_error_handler(struct nodepda_s *err_nodepda)
-{
- spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
- int i;
- unsigned long irq_flags;
- volatile u64 *notify;
- bte_result_t bh_error;
-
- BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
- smp_processor_id()));
-
- spin_lock_irqsave(recovery_lock, irq_flags);
-
- /*
- * Lock all interfaces on this node to prevent new transfers
- * from being queued.
- */
- for (i = 0; i < BTES_PER_NODE; i++) {
- if (err_nodepda->bte_if[i].cleanup_active) {
- continue;
- }
- spin_lock(&err_nodepda->bte_if[i].spinlock);
- BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
- smp_processor_id(), i));
- err_nodepda->bte_if[i].cleanup_active = 1;
- }
-
- if (is_shub1()) {
- if (shub1_bte_error_handler(err_nodepda)) {
- spin_unlock_irqrestore(recovery_lock, irq_flags);
- return;
- }
- } else {
- if (shub2_bte_error_handler(err_nodepda)) {
- spin_unlock_irqrestore(recovery_lock, irq_flags);
- return;
- }
- }
-
- for (i = 0; i < BTES_PER_NODE; i++) {
- bh_error = err_nodepda->bte_if[i].bh_error;
- if (bh_error != BTE_SUCCESS) {
- /* There is an error which needs to be notified */
- notify = err_nodepda->bte_if[i].most_rcnt_na;
- BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
- err_nodepda->bte_if[i].bte_cnode,
- err_nodepda->bte_if[i].bte_num,
- IBLS_ERROR | (u64) bh_error));
- *notify = IBLS_ERROR | bh_error;
- err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
- }
-
- err_nodepda->bte_if[i].cleanup_active = 0;
- BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
- smp_processor_id(), i));
- spin_unlock(&err_nodepda->bte_if[i].spinlock);
- }
-
- spin_unlock_irqrestore(recovery_lock, irq_flags);
-}
-
-/*
- * First part error handler. This is called whenever any error CRB interrupt
- * is generated by the II.
- */
-void
-bte_crb_error_handler(cnodeid_t cnode, int btenum,
- int crbnum, ioerror_t * ioe, int bteop)
-{
- struct bteinfo_s *bte;
-
-
- bte = &(NODEPDA(cnode)->bte_if[btenum]);
-
- /*
- * The caller has already figured out the error type, we save that
- * in the bte handle structure for the thread exercising the
- * interface to consume.
- */
- bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
- bte->bte_error_count++;
-
- BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
- bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
- bte_error_handler(NODEPDA(cnode));
-}
-
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
deleted file mode 100644
index 97fa56dddf50..000000000000
--- a/arch/ia64/sn/kernel/huberror.c
+++ /dev/null
@@ -1,220 +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,2002-2007 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/delay.h>
-#include <asm/sn/sn_sal.h>
-#include "ioerror.h"
-#include <asm/sn/addrs.h>
-#include <asm/sn/shubio.h>
-#include <asm/sn/geo.h>
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-#include <asm/sn/bte.h>
-
-void hubiio_crb_error_handler(struct hubdev_info *hubdev_info);
-extern void bte_crb_error_handler(cnodeid_t, int, int, ioerror_t *,
- int);
-static irqreturn_t hub_eint_handler(int irq, void *arg)
-{
- struct hubdev_info *hubdev_info;
- struct ia64_sal_retval ret_stuff;
- nasid_t nasid;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
- hubdev_info = (struct hubdev_info *)arg;
- nasid = hubdev_info->hdi_nasid;
-
- if (is_shub1()) {
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
- (u64) nasid, 0, 0, 0, 0, 0, 0);
-
- if ((int)ret_stuff.v0)
- panic("%s: Fatal %s Error", __func__,
- ((nasid & 1) ? "TIO" : "HUBII"));
-
- if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
- (void)hubiio_crb_error_handler(hubdev_info);
- } else
- if (nasid & 1) { /* TIO errors */
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
- (u64) nasid, 0, 0, 0, 0, 0, 0);
-
- if ((int)ret_stuff.v0)
- panic("%s: Fatal TIO Error", __func__);
- } else
- bte_error_handler(NODEPDA(nasid_to_cnodeid(nasid)));
-
- return IRQ_HANDLED;
-}
-
-/*
- * Free the hub CRB "crbnum" which encountered an error.
- * Assumption is, error handling was successfully done,
- * and we now want to return the CRB back to Hub for normal usage.
- *
- * In order to free the CRB, all that's needed is to de-allocate it
- *
- * Assumption:
- * No other processor is mucking around with the hub control register.
- * So, upper layer has to single thread this.
- */
-void hubiio_crb_free(struct hubdev_info *hubdev_info, int crbnum)
-{
- ii_icrb0_b_u_t icrbb;
-
- /*
- * The hardware does NOT clear the mark bit, so it must get cleared
- * here to be sure the error is not processed twice.
- */
- icrbb.ii_icrb0_b_regval = REMOTE_HUB_L(hubdev_info->hdi_nasid,
- IIO_ICRB_B(crbnum));
- icrbb.b_mark = 0;
- REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICRB_B(crbnum),
- icrbb.ii_icrb0_b_regval);
- /*
- * Deallocate the register wait till hub indicates it's done.
- */
- REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum));
- while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND)
- cpu_relax();
-
-}
-
-/*
- * hubiio_crb_error_handler
- *
- * This routine gets invoked when a hub gets an error
- * interrupt. So, the routine is running in interrupt context
- * at error interrupt level.
- * Action:
- * It's responsible for identifying ALL the CRBs that are marked
- * with error, and process them.
- *
- * If you find the CRB that's marked with error, map this to the
- * reason it caused error, and invoke appropriate error handler.
- *
- * XXX Be aware of the information in the context register.
- *
- * NOTE:
- * Use REMOTE_HUB_* macro instead of LOCAL_HUB_* so that the interrupt
- * handler can be run on any node. (not necessarily the node
- * corresponding to the hub that encountered error).
- */
-
-void hubiio_crb_error_handler(struct hubdev_info *hubdev_info)
-{
- nasid_t nasid;
- ii_icrb0_a_u_t icrba; /* II CRB Register A */
- ii_icrb0_b_u_t icrbb; /* II CRB Register B */
- ii_icrb0_c_u_t icrbc; /* II CRB Register C */
- ii_icrb0_d_u_t icrbd; /* II CRB Register D */
- ii_icrb0_e_u_t icrbe; /* II CRB Register D */
- int i;
- int num_errors = 0; /* Num of errors handled */
- ioerror_t ioerror;
-
- nasid = hubdev_info->hdi_nasid;
-
- /*
- * XXX - Add locking for any recovery actions
- */
- /*
- * Scan through all CRBs in the Hub, and handle the errors
- * in any of the CRBs marked.
- */
- for (i = 0; i < IIO_NUM_CRBS; i++) {
- /* Check this crb entry to see if it is in error. */
- icrbb.ii_icrb0_b_regval = REMOTE_HUB_L(nasid, IIO_ICRB_B(i));
-
- if (icrbb.b_mark == 0) {
- continue;
- }
-
- icrba.ii_icrb0_a_regval = REMOTE_HUB_L(nasid, IIO_ICRB_A(i));
-
- IOERROR_INIT(&ioerror);
-
- /* read other CRB error registers. */
- icrbc.ii_icrb0_c_regval = REMOTE_HUB_L(nasid, IIO_ICRB_C(i));
- icrbd.ii_icrb0_d_regval = REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
- icrbe.ii_icrb0_e_regval = REMOTE_HUB_L(nasid, IIO_ICRB_E(i));
-
- IOERROR_SETVALUE(&ioerror, errortype, icrbb.b_ecode);
-
- /* Check if this error is due to BTE operation,
- * and handle it separately.
- */
- if (icrbd.d_bteop ||
- ((icrbb.b_initiator == IIO_ICRB_INIT_BTE0 ||
- icrbb.b_initiator == IIO_ICRB_INIT_BTE1) &&
- (icrbb.b_imsgtype == IIO_ICRB_IMSGT_BTE ||
- icrbb.b_imsgtype == IIO_ICRB_IMSGT_SN1NET))) {
-
- int bte_num;
-
- if (icrbd.d_bteop)
- bte_num = icrbc.c_btenum;
- else /* b_initiator bit 2 gives BTE number */
- bte_num = (icrbb.b_initiator & 0x4) >> 2;
-
- hubiio_crb_free(hubdev_info, i);
-
- bte_crb_error_handler(nasid_to_cnodeid(nasid), bte_num,
- i, &ioerror, icrbd.d_bteop);
- num_errors++;
- continue;
- }
- }
-}
-
-/*
- * Function : hub_error_init
- * Purpose : initialize the error handling requirements for a given hub.
- * Parameters : cnode, the compact nodeid.
- * Assumptions : Called only once per hub, either by a local cpu. Or by a
- * remote cpu, when this hub is headless.(cpuless)
- * Returns : None
- */
-void hub_error_init(struct hubdev_info *hubdev_info)
-{
-
- if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
- "SN_hub_error", hubdev_info)) {
- printk(KERN_ERR "hub_error_init: Failed to request_irq for 0x%p\n",
- hubdev_info);
- return;
- }
- irq_set_handler(SGI_II_ERROR, handle_level_irq);
- sn_set_err_irq_affinity(SGI_II_ERROR);
-}
-
-
-/*
- * Function : ice_error_init
- * Purpose : initialize the error handling requirements for a given tio.
- * Parameters : cnode, the compact nodeid.
- * Assumptions : Called only once per tio.
- * Returns : None
- */
-void ice_error_init(struct hubdev_info *hubdev_info)
-{
-
- if (request_irq
- (SGI_TIO_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_TIO_error",
- (void *)hubdev_info)) {
- printk("ice_error_init: request_irq() error hubdev_info 0x%p\n",
- hubdev_info);
- return;
- }
- irq_set_handler(SGI_TIO_ERROR, handle_level_irq);
- sn_set_err_irq_affinity(SGI_TIO_ERROR);
-}
-
diff --git a/arch/ia64/sn/kernel/idle.c b/arch/ia64/sn/kernel/idle.c
deleted file mode 100644
index 49d178f022b5..000000000000
--- a/arch/ia64/sn/kernel/idle.c
+++ /dev/null
@@ -1,30 +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) 2001-2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <asm/sn/leds.h>
-
-void snidle(int state)
-{
- if (state) {
- if (pda->idle_flag == 0) {
- /*
- * Turn the activity LED off.
- */
- set_led_bits(0, LED_CPU_ACTIVITY);
- }
-
- pda->idle_flag = 1;
- } else {
- /*
- * Turn the activity LED on.
- */
- set_led_bits(LED_CPU_ACTIVITY, LED_CPU_ACTIVITY);
-
- pda->idle_flag = 0;
- }
-}
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
deleted file mode 100644
index c31fe637b0b4..000000000000
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ /dev/null
@@ -1,513 +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) 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <asm/sn/types.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/sn_sal.h>
-#include "xtalk/hubdev.h"
-#include <linux/acpi.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-
-
-/*
- * The code in this file will only be executed when running with
- * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
- */
-
-
-/*
- * This value must match the UUID the PROM uses
- * (io/acpi/defblk.c) when building a vendor descriptor.
- */
-struct acpi_vendor_uuid sn_uuid = {
- .subtype = 0,
- .data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
- 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
-};
-
-struct sn_pcidev_match {
- u8 bus;
- unsigned int devfn;
- acpi_handle handle;
-};
-
-/*
- * Perform the early IO init in PROM.
- */
-static long
-sal_ioif_init(u64 *result)
-{
- struct ia64_sal_retval isrv = {0,0,0,0};
-
- SAL_CALL_NOLOCK(isrv,
- SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
- *result = isrv.v0;
- return isrv.status;
-}
-
-/*
- * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
- * for all SGIHUB and SGITIO acpi devices defined in the
- * DSDT. It obtains the hubdev_info pointer from the
- * ACPI vendor resource, which the PROM setup, and sets up the
- * hubdev_info in the pda.
- */
-
-static acpi_status __init
-sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
-{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- u64 addr;
- struct hubdev_info *hubdev;
- struct hubdev_info *hubdev_ptr;
- int i;
- u64 nasid;
- struct acpi_resource *resource;
- acpi_status status;
- struct acpi_resource_vendor_typed *vendor;
- extern void sn_common_hubdev_init(struct hubdev_info *);
-
- status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
- &sn_uuid, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
- "(0x%x) failed for: %s\n", status,
- (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return AE_OK; /* Continue walking namespace */
- }
-
- resource = buffer.pointer;
- vendor = &resource->data.vendor_typed;
- if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
- sizeof(struct hubdev_info *)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "sn_acpi_hubdev_init: Invalid vendor data length: "
- "%d for: %s\n",
- vendor->byte_length, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- goto exit;
- }
-
- memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
- hubdev_ptr = __va((struct hubdev_info *) addr);
-
- nasid = hubdev_ptr->hdi_nasid;
- i = nasid_to_cnodeid(nasid);
- hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
- *hubdev = *hubdev_ptr;
- sn_common_hubdev_init(hubdev);
-
-exit:
- kfree(buffer.pointer);
- return AE_OK; /* Continue walking namespace */
-}
-
-/*
- * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
- * the ACPI Vendor resource for this bus.
- */
-static struct pcibus_bussoft *
-sn_get_bussoft_ptr(struct pci_bus *bus)
-{
- u64 addr;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_handle handle;
- struct pcibus_bussoft *prom_bussoft_ptr;
- struct acpi_resource *resource;
- acpi_status status;
- struct acpi_resource_vendor_typed *vendor;
-
-
- handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
- status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
- &sn_uuid, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR "%s: "
- "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
- __func__, status, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return NULL;
- }
- resource = buffer.pointer;
- vendor = &resource->data.vendor_typed;
-
- if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
- sizeof(struct pcibus_bussoft *)) {
- printk(KERN_ERR
- "%s: Invalid vendor data length %d\n",
- __func__, vendor->byte_length);
- kfree(buffer.pointer);
- return NULL;
- }
- memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
- prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
- kfree(buffer.pointer);
-
- return prom_bussoft_ptr;
-}
-
-/*
- * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
- * pointers from the vendor resource using the
- * provided acpi handle, and copy the structures
- * into the argument buffers.
- */
-static int
-sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
- struct sn_irq_info **sn_irq_info)
-{
- u64 addr;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct sn_irq_info *irq_info, *irq_info_prom;
- struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
- struct acpi_resource *resource;
- int ret = 0;
- acpi_status status;
- struct acpi_resource_vendor_typed *vendor;
-
- /*
- * The pointer to this device's pcidev_info structure in
- * the PROM, is in the vendor resource.
- */
- status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
- &sn_uuid, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
- __func__, status, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return 1;
- }
-
- resource = buffer.pointer;
- vendor = &resource->data.vendor_typed;
- if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
- sizeof(struct pci_devdev_info *)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "%s: Invalid vendor data length: %d for: %s\n",
- __func__, vendor->byte_length,
- (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- ret = 1;
- goto exit;
- }
-
- pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
- if (!pcidev_ptr)
- panic("%s: Unable to alloc memory for pcidev_info", __func__);
-
- memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
- pcidev_prom_ptr = __va(addr);
- memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
-
- /* Get the IRQ info */
- irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
- if (!irq_info)
- panic("%s: Unable to alloc memory for sn_irq_info", __func__);
-
- if (pcidev_ptr->pdi_sn_irq_info) {
- irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
- memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
- }
-
- *pcidev_info = pcidev_ptr;
- *sn_irq_info = irq_info;
-
-exit:
- kfree(buffer.pointer);
- return ret;
-}
-
-static unsigned int
-get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
-{
- unsigned long long adr;
- acpi_handle child;
- unsigned int devfn;
- int function;
- acpi_handle parent;
- int slot;
- acpi_status status;
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
- acpi_get_name(device_handle, ACPI_FULL_PATHNAME, &name_buffer);
-
- /*
- * Do an upward search to find the root bus device, and
- * obtain the host devfn from the previous child device.
- */
- child = device_handle;
- while (child) {
- status = acpi_get_parent(child, &parent);
- if (ACPI_FAILURE(status)) {
- printk(KERN_ERR "%s: acpi_get_parent() failed "
- "(0x%x) for: %s\n", __func__, status,
- (char *)name_buffer.pointer);
- panic("%s: Unable to find host devfn\n", __func__);
- }
- if (parent == rootbus_handle)
- break;
- child = parent;
- }
- if (!child) {
- printk(KERN_ERR "%s: Unable to find root bus for: %s\n",
- __func__, (char *)name_buffer.pointer);
- BUG();
- }
-
- status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: %s\n",
- __func__, status, (char *)name_buffer.pointer);
- panic("%s: Unable to find host devfn\n", __func__);
- }
-
- kfree(name_buffer.pointer);
-
- slot = (adr >> 16) & 0xffff;
- function = adr & 0xffff;
- devfn = PCI_DEVFN(slot, function);
- return devfn;
-}
-
-/*
- * find_matching_device - Callback routine to find the ACPI device
- * that matches up with our pci_dev device.
- * Matching is done on bus number and devfn.
- * To find the bus number for a particular
- * ACPI device, we must look at the _BBN method
- * of its parent.
- */
-static acpi_status
-find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- unsigned long long bbn = -1;
- unsigned long long adr;
- acpi_handle parent = NULL;
- acpi_status status;
- unsigned int devfn;
- int function;
- int slot;
- struct sn_pcidev_match *info = context;
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
- &adr);
- if (ACPI_SUCCESS(status)) {
- status = acpi_get_parent(handle, &parent);
- if (ACPI_FAILURE(status)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "%s: acpi_get_parent() failed (0x%x) for: %s\n",
- __func__, status, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return AE_OK;
- }
- status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
- NULL, &bbn);
- if (ACPI_FAILURE(status)) {
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR
- "%s: Failed to find _BBN in parent of: %s\n",
- __func__, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return AE_OK;
- }
-
- slot = (adr >> 16) & 0xffff;
- function = adr & 0xffff;
- devfn = PCI_DEVFN(slot, function);
- if ((info->devfn == devfn) && (info->bus == bbn)) {
- /* We have a match! */
- info->handle = handle;
- return 1;
- }
- }
- return AE_OK;
-}
-
-/*
- * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
- * device matching the specified pci_dev,
- * and return the pcidev info and irq info.
- */
-int
-sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
- struct sn_irq_info **sn_irq_info)
-{
- unsigned int host_devfn;
- struct sn_pcidev_match pcidev_match;
- acpi_handle rootbus_handle;
- unsigned long long segment;
- acpi_status status;
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
- rootbus_handle = acpi_device_handle(PCI_CONTROLLER(dev)->companion);
- status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
- &segment);
- if (ACPI_SUCCESS(status)) {
- if (segment != pci_domain_nr(dev)) {
- acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME,
- &name_buffer);
- printk(KERN_ERR
- "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
- __func__, segment, pci_domain_nr(dev),
- (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return 1;
- }
- } else {
- acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME, &name_buffer);
- printk(KERN_ERR "%s: Unable to get __SEG from: %s\n",
- __func__, (char *)name_buffer.pointer);
- kfree(name_buffer.pointer);
- return 1;
- }
-
- /*
- * We want to search all devices in this segment/domain
- * of the ACPI namespace for the matching ACPI device,
- * which holds the pcidev_info pointer in its vendor resource.
- */
- pcidev_match.bus = dev->bus->number;
- pcidev_match.devfn = dev->devfn;
- pcidev_match.handle = NULL;
-
- acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
- find_matching_device, NULL, &pcidev_match, NULL);
-
- if (!pcidev_match.handle) {
- printk(KERN_ERR
- "%s: Could not find matching ACPI device for %s.\n",
- __func__, pci_name(dev));
- return 1;
- }
-
- if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
- return 1;
-
- /* Build up the pcidev_info.pdi_slot_host_handle */
- host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
- (*pcidev_info)->pdi_slot_host_handle =
- ((unsigned long) pci_domain_nr(dev) << 40) |
- /* bus == 0 */
- host_devfn;
- return 0;
-}
-
-/*
- * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
- * Perform any SN specific slot fixup.
- * At present there does not appear to be
- * any generic way to handle a ROM image
- * that has been shadowed by the PROM, so
- * we pass a pointer to it within the
- * pcidev_info structure.
- */
-
-void
-sn_acpi_slot_fixup(struct pci_dev *dev)
-{
- struct pcidev_info *pcidev_info = NULL;
- struct sn_irq_info *sn_irq_info = NULL;
- struct resource *res;
- size_t size;
-
- if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
- panic("%s: Failure obtaining pcidev_info for %s\n",
- __func__, pci_name(dev));
- }
-
- if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
- /*
- * A valid ROM image exists and has been shadowed by the
- * PROM. Setup the pci_dev ROM resource with the address
- * of the shadowed copy, and the actual length of the ROM image.
- */
- size = pci_resource_len(dev, PCI_ROM_RESOURCE);
-
- res = &dev->resource[PCI_ROM_RESOURCE];
-
- pci_disable_rom(dev);
- if (res->parent)
- release_resource(res);
-
- res->start = pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE];
- res->end = res->start + size - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
- IORESOURCE_PCI_FIXED;
- }
- sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
-}
-EXPORT_SYMBOL(sn_acpi_slot_fixup);
-
-
-/*
- * sn_acpi_bus_fixup - Perform SN specific setup of software structs
- * (pcibus_bussoft, pcidev_info) and hardware
- * registers, for the specified bus and devices under it.
- */
-void
-sn_acpi_bus_fixup(struct pci_bus *bus)
-{
- struct pci_dev *pci_dev = NULL;
- struct pcibus_bussoft *prom_bussoft_ptr;
-
- if (!bus->parent) { /* If root bus */
- prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
- if (prom_bussoft_ptr == NULL) {
- printk(KERN_ERR
- "%s: 0x%04x:0x%02x Unable to "
- "obtain prom_bussoft_ptr\n",
- __func__, pci_domain_nr(bus), bus->number);
- return;
- }
- sn_common_bus_fixup(bus, prom_bussoft_ptr);
- }
- list_for_each_entry(pci_dev, &bus->devices, bus_list) {
- sn_acpi_slot_fixup(pci_dev);
- }
-}
-
-/*
- * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
- * nodes and root buses in the DSDT. As a result, bus scanning
- * will be initiated by the Linux ACPI code.
- */
-
-void __init
-sn_io_acpi_init(void)
-{
- u64 result;
- long status;
-
- /* SN Altix does not follow the IOSAPIC IRQ routing model */
- acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
-
- /* Setup hubdev_info for all SGIHUB/SGITIO devices */
- acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL);
- acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL);
-
- status = sal_ioif_init(&result);
- if (status || result)
- panic("sal_ioif_init failed: [%lx] %s\n",
- status, ia64_sal_strerror(status));
-}
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
deleted file mode 100644
index d46847323ef6..000000000000
--- a/arch/ia64/sn/kernel/io_common.c
+++ /dev/null
@@ -1,561 +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) 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/memblock.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <asm/sn/types.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/sn_feature_sets.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/io.h>
-#include <asm/sn/l1.h>
-#include <asm/sn/module.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/tioca_provider.h>
-#include <asm/sn/tioce_provider.h>
-#include "xtalk/hubdev.h"
-#include "xtalk/xwidgetdev.h"
-#include <linux/acpi.h>
-#include <asm/sn/sn2/sn_hwperf.h>
-#include <asm/sn/acpi.h>
-
-extern void sn_init_cpei_timer(void);
-extern void register_sn_procfs(void);
-extern void sn_io_acpi_init(void);
-extern void sn_io_init(void);
-
-
-static struct list_head sn_sysdata_list;
-
-/* sysdata list struct */
-struct sysdata_el {
- struct list_head entry;
- void *sysdata;
-};
-
-int sn_ioif_inited; /* SN I/O infrastructure initialized? */
-
-int sn_acpi_rev; /* SN ACPI revision */
-EXPORT_SYMBOL_GPL(sn_acpi_rev);
-
-struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
-
-/*
- * Hooks and struct for unsupported pci providers
- */
-
-static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
-{
- return 0;
-}
-
-static void
-sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
-{
- return;
-}
-
-static void *
-sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
-{
- return NULL;
-}
-
-static struct sn_pcibus_provider sn_pci_default_provider = {
- .dma_map = sn_default_pci_map,
- .dma_map_consistent = sn_default_pci_map,
- .dma_unmap = sn_default_pci_unmap,
- .bus_fixup = sn_default_pci_bus_fixup,
-};
-
-/*
- * Retrieve the DMA Flush List given nasid, widget, and device.
- * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
- */
-static inline u64
-sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
- u64 address)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
- (u64) nasid, (u64) widget_num,
- (u64) device_num, (u64) address, 0, 0, 0);
- return ret_stuff.status;
-}
-
-/*
- * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
- * device.
- */
-inline struct pcidev_info *
-sn_pcidev_info_get(struct pci_dev *dev)
-{
- struct pcidev_info *pcidev;
-
- list_for_each_entry(pcidev,
- &(SN_PLATFORM_DATA(dev)->pcidev_info), pdi_list) {
- if (pcidev->pdi_linux_pcidev == dev)
- return pcidev;
- }
- return NULL;
-}
-
-/* Older PROM flush WAR
- *
- * 01/16/06 -- This war will be in place until a new official PROM is released.
- * Additionally note that the struct sn_flush_device_war also has to be
- * removed from arch/ia64/sn/include/xtalk/hubdev.h
- */
-
-static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
- struct sn_flush_device_common *common)
-{
- struct sn_flush_device_war *war_list;
- struct sn_flush_device_war *dev_entry;
- struct ia64_sal_retval isrv = {0,0,0,0};
-
- printk_once(KERN_WARNING
- "PROM version < 4.50 -- implementing old PROM flush WAR\n");
-
- war_list = kcalloc(DEV_PER_WIDGET, sizeof(*war_list), GFP_KERNEL);
- BUG_ON(!war_list);
-
- SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
- nasid, widget, __pa(war_list), 0, 0, 0 ,0);
- if (isrv.status)
- panic("sn_device_fixup_war failed: %s\n",
- ia64_sal_strerror(isrv.status));
-
- dev_entry = war_list + device;
- memcpy(common,dev_entry, sizeof(*common));
- kfree(war_list);
-
- return isrv.status;
-}
-
-/*
- * sn_common_hubdev_init() - This routine is called to initialize the HUB data
- * structure for each node in the system.
- */
-void __init
-sn_common_hubdev_init(struct hubdev_info *hubdev)
-{
-
- struct sn_flush_device_kernel *sn_flush_device_kernel;
- struct sn_flush_device_kernel *dev_entry;
- s64 status;
- int widget, device, size;
-
- /* Attach the error interrupt handlers */
- if (hubdev->hdi_nasid & 1) /* If TIO */
- ice_error_init(hubdev);
- else
- hub_error_init(hubdev);
-
- for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
- hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
-
- if (!hubdev->hdi_flush_nasid_list.widget_p)
- return;
-
- size = (HUB_WIDGET_ID_MAX + 1) *
- sizeof(struct sn_flush_device_kernel *);
- hubdev->hdi_flush_nasid_list.widget_p =
- kzalloc(size, GFP_KERNEL);
- BUG_ON(!hubdev->hdi_flush_nasid_list.widget_p);
-
- for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
- size = DEV_PER_WIDGET *
- sizeof(struct sn_flush_device_kernel);
- sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
- BUG_ON(!sn_flush_device_kernel);
-
- dev_entry = sn_flush_device_kernel;
- for (device = 0; device < DEV_PER_WIDGET;
- device++, dev_entry++) {
- size = sizeof(struct sn_flush_device_common);
- dev_entry->common = kzalloc(size, GFP_KERNEL);
- BUG_ON(!dev_entry->common);
- if (sn_prom_feature_available(PRF_DEVICE_FLUSH_LIST))
- status = sal_get_device_dmaflush_list(
- hubdev->hdi_nasid, widget, device,
- (u64)(dev_entry->common));
- else
- status = sn_device_fixup_war(hubdev->hdi_nasid,
- widget, device,
- dev_entry->common);
- if (status != SALRET_OK)
- panic("SAL call failed: %s\n",
- ia64_sal_strerror(status));
-
- spin_lock_init(&dev_entry->sfdl_flush_lock);
- }
-
- if (sn_flush_device_kernel)
- hubdev->hdi_flush_nasid_list.widget_p[widget] =
- sn_flush_device_kernel;
- }
-}
-
-void sn_pci_unfixup_slot(struct pci_dev *dev)
-{
- struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
-
- sn_irq_unfixup(dev);
- pci_dev_put(host_pci_dev);
- pci_dev_put(dev);
-}
-
-/*
- * sn_pci_fixup_slot()
- */
-void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
- struct sn_irq_info *sn_irq_info)
-{
- int segment = pci_domain_nr(dev->bus);
- struct pcibus_bussoft *bs;
- struct pci_dev *host_pci_dev;
- unsigned int bus_no, devfn;
-
- pci_dev_get(dev); /* for the sysdata pointer */
-
- /* Add pcidev_info to list in pci_controller.platform_data */
- list_add_tail(&pcidev_info->pdi_list,
- &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
- /*
- * Using the PROMs values for the PCI host bus, get the Linux
- * PCI host_pci_dev struct and set up host bus linkages
- */
-
- bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
- devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
- host_pci_dev = pci_get_domain_bus_and_slot(segment, bus_no, devfn);
-
- pcidev_info->host_pci_dev = host_pci_dev;
- pcidev_info->pdi_linux_pcidev = dev;
- pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
- bs = SN_PCIBUS_BUSSOFT(dev->bus);
- pcidev_info->pdi_pcibus_info = bs;
-
- if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
- SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
- } else {
- SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
- }
-
- /* Only set up IRQ stuff if this device has a host bus context */
- if (bs && sn_irq_info->irq_irq) {
- pcidev_info->pdi_sn_irq_info = sn_irq_info;
- dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
- sn_irq_fixup(dev, sn_irq_info);
- } else {
- pcidev_info->pdi_sn_irq_info = NULL;
- kfree(sn_irq_info);
- }
-}
-
-/*
- * sn_common_bus_fixup - Perform platform specific bus fixup.
- * Execute the ASIC specific fixup routine
- * for this bus.
- */
-void
-sn_common_bus_fixup(struct pci_bus *bus,
- struct pcibus_bussoft *prom_bussoft_ptr)
-{
- int cnode;
- struct pci_controller *controller;
- struct hubdev_info *hubdev_info;
- int nasid;
- void *provider_soft;
- struct sn_pcibus_provider *provider;
- struct sn_platform_data *sn_platform_data;
-
- controller = PCI_CONTROLLER(bus);
- /*
- * Per-provider fixup. Copies the bus soft structure from prom
- * to local area and links SN_PCIBUS_BUSSOFT().
- */
-
- if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
- printk(KERN_WARNING "sn_common_bus_fixup: Unsupported asic type, %d",
- prom_bussoft_ptr->bs_asic_type);
- return;
- }
-
- if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
- return; /* no further fixup necessary */
-
- provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
- if (provider == NULL)
- panic("sn_common_bus_fixup: No provider registered for this asic type, %d",
- prom_bussoft_ptr->bs_asic_type);
-
- if (provider->bus_fixup)
- provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr,
- controller);
- else
- provider_soft = NULL;
-
- /*
- * Generic bus fixup goes here. Don't reference prom_bussoft_ptr
- * after this point.
- */
- controller->platform_data = kzalloc(sizeof(struct sn_platform_data),
- GFP_KERNEL);
- BUG_ON(controller->platform_data == NULL);
- sn_platform_data =
- (struct sn_platform_data *) controller->platform_data;
- sn_platform_data->provider_soft = provider_soft;
- INIT_LIST_HEAD(&((struct sn_platform_data *)
- controller->platform_data)->pcidev_info);
- nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
- cnode = nasid_to_cnodeid(nasid);
- hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
- SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
- &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
-
- /*
- * If the node information we obtained during the fixup phase is
- * invalid then set controller->node to -1 (undetermined)
- */
- if (controller->node >= num_online_nodes()) {
- struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
-
- printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u "
- "L_IO=%llx L_MEM=%llx BASE=%llx\n",
- b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
- b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
- printk(KERN_WARNING "on node %d but only %d nodes online."
- "Association set to undetermined.\n",
- controller->node, num_online_nodes());
- controller->node = -1;
- }
-}
-
-void sn_bus_store_sysdata(struct pci_dev *dev)
-{
- struct sysdata_el *element;
-
- element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
- if (!element) {
- dev_dbg(&dev->dev, "%s: out of memory!\n", __func__);
- return;
- }
- element->sysdata = SN_PCIDEV_INFO(dev);
- list_add(&element->entry, &sn_sysdata_list);
-}
-
-void sn_bus_free_sysdata(void)
-{
- struct sysdata_el *element;
- struct list_head *list, *safe;
-
- list_for_each_safe(list, safe, &sn_sysdata_list) {
- element = list_entry(list, struct sysdata_el, entry);
- list_del(&element->entry);
- list_del(&(((struct pcidev_info *)
- (element->sysdata))->pdi_list));
- kfree(element->sysdata);
- kfree(element);
- }
- return;
-}
-
-/*
- * hubdev_init_node() - Creates the HUB data structure and link them to it's
- * own NODE specific data area.
- */
-void __init hubdev_init_node(nodepda_t * npda, cnodeid_t node)
-{
- struct hubdev_info *hubdev_info;
- int size;
-
- size = sizeof(struct hubdev_info);
-
- if (node >= num_online_nodes()) /* Headless/memless IO nodes */
- node = 0;
-
- hubdev_info = (struct hubdev_info *)memblock_alloc_node(size,
- SMP_CACHE_BYTES,
- node);
- if (!hubdev_info)
- panic("%s: Failed to allocate %d bytes align=0x%x nid=%d\n",
- __func__, size, SMP_CACHE_BYTES, node);
-
- npda->pdinfo = (void *)hubdev_info;
-}
-
-geoid_t
-cnodeid_get_geoid(cnodeid_t cnode)
-{
- struct hubdev_info *hubdev;
-
- hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
- return hubdev->hdi_geoid;
-}
-
-void sn_generate_path(struct pci_bus *pci_bus, char *address)
-{
- nasid_t nasid;
- cnodeid_t cnode;
- geoid_t geoid;
- moduleid_t moduleid;
- u16 bricktype;
-
- nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
- cnode = nasid_to_cnodeid(nasid);
- geoid = cnodeid_get_geoid(cnode);
- moduleid = geo_module(geoid);
-
- sprintf(address, "module_%c%c%c%c%.2d",
- '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
- '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
- '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
- MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
-
- /* Tollhouse requires slot id to be displayed */
- bricktype = MODULE_GET_BTYPE(moduleid);
- if ((bricktype == L1_BRICKTYPE_191010) ||
- (bricktype == L1_BRICKTYPE_1932))
- sprintf(address + strlen(address), "^%d",
- geo_slot(geoid));
-}
-
-void sn_pci_fixup_bus(struct pci_bus *bus)
-{
-
- if (SN_ACPI_BASE_SUPPORT())
- sn_acpi_bus_fixup(bus);
- else
- sn_bus_fixup(bus);
-}
-
-/*
- * sn_io_early_init - Perform early IO (and some non-IO) initialization.
- * In particular, setup the sn_pci_provider[] array.
- * This needs to be done prior to any bus scanning
- * (acpi_scan_init()) in the ACPI case, as the SN
- * bus fixup code will reference the array.
- */
-static int __init
-sn_io_early_init(void)
-{
- int i;
-
- if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
- return 0;
-
- /* we set the acpi revision to that of the DSDT table OEM rev. */
- {
- struct acpi_table_header *header = NULL;
-
- acpi_get_table(ACPI_SIG_DSDT, 1, &header);
- BUG_ON(header == NULL);
- sn_acpi_rev = header->oem_revision;
- }
-
- /*
- * prime sn_pci_provider[]. Individual provider init routines will
- * override their respective default entries.
- */
-
- for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
- sn_pci_provider[i] = &sn_pci_default_provider;
-
- pcibr_init_provider();
- tioca_init_provider();
- tioce_init_provider();
-
- sn_irq_lh_init();
- INIT_LIST_HEAD(&sn_sysdata_list);
- sn_init_cpei_timer();
-
-#ifdef CONFIG_PROC_FS
- register_sn_procfs();
-#endif
-
- {
- struct acpi_table_header *header;
- (void)acpi_get_table(ACPI_SIG_DSDT, 1, &header);
- printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n",
- header->oem_revision);
- }
- if (SN_ACPI_BASE_SUPPORT())
- sn_io_acpi_init();
- else
- sn_io_init();
- return 0;
-}
-
-arch_initcall(sn_io_early_init);
-
-/*
- * sn_io_late_init() - Perform any final platform specific IO initialization.
- */
-
-int __init
-sn_io_late_init(void)
-{
- struct pci_bus *bus;
- struct pcibus_bussoft *bussoft;
- cnodeid_t cnode;
- nasid_t nasid;
- cnodeid_t near_cnode;
-
- if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
- return 0;
-
- /*
- * Setup closest node in pci_controller->node for
- * PIC, TIOCP, TIOCE (TIOCA does it during bus fixup using
- * info from the PROM).
- */
- bus = NULL;
- while ((bus = pci_find_next_bus(bus)) != NULL) {
- bussoft = SN_PCIBUS_BUSSOFT(bus);
- nasid = NASID_GET(bussoft->bs_base);
- cnode = nasid_to_cnodeid(nasid);
- if ((bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) ||
- (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE) ||
- (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC)) {
- /* PCI Bridge: find nearest node with CPUs */
- int e = sn_hwperf_get_nearest_node(cnode, NULL,
- &near_cnode);
- if (e < 0) {
- near_cnode = (cnodeid_t)-1; /* use any node */
- printk(KERN_WARNING "sn_io_late_init: failed "
- "to find near node with CPUs for "
- "node %d, err=%d\n", cnode, e);
- }
- PCI_CONTROLLER(bus)->node = near_cnode;
- }
- }
-
- sn_ioif_inited = 1; /* SN I/O infrastructure now initialized */
-
- return 0;
-}
-
-fs_initcall(sn_io_late_init);
-
-EXPORT_SYMBOL(sn_pci_unfixup_slot);
-EXPORT_SYMBOL(sn_bus_store_sysdata);
-EXPORT_SYMBOL(sn_bus_free_sysdata);
-EXPORT_SYMBOL(sn_generate_path);
-
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
deleted file mode 100644
index d63809a6adfa..000000000000
--- a/arch/ia64/sn/kernel/io_init.c
+++ /dev/null
@@ -1,308 +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.
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <asm/sn/types.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/io.h>
-#include <asm/sn/module.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/sn_sal.h>
-#include "xtalk/hubdev.h"
-
-/*
- * The code in this file will only be executed when running with
- * a PROM that does _not_ have base ACPI IO support.
- * (i.e., SN_ACPI_BASE_SUPPORT() == 0)
- */
-
-static int max_segment_number; /* Default highest segment number */
-static int max_pcibus_number = 255; /* Default highest pci bus number */
-
-
-/*
- * Retrieve the hub device info structure for the given nasid.
- */
-static inline u64 sal_get_hubdev_info(u64 handle, u64 address)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_HUBDEV_INFO,
- (u64) handle, (u64) address, 0, 0, 0, 0, 0);
- return ret_stuff.v0;
-}
-
-/*
- * Retrieve the pci bus information given the bus number.
- */
-static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_PCIBUS_INFO,
- (u64) segment, (u64) busnum, (u64) address, 0, 0, 0, 0);
- return ret_stuff.v0;
-}
-
-/*
- * Retrieve the pci device information given the bus and device|function number.
- */
-static inline u64
-sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
- u64 sn_irq_info)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
- (u64) segment, (u64) bus_number, (u64) devfn,
- (u64) pci_dev,
- sn_irq_info, 0, 0);
- return ret_stuff.v0;
-}
-
-
-/*
- * sn_fixup_ionodes() - This routine initializes the HUB data structure for
- * each node in the system. This function is only
- * executed when running with a non-ACPI capable PROM.
- */
-static void __init sn_fixup_ionodes(void)
-{
-
- struct hubdev_info *hubdev;
- u64 status;
- u64 nasid;
- int i;
- extern void sn_common_hubdev_init(struct hubdev_info *);
-
- /*
- * Get SGI Specific HUB chipset information.
- * Inform Prom that this kernel can support domain bus numbering.
- */
- for (i = 0; i < num_cnodes; i++) {
- hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
- nasid = cnodeid_to_nasid(i);
- hubdev->max_segment_number = 0xffffffff;
- hubdev->max_pcibus_number = 0xff;
- status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev));
- if (status)
- continue;
-
- /* Save the largest Domain and pcibus numbers found. */
- if (hubdev->max_segment_number) {
- /*
- * Dealing with a Prom that supports segments.
- */
- max_segment_number = hubdev->max_segment_number;
- max_pcibus_number = hubdev->max_pcibus_number;
- }
- sn_common_hubdev_init(hubdev);
- }
-}
-
-/*
- * sn_pci_legacy_window_fixup - Setup PCI resources for
- * legacy IO and MEM space. This needs to
- * be done here, as the PROM does not have
- * ACPI support defining the root buses
- * and their resources (_CRS),
- */
-static void
-sn_legacy_pci_window_fixup(struct resource *res,
- u64 legacy_io, u64 legacy_mem)
-{
- res[0].name = "legacy_io";
- res[0].flags = IORESOURCE_IO;
- res[0].start = legacy_io;
- res[0].end = res[0].start + 0xffff;
- res[0].parent = &ioport_resource;
- res[1].name = "legacy_mem";
- res[1].flags = IORESOURCE_MEM;
- res[1].start = legacy_mem;
- res[1].end = res[1].start + (1024 * 1024) - 1;
- res[1].parent = &iomem_resource;
-}
-
-/*
- * sn_io_slot_fixup() - We are not running with an ACPI capable PROM,
- * and need to convert the pci_dev->resource
- * 'start' and 'end' addresses to mapped addresses,
- * and setup the pci_controller->window array entries.
- */
-void
-sn_io_slot_fixup(struct pci_dev *dev)
-{
- int idx;
- struct resource *res;
- unsigned long size;
- struct pcidev_info *pcidev_info;
- struct sn_irq_info *sn_irq_info;
- int status;
-
- pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
- if (!pcidev_info)
- panic("%s: Unable to alloc memory for pcidev_info", __func__);
-
- sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
- if (!sn_irq_info)
- panic("%s: Unable to alloc memory for sn_irq_info", __func__);
-
- /* Call to retrieve pci device information needed by kernel. */
- status = sal_get_pcidev_info((u64) pci_domain_nr(dev),
- (u64) dev->bus->number,
- dev->devfn,
- (u64) __pa(pcidev_info),
- (u64) __pa(sn_irq_info));
-
- BUG_ON(status); /* Cannot get platform pci device information */
-
-
- /* Copy over PIO Mapped Addresses */
- for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
- if (!pcidev_info->pdi_pio_mapped_addr[idx])
- continue;
-
- res = &dev->resource[idx];
-
- size = res->end - res->start;
- if (size == 0)
- continue;
-
- res->start = pcidev_info->pdi_pio_mapped_addr[idx];
- res->end = res->start + size;
-
- /*
- * if it's already in the device structure, remove it before
- * inserting
- */
- if (res->parent && res->parent->child)
- release_resource(res);
-
- if (res->flags & IORESOURCE_IO)
- insert_resource(&ioport_resource, res);
- else
- insert_resource(&iomem_resource, res);
- /*
- * If ROM, mark as shadowed in PROM.
- */
- if (idx == PCI_ROM_RESOURCE) {
- pci_disable_rom(dev);
- res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
- IORESOURCE_PCI_FIXED;
- }
- }
-
- sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
-}
-EXPORT_SYMBOL(sn_io_slot_fixup);
-
-/*
- * sn_pci_controller_fixup() - This routine sets up a bus's resources
- * consistent with the Linux PCI abstraction layer.
- */
-static void __init
-sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
-{
- s64 status = 0;
- struct pci_controller *controller;
- struct pcibus_bussoft *prom_bussoft_ptr;
- struct resource *res;
- LIST_HEAD(resources);
-
- status = sal_get_pcibus_info((u64) segment, (u64) busnum,
- (u64) ia64_tpa(&prom_bussoft_ptr));
- if (status > 0)
- return; /*bus # does not exist */
- prom_bussoft_ptr = __va(prom_bussoft_ptr);
-
- controller = kzalloc(sizeof(*controller), GFP_KERNEL);
- BUG_ON(!controller);
- controller->segment = segment;
-
- res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
- BUG_ON(!res);
-
- /*
- * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup().
- * (platform_data will be overwritten later in sn_common_bus_fixup())
- */
- controller->platform_data = prom_bussoft_ptr;
-
- sn_legacy_pci_window_fixup(res,
- prom_bussoft_ptr->bs_legacy_io,
- prom_bussoft_ptr->bs_legacy_mem);
- pci_add_resource_offset(&resources, &res[0],
- prom_bussoft_ptr->bs_legacy_io);
- pci_add_resource_offset(&resources, &res[1],
- prom_bussoft_ptr->bs_legacy_mem);
-
- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
- &resources);
- if (bus == NULL) {
- kfree(res);
- kfree(controller);
- return;
- }
- pci_bus_add_devices(bus);
-}
-
-/*
- * sn_bus_fixup
- */
-void
-sn_bus_fixup(struct pci_bus *bus)
-{
- struct pci_dev *pci_dev = NULL;
- struct pcibus_bussoft *prom_bussoft_ptr;
-
- if (!bus->parent) { /* If root bus */
- prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
- if (prom_bussoft_ptr == NULL) {
- printk(KERN_ERR
- "sn_bus_fixup: 0x%04x:0x%02x Unable to "
- "obtain prom_bussoft_ptr\n",
- pci_domain_nr(bus), bus->number);
- return;
- }
- sn_common_bus_fixup(bus, prom_bussoft_ptr);
- }
- list_for_each_entry(pci_dev, &bus->devices, bus_list) {
- sn_io_slot_fixup(pci_dev);
- }
-
-}
-
-/*
- * sn_io_init - PROM does not have ACPI support to define nodes or root buses,
- * so we need to do things the hard way, including initiating the
- * bus scanning ourselves.
- */
-
-void __init sn_io_init(void)
-{
- int i, j;
-
- sn_fixup_ionodes();
-
- /* busses are not known yet ... */
- for (i = 0; i <= max_segment_number; i++)
- for (j = 0; j <= max_pcibus_number; j++)
- sn_pci_controller_fixup(i, j, NULL);
-}
diff --git a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
deleted file mode 100644
index 2b22a71663c1..000000000000
--- a/arch/ia64/sn/kernel/iomv.c
+++ /dev/null
@@ -1,82 +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, 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/acpi.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/vga.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/acpi.h>
-
-#define IS_LEGACY_VGA_IOPORT(p) \
- (((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df))
-
-/**
- * sn_io_addr - convert an in/out port to an i/o address
- * @port: port to convert
- *
- * Legacy in/out instructions are converted to ld/st instructions
- * on IA64. This routine will convert a port number into a valid
- * SN i/o address. Used by sn_in*() and sn_out*().
- */
-
-void *sn_io_addr(unsigned long port)
-{
- if (!IS_RUNNING_ON_SIMULATOR()) {
- if (IS_LEGACY_VGA_IOPORT(port))
- return (__ia64_mk_io_addr(port));
- /* On sn2, legacy I/O ports don't point at anything */
- if (port < (64 * 1024))
- return NULL;
- if (SN_ACPI_BASE_SUPPORT())
- return (__ia64_mk_io_addr(port));
- else
- return ((void *)(port | __IA64_UNCACHED_OFFSET));
- } else {
- /* but the simulator uses them... */
- unsigned long addr;
-
- /*
- * word align port, but need more than 10 bits
- * for accessing registers in bedrock local block
- * (so we don't do port&0xfff)
- */
- addr = (is_shub2() ? 0xc00000028c000000UL : 0xc0000087cc000000UL) | ((port >> 2) << 12);
- if ((port >= 0x1f0 && port <= 0x1f7) || port == 0x3f6 || port == 0x3f7)
- addr |= port;
- return (void *)addr;
- }
-}
-
-EXPORT_SYMBOL(sn_io_addr);
-
-/**
- * __sn_mmiowb - I/O space memory barrier
- *
- * See arch/ia64/include/asm/io.h and Documentation/driver-api/device-io.rst
- * for details.
- *
- * On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear.
- * See PV 871084 for details about the WAR about zero value.
- *
- */
-void __sn_mmiowb(void)
-{
- volatile unsigned long *adr = pda->pio_write_status_addr;
- unsigned long val = pda->pio_write_status_val;
-
- while ((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != val)
- cpu_relax();
-}
-
-EXPORT_SYMBOL(__sn_mmiowb);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
deleted file mode 100644
index d9b576df4f82..000000000000
--- a/arch/ia64/sn/kernel/irq.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Platform dependent support for SGI SN
- *
- * 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-2008 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/irq.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/rculist.h>
-#include <linux/slab.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/sn_feature_sets.h>
-
-static void register_intr_pda(struct sn_irq_info *sn_irq_info);
-static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
-
-extern int sn_ioif_inited;
-struct list_head **sn_irq_lh;
-static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
-
-u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
- struct sn_irq_info *sn_irq_info,
- int req_irq, nasid_t req_nasid,
- int req_slice)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
- (u64) SAL_INTR_ALLOC, (u64) local_nasid,
- (u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
- (u64) req_nasid, (u64) req_slice);
-
- return ret_stuff.status;
-}
-
-void sn_intr_free(nasid_t local_nasid, int local_widget,
- struct sn_irq_info *sn_irq_info)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
- (u64) SAL_INTR_FREE, (u64) local_nasid,
- (u64) local_widget, (u64) sn_irq_info->irq_irq,
- (u64) sn_irq_info->irq_cookie, 0, 0);
-}
-
-u64 sn_intr_redirect(nasid_t local_nasid, int local_widget,
- struct sn_irq_info *sn_irq_info,
- nasid_t req_nasid, int req_slice)
-{
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
- (u64) SAL_INTR_REDIRECT, (u64) local_nasid,
- (u64) local_widget, __pa(sn_irq_info),
- (u64) req_nasid, (u64) req_slice, 0);
-
- return ret_stuff.status;
-}
-
-static unsigned int sn_startup_irq(struct irq_data *data)
-{
- return 0;
-}
-
-static void sn_shutdown_irq(struct irq_data *data)
-{
-}
-
-extern void ia64_mca_register_cpev(int);
-
-static void sn_disable_irq(struct irq_data *data)
-{
- if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
- ia64_mca_register_cpev(0);
-}
-
-static void sn_enable_irq(struct irq_data *data)
-{
- if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
- ia64_mca_register_cpev(data->irq);
-}
-
-static void sn_ack_irq(struct irq_data *data)
-{
- u64 event_occurred, mask;
- unsigned int irq = data->irq & 0xff;
-
- event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
- mask = event_occurred & SH_ALL_INT_MASK;
- HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
- __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
-
- irq_move_irq(data);
-}
-
-struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
- nasid_t nasid, int slice)
-{
- int vector;
- int cpuid;
-#ifdef CONFIG_SMP
- int cpuphys;
-#endif
- int64_t bridge;
- int local_widget, status;
- nasid_t local_nasid;
- struct sn_irq_info *new_irq_info;
- struct sn_pcibus_provider *pci_provider;
-
- bridge = (u64) sn_irq_info->irq_bridge;
- if (!bridge) {
- return NULL; /* irq is not a device interrupt */
- }
-
- local_nasid = NASID_GET(bridge);
-
- if (local_nasid & 1)
- local_widget = TIO_SWIN_WIDGETNUM(bridge);
- else
- local_widget = SWIN_WIDGETNUM(bridge);
- vector = sn_irq_info->irq_irq;
-
- /* Make use of SAL_INTR_REDIRECT if PROM supports it */
- status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice);
- if (!status) {
- new_irq_info = sn_irq_info;
- goto finish_up;
- }
-
- /*
- * PROM does not support SAL_INTR_REDIRECT, or it failed.
- * Revert to old method.
- */
- new_irq_info = kmemdup(sn_irq_info, sizeof(struct sn_irq_info),
- GFP_ATOMIC);
- if (new_irq_info == NULL)
- return NULL;
-
- /* Free the old PROM new_irq_info structure */
- sn_intr_free(local_nasid, local_widget, new_irq_info);
- unregister_intr_pda(new_irq_info);
-
- /* allocate a new PROM new_irq_info struct */
- status = sn_intr_alloc(local_nasid, local_widget,
- new_irq_info, vector,
- nasid, slice);
-
- /* SAL call failed */
- if (status) {
- kfree(new_irq_info);
- return NULL;
- }
-
- register_intr_pda(new_irq_info);
- spin_lock(&sn_irq_info_lock);
- list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
- spin_unlock(&sn_irq_info_lock);
- kfree_rcu(sn_irq_info, rcu);
-
-
-finish_up:
- /* Update kernels new_irq_info with new target info */
- cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
- new_irq_info->irq_slice);
- new_irq_info->irq_cpuid = cpuid;
-
- pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
-
- /*
- * If this represents a line interrupt, target it. If it's
- * an msi (irq_int_bit < 0), it's already targeted.
- */
- if (new_irq_info->irq_int_bit >= 0 &&
- pci_provider && pci_provider->target_interrupt)
- (pci_provider->target_interrupt)(new_irq_info);
-
-#ifdef CONFIG_SMP
- cpuphys = cpu_physical_id(cpuid);
- set_irq_affinity_info((vector & 0xff), cpuphys, 0);
-#endif
-
- return new_irq_info;
-}
-
-static int sn_set_affinity_irq(struct irq_data *data,
- const struct cpumask *mask, bool force)
-{
- struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
- unsigned int irq = data->irq;
- nasid_t nasid;
- int slice;
-
- nasid = cpuid_to_nasid(cpumask_first_and(mask, cpu_online_mask));
- slice = cpuid_to_slice(cpumask_first_and(mask, cpu_online_mask));
-
- list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
- sn_irq_lh[irq], list)
- (void)sn_retarget_vector(sn_irq_info, nasid, slice);
-
- return 0;
-}
-
-#ifdef CONFIG_SMP
-void sn_set_err_irq_affinity(unsigned int irq)
-{
- /*
- * On systems which support CPU disabling (SHub2), all error interrupts
- * are targeted at the boot CPU.
- */
- if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT))
- set_irq_affinity_info(irq, cpu_physical_id(0), 0);
-}
-#else
-void sn_set_err_irq_affinity(unsigned int irq) { }
-#endif
-
-static void
-sn_mask_irq(struct irq_data *data)
-{
-}
-
-static void
-sn_unmask_irq(struct irq_data *data)
-{
-}
-
-struct irq_chip irq_type_sn = {
- .name = "SN hub",
- .irq_startup = sn_startup_irq,
- .irq_shutdown = sn_shutdown_irq,
- .irq_enable = sn_enable_irq,
- .irq_disable = sn_disable_irq,
- .irq_ack = sn_ack_irq,
- .irq_mask = sn_mask_irq,
- .irq_unmask = sn_unmask_irq,
- .irq_set_affinity = sn_set_affinity_irq
-};
-
-ia64_vector sn_irq_to_vector(int irq)
-{
- if (irq >= IA64_NUM_VECTORS)
- return 0;
- return (ia64_vector)irq;
-}
-
-unsigned int sn_local_vector_to_irq(u8 vector)
-{
- return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
-}
-
-void sn_irq_init(void)
-{
- int i;
-
- ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
- ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
-
- for (i = 0; i < NR_IRQS; i++) {
- if (irq_get_chip(i) == &no_irq_chip)
- irq_set_chip(i, &irq_type_sn);
- }
-}
-
-static void register_intr_pda(struct sn_irq_info *sn_irq_info)
-{
- int irq = sn_irq_info->irq_irq;
- int cpu = sn_irq_info->irq_cpuid;
-
- if (pdacpu(cpu)->sn_last_irq < irq) {
- pdacpu(cpu)->sn_last_irq = irq;
- }
-
- if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq)
- pdacpu(cpu)->sn_first_irq = irq;
-}
-
-static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
-{
- int irq = sn_irq_info->irq_irq;
- int cpu = sn_irq_info->irq_cpuid;
- struct sn_irq_info *tmp_irq_info;
- int i, foundmatch;
-
- rcu_read_lock();
- if (pdacpu(cpu)->sn_last_irq == irq) {
- foundmatch = 0;
- for (i = pdacpu(cpu)->sn_last_irq - 1;
- i && !foundmatch; i--) {
- list_for_each_entry_rcu(tmp_irq_info,
- sn_irq_lh[i],
- list) {
- if (tmp_irq_info->irq_cpuid == cpu) {
- foundmatch = 1;
- break;
- }
- }
- }
- pdacpu(cpu)->sn_last_irq = i;
- }
-
- if (pdacpu(cpu)->sn_first_irq == irq) {
- foundmatch = 0;
- for (i = pdacpu(cpu)->sn_first_irq + 1;
- i < NR_IRQS && !foundmatch; i++) {
- list_for_each_entry_rcu(tmp_irq_info,
- sn_irq_lh[i],
- list) {
- if (tmp_irq_info->irq_cpuid == cpu) {
- foundmatch = 1;
- break;
- }
- }
- }
- pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i);
- }
- rcu_read_unlock();
-}
-
-void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
-{
- nasid_t nasid = sn_irq_info->irq_nasid;
- int slice = sn_irq_info->irq_slice;
- int cpu = nasid_slice_to_cpuid(nasid, slice);
-#ifdef CONFIG_SMP
- int cpuphys;
-#endif
-
- pci_dev_get(pci_dev);
- sn_irq_info->irq_cpuid = cpu;
- sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);
-
- /* link it into the sn_irq[irq] list */
- spin_lock(&sn_irq_info_lock);
- list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
- reserve_irq_vector(sn_irq_info->irq_irq);
- if (sn_irq_info->irq_int_bit != -1)
- irq_set_handler(sn_irq_info->irq_irq, handle_level_irq);
- spin_unlock(&sn_irq_info_lock);
-
- register_intr_pda(sn_irq_info);
-#ifdef CONFIG_SMP
- cpuphys = cpu_physical_id(cpu);
- set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
- /*
- * Affinity was set by the PROM, prevent it from
- * being reset by the request_irq() path.
- */
- irqd_mark_affinity_was_set(irq_get_irq_data(sn_irq_info->irq_irq));
-#endif
-}
-
-void sn_irq_unfixup(struct pci_dev *pci_dev)
-{
- struct sn_irq_info *sn_irq_info;
-
- /* Only cleanup IRQ stuff if this device has a host bus context */
- if (!SN_PCIDEV_BUSSOFT(pci_dev))
- return;
-
- sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
- if (!sn_irq_info)
- return;
- if (!sn_irq_info->irq_irq) {
- kfree(sn_irq_info);
- return;
- }
-
- unregister_intr_pda(sn_irq_info);
- spin_lock(&sn_irq_info_lock);
- list_del_rcu(&sn_irq_info->list);
- spin_unlock(&sn_irq_info_lock);
- if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
- free_irq_vector(sn_irq_info->irq_irq);
- kfree_rcu(sn_irq_info, rcu);
- pci_dev_put(pci_dev);
-
-}
-
-static inline void
-sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
-{
- struct sn_pcibus_provider *pci_provider;
-
- pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
-
- /* Don't force an interrupt if the irq has been disabled */
- if (!irqd_irq_disabled(irq_get_irq_data(sn_irq_info->irq_irq)) &&
- pci_provider && pci_provider->force_interrupt)
- (*pci_provider->force_interrupt)(sn_irq_info);
-}
-
-/*
- * Check for lost interrupts. If the PIC int_status reg. says that
- * an interrupt has been sent, but not handled, and the interrupt
- * is not pending in either the cpu irr regs or in the soft irr regs,
- * and the interrupt is not in service, then the interrupt may have
- * been lost. Force an interrupt on that pin. It is possible that
- * the interrupt is in flight, so we may generate a spurious interrupt,
- * but we should never miss a real lost interrupt.
- */
-static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
-{
- u64 regval;
- struct pcidev_info *pcidev_info;
- struct pcibus_info *pcibus_info;
-
- /*
- * Bridge types attached to TIO (anything but PIC) do not need this WAR
- * since they do not target Shub II interrupt registers. If that
- * ever changes, this check needs to accommodate.
- */
- if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
- return;
-
- pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- if (!pcidev_info)
- return;
-
- pcibus_info =
- (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info->
- pdi_pcibus_info;
- regval = pcireg_intr_status_get(pcibus_info);
-
- if (!ia64_get_irr(irq_to_vector(irq))) {
- if (!test_bit(irq, pda->sn_in_service_ivecs)) {
- regval &= 0xff;
- if (sn_irq_info->irq_int_bit & regval &
- sn_irq_info->irq_last_intr) {
- regval &= ~(sn_irq_info->irq_int_bit & regval);
- sn_call_force_intr_provider(sn_irq_info);
- }
- }
- }
- sn_irq_info->irq_last_intr = regval;
-}
-
-void sn_lb_int_war_check(void)
-{
- struct sn_irq_info *sn_irq_info;
- int i;
-
- if (!sn_ioif_inited || pda->sn_first_irq == 0)
- return;
-
- rcu_read_lock();
- for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
- list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
- sn_check_intr(i, sn_irq_info);
- }
- }
- rcu_read_unlock();
-}
-
-void __init sn_irq_lh_init(void)
-{
- int i;
-
- sn_irq_lh = kmalloc_array(NR_IRQS, sizeof(struct list_head *),
- GFP_KERNEL);
- if (!sn_irq_lh)
- panic("SN PCI INIT: Failed to allocate memory for PCI init\n");
-
- for (i = 0; i < NR_IRQS; i++) {
- sn_irq_lh[i] = kmalloc(sizeof(struct list_head), GFP_KERNEL);
- if (!sn_irq_lh[i])
- panic("SN PCI INIT: Failed IRQ memory allocation\n");
-
- INIT_LIST_HEAD(sn_irq_lh[i]);
- }
-}
diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c
deleted file mode 100644
index 87682b48ef83..000000000000
--- a/arch/ia64/sn/kernel/klconflib.c
+++ /dev/null
@@ -1,107 +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-2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <asm/sn/types.h>
-#include <asm/sn/module.h>
-#include <asm/sn/l1.h>
-
-char brick_types[MAX_BRICK_TYPES + 1] = "cri.xdpn%#=vo^kjbf890123456789...";
-/*
- * Format a module id for printing.
- *
- * There are three possible formats:
- *
- * MODULE_FORMAT_BRIEF is the brief 6-character format, including
- * the actual brick-type as recorded in the
- * moduleid_t, eg. 002c15 for a C-brick, or
- * 101#17 for a PX-brick.
- *
- * MODULE_FORMAT_LONG is the hwgraph format, eg. rack/002/bay/15
- * of rack/101/bay/17 (note that the brick
- * type does not appear in this format).
- *
- * MODULE_FORMAT_LCD is like MODULE_FORMAT_BRIEF, except that it
- * ensures that the module id provided appears
- * exactly as it would on the LCD display of
- * the corresponding brick, eg. still 002c15
- * for a C-brick, but 101p17 for a PX-brick.
- *
- * maule (9/13/04): Removed top-level check for (fmt == MODULE_FORMAT_LCD)
- * making MODULE_FORMAT_LCD equivalent to MODULE_FORMAT_BRIEF. It was
- * decided that all callers should assume the returned string should be what
- * is displayed on the brick L1 LCD.
- */
-void
-format_module_id(char *buffer, moduleid_t m, int fmt)
-{
- int rack, position;
- unsigned char brickchar;
-
- rack = MODULE_GET_RACK(m);
- brickchar = MODULE_GET_BTCHAR(m);
-
- /* Be sure we use the same brick type character as displayed
- * on the brick's LCD
- */
- switch (brickchar)
- {
- case L1_BRICKTYPE_GA:
- case L1_BRICKTYPE_OPUS_TIO:
- brickchar = L1_BRICKTYPE_C;
- break;
-
- case L1_BRICKTYPE_PX:
- case L1_BRICKTYPE_PE:
- case L1_BRICKTYPE_PA:
- case L1_BRICKTYPE_SA: /* we can move this to the "I's" later
- * if that makes more sense
- */
- brickchar = L1_BRICKTYPE_P;
- break;
-
- case L1_BRICKTYPE_IX:
- case L1_BRICKTYPE_IA:
-
- brickchar = L1_BRICKTYPE_I;
- break;
- }
-
- position = MODULE_GET_BPOS(m);
-
- if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) {
- /* Brief module number format, eg. 002c15 */
-
- /* Decompress the rack number */
- *buffer++ = '0' + RACK_GET_CLASS(rack);
- *buffer++ = '0' + RACK_GET_GROUP(rack);
- *buffer++ = '0' + RACK_GET_NUM(rack);
-
- /* Add the brick type */
- *buffer++ = brickchar;
- }
- else if (fmt == MODULE_FORMAT_LONG) {
- /* Fuller hwgraph format, eg. rack/002/bay/15 */
-
- strcpy(buffer, "rack" "/"); buffer += strlen(buffer);
-
- *buffer++ = '0' + RACK_GET_CLASS(rack);
- *buffer++ = '0' + RACK_GET_GROUP(rack);
- *buffer++ = '0' + RACK_GET_NUM(rack);
-
- strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer);
- }
-
- /* Add the bay position, using at least two digits */
- if (position < 10)
- *buffer++ = '0';
- sprintf(buffer, "%d", position);
-}
diff --git a/arch/ia64/sn/kernel/machvec.c b/arch/ia64/sn/kernel/machvec.c
deleted file mode 100644
index 02bb9155840c..000000000000
--- a/arch/ia64/sn/kernel/machvec.c
+++ /dev/null
@@ -1,11 +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) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#define MACHVEC_PLATFORM_NAME sn2
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_sn2.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
deleted file mode 100644
index bc3bd930c74c..000000000000
--- a/arch/ia64/sn/kernel/mca.c
+++ /dev/null
@@ -1,144 +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-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/vmalloc.h>
-#include <linux/mutex.h>
-#include <asm/mca.h>
-#include <asm/sal.h>
-#include <asm/sn/sn_sal.h>
-
-/*
- * Interval for calling SAL to poll for errors that do NOT cause error
- * interrupts. SAL will raise a CPEI if any errors are present that
- * need to be logged.
- */
-#define CPEI_INTERVAL (5*HZ)
-
-struct timer_list sn_cpei_timer;
-void sn_init_cpei_timer(void);
-
-/* Printing oemdata from mca uses data that is not passed through SAL, it is
- * global. Only one user at a time.
- */
-static DEFINE_MUTEX(sn_oemdata_mutex);
-static u8 **sn_oemdata;
-static u64 *sn_oemdata_size, sn_oemdata_bufsize;
-
-/*
- * print_hook
- *
- * This function is the callback routine that SAL calls to log error
- * info for platform errors. buf is appended to sn_oemdata, resizing as
- * required.
- * Note: this is a SAL to OS callback, running under the same rules as the SAL
- * code. SAL calls are run with preempt disabled so this routine must not
- * sleep. vmalloc can sleep so print_hook cannot resize the output buffer
- * itself, instead it must set the required size and return to let the caller
- * resize the buffer then redrive the SAL call.
- */
-static int print_hook(const char *fmt, ...)
-{
- char buf[400];
- int len;
- va_list args;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- len = strlen(buf);
- if (*sn_oemdata_size + len <= sn_oemdata_bufsize)
- memcpy(*sn_oemdata + *sn_oemdata_size, buf, len);
- *sn_oemdata_size += len;
- return 0;
-}
-
-static void sn_cpei_handler(int irq, void *devid, struct pt_regs *regs)
-{
- /*
- * this function's sole purpose is to call SAL when we receive
- * a CE interrupt from SHUB or when the timer routine decides
- * we need to call SAL to check for CEs.
- */
-
- /* CALL SAL_LOG_CE */
-
- ia64_sn_plat_cpei_handler();
-}
-
-static void sn_cpei_timer_handler(struct timer_list *unused)
-{
- sn_cpei_handler(-1, NULL, NULL);
- mod_timer(&sn_cpei_timer, jiffies + CPEI_INTERVAL);
-}
-
-void sn_init_cpei_timer(void)
-{
- timer_setup(&sn_cpei_timer, sn_cpei_timer_handler, 0);
- sn_cpei_timer.expires = jiffies + CPEI_INTERVAL;
- add_timer(&sn_cpei_timer);
-}
-
-static int
-sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
- u64 * oemdata_size)
-{
- mutex_lock(&sn_oemdata_mutex);
- sn_oemdata = oemdata;
- sn_oemdata_size = oemdata_size;
- sn_oemdata_bufsize = 0;
- *sn_oemdata_size = PAGE_SIZE; /* first guess at how much data will be generated */
- while (*sn_oemdata_size > sn_oemdata_bufsize) {
- u8 *newbuf = vmalloc(*sn_oemdata_size);
- if (!newbuf) {
- mutex_unlock(&sn_oemdata_mutex);
- printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
- __func__);
- return 1;
- }
- vfree(*sn_oemdata);
- *sn_oemdata = newbuf;
- sn_oemdata_bufsize = *sn_oemdata_size;
- *sn_oemdata_size = 0;
- ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
- }
- mutex_unlock(&sn_oemdata_mutex);
- return 0;
-}
-
-/* Callback when userspace salinfo wants to decode oem data via the platform
- * kernel and/or prom.
- */
-int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
-{
- efi_guid_t guid = *(efi_guid_t *)sect_header;
- int valid = 0;
- *oemdata_size = 0;
- vfree(*oemdata);
- *oemdata = NULL;
- if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
- sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header;
- valid = psei->valid.oem_data;
- } else if (efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
- sal_log_mem_dev_err_info_t *mdei = (sal_log_mem_dev_err_info_t *)sect_header;
- valid = mdei->valid.oem_data;
- }
- if (valid)
- return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size);
- else
- return 0;
-}
-
-static int __init sn_salinfo_init(void)
-{
- if (ia64_platform_is("sn2"))
- salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
- return 0;
-}
-device_initcall(sn_salinfo_init);
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
deleted file mode 100644
index fb25065b22c6..000000000000
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ /dev/null
@@ -1,238 +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) 2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/cpumask.h>
-#include <linux/msi.h>
-#include <linux/slab.h>
-
-#include <asm/sn/addrs.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/nodepda.h>
-
-struct sn_msi_info {
- u64 pci_addr;
- struct sn_irq_info *sn_irq_info;
-};
-
-static struct sn_msi_info sn_msi_info[NR_IRQS];
-
-static struct irq_chip sn_msi_chip;
-
-void sn_teardown_msi_irq(unsigned int irq)
-{
- nasid_t nasid;
- int widget;
- struct pci_dev *pdev;
- struct pcidev_info *sn_pdev;
- struct sn_irq_info *sn_irq_info;
- struct pcibus_bussoft *bussoft;
- struct sn_pcibus_provider *provider;
-
- sn_irq_info = sn_msi_info[irq].sn_irq_info;
- if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
- return;
-
- sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- pdev = sn_pdev->pdi_linux_pcidev;
- provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- (*provider->dma_unmap)(pdev,
- sn_msi_info[irq].pci_addr,
- PCI_DMA_FROMDEVICE);
- sn_msi_info[irq].pci_addr = 0;
-
- bussoft = SN_PCIDEV_BUSSOFT(pdev);
- nasid = NASID_GET(bussoft->bs_base);
- widget = (nasid & 1) ?
- TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
- SWIN_WIDGETNUM(bussoft->bs_base);
-
- sn_intr_free(nasid, widget, sn_irq_info);
- sn_msi_info[irq].sn_irq_info = NULL;
-
- destroy_irq(irq);
-}
-
-int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
-{
- struct msi_msg msg;
- int widget;
- int status;
- nasid_t nasid;
- u64 bus_addr;
- struct sn_irq_info *sn_irq_info;
- struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
- int irq;
-
- if (!entry->msi_attrib.is_64)
- return -EINVAL;
-
- if (bussoft == NULL)
- return -EINVAL;
-
- if (provider == NULL || provider->dma_map_consistent == NULL)
- return -EINVAL;
-
- irq = create_irq();
- if (irq < 0)
- return irq;
-
- /*
- * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
- * decide which cpu to direct this msi at by default.
- */
-
- nasid = NASID_GET(bussoft->bs_base);
- widget = (nasid & 1) ?
- TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
- SWIN_WIDGETNUM(bussoft->bs_base);
-
- sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
- if (! sn_irq_info) {
- destroy_irq(irq);
- return -ENOMEM;
- }
-
- status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
- if (status) {
- kfree(sn_irq_info);
- destroy_irq(irq);
- return -ENOMEM;
- }
-
- sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
- sn_irq_fixup(pdev, sn_irq_info);
-
- /* Prom probably should fill these in, but doesn't ... */
- sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
- sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
-
- /*
- * Map the xio address into bus space
- */
- bus_addr = (*provider->dma_map_consistent)(pdev,
- sn_irq_info->irq_xtalkaddr,
- sizeof(sn_irq_info->irq_xtalkaddr),
- SN_DMA_MSI|SN_DMA_ADDR_XIO);
- if (! bus_addr) {
- sn_intr_free(nasid, widget, sn_irq_info);
- kfree(sn_irq_info);
- destroy_irq(irq);
- return -ENOMEM;
- }
-
- sn_msi_info[irq].sn_irq_info = sn_irq_info;
- sn_msi_info[irq].pci_addr = bus_addr;
-
- msg.address_hi = (u32)(bus_addr >> 32);
- msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
-
- /*
- * In the SN platform, bit 16 is a "send vector" bit which
- * must be present in order to move the vector through the system.
- */
- msg.data = 0x100 + irq;
-
- irq_set_msi_desc(irq, entry);
- pci_write_msi_msg(irq, &msg);
- irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
-
- return 0;
-}
-
-#ifdef CONFIG_SMP
-static int sn_set_msi_irq_affinity(struct irq_data *data,
- const struct cpumask *cpu_mask, bool force)
-{
- struct msi_msg msg;
- int slice;
- nasid_t nasid;
- u64 bus_addr;
- struct pci_dev *pdev;
- struct pcidev_info *sn_pdev;
- struct sn_irq_info *sn_irq_info;
- struct sn_irq_info *new_irq_info;
- struct sn_pcibus_provider *provider;
- unsigned int cpu, irq = data->irq;
-
- cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
- sn_irq_info = sn_msi_info[irq].sn_irq_info;
- if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
- return -1;
-
- /*
- * Release XIO resources for the old MSI PCI address
- */
-
- __get_cached_msi_msg(irq_data_get_msi_desc(data), &msg);
- sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- pdev = sn_pdev->pdi_linux_pcidev;
- provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- bus_addr = (u64)(msg.address_hi) << 32 | (u64)(msg.address_lo);
- (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
- sn_msi_info[irq].pci_addr = 0;
-
- nasid = cpuid_to_nasid(cpu);
- slice = cpuid_to_slice(cpu);
-
- new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
- sn_msi_info[irq].sn_irq_info = new_irq_info;
- if (new_irq_info == NULL)
- return -1;
-
- /*
- * Map the xio address into bus space
- */
-
- bus_addr = (*provider->dma_map_consistent)(pdev,
- new_irq_info->irq_xtalkaddr,
- sizeof(new_irq_info->irq_xtalkaddr),
- SN_DMA_MSI|SN_DMA_ADDR_XIO);
-
- sn_msi_info[irq].pci_addr = bus_addr;
- msg.address_hi = (u32)(bus_addr >> 32);
- msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
-
- pci_write_msi_msg(irq, &msg);
- cpumask_copy(irq_data_get_affinity_mask(data), cpu_mask);
-
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-static void sn_ack_msi_irq(struct irq_data *data)
-{
- irq_move_irq(data);
- ia64_eoi();
-}
-
-static int sn_msi_retrigger_irq(struct irq_data *data)
-{
- unsigned int vector = data->irq;
- ia64_resend_irq(vector);
-
- return 1;
-}
-
-static struct irq_chip sn_msi_chip = {
- .name = "PCI-MSI",
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
- .irq_ack = sn_ack_msi_irq,
-#ifdef CONFIG_SMP
- .irq_set_affinity = sn_set_msi_irq_affinity,
-#endif
- .irq_retrigger = sn_msi_retrigger_irq,
-};
diff --git a/arch/ia64/sn/kernel/pio_phys.S b/arch/ia64/sn/kernel/pio_phys.S
deleted file mode 100644
index 3c7d48d6ecb8..000000000000
--- a/arch/ia64/sn/kernel/pio_phys.S
+++ /dev/null
@@ -1,71 +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-2005 Silicon Graphics, Inc. All rights reserved.
- *
- * This file contains macros used to access MMR registers via
- * uncached physical addresses.
- * pio_phys_read_mmr - read an MMR
- * pio_phys_write_mmr - write an MMR
- * pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
- * Second MMR will be skipped if address is NULL
- *
- * Addresses passed to these routines should be uncached physical addresses
- * ie., 0x80000....
- */
-
-
-
-#include <asm/asmmacro.h>
-#include <asm/page.h>
-
-GLOBAL_ENTRY(pio_phys_read_mmr)
- .prologue
- .regstk 1,0,0,0
- .body
- mov r2=psr
- rsm psr.i | psr.dt
- ;;
- srlz.d
- ld8.acq r8=[r32]
- ;;
- mov psr.l=r2;;
- srlz.d
- br.ret.sptk.many rp
-END(pio_phys_read_mmr)
-
-GLOBAL_ENTRY(pio_phys_write_mmr)
- .prologue
- .regstk 2,0,0,0
- .body
- mov r2=psr
- rsm psr.i | psr.dt
- ;;
- srlz.d
- st8.rel [r32]=r33
- ;;
- mov psr.l=r2;;
- srlz.d
- br.ret.sptk.many rp
-END(pio_phys_write_mmr)
-
-GLOBAL_ENTRY(pio_atomic_phys_write_mmrs)
- .prologue
- .regstk 4,0,0,0
- .body
- mov r2=psr
- cmp.ne p9,p0=r34,r0;
- rsm psr.i | psr.dt | psr.ic
- ;;
- srlz.d
- st8.rel [r32]=r33
-(p9) st8.rel [r34]=r35
- ;;
- mov psr.l=r2;;
- srlz.d
- br.ret.sptk.many rp
-END(pio_atomic_phys_write_mmrs)
-
-
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
deleted file mode 100644
index e6a5049ef503..000000000000
--- a/arch/ia64/sn/kernel/setup.c
+++ /dev/null
@@ -1,786 +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) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/string.h>
-#include <linux/screen_info.h>
-#include <linux/console.h>
-#include <linux/timex.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/irq.h>
-#include <linux/memblock.h>
-#include <linux/mmzone.h>
-#include <linux/interrupt.h>
-#include <linux/acpi.h>
-#include <linux/compiler.h>
-#include <linux/root_dev.h>
-#include <linux/nodemask.h>
-#include <linux/pm.h>
-#include <linux/efi.h>
-
-#include <asm/io.h>
-#include <asm/sal.h>
-#include <asm/machvec.h>
-#include <asm/processor.h>
-#include <asm/vga.h>
-#include <asm/setup.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/leds.h>
-#include <asm/sn/bte.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/clksupport.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/sn_feature_sets.h>
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-#include <asm/sn/klconfig.h>
-
-
-DEFINE_PER_CPU(struct pda_s, pda_percpu);
-
-#define MAX_PHYS_MEMORY (1UL << IA64_MAX_PHYS_BITS) /* Max physical address supported */
-
-extern void bte_init_node(nodepda_t *, cnodeid_t);
-
-extern void sn_timer_init(void);
-extern unsigned long last_time_offset;
-extern void (*ia64_mark_idle) (int);
-extern void snidle(int);
-
-unsigned long sn_rtc_cycles_per_second;
-EXPORT_SYMBOL(sn_rtc_cycles_per_second);
-
-DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
-EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
-
-DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]);
-EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
-
-DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
-EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
-
-char sn_system_serial_number_string[128];
-EXPORT_SYMBOL(sn_system_serial_number_string);
-u64 sn_partition_serial_number;
-EXPORT_SYMBOL(sn_partition_serial_number);
-u8 sn_partition_id;
-EXPORT_SYMBOL(sn_partition_id);
-u8 sn_system_size;
-EXPORT_SYMBOL(sn_system_size);
-u8 sn_sharing_domain_size;
-EXPORT_SYMBOL(sn_sharing_domain_size);
-u8 sn_coherency_id;
-EXPORT_SYMBOL(sn_coherency_id);
-u8 sn_region_size;
-EXPORT_SYMBOL(sn_region_size);
-int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
-
-short physical_node_map[MAX_NUMALINK_NODES];
-static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
-
-EXPORT_SYMBOL(physical_node_map);
-
-int num_cnodes;
-
-static void sn_init_pdas(char **);
-static void build_cnode_tables(void);
-
-static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
-
-/*
- * 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 sn_screen_info = {
- .orig_x = 0,
- .orig_y = 0,
- .orig_video_mode = 3,
- .orig_video_cols = 80,
- .orig_video_ega_bx = 3,
- .orig_video_lines = 25,
- .orig_video_isVGA = 1,
- .orig_video_points = 16
-};
-
-/*
- * This routine can only be used during init, since
- * smp_boot_data is an init data structure.
- * We have to use smp_boot_data.cpu_phys_id to find
- * the physical id of the processor because the normal
- * cpu_physical_id() relies on data structures that
- * may not be initialized yet.
- */
-
-static int __init pxm_to_nasid(int pxm)
-{
- int i;
- int nid;
-
- nid = pxm_to_node(pxm);
- for (i = 0; i < num_node_memblks; i++) {
- if (node_memblk[i].nid == nid) {
- return NASID_GET(node_memblk[i].start_paddr);
- }
- }
- return -1;
-}
-
-/**
- * early_sn_setup - early setup routine for SN platforms
- *
- * Sets up an initial console to aid debugging. Intended primarily
- * for bringup. See start_kernel() in init/main.c.
- */
-
-void __init early_sn_setup(void)
-{
- efi_system_table_t *efi_systab;
- efi_config_table_t *config_tables;
- struct ia64_sal_systab *sal_systab;
- struct ia64_sal_desc_entry_point *ep;
- char *p;
- int i, j;
-
- /*
- * Parse enough of the SAL tables to locate the SAL entry point. Since, console
- * IO on SN2 is done via SAL calls, early_printk won't work without this.
- *
- * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c.
- * Any changes to those file may have to be made here as well.
- */
- efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab);
- config_tables = __va(efi_systab->tables);
- for (i = 0; i < efi_systab->nr_tables; i++) {
- if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) ==
- 0) {
- sal_systab = __va(config_tables[i].table);
- p = (char *)(sal_systab + 1);
- for (j = 0; j < sal_systab->entry_count; j++) {
- if (*p == SAL_DESC_ENTRY_POINT) {
- ep = (struct ia64_sal_desc_entry_point
- *)p;
- ia64_sal_handler_init(__va
- (ep->sal_proc),
- __va(ep->gp));
- return;
- }
- p += SAL_DESC_SIZE(*p);
- }
- }
- }
- /* Uh-oh, SAL not available?? */
- printk(KERN_ERR "failed to find SAL entry point\n");
-}
-
-extern int platform_intr_list[];
-static int shub_1_1_found;
-
-/*
- * sn_check_for_wars
- *
- * Set flag for enabling shub specific wars
- */
-
-static inline int is_shub_1_1(int nasid)
-{
- unsigned long id;
- int rev;
-
- if (is_shub2())
- return 0;
- id = REMOTE_HUB_L(nasid, SH1_SHUB_ID);
- rev = (id & SH1_SHUB_ID_REVISION_MASK) >> SH1_SHUB_ID_REVISION_SHFT;
- return rev <= 2;
-}
-
-static void sn_check_for_wars(void)
-{
- int cnode;
-
- if (is_shub2()) {
- /* none yet */
- } else {
- for_each_online_node(cnode) {
- if (is_shub_1_1(cnodeid_to_nasid(cnode)))
- shub_1_1_found = 1;
- }
- }
-}
-
-/*
- * Scan the EFI PCDP table (if it exists) for an acceptable VGA console
- * output device. If one exists, pick it and set sn_legacy_{io,mem} to
- * reflect the bus offsets needed to address it.
- *
- * Since pcdp support in SN is not supported in the 2.4 kernel (or at least
- * the one lbs is based on) just declare the needed structs here.
- *
- * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf
- *
- * Returns 0 if no acceptable vga is found, !0 otherwise.
- *
- * Note: This stuff is duped here because Altix requires the PCDP to
- * locate a usable VGA device due to lack of proper ACPI support. Structures
- * could be used from drivers/firmware/pcdp.h, but it was decided that moving
- * this file to a more public location just for Altix use was undesirable.
- */
-
-struct hcdp_uart_desc {
- u8 pad[45];
-};
-
-struct pcdp {
- u8 signature[4]; /* should be 'HCDP' */
- u32 length;
- u8 rev; /* should be >=3 for pcdp, <3 for hcdp */
- u8 sum;
- u8 oem_id[6];
- u64 oem_tableid;
- u32 oem_rev;
- u32 creator_id;
- u32 creator_rev;
- u32 num_type0;
- struct hcdp_uart_desc uart[0]; /* num_type0 of these */
- /* pcdp descriptors follow */
-} __attribute__((packed));
-
-struct pcdp_device_desc {
- u8 type;
- u8 primary;
- u16 length;
- u16 index;
- /* interconnect specific structure follows */
- /* device specific structure follows that */
-} __attribute__((packed));
-
-struct pcdp_interface_pci {
- u8 type; /* 1 == pci */
- u8 reserved;
- u16 length;
- u8 segment;
- u8 bus;
- u8 dev;
- u8 fun;
- u16 devid;
- u16 vendid;
- u32 acpi_interrupt;
- u64 mmio_tra;
- u64 ioport_tra;
- u8 flags;
- u8 translation;
-} __attribute__((packed));
-
-struct pcdp_vga_device {
- u8 num_eas_desc;
- /* ACPI Extended Address Space Desc follows */
-} __attribute__((packed));
-
-/* from pcdp_device_desc.primary */
-#define PCDP_PRIMARY_CONSOLE 0x01
-
-/* from pcdp_device_desc.type */
-#define PCDP_CONSOLE_INOUT 0x0
-#define PCDP_CONSOLE_DEBUG 0x1
-#define PCDP_CONSOLE_OUT 0x2
-#define PCDP_CONSOLE_IN 0x3
-#define PCDP_CONSOLE_TYPE_VGA 0x8
-
-#define PCDP_CONSOLE_VGA (PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT)
-
-/* from pcdp_interface_pci.type */
-#define PCDP_IF_PCI 1
-
-/* from pcdp_interface_pci.translation */
-#define PCDP_PCI_TRANS_IOPORT 0x02
-#define PCDP_PCI_TRANS_MMIO 0x01
-
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
-static void
-sn_scan_pcdp(void)
-{
- u8 *bp;
- struct pcdp *pcdp;
- struct pcdp_device_desc device;
- struct pcdp_interface_pci if_pci;
- extern struct efi efi;
-
- if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
- return; /* no hcdp/pcdp table */
-
- pcdp = __va(efi.hcdp);
-
- if (pcdp->rev < 3)
- return; /* only support PCDP (rev >= 3) */
-
- for (bp = (u8 *)&pcdp->uart[pcdp->num_type0];
- bp < (u8 *)pcdp + pcdp->length;
- bp += device.length) {
- memcpy(&device, bp, sizeof(device));
- if (! (device.primary & PCDP_PRIMARY_CONSOLE))
- continue; /* not primary console */
-
- if (device.type != PCDP_CONSOLE_VGA)
- continue; /* not VGA descriptor */
-
- memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci));
- if (if_pci.type != PCDP_IF_PCI)
- continue; /* not PCI interconnect */
-
- if (if_pci.translation & PCDP_PCI_TRANS_IOPORT)
- vga_console_iobase = if_pci.ioport_tra;
-
- if (if_pci.translation & PCDP_PCI_TRANS_MMIO)
- vga_console_membase =
- if_pci.mmio_tra | __IA64_UNCACHED_OFFSET;
-
- break; /* once we find the primary, we're done */
- }
-}
-#endif
-
-static unsigned long sn2_rtc_initial;
-
-/**
- * sn_setup - SN platform setup routine
- * @cmdline_p: kernel command line
- *
- * Handles platform setup for SN machines. This includes determining
- * the RTC frequency (via a SAL call), initializing secondary CPUs, and
- * setting up per-node data areas. The console is also initialized here.
- */
-void __init sn_setup(char **cmdline_p)
-{
- long status, ticks_per_sec, drift;
- u32 version = sn_sal_rev();
- extern void sn_cpu_init(void);
-
- sn2_rtc_initial = rtc_time();
- ia64_sn_plat_set_error_handling_features(); // obsolete
- ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
- ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
- /*
- * Note: The calls to notify the PROM of ACPI and PCI Segment
- * support must be done prior to acpi_load_tables(), as
- * an ACPI capable PROM will rebuild the DSDT as result
- * of the call.
- */
- ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE);
- ia64_sn_set_os_feature(OSF_ACPI_ENABLE);
-
- /* Load the new DSDT and SSDT tables into the global table list. */
- acpi_table_init();
-
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
- /*
- * Handle SN vga console.
- *
- * SN systems do not have enough ACPI table information
- * being passed from prom to identify VGA adapters and the legacy
- * addresses to access them. Until that is done, SN systems rely
- * on the PCDP table to identify the primary VGA console if one
- * exists.
- *
- * However, kernel PCDP support is optional, and even if it is built
- * into the kernel, it will not be used if the boot cmdline contains
- * console= directives.
- *
- * So, to work around this mess, we duplicate some of the PCDP code
- * here so that the primary VGA console (as defined by PCDP) will
- * work on SN systems even if a different console (e.g. serial) is
- * selected on the boot line (or CONFIG_EFI_PCDP is off).
- */
-
- if (! vga_console_membase)
- sn_scan_pcdp();
-
- /*
- * Setup legacy IO space.
- * vga_console_iobase maps to PCI IO Space address 0 on the
- * bus containing the VGA console.
- */
- if (vga_console_iobase) {
- io_space[0].mmio_base =
- (unsigned long) ioremap(vga_console_iobase, 0);
- io_space[0].sparse = 0;
- }
-
- if (vga_console_membase) {
- /* usable vga ... make tty0 the preferred default console */
- if (!strstr(*cmdline_p, "console="))
- add_preferred_console("tty", 0, NULL);
- } else {
- printk(KERN_DEBUG "SGI: Disabling VGA console\n");
- if (!strstr(*cmdline_p, "console="))
- add_preferred_console("ttySG", 0, NULL);
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#else
- conswitchp = NULL;
-#endif /* CONFIG_DUMMY_CONSOLE */
- }
-#endif /* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */
-
- MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
-
- /*
- * Build the tables for managing cnodes.
- */
- build_cnode_tables();
-
- status =
- ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
- &drift);
- if (status != 0 || ticks_per_sec < 100000) {
- printk(KERN_WARNING
- "unable to determine platform RTC clock frequency, guessing.\n");
- /* PROM gives wrong value for clock freq. so guess */
- sn_rtc_cycles_per_second = 1000000000000UL / 30000UL;
- } else
- sn_rtc_cycles_per_second = ticks_per_sec;
-
- platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
-
- printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
-
- /*
- * we set the default root device to /dev/hda
- * to make simulation easy
- */
- ROOT_DEV = Root_HDA1;
-
- /*
- * Create the PDAs and NODEPDAs for all the cpus.
- */
- sn_init_pdas(cmdline_p);
-
- ia64_mark_idle = &snidle;
-
- /*
- * For the bootcpu, we do this here. All other cpus will make the
- * call as part of cpu_init in slave cpu initialization.
- */
- sn_cpu_init();
-
-#ifdef CONFIG_SMP
- init_smp_config();
-#endif
- screen_info = sn_screen_info;
-
- sn_timer_init();
-
- /*
- * set pm_power_off to a SAL call to allow
- * sn machines to power off. The SAL call can be replaced
- * by an ACPI interface call when ACPI is fully implemented
- * for sn.
- */
- pm_power_off = ia64_sn_power_down;
- current->thread.flags |= IA64_THREAD_MIGRATION;
-}
-
-/**
- * sn_init_pdas - setup node data areas
- *
- * One time setup for Node Data Area. Called by sn_setup().
- */
-static void __init sn_init_pdas(char **cmdline_p)
-{
- cnodeid_t cnode;
-
- /*
- * Allocate & initialize the nodepda for each node.
- */
- for_each_online_node(cnode) {
- nodepdaindr[cnode] =
- memblock_alloc_node(sizeof(nodepda_t), SMP_CACHE_BYTES,
- cnode);
- if (!nodepdaindr[cnode])
- panic("%s: Failed to allocate %lu bytes align=0x%x nid=%d\n",
- __func__, sizeof(nodepda_t), SMP_CACHE_BYTES,
- cnode);
- memset(nodepdaindr[cnode]->phys_cpuid, -1,
- sizeof(nodepdaindr[cnode]->phys_cpuid));
- spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
- }
-
- /*
- * Allocate & initialize nodepda for TIOs. For now, put them on node 0.
- */
- for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
- nodepdaindr[cnode] =
- memblock_alloc_node(sizeof(nodepda_t), SMP_CACHE_BYTES, 0);
- if (!nodepdaindr[cnode])
- panic("%s: Failed to allocate %lu bytes align=0x%x nid=%d\n",
- __func__, sizeof(nodepda_t), SMP_CACHE_BYTES,
- cnode);
- }
-
-
- /*
- * Now copy the array of nodepda pointers to each nodepda.
- */
- for (cnode = 0; cnode < num_cnodes; cnode++)
- memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
- sizeof(nodepdaindr));
-
- /*
- * Set up IO related platform-dependent nodepda fields.
- * The following routine actually sets up the hubinfo struct
- * in nodepda.
- */
- for_each_online_node(cnode) {
- bte_init_node(nodepdaindr[cnode], cnode);
- }
-
- /*
- * Initialize the per node hubdev. This includes IO Nodes and
- * headless/memless nodes.
- */
- for (cnode = 0; cnode < num_cnodes; cnode++) {
- hubdev_init_node(nodepdaindr[cnode], cnode);
- }
-}
-
-/**
- * sn_cpu_init - initialize per-cpu data areas
- * @cpuid: cpuid of the caller
- *
- * Called during cpu initialization on each cpu as it starts.
- * Currently, initializes the per-cpu data area for SNIA.
- * Also sets up a few fields in the nodepda. Also known as
- * platform_cpu_init() by the ia64 machvec code.
- */
-void sn_cpu_init(void)
-{
- int cpuid;
- int cpuphyid;
- int nasid;
- int subnode;
- int slice;
- int cnode;
- int i;
- static int wars_have_been_checked, set_cpu0_number;
-
- cpuid = smp_processor_id();
- if (cpuid == 0 && IS_MEDUSA()) {
- if (ia64_sn_is_fake_prom())
- sn_prom_type = 2;
- else
- sn_prom_type = 1;
- printk(KERN_INFO "Running on medusa with %s PROM\n",
- (sn_prom_type == 1) ? "real" : "fake");
- }
-
- memset(pda, 0, sizeof(*pda));
- if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
- &sn_hub_info->nasid_bitmask,
- &sn_hub_info->nasid_shift,
- &sn_system_size, &sn_sharing_domain_size,
- &sn_partition_id, &sn_coherency_id,
- &sn_region_size))
- BUG();
- sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
-
- /*
- * Don't check status. The SAL call is not supported on all PROMs
- * but a failure is harmless.
- * Architecturally, cpu_init is always called twice on cpu 0. We
- * should set cpu_number on cpu 0 once.
- */
- if (cpuid == 0) {
- if (!set_cpu0_number) {
- (void) ia64_sn_set_cpu_number(cpuid);
- set_cpu0_number = 1;
- }
- } else
- (void) ia64_sn_set_cpu_number(cpuid);
-
- /*
- * The boot cpu makes this call again after platform initialization is
- * complete.
- */
- if (nodepdaindr[0] == NULL)
- return;
-
- for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)
- if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
- break;
-
- cpuphyid = get_sapicid();
-
- if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
- BUG();
-
- for (i=0; i < MAX_NUMNODES; i++) {
- if (nodepdaindr[i]) {
- nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid;
- nodepdaindr[i]->phys_cpuid[cpuid].slice = slice;
- nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode;
- }
- }
-
- cnode = nasid_to_cnodeid(nasid);
-
- __this_cpu_write(__sn_nodepda, nodepdaindr[cnode]);
-
- pda->led_address =
- (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
- pda->led_state = LED_ALWAYS_SET;
- pda->hb_count = HZ / 2;
- pda->hb_state = 0;
- pda->idle_flag = 0;
-
- if (cpuid != 0) {
- /* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */
- memcpy(sn_cnodeid_to_nasid,
- (&per_cpu(__sn_cnodeid_to_nasid, 0)),
- sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
- }
-
- /*
- * Check for WARs.
- * Only needs to be done once, on BSP.
- * Has to be done after loop above, because it uses this cpu's
- * sn_cnodeid_to_nasid table which was just initialized if this
- * isn't cpu 0.
- * Has to be done before assignment below.
- */
- if (!wars_have_been_checked) {
- sn_check_for_wars();
- wars_have_been_checked = 1;
- }
- sn_hub_info->shub_1_1_found = shub_1_1_found;
-
- /*
- * Set up addresses of PIO/MEM write status registers.
- */
- {
- u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
- u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2,
- SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
- u64 *pio;
- pio = is_shub1() ? pio1 : pio2;
- pda->pio_write_status_addr =
- (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
- pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
- }
-
- /*
- * WAR addresses for SHUB 1.x.
- */
- if (local_node_data->active_cpu_count++ == 0 && is_shub1()) {
- int buddy_nasid;
- buddy_nasid =
- cnodeid_to_nasid(numa_node_id() ==
- num_online_nodes() - 1 ? 0 : numa_node_id() + 1);
- pda->pio_shub_war_cam_addr =
- (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid,
- SH1_PI_CAM_CONTROL);
- }
-}
-
-/*
- * Build tables for converting between NASIDs and cnodes.
- */
-static inline int __init board_needs_cnode(int type)
-{
- return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
-}
-
-void __init build_cnode_tables(void)
-{
- int nasid;
- int node;
- lboard_t *brd;
-
- memset(physical_node_map, -1, sizeof(physical_node_map));
- memset(sn_cnodeid_to_nasid, -1,
- sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
-
- /*
- * First populate the tables with C/M bricks. This ensures that
- * cnode == node for all C & M bricks.
- */
- for_each_online_node(node) {
- nasid = pxm_to_nasid(node_to_pxm(node));
- sn_cnodeid_to_nasid[node] = nasid;
- physical_node_map[nasid] = node;
- }
-
- /*
- * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
- * limit on the number of nodes, we can't use the generic node numbers
- * for this. Note that num_cnodes is incremented below as TIOs or
- * headless/memoryless nodes are discovered.
- */
- num_cnodes = num_online_nodes();
-
- /* fakeprom does not support klgraph */
- if (IS_RUNNING_ON_FAKE_PROM())
- return;
-
- /* Find TIOs & headless/memoryless nodes and add them to the tables */
- for_each_online_node(node) {
- kl_config_hdr_t *klgraph_header;
- nasid = cnodeid_to_nasid(node);
- klgraph_header = ia64_sn_get_klconfig_addr(nasid);
- BUG_ON(klgraph_header == NULL);
- brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
- while (brd) {
- if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
- sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
- physical_node_map[brd->brd_nasid] = num_cnodes++;
- }
- brd = find_lboard_next(brd);
- }
- }
-}
-
-int
-nasid_slice_to_cpuid(int nasid, int slice)
-{
- long cpu;
-
- for (cpu = 0; cpu < nr_cpu_ids; cpu++)
- if (cpuid_to_nasid(cpu) == nasid &&
- cpuid_to_slice(cpu) == slice)
- return cpu;
-
- return -1;
-}
-
-int sn_prom_feature_available(int id)
-{
- if (id >= BITS_PER_LONG * MAX_PROM_FEATURE_SETS)
- return 0;
- return test_bit(id, sn_prom_features);
-}
-
-void
-sn_kernel_launch_event(void)
-{
- /* ignore status until we understand possible failure, if any*/
- if (ia64_sn_kernel_launch_event())
- printk(KERN_ERR "KEXEC is not supported in this PROM, Please update the PROM.\n");
-}
-EXPORT_SYMBOL(sn_prom_feature_available);
-
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
deleted file mode 100644
index 170bde4549da..000000000000
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# arch/ia64/sn/kernel/sn2/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) 1999,2001-2002 Silicon Graphics, Inc. All rights reserved.
-#
-# sn2 specific kernel files
-#
-
-obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
- prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c
deleted file mode 100644
index 2862cb33026d..000000000000
--- a/arch/ia64/sn/kernel/sn2/cache.c
+++ /dev/null
@@ -1,41 +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) 2001-2003, 2006 Silicon Graphics, Inc. All rights reserved.
- *
- */
-#include <linux/module.h>
-#include <asm/pgalloc.h>
-#include <asm/sn/arch.h>
-
-/**
- * sn_flush_all_caches - flush a range of address from all caches (incl. L4)
- * @flush_addr: identity mapped region 7 address to start flushing
- * @bytes: number of bytes to flush
- *
- * Flush a range of addresses from all caches including L4.
- * All addresses fully or partially contained within
- * @flush_addr to @flush_addr + @bytes are flushed
- * from all caches.
- */
-void
-sn_flush_all_caches(long flush_addr, long bytes)
-{
- unsigned long addr = flush_addr;
-
- /* SHub1 requires a cached address */
- if (is_shub1() && (addr & RGN_BITS) == RGN_BASE(RGN_UNCACHED))
- addr = (addr - RGN_BASE(RGN_UNCACHED)) + RGN_BASE(RGN_KERNEL);
-
- flush_icache_range(addr, addr + bytes);
- /*
- * The last call may have returned before the caches
- * were actually flushed, so we call it again to make
- * sure.
- */
- flush_icache_range(addr, addr + bytes);
- mb();
-}
-EXPORT_SYMBOL(sn_flush_all_caches);
diff --git a/arch/ia64/sn/kernel/sn2/io.c b/arch/ia64/sn/kernel/sn2/io.c
deleted file mode 100644
index a12c0586de38..000000000000
--- a/arch/ia64/sn/kernel/sn2/io.c
+++ /dev/null
@@ -1,101 +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) 2003 Silicon Graphics, Inc. All rights reserved.
- *
- * The generic kernel requires function pointers to these routines, so
- * we wrap the inlines from asm/ia64/sn/sn2/io.h here.
- */
-
-#include <asm/sn/io.h>
-
-#ifdef CONFIG_IA64_GENERIC
-
-#undef __sn_inb
-#undef __sn_inw
-#undef __sn_inl
-#undef __sn_outb
-#undef __sn_outw
-#undef __sn_outl
-#undef __sn_readb
-#undef __sn_readw
-#undef __sn_readl
-#undef __sn_readq
-#undef __sn_readb_relaxed
-#undef __sn_readw_relaxed
-#undef __sn_readl_relaxed
-#undef __sn_readq_relaxed
-
-unsigned int __sn_inb(unsigned long port)
-{
- return ___sn_inb(port);
-}
-
-unsigned int __sn_inw(unsigned long port)
-{
- return ___sn_inw(port);
-}
-
-unsigned int __sn_inl(unsigned long port)
-{
- return ___sn_inl(port);
-}
-
-void __sn_outb(unsigned char val, unsigned long port)
-{
- ___sn_outb(val, port);
-}
-
-void __sn_outw(unsigned short val, unsigned long port)
-{
- ___sn_outw(val, port);
-}
-
-void __sn_outl(unsigned int val, unsigned long port)
-{
- ___sn_outl(val, port);
-}
-
-unsigned char __sn_readb(void __iomem *addr)
-{
- return ___sn_readb(addr);
-}
-
-unsigned short __sn_readw(void __iomem *addr)
-{
- return ___sn_readw(addr);
-}
-
-unsigned int __sn_readl(void __iomem *addr)
-{
- return ___sn_readl(addr);
-}
-
-unsigned long __sn_readq(void __iomem *addr)
-{
- return ___sn_readq(addr);
-}
-
-unsigned char __sn_readb_relaxed(void __iomem *addr)
-{
- return ___sn_readb_relaxed(addr);
-}
-
-unsigned short __sn_readw_relaxed(void __iomem *addr)
-{
- return ___sn_readw_relaxed(addr);
-}
-
-unsigned int __sn_readl_relaxed(void __iomem *addr)
-{
- return ___sn_readl_relaxed(addr);
-}
-
-unsigned long __sn_readq_relaxed(void __iomem *addr)
-{
- return ___sn_readq_relaxed(addr);
-}
-
-#endif
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
deleted file mode 100644
index e15457bf21ac..000000000000
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+++ /dev/null
@@ -1,207 +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) 1999,2001-2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Module to export the system's Firmware Interface Tables, including
- * PROM revision numbers and banners, in /proc
- */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/nodemask.h>
-#include <asm/io.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/addrs.h>
-
-MODULE_DESCRIPTION("PROM version reporting for /proc");
-MODULE_AUTHOR("Chad Talbott");
-MODULE_LICENSE("GPL");
-
-/* Standard Intel FIT entry types */
-#define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */
-#define FIT_ENTRY_PAL_B 0x01 /* PAL_B entry */
-/* Entries 0x02 through 0x0D reserved by Intel */
-#define FIT_ENTRY_PAL_A_PROC 0x0E /* Processor-specific PAL_A entry */
-#define FIT_ENTRY_PAL_A 0x0F /* PAL_A entry, same as... */
-#define FIT_ENTRY_PAL_A_GEN 0x0F /* ...Generic PAL_A entry */
-#define FIT_ENTRY_UNUSED 0x7F /* Unused (reserved by Intel?) */
-/* OEM-defined entries range from 0x10 to 0x7E. */
-#define FIT_ENTRY_SAL_A 0x10 /* SAL_A entry */
-#define FIT_ENTRY_SAL_B 0x11 /* SAL_B entry */
-#define FIT_ENTRY_SALRUNTIME 0x12 /* SAL runtime entry */
-#define FIT_ENTRY_EFI 0x1F /* EFI entry */
-#define FIT_ENTRY_FPSWA 0x20 /* embedded fpswa entry */
-#define FIT_ENTRY_VMLINUX 0x21 /* embedded vmlinux entry */
-
-#define FIT_MAJOR_SHIFT (32 + 8)
-#define FIT_MAJOR_MASK ((1 << 8) - 1)
-#define FIT_MINOR_SHIFT 32
-#define FIT_MINOR_MASK ((1 << 8) - 1)
-
-#define FIT_MAJOR(q) \
- ((unsigned) ((q) >> FIT_MAJOR_SHIFT) & FIT_MAJOR_MASK)
-#define FIT_MINOR(q) \
- ((unsigned) ((q) >> FIT_MINOR_SHIFT) & FIT_MINOR_MASK)
-
-#define FIT_TYPE_SHIFT (32 + 16)
-#define FIT_TYPE_MASK ((1 << 7) - 1)
-
-#define FIT_TYPE(q) \
- ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
-
-struct fit_type_map_t {
- unsigned char type;
- const char *name;
-};
-
-static const struct fit_type_map_t fit_entry_types[] = {
- {FIT_ENTRY_FIT_HEADER, "FIT Header"},
- {FIT_ENTRY_PAL_A_GEN, "Generic PAL_A"},
- {FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A"},
- {FIT_ENTRY_PAL_A, "PAL_A"},
- {FIT_ENTRY_PAL_B, "PAL_B"},
- {FIT_ENTRY_SAL_A, "SAL_A"},
- {FIT_ENTRY_SAL_B, "SAL_B"},
- {FIT_ENTRY_SALRUNTIME, "SAL runtime"},
- {FIT_ENTRY_EFI, "EFI"},
- {FIT_ENTRY_VMLINUX, "Embedded Linux"},
- {FIT_ENTRY_FPSWA, "Embedded FPSWA"},
- {FIT_ENTRY_UNUSED, "Unused"},
- {0xff, "Error"},
-};
-
-static const char *fit_type_name(unsigned char type)
-{
- struct fit_type_map_t const *mapp;
-
- for (mapp = fit_entry_types; mapp->type != 0xff; mapp++)
- if (type == mapp->type)
- return mapp->name;
-
- if ((type > FIT_ENTRY_PAL_A) && (type < FIT_ENTRY_UNUSED))
- return "OEM type";
- if ((type > FIT_ENTRY_PAL_B) && (type < FIT_ENTRY_PAL_A))
- return "Reserved";
-
- return "Unknown type";
-}
-
-static int
-get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
- char *banner, int banlen)
-{
- return ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
-}
-
-
-/*
- * These two routines display the FIT table for each node.
- */
-static void dump_fit_entry(struct seq_file *m, unsigned long *fentry)
-{
- unsigned type;
-
- type = FIT_TYPE(fentry[1]);
- seq_printf(m, "%02x %-25s %x.%02x %016lx %u\n",
- type,
- fit_type_name(type),
- FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
- fentry[0],
- /* mult by sixteen to get size in bytes */
- (unsigned)(fentry[1] & 0xffffff) * 16);
-}
-
-
-/*
- * We assume that the fit table will be small enough that we can print
- * the whole thing into one page. (This is true for our default 16kB
- * pages -- each entry is about 60 chars wide when printed.) I read
- * somewhere that the maximum size of the FIT is 128 entries, so we're
- * OK except for 4kB pages (and no one is going to do that on SN
- * anyway).
- */
-static int proc_fit_show(struct seq_file *m, void *v)
-{
- unsigned long nasid = (unsigned long)m->private;
- unsigned long fentry[2];
- int index;
-
- for (index=0;;index++) {
- BUG_ON(index * 60 > PAGE_SIZE);
- if (get_fit_entry(nasid, index, fentry, NULL, 0))
- break;
- dump_fit_entry(m, fentry);
- }
- return 0;
-}
-
-static int proc_version_show(struct seq_file *m, void *v)
-{
- unsigned long nasid = (unsigned long)m->private;
- unsigned long fentry[2];
- char banner[128];
- int index;
-
- for (index = 0; ; index++) {
- if (get_fit_entry(nasid, index, fentry, banner,
- sizeof(banner)))
- return 0;
- if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
- break;
- }
-
- seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]));
-
- if (banner[0])
- seq_printf(m, "%s\n", banner);
- return 0;
-}
-
-/* module entry points */
-int __init prominfo_init(void);
-void __exit prominfo_exit(void);
-
-module_init(prominfo_init);
-module_exit(prominfo_exit);
-
-#define NODE_NAME_LEN 11
-
-int __init prominfo_init(void)
-{
- struct proc_dir_entry *sgi_prominfo_entry;
- cnodeid_t cnodeid;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
- if (!sgi_prominfo_entry)
- return -ENOMEM;
-
- for_each_online_node(cnodeid) {
- struct proc_dir_entry *dir;
- unsigned long nasid;
- char name[NODE_NAME_LEN];
-
- sprintf(name, "node%d", cnodeid);
- dir = proc_mkdir(name, sgi_prominfo_entry);
- if (!dir)
- continue;
- nasid = cnodeid_to_nasid(cnodeid);
- proc_create_single_data("fit", 0, dir, proc_fit_show,
- (void *)nasid);
- proc_create_single_data("version", 0, dir, proc_version_show,
- (void *)nasid);
- }
- return 0;
-}
-
-void __exit prominfo_exit(void)
-{
- remove_proc_subtree("sgi_prominfo", NULL);
-}
diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
deleted file mode 100644
index bebbcc4f8dd4..000000000000
--- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
+++ /dev/null
@@ -1,92 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <asm/types.h>
-#include <asm/sn/shub_mmr.h>
-
-#define DEADLOCKBIT SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT
-#define WRITECOUNTMASK SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
-#define ALIAS_OFFSET 8
-
-
- .global sn2_ptc_deadlock_recovery_core
- .proc sn2_ptc_deadlock_recovery_core
-
-sn2_ptc_deadlock_recovery_core:
- .regstk 6,0,0,0
-
- ptc0 = in0
- data0 = in1
- ptc1 = in2
- data1 = in3
- piowc = in4
- zeroval = in5
- piowcphy = r30
- psrsave = r2
- scr1 = r16
- scr2 = r17
- mask = r18
-
-
- extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address
- dep piowcphy=-1,piowcphy,63,1
- movl mask=WRITECOUNTMASK
- mov r8=r0
-
-1:
- cmp.ne p8,p9=r0,ptc1 // Test for shub type (ptc1 non-null on shub1)
- // p8 = 1 if shub1, p9 = 1 if shub2
-
- add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register
- mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR
-(p8) st8.rel [scr2]=scr1;;
-(p9) ld8.acq scr1=[scr2];;
-
-5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete.
- hint @pause
- and scr2=scr1,mask;; // mask of writecount bits
- cmp.ne p6,p0=zeroval,scr2
-(p6) br.cond.sptk 5b
-
-
-
- ////////////// BEGIN PHYSICAL MODE ////////////////////
- mov psrsave=psr // Disable IC (no PMIs)
- rsm psr.i | psr.dt | psr.ic;;
- srlz.i;;
-
- st8.rel [ptc0]=data0 // Write PTC0 & wait for completion.
-
-5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
- hint @pause
- and scr2=scr1,mask;; // mask of writecount bits
- cmp.ne p6,p0=zeroval,scr2
-(p6) br.cond.sptk 5b;;
-
- tbit.nz p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK
-(p7) cmp.ne p7,p0=r0,ptc1;; // Test for non-null ptc1
-
-(p7) st8.rel [ptc1]=data1;; // Now write PTC1.
-
-5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
- hint @pause
- and scr2=scr1,mask;; // mask of writecount bits
- cmp.ne p6,p0=zeroval,scr2
-(p6) br.cond.sptk 5b
-
- tbit.nz p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK
-
- mov psr.l=psrsave;; // Reenable IC
- srlz.i;;
- ////////////// END PHYSICAL MODE ////////////////////
-
-(p8) add r8=1,r8
-(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred.
-
- br.ret.sptk rp
- .endp sn2_ptc_deadlock_recovery_core
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
deleted file mode 100644
index b510f4f17fd4..000000000000
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * SN2 Platform specific SMP Support
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/mm_types.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mmzone.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/nodemask.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/sal.h>
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/tlb.h>
-#include <asm/numa.h>
-#include <asm/hw_irq.h>
-#include <asm/current.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/rw_mmr.h>
-#include <asm/sn/sn_feature_sets.h>
-
-DEFINE_PER_CPU(struct ptc_stats, ptcstats);
-DECLARE_PER_CPU(struct ptc_stats, ptcstats);
-
-static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
-
-/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */
-static int sn2_flush_opt = 0;
-
-extern unsigned long
-sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
- volatile unsigned long *, unsigned long,
- volatile unsigned long *, unsigned long);
-void
-sn2_ptc_deadlock_recovery(nodemask_t, short, short, int,
- volatile unsigned long *, unsigned long,
- volatile unsigned long *, unsigned long);
-
-/*
- * Note: some is the following is captured here to make degugging easier
- * (the macros make more sense if you see the debug patch - not posted)
- */
-#define sn2_ptctest 0
-#define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0)
-#define max_active_pio(sh1) ((sh1) ? 32 : 7)
-#define reset_max_active_on_deadlock() 1
-#define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock)
-
-struct ptc_stats {
- unsigned long ptc_l;
- unsigned long change_rid;
- unsigned long shub_ptc_flushes;
- unsigned long nodes_flushed;
- unsigned long deadlocks;
- unsigned long deadlocks2;
- unsigned long lock_itc_clocks;
- unsigned long shub_itc_clocks;
- unsigned long shub_itc_clocks_max;
- unsigned long shub_ptc_flushes_not_my_mm;
- unsigned long shub_ipi_flushes;
- unsigned long shub_ipi_flushes_itc_clocks;
-};
-
-#define sn2_ptctest 0
-
-static inline unsigned long wait_piowc(void)
-{
- volatile unsigned long *piows;
- unsigned long zeroval, ws;
-
- piows = pda->pio_write_status_addr;
- zeroval = pda->pio_write_status_val;
- do {
- cpu_relax();
- } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval);
- return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
-}
-
-/**
- * sn_migrate - SN-specific task migration actions
- * @task: Task being migrated to new CPU
- *
- * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
- * Context switching user threads which have memory-mapped MMIO may cause
- * PIOs to issue from separate CPUs, thus the PIO writes must be drained
- * from the previous CPU's Shub before execution resumes on the new CPU.
- */
-void sn_migrate(struct task_struct *task)
-{
- pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
- volatile unsigned long *adr = last_pda->pio_write_status_addr;
- unsigned long val = last_pda->pio_write_status_val;
-
- /* Drain PIO writes from old CPU's Shub */
- while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
- != val))
- cpu_relax();
-}
-
-static void
-sn2_ipi_flush_all_tlb(struct mm_struct *mm)
-{
- unsigned long itc;
-
- itc = ia64_get_itc();
- smp_flush_tlb_cpumask(*mm_cpumask(mm));
- itc = ia64_get_itc() - itc;
- __this_cpu_add(ptcstats.shub_ipi_flushes_itc_clocks, itc);
- __this_cpu_inc(ptcstats.shub_ipi_flushes);
-}
-
-/**
- * sn2_global_tlb_purge - globally purge translation cache of virtual address range
- * @mm: mm_struct containing virtual address range
- * @start: start of virtual address range
- * @end: end of virtual address range
- * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
- *
- * Purges the translation caches of all processors of the given virtual address
- * range.
- *
- * Note:
- * - cpu_vm_mask is a bit mask that indicates which cpus have loaded the context.
- * - cpu_vm_mask is converted into a nodemask of the nodes containing the
- * cpus in cpu_vm_mask.
- * - if only one bit is set in cpu_vm_mask & it is the current cpu & the
- * process is purging its own virtual address range, then only the
- * local TLB needs to be flushed. This flushing can be done using
- * ptc.l. This is the common case & avoids the global spinlock.
- * - if multiple cpus have loaded the context, then flushing has to be
- * done with ptc.g/MMRs under protection of the global ptc_lock.
- */
-
-void
-sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned long nbits)
-{
- int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid;
- int mymm = (mm == current->active_mm && mm == current->mm);
- int use_cpu_ptcga;
- volatile unsigned long *ptc0, *ptc1;
- unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
- short nix;
- nodemask_t nodes_flushed;
- int active, max_active, deadlock, flush_opt = sn2_flush_opt;
-
- if (flush_opt > 2) {
- sn2_ipi_flush_all_tlb(mm);
- return;
- }
-
- nodes_clear(nodes_flushed);
- i = 0;
-
- for_each_cpu(cpu, mm_cpumask(mm)) {
- cnode = cpu_to_node(cpu);
- node_set(cnode, nodes_flushed);
- lcpu = cpu;
- i++;
- }
-
- if (i == 0)
- return;
-
- preempt_disable();
-
- if (likely(i == 1 && lcpu == smp_processor_id() && mymm)) {
- do {
- ia64_ptcl(start, nbits << 2);
- start += (1UL << nbits);
- } while (start < end);
- ia64_srlz_i();
- __this_cpu_inc(ptcstats.ptc_l);
- preempt_enable();
- return;
- }
-
- if (atomic_read(&mm->mm_users) == 1 && mymm) {
- flush_tlb_mm(mm);
- __this_cpu_inc(ptcstats.change_rid);
- preempt_enable();
- return;
- }
-
- if (flush_opt == 2) {
- sn2_ipi_flush_all_tlb(mm);
- preempt_enable();
- return;
- }
-
- itc = ia64_get_itc();
- nix = nodes_weight(nodes_flushed);
-
- rr_value = (mm->context << 3) | REGION_NUMBER(start);
-
- shub1 = is_shub1();
- if (shub1) {
- data0 = (1UL << SH1_PTC_0_A_SHFT) |
- (nbits << SH1_PTC_0_PS_SHFT) |
- (rr_value << SH1_PTC_0_RID_SHFT) |
- (1UL << SH1_PTC_0_START_SHFT);
- ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
- ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
- } else {
- data0 = (1UL << SH2_PTC_A_SHFT) |
- (nbits << SH2_PTC_PS_SHFT) |
- (1UL << SH2_PTC_START_SHFT);
- ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC +
- (rr_value << SH2_PTC_RID_SHFT));
- ptc1 = NULL;
- }
-
-
- mynasid = get_nasid();
- use_cpu_ptcga = local_node_uses_ptc_ga(shub1);
- max_active = max_active_pio(shub1);
-
- itc = ia64_get_itc();
- spin_lock_irqsave(PTC_LOCK(shub1), flags);
- itc2 = ia64_get_itc();
-
- __this_cpu_add(ptcstats.lock_itc_clocks, itc2 - itc);
- __this_cpu_inc(ptcstats.shub_ptc_flushes);
- __this_cpu_add(ptcstats.nodes_flushed, nix);
- if (!mymm)
- __this_cpu_inc(ptcstats.shub_ptc_flushes_not_my_mm);
-
- if (use_cpu_ptcga && !mymm) {
- old_rr = ia64_get_rr(start);
- ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8));
- ia64_srlz_d();
- }
-
- wait_piowc();
- do {
- if (shub1)
- data1 = start | (1UL << SH1_PTC_1_START_SHFT);
- else
- data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
- deadlock = 0;
- active = 0;
- ibegin = 0;
- i = 0;
- for_each_node_mask(cnode, nodes_flushed) {
- nasid = cnodeid_to_nasid(cnode);
- if (use_cpu_ptcga && unlikely(nasid == mynasid)) {
- ia64_ptcga(start, nbits << 2);
- ia64_srlz_i();
- } else {
- ptc0 = CHANGE_NASID(nasid, ptc0);
- if (ptc1)
- ptc1 = CHANGE_NASID(nasid, ptc1);
- pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
- active++;
- }
- if (active >= max_active || i == (nix - 1)) {
- if ((deadlock = wait_piowc())) {
- if (flush_opt == 1)
- goto done;
- sn2_ptc_deadlock_recovery(nodes_flushed, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
- if (reset_max_active_on_deadlock())
- max_active = 1;
- }
- active = 0;
- ibegin = i + 1;
- }
- i++;
- }
- start += (1UL << nbits);
- } while (start < end);
-
-done:
- itc2 = ia64_get_itc() - itc2;
- __this_cpu_add(ptcstats.shub_itc_clocks, itc2);
- if (itc2 > __this_cpu_read(ptcstats.shub_itc_clocks_max))
- __this_cpu_write(ptcstats.shub_itc_clocks_max, itc2);
-
- if (old_rr) {
- ia64_set_rr(start, old_rr);
- ia64_srlz_d();
- }
-
- spin_unlock_irqrestore(PTC_LOCK(shub1), flags);
-
- if (flush_opt == 1 && deadlock) {
- __this_cpu_inc(ptcstats.deadlocks);
- sn2_ipi_flush_all_tlb(mm);
- }
-
- preempt_enable();
-}
-
-/*
- * sn2_ptc_deadlock_recovery
- *
- * Recover from PTC deadlocks conditions. Recovery requires stepping thru each
- * TLB flush transaction. The recovery sequence is somewhat tricky & is
- * coded in assembly language.
- */
-
-void
-sn2_ptc_deadlock_recovery(nodemask_t nodes, short ib, short ie, int mynasid,
- volatile unsigned long *ptc0, unsigned long data0,
- volatile unsigned long *ptc1, unsigned long data1)
-{
- short nasid, i;
- int cnode;
- unsigned long *piows, zeroval, n;
-
- __this_cpu_inc(ptcstats.deadlocks);
-
- piows = (unsigned long *) pda->pio_write_status_addr;
- zeroval = pda->pio_write_status_val;
-
- i = 0;
- for_each_node_mask(cnode, nodes) {
- if (i < ib)
- goto next;
-
- if (i > ie)
- break;
-
- nasid = cnodeid_to_nasid(cnode);
- if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)
- goto next;
-
- ptc0 = CHANGE_NASID(nasid, ptc0);
- if (ptc1)
- ptc1 = CHANGE_NASID(nasid, ptc1);
-
- n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
- __this_cpu_add(ptcstats.deadlocks2, n);
-next:
- i++;
- }
-
-}
-
-/**
- * sn_send_IPI_phys - send an IPI to a Nasid and slice
- * @nasid: nasid to receive the interrupt (may be outside partition)
- * @physid: physical cpuid to receive the interrupt.
- * @vector: command to send
- * @delivery_mode: delivery mechanism
- *
- * Sends an IPI (interprocessor interrupt) to the processor specified by
- * @physid
- *
- * @delivery_mode can be one of the following
- *
- * %IA64_IPI_DM_INT - pend an interrupt
- * %IA64_IPI_DM_PMI - pend a PMI
- * %IA64_IPI_DM_NMI - pend an NMI
- * %IA64_IPI_DM_INIT - pend an INIT interrupt
- */
-void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode)
-{
- long val;
- unsigned long flags = 0;
- volatile long *p;
-
- p = (long *)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT);
- val = (1UL << SH_IPI_INT_SEND_SHFT) |
- (physid << SH_IPI_INT_PID_SHFT) |
- ((long)delivery_mode << SH_IPI_INT_TYPE_SHFT) |
- ((long)vector << SH_IPI_INT_IDX_SHFT) |
- (0x000feeUL << SH_IPI_INT_BASE_SHFT);
-
- mb();
- if (enable_shub_wars_1_1()) {
- spin_lock_irqsave(&sn2_global_ptc_lock, flags);
- }
- pio_phys_write_mmr(p, val);
- if (enable_shub_wars_1_1()) {
- wait_piowc();
- spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
- }
-
-}
-
-EXPORT_SYMBOL(sn_send_IPI_phys);
-
-/**
- * sn2_send_IPI - send an IPI to a processor
- * @cpuid: target of the IPI
- * @vector: command to send
- * @delivery_mode: delivery mechanism
- * @redirect: redirect the IPI?
- *
- * Sends an IPI (InterProcessor Interrupt) to the processor specified by
- * @cpuid. @vector specifies the command to send, while @delivery_mode can
- * be one of the following
- *
- * %IA64_IPI_DM_INT - pend an interrupt
- * %IA64_IPI_DM_PMI - pend a PMI
- * %IA64_IPI_DM_NMI - pend an NMI
- * %IA64_IPI_DM_INIT - pend an INIT interrupt
- */
-void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
-{
- long physid;
- int nasid;
-
- physid = cpu_physical_id(cpuid);
- nasid = cpuid_to_nasid(cpuid);
-
- /* the following is used only when starting cpus at boot time */
- if (unlikely(nasid == -1))
- ia64_sn_get_sapic_info(physid, &nasid, NULL, NULL);
-
- sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/**
- * sn_cpu_disable_allowed - Determine if a CPU can be disabled.
- * @cpu - CPU that is requested to be disabled.
- *
- * CPU disable is only allowed on SHub2 systems running with a PROM
- * that supports CPU disable. It is not permitted to disable the boot processor.
- */
-bool sn_cpu_disable_allowed(int cpu)
-{
- if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) {
- if (cpu != 0)
- return true;
- else
- printk(KERN_WARNING
- "Disabling the boot processor is not allowed.\n");
-
- } else
- printk(KERN_WARNING
- "CPU disable is not supported on this system.\n");
-
- return false;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-#ifdef CONFIG_PROC_FS
-
-#define PTC_BASENAME "sgi_sn/ptc_statistics"
-
-static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset)
-{
- if (*offset < nr_cpu_ids)
- return offset;
- return NULL;
-}
-
-static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset)
-{
- (*offset)++;
- if (*offset < nr_cpu_ids)
- return offset;
- return NULL;
-}
-
-static void sn2_ptc_seq_stop(struct seq_file *file, void *data)
-{
-}
-
-static int sn2_ptc_seq_show(struct seq_file *file, void *data)
-{
- struct ptc_stats *stat;
- int cpu;
-
- cpu = *(loff_t *) data;
-
- if (!cpu) {
- seq_printf(file,
- "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n");
- seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt);
- }
-
- if (cpu < nr_cpu_ids && cpu_online(cpu)) {
- stat = &per_cpu(ptcstats, cpu);
- seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
- stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
- stat->deadlocks,
- 1000 * stat->lock_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
- 1000 * stat->shub_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
- 1000 * stat->shub_itc_clocks_max / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
- stat->shub_ptc_flushes_not_my_mm,
- stat->deadlocks2,
- stat->shub_ipi_flushes,
- 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec);
- }
- return 0;
-}
-
-static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data)
-{
- int cpu;
- char optstr[64];
-
- if (count == 0 || count > sizeof(optstr))
- return -EINVAL;
- if (copy_from_user(optstr, user, count))
- return -EFAULT;
- optstr[count - 1] = '\0';
- sn2_flush_opt = simple_strtoul(optstr, NULL, 0);
-
- for_each_online_cpu(cpu)
- memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats));
-
- return count;
-}
-
-static const struct seq_operations sn2_ptc_seq_ops = {
- .start = sn2_ptc_seq_start,
- .next = sn2_ptc_seq_next,
- .stop = sn2_ptc_seq_stop,
- .show = sn2_ptc_seq_show
-};
-
-static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &sn2_ptc_seq_ops);
-}
-
-static const struct file_operations proc_sn2_ptc_operations = {
- .open = sn2_ptc_proc_open,
- .read = seq_read,
- .write = sn2_ptc_proc_write,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static struct proc_dir_entry *proc_sn2_ptc;
-
-static int __init sn2_ptc_init(void)
-{
- if (!ia64_platform_is("sn2"))
- return 0;
-
- proc_sn2_ptc = proc_create(PTC_BASENAME, 0444,
- NULL, &proc_sn2_ptc_operations);
- if (!proc_sn2_ptc) {
- printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
- return -EINVAL;
- }
- spin_lock_init(&sn2_global_ptc_lock);
- return 0;
-}
-
-static void __exit sn2_ptc_exit(void)
-{
- remove_proc_entry(PTC_BASENAME, NULL);
-}
-
-module_init(sn2_ptc_init);
-module_exit(sn2_ptc_exit);
-#endif /* CONFIG_PROC_FS */
-
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
deleted file mode 100644
index 55febd65911a..000000000000
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ /dev/null
@@ -1,1004 +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) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- *
- * SGI Altix topology and hardware performance monitoring API.
- * Mark Goodwin <markgw@sgi.com>.
- *
- * Creates /proc/sgi_sn/sn_topology (read-only) to export
- * info about Altix nodes, routers, CPUs and NumaLink
- * interconnection/topology.
- *
- * Also creates a dynamic misc device named "sn_hwperf"
- * that supports an ioctl interface to call down into SAL
- * to discover hw objects, topology and to read/write
- * memory mapped registers, e.g. for performance monitoring.
- * The "sn_hwperf" device is registered only after the procfs
- * file is first opened, i.e. only if/when it's needed.
- *
- * This API is used by SGI Performance Co-Pilot and other
- * tools, see http://oss.sgi.com/projects/pcp
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/vmalloc.h>
-#include <linux/seq_file.h>
-#include <linux/miscdevice.h>
-#include <linux/utsname.h>
-#include <linux/cpumask.h>
-#include <linux/nodemask.h>
-#include <linux/smp.h>
-#include <linux/mutex.h>
-
-#include <asm/processor.h>
-#include <asm/topology.h>
-#include <linux/uaccess.h>
-#include <asm/sal.h>
-#include <asm/sn/io.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/module.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/sn2/sn_hwperf.h>
-#include <asm/sn/addrs.h>
-
-static void *sn_hwperf_salheap = NULL;
-static int sn_hwperf_obj_cnt = 0;
-static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
-static int sn_hwperf_init(void);
-static DEFINE_MUTEX(sn_hwperf_init_mutex);
-
-#define cnode_possible(n) ((n) < num_cnodes)
-
-static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
-{
- int e;
- u64 sz;
- struct sn_hwperf_object_info *objbuf = NULL;
-
- if ((e = sn_hwperf_init()) < 0) {
- printk(KERN_ERR "sn_hwperf_init failed: err %d\n", e);
- goto out;
- }
-
- sz = sn_hwperf_obj_cnt * sizeof(struct sn_hwperf_object_info);
- objbuf = vmalloc(sz);
- if (objbuf == NULL) {
- printk("sn_hwperf_enum_objects: vmalloc(%d) failed\n", (int)sz);
- e = -ENOMEM;
- goto out;
- }
-
- e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_OBJECTS,
- 0, sz, (u64) objbuf, 0, 0, NULL);
- if (e != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- vfree(objbuf);
- }
-
-out:
- *nobj = sn_hwperf_obj_cnt;
- *ret = objbuf;
- return e;
-}
-
-static int sn_hwperf_location_to_bpos(char *location,
- int *rack, int *bay, int *slot, int *slab)
-{
- char type;
-
- /* first scan for an old style geoid string */
- if (sscanf(location, "%03d%c%02d#%d",
- rack, &type, bay, slab) == 4)
- *slot = 0;
- else /* scan for a new bladed geoid string */
- if (sscanf(location, "%03d%c%02d^%02d#%d",
- rack, &type, bay, slot, slab) != 5)
- return -1;
- /* success */
- return 0;
-}
-
-static int sn_hwperf_geoid_to_cnode(char *location)
-{
- int cnode;
- geoid_t geoid;
- moduleid_t module_id;
- int rack, bay, slot, slab;
- int this_rack, this_bay, this_slot, this_slab;
-
- if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
- return -1;
-
- /*
- * FIXME: replace with cleaner for_each_XXX macro which addresses
- * both compute and IO nodes once ACPI3.0 is available.
- */
- for (cnode = 0; cnode < num_cnodes; cnode++) {
- geoid = cnodeid_get_geoid(cnode);
- module_id = geo_module(geoid);
- this_rack = MODULE_GET_RACK(module_id);
- this_bay = MODULE_GET_BPOS(module_id);
- this_slot = geo_slot(geoid);
- this_slab = geo_slab(geoid);
- if (rack == this_rack && bay == this_bay &&
- slot == this_slot && slab == this_slab) {
- break;
- }
- }
-
- return cnode_possible(cnode) ? cnode : -1;
-}
-
-static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
-{
- if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
- BUG();
- if (SN_HWPERF_FOREIGN(obj))
- return -1;
- return sn_hwperf_geoid_to_cnode(obj->location);
-}
-
-static int sn_hwperf_generic_ordinal(struct sn_hwperf_object_info *obj,
- struct sn_hwperf_object_info *objs)
-{
- int ordinal;
- struct sn_hwperf_object_info *p;
-
- for (ordinal=0, p=objs; p != obj; p++) {
- if (SN_HWPERF_FOREIGN(p))
- continue;
- if (SN_HWPERF_SAME_OBJTYPE(p, obj))
- ordinal++;
- }
-
- return ordinal;
-}
-
-static const char *slabname_node = "node"; /* SHub asic */
-static const char *slabname_ionode = "ionode"; /* TIO asic */
-static const char *slabname_router = "router"; /* NL3R or NL4R */
-static const char *slabname_other = "other"; /* unknown asic */
-
-static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
- struct sn_hwperf_object_info *objs, int *ordinal)
-{
- int isnode;
- const char *slabname = slabname_other;
-
- if ((isnode = SN_HWPERF_IS_NODE(obj)) || SN_HWPERF_IS_IONODE(obj)) {
- slabname = isnode ? slabname_node : slabname_ionode;
- *ordinal = sn_hwperf_obj_to_cnode(obj);
- }
- else {
- *ordinal = sn_hwperf_generic_ordinal(obj, objs);
- if (SN_HWPERF_IS_ROUTER(obj))
- slabname = slabname_router;
- }
-
- return slabname;
-}
-
-static void print_pci_topology(struct seq_file *s)
-{
- char *p;
- size_t sz;
- int e;
-
- for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
- if (!(p = kmalloc(sz, GFP_KERNEL)))
- break;
- e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
- if (e == SALRET_OK)
- seq_puts(s, p);
- kfree(p);
- if (e == SALRET_OK || e == SALRET_NOT_IMPLEMENTED)
- break;
- }
-}
-
-static inline int sn_hwperf_has_cpus(cnodeid_t node)
-{
- return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node);
-}
-
-static inline int sn_hwperf_has_mem(cnodeid_t node)
-{
- return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages;
-}
-
-static struct sn_hwperf_object_info *
-sn_hwperf_findobj_id(struct sn_hwperf_object_info *objbuf,
- int nobj, int id)
-{
- int i;
- struct sn_hwperf_object_info *p = objbuf;
-
- for (i=0; i < nobj; i++, p++) {
- if (p->id == id)
- return p;
- }
-
- return NULL;
-
-}
-
-static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objbuf,
- int nobj, cnodeid_t node, cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
-{
- int e;
- struct sn_hwperf_object_info *nodeobj = NULL;
- struct sn_hwperf_object_info *op;
- struct sn_hwperf_object_info *dest;
- struct sn_hwperf_object_info *router;
- struct sn_hwperf_port_info ptdata[16];
- int sz, i, j;
- cnodeid_t c;
- int found_mem = 0;
- int found_cpu = 0;
-
- if (!cnode_possible(node))
- return -EINVAL;
-
- if (sn_hwperf_has_cpus(node)) {
- if (near_cpu_node)
- *near_cpu_node = node;
- found_cpu++;
- }
-
- if (sn_hwperf_has_mem(node)) {
- if (near_mem_node)
- *near_mem_node = node;
- found_mem++;
- }
-
- if (found_cpu && found_mem)
- return 0; /* trivially successful */
-
- /* find the argument node object */
- for (i=0, op=objbuf; i < nobj; i++, op++) {
- if (!SN_HWPERF_IS_NODE(op) && !SN_HWPERF_IS_IONODE(op))
- continue;
- if (node == sn_hwperf_obj_to_cnode(op)) {
- nodeobj = op;
- break;
- }
- }
- if (!nodeobj) {
- e = -ENOENT;
- goto err;
- }
-
- /* get it's interconnect topology */
- sz = op->ports * sizeof(struct sn_hwperf_port_info);
- BUG_ON(sz > sizeof(ptdata));
- e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- SN_HWPERF_ENUM_PORTS, nodeobj->id, sz,
- (u64)&ptdata, 0, 0, NULL);
- if (e != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- goto err;
- }
-
- /* find nearest node with cpus and nearest memory */
- for (router=NULL, j=0; j < op->ports; j++) {
- dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id);
- if (dest && SN_HWPERF_IS_ROUTER(dest))
- router = dest;
- if (!dest || SN_HWPERF_FOREIGN(dest) ||
- !SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
- continue;
- }
- c = sn_hwperf_obj_to_cnode(dest);
- if (!found_cpu && sn_hwperf_has_cpus(c)) {
- if (near_cpu_node)
- *near_cpu_node = c;
- found_cpu++;
- }
- if (!found_mem && sn_hwperf_has_mem(c)) {
- if (near_mem_node)
- *near_mem_node = c;
- found_mem++;
- }
- }
-
- if (router && (!found_cpu || !found_mem)) {
- /* search for a node connected to the same router */
- sz = router->ports * sizeof(struct sn_hwperf_port_info);
- BUG_ON(sz > sizeof(ptdata));
- e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- SN_HWPERF_ENUM_PORTS, router->id, sz,
- (u64)&ptdata, 0, 0, NULL);
- if (e != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- goto err;
- }
- for (j=0; j < router->ports; j++) {
- dest = sn_hwperf_findobj_id(objbuf, nobj,
- ptdata[j].conn_id);
- if (!dest || dest->id == node ||
- SN_HWPERF_FOREIGN(dest) ||
- !SN_HWPERF_IS_NODE(dest) ||
- SN_HWPERF_IS_IONODE(dest)) {
- continue;
- }
- c = sn_hwperf_obj_to_cnode(dest);
- if (!found_cpu && sn_hwperf_has_cpus(c)) {
- if (near_cpu_node)
- *near_cpu_node = c;
- found_cpu++;
- }
- if (!found_mem && sn_hwperf_has_mem(c)) {
- if (near_mem_node)
- *near_mem_node = c;
- found_mem++;
- }
- if (found_cpu && found_mem)
- break;
- }
- }
-
- if (!found_cpu || !found_mem) {
- /* resort to _any_ node with CPUs and memory */
- for (i=0, op=objbuf; i < nobj; i++, op++) {
- if (SN_HWPERF_FOREIGN(op) ||
- SN_HWPERF_IS_IONODE(op) ||
- !SN_HWPERF_IS_NODE(op)) {
- continue;
- }
- c = sn_hwperf_obj_to_cnode(op);
- if (!found_cpu && sn_hwperf_has_cpus(c)) {
- if (near_cpu_node)
- *near_cpu_node = c;
- found_cpu++;
- }
- if (!found_mem && sn_hwperf_has_mem(c)) {
- if (near_mem_node)
- *near_mem_node = c;
- found_mem++;
- }
- if (found_cpu && found_mem)
- break;
- }
- }
-
- if (!found_cpu || !found_mem)
- e = -ENODATA;
-
-err:
- return e;
-}
-
-
-static int sn_topology_show(struct seq_file *s, void *d)
-{
- int sz;
- int pt;
- int e = 0;
- int i;
- int j;
- const char *slabname;
- int ordinal;
- char slice;
- struct cpuinfo_ia64 *c;
- struct sn_hwperf_port_info *ptdata;
- struct sn_hwperf_object_info *p;
- struct sn_hwperf_object_info *obj = d; /* this object */
- struct sn_hwperf_object_info *objs = s->private; /* all objects */
- u8 shubtype;
- u8 system_size;
- u8 sharing_size;
- u8 partid;
- u8 coher;
- u8 nasid_shift;
- u8 region_size;
- u16 nasid_mask;
- int nasid_msb;
-
- if (obj == objs) {
- seq_printf(s, "# sn_topology version 2\n");
- seq_printf(s, "# objtype ordinal location partition"
- " [attribute value [, ...]]\n");
-
- if (ia64_sn_get_sn_info(0,
- &shubtype, &nasid_mask, &nasid_shift, &system_size,
- &sharing_size, &partid, &coher, &region_size))
- BUG();
- for (nasid_msb=63; nasid_msb > 0; nasid_msb--) {
- if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb))
- break;
- }
- seq_printf(s, "partition %u %s local "
- "shubtype %s, "
- "nasid_mask 0x%016llx, "
- "nasid_bits %d:%d, "
- "system_size %d, "
- "sharing_size %d, "
- "coherency_domain %d, "
- "region_size %d\n",
-
- partid, utsname()->nodename,
- shubtype ? "shub2" : "shub1",
- (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
- system_size, sharing_size, coher, region_size);
-
- print_pci_topology(s);
- }
-
- if (SN_HWPERF_FOREIGN(obj)) {
- /* private in another partition: not interesting */
- return 0;
- }
-
- for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
- if (obj->name[i] == ' ')
- obj->name[i] = '_';
- }
-
- slabname = sn_hwperf_get_slabname(obj, objs, &ordinal);
- seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location,
- obj->sn_hwp_this_part ? "local" : "shared", obj->name);
-
- if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)))
- seq_putc(s, '\n');
- else {
- cnodeid_t near_mem = -1;
- cnodeid_t near_cpu = -1;
-
- seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
-
- if (sn_hwperf_get_nearest_node_objdata(objs, sn_hwperf_obj_cnt,
- ordinal, &near_mem, &near_cpu) == 0) {
- seq_printf(s, ", near_mem_nodeid %d, near_cpu_nodeid %d",
- near_mem, near_cpu);
- }
-
- if (!SN_HWPERF_IS_IONODE(obj)) {
- for_each_online_node(i) {
- seq_printf(s, i ? ":%d" : ", dist %d",
- node_distance(ordinal, i));
- }
- }
-
- seq_putc(s, '\n');
-
- /*
- * CPUs on this node, if any
- */
- if (!SN_HWPERF_IS_IONODE(obj)) {
- for_each_cpu_and(i, cpu_online_mask,
- cpumask_of_node(ordinal)) {
- slice = 'a' + cpuid_to_slice(i);
- c = cpu_data(i);
- seq_printf(s, "cpu %d %s%c local"
- " freq %luMHz, arch ia64",
- i, obj->location, slice,
- c->proc_freq / 1000000);
- for_each_online_cpu(j) {
- seq_printf(s, j ? ":%d" : ", dist %d",
- node_distance(
- cpu_to_node(i),
- cpu_to_node(j)));
- }
- seq_putc(s, '\n');
- }
- }
- }
-
- if (obj->ports) {
- /*
- * numalink ports
- */
- sz = obj->ports * sizeof(struct sn_hwperf_port_info);
- if ((ptdata = kmalloc(sz, GFP_KERNEL)) == NULL)
- return -ENOMEM;
- e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- SN_HWPERF_ENUM_PORTS, obj->id, sz,
- (u64) ptdata, 0, 0, NULL);
- if (e != SN_HWPERF_OP_OK)
- return -EINVAL;
- for (ordinal=0, p=objs; p != obj; p++) {
- if (!SN_HWPERF_FOREIGN(p))
- ordinal += p->ports;
- }
- for (pt = 0; pt < obj->ports; pt++) {
- for (p = objs, i = 0; i < sn_hwperf_obj_cnt; i++, p++) {
- if (ptdata[pt].conn_id == p->id) {
- break;
- }
- }
- seq_printf(s, "numalink %d %s-%d",
- ordinal+pt, obj->location, ptdata[pt].port);
-
- if (i >= sn_hwperf_obj_cnt) {
- /* no connection */
- seq_puts(s, " local endpoint disconnected"
- ", protocol unknown\n");
- continue;
- }
-
- if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
- /* both ends local to this partition */
- seq_puts(s, " local");
- else if (SN_HWPERF_FOREIGN(p))
- /* both ends of the link in foreign partition */
- seq_puts(s, " foreign");
- else
- /* link straddles a partition */
- seq_puts(s, " shared");
-
- /*
- * Unlikely, but strictly should query the LLP config
- * registers because an NL4R can be configured to run
- * NL3 protocol, even when not talking to an NL3 router.
- * Ditto for node-node.
- */
- seq_printf(s, " endpoint %s-%d, protocol %s\n",
- p->location, ptdata[pt].conn_port,
- (SN_HWPERF_IS_NL3ROUTER(obj) ||
- SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4");
- }
- kfree(ptdata);
- }
-
- return 0;
-}
-
-static void *sn_topology_start(struct seq_file *s, loff_t * pos)
-{
- struct sn_hwperf_object_info *objs = s->private;
-
- if (*pos < sn_hwperf_obj_cnt)
- return (void *)(objs + *pos);
-
- return NULL;
-}
-
-static void *sn_topology_next(struct seq_file *s, void *v, loff_t * pos)
-{
- ++*pos;
- return sn_topology_start(s, pos);
-}
-
-static void sn_topology_stop(struct seq_file *m, void *v)
-{
- return;
-}
-
-/*
- * /proc/sgi_sn/sn_topology, read-only using seq_file
- */
-static const struct seq_operations sn_topology_seq_ops = {
- .start = sn_topology_start,
- .next = sn_topology_next,
- .stop = sn_topology_stop,
- .show = sn_topology_show
-};
-
-struct sn_hwperf_op_info {
- u64 op;
- struct sn_hwperf_ioctl_args *a;
- void *p;
- int *v0;
- int ret;
-};
-
-static void sn_hwperf_call_sal(void *info)
-{
- struct sn_hwperf_op_info *op_info = info;
- int r;
-
- r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op_info->op,
- op_info->a->arg, op_info->a->sz,
- (u64) op_info->p, 0, 0, op_info->v0);
- op_info->ret = r;
-}
-
-static long sn_hwperf_call_sal_work(void *info)
-{
- sn_hwperf_call_sal(info);
- return 0;
-}
-
-static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
-{
- u32 cpu;
- u32 use_ipi;
- int r = 0;
-
- cpu = (op_info->a->arg & SN_HWPERF_ARG_CPU_MASK) >> 32;
- use_ipi = op_info->a->arg & SN_HWPERF_ARG_USE_IPI_MASK;
- op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
-
- if (cpu != SN_HWPERF_ARG_ANY_CPU) {
- if (cpu >= nr_cpu_ids || !cpu_online(cpu)) {
- r = -EINVAL;
- goto out;
- }
- }
-
- if (cpu == SN_HWPERF_ARG_ANY_CPU) {
- /* don't care which cpu */
- sn_hwperf_call_sal(op_info);
- } else if (cpu == get_cpu()) {
- /* already on correct cpu */
- sn_hwperf_call_sal(op_info);
- put_cpu();
- } else {
- put_cpu();
- if (use_ipi) {
- /* use an interprocessor interrupt to call SAL */
- smp_call_function_single(cpu, sn_hwperf_call_sal,
- op_info, 1);
- } else {
- /* Call on the target CPU */
- work_on_cpu_safe(cpu, sn_hwperf_call_sal_work, op_info);
- }
- }
- r = op_info->ret;
-
-out:
- return r;
-}
-
-/* map SAL hwperf error code to system error code */
-static int sn_hwperf_map_err(int hwperf_err)
-{
- int e;
-
- switch(hwperf_err) {
- case SN_HWPERF_OP_OK:
- e = 0;
- break;
-
- case SN_HWPERF_OP_NOMEM:
- e = -ENOMEM;
- break;
-
- case SN_HWPERF_OP_NO_PERM:
- e = -EPERM;
- break;
-
- case SN_HWPERF_OP_IO_ERROR:
- e = -EIO;
- break;
-
- case SN_HWPERF_OP_BUSY:
- e = -EBUSY;
- break;
-
- case SN_HWPERF_OP_RECONFIGURE:
- e = -EAGAIN;
- break;
-
- case SN_HWPERF_OP_INVAL:
- default:
- e = -EINVAL;
- break;
- }
-
- return e;
-}
-
-/*
- * ioctl for "sn_hwperf" misc device
- */
-static long sn_hwperf_ioctl(struct file *fp, u32 op, unsigned long arg)
-{
- struct sn_hwperf_ioctl_args a;
- struct cpuinfo_ia64 *cdata;
- struct sn_hwperf_object_info *objs;
- struct sn_hwperf_object_info *cpuobj;
- struct sn_hwperf_op_info op_info;
- void *p = NULL;
- int nobj;
- char slice;
- int node;
- int r;
- int v0;
- int i;
- int j;
-
- /* only user requests are allowed here */
- if ((op & SN_HWPERF_OP_MASK) < 10) {
- r = -EINVAL;
- goto error;
- }
- r = copy_from_user(&a, (const void __user *)arg,
- sizeof(struct sn_hwperf_ioctl_args));
- if (r != 0) {
- r = -EFAULT;
- goto error;
- }
-
- /*
- * Allocate memory to hold a kernel copy of the user buffer. The
- * buffer contents are either copied in or out (or both) of user
- * space depending on the flags encoded in the requested operation.
- */
- if (a.ptr) {
- p = vmalloc(a.sz);
- if (!p) {
- r = -ENOMEM;
- goto error;
- }
- }
-
- if (op & SN_HWPERF_OP_MEM_COPYIN) {
- r = copy_from_user(p, (const void __user *)a.ptr, a.sz);
- if (r != 0) {
- r = -EFAULT;
- goto error;
- }
- }
-
- switch (op) {
- case SN_HWPERF_GET_CPU_INFO:
- if (a.sz == sizeof(u64)) {
- /* special case to get size needed */
- *(u64 *) p = (u64) num_online_cpus() *
- sizeof(struct sn_hwperf_object_info);
- } else
- if (a.sz < num_online_cpus() * sizeof(struct sn_hwperf_object_info)) {
- r = -ENOMEM;
- goto error;
- } else
- if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
- int cpuobj_index = 0;
-
- memset(p, 0, a.sz);
- for (i = 0; i < nobj; i++) {
- if (!SN_HWPERF_IS_NODE(objs + i))
- continue;
- node = sn_hwperf_obj_to_cnode(objs + i);
- for_each_online_cpu(j) {
- if (node != cpu_to_node(j))
- continue;
- cpuobj = (struct sn_hwperf_object_info *) p + cpuobj_index++;
- slice = 'a' + cpuid_to_slice(j);
- cdata = cpu_data(j);
- cpuobj->id = j;
- snprintf(cpuobj->name,
- sizeof(cpuobj->name),
- "CPU %luMHz %s",
- cdata->proc_freq / 1000000,
- cdata->vendor);
- snprintf(cpuobj->location,
- sizeof(cpuobj->location),
- "%s%c", objs[i].location,
- slice);
- }
- }
-
- vfree(objs);
- }
- break;
-
- case SN_HWPERF_GET_NODE_NASID:
- if (a.sz != sizeof(u64) ||
- (node = a.arg) < 0 || !cnode_possible(node)) {
- r = -EINVAL;
- goto error;
- }
- *(u64 *)p = (u64)cnodeid_to_nasid(node);
- break;
-
- case SN_HWPERF_GET_OBJ_NODE:
- i = a.arg;
- if (a.sz != sizeof(u64) || i < 0) {
- r = -EINVAL;
- goto error;
- }
- if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
- if (i >= nobj) {
- r = -EINVAL;
- vfree(objs);
- goto error;
- }
- if (objs[i].id != a.arg) {
- for (i = 0; i < nobj; i++) {
- if (objs[i].id == a.arg)
- break;
- }
- }
- if (i == nobj) {
- r = -EINVAL;
- vfree(objs);
- goto error;
- }
-
- if (!SN_HWPERF_IS_NODE(objs + i) &&
- !SN_HWPERF_IS_IONODE(objs + i)) {
- r = -ENOENT;
- vfree(objs);
- goto error;
- }
-
- *(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i);
- vfree(objs);
- }
- break;
-
- case SN_HWPERF_GET_MMRS:
- case SN_HWPERF_SET_MMRS:
- case SN_HWPERF_OBJECT_DISTANCE:
- op_info.p = p;
- op_info.a = &a;
- op_info.v0 = &v0;
- op_info.op = op;
- r = sn_hwperf_op_cpu(&op_info);
- if (r) {
- r = sn_hwperf_map_err(r);
- a.v0 = v0;
- goto error;
- }
- break;
-
- default:
- /* all other ops are a direct SAL call */
- r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op,
- a.arg, a.sz, (u64) p, 0, 0, &v0);
- if (r) {
- r = sn_hwperf_map_err(r);
- goto error;
- }
- a.v0 = v0;
- break;
- }
-
- if (op & SN_HWPERF_OP_MEM_COPYOUT) {
- r = copy_to_user((void __user *)a.ptr, p, a.sz);
- if (r != 0) {
- r = -EFAULT;
- goto error;
- }
- }
-
-error:
- vfree(p);
-
- return r;
-}
-
-static const struct file_operations sn_hwperf_fops = {
- .unlocked_ioctl = sn_hwperf_ioctl,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice sn_hwperf_dev = {
- MISC_DYNAMIC_MINOR,
- "sn_hwperf",
- &sn_hwperf_fops
-};
-
-static int sn_hwperf_init(void)
-{
- u64 v;
- int salr;
- int e = 0;
-
- /* single threaded, once-only initialization */
- mutex_lock(&sn_hwperf_init_mutex);
-
- if (sn_hwperf_salheap) {
- mutex_unlock(&sn_hwperf_init_mutex);
- return e;
- }
-
- /*
- * The PROM code needs a fixed reference node. For convenience the
- * same node as the console I/O is used.
- */
- sn_hwperf_master_nasid = (nasid_t) ia64_sn_get_console_nasid();
-
- /*
- * Request the needed size and install the PROM scratch area.
- * The PROM keeps various tracking bits in this memory area.
- */
- salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- (u64) SN_HWPERF_GET_HEAPSIZE, 0,
- (u64) sizeof(u64), (u64) &v, 0, 0, NULL);
- if (salr != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- goto out;
- }
-
- if ((sn_hwperf_salheap = vmalloc(v)) == NULL) {
- e = -ENOMEM;
- goto out;
- }
- salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- SN_HWPERF_INSTALL_HEAP, 0, v,
- (u64) sn_hwperf_salheap, 0, 0, NULL);
- if (salr != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- goto out;
- }
-
- salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
- SN_HWPERF_OBJECT_COUNT, 0,
- sizeof(u64), (u64) &v, 0, 0, NULL);
- if (salr != SN_HWPERF_OP_OK) {
- e = -EINVAL;
- goto out;
- }
- sn_hwperf_obj_cnt = (int)v;
-
-out:
- if (e < 0 && sn_hwperf_salheap) {
- vfree(sn_hwperf_salheap);
- sn_hwperf_salheap = NULL;
- sn_hwperf_obj_cnt = 0;
- }
- mutex_unlock(&sn_hwperf_init_mutex);
- return e;
-}
-
-int sn_topology_open(struct inode *inode, struct file *file)
-{
- int e;
- struct seq_file *seq;
- struct sn_hwperf_object_info *objbuf;
- int nobj;
-
- if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
- e = seq_open(file, &sn_topology_seq_ops);
- seq = file->private_data;
- seq->private = objbuf;
- }
-
- return e;
-}
-
-int sn_topology_release(struct inode *inode, struct file *file)
-{
- struct seq_file *seq = file->private_data;
-
- vfree(seq->private);
- return seq_release(inode, file);
-}
-
-int sn_hwperf_get_nearest_node(cnodeid_t node,
- cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
-{
- int e;
- int nobj;
- struct sn_hwperf_object_info *objbuf;
-
- if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
- e = sn_hwperf_get_nearest_node_objdata(objbuf, nobj,
- node, near_mem_node, near_cpu_node);
- vfree(objbuf);
- }
-
- return e;
-}
-
-static int sn_hwperf_misc_register_init(void)
-{
- int e;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- sn_hwperf_init();
-
- /*
- * Register a dynamic misc device for hwperf ioctls. Platforms
- * supporting hotplug will create /dev/sn_hwperf, else user
- * can to look up the minor number in /proc/misc.
- */
- if ((e = misc_register(&sn_hwperf_dev)) != 0) {
- printk(KERN_ERR "sn_hwperf_misc_register_init: failed to "
- "register misc device for \"%s\"\n", sn_hwperf_dev.name);
- }
-
- return e;
-}
-
-device_initcall(sn_hwperf_misc_register_init); /* after misc_init() */
-EXPORT_SYMBOL(sn_hwperf_get_nearest_node);
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
deleted file mode 100644
index c2a4d84297b0..000000000000
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ /dev/null
@@ -1,69 +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-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <asm/sn/sn_sal.h>
-
-static int partition_id_show(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", sn_partition_id);
- return 0;
-}
-
-static int system_serial_number_show(struct seq_file *s, void *p)
-{
- seq_printf(s, "%s\n", sn_system_serial_number());
- return 0;
-}
-
-static int licenseID_show(struct seq_file *s, void *p)
-{
- seq_printf(s, "0x%llx\n", sn_partition_serial_number_val());
- return 0;
-}
-
-static int coherence_id_show(struct seq_file *s, void *p)
-{
- seq_printf(s, "%d\n", partition_coherence_id());
-
- return 0;
-}
-
-/* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */
-extern int sn_topology_open(struct inode *, struct file *);
-extern int sn_topology_release(struct inode *, struct file *);
-
-static const struct file_operations proc_sn_topo_fops = {
- .open = sn_topology_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = sn_topology_release,
-};
-
-void register_sn_procfs(void)
-{
- static struct proc_dir_entry *sgi_proc_dir = NULL;
-
- BUG_ON(sgi_proc_dir != NULL);
- if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
- return;
-
- proc_create_single("partition_id", 0444, sgi_proc_dir,
- partition_id_show);
- proc_create_single("system_serial_number", 0444, sgi_proc_dir,
- system_serial_number_show);
- proc_create_single("licenseID", 0444, sgi_proc_dir, licenseID_show);
- proc_create_single("coherence_id", 0444, sgi_proc_dir,
- coherence_id_show);
- proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops);
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
deleted file mode 100644
index 3009d9d86f29..000000000000
--- a/arch/ia64/sn/kernel/sn2/timer.c
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/arch/ia64/sn/kernel/sn2/timer.c
- *
- * Copyright (C) 2003 Silicon Graphics, Inc.
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger <davidm@hpl.hp.com>: updated for new timer-interpolation infrastructure
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/clocksource.h>
-
-#include <asm/hw_irq.h>
-#include <asm/timex.h>
-
-#include <asm/sn/leds.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/clksupport.h>
-
-extern unsigned long sn_rtc_cycles_per_second;
-
-static u64 read_sn2(struct clocksource *cs)
-{
- return (u64)readq(RTC_COUNTER_ADDR);
-}
-
-static struct clocksource clocksource_sn2 = {
- .name = "sn2_rtc",
- .rating = 450,
- .read = read_sn2,
- .mask = (1LL << 55) - 1,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
- * sn udelay uses the RTC instead of the ITC because the ITC is not
- * synchronized across all CPUs, and the thread may migrate to another CPU
- * if preemption is enabled.
- */
-static void
-ia64_sn_udelay (unsigned long usecs)
-{
- unsigned long start = rtc_time();
- unsigned long end = start +
- usecs * sn_rtc_cycles_per_second / 1000000;
-
- while (time_before((unsigned long)rtc_time(), end))
- cpu_relax();
-}
-
-void __init sn_timer_init(void)
-{
- clocksource_sn2.archdata.fsys_mmio = RTC_COUNTER_ADDR;
- clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second);
-
- ia64_udelay = &ia64_sn_udelay;
-}
diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
deleted file mode 100644
index 103d6ea8e94b..000000000000
--- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- *
- * Copyright (c) 2005, 2006 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/interrupt.h>
-#include <asm/sn/pda.h>
-#include <asm/sn/leds.h>
-
-extern void sn_lb_int_war_check(void);
-extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-#define SN_LB_INT_WAR_INTERVAL 100
-
-void sn_timer_interrupt(int irq, void *dev_id)
-{
- /* LED blinking */
- if (!pda->hb_count--) {
- pda->hb_count = HZ / 2;
- set_led_bits(pda->hb_state ^=
- LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT);
- }
-
- if (is_shub1()) {
- if (enable_shub_wars_1_1()) {
- /* Bugfix code for SHUB 1.1 */
- if (pda->pio_shub_war_cam_addr)
- *pda->pio_shub_war_cam_addr = 0x8000000000000010UL;
- }
- if (pda->sn_lb_int_war_ticks == 0)
- sn_lb_int_war_check();
- pda->sn_lb_int_war_ticks++;
- if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
- pda->sn_lb_int_war_ticks = 0;
- }
-}
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
deleted file mode 100644
index 32d0380eb72e..000000000000
--- a/arch/ia64/sn/kernel/tiocx.c
+++ /dev/null
@@ -1,569 +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) 2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/proc_fs.h>
-#include <linux/capability.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/io.h>
-#include <asm/sn/types.h>
-#include <asm/sn/shubio.h>
-#include <asm/sn/tiocx.h>
-#include <asm/sn/l1.h>
-#include <asm/sn/module.h>
-#include "tio.h"
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-
-#define CX_DEV_NONE 0
-#define DEVICE_NAME "tiocx"
-#define WIDGET_ID 0
-#define TIOCX_DEBUG 0
-
-#if TIOCX_DEBUG
-#define DBG(fmt...) printk(KERN_ALERT fmt)
-#else
-#define DBG(fmt...)
-#endif
-
-struct device_attribute dev_attr_cxdev_control;
-
-/**
- * tiocx_match - Try to match driver id list with device.
- * @dev: device pointer
- * @drv: driver pointer
- *
- * Returns 1 if match, 0 otherwise.
- */
-static int tiocx_match(struct device *dev, struct device_driver *drv)
-{
- struct cx_dev *cx_dev = to_cx_dev(dev);
- struct cx_drv *cx_drv = to_cx_driver(drv);
- const struct cx_device_id *ids = cx_drv->id_table;
-
- if (!ids)
- return 0;
-
- while (ids->part_num) {
- if (ids->part_num == cx_dev->cx_id.part_num)
- return 1;
- ids++;
- }
- return 0;
-
-}
-
-static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-
-static void tiocx_bus_release(struct device *dev)
-{
- kfree(to_cx_dev(dev));
-}
-
-/**
- * cx_device_match - Find cx_device in the id table.
- * @ids: id table from driver
- * @cx_device: part/mfg id for the device
- *
- */
-static const struct cx_device_id *cx_device_match(const struct cx_device_id
- *ids,
- struct cx_dev *cx_device)
-{
- /*
- * NOTES: We may want to check for CX_ANY_ID too.
- * Do we want to match against nasid too?
- * CX_DEV_NONE == 0, if the driver tries to register for
- * part/mfg == 0 we should return no-match (NULL) here.
- */
- while (ids->part_num && ids->mfg_num) {
- if (ids->part_num == cx_device->cx_id.part_num &&
- ids->mfg_num == cx_device->cx_id.mfg_num)
- return ids;
- ids++;
- }
-
- return NULL;
-}
-
-/**
- * cx_device_probe - Look for matching device.
- * Call driver probe routine if found.
- * @cx_driver: driver table (cx_drv struct) from driver
- * @cx_device: part/mfg id for the device
- */
-static int cx_device_probe(struct device *dev)
-{
- const struct cx_device_id *id;
- struct cx_drv *cx_drv = to_cx_driver(dev->driver);
- struct cx_dev *cx_dev = to_cx_dev(dev);
- int error = 0;
-
- if (!cx_dev->driver && cx_drv->probe) {
- id = cx_device_match(cx_drv->id_table, cx_dev);
- if (id) {
- if ((error = cx_drv->probe(cx_dev, id)) < 0)
- return error;
- else
- cx_dev->driver = cx_drv;
- }
- }
-
- return error;
-}
-
-/**
- * cx_driver_remove - Remove driver from device struct.
- * @dev: device
- */
-static int cx_driver_remove(struct device *dev)
-{
- struct cx_dev *cx_dev = to_cx_dev(dev);
- struct cx_drv *cx_drv = cx_dev->driver;
- if (cx_drv->remove)
- cx_drv->remove(cx_dev);
- cx_dev->driver = NULL;
- return 0;
-}
-
-struct bus_type tiocx_bus_type = {
- .name = "tiocx",
- .match = tiocx_match,
- .uevent = tiocx_uevent,
- .probe = cx_device_probe,
- .remove = cx_driver_remove,
-};
-
-/**
- * cx_driver_register - Register the driver.
- * @cx_driver: driver table (cx_drv struct) from driver
- *
- * Called from the driver init routine to register a driver.
- * The cx_drv struct contains the driver name, a pointer to
- * a table of part/mfg numbers and a pointer to the driver's
- * probe/attach routine.
- */
-int cx_driver_register(struct cx_drv *cx_driver)
-{
- cx_driver->driver.name = cx_driver->name;
- cx_driver->driver.bus = &tiocx_bus_type;
-
- return driver_register(&cx_driver->driver);
-}
-
-/**
- * cx_driver_unregister - Unregister the driver.
- * @cx_driver: driver table (cx_drv struct) from driver
- */
-int cx_driver_unregister(struct cx_drv *cx_driver)
-{
- driver_unregister(&cx_driver->driver);
- return 0;
-}
-
-/**
- * cx_device_register - Register a device.
- * @nasid: device's nasid
- * @part_num: device's part number
- * @mfg_num: device's manufacturer number
- * @hubdev: hub info associated with this device
- * @bt: board type of the device
- *
- */
-int
-cx_device_register(nasid_t nasid, int part_num, int mfg_num,
- struct hubdev_info *hubdev, int bt)
-{
- struct cx_dev *cx_dev;
- int r;
-
- cx_dev = kzalloc(sizeof(struct cx_dev), GFP_KERNEL);
- DBG("cx_dev= 0x%p\n", cx_dev);
- if (cx_dev == NULL)
- return -ENOMEM;
-
- cx_dev->cx_id.part_num = part_num;
- cx_dev->cx_id.mfg_num = mfg_num;
- cx_dev->cx_id.nasid = nasid;
- cx_dev->hubdev = hubdev;
- cx_dev->bt = bt;
-
- cx_dev->dev.parent = NULL;
- cx_dev->dev.bus = &tiocx_bus_type;
- cx_dev->dev.release = tiocx_bus_release;
- dev_set_name(&cx_dev->dev, "%d", cx_dev->cx_id.nasid);
- r = device_register(&cx_dev->dev);
- if (r) {
- kfree(cx_dev);
- return r;
- }
- get_device(&cx_dev->dev);
-
- device_create_file(&cx_dev->dev, &dev_attr_cxdev_control);
-
- return 0;
-}
-
-/**
- * cx_device_unregister - Unregister a device.
- * @cx_dev: part/mfg id for the device
- */
-int cx_device_unregister(struct cx_dev *cx_dev)
-{
- put_device(&cx_dev->dev);
- device_unregister(&cx_dev->dev);
- return 0;
-}
-
-/**
- * cx_device_reload - Reload the device.
- * @nasid: device's nasid
- * @part_num: device's part number
- * @mfg_num: device's manufacturer number
- *
- * Remove the device associated with 'nasid' from device list and then
- * call device-register with the given part/mfg numbers.
- */
-static int cx_device_reload(struct cx_dev *cx_dev)
-{
- cx_device_unregister(cx_dev);
- return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
- cx_dev->cx_id.mfg_num, cx_dev->hubdev,
- cx_dev->bt);
-}
-
-static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget,
- u64 sn_irq_info,
- int req_irq, nasid_t req_nasid,
- int req_slice)
-{
- struct ia64_sal_retval rv;
- rv.status = 0;
- rv.v0 = 0;
-
- ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
- SAL_INTR_ALLOC, nasid,
- widget, sn_irq_info, req_irq,
- req_nasid, req_slice);
- return rv.status;
-}
-
-static inline void tiocx_intr_free(nasid_t nasid, int widget,
- struct sn_irq_info *sn_irq_info)
-{
- struct ia64_sal_retval rv;
- rv.status = 0;
- rv.v0 = 0;
-
- ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
- SAL_INTR_FREE, nasid,
- widget, sn_irq_info->irq_irq,
- sn_irq_info->irq_cookie, 0, 0);
-}
-
-struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
- nasid_t req_nasid, int slice)
-{
- struct sn_irq_info *sn_irq_info;
- int status;
- int sn_irq_size = sizeof(struct sn_irq_info);
-
- if ((nasid & 1) == 0)
- return NULL;
-
- sn_irq_info = kzalloc(sn_irq_size, GFP_KERNEL);
- if (sn_irq_info == NULL)
- return NULL;
-
- status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq,
- req_nasid, slice);
- if (status) {
- kfree(sn_irq_info);
- return NULL;
- } else {
- return sn_irq_info;
- }
-}
-
-void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
-{
- u64 bridge = (u64) sn_irq_info->irq_bridge;
- nasid_t nasid = NASID_GET(bridge);
- int widget;
-
- if (nasid & 1) {
- widget = TIO_SWIN_WIDGETNUM(bridge);
- tiocx_intr_free(nasid, widget, sn_irq_info);
- kfree(sn_irq_info);
- }
-}
-
-u64 tiocx_dma_addr(u64 addr)
-{
- return PHYS_TO_TIODMA(addr);
-}
-
-u64 tiocx_swin_base(int nasid)
-{
- return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
-}
-
-EXPORT_SYMBOL(cx_driver_register);
-EXPORT_SYMBOL(cx_driver_unregister);
-EXPORT_SYMBOL(cx_device_register);
-EXPORT_SYMBOL(cx_device_unregister);
-EXPORT_SYMBOL(tiocx_irq_alloc);
-EXPORT_SYMBOL(tiocx_irq_free);
-EXPORT_SYMBOL(tiocx_bus_type);
-EXPORT_SYMBOL(tiocx_dma_addr);
-EXPORT_SYMBOL(tiocx_swin_base);
-
-static void tio_conveyor_set(nasid_t nasid, int enable_flag)
-{
- u64 ice_frz;
- u64 disable_cb = (1ull << 61);
-
- if (!(nasid & 1))
- return;
-
- ice_frz = REMOTE_HUB_L(nasid, TIO_ICE_FRZ_CFG);
- if (enable_flag) {
- if (!(ice_frz & disable_cb)) /* already enabled */
- return;
- ice_frz &= ~disable_cb;
- } else {
- if (ice_frz & disable_cb) /* already disabled */
- return;
- ice_frz |= disable_cb;
- }
- DBG(KERN_ALERT "TIO_ICE_FRZ_CFG= 0x%lx\n", ice_frz);
- REMOTE_HUB_S(nasid, TIO_ICE_FRZ_CFG, ice_frz);
-}
-
-#define tio_conveyor_enable(nasid) tio_conveyor_set(nasid, 1)
-#define tio_conveyor_disable(nasid) tio_conveyor_set(nasid, 0)
-
-static void tio_corelet_reset(nasid_t nasid, int corelet)
-{
- if (!(nasid & 1))
- return;
-
- REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 1 << corelet);
- udelay(2000);
- REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 0);
- udelay(2000);
-}
-
-static int is_fpga_tio(int nasid, int *bt)
-{
- u16 uninitialized_var(ioboard_type); /* GCC be quiet */
- long rc;
-
- rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
- if (rc) {
- printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
- rc);
- return 0;
- }
-
- switch (ioboard_type) {
- case L1_BRICKTYPE_SA:
- case L1_BRICKTYPE_ATHENA:
- case L1_BOARDTYPE_DAYTONA:
- *bt = ioboard_type;
- return 1;
- }
-
- return 0;
-}
-
-static int bitstream_loaded(nasid_t nasid)
-{
- u64 cx_credits;
-
- cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
- cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
- DBG("cx_credits= 0x%lx\n", cx_credits);
-
- return (cx_credits == 0xf) ? 1 : 0;
-}
-
-static int tiocx_reload(struct cx_dev *cx_dev)
-{
- int part_num = CX_DEV_NONE;
- int mfg_num = CX_DEV_NONE;
- nasid_t nasid = cx_dev->cx_id.nasid;
-
- if (bitstream_loaded(nasid)) {
- u64 cx_id;
- int rv;
-
- rv = ia64_sn_sysctl_tio_clock_reset(nasid);
- if (rv) {
- printk(KERN_ALERT "CX port JTAG reset failed.\n");
- } else {
- cx_id = *(volatile u64 *)
- (TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
- WIDGET_ID);
- part_num = XWIDGET_PART_NUM(cx_id);
- mfg_num = XWIDGET_MFG_NUM(cx_id);
- DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
- /* just ignore it if it's a CE */
- if (part_num == TIO_CE_ASIC_PARTNUM)
- return 0;
- }
- }
-
- cx_dev->cx_id.part_num = part_num;
- cx_dev->cx_id.mfg_num = mfg_num;
-
- /*
- * Delete old device and register the new one. It's ok if
- * part_num/mfg_num == CX_DEV_NONE. We want to register
- * devices in the table even if a bitstream isn't loaded.
- * That allows use to see that a bitstream isn't loaded via
- * TIOCX_IOCTL_DEV_LIST.
- */
- return cx_device_reload(cx_dev);
-}
-
-static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct cx_dev *cx_dev = to_cx_dev(dev);
-
- return sprintf(buf, "0x%x 0x%x 0x%x 0x%x\n",
- cx_dev->cx_id.nasid,
- cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
- cx_dev->bt);
-}
-
-static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
-{
- int n;
- struct cx_dev *cx_dev = to_cx_dev(dev);
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (count <= 0)
- return 0;
-
- n = simple_strtoul(buf, NULL, 0);
-
- switch (n) {
- case 1:
- tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
- tiocx_reload(cx_dev);
- break;
- case 2:
- tiocx_reload(cx_dev);
- break;
- case 3:
- tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
- break;
- default:
- break;
- }
-
- return count;
-}
-
-DEVICE_ATTR(cxdev_control, 0644, show_cxdev_control, store_cxdev_control);
-
-static int __init tiocx_init(void)
-{
- cnodeid_t cnodeid;
- int found_tiocx_device = 0;
- int err;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- err = bus_register(&tiocx_bus_type);
- if (err)
- return err;
-
- for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
- nasid_t nasid;
- int bt;
-
- nasid = cnodeid_to_nasid(cnodeid);
-
- if ((nasid & 0x1) && is_fpga_tio(nasid, &bt)) {
- struct hubdev_info *hubdev;
- struct xwidget_info *widgetp;
-
- DBG("Found TIO at nasid 0x%x\n", nasid);
-
- hubdev =
- (struct hubdev_info *)(NODEPDA(cnodeid)->pdinfo);
-
- widgetp = &hubdev->hdi_xwidget_info[TIOCX_CORELET];
-
- /* The CE hangs off of the CX port but is not an FPGA */
- if (widgetp->xwi_hwid.part_num == TIO_CE_ASIC_PARTNUM)
- continue;
-
- tio_corelet_reset(nasid, TIOCX_CORELET);
- tio_conveyor_enable(nasid);
-
- if (cx_device_register
- (nasid, widgetp->xwi_hwid.part_num,
- widgetp->xwi_hwid.mfg_num, hubdev, bt) < 0)
- return -ENXIO;
- else
- found_tiocx_device++;
- }
- }
-
- /* It's ok if we find zero devices. */
- DBG("found_tiocx_device= %d\n", found_tiocx_device);
-
- return 0;
-}
-
-static int cx_remove_device(struct device * dev, void * data)
-{
- struct cx_dev *cx_dev = to_cx_dev(dev);
- device_remove_file(dev, &dev_attr_cxdev_control);
- cx_device_unregister(cx_dev);
- return 0;
-}
-
-static void __exit tiocx_exit(void)
-{
- DBG("tiocx_exit\n");
-
- /*
- * Unregister devices.
- */
- bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device);
- bus_unregister(&tiocx_bus_type);
-}
-
-fs_initcall(tiocx_init);
-module_exit(tiocx_exit);
-
-/************************************************************************
- * Module licensing and description
- ************************************************************************/
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
-MODULE_DESCRIPTION("TIOCX module");
-MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
deleted file mode 100644
index 321576b1b425..000000000000
--- a/arch/ia64/sn/pci/Makefile
+++ /dev/null
@@ -1,10 +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-2004 Silicon Graphics, Inc. All Rights Reserved.
-#
-# Makefile for the sn pci general routines.
-
-obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
deleted file mode 100644
index b7d42e4edc1f..000000000000
--- a/arch/ia64/sn/pci/pci_dma.c
+++ /dev/null
@@ -1,446 +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,2002-2005 Silicon Graphics, Inc. All rights reserved.
- *
- * Routines for PCI DMA mapping. See Documentation/DMA-API.txt for
- * a description of how these routines should be used.
- */
-
-#include <linux/gfp.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <asm/dma.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/sn_sal.h>
-
-#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg)))
-#define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
-
-/**
- * sn_dma_supported - test a DMA mask
- * @dev: device to test
- * @mask: DMA mask to test
- *
- * Return whether the given PCI device DMA address mask can be supported
- * properly. For example, if your device can only drive the low 24-bits
- * during PCI bus mastering, then you would pass 0x00ffffff as the mask to
- * this function. Of course, SN only supports devices that have 32 or more
- * address bits when using the PMU.
- */
-static int sn_dma_supported(struct device *dev, u64 mask)
-{
- BUG_ON(!dev_is_pci(dev));
-
- if (mask < 0x7fffffff)
- return 0;
- return 1;
-}
-
-/**
- * sn_dma_set_mask - set the DMA mask
- * @dev: device to set
- * @dma_mask: new mask
- *
- * Set @dev's DMA mask if the hw supports it.
- */
-int sn_dma_set_mask(struct device *dev, u64 dma_mask)
-{
- BUG_ON(!dev_is_pci(dev));
-
- if (!sn_dma_supported(dev, dma_mask))
- return 0;
-
- *dev->dma_mask = dma_mask;
- return 1;
-}
-EXPORT_SYMBOL(sn_dma_set_mask);
-
-/**
- * sn_dma_alloc_coherent - allocate memory for coherent DMA
- * @dev: device to allocate for
- * @size: size of the region
- * @dma_handle: DMA (bus) address
- * @flags: memory allocation flags
- *
- * dma_alloc_coherent() returns a pointer to a memory region suitable for
- * coherent DMA traffic to/from a PCI device. On SN platforms, this means
- * that @dma_handle will have the %PCIIO_DMA_CMD flag set.
- *
- * This interface is usually used for "command" streams (e.g. the command
- * queue for a SCSI controller). See Documentation/DMA-API.txt for
- * more information.
- */
-static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t flags,
- unsigned long attrs)
-{
- void *cpuaddr;
- unsigned long phys_addr;
- int node;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- BUG_ON(!dev_is_pci(dev));
-
- /*
- * Allocate the memory.
- */
- node = pcibus_to_node(pdev->bus);
- if (likely(node >=0)) {
- struct page *p = __alloc_pages_node(node,
- flags, get_order(size));
-
- if (likely(p))
- cpuaddr = page_address(p);
- else
- return NULL;
- } else
- cpuaddr = (void *)__get_free_pages(flags, get_order(size));
-
- if (unlikely(!cpuaddr))
- return NULL;
-
- memset(cpuaddr, 0x0, size);
-
- /* physical addr. of the memory we just got */
- phys_addr = __pa(cpuaddr);
-
- /*
- * 64 bit address translations should never fail.
- * 32 bit translations can fail if there are insufficient mapping
- * resources.
- */
-
- *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size,
- SN_DMA_ADDR_PHYS);
- if (!*dma_handle) {
- printk(KERN_ERR "%s: out of ATEs\n", __func__);
- free_pages((unsigned long)cpuaddr, get_order(size));
- return NULL;
- }
-
- return cpuaddr;
-}
-
-/**
- * sn_pci_free_coherent - free memory associated with coherent DMAable region
- * @dev: device to free for
- * @size: size to free
- * @cpu_addr: kernel virtual address to free
- * @dma_handle: DMA address associated with this region
- *
- * Frees the memory allocated by dma_alloc_coherent(), potentially unmapping
- * any associated IOMMU mappings.
- */
-static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t dma_handle, unsigned long attrs)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- BUG_ON(!dev_is_pci(dev));
-
- provider->dma_unmap(pdev, dma_handle, 0);
- free_pages((unsigned long)cpu_addr, get_order(size));
-}
-
-/**
- * sn_dma_map_single_attrs - map a single page for DMA
- * @dev: device to map for
- * @cpu_addr: kernel virtual address of the region to map
- * @size: size of the region
- * @direction: DMA direction
- * @attrs: optional dma attributes
- *
- * Map the region pointed to by @cpu_addr for DMA and return the
- * DMA address.
- *
- * We map this to the one step pcibr_dmamap_trans interface rather than
- * the two step pcibr_dmamap_alloc/pcibr_dmamap_addr because we have
- * no way of saving the dmamap handle from the alloc to later free
- * (which is pretty much unacceptable).
- *
- * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
- * dma_map_consistent() so that writes force a flush of pending DMA.
- * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
- * Document Number: 007-4763-001)
- *
- * TODO: simplify our interface;
- * figure out how to save dmamap handle so can use two step.
- */
-static dma_addr_t sn_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
-{
- void *cpu_addr = page_address(page) + offset;
- dma_addr_t dma_addr;
- unsigned long phys_addr;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- BUG_ON(!dev_is_pci(dev));
-
- phys_addr = __pa(cpu_addr);
- if (attrs & DMA_ATTR_WRITE_BARRIER)
- dma_addr = provider->dma_map_consistent(pdev, phys_addr,
- size, SN_DMA_ADDR_PHYS);
- else
- dma_addr = provider->dma_map(pdev, phys_addr, size,
- SN_DMA_ADDR_PHYS);
-
- if (!dma_addr) {
- printk(KERN_ERR "%s: out of ATEs\n", __func__);
- return DMA_MAPPING_ERROR;
- }
- return dma_addr;
-}
-
-/**
- * sn_dma_unmap_single_attrs - unamp a DMA mapped page
- * @dev: device to sync
- * @dma_addr: DMA address to sync
- * @size: size of region
- * @direction: DMA direction
- * @attrs: optional dma attributes
- *
- * This routine is supposed to sync the DMA region specified
- * by @dma_handle into the coherence domain. On SN, we're always cache
- * coherent, so we just need to free any ATEs associated with this mapping.
- */
-static void sn_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- BUG_ON(!dev_is_pci(dev));
-
- provider->dma_unmap(pdev, dma_addr, dir);
-}
-
-/**
- * sn_dma_unmap_sg - unmap a DMA scatterlist
- * @dev: device to unmap
- * @sg: scatterlist to unmap
- * @nhwentries: number of scatterlist entries
- * @direction: DMA direction
- * @attrs: optional dma attributes
- *
- * Unmap a set of streaming mode DMA translations.
- */
-static void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
- int nhwentries, enum dma_data_direction dir,
- unsigned long attrs)
-{
- int i;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
- struct scatterlist *sg;
-
- BUG_ON(!dev_is_pci(dev));
-
- for_each_sg(sgl, sg, nhwentries, i) {
- provider->dma_unmap(pdev, sg->dma_address, dir);
- sg->dma_address = (dma_addr_t) NULL;
- sg->dma_length = 0;
- }
-}
-
-/**
- * sn_dma_map_sg - map a scatterlist for DMA
- * @dev: device to map for
- * @sg: scatterlist to map
- * @nhwentries: number of entries
- * @direction: direction of the DMA transaction
- * @attrs: optional dma attributes
- *
- * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
- * dma_map_consistent() so that writes force a flush of pending DMA.
- * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
- * Document Number: 007-4763-001)
- *
- * Maps each entry of @sg for DMA.
- */
-static int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl,
- int nhwentries, enum dma_data_direction dir,
- unsigned long attrs)
-{
- unsigned long phys_addr;
- struct scatterlist *saved_sg = sgl, *sg;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
- int i;
-
- BUG_ON(!dev_is_pci(dev));
-
- /*
- * Setup a DMA address for each entry in the scatterlist.
- */
- for_each_sg(sgl, sg, nhwentries, i) {
- dma_addr_t dma_addr;
- phys_addr = SG_ENT_PHYS_ADDRESS(sg);
- if (attrs & DMA_ATTR_WRITE_BARRIER)
- dma_addr = provider->dma_map_consistent(pdev,
- phys_addr,
- sg->length,
- SN_DMA_ADDR_PHYS);
- else
- dma_addr = provider->dma_map(pdev, phys_addr,
- sg->length,
- SN_DMA_ADDR_PHYS);
-
- sg->dma_address = dma_addr;
- if (!sg->dma_address) {
- printk(KERN_ERR "%s: out of ATEs\n", __func__);
-
- /*
- * Free any successfully allocated entries.
- */
- if (i > 0)
- sn_dma_unmap_sg(dev, saved_sg, i, dir, attrs);
- return 0;
- }
-
- sg->dma_length = sg->length;
- }
-
- return nhwentries;
-}
-
-static u64 sn_dma_get_required_mask(struct device *dev)
-{
- return DMA_BIT_MASK(64);
-}
-
-char *sn_pci_get_legacy_mem(struct pci_bus *bus)
-{
- if (!SN_PCIBUS_BUSSOFT(bus))
- return ERR_PTR(-ENODEV);
-
- return (char *)(SN_PCIBUS_BUSSOFT(bus)->bs_legacy_mem | __IA64_UNCACHED_OFFSET);
-}
-
-int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
-{
- unsigned long addr;
- int ret;
- struct ia64_sal_retval isrv;
-
- /*
- * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
- * around hw issues at the pci bus level. SGI proms older than
- * 4.10 don't implement this.
- */
-
- SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
- pci_domain_nr(bus), bus->number,
- 0, /* io */
- 0, /* read */
- port, size, __pa(val));
-
- if (isrv.status == 0)
- return size;
-
- /*
- * If the above failed, retry using the SAL_PROBE call which should
- * be present in all proms (but which cannot work round PCI chipset
- * bugs). This code is retained for compatibility with old
- * pre-4.10 proms, and should be removed at some point in the future.
- */
-
- if (!SN_PCIBUS_BUSSOFT(bus))
- return -ENODEV;
-
- addr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
- addr += port;
-
- ret = ia64_sn_probe_mem(addr, (long)size, (void *)val);
-
- if (ret == 2)
- return -EINVAL;
-
- if (ret == 1)
- *val = -1;
-
- return size;
-}
-
-int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
-{
- int ret = size;
- unsigned long paddr;
- unsigned long *addr;
- struct ia64_sal_retval isrv;
-
- /*
- * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
- * around hw issues at the pci bus level. SGI proms older than
- * 4.10 don't implement this.
- */
-
- SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
- pci_domain_nr(bus), bus->number,
- 0, /* io */
- 1, /* write */
- port, size, __pa(&val));
-
- if (isrv.status == 0)
- return size;
-
- /*
- * If the above failed, retry using the SAL_PROBE call which should
- * be present in all proms (but which cannot work round PCI chipset
- * bugs). This code is retained for compatibility with old
- * pre-4.10 proms, and should be removed at some point in the future.
- */
-
- if (!SN_PCIBUS_BUSSOFT(bus)) {
- ret = -ENODEV;
- goto out;
- }
-
- /* Put the phys addr in uncached space */
- paddr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
- paddr += port;
- addr = (unsigned long *)paddr;
-
- switch (size) {
- case 1:
- *(volatile u8 *)(addr) = (u8)(val);
- break;
- case 2:
- *(volatile u16 *)(addr) = (u16)(val);
- break;
- case 4:
- *(volatile u32 *)(addr) = (u32)(val);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- out:
- return ret;
-}
-
-static struct dma_map_ops sn_dma_ops = {
- .alloc = sn_dma_alloc_coherent,
- .free = sn_dma_free_coherent,
- .map_page = sn_dma_map_page,
- .unmap_page = sn_dma_unmap_page,
- .map_sg = sn_dma_map_sg,
- .unmap_sg = sn_dma_unmap_sg,
- .dma_supported = sn_dma_supported,
- .get_required_mask = sn_dma_get_required_mask,
-};
-
-void sn_dma_init(void)
-{
- dma_ops = &sn_dma_ops;
-}
diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile
deleted file mode 100644
index 712f6af7c6e0..000000000000
--- a/arch/ia64/sn/pci/pcibr/Makefile
+++ /dev/null
@@ -1,13 +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) 2002-2004 Silicon Graphics, Inc. All Rights Reserved.
-#
-# Makefile for the sn2 io routines.
-
-ccflags-y := -I $(srctree)/arch/ia64/sn/include
-
-obj-y += pcibr_dma.o pcibr_reg.o \
- pcibr_ate.o pcibr_provider.o
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
deleted file mode 100644
index b67bb4cb73ff..000000000000
--- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c
+++ /dev/null
@@ -1,177 +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) 2001-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-
-int pcibr_invalidate_ate; /* by default don't invalidate ATE on free */
-
-/*
- * mark_ate: Mark the ate as either free or inuse.
- */
-static void mark_ate(struct ate_resource *ate_resource, int start, int number,
- u64 value)
-{
- u64 *ate = ate_resource->ate;
- int index;
- int length = 0;
-
- for (index = start; length < number; index++, length++)
- ate[index] = value;
-}
-
-/*
- * find_free_ate: Find the first free ate index starting from the given
- * index for the desired consecutive count.
- */
-static int find_free_ate(struct ate_resource *ate_resource, int start,
- int count)
-{
- u64 *ate = ate_resource->ate;
- int index;
- int start_free;
-
- for (index = start; index < ate_resource->num_ate;) {
- if (!ate[index]) {
- int i;
- int free;
- free = 0;
- start_free = index; /* Found start free ate */
- for (i = start_free; i < ate_resource->num_ate; i++) {
- if (!ate[i]) { /* This is free */
- if (++free == count)
- return start_free;
- } else {
- index = i + 1;
- break;
- }
- }
- if (i >= ate_resource->num_ate)
- return -1;
- } else
- index++; /* Try next ate */
- }
-
- return -1;
-}
-
-/*
- * free_ate_resource: Free the requested number of ATEs.
- */
-static inline void free_ate_resource(struct ate_resource *ate_resource,
- int start)
-{
- mark_ate(ate_resource, start, ate_resource->ate[start], 0);
- if ((ate_resource->lowest_free_index > start) ||
- (ate_resource->lowest_free_index < 0))
- ate_resource->lowest_free_index = start;
-}
-
-/*
- * alloc_ate_resource: Allocate the requested number of ATEs.
- */
-static inline int alloc_ate_resource(struct ate_resource *ate_resource,
- int ate_needed)
-{
- int start_index;
-
- /*
- * Check for ate exhaustion.
- */
- if (ate_resource->lowest_free_index < 0)
- return -1;
-
- /*
- * Find the required number of free consecutive ates.
- */
- start_index =
- find_free_ate(ate_resource, ate_resource->lowest_free_index,
- ate_needed);
- if (start_index >= 0)
- mark_ate(ate_resource, start_index, ate_needed, ate_needed);
-
- ate_resource->lowest_free_index =
- find_free_ate(ate_resource, ate_resource->lowest_free_index, 1);
-
- return start_index;
-}
-
-/*
- * Allocate "count" contiguous Bridge Address Translation Entries
- * on the specified bridge to be used for PCI to XTALK mappings.
- * Indices in rm map range from 1..num_entries. Indices returned
- * to caller range from 0..num_entries-1.
- *
- * Return the start index on success, -1 on failure.
- */
-int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
-{
- int status;
- unsigned long flags;
-
- spin_lock_irqsave(&pcibus_info->pbi_lock, flags);
- status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count);
- spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags);
-
- return status;
-}
-
-/*
- * Setup an Address Translation Entry as specified. Use either the Bridge
- * internal maps or the external map RAM, as appropriate.
- */
-static inline u64 __iomem *pcibr_ate_addr(struct pcibus_info *pcibus_info,
- int ate_index)
-{
- if (ate_index < pcibus_info->pbi_int_ate_size) {
- return pcireg_int_ate_addr(pcibus_info, ate_index);
- }
- panic("pcibr_ate_addr: invalid ate_index 0x%x", ate_index);
-}
-
-/*
- * Update the ate.
- */
-inline void
-ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
- volatile u64 ate)
-{
- while (count-- > 0) {
- if (ate_index < pcibus_info->pbi_int_ate_size) {
- pcireg_int_ate_set(pcibus_info, ate_index, ate);
- } else {
- panic("ate_write: invalid ate_index 0x%x", ate_index);
- }
- ate_index++;
- ate += IOPGSIZE;
- }
-
- pcireg_tflush_get(pcibus_info); /* wait until Bridge PIO complete */
-}
-
-void pcibr_ate_free(struct pcibus_info *pcibus_info, int index)
-{
-
- volatile u64 ate;
- int count;
- unsigned long flags;
-
- if (pcibr_invalidate_ate) {
- /* For debugging purposes, clear the valid bit in the ATE */
- ate = *pcibr_ate_addr(pcibus_info, index);
- count = pcibus_info->pbi_int_ate_resource.ate[index];
- ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V));
- }
-
- spin_lock_irqsave(&pcibus_info->pbi_lock, flags);
- free_ate_resource(&pcibus_info->pbi_int_ate_resource, index);
- spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags);
-}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
deleted file mode 100644
index 1e863b277ac9..000000000000
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ /dev/null
@@ -1,413 +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) 2001-2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/export.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pic.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/tiocp.h>
-#include "tio.h"
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-
-extern int sn_ioif_inited;
-
-/* =====================================================================
- * DMA MANAGEMENT
- *
- * The Bridge ASIC provides three methods of doing DMA: via a "direct map"
- * register available in 32-bit PCI space (which selects a contiguous 2G
- * address space on some other widget), via "direct" addressing via 64-bit
- * PCI space (all destination information comes from the PCI address,
- * including transfer attributes), and via a "mapped" region that allows
- * a bunch of different small mappings to be established with the PMU.
- *
- * For efficiency, we most prefer to use the 32bit direct mapping facility,
- * since it requires no resource allocations. The advantage of using the
- * PMU over the 64-bit direct is that single-cycle PCI addressing can be
- * used; the advantage of using 64-bit direct over PMU addressing is that
- * we do not have to allocate entries in the PMU.
- */
-
-static dma_addr_t
-pcibr_dmamap_ate32(struct pcidev_info *info,
- u64 paddr, size_t req_size, u64 flags, int dma_flags)
-{
-
- struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
- struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
- pdi_pcibus_info;
- u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info->
- pdi_linux_pcidev->devfn)) - 1;
- int ate_count;
- int ate_index;
- u64 ate_flags = flags | PCI32_ATE_V;
- u64 ate;
- u64 pci_addr;
- u64 xio_addr;
- u64 offset;
-
- /* PIC in PCI-X mode does not supports 32bit PageMap mode */
- if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) {
- return 0;
- }
-
- /* Calculate the number of ATEs needed. */
- if (!(MINIMAL_ATE_FLAG(paddr, req_size))) {
- ate_count = IOPG((IOPGSIZE - 1) /* worst case start offset */
- +req_size /* max mapping bytes */
- - 1) + 1; /* round UP */
- } else { /* assume requested target is page aligned */
- ate_count = IOPG(req_size /* max mapping bytes */
- - 1) + 1; /* round UP */
- }
-
- /* Get the number of ATEs required. */
- ate_index = pcibr_ate_alloc(pcibus_info, ate_count);
- if (ate_index < 0)
- return 0;
-
- /* In PCI-X mode, Prefetch not supported */
- if (IS_PCIX(pcibus_info))
- ate_flags &= ~(PCI32_ATE_PREF);
-
- if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS))
- xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
- else
- xio_addr = paddr;
-
- offset = IOPGOFF(xio_addr);
- ate = ate_flags | (xio_addr - offset);
-
- /* If PIC, put the targetid in the ATE */
- if (IS_PIC_SOFT(pcibus_info)) {
- ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT);
- }
-
- /*
- * If we're mapping for MSI, set the MSI bit in the ATE. If it's a
- * TIOCP based pci bus, we also need to set the PIO bit in the ATE.
- */
- if (dma_flags & SN_DMA_MSI) {
- ate |= PCI32_ATE_MSI;
- if (IS_TIOCP_SOFT(pcibus_info))
- ate |= PCI32_ATE_PIO;
- }
-
- ate_write(pcibus_info, ate_index, ate_count, ate);
-
- /*
- * Set up the DMA mapped Address.
- */
- pci_addr = PCI32_MAPPED_BASE + offset + IOPGSIZE * ate_index;
-
- /*
- * If swap was set in device in pcibr_endian_set()
- * we need to turn swapping on.
- */
- if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR)
- ATE_SWAP_ON(pci_addr);
-
-
- return pci_addr;
-}
-
-static dma_addr_t
-pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
- u64 dma_attributes, int dma_flags)
-{
- struct pcibus_info *pcibus_info = (struct pcibus_info *)
- ((info->pdi_host_pcidev_info)->pdi_pcibus_info);
- u64 pci_addr;
-
- /* Translate to Crosstalk View of Physical Address */
- if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
- pci_addr = IS_PIC_SOFT(pcibus_info) ?
- PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
- else
- pci_addr = paddr;
- pci_addr |= dma_attributes;
-
- /* Handle Bus mode */
- if (IS_PCIX(pcibus_info))
- pci_addr &= ~PCI64_ATTR_PREF;
-
- /* Handle Bridge Chipset differences */
- if (IS_PIC_SOFT(pcibus_info)) {
- pci_addr |=
- ((u64) pcibus_info->
- pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
- } else
- pci_addr |= (dma_flags & SN_DMA_MSI) ?
- TIOCP_PCI64_CMDTYPE_MSI :
- TIOCP_PCI64_CMDTYPE_MEM;
-
- /* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */
- if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn))
- pci_addr |= PCI64_ATTR_VIRTUAL;
-
- return pci_addr;
-}
-
-static dma_addr_t
-pcibr_dmatrans_direct32(struct pcidev_info * info,
- u64 paddr, size_t req_size, u64 flags, int dma_flags)
-{
- struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
- struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
- pdi_pcibus_info;
- u64 xio_addr;
-
- u64 xio_base;
- u64 offset;
- u64 endoff;
-
- if (IS_PCIX(pcibus_info)) {
- return 0;
- }
-
- if (dma_flags & SN_DMA_MSI)
- return 0;
-
- if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
- xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
- else
- xio_addr = paddr;
-
- xio_base = pcibus_info->pbi_dir_xbase;
- offset = xio_addr - xio_base;
- endoff = req_size + offset;
- if ((req_size > (1ULL << 31)) || /* Too Big */
- (xio_addr < xio_base) || /* Out of range for mappings */
- (endoff > (1ULL << 31))) { /* Too Big */
- return 0;
- }
-
- return PCI32_DIRECT_BASE | offset;
-}
-
-/*
- * Wrapper routine for freeing DMA maps
- * DMA mappings for Direct 64 and 32 do not have any DMA maps.
- */
-void
-pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
-{
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
- struct pcibus_info *pcibus_info =
- (struct pcibus_info *)pcidev_info->pdi_pcibus_info;
-
- if (IS_PCI32_MAPPED(dma_handle)) {
- int ate_index;
-
- ate_index =
- IOPG((ATE_SWAP_OFF(dma_handle) - PCI32_MAPPED_BASE));
- pcibr_ate_free(pcibus_info, ate_index);
- }
-}
-
-/*
- * On SN systems there is a race condition between a PIO read response and
- * DMA's. In rare cases, the read response may beat the DMA, causing the
- * driver to think that data in memory is complete and meaningful. This code
- * eliminates that race. This routine is called by the PIO read routines
- * after doing the read. For PIC this routine then forces a fake interrupt
- * on another line, which is logically associated with the slot that the PIO
- * is addressed to. It then spins while watching the memory location that
- * the interrupt is targeted to. When the interrupt response arrives, we
- * are sure that the DMA has landed in memory and it is safe for the driver
- * to proceed. For TIOCP use the Device(x) Write Request Buffer Flush
- * Bridge register since it ensures the data has entered the coherence domain,
- * unlike the PIC Device(x) Write Request Buffer Flush register.
- */
-
-void sn_dma_flush(u64 addr)
-{
- nasid_t nasid;
- int is_tio;
- int wid_num;
- int i, j;
- unsigned long flags;
- u64 itte;
- struct hubdev_info *hubinfo;
- struct sn_flush_device_kernel *p;
- struct sn_flush_device_common *common;
- struct sn_flush_nasid_entry *flush_nasid_list;
-
- if (!sn_ioif_inited)
- return;
-
- nasid = NASID_GET(addr);
- if (-1 == nasid_to_cnodeid(nasid))
- return;
-
- hubinfo = (NODEPDA(nasid_to_cnodeid(nasid)))->pdinfo;
-
- BUG_ON(!hubinfo);
-
- flush_nasid_list = &hubinfo->hdi_flush_nasid_list;
- if (flush_nasid_list->widget_p == NULL)
- return;
-
- is_tio = (nasid & 1);
- if (is_tio) {
- int itte_index;
-
- if (TIO_HWIN(addr))
- itte_index = 0;
- else if (TIO_BWIN_WINDOWNUM(addr))
- itte_index = TIO_BWIN_WINDOWNUM(addr);
- else
- itte_index = -1;
-
- if (itte_index >= 0) {
- itte = flush_nasid_list->iio_itte[itte_index];
- if (! TIO_ITTE_VALID(itte))
- return;
- wid_num = TIO_ITTE_WIDGET(itte);
- } else
- wid_num = TIO_SWIN_WIDGETNUM(addr);
- } else {
- if (BWIN_WINDOWNUM(addr)) {
- itte = flush_nasid_list->iio_itte[BWIN_WINDOWNUM(addr)];
- wid_num = IIO_ITTE_WIDGET(itte);
- } else
- wid_num = SWIN_WIDGETNUM(addr);
- }
- if (flush_nasid_list->widget_p[wid_num] == NULL)
- return;
- p = &flush_nasid_list->widget_p[wid_num][0];
-
- /* find a matching BAR */
- for (i = 0; i < DEV_PER_WIDGET; i++,p++) {
- common = p->common;
- for (j = 0; j < PCI_ROM_RESOURCE; j++) {
- if (common->sfdl_bar_list[j].start == 0)
- break;
- if (addr >= common->sfdl_bar_list[j].start
- && addr <= common->sfdl_bar_list[j].end)
- break;
- }
- if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0)
- break;
- }
-
- /* if no matching BAR, return without doing anything. */
- if (i == DEV_PER_WIDGET)
- return;
-
- /*
- * For TIOCP use the Device(x) Write Request Buffer Flush Bridge
- * register since it ensures the data has entered the coherence
- * domain, unlike PIC.
- */
- if (is_tio) {
- /*
- * Note: devices behind TIOCE should never be matched in the
- * above code, and so the following code is PIC/CP centric.
- * If CE ever needs the sn_dma_flush mechanism, we will have
- * to account for that here and in tioce_bus_fixup().
- */
- u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
- u32 revnum = XWIDGET_PART_REV_NUM(tio_id);
-
- /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */
- if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) {
- return;
- } else {
- pcireg_wrb_flush_get(common->sfdl_pcibus_info,
- (common->sfdl_slot - 1));
- }
- } else {
- spin_lock_irqsave(&p->sfdl_flush_lock, flags);
- *common->sfdl_flush_addr = 0;
-
- /* force an interrupt. */
- *(volatile u32 *)(common->sfdl_force_int_addr) = 1;
-
- /* wait for the interrupt to come back. */
- while (*(common->sfdl_flush_addr) != 0x10f)
- cpu_relax();
-
- /* okay, everything is synched up. */
- spin_unlock_irqrestore(&p->sfdl_flush_lock, flags);
- }
- return;
-}
-
-/*
- * DMA interfaces. Called from pci_dma.c routines.
- */
-
-dma_addr_t
-pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags)
-{
- dma_addr_t dma_handle;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
-
- /* SN cannot support DMA addresses smaller than 32 bits. */
- if (hwdev->dma_mask < 0x7fffffff) {
- return 0;
- }
-
- if (hwdev->dma_mask == ~0UL) {
- /*
- * Handle the most common case: 64 bit cards. This
- * call should always succeed.
- */
-
- dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_PREF, dma_flags);
- } else {
- /* Handle 32-63 bit cards via direct mapping */
- dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
- size, 0, dma_flags);
- if (!dma_handle) {
- /*
- * It is a 32 bit card and we cannot do direct mapping,
- * so we use an ATE.
- */
-
- dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
- size, PCI32_ATE_PREF,
- dma_flags);
- }
- }
-
- return dma_handle;
-}
-
-dma_addr_t
-pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
- size_t size, int dma_flags)
-{
- dma_addr_t dma_handle;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
-
- if (hwdev->dev.coherent_dma_mask == ~0UL) {
- dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_BAR, dma_flags);
- } else {
- dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
- phys_addr, size,
- PCI32_ATE_BAR, dma_flags);
- }
-
- return dma_handle;
-}
-
-EXPORT_SYMBOL(sn_dma_flush);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
deleted file mode 100644
index 7195df1da121..000000000000
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ /dev/null
@@ -1,265 +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) 2001-2004, 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/export.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/pic.h>
-#include <asm/sn/sn2/sn_hwperf.h>
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
-
-int
-sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp,
- char **ssdt)
-{
- struct ia64_sal_retval ret_stuff;
- u64 busnum;
- u64 segment;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- segment = soft->pbi_buscommon.bs_persist_segment;
- busnum = soft->pbi_buscommon.bs_persist_busnum;
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
- busnum, (u64) device, (u64) resp, (u64)ia64_tpa(ssdt),
- 0, 0);
-
- return (int)ret_stuff.v0;
-}
-
-int
-sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
- void *resp)
-{
- struct ia64_sal_retval ret_stuff;
- u64 busnum;
- u64 segment;
-
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- segment = soft->pbi_buscommon.bs_persist_segment;
- busnum = soft->pbi_buscommon.bs_persist_busnum;
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
- segment, busnum, (u64) device, (u64) action,
- (u64) resp, 0, 0);
-
- return (int)ret_stuff.v0;
-}
-
-static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
-{
- struct ia64_sal_retval ret_stuff;
- u64 busnum;
- int segment;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- segment = soft->pbi_buscommon.bs_persist_segment;
- busnum = soft->pbi_buscommon.bs_persist_busnum;
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
- (u64) segment, (u64) busnum, 0, 0, 0, 0, 0);
-
- return (int)ret_stuff.v0;
-}
-
-u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
-{
- long rc;
- u16 uninitialized_var(ioboard); /* GCC be quiet */
- nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
-
- rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard);
- if (rc) {
- printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
- rc);
- return 0;
- }
-
- return ioboard;
-}
-
-/*
- * PCI Bridge Error interrupt handler. Gets invoked whenever a PCI
- * bridge sends an error interrupt.
- */
-static irqreturn_t
-pcibr_error_intr_handler(int irq, void *arg)
-{
- struct pcibus_info *soft = arg;
-
- if (sal_pcibr_error_interrupt(soft) < 0)
- panic("pcibr_error_intr_handler(): Fatal Bridge Error");
-
- return IRQ_HANDLED;
-}
-
-void *
-pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
-{
- int nasid, cnode, j;
- struct hubdev_info *hubdev_info;
- struct pcibus_info *soft;
- struct sn_flush_device_kernel *sn_flush_device_kernel;
- struct sn_flush_device_common *common;
-
- if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) {
- return NULL;
- }
-
- /*
- * Allocate kernel bus soft and copy from prom.
- */
-
- soft = kmemdup(prom_bussoft, sizeof(struct pcibus_info), GFP_KERNEL);
- if (!soft) {
- return NULL;
- }
-
- soft->pbi_buscommon.bs_base = (unsigned long)
- ioremap(REGION_OFFSET(soft->pbi_buscommon.bs_base),
- sizeof(struct pic));
-
- spin_lock_init(&soft->pbi_lock);
-
- /*
- * register the bridge's error interrupt handler
- */
- if (request_irq(SGI_PCIASIC_ERROR, pcibr_error_intr_handler,
- IRQF_SHARED, "PCIBR error", (void *)(soft))) {
- printk(KERN_WARNING
- "pcibr cannot allocate interrupt for error handler\n");
- }
- irq_set_handler(SGI_PCIASIC_ERROR, handle_level_irq);
- sn_set_err_irq_affinity(SGI_PCIASIC_ERROR);
-
- /*
- * Update the Bridge with the "kernel" pagesize
- */
- if (PAGE_SIZE < 16384) {
- pcireg_control_bit_clr(soft, PCIBR_CTRL_PAGE_SIZE);
- } else {
- pcireg_control_bit_set(soft, PCIBR_CTRL_PAGE_SIZE);
- }
-
- nasid = NASID_GET(soft->pbi_buscommon.bs_base);
- cnode = nasid_to_cnodeid(nasid);
- hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
-
- if (hubdev_info->hdi_flush_nasid_list.widget_p) {
- sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list.
- widget_p[(int)soft->pbi_buscommon.bs_xid];
- if (sn_flush_device_kernel) {
- for (j = 0; j < DEV_PER_WIDGET;
- j++, sn_flush_device_kernel++) {
- common = sn_flush_device_kernel->common;
- if (common->sfdl_slot == -1)
- continue;
- if ((common->sfdl_persistent_segment ==
- soft->pbi_buscommon.bs_persist_segment) &&
- (common->sfdl_persistent_busnum ==
- soft->pbi_buscommon.bs_persist_busnum))
- common->sfdl_pcibus_info =
- soft;
- }
- }
- }
-
- /* Setup the PMU ATE map */
- soft->pbi_int_ate_resource.lowest_free_index = 0;
- soft->pbi_int_ate_resource.ate =
- kcalloc(soft->pbi_int_ate_size, sizeof(u64), GFP_KERNEL);
-
- if (!soft->pbi_int_ate_resource.ate) {
- kfree(soft);
- return NULL;
- }
-
- return soft;
-}
-
-void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
-{
- struct pcidev_info *pcidev_info;
- struct pcibus_info *pcibus_info;
- int bit = sn_irq_info->irq_int_bit;
-
- if (! sn_irq_info->irq_bridge)
- return;
-
- pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- if (pcidev_info) {
- pcibus_info =
- (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info->
- pdi_pcibus_info;
- pcireg_force_intr_set(pcibus_info, bit);
- }
-}
-
-void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
-{
- struct pcidev_info *pcidev_info;
- struct pcibus_info *pcibus_info;
- int bit = sn_irq_info->irq_int_bit;
- u64 xtalk_addr = sn_irq_info->irq_xtalkaddr;
-
- pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- if (pcidev_info) {
- pcibus_info =
- (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info->
- pdi_pcibus_info;
-
- /* Disable the device's IRQ */
- pcireg_intr_enable_bit_clr(pcibus_info, (1 << bit));
-
- /* Change the device's IRQ */
- pcireg_intr_addr_addr_set(pcibus_info, bit, xtalk_addr);
-
- /* Re-enable the device's IRQ */
- pcireg_intr_enable_bit_set(pcibus_info, (1 << bit));
-
- pcibr_force_interrupt(sn_irq_info);
- }
-}
-
-/*
- * Provider entries for PIC/CP
- */
-
-struct sn_pcibus_provider pcibr_provider = {
- .dma_map = pcibr_dma_map,
- .dma_map_consistent = pcibr_dma_map_consistent,
- .dma_unmap = pcibr_dma_unmap,
- .bus_fixup = pcibr_bus_fixup,
- .force_interrupt = pcibr_force_interrupt,
- .target_interrupt = pcibr_target_interrupt
-};
-
-int
-pcibr_init_provider(void)
-{
- sn_pci_provider[PCIIO_ASIC_TYPE_PIC] = &pcibr_provider;
- sn_pci_provider[PCIIO_ASIC_TYPE_TIOCP] = &pcibr_provider;
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable);
-EXPORT_SYMBOL_GPL(sal_pcibr_slot_disable);
-EXPORT_SYMBOL_GPL(sn_ioboard_to_pci_bus);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
deleted file mode 100644
index 8b8bbd51d433..000000000000
--- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c
+++ /dev/null
@@ -1,285 +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) 2004 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <asm/sn/io.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pic.h>
-#include <asm/sn/tiocp.h>
-
-union br_ptr {
- struct tiocp tio;
- struct pic pic;
-};
-
-/*
- * Control Register Access -- Read/Write 0000_0020
- */
-void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- __sn_clrq_relaxed(&ptr->tio.cp_control, bits);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- __sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
- break;
- default:
- panic
- ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- __sn_setq_relaxed(&ptr->tio.cp_control, bits);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- __sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
- break;
- default:
- panic
- ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-/*
- * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050
- */
-u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- u64 ret = 0;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
- break;
- default:
- panic
- ("pcireg_tflush_get: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-
- /* Read of the Target Flush should always return zero */
- if (ret != 0)
- panic("pcireg_tflush_get:Target Flush failed\n");
-
- return ret;
-}
-
-/*
- * Interrupt Status Register Access -- Read Only 0000_0100
- */
-u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- u64 ret = 0;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
- break;
- default:
- panic
- ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
- return ret;
-}
-
-/*
- * Interrupt Enable Register Access -- Read/Write 0000_0108
- */
-void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- __sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- __sn_clrq_relaxed(&ptr->pic.p_int_enable, bits);
- break;
- default:
- panic
- ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- __sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- __sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
- break;
- default:
- panic
- ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-/*
- * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168
- */
-void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
- u64 addr)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- __sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
- TIOCP_HOST_INTR_ADDR);
- __sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
- (addr & TIOCP_HOST_INTR_ADDR));
- break;
- case PCIBR_BRIDGETYPE_PIC:
- __sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
- PIC_HOST_INTR_ADDR);
- __sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
- (addr & PIC_HOST_INTR_ADDR));
- break;
- default:
- panic
- ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-/*
- * Force Interrupt Register Access -- Write Only 0000_01C0 - 0000_01F8
- */
-void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- writeq(1, &ptr->tio.cp_force_pin[int_n]);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- writeq(1, &ptr->pic.p_force_pin[int_n]);
- break;
- default:
- panic
- ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-/*
- * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
- */
-u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- u64 ret = 0;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- ret =
- __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- ret =
- __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
- break;
- default:
- panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr);
- }
-
- }
- /* Read of the Write Buffer Flush should always return zero */
- return ret;
-}
-
-void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
- u64 val)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]);
- break;
- case PCIBR_BRIDGETYPE_PIC:
- writeq(val, &ptr->pic.p_int_ate_ram[ate_index]);
- break;
- default:
- panic
- ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
-}
-
-u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
-{
- union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- u64 __iomem *ret = NULL;
-
- if (pcibus_info) {
- switch (pcibus_info->pbi_bridge_type) {
- case PCIBR_BRIDGETYPE_TIOCP:
- ret = &ptr->tio.cp_int_ate_ram[ate_index];
- break;
- case PCIBR_BRIDGETYPE_PIC:
- ret = &ptr->pic.p_int_ate_ram[ate_index];
- break;
- default:
- panic
- ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p",
- ptr);
- }
- }
- return ret;
-}
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
deleted file mode 100644
index a70b11fd57d6..000000000000
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ /dev/null
@@ -1,677 +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) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/io.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/tioca_provider.h>
-
-u32 tioca_gart_found;
-EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */
-
-LIST_HEAD(tioca_list);
-EXPORT_SYMBOL(tioca_list); /* used by agp-sgi */
-
-static int tioca_gart_init(struct tioca_kernel *);
-
-/**
- * tioca_gart_init - Initialize SGI TIOCA GART
- * @tioca_common: ptr to common prom/kernel struct identifying the
- *
- * If the indicated tioca has devices present, initialize its associated
- * GART MMR's and kernel memory.
- */
-static int
-tioca_gart_init(struct tioca_kernel *tioca_kern)
-{
- u64 ap_reg;
- u64 offset;
- struct page *tmp;
- struct tioca_common *tioca_common;
- struct tioca __iomem *ca_base;
-
- tioca_common = tioca_kern->ca_common;
- ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
-
- if (list_empty(tioca_kern->ca_devices))
- return 0;
-
- ap_reg = 0;
-
- /*
- * Validate aperature size
- */
-
- switch (CA_APERATURE_SIZE >> 20) {
- case 4:
- ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT); /* 4MB */
- break;
- case 8:
- ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT); /* 8MB */
- break;
- case 16:
- ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT); /* 16MB */
- break;
- case 32:
- ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT); /* 32 MB */
- break;
- case 64:
- ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT); /* 64 MB */
- break;
- case 128:
- ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT); /* 128 MB */
- break;
- case 256:
- ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT); /* 256 MB */
- break;
- case 512:
- ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT); /* 512 MB */
- break;
- case 1024:
- ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT); /* 1GB */
- break;
- case 2048:
- ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT); /* 2GB */
- break;
- case 4096:
- ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT); /* 4 GB */
- break;
- default:
- printk(KERN_ERR "%s: Invalid CA_APERATURE_SIZE "
- "0x%lx\n", __func__, (ulong) CA_APERATURE_SIZE);
- return -1;
- }
-
- /*
- * Set up other aperature parameters
- */
-
- if (PAGE_SIZE >= 16384) {
- tioca_kern->ca_ap_pagesize = 16384;
- ap_reg |= CA_GART_PAGE_SIZE;
- } else {
- tioca_kern->ca_ap_pagesize = 4096;
- }
-
- tioca_kern->ca_ap_size = CA_APERATURE_SIZE;
- tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE;
- tioca_kern->ca_gart_entries =
- tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize;
-
- ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI);
- ap_reg |= tioca_kern->ca_ap_bus_base;
-
- /*
- * Allocate and set up the GART
- */
-
- tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64);
- tmp =
- alloc_pages_node(tioca_kern->ca_closest_node,
- GFP_KERNEL | __GFP_ZERO,
- get_order(tioca_kern->ca_gart_size));
-
- if (!tmp) {
- printk(KERN_ERR "%s: Could not allocate "
- "%llu bytes (order %d) for GART\n",
- __func__,
- tioca_kern->ca_gart_size,
- get_order(tioca_kern->ca_gart_size));
- return -ENOMEM;
- }
-
- tioca_kern->ca_gart = page_address(tmp);
- tioca_kern->ca_gart_coretalk_addr =
- PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart));
-
- /*
- * Compute PCI/AGP convenience fields
- */
-
- offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE;
- tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE;
- tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE;
- tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize;
- tioca_kern->ca_pcigart_base =
- tioca_kern->ca_gart_coretalk_addr + offset;
- tioca_kern->ca_pcigart =
- &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start];
- tioca_kern->ca_pcigart_entries =
- tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
- tioca_kern->ca_pcigart_pagemap =
- kzalloc(tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
- if (!tioca_kern->ca_pcigart_pagemap) {
- free_pages((unsigned long)tioca_kern->ca_gart,
- get_order(tioca_kern->ca_gart_size));
- return -1;
- }
-
- offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE;
- tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE;
- tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE;
- tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize;
- tioca_kern->ca_gfxgart_base =
- tioca_kern->ca_gart_coretalk_addr + offset;
- tioca_kern->ca_gfxgart =
- &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start];
- tioca_kern->ca_gfxgart_entries =
- tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize;
-
- /*
- * various control settings:
- * use agp op-combining
- * use GET semantics to fetch memory
- * participate in coherency domain
- * DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
- */
-
- __sn_setq_relaxed(&ca_base->ca_control1,
- CA_AGPDMA_OP_ENB_COMBDELAY); /* PV895469 ? */
- __sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
- __sn_setq_relaxed(&ca_base->ca_control2,
- (0x2ull << CA_GART_MEM_PARAM_SHFT));
- tioca_kern->ca_gart_iscoherent = 1;
- __sn_clrq_relaxed(&ca_base->ca_control2,
- (CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB));
-
- /*
- * Unmask GART fetch error interrupts. Clear residual errors first.
- */
-
- writeq(CA_GART_FETCH_ERR, &ca_base->ca_int_status_alias);
- writeq(CA_GART_FETCH_ERR, &ca_base->ca_mult_error_alias);
- __sn_clrq_relaxed(&ca_base->ca_int_mask, CA_GART_FETCH_ERR);
-
- /*
- * Program the aperature and gart registers in TIOCA
- */
-
- writeq(ap_reg, &ca_base->ca_gart_aperature);
- writeq(tioca_kern->ca_gart_coretalk_addr|1, &ca_base->ca_gart_ptr_table);
-
- return 0;
-}
-
-/**
- * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions
- * @tioca_kernel: structure representing the CA
- *
- * Given a CA, scan all attached functions making sure they all support
- * FastWrite. If so, enable FastWrite for all functions and the CA itself.
- */
-
-void
-tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
-{
- int cap_ptr;
- u32 reg;
- struct tioca __iomem *tioca_base;
- struct pci_dev *pdev;
- struct tioca_common *common;
-
- common = tioca_kern->ca_common;
-
- /*
- * Scan all vga controllers on this bus making sure they all
- * support FW. If not, return.
- */
-
- list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
- if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
- continue;
-
- cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
- if (!cap_ptr)
- return; /* no AGP CAP means no FW */
-
- pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, &reg);
- if (!(reg & PCI_AGP_STATUS_FW))
- return; /* function doesn't support FW */
- }
-
- /*
- * Set fw for all vga fn's
- */
-
- list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
- if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
- continue;
-
- cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
- pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, &reg);
- reg |= PCI_AGP_COMMAND_FW;
- pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg);
- }
-
- /*
- * Set ca's fw to match
- */
-
- tioca_base = (struct tioca __iomem*)common->ca_common.bs_base;
- __sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);
-}
-
-EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
-
-/**
- * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode
- * @paddr: system physical address
- *
- * Map @paddr into 64-bit CA bus space. No device context is necessary.
- * Bits 53:0 come from the coretalk address. We just need to mask in the
- * following optional bits of the 64-bit pci address:
- *
- * 63:60 - Coretalk Packet Type - 0x1 for Mem Get/Put (coherent)
- * 0x2 for PIO (non-coherent)
- * We will always use 0x1
- * 55:55 - Swap bytes Currently unused
- */
-static u64
-tioca_dma_d64(unsigned long paddr)
-{
- dma_addr_t bus_addr;
-
- bus_addr = PHYS_TO_TIODMA(paddr);
-
- BUG_ON(!bus_addr);
- BUG_ON(bus_addr >> 54);
-
- /* Set upper nibble to Cache Coherent Memory op */
- bus_addr |= (1UL << 60);
-
- return bus_addr;
-}
-
-/**
- * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode
- * @pdev: linux pci_dev representing the function
- * @paddr: system physical address
- *
- * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info.
- *
- * The CA agp 48 bit direct address falls out as follows:
- *
- * When direct mapping AGP addresses, the 48 bit AGP address is
- * constructed as follows:
- *
- * [47:40] - Low 8 bits of the page Node ID extracted from coretalk
- * address [47:40]. The upper 8 node bits are fixed
- * and come from the xxx register bits [5:0]
- * [39:38] - Chiplet ID extracted from coretalk address [39:38]
- * [37:00] - node offset extracted from coretalk address [37:00]
- *
- * Since the node id in general will be non-zero, and the chiplet id
- * will always be non-zero, it follows that the device must support
- * a dma mask of at least 0xffffffffff (40 bits) to target node 0
- * and in general should be 0xffffffffffff (48 bits) to target nodes
- * up to 255. Nodes above 255 need the support of the xxx register,
- * and so a given CA can only directly target nodes in the range
- * xxx - xxx+255.
- */
-static u64
-tioca_dma_d48(struct pci_dev *pdev, u64 paddr)
-{
- struct tioca_common *tioca_common;
- struct tioca __iomem *ca_base;
- u64 ct_addr;
- dma_addr_t bus_addr;
- u32 node_upper;
- u64 agp_dma_extn;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
-
- tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
- ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
-
- ct_addr = PHYS_TO_TIODMA(paddr);
- if (!ct_addr)
- return 0;
-
- bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffffUL);
- node_upper = ct_addr >> 48;
-
- if (node_upper > 64) {
- printk(KERN_ERR "%s: coretalk addr 0x%p node id out "
- "of range\n", __func__, (void *)ct_addr);
- return 0;
- }
-
- agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
- if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
- printk(KERN_ERR "%s: coretalk upper node (%u) "
- "mismatch with ca_agp_dma_addr_extn (%llu)\n",
- __func__,
- node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
- return 0;
- }
-
- return bus_addr;
-}
-
-/**
- * tioca_dma_mapped - create a DMA mapping using a CA GART
- * @pdev: linux pci_dev representing the function
- * @paddr: host physical address to map
- * @req_size: len (bytes) to map
- *
- * Map @paddr into CA address space using the GART mechanism. The mapped
- * dma_addr_t is guaranteed to be contiguous in CA bus space.
- */
-static dma_addr_t
-tioca_dma_mapped(struct pci_dev *pdev, unsigned long paddr, size_t req_size)
-{
- int ps, ps_shift, entry, entries, mapsize;
- u64 xio_addr, end_xio_addr;
- struct tioca_common *tioca_common;
- struct tioca_kernel *tioca_kern;
- dma_addr_t bus_addr = 0;
- struct tioca_dmamap *ca_dmamap;
- void *map;
- unsigned long flags;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
-
- tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
- tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
-
- xio_addr = PHYS_TO_TIODMA(paddr);
- if (!xio_addr)
- return 0;
-
- spin_lock_irqsave(&tioca_kern->ca_lock, flags);
-
- /*
- * allocate a map struct
- */
-
- ca_dmamap = kzalloc(sizeof(struct tioca_dmamap), GFP_ATOMIC);
- if (!ca_dmamap)
- goto map_return;
-
- /*
- * Locate free entries that can hold req_size. Account for
- * unaligned start/length when allocating.
- */
-
- ps = tioca_kern->ca_ap_pagesize; /* will be power of 2 */
- ps_shift = ffs(ps) - 1;
- end_xio_addr = xio_addr + req_size - 1;
-
- entries = (end_xio_addr >> ps_shift) - (xio_addr >> ps_shift) + 1;
-
- map = tioca_kern->ca_pcigart_pagemap;
- mapsize = tioca_kern->ca_pcigart_entries;
-
- entry = bitmap_find_next_zero_area(map, mapsize, 0, entries, 0);
- if (entry >= mapsize) {
- kfree(ca_dmamap);
- goto map_return;
- }
-
- bitmap_set(map, entry, entries);
-
- bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
-
- ca_dmamap->cad_dma_addr = bus_addr;
- ca_dmamap->cad_gart_size = entries;
- ca_dmamap->cad_gart_entry = entry;
- list_add(&ca_dmamap->cad_list, &tioca_kern->ca_dmamaps);
-
- if (xio_addr % ps) {
- tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
- bus_addr += xio_addr & (ps - 1);
- xio_addr &= ~(ps - 1);
- xio_addr += ps;
- entry++;
- }
-
- while (xio_addr < end_xio_addr) {
- tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
- xio_addr += ps;
- entry++;
- }
-
- tioca_tlbflush(tioca_kern);
-
-map_return:
- spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
- return bus_addr;
-}
-
-/**
- * tioca_dma_unmap - release CA mapping resources
- * @pdev: linux pci_dev representing the function
- * @bus_addr: bus address returned by an earlier tioca_dma_map
- * @dir: mapping direction (unused)
- *
- * Locate mapping resources associated with @bus_addr and release them.
- * For mappings created using the direct modes (64 or 48) there are no
- * resources to release.
- */
-static void
-tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
-{
- int i, entry;
- struct tioca_common *tioca_common;
- struct tioca_kernel *tioca_kern;
- struct tioca_dmamap *map;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
- unsigned long flags;
-
- tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
- tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
-
- /* return straight away if this isn't be a mapped address */
-
- if (bus_addr < tioca_kern->ca_pciap_base ||
- bus_addr >= (tioca_kern->ca_pciap_base + tioca_kern->ca_pciap_size))
- return;
-
- spin_lock_irqsave(&tioca_kern->ca_lock, flags);
-
- list_for_each_entry(map, &tioca_kern->ca_dmamaps, cad_list)
- if (map->cad_dma_addr == bus_addr)
- break;
-
- BUG_ON(map == NULL);
-
- entry = map->cad_gart_entry;
-
- for (i = 0; i < map->cad_gart_size; i++, entry++) {
- clear_bit(entry, tioca_kern->ca_pcigart_pagemap);
- tioca_kern->ca_pcigart[entry] = 0;
- }
- tioca_tlbflush(tioca_kern);
-
- list_del(&map->cad_list);
- spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
- kfree(map);
-}
-
-/**
- * tioca_dma_map - map pages for PCI DMA
- * @pdev: linux pci_dev representing the function
- * @paddr: host physical address to map
- * @byte_count: bytes to map
- *
- * This is the main wrapper for mapping host physical pages to CA PCI space.
- * The mapping mode used is based on the devices dma_mask. As a last resort
- * use the GART mapped mode.
- */
-static u64
-tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
-{
- u64 mapaddr;
-
- /*
- * Not supported for now ...
- */
- if (dma_flags & SN_DMA_MSI)
- return 0;
-
- /*
- * If card is 64 or 48 bit addressable, use a direct mapping. 32
- * bit direct is so restrictive w.r.t. where the memory resides that
- * we don't use it even though CA has some support.
- */
-
- if (pdev->dma_mask == ~0UL)
- mapaddr = tioca_dma_d64(paddr);
- else if (pdev->dma_mask == 0xffffffffffffUL)
- mapaddr = tioca_dma_d48(pdev, paddr);
- else
- mapaddr = 0;
-
- /* Last resort ... use PCI portion of CA GART */
-
- if (mapaddr == 0)
- mapaddr = tioca_dma_mapped(pdev, paddr, byte_count);
-
- return mapaddr;
-}
-
-/**
- * tioca_error_intr_handler - SGI TIO CA error interrupt handler
- * @irq: unused
- * @arg: pointer to tioca_common struct for the given CA
- *
- * Handle a CA error interrupt. Simply a wrapper around a SAL call which
- * defers processing to the SGI prom.
- */
-static irqreturn_t
-tioca_error_intr_handler(int irq, void *arg)
-{
- struct tioca_common *soft = arg;
- struct ia64_sal_retval ret_stuff;
- u64 segment;
- u64 busnum;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- segment = soft->ca_common.bs_persist_segment;
- busnum = soft->ca_common.bs_persist_busnum;
-
- SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
- segment, busnum, 0, 0, 0, 0, 0);
-
- return IRQ_HANDLED;
-}
-
-/**
- * tioca_bus_fixup - perform final PCI fixup for a TIO CA bus
- * @prom_bussoft: Common prom/kernel struct representing the bus
- *
- * Replicates the tioca_common pointed to by @prom_bussoft in kernel
- * space. Allocates and initializes a kernel-only area for a given CA,
- * and sets up an irq for handling CA error interrupts.
- *
- * On successful setup, returns the kernel version of tioca_common back to
- * the caller.
- */
-static void *
-tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
-{
- struct tioca_common *tioca_common;
- struct tioca_kernel *tioca_kern;
- struct pci_bus *bus;
-
- /* sanity check prom rev */
-
- if (is_shub1() && sn_sal_rev() < 0x0406) {
- printk
- (KERN_ERR "%s: SGI prom rev 4.06 or greater required "
- "for tioca support\n", __func__);
- return NULL;
- }
-
- /*
- * Allocate kernel bus soft and copy from prom.
- */
-
- tioca_common = kmemdup(prom_bussoft, sizeof(struct tioca_common),
- GFP_KERNEL);
- if (!tioca_common)
- return NULL;
-
- tioca_common->ca_common.bs_base = (unsigned long)
- ioremap(REGION_OFFSET(tioca_common->ca_common.bs_base),
- sizeof(struct tioca_common));
-
- /* init kernel-private area */
-
- tioca_kern = kzalloc(sizeof(struct tioca_kernel), GFP_KERNEL);
- if (!tioca_kern) {
- kfree(tioca_common);
- return NULL;
- }
-
- tioca_kern->ca_common = tioca_common;
- spin_lock_init(&tioca_kern->ca_lock);
- INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
- tioca_kern->ca_closest_node =
- nasid_to_cnodeid(tioca_common->ca_closest_nasid);
- tioca_common->ca_kernel_private = (u64) tioca_kern;
-
- bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
- tioca_common->ca_common.bs_persist_busnum);
- BUG_ON(!bus);
- tioca_kern->ca_devices = &bus->devices;
-
- /* init GART */
-
- if (tioca_gart_init(tioca_kern) < 0) {
- kfree(tioca_kern);
- kfree(tioca_common);
- return NULL;
- }
-
- tioca_gart_found++;
- list_add(&tioca_kern->ca_list, &tioca_list);
-
- if (request_irq(SGI_TIOCA_ERROR,
- tioca_error_intr_handler,
- IRQF_SHARED, "TIOCA error", (void *)tioca_common))
- printk(KERN_WARNING
- "%s: Unable to get irq %d. "
- "Error interrupts won't be routed for TIOCA bus %d\n",
- __func__, SGI_TIOCA_ERROR,
- (int)tioca_common->ca_common.bs_persist_busnum);
-
- irq_set_handler(SGI_TIOCA_ERROR, handle_level_irq);
- sn_set_err_irq_affinity(SGI_TIOCA_ERROR);
-
- /* Setup locality information */
- controller->node = tioca_kern->ca_closest_node;
- return tioca_common;
-}
-
-static struct sn_pcibus_provider tioca_pci_interfaces = {
- .dma_map = tioca_dma_map,
- .dma_map_consistent = tioca_dma_map,
- .dma_unmap = tioca_dma_unmap,
- .bus_fixup = tioca_bus_fixup,
- .force_interrupt = NULL,
- .target_interrupt = NULL
-};
-
-/**
- * tioca_init_provider - init SN PCI provider ops for TIO CA
- */
-int
-tioca_init_provider(void)
-{
- sn_pci_provider[PCIIO_ASIC_TYPE_TIOCA] = &tioca_pci_interfaces;
- return 0;
-}
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
deleted file mode 100644
index 3bd9abc35485..000000000000
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ /dev/null
@@ -1,1062 +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) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/io.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/tioce_provider.h>
-
-/*
- * 1/26/2006
- *
- * WAR for SGI PV 944642. For revA TIOCE, need to use the following recipe
- * (taken from the above PV) before and after accessing tioce internal MMR's
- * to avoid tioce lockups.
- *
- * The recipe as taken from the PV:
- *
- * if(mmr address < 0x45000) {
- * if(mmr address == 0 or 0x80)
- * mmr wrt or read address 0xc0
- * else if(mmr address == 0x148 or 0x200)
- * mmr wrt or read address 0x28
- * else
- * mmr wrt or read address 0x158
- *
- * do desired mmr access (rd or wrt)
- *
- * if(mmr address == 0x100)
- * mmr wrt or read address 0x38
- * mmr wrt or read address 0xb050
- * } else
- * do desired mmr access
- *
- * According to hw, we can use reads instead of writes to the above address
- *
- * Note this WAR can only to be used for accessing internal MMR's in the
- * TIOCE Coretalk Address Range 0x0 - 0x07ff_ffff. This includes the
- * "Local CE Registers and Memories" and "PCI Compatible Config Space" address
- * spaces from table 2-1 of the "CE Programmer's Reference Overview" document.
- *
- * All registers defined in struct tioce will meet that criteria.
- */
-
-static inline void
-tioce_mmr_war_pre(struct tioce_kernel *kern, void __iomem *mmr_addr)
-{
- u64 mmr_base;
- u64 mmr_offset;
-
- if (kern->ce_common->ce_rev != TIOCE_REV_A)
- return;
-
- mmr_base = kern->ce_common->ce_pcibus.bs_base;
- mmr_offset = (unsigned long)mmr_addr - mmr_base;
-
- if (mmr_offset < 0x45000) {
- u64 mmr_war_offset;
-
- if (mmr_offset == 0 || mmr_offset == 0x80)
- mmr_war_offset = 0xc0;
- else if (mmr_offset == 0x148 || mmr_offset == 0x200)
- mmr_war_offset = 0x28;
- else
- mmr_war_offset = 0x158;
-
- readq_relaxed((void __iomem *)(mmr_base + mmr_war_offset));
- }
-}
-
-static inline void
-tioce_mmr_war_post(struct tioce_kernel *kern, void __iomem *mmr_addr)
-{
- u64 mmr_base;
- u64 mmr_offset;
-
- if (kern->ce_common->ce_rev != TIOCE_REV_A)
- return;
-
- mmr_base = kern->ce_common->ce_pcibus.bs_base;
- mmr_offset = (unsigned long)mmr_addr - mmr_base;
-
- if (mmr_offset < 0x45000) {
- if (mmr_offset == 0x100)
- readq_relaxed((void __iomem *)(mmr_base + 0x38));
- readq_relaxed((void __iomem *)(mmr_base + 0xb050));
- }
-}
-
-/* load mmr contents into a variable */
-#define tioce_mmr_load(kern, mmrp, varp) do {\
- tioce_mmr_war_pre(kern, mmrp); \
- *(varp) = readq_relaxed(mmrp); \
- tioce_mmr_war_post(kern, mmrp); \
-} while (0)
-
-/* store variable contents into mmr */
-#define tioce_mmr_store(kern, mmrp, varp) do {\
- tioce_mmr_war_pre(kern, mmrp); \
- writeq(*varp, mmrp); \
- tioce_mmr_war_post(kern, mmrp); \
-} while (0)
-
-/* store immediate value into mmr */
-#define tioce_mmr_storei(kern, mmrp, val) do {\
- tioce_mmr_war_pre(kern, mmrp); \
- writeq(val, mmrp); \
- tioce_mmr_war_post(kern, mmrp); \
-} while (0)
-
-/* set bits (immediate value) into mmr */
-#define tioce_mmr_seti(kern, mmrp, bits) do {\
- u64 tmp; \
- tioce_mmr_load(kern, mmrp, &tmp); \
- tmp |= (bits); \
- tioce_mmr_store(kern, mmrp, &tmp); \
-} while (0)
-
-/* clear bits (immediate value) into mmr */
-#define tioce_mmr_clri(kern, mmrp, bits) do { \
- u64 tmp; \
- tioce_mmr_load(kern, mmrp, &tmp); \
- tmp &= ~(bits); \
- tioce_mmr_store(kern, mmrp, &tmp); \
-} while (0)
-
-/**
- * Bus address ranges for the 5 flavors of TIOCE DMA
- */
-
-#define TIOCE_D64_MIN 0x8000000000000000UL
-#define TIOCE_D64_MAX 0xffffffffffffffffUL
-#define TIOCE_D64_ADDR(a) ((a) >= TIOCE_D64_MIN)
-
-#define TIOCE_D32_MIN 0x0000000080000000UL
-#define TIOCE_D32_MAX 0x00000000ffffffffUL
-#define TIOCE_D32_ADDR(a) ((a) >= TIOCE_D32_MIN && (a) <= TIOCE_D32_MAX)
-
-#define TIOCE_M32_MIN 0x0000000000000000UL
-#define TIOCE_M32_MAX 0x000000007fffffffUL
-#define TIOCE_M32_ADDR(a) ((a) >= TIOCE_M32_MIN && (a) <= TIOCE_M32_MAX)
-
-#define TIOCE_M40_MIN 0x0000004000000000UL
-#define TIOCE_M40_MAX 0x0000007fffffffffUL
-#define TIOCE_M40_ADDR(a) ((a) >= TIOCE_M40_MIN && (a) <= TIOCE_M40_MAX)
-
-#define TIOCE_M40S_MIN 0x0000008000000000UL
-#define TIOCE_M40S_MAX 0x000000ffffffffffUL
-#define TIOCE_M40S_ADDR(a) ((a) >= TIOCE_M40S_MIN && (a) <= TIOCE_M40S_MAX)
-
-/*
- * ATE manipulation macros.
- */
-
-#define ATE_PAGESHIFT(ps) (__ffs(ps))
-#define ATE_PAGEMASK(ps) ((ps)-1)
-
-#define ATE_PAGE(x, ps) ((x) >> ATE_PAGESHIFT(ps))
-#define ATE_NPAGES(start, len, pagesize) \
- (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
-
-#define ATE_VALID(ate) ((ate) & (1UL << 63))
-#define ATE_MAKE(addr, ps, msi) \
- (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0))
-
-/*
- * Flavors of ate-based mapping supported by tioce_alloc_map()
- */
-
-#define TIOCE_ATE_M32 1
-#define TIOCE_ATE_M40 2
-#define TIOCE_ATE_M40S 3
-
-#define KB(x) ((u64)(x) << 10)
-#define MB(x) ((u64)(x) << 20)
-#define GB(x) ((u64)(x) << 30)
-
-/**
- * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode
- * @ct_addr: system coretalk address
- *
- * Map @ct_addr into 64-bit CE bus space. No device context is necessary
- * and no CE mapping are consumed.
- *
- * Bits 53:0 come from the coretalk address. The remaining bits are set as
- * follows:
- *
- * 63 - must be 1 to indicate d64 mode to CE hardware
- * 62 - barrier bit ... controlled with tioce_dma_barrier()
- * 61 - msi bit ... specified through dma_flags
- * 60:54 - reserved, MBZ
- */
-static u64
-tioce_dma_d64(unsigned long ct_addr, int dma_flags)
-{
- u64 bus_addr;
-
- bus_addr = ct_addr | (1UL << 63);
- if (dma_flags & SN_DMA_MSI)
- bus_addr |= (1UL << 61);
-
- return bus_addr;
-}
-
-/**
- * pcidev_to_tioce - return misc ce related pointers given a pci_dev
- * @pci_dev: pci device context
- * @base: ptr to store struct tioce_mmr * for the CE holding this device
- * @kernel: ptr to store struct tioce_kernel * for the CE holding this device
- * @port: ptr to store the CE port number that this device is on
- *
- * Return pointers to various CE-related structures for the CE upstream of
- * @pci_dev.
- */
-static inline void
-pcidev_to_tioce(struct pci_dev *pdev, struct tioce __iomem **base,
- struct tioce_kernel **kernel, int *port)
-{
- struct pcidev_info *pcidev_info;
- struct tioce_common *ce_common;
- struct tioce_kernel *ce_kernel;
-
- pcidev_info = SN_PCIDEV_INFO(pdev);
- ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
- ce_kernel = (struct tioce_kernel *)ce_common->ce_kernel_private;
-
- if (base)
- *base = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
- if (kernel)
- *kernel = ce_kernel;
-
- /*
- * we use port as a zero-based value internally, even though the
- * documentation is 1-based.
- */
- if (port)
- *port =
- (pdev->bus->number < ce_kernel->ce_port1_secondary) ? 0 : 1;
-}
-
-/**
- * tioce_alloc_map - Given a coretalk address, map it to pcie bus address
- * space using one of the various ATE-based address modes.
- * @ce_kern: tioce context
- * @type: map mode to use
- * @port: 0-based port that the requesting device is downstream of
- * @ct_addr: the coretalk address to map
- * @len: number of bytes to map
- *
- * Given the addressing type, set up various parameters that define the
- * ATE pool to use. Search for a contiguous block of entries to cover the
- * length, and if enough resources exist, fill in the ATEs and construct a
- * tioce_dmamap struct to track the mapping.
- */
-static u64
-tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
- u64 ct_addr, int len, int dma_flags)
-{
- int i;
- int j;
- int first;
- int last;
- int entries;
- int nates;
- u64 pagesize;
- int msi_capable, msi_wanted;
- u64 *ate_shadow;
- u64 __iomem *ate_reg;
- u64 addr;
- struct tioce __iomem *ce_mmr;
- u64 bus_base;
- struct tioce_dmamap *map;
-
- ce_mmr = (struct tioce __iomem *)ce_kern->ce_common->ce_pcibus.bs_base;
-
- switch (type) {
- case TIOCE_ATE_M32:
- /*
- * The first 64 entries of the ate3240 pool are dedicated to
- * super-page (TIOCE_ATE_M40S) mode.
- */
- first = 64;
- entries = TIOCE_NUM_M3240_ATES - 64;
- ate_shadow = ce_kern->ce_ate3240_shadow;
- ate_reg = ce_mmr->ce_ure_ate3240;
- pagesize = ce_kern->ce_ate3240_pagesize;
- bus_base = TIOCE_M32_MIN;
- msi_capable = 1;
- break;
- case TIOCE_ATE_M40:
- first = 0;
- entries = TIOCE_NUM_M40_ATES;
- ate_shadow = ce_kern->ce_ate40_shadow;
- ate_reg = ce_mmr->ce_ure_ate40;
- pagesize = MB(64);
- bus_base = TIOCE_M40_MIN;
- msi_capable = 0;
- break;
- case TIOCE_ATE_M40S:
- /*
- * ate3240 entries 0-31 are dedicated to port1 super-page
- * mappings. ate3240 entries 32-63 are dedicated to port2.
- */
- first = port * 32;
- entries = 32;
- ate_shadow = ce_kern->ce_ate3240_shadow;
- ate_reg = ce_mmr->ce_ure_ate3240;
- pagesize = GB(16);
- bus_base = TIOCE_M40S_MIN;
- msi_capable = 0;
- break;
- default:
- return 0;
- }
-
- msi_wanted = dma_flags & SN_DMA_MSI;
- if (msi_wanted && !msi_capable)
- return 0;
-
- nates = ATE_NPAGES(ct_addr, len, pagesize);
- if (nates > entries)
- return 0;
-
- last = first + entries - nates;
- for (i = first; i <= last; i++) {
- if (ATE_VALID(ate_shadow[i]))
- continue;
-
- for (j = i; j < i + nates; j++)
- if (ATE_VALID(ate_shadow[j]))
- break;
-
- if (j >= i + nates)
- break;
- }
-
- if (i > last)
- return 0;
-
- map = kzalloc(sizeof(struct tioce_dmamap), GFP_ATOMIC);
- if (!map)
- return 0;
-
- addr = ct_addr;
- for (j = 0; j < nates; j++) {
- u64 ate;
-
- ate = ATE_MAKE(addr, pagesize, msi_wanted);
- ate_shadow[i + j] = ate;
- tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
- addr += pagesize;
- }
-
- map->refcnt = 1;
- map->nbytes = nates * pagesize;
- map->ct_start = ct_addr & ~ATE_PAGEMASK(pagesize);
- map->pci_start = bus_base + (i * pagesize);
- map->ate_hw = &ate_reg[i];
- map->ate_shadow = &ate_shadow[i];
- map->ate_count = nates;
-
- list_add(&map->ce_dmamap_list, &ce_kern->ce_dmamap_list);
-
- return (map->pci_start + (ct_addr - map->ct_start));
-}
-
-/**
- * tioce_dma_d32 - create a DMA mapping using 32-bit direct mode
- * @pdev: linux pci_dev representing the function
- * @paddr: system physical address
- *
- * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
- */
-static u64
-tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags)
-{
- int dma_ok;
- int port;
- struct tioce __iomem *ce_mmr;
- struct tioce_kernel *ce_kern;
- u64 ct_upper;
- u64 ct_lower;
- dma_addr_t bus_addr;
-
- if (dma_flags & SN_DMA_MSI)
- return 0;
-
- ct_upper = ct_addr & ~0x3fffffffUL;
- ct_lower = ct_addr & 0x3fffffffUL;
-
- pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
-
- if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
- u64 tmp;
-
- ce_kern->ce_port[port].dirmap_shadow = ct_upper;
- tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
- ct_upper);
- tmp = ce_mmr->ce_ure_dir_map[port];
- dma_ok = 1;
- } else
- dma_ok = (ce_kern->ce_port[port].dirmap_shadow == ct_upper);
-
- if (dma_ok) {
- ce_kern->ce_port[port].dirmap_refcnt++;
- bus_addr = TIOCE_D32_MIN + ct_lower;
- } else
- bus_addr = 0;
-
- return bus_addr;
-}
-
-/**
- * tioce_dma_barrier - swizzle a TIOCE bus address to include or exclude
- * the barrier bit.
- * @bus_addr: bus address to swizzle
- *
- * Given a TIOCE bus address, set the appropriate bit to indicate barrier
- * attributes.
- */
-static u64
-tioce_dma_barrier(u64 bus_addr, int on)
-{
- u64 barrier_bit;
-
- /* barrier not supported in M40/M40S mode */
- if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr))
- return bus_addr;
-
- if (TIOCE_D64_ADDR(bus_addr))
- barrier_bit = (1UL << 62);
- else /* must be m32 or d32 */
- barrier_bit = (1UL << 30);
-
- return (on) ? (bus_addr | barrier_bit) : (bus_addr & ~barrier_bit);
-}
-
-/**
- * tioce_dma_unmap - release CE mapping resources
- * @pdev: linux pci_dev representing the function
- * @bus_addr: bus address returned by an earlier tioce_dma_map
- * @dir: mapping direction (unused)
- *
- * Locate mapping resources associated with @bus_addr and release them.
- * For mappings created using the direct modes there are no resources
- * to release.
- */
-void
-tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
-{
- int i;
- int port;
- struct tioce_kernel *ce_kern;
- struct tioce __iomem *ce_mmr;
- unsigned long flags;
-
- bus_addr = tioce_dma_barrier(bus_addr, 0);
- pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
-
- /* nothing to do for D64 */
-
- if (TIOCE_D64_ADDR(bus_addr))
- return;
-
- spin_lock_irqsave(&ce_kern->ce_lock, flags);
-
- if (TIOCE_D32_ADDR(bus_addr)) {
- if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
- ce_kern->ce_port[port].dirmap_shadow = 0;
- tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
- 0);
- }
- } else {
- struct tioce_dmamap *map;
-
- list_for_each_entry(map, &ce_kern->ce_dmamap_list,
- ce_dmamap_list) {
- u64 last;
-
- last = map->pci_start + map->nbytes - 1;
- if (bus_addr >= map->pci_start && bus_addr <= last)
- break;
- }
-
- if (&map->ce_dmamap_list == &ce_kern->ce_dmamap_list) {
- printk(KERN_WARNING
- "%s: %s - no map found for bus_addr 0x%llx\n",
- __func__, pci_name(pdev), bus_addr);
- } else if (--map->refcnt == 0) {
- for (i = 0; i < map->ate_count; i++) {
- map->ate_shadow[i] = 0;
- tioce_mmr_storei(ce_kern, &map->ate_hw[i], 0);
- }
-
- list_del(&map->ce_dmamap_list);
- kfree(map);
- }
- }
-
- spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
-}
-
-/**
- * tioce_do_dma_map - map pages for PCI DMA
- * @pdev: linux pci_dev representing the function
- * @paddr: host physical address to map
- * @byte_count: bytes to map
- *
- * This is the main wrapper for mapping host physical pages to CE PCI space.
- * The mapping mode used is based on the device's dma_mask.
- */
-static u64
-tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
- int barrier, int dma_flags)
-{
- unsigned long flags;
- u64 ct_addr;
- u64 mapaddr = 0;
- struct tioce_kernel *ce_kern;
- struct tioce_dmamap *map;
- int port;
- u64 dma_mask;
-
- dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask;
-
- /* cards must be able to address at least 31 bits */
- if (dma_mask < 0x7fffffffUL)
- return 0;
-
- if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
- ct_addr = PHYS_TO_TIODMA(paddr);
- else
- ct_addr = paddr;
-
- /*
- * If the device can generate 64 bit addresses, create a D64 map.
- */
- if (dma_mask == ~0UL) {
- mapaddr = tioce_dma_d64(ct_addr, dma_flags);
- if (mapaddr)
- goto dma_map_done;
- }
-
- pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
-
- spin_lock_irqsave(&ce_kern->ce_lock, flags);
-
- /*
- * D64 didn't work ... See if we have an existing map that covers
- * this address range. Must account for devices dma_mask here since
- * an existing map might have been done in a mode using more pci
- * address bits than this device can support.
- */
- list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) {
- u64 last;
-
- last = map->ct_start + map->nbytes - 1;
- if (ct_addr >= map->ct_start &&
- ct_addr + byte_count - 1 <= last &&
- map->pci_start <= dma_mask) {
- map->refcnt++;
- mapaddr = map->pci_start + (ct_addr - map->ct_start);
- break;
- }
- }
-
- /*
- * If we don't have a map yet, and the card can generate 40
- * bit addresses, try the M40/M40S modes. Note these modes do not
- * support a barrier bit, so if we need a consistent map these
- * won't work.
- */
- if (!mapaddr && !barrier && dma_mask >= 0xffffffffffUL) {
- /*
- * We have two options for 40-bit mappings: 16GB "super" ATEs
- * and 64MB "regular" ATEs. We'll try both if needed for a
- * given mapping but which one we try first depends on the
- * size. For requests >64MB, prefer to use a super page with
- * regular as the fallback. Otherwise, try in the reverse order.
- */
-
- if (byte_count > MB(64)) {
- mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count,
- dma_flags);
- if (!mapaddr)
- mapaddr =
- tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count,
- dma_flags);
- } else {
- mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count,
- dma_flags);
- if (!mapaddr)
- mapaddr =
- tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count,
- dma_flags);
- }
- }
-
- /*
- * 32-bit direct is the next mode to try
- */
- if (!mapaddr && dma_mask >= 0xffffffffUL)
- mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags);
-
- /*
- * Last resort, try 32-bit ATE-based map.
- */
- if (!mapaddr)
- mapaddr =
- tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
- byte_count, dma_flags);
-
- spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
-
-dma_map_done:
- if (mapaddr && barrier)
- mapaddr = tioce_dma_barrier(mapaddr, 1);
-
- return mapaddr;
-}
-
-/**
- * tioce_dma - standard pci dma map interface
- * @pdev: pci device requesting the map
- * @paddr: system physical address to map into pci space
- * @byte_count: # bytes to map
- *
- * Simply call tioce_do_dma_map() to create a map with the barrier bit clear
- * in the address.
- */
-static u64
-tioce_dma(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
-{
- return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
-}
-
-/**
- * tioce_dma_consistent - consistent pci dma map interface
- * @pdev: pci device requesting the map
- * @paddr: system physical address to map into pci space
- * @byte_count: # bytes to map
- *
- * Simply call tioce_do_dma_map() to create a map with the barrier bit set
- * in the address.
- */
-static u64
-tioce_dma_consistent(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
-{
- return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
-}
-
-/**
- * tioce_error_intr_handler - SGI TIO CE error interrupt handler
- * @irq: unused
- * @arg: pointer to tioce_common struct for the given CE
- *
- * Handle a CE error interrupt. Simply a wrapper around a SAL call which
- * defers processing to the SGI prom.
- */
-static irqreturn_t
-tioce_error_intr_handler(int irq, void *arg)
-{
- struct tioce_common *soft = arg;
- struct ia64_sal_retval ret_stuff;
- ret_stuff.status = 0;
- ret_stuff.v0 = 0;
-
- SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
- soft->ce_pcibus.bs_persist_segment,
- soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0);
-
- if (ret_stuff.v0)
- panic("tioce_error_intr_handler: Fatal TIOCE error");
-
- return IRQ_HANDLED;
-}
-
-/**
- * tioce_reserve_m32 - reserve M32 ATEs for the indicated address range
- * @tioce_kernel: TIOCE context to reserve ATEs for
- * @base: starting bus address to reserve
- * @limit: last bus address to reserve
- *
- * If base/limit falls within the range of bus space mapped through the
- * M32 space, reserve the resources corresponding to the range.
- */
-static void
-tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
-{
- int ate_index, last_ate, ps;
- struct tioce __iomem *ce_mmr;
-
- ce_mmr = (struct tioce __iomem *)ce_kern->ce_common->ce_pcibus.bs_base;
- ps = ce_kern->ce_ate3240_pagesize;
- ate_index = ATE_PAGE(base, ps);
- last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1;
-
- if (ate_index < 64)
- ate_index = 64;
-
- if (last_ate >= TIOCE_NUM_M3240_ATES)
- last_ate = TIOCE_NUM_M3240_ATES - 1;
-
- while (ate_index <= last_ate) {
- u64 ate;
-
- ate = ATE_MAKE(0xdeadbeef, ps, 0);
- ce_kern->ce_ate3240_shadow[ate_index] = ate;
- tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
- ate);
- ate_index++;
- }
-}
-
-/**
- * tioce_kern_init - init kernel structures related to a given TIOCE
- * @tioce_common: ptr to a cached tioce_common struct that originated in prom
- */
-static struct tioce_kernel *
-tioce_kern_init(struct tioce_common *tioce_common)
-{
- int i;
- int ps;
- int dev;
- u32 tmp;
- unsigned int seg, bus;
- struct tioce __iomem *tioce_mmr;
- struct tioce_kernel *tioce_kern;
-
- tioce_kern = kzalloc(sizeof(struct tioce_kernel), GFP_KERNEL);
- if (!tioce_kern) {
- return NULL;
- }
-
- tioce_kern->ce_common = tioce_common;
- spin_lock_init(&tioce_kern->ce_lock);
- INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list);
- tioce_common->ce_kernel_private = (u64) tioce_kern;
-
- /*
- * Determine the secondary bus number of the port2 logical PPB.
- * This is used to decide whether a given pci device resides on
- * port1 or port2. Note: We don't have enough plumbing set up
- * here to use pci_read_config_xxx() so use raw_pci_read().
- */
-
- seg = tioce_common->ce_pcibus.bs_persist_segment;
- bus = tioce_common->ce_pcibus.bs_persist_busnum;
-
- raw_pci_read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
- tioce_kern->ce_port1_secondary = (u8) tmp;
-
- /*
- * Set PMU pagesize to the largest size available, and zero out
- * the ATEs.
- */
-
- tioce_mmr = (struct tioce __iomem *)tioce_common->ce_pcibus.bs_base;
- tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map,
- CE_URE_PAGESIZE_MASK);
- tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map,
- CE_URE_256K_PAGESIZE);
- ps = tioce_kern->ce_ate3240_pagesize = KB(256);
-
- for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
- tioce_kern->ce_ate40_shadow[i] = 0;
- tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate40[i], 0);
- }
-
- for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
- tioce_kern->ce_ate3240_shadow[i] = 0;
- tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate3240[i], 0);
- }
-
- /*
- * Reserve ATEs corresponding to reserved address ranges. These
- * include:
- *
- * Memory space covered by each PPB mem base/limit register
- * Memory space covered by each PPB prefetch base/limit register
- *
- * These bus ranges are for pio (downstream) traffic only, and so
- * cannot be used for DMA.
- */
-
- for (dev = 1; dev <= 2; dev++) {
- u64 base, limit;
-
- /* mem base/limit */
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_MEMORY_BASE, 2, &tmp);
- base = (u64)tmp << 16;
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_MEMORY_LIMIT, 2, &tmp);
- limit = (u64)tmp << 16;
- limit |= 0xfffffUL;
-
- if (base < limit)
- tioce_reserve_m32(tioce_kern, base, limit);
-
- /*
- * prefetch mem base/limit. The tioce ppb's have 64-bit
- * decoders, so read the upper portions w/o checking the
- * attributes.
- */
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_PREF_MEMORY_BASE, 2, &tmp);
- base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_PREF_BASE_UPPER32, 4, &tmp);
- base |= (u64)tmp << 32;
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_PREF_MEMORY_LIMIT, 2, &tmp);
-
- limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
- limit |= 0xfffffUL;
-
- raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
- PCI_PREF_LIMIT_UPPER32, 4, &tmp);
- limit |= (u64)tmp << 32;
-
- if ((base < limit) && TIOCE_M32_ADDR(base))
- tioce_reserve_m32(tioce_kern, base, limit);
- }
-
- return tioce_kern;
-}
-
-/**
- * tioce_force_interrupt - implement altix force_interrupt() backend for CE
- * @sn_irq_info: sn asic irq that we need an interrupt generated for
- *
- * Given an sn_irq_info struct, set the proper bit in ce_adm_force_int to
- * force a secondary interrupt to be generated. This is to work around an
- * asic issue where there is a small window of opportunity for a legacy device
- * interrupt to be lost.
- */
-static void
-tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
-{
- struct pcidev_info *pcidev_info;
- struct tioce_common *ce_common;
- struct tioce_kernel *ce_kern;
- struct tioce __iomem *ce_mmr;
- u64 force_int_val;
-
- if (!sn_irq_info->irq_bridge)
- return;
-
- if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_TIOCE)
- return;
-
- pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- if (!pcidev_info)
- return;
-
- ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
- ce_mmr = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
- ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
-
- /*
- * TIOCE Rev A workaround (PV 945826), force an interrupt by writing
- * the TIO_INTx register directly (1/26/2006)
- */
- if (ce_common->ce_rev == TIOCE_REV_A) {
- u64 int_bit_mask = (1ULL << sn_irq_info->irq_int_bit);
- u64 status;
-
- tioce_mmr_load(ce_kern, &ce_mmr->ce_adm_int_status, &status);
- if (status & int_bit_mask) {
- u64 force_irq = (1 << 8) | sn_irq_info->irq_irq;
- u64 ctalk = sn_irq_info->irq_xtalkaddr;
- u64 nasid, offset;
-
- nasid = (ctalk & CTALK_NASID_MASK) >> CTALK_NASID_SHFT;
- offset = (ctalk & CTALK_NODE_OFFSET);
- HUB_S(TIO_IOSPACE_ADDR(nasid, offset), force_irq);
- }
-
- return;
- }
-
- /*
- * irq_int_bit is originally set up by prom, and holds the interrupt
- * bit shift (not mask) as defined by the bit definitions in the
- * ce_adm_int mmr. These shifts are not the same for the
- * ce_adm_force_int register, so do an explicit mapping here to make
- * things clearer.
- */
-
- switch (sn_irq_info->irq_int_bit) {
- case CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT;
- break;
- case CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT:
- force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT;
- break;
- default:
- return;
- }
- tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_force_int, force_int_val);
-}
-
-/**
- * tioce_target_interrupt - implement set_irq_affinity for tioce resident
- * functions. Note: only applies to line interrupts, not MSI's.
- *
- * @sn_irq_info: SN IRQ context
- *
- * Given an sn_irq_info, set the associated CE device's interrupt destination
- * register. Since the interrupt destination registers are on a per-ce-slot
- * basis, this will retarget line interrupts for all functions downstream of
- * the slot.
- */
-static void
-tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
-{
- struct pcidev_info *pcidev_info;
- struct tioce_common *ce_common;
- struct tioce_kernel *ce_kern;
- struct tioce __iomem *ce_mmr;
- int bit;
- u64 vector;
-
- pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- if (!pcidev_info)
- return;
-
- ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
- ce_mmr = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
- ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
-
- bit = sn_irq_info->irq_int_bit;
-
- tioce_mmr_seti(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
- vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
- vector |= sn_irq_info->irq_xtalkaddr;
- tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_int_dest[bit], vector);
- tioce_mmr_clri(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
-
- tioce_force_interrupt(sn_irq_info);
-}
-
-/**
- * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
- * @prom_bussoft: Common prom/kernel struct representing the bus
- *
- * Replicates the tioce_common pointed to by @prom_bussoft in kernel
- * space. Allocates and initializes a kernel-only area for a given CE,
- * and sets up an irq for handling CE error interrupts.
- *
- * On successful setup, returns the kernel version of tioce_common back to
- * the caller.
- */
-static void *
-tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
-{
- struct tioce_common *tioce_common;
- struct tioce_kernel *tioce_kern;
- struct tioce __iomem *tioce_mmr;
-
- /*
- * Allocate kernel bus soft and copy from prom.
- */
-
- tioce_common = kzalloc(sizeof(struct tioce_common), GFP_KERNEL);
- if (!tioce_common)
- return NULL;
-
- memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
- tioce_common->ce_pcibus.bs_base = (unsigned long)
- ioremap(REGION_OFFSET(tioce_common->ce_pcibus.bs_base),
- sizeof(struct tioce_common));
-
- tioce_kern = tioce_kern_init(tioce_common);
- if (tioce_kern == NULL) {
- kfree(tioce_common);
- return NULL;
- }
-
- /*
- * Clear out any transient errors before registering the error
- * interrupt handler.
- */
-
- tioce_mmr = (struct tioce __iomem *)tioce_common->ce_pcibus.bs_base;
- tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
- tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
- ~0ULL);
- tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, 0ULL);
-
- if (request_irq(SGI_PCIASIC_ERROR,
- tioce_error_intr_handler,
- IRQF_SHARED, "TIOCE error", (void *)tioce_common))
- printk(KERN_WARNING
- "%s: Unable to get irq %d. "
- "Error interrupts won't be routed for "
- "TIOCE bus %04x:%02x\n",
- __func__, SGI_PCIASIC_ERROR,
- tioce_common->ce_pcibus.bs_persist_segment,
- tioce_common->ce_pcibus.bs_persist_busnum);
-
- irq_set_handler(SGI_PCIASIC_ERROR, handle_level_irq);
- sn_set_err_irq_affinity(SGI_PCIASIC_ERROR);
- return tioce_common;
-}
-
-static struct sn_pcibus_provider tioce_pci_interfaces = {
- .dma_map = tioce_dma,
- .dma_map_consistent = tioce_dma_consistent,
- .dma_unmap = tioce_dma_unmap,
- .bus_fixup = tioce_bus_fixup,
- .force_interrupt = tioce_force_interrupt,
- .target_interrupt = tioce_target_interrupt
-};
-
-/**
- * tioce_init_provider - init SN PCI provider ops for TIO CE
- */
-int
-tioce_init_provider(void)
-{
- sn_pci_provider[PCIIO_ASIC_TYPE_TIOCE] = &tioce_pci_interfaces;
- return 0;
-}
diff --git a/arch/ia64/uv/kernel/Makefile b/arch/ia64/uv/kernel/Makefile
index 124e441d383d..297196578d19 100644
--- a/arch/ia64/uv/kernel/Makefile
+++ b/arch/ia64/uv/kernel/Makefile
@@ -10,4 +10,3 @@
ccflags-y := -Iarch/ia64/sn/include
obj-y += setup.o
-obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff --git a/arch/ia64/uv/kernel/machvec.c b/arch/ia64/uv/kernel/machvec.c
deleted file mode 100644
index 50737a9dca74..000000000000
--- a/arch/ia64/uv/kernel/machvec.c
+++ /dev/null
@@ -1,11 +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) 2008 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#define MACHVEC_PLATFORM_NAME uv
-#define MACHVEC_PLATFORM_HEADER <asm/machvec_uv.h>
-#include <asm/machvec_init.h>
diff --git a/arch/ia64/uv/kernel/setup.c b/arch/ia64/uv/kernel/setup.c
index f1490657bafc..bb025486d791 100644
--- a/arch/ia64/uv/kernel/setup.c
+++ b/arch/ia64/uv/kernel/setup.c
@@ -8,25 +8,20 @@
* 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/sn/simulator.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);
-#ifdef CONFIG_IA64_SGI_UV
-int sn_prom_type;
-long sn_partition_id;
-EXPORT_SYMBOL(sn_partition_id);
-long sn_coherency_id;
-EXPORT_SYMBOL_GPL(sn_coherency_id);
-long sn_region_size;
-EXPORT_SYMBOL(sn_region_size);
-#endif
-
struct redir_addr {
unsigned long redirect;
unsigned long alias;
@@ -58,6 +53,34 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
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;
@@ -66,30 +89,11 @@ void __init uv_setup(char **cmdline_p)
int nid, cpu, m_val, n_val;
unsigned long mmr_base, lowmem_redir_base, lowmem_redir_size;
- if (IS_MEDUSA()) {
- lowmem_redir_base = 0;
- lowmem_redir_size = 0;
- node_id.v = 0;
- m_n_config.s.m_skt = 37;
- m_n_config.s.n_skt = 0;
- mmr_base = 0;
-#if 0
- /* Need BIOS calls - TDB */
- if (!ia64_sn_is_fake_prom())
- sn_prom_type = 1;
- else
-#endif
- sn_prom_type = 2;
- printk(KERN_INFO "Running on medusa with %s PROM\n",
- (sn_prom_type == 1) ? "real" : "fake");
- } else {
- 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;
- }
+ 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;
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 902255e7b5b2..73bf5ea9ee1b 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -246,9 +246,9 @@ void __init config_atari(void)
} else if (hwreg_present(tt_palette)) {
ATARIHW_SET(TT_SHIFTER);
pr_cont(" TT_SHIFTER");
- } else if (hwreg_present(&shifter.bas_hi)) {
- if (hwreg_present(&shifter.bas_lo) &&
- (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
+ } else if (hwreg_present(&shifter_st.bas_hi)) {
+ if (hwreg_present(&shifter_st.bas_lo) &&
+ (shifter_st.bas_lo = 0x0aau, shifter_st.bas_lo == 0x0aau)) {
ATARIHW_SET(EXTD_SHIFTER);
pr_cont(" EXTD_SHIFTER");
} else {
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 04e0f211afb3..9a33c1c006a1 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -125,6 +125,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -250,9 +251,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -330,7 +333,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -450,7 +452,6 @@ CONFIG_RTC_DRV_RP5C01=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -573,6 +574,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -582,8 +584,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -618,6 +622,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -636,6 +641,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -644,4 +650,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index c6abbb535878..7fdbc797a05d 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -121,6 +121,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -246,9 +247,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -315,7 +318,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -410,7 +412,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -533,6 +534,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -542,8 +544,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -578,6 +582,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -596,6 +601,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -604,4 +610,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 06ae65bad177..f1763405a539 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -128,6 +128,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -253,9 +254,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -330,7 +333,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -432,7 +434,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -555,6 +556,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -564,8 +566,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -600,6 +604,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -618,6 +623,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -626,4 +632,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 5616b94053b6..91154d6acb31 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -118,6 +118,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -243,9 +244,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -312,7 +315,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -403,7 +405,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -526,6 +527,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -535,8 +537,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -571,6 +575,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -589,6 +594,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -597,4 +603,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 1106521f3b56..c398c4a94d95 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -120,6 +120,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -245,9 +246,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -314,7 +317,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -412,7 +414,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -535,6 +536,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -544,8 +546,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -580,6 +584,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -598,6 +603,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -606,4 +612,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 226c6c063cd4..350d004559be 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -119,6 +119,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -244,9 +245,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -321,7 +324,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -434,7 +436,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -557,6 +558,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -566,8 +568,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -602,6 +606,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -620,6 +625,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -628,4 +634,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 39f603417928..b838dd820348 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -139,6 +139,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -264,9 +265,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -354,7 +357,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -516,7 +518,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -639,6 +640,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -648,8 +650,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -684,6 +688,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -702,6 +707,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -710,4 +716,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 175a607f576c..3f8dd61559cf 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -117,6 +117,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -242,9 +243,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -311,7 +314,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -402,7 +404,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -525,6 +526,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -534,8 +536,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -570,6 +574,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -588,6 +593,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -596,4 +602,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index f41c34d3cdd0..ae3b2d4f636c 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -118,6 +118,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -243,9 +244,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -312,7 +315,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -403,7 +405,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -526,6 +527,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -535,8 +537,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -571,6 +575,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -589,6 +594,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -597,4 +603,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index c9d2cb0a1cf4..cd61ef14b582 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -119,6 +119,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -244,9 +245,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -320,7 +323,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -421,7 +423,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -544,6 +545,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -553,8 +555,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -589,6 +593,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -607,6 +612,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -615,4 +621,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 79a64fdd6bf0..151f5371cd3d 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -115,6 +115,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -240,9 +241,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -309,7 +312,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -405,7 +407,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -528,6 +529,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -537,8 +539,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -573,6 +577,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -591,6 +596,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -599,3 +605,4 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index e3402a5d165b..1dcb0ee1fe98 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -115,6 +115,7 @@ CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
@@ -240,9 +241,11 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -309,7 +312,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
@@ -404,7 +406,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
-# CONFIG_VALIDATE_FS_PARSER is not set
CONFIG_EXT4_FS=y
CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
@@ -527,6 +528,7 @@ CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -536,8 +538,10 @@ CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -572,6 +576,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_WW_MUTEX_SELFTEST=m
CONFIG_TEST_LIST_SORT=m
CONFIG_TEST_SORT=m
+CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_TEST_HEXDUMP=m
@@ -590,6 +595,7 @@ CONFIG_TEST_IDA=m
CONFIG_TEST_VMALLOC=m
CONFIG_TEST_USER_COPY=m
CONFIG_TEST_BPF=m
+CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_FIND_BIT_BENCHMARK=m
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_SYSCTL=m
@@ -598,4 +604,5 @@ CONFIG_TEST_STATIC_KEYS=m
CONFIG_TEST_KMOD=m
CONFIG_TEST_MEMCAT_P=m
CONFIG_TEST_STACKINIT=m
+CONFIG_TEST_MEMINIT=m
CONFIG_EARLY_PRINTK=y
diff --git a/arch/m68k/include/asm/atarihw.h b/arch/m68k/include/asm/atarihw.h
index 533008262b69..9a038a3edb83 100644
--- a/arch/m68k/include/asm/atarihw.h
+++ b/arch/m68k/include/asm/atarihw.h
@@ -22,7 +22,6 @@
#include <linux/types.h>
#include <asm/bootinfo-atari.h>
-#include <asm/raw_io.h>
#include <asm/kmap.h>
extern u_long atari_mch_cookie;
@@ -132,14 +131,6 @@ extern struct atari_hw_present atari_hw_present;
*/
-#define atari_readb raw_inb
-#define atari_writeb raw_outb
-
-#define atari_inb_p raw_inb
-#define atari_outb_p raw_outb
-
-
-
#include <linux/mm.h>
#include <asm/cacheflush.h>
@@ -170,7 +161,7 @@ static inline void dma_cache_maintenance( unsigned long paddr,
#define TT_HIGH 6
#define SHF_BAS (0xffff8200)
-struct SHIFTER
+struct SHIFTER_ST
{
u_char pad1;
u_char bas_hi;
@@ -187,7 +178,7 @@ struct SHIFTER
u_char pad7;
u_char bas_lo;
};
-# define shifter ((*(volatile struct SHIFTER *)SHF_BAS))
+# define shifter_st ((*(volatile struct SHIFTER_ST *)SHF_BAS))
#define SHF_FBAS (0xffff820e)
struct SHIFTER_F030
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 6c03ca5bc436..819f611dccf2 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -29,7 +29,11 @@
#include <asm-generic/iomap.h>
#ifdef CONFIG_ATARI
-#include <asm/atarihw.h>
+#define atari_readb raw_inb
+#define atari_writeb raw_outb
+
+#define atari_inb_p raw_inb
+#define atari_outb_p raw_outb
#endif
diff --git a/arch/m68k/include/asm/kmap.h b/arch/m68k/include/asm/kmap.h
index aac7f045f7f0..421b6c9c769d 100644
--- a/arch/m68k/include/asm/kmap.h
+++ b/arch/m68k/include/asm/kmap.h
@@ -28,14 +28,8 @@ static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-#define ioremap_nocache ioremap_nocache
-static inline void __iomem *ioremap_nocache(unsigned long physaddr,
- unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-
-#define ioremap_uc ioremap_nocache
+#define ioremap_nocache ioremap
+#define ioremap_uc ioremap
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(unsigned long physaddr,
unsigned long size)
@@ -43,13 +37,6 @@ static inline void __iomem *ioremap_wt(unsigned long physaddr,
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-#define ioremap_fullcache ioremap_fullcache
-static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
- unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
-}
-
#define memset_io memset_io
static inline void memset_io(volatile void __iomem *addr, unsigned char val,
int count)
diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h
index d9a08bed4b12..8a43babcf53a 100644
--- a/arch/m68k/include/asm/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
@@ -4,6 +4,7 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/bootinfo-mac.h>
@@ -82,11 +83,11 @@ struct mac_model
#define MAC_EXP_PDS_NUBUS 3 /* Accepts PDS card and/or NuBus card(s) */
#define MAC_EXP_PDS_COMM 4 /* Accepts PDS card or Comm Slot card */
-#define MAC_FLOPPY_IWM 0
-#define MAC_FLOPPY_SWIM_ADDR1 1
-#define MAC_FLOPPY_SWIM_ADDR2 2
-#define MAC_FLOPPY_SWIM_IOP 3
-#define MAC_FLOPPY_AV 4
+#define MAC_FLOPPY_UNSUPPORTED 0
+#define MAC_FLOPPY_SWIM_IOP 1
+#define MAC_FLOPPY_OLD 2
+#define MAC_FLOPPY_QUADRA 3
+#define MAC_FLOPPY_LC 4
extern struct mac_model *macintosh_config;
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 205ac75da13d..611f73bfc87c 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -209,7 +209,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_IWM,
+ .floppy_type = MAC_FLOPPY_UNSUPPORTED, /* IWM */
},
/*
@@ -224,7 +224,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_IWM,
+ .floppy_type = MAC_FLOPPY_UNSUPPORTED, /* IWM */
}, {
.ident = MAC_MODEL_IIX,
.name = "IIx",
@@ -233,7 +233,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_IICX,
.name = "IIcx",
@@ -242,7 +242,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_SE30,
.name = "SE/30",
@@ -251,7 +251,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
},
/*
@@ -269,7 +269,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_IIFX,
.name = "IIfx",
@@ -278,7 +278,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_IIFX,
.scc_type = MAC_SCC_IOP,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_IOP,
+ .floppy_type = MAC_FLOPPY_SWIM_IOP, /* SWIM */
}, {
.ident = MAC_MODEL_IISI,
.name = "IIsi",
@@ -287,7 +287,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_IIVI,
.name = "IIvi",
@@ -296,7 +296,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
}, {
.ident = MAC_MODEL_IIVX,
.name = "IIvx",
@@ -305,7 +305,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
},
/*
@@ -319,7 +319,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
}, {
.ident = MAC_MODEL_CCL,
.name = "Color Classic",
@@ -328,7 +328,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
}, {
.ident = MAC_MODEL_CCLII,
.name = "Color Classic II",
@@ -337,7 +337,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
},
/*
@@ -352,7 +352,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
}, {
.ident = MAC_MODEL_LCII,
.name = "LC II",
@@ -361,7 +361,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
}, {
.ident = MAC_MODEL_LCIII,
.name = "LC III",
@@ -370,7 +370,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
},
/*
@@ -391,7 +391,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_Q605_ACC,
.name = "Quadra 605",
@@ -400,7 +400,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_Q610,
.name = "Quadra 610",
@@ -410,7 +410,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_Q630,
.name = "Quadra 630",
@@ -420,7 +420,7 @@ static struct mac_model mac_data_table[] = {
.ide_type = MAC_IDE_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_PDS_COMM,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_Q650,
.name = "Quadra 650",
@@ -430,7 +430,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
},
/* The Q700 does have a NS Sonic */
{
@@ -442,7 +442,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM */
}, {
.ident = MAC_MODEL_Q800,
.name = "Quadra 800",
@@ -452,7 +452,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_Q840,
.name = "Quadra 840AV",
@@ -462,7 +462,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_PSC,
.ether_type = MAC_ETHER_MACE,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_AV,
+ .floppy_type = MAC_FLOPPY_UNSUPPORTED, /* New Age */
}, {
.ident = MAC_MODEL_Q900,
.name = "Quadra 900",
@@ -472,7 +472,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_IOP,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_IOP,
+ .floppy_type = MAC_FLOPPY_SWIM_IOP, /* SWIM */
}, {
.ident = MAC_MODEL_Q950,
.name = "Quadra 950",
@@ -482,7 +482,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_IOP,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_IOP,
+ .floppy_type = MAC_FLOPPY_SWIM_IOP, /* SWIM */
},
/*
@@ -497,7 +497,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P475,
.name = "Performa 475",
@@ -506,7 +506,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P475F,
.name = "Performa 475",
@@ -515,7 +515,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P520,
.name = "Performa 520",
@@ -524,7 +524,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P550,
.name = "Performa 550",
@@ -533,7 +533,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
},
/* These have the comm slot, and therefore possibly SONIC ethernet */
{
@@ -544,7 +544,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS_COMM,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P588,
.name = "Performa 588",
@@ -554,7 +554,7 @@ static struct mac_model mac_data_table[] = {
.ide_type = MAC_IDE_QUADRA,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_PDS_COMM,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_TV,
.name = "TV",
@@ -562,7 +562,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM 2 */
}, {
.ident = MAC_MODEL_P600,
.name = "Performa 600",
@@ -571,7 +571,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_LC, /* SWIM */
},
/*
@@ -588,7 +588,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_C650,
.name = "Centris 650",
@@ -598,7 +598,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR1,
+ .floppy_type = MAC_FLOPPY_QUADRA, /* SWIM 2 */
}, {
.ident = MAC_MODEL_C660,
.name = "Centris 660AV",
@@ -608,7 +608,7 @@ static struct mac_model mac_data_table[] = {
.scc_type = MAC_SCC_PSC,
.ether_type = MAC_ETHER_MACE,
.expansion_type = MAC_EXP_PDS_NUBUS,
- .floppy_type = MAC_FLOPPY_AV,
+ .floppy_type = MAC_FLOPPY_UNSUPPORTED, /* New Age */
},
/*
@@ -624,7 +624,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB145,
.name = "PowerBook 145",
@@ -632,7 +632,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB150,
.name = "PowerBook 150",
@@ -641,7 +641,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.ide_type = MAC_IDE_PB,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB160,
.name = "PowerBook 160",
@@ -649,7 +649,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB165,
.name = "PowerBook 165",
@@ -657,7 +657,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB165C,
.name = "PowerBook 165c",
@@ -665,7 +665,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB170,
.name = "PowerBook 170",
@@ -673,7 +673,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB180,
.name = "PowerBook 180",
@@ -681,7 +681,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB180C,
.name = "PowerBook 180c",
@@ -689,7 +689,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB190,
.name = "PowerBook 190",
@@ -698,7 +698,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.ide_type = MAC_IDE_BABOON,
.scc_type = MAC_SCC_QUADRA,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM 2 */
}, {
.ident = MAC_MODEL_PB520,
.name = "PowerBook 520",
@@ -707,7 +707,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM 2 */
},
/*
@@ -724,7 +724,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB230,
.name = "PowerBook Duo 230",
@@ -733,7 +733,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB250,
.name = "PowerBook Duo 250",
@@ -742,7 +742,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB270C,
.name = "PowerBook Duo 270c",
@@ -751,7 +751,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB280,
.name = "PowerBook Duo 280",
@@ -760,7 +760,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
}, {
.ident = MAC_MODEL_PB280C,
.name = "PowerBook Duo 280c",
@@ -769,7 +769,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.expansion_type = MAC_EXP_NUBUS,
- .floppy_type = MAC_FLOPPY_SWIM_ADDR2,
+ .floppy_type = MAC_FLOPPY_OLD, /* SWIM */
},
/*
@@ -960,7 +960,7 @@ static const struct resource mac_scsi_ccl_rsrc[] __initconst = {
int __init mac_platform_init(void)
{
- u8 *swim_base;
+ phys_addr_t swim_base = 0;
if (!MACH_IS_MAC)
return -ENODEV;
@@ -977,22 +977,22 @@ int __init mac_platform_init(void)
*/
switch (macintosh_config->floppy_type) {
- case MAC_FLOPPY_SWIM_ADDR1:
- swim_base = (u8 *)(VIA1_BASE + 0x1E000);
+ case MAC_FLOPPY_QUADRA:
+ swim_base = 0x5001E000;
break;
- case MAC_FLOPPY_SWIM_ADDR2:
- swim_base = (u8 *)(VIA1_BASE + 0x16000);
+ case MAC_FLOPPY_OLD:
+ swim_base = 0x50016000;
break;
- default:
- swim_base = NULL;
+ case MAC_FLOPPY_LC:
+ swim_base = 0x50F16000;
break;
}
if (swim_base) {
struct resource swim_rsrc = {
.flags = IORESOURCE_MEM,
- .start = (resource_size_t)swim_base,
- .end = (resource_size_t)swim_base + 0x1FFF,
+ .start = swim_base,
+ .end = swim_base + 0x1FFF,
};
platform_device_register_simple("swim", -1, &swim_rsrc, 1);
diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c
index 1f730ded5224..cc88a08bc1f7 100644
--- a/arch/mips/cavium-octeon/octeon-usb.c
+++ b/arch/mips/cavium-octeon/octeon-usb.c
@@ -398,6 +398,7 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base)
default:
dev_err(dev, "Invalid ref_clk %u, using 100000000 instead\n",
clock_rate);
+ /* fall through */
case 100000000:
mpll_mul = 0x19;
if (ref_clk_sel < 2)
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 66566026409d..f14ad0538f4e 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -103,7 +103,6 @@ CONFIG_FW_LOADER=m
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
-CONFIG_SGI_IOC4=m
CONFIG_EEPROM_LEGACY=y
CONFIG_EEPROM_MAX6875=y
CONFIG_IDE=y
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 572cab91670c..370884018aad 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -46,7 +46,6 @@ CONFIG_CONNECTOR=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
-CONFIG_SGI_IOC4=y
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index ae93a94f8c71..507ad91b21e7 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -117,7 +117,6 @@ CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_SGI_IOC4=m
CONFIG_SCSI=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 0f4b09f8a0ee..8762e75f5d5f 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -198,7 +198,6 @@ CONFIG_BLK_DEV_SX8=m
CONFIG_BLK_DEV_RAM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
-CONFIG_SGI_IOC4=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index 6883ea4477d4..bb0b1b22ebe1 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -49,7 +49,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=9220
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
-CONFIG_SGI_IOC4=m
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDETAPE=y
diff --git a/arch/mips/include/asm/octeon/cvmx-sli-defs.h b/arch/mips/include/asm/octeon/cvmx-sli-defs.h
index 52cf96ea43e5..cbc7cdae1c6a 100644
--- a/arch/mips/include/asm/octeon/cvmx-sli-defs.h
+++ b/arch/mips/include/asm/octeon/cvmx-sli-defs.h
@@ -46,6 +46,7 @@ static inline uint64_t CVMX_SLI_PCIE_MSI_RCV_FUNC(void)
case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
return 0x0000000000003CB0ull;
+ /* Else, fall through */
default:
return 0x0000000000023CB0ull;
}
diff --git a/arch/mips/kernel/cacheinfo.c b/arch/mips/kernel/cacheinfo.c
index e0dd66881da6..f777e44653d5 100644
--- a/arch/mips/kernel/cacheinfo.c
+++ b/arch/mips/kernel/cacheinfo.c
@@ -69,6 +69,8 @@ static int __populate_cache_leaves(unsigned int cpu)
if (c->tcache.waysize)
populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED);
+ this_cpu_ci->cpu_map_populated = true;
+
return 0;
}
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 5f209f111e59..df7ddd246eaa 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -32,7 +32,8 @@ void __init setup_pit_timer(void)
static int __init init_pit_clocksource(void)
{
- if (num_possible_cpus() > 1) /* PIT does not scale! */
+ if (num_possible_cpus() > 1 || /* PIT does not scale! */
+ !clockevent_state_periodic(&i8253_clockevent))
return 0;
return clocksource_i8253_init();
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index e5de6bac8197..754094b40a75 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -140,6 +140,7 @@ static int kvm_compute_return_epc(struct kvm_vcpu *vcpu, unsigned long instpc,
/* These are unconditional and in j_format. */
case jal_op:
arch->gprs[31] = instpc + 8;
+ /* fall through */
case j_op:
epc += 4;
epc >>= 28;
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 2cfe839f0b3a..1109924560d8 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -150,16 +150,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
return 0;
}
-bool kvm_arch_has_vcpu_debugfs(void)
-{
- return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
- return 0;
-}
-
void kvm_mips_free_vcpus(struct kvm *kvm)
{
unsigned int i;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 7c04b17f4a48..96c13a0ab078 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -172,12 +172,15 @@ static void mipsxx_cpu_setup(void *args)
case 4:
w_c0_perfctrl3(0);
w_c0_perfcntr3(reg.counter[3]);
+ /* fall through */
case 3:
w_c0_perfctrl2(0);
w_c0_perfcntr2(reg.counter[2]);
+ /* fall through */
case 2:
w_c0_perfctrl1(0);
w_c0_perfcntr1(reg.counter[1]);
+ /* fall through */
case 1:
w_c0_perfctrl0(0);
w_c0_perfcntr0(reg.counter[0]);
@@ -195,10 +198,13 @@ static void mipsxx_cpu_start(void *args)
switch (counters) {
case 4:
w_c0_perfctrl3(WHAT | reg.control[3]);
+ /* fall through */
case 3:
w_c0_perfctrl2(WHAT | reg.control[2]);
+ /* fall through */
case 2:
w_c0_perfctrl1(WHAT | reg.control[1]);
+ /* fall through */
case 1:
w_c0_perfctrl0(WHAT | reg.control[0]);
}
@@ -215,10 +221,13 @@ static void mipsxx_cpu_stop(void *args)
switch (counters) {
case 4:
w_c0_perfctrl3(0);
+ /* fall through */
case 3:
w_c0_perfctrl2(0);
+ /* fall through */
case 2:
w_c0_perfctrl1(0);
+ /* fall through */
case 1:
w_c0_perfctrl0(0);
}
@@ -236,6 +245,7 @@ static int mipsxx_perfcount_handler(void)
switch (counters) {
#define HANDLE_COUNTER(n) \
+ /* fall through */ \
case n + 1: \
control = r_c0_perfctrl ## n(); \
counter = r_c0_perfcntr ## n(); \
@@ -297,12 +307,15 @@ static void reset_counters(void *arg)
case 4:
w_c0_perfctrl3(0);
w_c0_perfcntr3(0);
+ /* fall through */
case 3:
w_c0_perfctrl2(0);
w_c0_perfcntr2(0);
+ /* fall through */
case 2:
w_c0_perfctrl1(0);
w_c0_perfcntr1(0);
+ /* fall through */
case 1:
w_c0_perfctrl0(0);
w_c0_perfcntr0(0);
diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c
index d02eb9d16b55..925c72348fb6 100644
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -474,6 +474,7 @@ static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
if (PCI_SLOT(devfn) == 0)
return bcm_pcie_readl(PCIE_DLSTATUS_REG)
& DLSTATUS_PHYLINKUP;
+ /* else, fall through */
default:
return false;
}
diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h
index 14b1931be69c..b65b169778e3 100644
--- a/arch/mips/vdso/vdso.h
+++ b/arch/mips/vdso/vdso.h
@@ -9,6 +9,7 @@
#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
+#define BUILD_VDSO32_64
#undef CONFIG_64BIT
#define CONFIG_32BIT 1
#ifndef __ASSEMBLY__
diff --git a/arch/nds32/include/uapi/asm/auxvec.h b/arch/nds32/include/uapi/asm/auxvec.h
index b5d58ea8decb..bc0b92ab8c15 100644
--- a/arch/nds32/include/uapi/asm/auxvec.h
+++ b/arch/nds32/include/uapi/asm/auxvec.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __ASM_AUXVEC_H
diff --git a/arch/nds32/include/uapi/asm/byteorder.h b/arch/nds32/include/uapi/asm/byteorder.h
index 511e653c709d..c264ef12c49c 100644
--- a/arch/nds32/include/uapi/asm/byteorder.h
+++ b/arch/nds32/include/uapi/asm/byteorder.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __NDS32_BYTEORDER_H__
diff --git a/arch/nds32/include/uapi/asm/cachectl.h b/arch/nds32/include/uapi/asm/cachectl.h
index 73793662815c..31b9b439d819 100644
--- a/arch/nds32/include/uapi/asm/cachectl.h
+++ b/arch/nds32/include/uapi/asm/cachectl.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 1994, 1995, 1996 by Ralf Baechle
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef _ASM_CACHECTL
diff --git a/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
index d54a5d6c6538..f17396db16ec 100644
--- a/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
+++ b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* Copyright (C) 2005-2019 Andes Technology Corporation */
#ifndef _FP_UDF_IEX_CRTL_H
#define _FP_UDF_IEX_CRTL_H
diff --git a/arch/nds32/include/uapi/asm/param.h b/arch/nds32/include/uapi/asm/param.h
index 2977534a6bd3..48d00328d328 100644
--- a/arch/nds32/include/uapi/asm/param.h
+++ b/arch/nds32/include/uapi/asm/param.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __ASM_NDS32_PARAM_H
diff --git a/arch/nds32/include/uapi/asm/ptrace.h b/arch/nds32/include/uapi/asm/ptrace.h
index 1a6e01c00e6f..d76217c7c010 100644
--- a/arch/nds32/include/uapi/asm/ptrace.h
+++ b/arch/nds32/include/uapi/asm/ptrace.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __UAPI_ASM_NDS32_PTRACE_H
diff --git a/arch/nds32/include/uapi/asm/sigcontext.h b/arch/nds32/include/uapi/asm/sigcontext.h
index dc89af7ddcc3..6c1e6648878f 100644
--- a/arch/nds32/include/uapi/asm/sigcontext.h
+++ b/arch/nds32/include/uapi/asm/sigcontext.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef _ASMNDS32_SIGCONTEXT_H
diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h
index a0b2f7b9c0f2..410795e280fe 100644
--- a/arch/nds32/include/uapi/asm/unistd.h
+++ b/arch/nds32/include/uapi/asm/unistd.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2005-2017 Andes Technology Corporation
#define __ARCH_WANT_STAT64
diff --git a/arch/nds32/kernel/signal.c b/arch/nds32/kernel/signal.c
index fe61513982b4..330b19fcd990 100644
--- a/arch/nds32/kernel/signal.c
+++ b/arch/nds32/kernel/signal.c
@@ -316,6 +316,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
regs->uregs[0] = -EINTR;
break;
}
+ /* Else, fall through */
case -ERESTARTNOINTR:
regs->uregs[0] = regs->orig_r0;
regs->ipc -= 4;
@@ -360,6 +361,7 @@ static void do_signal(struct pt_regs *regs)
switch (regs->uregs[0]) {
case -ERESTART_RESTARTBLOCK:
regs->uregs[15] = __NR_restart_syscall;
+ /* Fall through */
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6d732e451071..2e757c785239 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -61,6 +61,8 @@ config PARISC
select HAVE_KRETPROBES
select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1)
select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
+ select HAVE_KPROBES_ON_FTRACE
+ select HAVE_DYNAMIC_FTRACE_WITH_REGS
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
@@ -344,6 +346,29 @@ config NR_CPUS
depends on SMP
default "4"
+config KEXEC
+ bool "Kexec system call"
+ select KEXEC_CORE
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is independent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ It is an ongoing process to be certain the hardware in a machine
+ shutdown, so do not be surprised if this code does not
+ initially work for you.
+
+config KEXEC_FILE
+ bool "kexec file based system call"
+ select KEXEC_CORE
+ select KEXEC_ELF
+ help
+ This enables the kexec_file_load() System call. This is
+ file based and takes file descriptors as system call argument
+ for kernel and initramfs as opposed to list of segments as
+ accepted by previous system call.
+
endmenu
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 8acb8fa1f8d6..3b77d729057f 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -19,8 +19,6 @@
KBUILD_IMAGE := vmlinuz
-KBUILD_DEFCONFIG := default_defconfig
-
NM = sh $(srctree)/arch/parisc/nm
CHECKFLAGS += -D__hppa__=1
LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
@@ -182,5 +180,8 @@ define archhelp
@echo ' zinstall - Install compressed vmlinuz kernel'
endef
+archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
archheaders:
$(Q)$(MAKE) $(build)=arch/parisc/kernel/syscalls all
diff --git a/arch/parisc/boot/compressed/.gitignore b/arch/parisc/boot/compressed/.gitignore
index ae06b9b4c02f..926cd41c1069 100644
--- a/arch/parisc/boot/compressed/.gitignore
+++ b/arch/parisc/boot/compressed/.gitignore
@@ -1,3 +1,5 @@
+firmware.c
+real2.S
sizes.h
vmlinux
vmlinux.lds
diff --git a/arch/parisc/boot/compressed/Makefile b/arch/parisc/boot/compressed/Makefile
index 2da8624e5cf6..1e5879c6a752 100644
--- a/arch/parisc/boot/compressed/Makefile
+++ b/arch/parisc/boot/compressed/Makefile
@@ -12,6 +12,7 @@ UBSAN_SANITIZE := n
targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2
targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4
targets += misc.o piggy.o sizes.h head.o real2.o firmware.o
+targets += real2.S firmware.c
KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
@@ -55,7 +56,8 @@ $(obj)/misc.o: $(obj)/sizes.h
CPPFLAGS_vmlinux.lds += -I$(objtree)/$(obj) -DBOOTLOADER
$(obj)/vmlinux.lds: $(obj)/sizes.h
-$(obj)/vmlinux.bin: vmlinux
+OBJCOPYFLAGS_vmlinux.bin := -R .comment -R .note -S
+$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
vmlinux.bin.all-y := $(obj)/vmlinux.bin
diff --git a/arch/parisc/boot/compressed/vmlinux.lds.S b/arch/parisc/boot/compressed/vmlinux.lds.S
index bfd7872739a3..2ac3a643f2eb 100644
--- a/arch/parisc/boot/compressed/vmlinux.lds.S
+++ b/arch/parisc/boot/compressed/vmlinux.lds.S
@@ -48,8 +48,8 @@ SECTIONS
*(.rodata.compressed)
}
- /* bootloader code and data starts behind area of extracted kernel */
- . = (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START);
+ /* bootloader code and data starts at least behind area of extracted kernel */
+ . = MAX(ABSOLUTE(.), (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START));
/* align on next page boundary */
. = ALIGN(4096);
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/defconfig
index 5b877ca34ebf..5b877ca34ebf 100644
--- a/arch/parisc/configs/default_defconfig
+++ b/arch/parisc/configs/defconfig
diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h
index 793d8baa3a10..0ec54f43d6d2 100644
--- a/arch/parisc/include/asm/alternative.h
+++ b/arch/parisc/include/asm/alternative.h
@@ -8,6 +8,7 @@
#define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */
#define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */
#define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */
+#define ALT_COND_RUN_ON_QEMU 0x20 /* if running on QEMU */
#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */
#define INSN_NOP 0x08000240 /* nop */
@@ -21,7 +22,7 @@
struct alt_instr {
s32 orig_offset; /* offset to original instructions */
- u32 len; /* end of original instructions */
+ s32 len; /* end of original instructions */
u32 cond; /* see ALT_COND_XXX */
u32 replacement; /* replacement instruction or code */
};
@@ -40,12 +41,20 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
#else
+/* to replace one single instructions by a new instruction */
#define ALTERNATIVE(from, to, cond, replacement)\
.section .altinstructions, "aw" ! \
.word (from - .), (to - from)/4 ! \
.word cond, replacement ! \
.previous
+/* to replace multiple instructions by new code */
+#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
+ .section .altinstructions, "aw" ! \
+ .word (from - .), -num_instructions ! \
+ .word cond, (new_instr_ptr - .) ! \
+ .previous
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PARISC_ALTERNATIVE_H */
diff --git a/arch/parisc/include/asm/fixmap.h b/arch/parisc/include/asm/fixmap.h
index 288da73d4cc0..e480b2c05407 100644
--- a/arch/parisc/include/asm/fixmap.h
+++ b/arch/parisc/include/asm/fixmap.h
@@ -30,6 +30,7 @@
enum fixed_addresses {
/* Support writing RO kernel text via kprobes, jump labels, etc. */
FIX_TEXT_POKE0,
+ FIX_TEXT_KEXEC,
FIX_BITMAP_COUNT
};
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 958c0aa5dbb2..a7cf0d05ccf4 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -8,6 +8,7 @@ extern void mcount(void);
#define MCOUNT_ADDR ((unsigned long)mcount)
#define MCOUNT_INSN_SIZE 4
#define CC_USING_NOP_MCOUNT
+#define ARCH_SUPPORTS_FTRACE_OPS 1
extern unsigned long sys_call_table[];
extern unsigned long return_address(unsigned int);
diff --git a/arch/parisc/include/asm/kexec.h b/arch/parisc/include/asm/kexec.h
new file mode 100644
index 000000000000..a99ea747d7ed
--- /dev/null
+++ b/arch/parisc/include/asm/kexec.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_PARISC_KEXEC_H
+#define _ASM_PARISC_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 */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE 4096
+
+#define KEXEC_ARCH KEXEC_ARCH_PARISC
+#define ARCH_HAS_KIMAGE_ARCH
+
+#ifndef __ASSEMBLY__
+
+struct kimage_arch {
+ unsigned long initrd_start;
+ unsigned long initrd_end;
+ unsigned long cmdline;
+};
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ /* Dummy implementation for now */
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ASM_PARISC_KEXEC_H */
diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h
index 19bb2e46cd36..b388d8176588 100644
--- a/arch/parisc/include/asm/pdc.h
+++ b/arch/parisc/include/asm/pdc.h
@@ -91,6 +91,7 @@ int pdc_sti_call(unsigned long func, unsigned long flags,
unsigned long inptr, unsigned long outputr,
unsigned long glob_cfg);
+int __pdc_cpu_rendezvous(void);
static inline char * os_id_to_string(u16 os_id) {
switch(os_id) {
case OS_ID_NONE: return "No OS";
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index a39b079e73f2..6d58c1739b42 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -2,6 +2,7 @@
#ifndef _PARISC_PGTABLE_H
#define _PARISC_PGTABLE_H
+#include <asm/page.h>
#include <asm-generic/4level-fixup.h>
#include <asm/fixmap.h>
@@ -98,8 +99,6 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
#endif /* !__ASSEMBLY__ */
-#include <asm/page.h>
-
#define pte_ERROR(e) \
printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
diff --git a/arch/parisc/include/asm/string.h b/arch/parisc/include/asm/string.h
index f6e1132f4e35..4a0c9dbd62fd 100644
--- a/arch/parisc/include/asm/string.h
+++ b/arch/parisc/include/asm/string.h
@@ -8,4 +8,19 @@ extern void * memset(void *, int, size_t);
#define __HAVE_ARCH_MEMCPY
void * memcpy(void * dest,const void *src,size_t count);
+#define __HAVE_ARCH_STRLEN
+extern size_t strlen(const char *s);
+
+#define __HAVE_ARCH_STRCPY
+extern char *strcpy(char *dest, const char *src);
+
+#define __HAVE_ARCH_STRNCPY
+extern char *strncpy(char *dest, const char *src, size_t count);
+
+#define __HAVE_ARCH_STRCAT
+extern char *strcat(char *dest, const char *src);
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, size_t);
+
#endif
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index c232266b517c..2663c8f8be11 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -37,3 +37,5 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_KEXEC) += kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c
index ca1f5ca0540a..3c66d5c4d90d 100644
--- a/arch/parisc/kernel/alternative.c
+++ b/arch/parisc/kernel/alternative.c
@@ -28,7 +28,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
for (entry = start; entry < end; entry++, index++) {
- u32 *from, len, cond, replacement;
+ u32 *from, cond, replacement;
+ s32 len;
from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
len = entry->len;
@@ -49,6 +50,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
continue;
if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0))
continue;
+ if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu)
+ continue;
/*
* If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit
@@ -74,11 +77,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
if (replacement == INSN_NOP && len > 1)
replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */
- pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n",
- index, cond, len, from, replacement);
-
- /* Replace instruction */
- *from = replacement;
+ pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n",
+ index, cond, len, replacement, from, from);
+
+ if (len < 0) {
+ /* Replace multiple instruction by new code */
+ u32 *source;
+ len = -len;
+ source = (u32 *)((ulong)&entry->replacement + entry->replacement);
+ memcpy(from, source, 4 * len);
+ } else {
+ /* Replace by one instruction */
+ *from = replacement;
+ }
applied++;
}
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d9d3387f7c47..1d1d748c227f 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1996,6 +1996,7 @@ _mcount:
* calling mcount(), and 2 instructions for ftrace_stub(). That way we
* have all on one L1 cacheline.
*/
+ ldi 0, %arg3
b ftrace_function_trampoline
copy %r3, %arg2 /* caller original %sp */
ftrace_stub:
@@ -2048,6 +2049,7 @@ ftrace_caller:
LDREG 0(%r3), %r25
copy %rp, %r26
ldo -8(%r25), %r25
+ ldi 0, %r23 /* no pt_regs */
b,l ftrace_function_trampoline, %rp
copy %r3, %r24
@@ -2075,6 +2077,103 @@ ftrace_caller:
ENDPROC_CFI(ftrace_caller)
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
+ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN,
+ CALLS,SAVE_RP,SAVE_SP)
+ftrace_regs_caller:
+ .global ftrace_regs_caller
+
+ ldo -FTRACE_FRAME_SIZE(%sp), %r1
+ STREG %rp, -RP_OFFSET(%r1)
+
+ copy %sp, %r1
+ ldo PT_SZ_ALGN(%sp), %sp
+
+ STREG %rp, PT_GR2(%r1)
+ STREG %r3, PT_GR3(%r1)
+ STREG %r4, PT_GR4(%r1)
+ STREG %r5, PT_GR5(%r1)
+ STREG %r6, PT_GR6(%r1)
+ STREG %r7, PT_GR7(%r1)
+ STREG %r8, PT_GR8(%r1)
+ STREG %r9, PT_GR9(%r1)
+ STREG %r10, PT_GR10(%r1)
+ STREG %r11, PT_GR11(%r1)
+ STREG %r12, PT_GR12(%r1)
+ STREG %r13, PT_GR13(%r1)
+ STREG %r14, PT_GR14(%r1)
+ STREG %r15, PT_GR15(%r1)
+ STREG %r16, PT_GR16(%r1)
+ STREG %r17, PT_GR17(%r1)
+ STREG %r18, PT_GR18(%r1)
+ STREG %r19, PT_GR19(%r1)
+ STREG %r20, PT_GR20(%r1)
+ STREG %r21, PT_GR21(%r1)
+ STREG %r22, PT_GR22(%r1)
+ STREG %r23, PT_GR23(%r1)
+ STREG %r24, PT_GR24(%r1)
+ STREG %r25, PT_GR25(%r1)
+ STREG %r26, PT_GR26(%r1)
+ STREG %r27, PT_GR27(%r1)
+ STREG %r28, PT_GR28(%r1)
+ STREG %r29, PT_GR29(%r1)
+ STREG %r30, PT_GR30(%r1)
+ STREG %r31, PT_GR31(%r1)
+ mfctl %cr11, %r26
+ STREG %r26, PT_SAR(%r1)
+
+ copy %rp, %r26
+ LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
+ ldo -8(%r25), %r25
+ copy %r3, %arg2
+ b,l ftrace_function_trampoline, %rp
+ copy %r1, %arg3 /* struct pt_regs */
+
+ ldo -PT_SZ_ALGN(%sp), %r1
+
+ LDREG PT_SAR(%r1), %rp
+ mtctl %rp, %cr11
+
+ LDREG PT_GR2(%r1), %rp
+ LDREG PT_GR3(%r1), %r3
+ LDREG PT_GR4(%r1), %r4
+ LDREG PT_GR5(%r1), %r5
+ LDREG PT_GR6(%r1), %r6
+ LDREG PT_GR7(%r1), %r7
+ LDREG PT_GR8(%r1), %r8
+ LDREG PT_GR9(%r1), %r9
+ LDREG PT_GR10(%r1),%r10
+ LDREG PT_GR11(%r1),%r11
+ LDREG PT_GR12(%r1),%r12
+ LDREG PT_GR13(%r1),%r13
+ LDREG PT_GR14(%r1),%r14
+ LDREG PT_GR15(%r1),%r15
+ LDREG PT_GR16(%r1),%r16
+ LDREG PT_GR17(%r1),%r17
+ LDREG PT_GR18(%r1),%r18
+ LDREG PT_GR19(%r1),%r19
+ LDREG PT_GR20(%r1),%r20
+ LDREG PT_GR21(%r1),%r21
+ LDREG PT_GR22(%r1),%r22
+ LDREG PT_GR23(%r1),%r23
+ LDREG PT_GR24(%r1),%r24
+ LDREG PT_GR25(%r1),%r25
+ LDREG PT_GR26(%r1),%r26
+ LDREG PT_GR27(%r1),%r27
+ LDREG PT_GR28(%r1),%r28
+ LDREG PT_GR29(%r1),%r29
+ LDREG PT_GR30(%r1),%r30
+ LDREG PT_GR31(%r1),%r31
+
+ ldo -PT_SZ_ALGN(%sp), %sp
+ LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
+ /* Adjust return point to jump back to beginning of traced function */
+ ldo -4(%r1), %r1
+ bv,n (%r1)
+
+ENDPROC_CFI(ftrace_regs_caller)
+
+#endif
#endif
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 58cc08e7fd12..1d976f2ebff0 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -312,6 +312,19 @@ int pdc_chassis_disp(unsigned long disp)
}
/**
+ * pdc_cpu_rendenzvous - Stop currently executing CPU
+ * @retval: -1 on error, 0 on success
+ */
+int __pdc_cpu_rendezvous(void)
+{
+ if (is_pdc_pat())
+ return mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_RENDEZVOUS);
+ else
+ return mem_pdc_call(PDC_PROC, 1, 0);
+}
+
+
+/**
* pdc_chassis_warn - Fetches chassis warnings
* @retval: -1 on error, 0 on success
*/
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index d784ccdd8fef..b836fc61a24f 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -13,6 +13,8 @@
#include <linux/init.h>
#include <linux/ftrace.h>
#include <linux/uaccess.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
#include <asm/assembly.h>
#include <asm/sections.h>
@@ -48,17 +50,22 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
void notrace __hot ftrace_function_trampoline(unsigned long parent,
unsigned long self_addr,
- unsigned long org_sp_gr3)
+ unsigned long org_sp_gr3,
+ struct pt_regs *regs)
{
#ifndef CONFIG_DYNAMIC_FTRACE
extern ftrace_func_t ftrace_trace_function;
#endif
- if (ftrace_trace_function != ftrace_stub)
- ftrace_trace_function(self_addr, parent, NULL, NULL);
+ extern struct ftrace_ops *function_trace_op;
+
+ if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
+ ftrace_trace_function != ftrace_stub)
+ ftrace_trace_function(self_addr, parent,
+ function_trace_op, regs);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
- ftrace_graph_entry != ftrace_graph_entry_stub) {
+ ftrace_graph_entry != ftrace_graph_entry_stub) {
unsigned long *parent_rp;
/* calculate pointer to %rp in stack */
@@ -96,6 +103,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
return 0;
}
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+ unsigned long addr)
+{
+ return 0;
+}
+
unsigned long ftrace_call_adjust(unsigned long addr)
{
return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
@@ -181,8 +194,52 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
for (i = 0; i < ARRAY_SIZE(insn); i++)
insn[i] = INSN_NOP;
+ __patch_text((void *)rec->ip, INSN_NOP);
__patch_text_multiple((void *)rec->ip + 4 - sizeof(insn),
- insn, sizeof(insn));
+ insn, sizeof(insn)-4);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_KPROBES_ON_FTRACE
+void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+ struct ftrace_ops *ops, struct pt_regs *regs)
+{
+ struct kprobe_ctlblk *kcb;
+ struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
+
+ if (unlikely(!p) || kprobe_disabled(p))
+ return;
+
+ if (kprobe_running()) {
+ kprobes_inc_nmissed_count(p);
+ return;
+ }
+
+ __this_cpu_write(current_kprobe, p);
+
+ kcb = get_kprobe_ctlblk();
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+ regs->iaoq[0] = ip;
+ regs->iaoq[1] = ip + 4;
+
+ if (!p->pre_handler || !p->pre_handler(p, regs)) {
+ regs->iaoq[0] = ip + 4;
+ regs->iaoq[1] = ip + 8;
+
+ if (unlikely(p->post_handler)) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ p->post_handler(p, regs, 0);
+ }
+ }
+ __this_cpu_write(current_kprobe, NULL);
+}
+NOKPROBE_SYMBOL(kprobe_ftrace_handler);
+
+int arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+ p->ainsn.insn = NULL;
return 0;
}
#endif
diff --git a/arch/parisc/kernel/kexec.c b/arch/parisc/kernel/kexec.c
new file mode 100644
index 000000000000..5eb7f30edc1f
--- /dev/null
+++ b/arch/parisc/kernel/kexec.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/cacheflush.h>
+#include <asm/sections.h>
+
+extern void relocate_new_kernel(unsigned long head,
+ unsigned long start,
+ unsigned long phys);
+
+extern const unsigned int relocate_new_kernel_size;
+extern unsigned int kexec_initrd_start_offset;
+extern unsigned int kexec_initrd_end_offset;
+extern unsigned int kexec_cmdline_offset;
+extern unsigned int kexec_free_mem_offset;
+
+static void kexec_show_segment_info(const struct kimage *kimage,
+ unsigned long n)
+{
+ pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n",
+ n,
+ kimage->segment[n].mem,
+ kimage->segment[n].mem + kimage->segment[n].memsz,
+ (unsigned long)kimage->segment[n].memsz,
+ (unsigned long)kimage->segment[n].memsz / PAGE_SIZE);
+}
+
+static void kexec_image_info(const struct kimage *kimage)
+{
+ unsigned long i;
+
+ pr_debug("kexec kimage info:\n");
+ pr_debug(" type: %d\n", kimage->type);
+ pr_debug(" start: %lx\n", kimage->start);
+ pr_debug(" head: %lx\n", kimage->head);
+ pr_debug(" nr_segments: %lu\n", kimage->nr_segments);
+
+ for (i = 0; i < kimage->nr_segments; i++)
+ kexec_show_segment_info(kimage, i);
+
+#ifdef CONFIG_KEXEC_FILE
+ if (kimage->file_mode) {
+ pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len,
+ kimage->cmdline_buf);
+ }
+#endif
+}
+
+void machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void machine_shutdown(void)
+{
+ smp_send_stop();
+ while (num_online_cpus() > 1) {
+ cpu_relax();
+ mdelay(1);
+ }
+}
+
+void machine_kexec(struct kimage *image)
+{
+#ifdef CONFIG_64BIT
+ Elf64_Fdesc desc;
+#endif
+ void (*reloc)(unsigned long head,
+ unsigned long start,
+ unsigned long phys);
+
+ unsigned long phys = page_to_phys(image->control_code_page);
+ void *virt = (void *)__fix_to_virt(FIX_TEXT_KEXEC);
+ struct kimage_arch *arch = &image->arch;
+
+ set_fixmap(FIX_TEXT_KEXEC, phys);
+
+ flush_cache_all();
+
+#ifdef CONFIG_64BIT
+ reloc = (void *)&desc;
+ desc.addr = (long long)virt;
+#else
+ reloc = (void *)virt;
+#endif
+
+ memcpy(virt, dereference_function_descriptor(relocate_new_kernel),
+ relocate_new_kernel_size);
+
+ *(unsigned long *)(virt + kexec_cmdline_offset) = arch->cmdline;
+ *(unsigned long *)(virt + kexec_initrd_start_offset) = arch->initrd_start;
+ *(unsigned long *)(virt + kexec_initrd_end_offset) = arch->initrd_end;
+ *(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0->mem_free;
+
+ flush_cache_all();
+ flush_tlb_all();
+ local_irq_disable();
+
+ reloc(image->head & PAGE_MASK, image->start, phys);
+}
+
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_image_info(image);
+ return 0;
+}
diff --git a/arch/parisc/kernel/kexec_file.c b/arch/parisc/kernel/kexec_file.c
new file mode 100644
index 000000000000..8c534204f0fd
--- /dev/null
+++ b/arch/parisc/kernel/kexec_file.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Load ELF vmlinux file for the kexec_file_load syscall.
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ *
+ */
+#include <linux/elf.h>
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/module.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+static void *elf_load(struct kimage *image, char *kernel_buf,
+ unsigned long kernel_len, char *initrd,
+ unsigned long initrd_len, char *cmdline,
+ unsigned long cmdline_len)
+{
+ int ret, i;
+ unsigned long kernel_load_addr;
+ struct elfhdr ehdr;
+ struct kexec_elf_info elf_info;
+ struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+ .buf_max = -1UL, };
+
+ ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
+ if (ret)
+ goto out;
+
+ ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
+ if (ret)
+ goto out;
+
+ image->start = __pa(elf_info.ehdr->e_entry);
+
+ for (i = 0; i < image->nr_segments; i++)
+ image->segment[i].mem = __pa(image->segment[i].mem);
+
+ pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n",
+ kernel_load_addr, image->start);
+
+ if (initrd != NULL) {
+ kbuf.buffer = initrd;
+ kbuf.bufsz = kbuf.memsz = initrd_len;
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.top_down = false;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out;
+
+ pr_debug("Loaded initrd at 0x%lx\n", kbuf.mem);
+ image->arch.initrd_start = kbuf.mem;
+ image->arch.initrd_end = kbuf.mem + initrd_len;
+ }
+
+ if (cmdline != NULL) {
+ kbuf.buffer = cmdline;
+ kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8);
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.top_down = false;
+ kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE;
+ kbuf.buf_max = kernel_load_addr;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out;
+
+ pr_debug("Loaded cmdline at 0x%lx\n", kbuf.mem);
+ image->arch.cmdline = kbuf.mem;
+ }
+out:
+ return NULL;
+}
+
+const struct kexec_file_ops kexec_elf_ops = {
+ .probe = kexec_elf_probe,
+ .load = elf_load,
+};
+
+const struct kexec_file_ops * const kexec_file_loaders[] = {
+ &kexec_elf_ops,
+ NULL
+};
diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c
index 5d7f2692ac5a..77ec51818916 100644
--- a/arch/parisc/kernel/kprobes.c
+++ b/arch/parisc/kernel/kprobes.c
@@ -281,10 +281,6 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
{
return p->addr == trampoline_p.addr;
}
-bool arch_kprobe_on_func_entry(unsigned long offset)
-{
- return !offset;
-}
int __init arch_init_kprobes(void)
{
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index df46b0e5a915..fa092ed1e837 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -174,6 +174,15 @@ fdtdone:
2: bv %r0(%r2)
nop
+
+ /*
+ * When running in qemu, drop whole flush_tlb_all_local function and
+ * replace by one pdtlbe instruction, for which QEMU will drop all
+ * local TLB entries.
+ */
+3: pdtlbe %r0(%sr1,%r0)
+ bv,n %r0(%r2)
+ ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b)
ENDPROC_CFI(flush_tlb_all_local)
.import cache_info,data
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index e8a6a751dfd8..8ed409ecec93 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -17,6 +17,10 @@
#include <linux/string.h>
EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
#include <linux/atomic.h>
EXPORT_SYMBOL(__xchg8);
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index bc41ca243cfe..cf285b17a5ae 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -34,17 +34,6 @@
#define DBG_RES(x...)
#endif
-/* To be used as: mdelay(pci_post_reset_delay);
- *
- * post_reset is the time the kernel should stall to prevent anyone from
- * accessing the PCI bus once #RESET is de-asserted.
- * PCI spec somewhere says 1 second but with multi-PCI bus systems,
- * this makes the boot time much longer than necessary.
- * 20ms seems to work for all the HP PCI implementations to date.
- *
- * #define pci_post_reset_delay 50
- */
-
struct pci_port_ops *pci_port __ro_after_init;
struct pci_bios_ops *pci_bios __ro_after_init;
diff --git a/arch/parisc/kernel/relocate_kernel.S b/arch/parisc/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..2561e52b8d9b
--- /dev/null
+++ b/arch/parisc/kernel/relocate_kernel.S
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+#include <linux/kexec.h>
+
+#include <asm/assembly.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/psw.h>
+
+.level PA_ASM_LEVEL
+
+.macro kexec_param name
+.align 8
+ENTRY(kexec\()_\name)
+#ifdef CONFIG_64BIT
+ .dword 0
+#else
+ .word 0
+#endif
+
+ENTRY(kexec\()_\name\()_offset)
+ .word kexec\()_\name - relocate_new_kernel
+.endm
+
+.text
+
+/* args:
+ * r26 - kimage->head
+ * r25 - start address of kernel
+ * r24 - physical address of relocate code
+ */
+
+ENTRY_CFI(relocate_new_kernel)
+0: copy %arg1, %rp
+ /* disable I and Q bit, so we are allowed to execute RFI */
+ rsm PSW_SM_I, %r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm PSW_SM_Q, %r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /*
+ * After return-from-interrupt, we want to run without Code/Data
+ * translation enabled just like on a normal boot.
+ */
+
+ /* calculate new physical execution address */
+ ldo 1f-0b(%arg2), %r1
+ mtctl %r0, %cr17 /* IIASQ */
+ mtctl %r0, %cr17 /* IIASQ */
+ mtctl %r1, %cr18 /* IIAOQ */
+ ldo 4(%r1),%r1
+ mtctl %r1, %cr18 /* IIAOQ */
+#ifdef CONFIG_64BIT
+ depdi,z 1, PSW_W_BIT, 1, %r1
+ mtctl %r1, %cr22 /* IPSW */
+#else
+ mtctl %r0, %cr22 /* IPSW */
+#endif
+ /* lets go... */
+ rfi
+1: nop
+ nop
+
+.Lloop:
+ LDREG,ma REG_SZ(%arg0), %r3
+ /* If crash kernel, no copy needed */
+ cmpib,COND(=),n 0,%r3,boot
+
+ bb,<,n %r3, 31 - IND_DONE_BIT, boot
+ bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind
+ /* indirection, load and restart */
+ movb %r3, %arg0, .Lloop
+ depi 0, 31, PAGE_SHIFT, %arg0
+
+.Lnotind:
+ bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest
+ b .Lloop
+ copy %r3, %r20
+
+.Lnotdest:
+ bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop
+ depi 0, 31, PAGE_SHIFT, %r3
+ copy %r3, %r21
+
+ /* copy page */
+ copy %r0, %r18
+ zdepi 1, 31 - PAGE_SHIFT, 1, %r18
+ add %r20, %r18, %r17
+
+ depi 0, 31, PAGE_SHIFT, %r20
+.Lcopy:
+ copy %r20, %r12
+ LDREG,ma REG_SZ(%r21), %r8
+ LDREG,ma REG_SZ(%r21), %r9
+ LDREG,ma REG_SZ(%r21), %r10
+ LDREG,ma REG_SZ(%r21), %r11
+ STREG,ma %r8, REG_SZ(%r20)
+ STREG,ma %r9, REG_SZ(%r20)
+ STREG,ma %r10, REG_SZ(%r20)
+ STREG,ma %r11, REG_SZ(%r20)
+
+#ifndef CONFIG_64BIT
+ LDREG,ma REG_SZ(%r21), %r8
+ LDREG,ma REG_SZ(%r21), %r9
+ LDREG,ma REG_SZ(%r21), %r10
+ LDREG,ma REG_SZ(%r21), %r11
+ STREG,ma %r8, REG_SZ(%r20)
+ STREG,ma %r9, REG_SZ(%r20)
+ STREG,ma %r10, REG_SZ(%r20)
+ STREG,ma %r11, REG_SZ(%r20)
+#endif
+
+ fdc %r0(%r12)
+ cmpb,COND(<<) %r20,%r17,.Lcopy
+ fic (%sr4, %r12)
+ b,n .Lloop
+
+boot:
+ mtctl %r0, %cr15
+
+ LDREG kexec_free_mem-0b(%arg2), %arg0
+ LDREG kexec_cmdline-0b(%arg2), %arg1
+ LDREG kexec_initrd_end-0b(%arg2), %arg3
+ LDREG kexec_initrd_start-0b(%arg2), %arg2
+ bv,n %r0(%rp)
+
+ENDPROC_CFI(relocate_new_kernel);
+
+ENTRY(relocate_new_kernel_size)
+ .word relocate_new_kernel_size - relocate_new_kernel
+
+kexec_param cmdline
+kexec_param initrd_start
+kexec_param initrd_end
+kexec_param free_mem
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index cbd074ba22da..e202c37e56af 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -109,6 +109,7 @@ halt_processor(void)
/* REVISIT : does PM *know* this CPU isn't available? */
set_cpu_online(smp_processor_id(), false);
local_irq_disable();
+ __pdc_cpu_rendezvous();
for (;;)
;
}
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 670d1371aca1..285ff516150c 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -399,7 +399,8 @@
352 common pkey_alloc sys_pkey_alloc
353 common pkey_free sys_pkey_free
354 common rseq sys_rseq
-# 355 through 402 are unassigned to sync up with generic numbers
+355 common kexec_file_load sys_kexec_file_load sys_kexec_file_load
+# up to 402 is unassigned and reserved for arch specific syscalls
403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime
404 32 clock_settime64 sys_clock_settime sys_clock_settime
405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 58dcf445e32f..82fc01189488 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -29,6 +29,7 @@
#include <linux/bug.h>
#include <linux/ratelimit.h>
#include <linux/uaccess.h>
+#include <linux/kdebug.h>
#include <asm/assembly.h>
#include <asm/io.h>
@@ -414,6 +415,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
{
static DEFINE_SPINLOCK(terminate_lock);
+ (void)notify_die(DIE_OOPS, msg, regs, 0, code, SIGTRAP);
bust_spinlocks(1);
set_eiem(0);
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 7b197667faf6..2d7a9974dbae 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -3,7 +3,7 @@
# Makefile for parisc-specific library files
#
-lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \
- ucmpdi2.o delay.o
+lib-y := lusercopy.o bitops.o checksum.o io.o memcpy.o \
+ ucmpdi2.o delay.o string.o
obj-y := iomap.o
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c
deleted file mode 100644
index 1d7929bd7642..000000000000
--- a/arch/parisc/lib/memset.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
-
-#include <linux/types.h>
-#include <asm/string.h>
-
-#define OPSIZ (BITS_PER_LONG/8)
-typedef unsigned long op_t;
-
-void *
-memset (void *dstpp, int sc, size_t len)
-{
- unsigned int c = sc;
- long int dstp = (long int) dstpp;
-
- if (len >= 8)
- {
- size_t xlen;
- op_t cccc;
-
- cccc = (unsigned char) c;
- cccc |= cccc << 8;
- cccc |= cccc << 16;
- if (OPSIZ > 4)
- /* Do the shift in two steps to avoid warning if long has 32 bits. */
- cccc |= (cccc << 16) << 16;
-
- /* There are at least some bytes to set.
- No need to test for LEN == 0 in this alignment loop. */
- while (dstp % OPSIZ != 0)
- {
- ((unsigned char *) dstp)[0] = c;
- dstp += 1;
- len -= 1;
- }
-
- /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
- xlen = len / (OPSIZ * 8);
- while (xlen > 0)
- {
- ((op_t *) dstp)[0] = cccc;
- ((op_t *) dstp)[1] = cccc;
- ((op_t *) dstp)[2] = cccc;
- ((op_t *) dstp)[3] = cccc;
- ((op_t *) dstp)[4] = cccc;
- ((op_t *) dstp)[5] = cccc;
- ((op_t *) dstp)[6] = cccc;
- ((op_t *) dstp)[7] = cccc;
- dstp += 8 * OPSIZ;
- xlen -= 1;
- }
- len %= OPSIZ * 8;
-
- /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
- xlen = len / OPSIZ;
- while (xlen > 0)
- {
- ((op_t *) dstp)[0] = cccc;
- dstp += OPSIZ;
- xlen -= 1;
- }
- len %= OPSIZ;
- }
-
- /* Write the last few bytes. */
- while (len > 0)
- {
- ((unsigned char *) dstp)[0] = c;
- dstp += 1;
- len -= 1;
- }
-
- return dstpp;
-}
diff --git a/arch/parisc/lib/string.S b/arch/parisc/lib/string.S
new file mode 100644
index 000000000000..4a64264427a6
--- /dev/null
+++ b/arch/parisc/lib/string.S
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PA-RISC assembly string functions
+ *
+ * Copyright (C) 2019 Helge Deller <deller@gmx.de>
+ */
+
+#include <asm/assembly.h>
+#include <linux/linkage.h>
+
+ .section .text.hot
+ .level PA_ASM_LEVEL
+
+ t0 = r20
+ t1 = r21
+ t2 = r22
+
+ENTRY_CFI(strlen, frame=0,no_calls)
+ or,COND(<>) arg0,r0,ret0
+ b,l,n .Lstrlen_null_ptr,r0
+ depwi 0,31,2,ret0
+ cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned
+ ldw,ma 4(ret0),t0
+ cmpib,tr 0,r0,.Lstrlen_loop
+ uxor,nbz r0,t0,r0
+.Lstrlen_not_aligned:
+ uaddcm arg0,ret0,t1
+ shladd t1,3,r0,t1
+ mtsar t1
+ depwi -1,%sar,32,t0
+ uxor,nbz r0,t0,r0
+.Lstrlen_loop:
+ b,l,n .Lstrlen_end_loop,r0
+ ldw,ma 4(ret0),t0
+ cmpib,tr 0,r0,.Lstrlen_loop
+ uxor,nbz r0,t0,r0
+.Lstrlen_end_loop:
+ extrw,u,<> t0,7,8,r0
+ addib,tr,n -3,ret0,.Lstrlen_out
+ extrw,u,<> t0,15,8,r0
+ addib,tr,n -2,ret0,.Lstrlen_out
+ extrw,u,<> t0,23,8,r0
+ addi -1,ret0,ret0
+.Lstrlen_out:
+ bv r0(rp)
+ uaddcm ret0,arg0,ret0
+.Lstrlen_null_ptr:
+ bv,n r0(rp)
+ENDPROC_CFI(strlen)
+
+
+ENTRY_CFI(strcpy, frame=0,no_calls)
+ ldb 0(arg1),t0
+ stb t0,0(arg0)
+ ldo 0(arg0),ret0
+ ldo 1(arg1),t1
+ cmpb,= r0,t0,2f
+ ldo 1(arg0),t2
+1: ldb 0(t1),arg1
+ stb arg1,0(t2)
+ ldo 1(t1),t1
+ cmpb,<> r0,arg1,1b
+ ldo 1(t2),t2
+2: bv,n r0(rp)
+ENDPROC_CFI(strcpy)
+
+
+ENTRY_CFI(strncpy, frame=0,no_calls)
+ ldb 0(arg1),t0
+ stb t0,0(arg0)
+ ldo 1(arg1),t1
+ ldo 0(arg0),ret0
+ cmpb,= r0,t0,2f
+ ldo 1(arg0),arg1
+1: ldo -1(arg2),arg2
+ cmpb,COND(=),n r0,arg2,2f
+ ldb 0(t1),arg0
+ stb arg0,0(arg1)
+ ldo 1(t1),t1
+ cmpb,<> r0,arg0,1b
+ ldo 1(arg1),arg1
+2: bv,n r0(rp)
+ENDPROC_CFI(strncpy)
+
+
+ENTRY_CFI(strcat, frame=0,no_calls)
+ ldb 0(arg0),t0
+ cmpb,= t0,r0,2f
+ ldo 0(arg0),ret0
+ ldo 1(arg0),arg0
+1: ldb 0(arg0),t1
+ cmpb,<>,n r0,t1,1b
+ ldo 1(arg0),arg0
+2: ldb 0(arg1),t2
+ stb t2,0(arg0)
+ ldo 1(arg0),arg0
+ ldb 0(arg1),t0
+ cmpb,<> r0,t0,2b
+ ldo 1(arg1),arg1
+ bv,n r0(rp)
+ENDPROC_CFI(strcat)
+
+
+ENTRY_CFI(memset, frame=0,no_calls)
+ copy arg0,ret0
+ cmpb,COND(=) r0,arg0,4f
+ copy arg0,t2
+ cmpb,COND(=) r0,arg2,4f
+ ldo -1(arg2),arg3
+ subi -1,arg3,t0
+ subi 0,t0,t1
+ cmpiclr,COND(>=) 0,t1,arg2
+ ldo -1(t1),arg2
+ extru arg2,31,2,arg0
+2: stb arg1,0(t2)
+ ldo 1(t2),t2
+ addib,>= -1,arg0,2b
+ ldo -1(arg3),arg3
+ cmpiclr,COND(<=) 4,arg2,r0
+ b,l,n 4f,r0
+#ifdef CONFIG_64BIT
+ depd,* r0,63,2,arg2
+#else
+ depw r0,31,2,arg2
+#endif
+ ldo 1(t2),t2
+3: stb arg1,-1(t2)
+ stb arg1,0(t2)
+ stb arg1,1(t2)
+ stb arg1,2(t2)
+ addib,COND(>) -4,arg2,3b
+ ldo 4(t2),t2
+4: bv,n r0(rp)
+ENDPROC_CFI(memset)
+
+ .end
diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile
index b6c4b254901a..3747a0cbd3b8 100644
--- a/arch/parisc/math-emu/Makefile
+++ b/arch/parisc/math-emu/Makefile
@@ -18,3 +18,4 @@ obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
# other very old or stripped-down PA-RISC CPUs -- not currently supported
obj-$(CONFIG_MATH_EMULATION) += unimplemented-math-emulation.o
+CFLAGS_REMOVE_fpudispatch.o = -Wimplicit-fallthrough
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 6dd4669ce7a5..adbd5e2144a3 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -66,6 +66,7 @@ parisc_acctyp(unsigned long code, unsigned int inst)
case 0x30000000: /* coproc2 */
if (bit22set(inst))
return VM_WRITE;
+ /* fall through */
case 0x0: /* indexed/memory management */
if (bit22set(inst)) {
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d8dcd8820369..891cd23f9c8b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -511,6 +511,7 @@ config KEXEC_FILE
select KEXEC_CORE
select HAVE_IMA_KEXEC
select BUILD_BIN2C
+ select KEXEC_ELF
depends on PPC64
depends on CRYPTO=y
depends on CRYPTO_SHA256=y
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index c345b79414a9..403f7e193833 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -39,13 +39,11 @@ endif
uname := $(shell uname -m)
KBUILD_DEFCONFIG := $(if $(filter ppc%,$(uname)),$(uname),ppc64)_defconfig
-ifdef CONFIG_PPC64
new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
ifeq ($(new_nm),y)
NM := $(NM) --synthetic
endif
-endif
# BITS is used as extension for files which are available in a 32 bit
# and a 64 bit version to simplify shared Makefiles.
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index b3388d95f451..45e3137ccd71 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -107,22 +107,22 @@ extern void _set_L3CR(unsigned long);
static inline void dcbz(void *addr)
{
- __asm__ __volatile__ ("dcbz %y0" : : "Z"(*(u8 *)addr) : "memory");
+ __asm__ __volatile__ ("dcbz 0, %0" : : "r"(addr) : "memory");
}
static inline void dcbi(void *addr)
{
- __asm__ __volatile__ ("dcbi %y0" : : "Z"(*(u8 *)addr) : "memory");
+ __asm__ __volatile__ ("dcbi 0, %0" : : "r"(addr) : "memory");
}
static inline void dcbf(void *addr)
{
- __asm__ __volatile__ ("dcbf %y0" : : "Z"(*(u8 *)addr) : "memory");
+ __asm__ __volatile__ ("dcbf 0, %0" : : "r"(addr) : "memory");
}
static inline void dcbst(void *addr)
{
- __asm__ __volatile__ ("dcbst %y0" : : "Z"(*(u8 *)addr) : "memory");
+ __asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory");
}
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/error-injection.h b/arch/powerpc/include/asm/error-injection.h
deleted file mode 100644
index 62fd24739852..000000000000
--- a/arch/powerpc/include/asm/error-injection.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-
-#ifndef _ASM_ERROR_INJECTION_H
-#define _ASM_ERROR_INJECTION_H
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-#include <asm-generic/error-injection.h>
-
-void override_function_with_return(struct pt_regs *regs);
-
-#endif /* _ASM_ERROR_INJECTION_H */
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 463c63a9fcf1..11112023e327 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -302,9 +302,14 @@
#define H_SCM_UNBIND_MEM 0x3F0
#define H_SCM_QUERY_BLOCK_MEM_BINDING 0x3F4
#define H_SCM_QUERY_LOGICAL_MEM_BINDING 0x3F8
-#define H_SCM_MEM_QUERY 0x3FC
-#define H_SCM_BLOCK_CLEAR 0x400
-#define MAX_HCALL_OPCODE H_SCM_BLOCK_CLEAR
+#define H_SCM_UNBIND_ALL 0x3FC
+#define H_SCM_HEALTH 0x400
+#define H_SCM_PERFORMANCE_STATS 0x418
+#define MAX_HCALL_OPCODE H_SCM_PERFORMANCE_STATS
+
+/* Scope args for H_SCM_UNBIND_ALL */
+#define H_UNBIND_SCOPE_ALL (0x1)
+#define H_UNBIND_SCOPE_DRC (0x2)
/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE 0x01
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index bb7c8cc77f1a..04b2b927bb5a 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -535,7 +535,7 @@ static inline void note_hpte_modification(struct kvm *kvm,
*/
static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm)
{
- return rcu_dereference_raw_notrace(kvm->memslots[0]);
+ return rcu_dereference_raw_check(kvm->memslots[0]);
}
extern void kvmppc_mmu_debugfs_init(struct kvm *kvm);
diff --git a/arch/powerpc/include/asm/pmc.h b/arch/powerpc/include/asm/pmc.h
index dc9a1ca70edf..c6bbe9778d3c 100644
--- a/arch/powerpc/include/asm/pmc.h
+++ b/arch/powerpc/include/asm/pmc.h
@@ -27,11 +27,10 @@ static inline void ppc_set_pmu_inuse(int inuse)
#ifdef CONFIG_PPC_PSERIES
get_lppaca()->pmcregs_in_use = inuse;
#endif
- } else {
+ }
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
- get_paca()->pmcregs_in_use = inuse;
+ get_paca()->pmcregs_in_use = inuse;
#endif
- }
#endif
}
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 68473c3c471c..b0720c7c3fcf 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -49,6 +49,7 @@
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
index b551b741653d..5e1e648aeec4 100644
--- a/arch/powerpc/include/uapi/asm/bpf_perf_event.h
+++ b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
#define _UAPI__ASM_BPF_PERF_EVENT_H__
diff --git a/arch/powerpc/include/uapi/asm/kvm_para.h b/arch/powerpc/include/uapi/asm/kvm_para.h
index 01555c6ae0f5..be48c2215fa2 100644
--- a/arch/powerpc/include/uapi/asm/kvm_para.h
+++ b/arch/powerpc/include/uapi/asm/kvm_para.h
@@ -31,7 +31,7 @@
* Struct fields are always 32 or 64 bit aligned, depending on them being 32
* or 64 bit wide respectively.
*
- * See Documentation/virtual/kvm/ppc-pv.txt
+ * See Documentation/virt/kvm/ppc-pv.txt
*/
struct kvm_vcpu_arch_shared {
__u64 scratch1;
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 7107ad86de65..92045ed64976 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -176,9 +176,11 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
ret |= __get_user_inatomic(temp.v[1], p++);
ret |= __get_user_inatomic(temp.v[2], p++);
ret |= __get_user_inatomic(temp.v[3], p++);
+ /* fall through */
case 4:
ret |= __get_user_inatomic(temp.v[4], p++);
ret |= __get_user_inatomic(temp.v[5], p++);
+ /* fall through */
case 2:
ret |= __get_user_inatomic(temp.v[6], p++);
ret |= __get_user_inatomic(temp.v[7], p++);
@@ -259,9 +261,11 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
ret |= __put_user_inatomic(data.v[1], p++);
ret |= __put_user_inatomic(data.v[2], p++);
ret |= __put_user_inatomic(data.v[3], p++);
+ /* fall through */
case 4:
ret |= __put_user_inatomic(data.v[4], p++);
ret |= __put_user_inatomic(data.v[5], p++);
+ /* fall through */
case 2:
ret |= __put_user_inatomic(data.v[6], p++);
ret |= __put_user_inatomic(data.v[7], p++);
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 85fdb6d879f1..54fab22c9a43 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -597,6 +597,14 @@ ppc_clone:
stw r0,_TRAP(r1) /* register set saved */
b sys_clone
+ .globl ppc_clone3
+ppc_clone3:
+ SAVE_NVGPRS(r1)
+ lwz r0,_TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,_TRAP(r1) /* register set saved */
+ b sys_clone3
+
.globl ppc_swapcontext
ppc_swapcontext:
SAVE_NVGPRS(r1)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d9105fcf4021..0a0b5310f54a 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -487,6 +487,11 @@ _GLOBAL(ppc_clone)
bl sys_clone
b .Lsyscall_exit
+_GLOBAL(ppc_clone3)
+ bl save_nvgprs
+ bl sys_clone3
+ b .Lsyscall_exit
+
_GLOBAL(ppc32_swapcontext)
bl save_nvgprs
bl compat_sys_swapcontext
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index eee5bef736c8..6ba3cc2ef8ab 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1531,7 +1531,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
*
* Call convention:
*
- * syscall register convention is in Documentation/powerpc/syscall64-abi.txt
+ * syscall register convention is in Documentation/powerpc/syscall64-abi.rst
*
* For hypercalls, the register convention is as follows:
* r0 volatile
diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 83cf7b852876..3072fd6dbe94 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -23,541 +23,6 @@
#include <linux/slab.h>
#include <linux/types.h>
-#define PURGATORY_STACK_SIZE (16 * 1024)
-
-#define elf_addr_to_cpu elf64_to_cpu
-
-#ifndef Elf_Rel
-#define Elf_Rel Elf64_Rel
-#endif /* Elf_Rel */
-
-struct elf_info {
- /*
- * Where the ELF binary contents are kept.
- * Memory managed by the user of the struct.
- */
- const char *buffer;
-
- const struct elfhdr *ehdr;
- const struct elf_phdr *proghdrs;
- struct elf_shdr *sechdrs;
-};
-
-static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
-{
- return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
-}
-
-static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
-{
- if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
- value = le64_to_cpu(value);
- else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- value = be64_to_cpu(value);
-
- return value;
-}
-
-static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
-{
- if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
- value = le16_to_cpu(value);
- else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- value = be16_to_cpu(value);
-
- return value;
-}
-
-static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
-{
- if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
- value = le32_to_cpu(value);
- else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- value = be32_to_cpu(value);
-
- return value;
-}
-
-/**
- * elf_is_ehdr_sane - check that it is safe to use the ELF header
- * @buf_len: size of the buffer in which the ELF file is loaded.
- */
-static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
-{
- if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
- pr_debug("Bad program header size.\n");
- return false;
- } else if (ehdr->e_shnum > 0 &&
- ehdr->e_shentsize != sizeof(struct elf_shdr)) {
- pr_debug("Bad section header size.\n");
- return false;
- } else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
- ehdr->e_version != EV_CURRENT) {
- pr_debug("Unknown ELF version.\n");
- return false;
- }
-
- if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
- size_t phdr_size;
-
- /*
- * e_phnum is at most 65535 so calculating the size of the
- * program header cannot overflow.
- */
- phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
-
- /* Sanity check the program header table location. */
- if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
- pr_debug("Program headers at invalid location.\n");
- return false;
- } else if (ehdr->e_phoff + phdr_size > buf_len) {
- pr_debug("Program headers truncated.\n");
- return false;
- }
- }
-
- if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
- size_t shdr_size;
-
- /*
- * e_shnum is at most 65536 so calculating
- * the size of the section header cannot overflow.
- */
- shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
-
- /* Sanity check the section header table location. */
- if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
- pr_debug("Section headers at invalid location.\n");
- return false;
- } else if (ehdr->e_shoff + shdr_size > buf_len) {
- pr_debug("Section headers truncated.\n");
- return false;
- }
- }
-
- return true;
-}
-
-static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
-{
- struct elfhdr *buf_ehdr;
-
- if (len < sizeof(*buf_ehdr)) {
- pr_debug("Buffer is too small to hold ELF header.\n");
- return -ENOEXEC;
- }
-
- memset(ehdr, 0, sizeof(*ehdr));
- memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
- if (!elf_is_elf_file(ehdr)) {
- pr_debug("No ELF header magic.\n");
- return -ENOEXEC;
- }
-
- if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
- pr_debug("Not a supported ELF class.\n");
- return -ENOEXEC;
- } else if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
- ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
- pr_debug("Not a supported ELF data format.\n");
- return -ENOEXEC;
- }
-
- buf_ehdr = (struct elfhdr *) buf;
- if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
- pr_debug("Bad ELF header size.\n");
- return -ENOEXEC;
- }
-
- ehdr->e_type = elf16_to_cpu(ehdr, buf_ehdr->e_type);
- ehdr->e_machine = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
- ehdr->e_version = elf32_to_cpu(ehdr, buf_ehdr->e_version);
- ehdr->e_entry = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry);
- ehdr->e_phoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff);
- ehdr->e_shoff = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff);
- ehdr->e_flags = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
- ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
- ehdr->e_phnum = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
- ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
- ehdr->e_shnum = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
- ehdr->e_shstrndx = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
-
- return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
-}
-
-/**
- * elf_is_phdr_sane - check that it is safe to use the program header
- * @buf_len: size of the buffer in which the ELF file is loaded.
- */
-static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
-{
-
- if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
- pr_debug("ELF segment location wraps around.\n");
- return false;
- } else if (phdr->p_offset + phdr->p_filesz > buf_len) {
- pr_debug("ELF segment not in file.\n");
- return false;
- } else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
- pr_debug("ELF segment address wraps around.\n");
- return false;
- }
-
- return true;
-}
-
-static int elf_read_phdr(const char *buf, size_t len, struct elf_info *elf_info,
- int idx)
-{
- /* Override the const in proghdrs, we are the ones doing the loading. */
- struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
- const char *pbuf;
- struct elf_phdr *buf_phdr;
-
- pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
- buf_phdr = (struct elf_phdr *) pbuf;
-
- phdr->p_type = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
- phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset);
- phdr->p_paddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr);
- phdr->p_vaddr = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr);
- phdr->p_flags = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
-
- /*
- * The following fields have a type equivalent to Elf_Addr
- * both in 32 bit and 64 bit ELF.
- */
- phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz);
- phdr->p_memsz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz);
- phdr->p_align = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align);
-
- return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
-}
-
-/**
- * elf_read_phdrs - read the program headers from the buffer
- *
- * This function assumes that the program header table was checked for sanity.
- * Use elf_is_ehdr_sane() if it wasn't.
- */
-static int elf_read_phdrs(const char *buf, size_t len,
- struct elf_info *elf_info)
-{
- size_t phdr_size, i;
- const struct elfhdr *ehdr = elf_info->ehdr;
-
- /*
- * e_phnum is at most 65535 so calculating the size of the
- * program header cannot overflow.
- */
- phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
-
- elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
- if (!elf_info->proghdrs)
- return -ENOMEM;
-
- for (i = 0; i < ehdr->e_phnum; i++) {
- int ret;
-
- ret = elf_read_phdr(buf, len, elf_info, i);
- if (ret) {
- kfree(elf_info->proghdrs);
- elf_info->proghdrs = NULL;
- return ret;
- }
- }
-
- return 0;
-}
-
-/**
- * elf_is_shdr_sane - check that it is safe to use the section header
- * @buf_len: size of the buffer in which the ELF file is loaded.
- */
-static bool elf_is_shdr_sane(const struct elf_shdr *shdr, size_t buf_len)
-{
- bool size_ok;
-
- /* SHT_NULL headers have undefined values, so we can't check them. */
- if (shdr->sh_type == SHT_NULL)
- return true;
-
- /* Now verify sh_entsize */
- switch (shdr->sh_type) {
- case SHT_SYMTAB:
- size_ok = shdr->sh_entsize == sizeof(Elf_Sym);
- break;
- case SHT_RELA:
- size_ok = shdr->sh_entsize == sizeof(Elf_Rela);
- break;
- case SHT_DYNAMIC:
- size_ok = shdr->sh_entsize == sizeof(Elf_Dyn);
- break;
- case SHT_REL:
- size_ok = shdr->sh_entsize == sizeof(Elf_Rel);
- break;
- case SHT_NOTE:
- case SHT_PROGBITS:
- case SHT_HASH:
- case SHT_NOBITS:
- default:
- /*
- * This is a section whose entsize requirements
- * I don't care about. If I don't know about
- * the section I can't care about it's entsize
- * requirements.
- */
- size_ok = true;
- break;
- }
-
- if (!size_ok) {
- pr_debug("ELF section with wrong entry size.\n");
- return false;
- } else if (shdr->sh_addr + shdr->sh_size < shdr->sh_addr) {
- pr_debug("ELF section address wraps around.\n");
- return false;
- }
-
- if (shdr->sh_type != SHT_NOBITS) {
- if (shdr->sh_offset + shdr->sh_size < shdr->sh_offset) {
- pr_debug("ELF section location wraps around.\n");
- return false;
- } else if (shdr->sh_offset + shdr->sh_size > buf_len) {
- pr_debug("ELF section not in file.\n");
- return false;
- }
- }
-
- return true;
-}
-
-static int elf_read_shdr(const char *buf, size_t len, struct elf_info *elf_info,
- int idx)
-{
- struct elf_shdr *shdr = &elf_info->sechdrs[idx];
- const struct elfhdr *ehdr = elf_info->ehdr;
- const char *sbuf;
- struct elf_shdr *buf_shdr;
-
- sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
- buf_shdr = (struct elf_shdr *) sbuf;
-
- shdr->sh_name = elf32_to_cpu(ehdr, buf_shdr->sh_name);
- shdr->sh_type = elf32_to_cpu(ehdr, buf_shdr->sh_type);
- shdr->sh_addr = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
- shdr->sh_offset = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
- shdr->sh_link = elf32_to_cpu(ehdr, buf_shdr->sh_link);
- shdr->sh_info = elf32_to_cpu(ehdr, buf_shdr->sh_info);
-
- /*
- * The following fields have a type equivalent to Elf_Addr
- * both in 32 bit and 64 bit ELF.
- */
- shdr->sh_flags = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
- shdr->sh_size = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
- shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
- shdr->sh_entsize = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);
-
- return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
-}
-
-/**
- * elf_read_shdrs - read the section headers from the buffer
- *
- * This function assumes that the section header table was checked for sanity.
- * Use elf_is_ehdr_sane() if it wasn't.
- */
-static int elf_read_shdrs(const char *buf, size_t len,
- struct elf_info *elf_info)
-{
- size_t shdr_size, i;
-
- /*
- * e_shnum is at most 65536 so calculating
- * the size of the section header cannot overflow.
- */
- shdr_size = sizeof(struct elf_shdr) * elf_info->ehdr->e_shnum;
-
- elf_info->sechdrs = kzalloc(shdr_size, GFP_KERNEL);
- if (!elf_info->sechdrs)
- return -ENOMEM;
-
- for (i = 0; i < elf_info->ehdr->e_shnum; i++) {
- int ret;
-
- ret = elf_read_shdr(buf, len, elf_info, i);
- if (ret) {
- kfree(elf_info->sechdrs);
- elf_info->sechdrs = NULL;
- return ret;
- }
- }
-
- return 0;
-}
-
-/**
- * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
- * @buf: Buffer to read ELF file from.
- * @len: Size of @buf.
- * @ehdr: Pointer to existing struct which will be populated.
- * @elf_info: Pointer to existing struct which will be populated.
- *
- * This function allows reading ELF files with different byte order than
- * the kernel, byte-swapping the fields as needed.
- *
- * Return:
- * On success returns 0, and the caller should call elf_free_info(elf_info) to
- * free the memory allocated for the section and program headers.
- */
-int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr,
- struct elf_info *elf_info)
-{
- int ret;
-
- ret = elf_read_ehdr(buf, len, ehdr);
- if (ret)
- return ret;
-
- elf_info->buffer = buf;
- elf_info->ehdr = ehdr;
- if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
- ret = elf_read_phdrs(buf, len, elf_info);
- if (ret)
- return ret;
- }
- if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
- ret = elf_read_shdrs(buf, len, elf_info);
- if (ret) {
- kfree(elf_info->proghdrs);
- return ret;
- }
- }
-
- return 0;
-}
-
-/**
- * elf_free_info - free memory allocated by elf_read_from_buffer
- */
-void elf_free_info(struct elf_info *elf_info)
-{
- kfree(elf_info->proghdrs);
- kfree(elf_info->sechdrs);
- memset(elf_info, 0, sizeof(*elf_info));
-}
-/**
- * build_elf_exec_info - read ELF executable and check that we can use it
- */
-static int build_elf_exec_info(const char *buf, size_t len, struct elfhdr *ehdr,
- struct elf_info *elf_info)
-{
- int i;
- int ret;
-
- ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
- if (ret)
- return ret;
-
- /* Big endian vmlinux has type ET_DYN. */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
- pr_err("Not an ELF executable.\n");
- goto error;
- } else if (!elf_info->proghdrs) {
- pr_err("No ELF program header.\n");
- goto error;
- }
-
- for (i = 0; i < ehdr->e_phnum; i++) {
- /*
- * Kexec does not support loading interpreters.
- * In addition this check keeps us from attempting
- * to kexec ordinay executables.
- */
- if (elf_info->proghdrs[i].p_type == PT_INTERP) {
- pr_err("Requires an ELF interpreter.\n");
- goto error;
- }
- }
-
- return 0;
-error:
- elf_free_info(elf_info);
- return -ENOEXEC;
-}
-
-static int elf64_probe(const char *buf, unsigned long len)
-{
- struct elfhdr ehdr;
- struct elf_info elf_info;
- int ret;
-
- ret = build_elf_exec_info(buf, len, &ehdr, &elf_info);
- if (ret)
- return ret;
-
- elf_free_info(&elf_info);
-
- return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
-}
-
-/**
- * elf_exec_load - load ELF executable image
- * @lowest_load_addr: On return, will be the address where the first PT_LOAD
- * section will be loaded in memory.
- *
- * Return:
- * 0 on success, negative value on failure.
- */
-static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
- struct elf_info *elf_info,
- unsigned long *lowest_load_addr)
-{
- unsigned long base = 0, lowest_addr = UINT_MAX;
- int ret;
- size_t i;
- struct kexec_buf kbuf = { .image = image, .buf_max = ppc64_rma_size,
- .top_down = false };
-
- /* Read in the PT_LOAD segments. */
- for (i = 0; i < ehdr->e_phnum; i++) {
- unsigned long load_addr;
- size_t size;
- const struct elf_phdr *phdr;
-
- phdr = &elf_info->proghdrs[i];
- if (phdr->p_type != PT_LOAD)
- continue;
-
- size = phdr->p_filesz;
- if (size > phdr->p_memsz)
- size = phdr->p_memsz;
-
- kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
- kbuf.bufsz = size;
- kbuf.memsz = phdr->p_memsz;
- kbuf.buf_align = phdr->p_align;
- kbuf.buf_min = phdr->p_paddr + base;
- kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
- ret = kexec_add_buffer(&kbuf);
- if (ret)
- goto out;
- load_addr = kbuf.mem;
-
- if (load_addr < lowest_addr)
- lowest_addr = load_addr;
- }
-
- /* Update entry point to reflect new load address. */
- ehdr->e_entry += base;
-
- *lowest_load_addr = lowest_addr;
- ret = 0;
- out:
- return ret;
-}
-
static void *elf64_load(struct kimage *image, char *kernel_buf,
unsigned long kernel_len, char *initrd,
unsigned long initrd_len, char *cmdline,
@@ -570,18 +35,18 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
void *fdt;
const void *slave_code;
struct elfhdr ehdr;
- struct elf_info elf_info;
+ struct kexec_elf_info elf_info;
struct kexec_buf kbuf = { .image = image, .buf_min = 0,
.buf_max = ppc64_rma_size };
struct kexec_buf pbuf = { .image = image, .buf_min = 0,
.buf_max = ppc64_rma_size, .top_down = true,
.mem = KEXEC_BUF_MEM_UNKNOWN };
- ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
+ ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
if (ret)
goto out;
- ret = elf_exec_load(image, &ehdr, &elf_info, &kernel_load_addr);
+ ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
if (ret)
goto out;
@@ -648,13 +113,13 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
pr_err("Error setting up the purgatory.\n");
out:
- elf_free_info(&elf_info);
+ kexec_free_elf_info(&elf_info);
/* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
return ret ? ERR_PTR(ret) : fdt;
}
const struct kexec_file_ops kexec_elf64_ops = {
- .probe = elf64_probe,
+ .probe = kexec_elf_probe,
.load = elf64_load,
};
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 8fc4de0d22b4..7a84c9f1778e 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -101,21 +101,8 @@ static void check_if_tm_restore_required(struct task_struct *tsk)
}
}
-static bool tm_active_with_fp(struct task_struct *tsk)
-{
- return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
- (tsk->thread.ckpt_regs.msr & MSR_FP);
-}
-
-static bool tm_active_with_altivec(struct task_struct *tsk)
-{
- return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
- (tsk->thread.ckpt_regs.msr & MSR_VEC);
-}
#else
static inline void check_if_tm_restore_required(struct task_struct *tsk) { }
-static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; }
-static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; }
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
bool strict_msr_control;
@@ -252,7 +239,7 @@ EXPORT_SYMBOL(enable_kernel_fp);
static int restore_fp(struct task_struct *tsk)
{
- if (tsk->thread.load_fp || tm_active_with_fp(tsk)) {
+ if (tsk->thread.load_fp) {
load_fp_state(&current->thread.fp_state);
current->thread.load_fp++;
return 1;
@@ -334,8 +321,7 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
static int restore_altivec(struct task_struct *tsk)
{
- if (cpu_has_feature(CPU_FTR_ALTIVEC) &&
- (tsk->thread.load_vec || tm_active_with_altivec(tsk))) {
+ if (cpu_has_feature(CPU_FTR_ALTIVEC) && (tsk->thread.load_vec)) {
load_vr_state(&tsk->thread.vr_state);
tsk->thread.used_vr = 1;
tsk->thread.load_vec++;
@@ -497,13 +483,14 @@ void giveup_all(struct task_struct *tsk)
if (!tsk->thread.regs)
return;
+ check_if_tm_restore_required(tsk);
+
usermsr = tsk->thread.regs->msr;
if ((usermsr & msr_all_available) == 0)
return;
msr_check_and_set(msr_all_available);
- check_if_tm_restore_required(tsk);
WARN_ON((usermsr & MSR_VSX) && !((usermsr & MSR_FP) && (usermsr & MSR_VEC)));
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index f50b708d6d77..98600b276f76 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -1198,6 +1198,9 @@ SYSCALL_DEFINE0(rt_sigreturn)
goto bad;
if (MSR_TM_ACTIVE(msr_hi<<32)) {
+ /* Trying to start TM on non TM system */
+ if (!cpu_has_feature(CPU_FTR_TM))
+ goto bad;
/* We only recheckpoint on return if we're
* transaction.
*/
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 2f80e270c7b0..117515564ec7 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -771,6 +771,11 @@ SYSCALL_DEFINE0(rt_sigreturn)
if (MSR_TM_ACTIVE(msr)) {
/* We recheckpoint on return. */
struct ucontext __user *uc_transact;
+
+ /* Trying to start TM on non TM system */
+ if (!cpu_has_feature(CPU_FTR_TM))
+ goto badframe;
+
if (__get_user(uc_transact, &uc->uc_link))
goto badframe;
if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index 3331749aab20..43f736ed47f2 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -516,4 +516,4 @@
432 common fsmount sys_fsmount
433 common fspick sys_fspick
434 common pidfd_open sys_pidfd_open
-# 435 reserved for clone3
+435 nospu clone3 ppc_clone3
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 653936177857..18f244aad7aa 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -239,6 +239,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
case 2:
case 6:
pte->may_write = true;
+ /* fall through */
case 3:
case 5:
case 7:
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index e99a14798ab0..c4b606fe73eb 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -660,8 +660,10 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
}
tce = be64_to_cpu(tce);
- if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua))
- return H_PARAMETER;
+ if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) {
+ ret = H_PARAMETER;
+ goto unlock_exit;
+ }
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
ret = kvmppc_tce_iommu_map(vcpu->kvm, stt,
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index f50bbeedfc66..b4f20f13b860 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -556,8 +556,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
unsigned long tce = be64_to_cpu(((u64 *)tces)[i]);
ua = 0;
- if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua, NULL))
- return H_PARAMETER;
+ if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) {
+ ret = H_PARAMETER;
+ goto unlock_exit;
+ }
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index ec1804f822af..cde3f5a4b3e4 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -3569,9 +3569,18 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
mtspr(SPRN_DEC, vcpu->arch.dec_expires - mftb());
if (kvmhv_on_pseries()) {
+ /*
+ * We need to save and restore the guest visible part of the
+ * psscr (i.e. using SPRN_PSSCR_PR) since the hypervisor
+ * doesn't do this for us. Note only required if pseries since
+ * this is done in kvmhv_load_hv_regs_and_go() below otherwise.
+ */
+ unsigned long host_psscr;
/* call our hypervisor to load up HV regs and go */
struct hv_guest_state hvregs;
+ host_psscr = mfspr(SPRN_PSSCR_PR);
+ mtspr(SPRN_PSSCR_PR, vcpu->arch.psscr);
kvmhv_save_hv_regs(vcpu, &hvregs);
hvregs.lpcr = lpcr;
vcpu->arch.regs.msr = vcpu->arch.shregs.msr;
@@ -3590,6 +3599,8 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
vcpu->arch.shregs.msr = vcpu->arch.regs.msr;
vcpu->arch.shregs.dar = mfspr(SPRN_DAR);
vcpu->arch.shregs.dsisr = mfspr(SPRN_DSISR);
+ vcpu->arch.psscr = mfspr(SPRN_PSSCR_PR);
+ mtspr(SPRN_PSSCR_PR, host_psscr);
/* H_CEDE has to be handled now, not later */
if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested &&
@@ -3654,6 +3665,8 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
vcpu->arch.vpa.dirty = 1;
save_pmu = lp->pmcregs_in_use;
}
+ /* Must save pmu if this guest is capable of running nested guests */
+ save_pmu |= nesting_enabled(vcpu->kvm);
kvmhv_save_guest_pmu(vcpu, save_pmu);
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
index 6ca0d7376a9f..e3ba67095895 100644
--- a/arch/powerpc/kvm/book3s_xive.c
+++ b/arch/powerpc/kvm/book3s_xive.c
@@ -1986,10 +1986,8 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
xive->single_escalation = xive_native_has_single_escalation();
- if (ret) {
- kfree(xive);
+ if (ret)
return ret;
- }
return 0;
}
diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
index 5596c8ec221a..a998823f68a3 100644
--- a/arch/powerpc/kvm/book3s_xive_native.c
+++ b/arch/powerpc/kvm/book3s_xive_native.c
@@ -1090,9 +1090,9 @@ static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type)
xive->ops = &kvmppc_xive_native_ops;
if (ret)
- kfree(xive);
+ return ret;
- return ret;
+ return 0;
}
/*
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 0dba7eb24f92..3e566c2e6066 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -50,6 +50,11 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
return !!(v->arch.pending_exceptions) || kvm_request_pending(v);
}
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+ return kvm_arch_vcpu_runnable(vcpu);
+}
+
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
{
return false;
@@ -452,16 +457,6 @@ err_out:
return -EINVAL;
}
-bool kvm_arch_has_vcpu_debugfs(void)
-{
- return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
- return 0;
-}
-
void kvm_arch_destroy_vm(struct kvm *kvm)
{
unsigned int i;
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index 9a5963e07a82..b8ad14bb1170 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -1899,11 +1899,20 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
*
* For guests on platforms before POWER9, we clamp the it limit to 1G
* to avoid some funky things such as RTAS bugs etc...
+ *
+ * On POWER9 we limit to 1TB in case the host erroneously told us that
+ * the RMA was >1TB. Effective address bits 0:23 are treated as zero
+ * (meaning the access is aliased to zero i.e. addr = addr % 1TB)
+ * for virtual real mode addressing and so it doesn't make sense to
+ * have an area larger than 1TB as it can't be addressed.
*/
if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
ppc64_rma_size = first_memblock_size;
if (!early_cpu_has_feature(CPU_FTR_ARCH_300))
ppc64_rma_size = min_t(u64, ppc64_rma_size, 0x40000000);
+ else
+ ppc64_rma_size = min_t(u64, ppc64_rma_size,
+ 1UL << SID_SHIFT_1T);
/* Finally limit subsequent allocations */
memblock_set_current_limit(ppc64_rma_size);
diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/kasan_init_32.c
index 0d62be3cba47..74f4555a62ba 100644
--- a/arch/powerpc/mm/kasan/kasan_init_32.c
+++ b/arch/powerpc/mm/kasan/kasan_init_32.c
@@ -21,7 +21,7 @@ static void kasan_populate_pte(pte_t *ptep, pgprot_t prot)
__set_pte_at(&init_mm, va, ptep, pfn_pte(PHYS_PFN(pa), prot), 0);
}
-static int kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_end)
+static int __ref kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_end)
{
pmd_t *pmd;
unsigned long k_cur, k_next;
@@ -35,7 +35,10 @@ static int kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_
if ((void *)pmd_page_vaddr(*pmd) != kasan_early_shadow_pte)
continue;
- new = pte_alloc_one_kernel(&init_mm);
+ if (slab_is_available())
+ new = pte_alloc_one_kernel(&init_mm);
+ else
+ new = memblock_alloc(PTE_FRAG_SIZE, PTE_FRAG_SIZE);
if (!new)
return -ENOMEM;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 9259337d7374..9191a66b3bc5 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -239,7 +239,7 @@ void __init paging_init(void)
#ifdef CONFIG_ZONE_DMA
max_zone_pfns[ZONE_DMA] = min(max_low_pfn,
- ((1UL << ARCH_ZONE_DMA_BITS) - 1) >> PAGE_SHIFT);
+ 1UL << (ARCH_ZONE_DMA_BITS - PAGE_SHIFT));
#endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index d4acf6fa0596..bf60983a58c7 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -630,7 +630,6 @@ static void early_init_this_mmu(void)
#ifdef CONFIG_PPC_FSL_BOOK3E
if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
unsigned int num_cams;
- int __maybe_unused cpu = smp_processor_id();
bool map = true;
/* use a quarter of the TLBCAM for bolted linear map */
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index c8ec670ee924..a5ac371a3f06 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -11,6 +11,7 @@
#include <linux/sched.h>
#include <linux/libnvdimm.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <asm/plpar_wrappers.h>
@@ -43,8 +44,9 @@ struct papr_scm_priv {
static int drc_pmem_bind(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
- uint64_t rc, token;
uint64_t saved = 0;
+ uint64_t token;
+ int64_t rc;
/*
* When the hypervisor cannot map all the requested memory in a single
@@ -64,6 +66,10 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
} while (rc == H_BUSY);
if (rc) {
+ /* H_OVERLAP needs a separate error path */
+ if (rc == H_OVERLAP)
+ return -EBUSY;
+
dev_err(&p->pdev->dev, "bind err: %lld\n", rc);
return -ENXIO;
}
@@ -78,22 +84,36 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
static int drc_pmem_unbind(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
- uint64_t rc, token;
+ uint64_t token = 0;
+ int64_t rc;
- token = 0;
+ dev_dbg(&p->pdev->dev, "unbind drc %x\n", p->drc_index);
- /* NB: unbind has the same retry requirements mentioned above */
+ /* NB: unbind has the same retry requirements as drc_pmem_bind() */
do {
- rc = plpar_hcall(H_SCM_UNBIND_MEM, ret, p->drc_index,
- p->bound_addr, p->blocks, token);
+
+ /* Unbind of all SCM resources associated with drcIndex */
+ rc = plpar_hcall(H_SCM_UNBIND_ALL, ret, H_UNBIND_SCOPE_DRC,
+ p->drc_index, token);
token = ret[0];
- cond_resched();
+
+ /* Check if we are stalled for some time */
+ if (H_IS_LONG_BUSY(rc)) {
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ } else if (rc == H_BUSY) {
+ cond_resched();
+ }
+
} while (rc == H_BUSY);
if (rc)
dev_err(&p->pdev->dev, "unbind error: %lld\n", rc);
+ else
+ dev_dbg(&p->pdev->dev, "unbind drc %x complete\n",
+ p->drc_index);
- return !!rc;
+ return rc == H_SUCCESS ? 0 : -ENXIO;
}
static int papr_scm_meta_get(struct papr_scm_priv *p,
@@ -255,12 +275,32 @@ static const struct attribute_group *papr_scm_dimm_groups[] = {
NULL,
};
+static inline int papr_scm_node(int node)
+{
+ int min_dist = INT_MAX, dist;
+ int nid, min_node;
+
+ if ((node == NUMA_NO_NODE) || node_online(node))
+ return node;
+
+ min_node = first_online_node;
+ for_each_online_node(nid) {
+ dist = node_distance(node, nid);
+ if (dist < min_dist) {
+ min_dist = dist;
+ min_node = nid;
+ }
+ }
+ return min_node;
+}
+
static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
{
struct device *dev = &p->pdev->dev;
struct nd_mapping_desc mapping;
struct nd_region_desc ndr_desc;
unsigned long dimm_flags;
+ int target_nid, online_nid;
p->bus_desc.ndctl = papr_scm_ndctl;
p->bus_desc.module = THIS_MODULE;
@@ -299,8 +339,10 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
memset(&ndr_desc, 0, sizeof(ndr_desc));
ndr_desc.attr_groups = region_attr_groups;
- ndr_desc.numa_node = dev_to_node(&p->pdev->dev);
- ndr_desc.target_node = ndr_desc.numa_node;
+ target_nid = dev_to_node(&p->pdev->dev);
+ online_nid = papr_scm_node(target_nid);
+ ndr_desc.numa_node = online_nid;
+ ndr_desc.target_node = target_nid;
ndr_desc.res = &p->res;
ndr_desc.of_node = p->dn;
ndr_desc.provider_data = p;
@@ -318,6 +360,9 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
ndr_desc.res, p->dn);
goto err;
}
+ if (target_nid != online_nid)
+ dev_info(dev, "Region registered with target node %d and online node %d",
+ target_nid, online_nid);
return 0;
@@ -389,6 +434,14 @@ static int papr_scm_probe(struct platform_device *pdev)
/* request the hypervisor to bind this region to somewhere in memory */
rc = drc_pmem_bind(p);
+
+ /* If phyp says drc memory still bound then force unbound and retry */
+ if (rc == -EBUSY) {
+ dev_warn(&pdev->dev, "Retrying bind after unbinding\n");
+ drc_pmem_unbind(p);
+ rc = drc_pmem_bind(p);
+ }
+
if (rc)
goto err;
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index 082c7e1c20f0..1cdb39575eae 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -479,7 +479,7 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
* Now go through the entire mask until we find a valid
* target.
*/
- for (;;) {
+ do {
/*
* We re-check online as the fallback case passes us
* an untested affinity mask
@@ -487,12 +487,11 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
if (cpu_online(cpu) && xive_try_pick_target(cpu))
return cpu;
cpu = cpumask_next(cpu, mask);
- if (cpu == first)
- break;
/* Wrap around */
if (cpu >= nr_cpu_ids)
cpu = cpumask_first(mask);
- }
+ } while (cpu != first);
+
return -1;
}
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/riscv/Kbuild
index 2eb23c0cb6b0..d1d0aa70fdf1 100644
--- a/arch/arm/mach-netx/Makefile.boot
+++ b/arch/riscv/Kbuild
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
- zreladdr-y += 0x80008000
+obj-y += kernel/ mm/ net/
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 59a4727ecd6c..1211543c330c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -35,6 +35,8 @@ config RISCV
select HAVE_DMA_CONTIGUOUS
select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
select HAVE_SYSCALL_TRACEPOINTS
select IRQ_DOMAIN
select SPARSE_IRQ
@@ -48,12 +50,14 @@ config RISCV
select PCI_MSI if PCI
select RISCV_TIMER
select GENERIC_IRQ_MULTI_HANDLER
+ select GENERIC_ARCH_TOPOLOGY if SMP
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_MMIOWB
select HAVE_EBPF_JIT if 64BIT
select EDAC_SUPPORT
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
+ select SPARSEMEM_STATIC if 32BIT
config MMU
def_bool y
@@ -62,12 +66,32 @@ config ZONE_DMA32
bool
default y if 64BIT
+config VA_BITS
+ int
+ default 32 if 32BIT
+ default 39 if 64BIT
+
+config PA_BITS
+ int
+ default 34 if 32BIT
+ default 56 if 64BIT
+
config PAGE_OFFSET
hex
default 0xC0000000 if 32BIT && MAXPHYSMEM_2GB
default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB
default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ select SPARSEMEM_VMEMMAP_ENABLE
+
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool ARCH_SPARSEMEM_ENABLE
+
config ARCH_WANT_GENERAL_HUGETLB
def_bool y
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 7a117be8297c..4f0a3d2018d2 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -54,6 +54,9 @@ endif
ifeq ($(CONFIG_MODULE_SECTIONS),y)
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/riscv/kernel/module.lds
endif
+ifeq ($(CONFIG_PERF_EVENTS),y)
+ KBUILD_CFLAGS += -fno-omit-frame-pointer
+endif
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
@@ -72,7 +75,7 @@ KBUILD_IMAGE := $(boot)/Image.gz
head-y := arch/riscv/kernel/head.o
-core-y += arch/riscv/kernel/ arch/riscv/mm/ arch/riscv/net/
+core-y += arch/riscv/
libs-y += arch/riscv/lib/
diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
index 40983491b95f..42b5ec223100 100644
--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
@@ -21,7 +21,6 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- timebase-frequency = <1000000>;
cpu0: cpu@0 {
compatible = "sifive,e51", "sifive,rocket0", "riscv";
device_type = "cpu";
@@ -217,5 +216,20 @@
#size-cells = <0>;
status = "disabled";
};
+ eth0: ethernet@10090000 {
+ compatible = "sifive,fu540-c000-gem";
+ interrupt-parent = <&plic0>;
+ interrupts = <53>;
+ reg = <0x0 0x10090000 0x0 0x2000
+ 0x0 0x100a0000 0x0 0x1000>;
+ local-mac-address = [00 00 00 00 00 00];
+ clock-names = "pclk", "hclk";
+ clocks = <&prci PRCI_CLK_GEMGXLPLL>,
+ <&prci PRCI_CLK_GEMGXLPLL>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
};
};
diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
index 0b55c53c08c7..93d68cbd64fe 100644
--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
@@ -76,3 +76,12 @@
disable-wp;
};
};
+
+&eth0 {
+ status = "okay";
+ phy-mode = "gmii";
+ phy-handle = <&phy0>;
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index b7b749b18853..3efff552a261 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_PCIEPORTBUS=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_XILINX=y
CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_SD=y
@@ -53,6 +54,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_SPI=y
+CONFIG_SPI_SIFIVE=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_DRM=y
CONFIG_DRM_RADEON=y
@@ -66,8 +71,9 @@ CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
CONFIG_VIRTIO_MMIO=y
-CONFIG_SPI_SIFIVE=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_AUTOFS4_FS=y
@@ -83,8 +89,4 @@ CONFIG_ROOT_NFS=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_PRINTK_TIME=y
-CONFIG_SPI=y
-CONFIG_MMC_SPI=y
-CONFIG_MMC=y
-CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_RCU_TRACE is not set
diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig
index d5449ef805a3..7da93e494445 100644
--- a/arch/riscv/configs/rv32_defconfig
+++ b/arch/riscv/configs/rv32_defconfig
@@ -34,6 +34,7 @@ CONFIG_PCIEPORTBUS=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_XILINX=y
CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_SD=y
@@ -53,6 +54,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_DRM=y
CONFIG_DRM_RADEON=y
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 1efaeddf1e4b..16970f246860 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -22,6 +22,7 @@ generic-y += kvm_para.h
generic-y += local.h
generic-y += local64.h
generic-y += mm-arch-hooks.h
+generic-y += msi.h
generic-y += percpu.h
generic-y += preempt.h
generic-y += sections.h
diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
index 9c66033c3a54..161f28d04a07 100644
--- a/arch/riscv/include/asm/fixmap.h
+++ b/arch/riscv/include/asm/fixmap.h
@@ -30,10 +30,6 @@ enum fixed_addresses {
__end_of_fixed_addresses
};
-#define FIXADDR_SIZE (__end_of_fixed_addresses * PAGE_SIZE)
-#define FIXADDR_TOP (VMALLOC_START)
-#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
-
#define FIXMAP_PAGE_IO PAGE_KERNEL
#define __early_set_fixmap __set_fixmap
diff --git a/arch/riscv/include/asm/image.h b/arch/riscv/include/asm/image.h
index ef28e106f247..344db5244547 100644
--- a/arch/riscv/include/asm/image.h
+++ b/arch/riscv/include/asm/image.h
@@ -3,7 +3,8 @@
#ifndef __ASM_IMAGE_H
#define __ASM_IMAGE_H
-#define RISCV_IMAGE_MAGIC "RISCV"
+#define RISCV_IMAGE_MAGIC "RISCV\0\0\0"
+#define RISCV_IMAGE_MAGIC2 "RSC\x05"
#define RISCV_IMAGE_FLAG_BE_SHIFT 0
#define RISCV_IMAGE_FLAG_BE_MASK 0x1
@@ -23,7 +24,7 @@
#define __HEAD_FLAGS (__HEAD_FLAG(BE))
#define RISCV_HEADER_VERSION_MAJOR 0
-#define RISCV_HEADER_VERSION_MINOR 1
+#define RISCV_HEADER_VERSION_MINOR 2
#define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \
RISCV_HEADER_VERSION_MINOR)
@@ -39,9 +40,8 @@
* @version: version
* @res1: reserved
* @res2: reserved
- * @magic: Magic number
- * @res3: reserved (will be used for additional RISC-V specific
- * header)
+ * @magic: Magic number (RISC-V specific; deprecated)
+ * @magic2: Magic number 2 (to match the ARM64 'magic' field pos)
* @res4: reserved (will be used for PE COFF offset)
*
* The intention is for this header format to be shared between multiple
@@ -58,7 +58,7 @@ struct riscv_image_header {
u32 res1;
u64 res2;
u64 magic;
- u32 res3;
+ u32 magic2;
u32 res4;
};
#endif /* __ASSEMBLY__ */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 707e00a8430b..3db261c4810f 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -110,8 +110,10 @@ extern unsigned long min_low_pfn;
#define page_to_bus(page) (page_to_phys(page))
#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr)))
+#ifdef CONFIG_FLATMEM
#define pfn_valid(pfn) \
(((pfn) >= pfn_base) && (((pfn)-pfn_base) < max_mapnr))
+#endif
#define ARCH_PFN_OFFSET (pfn_base)
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index a364aba23d55..80905b27ee98 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -84,6 +84,19 @@ extern pgd_t swapper_pg_dir[];
#define __S111 PAGE_SHARED_EXEC
/*
+ * Roughly size the vmemmap space to be large enough to fit enough
+ * struct pages to map half the virtual address space. Then
+ * position vmemmap directly below the VMALLOC region.
+ */
+#define VMEMMAP_SHIFT \
+ (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
+#define VMEMMAP_SIZE BIT(VMEMMAP_SHIFT)
+#define VMEMMAP_END (VMALLOC_START - 1)
+#define VMEMMAP_START (VMALLOC_START - VMEMMAP_SIZE)
+
+#define vmemmap ((struct page *)VMEMMAP_START)
+
+/*
* ZERO_PAGE is a global shared page that is always zero,
* used for zero-mapped memory areas, etc.
*/
@@ -420,14 +433,22 @@ static inline void pgtable_cache_init(void)
#define VMALLOC_END (PAGE_OFFSET - 1)
#define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE)
+#define FIXADDR_TOP VMALLOC_START
+#ifdef CONFIG_64BIT
+#define FIXADDR_SIZE PMD_SIZE
+#else
+#define FIXADDR_SIZE PGDIR_SIZE
+#endif
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
/*
- * Task size is 0x4000000000 for RV64 or 0xb800000 for RV32.
+ * Task size is 0x4000000000 for RV64 or 0x9fc00000 for RV32.
* Note that PGDIR_SIZE must evenly divide TASK_SIZE.
*/
#ifdef CONFIG_64BIT
#define TASK_SIZE (PGDIR_SIZE * PTRS_PER_PGD / 2)
#else
-#define TASK_SIZE VMALLOC_START
+#define TASK_SIZE FIXADDR_START
#endif
#include <asm-generic/pgtable.h>
diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index c6ed4d691def..a83451d73a4e 100644
--- a/arch/riscv/include/asm/smp.h
+++ b/arch/riscv/include/asm/smp.h
@@ -61,11 +61,5 @@ static inline unsigned long cpuid_to_hartid_map(int cpu)
return boot_cpu_hartid;
}
-static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in,
- struct cpumask *out)
-{
- cpumask_set_cpu(cpuid_to_hartid_map(0), out);
-}
-
#endif /* CONFIG_SMP */
#endif /* _ASM_RISCV_SMP_H */
diff --git a/arch/riscv/include/asm/sparsemem.h b/arch/riscv/include/asm/sparsemem.h
new file mode 100644
index 000000000000..b58ba2d9ed6e
--- /dev/null
+++ b/arch/riscv/include/asm/sparsemem.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_SPARSEMEM_H
+#define __ASM_SPARSEMEM_H
+
+#ifdef CONFIG_SPARSEMEM
+#define MAX_PHYSMEM_BITS CONFIG_PA_BITS
+#define SECTION_SIZE_BITS 27
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* __ASM_SPARSEMEM_H */
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 853b65ef656d..f0227bdce0f0 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -16,7 +16,13 @@ extern void __fstate_restore(struct task_struct *restore_from);
static inline void __fstate_clean(struct pt_regs *regs)
{
- regs->sstatus |= (regs->sstatus & ~(SR_FS)) | SR_FS_CLEAN;
+ regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_CLEAN;
+}
+
+static inline void fstate_off(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
}
static inline void fstate_save(struct task_struct *task,
diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h
index 6a703ec9d796..c7ef131b9e4c 100644
--- a/arch/riscv/include/asm/timex.h
+++ b/arch/riscv/include/asm/timex.h
@@ -6,43 +6,41 @@
#ifndef _ASM_RISCV_TIMEX_H
#define _ASM_RISCV_TIMEX_H
-#include <asm/param.h>
+#include <asm/csr.h>
typedef unsigned long cycles_t;
-static inline cycles_t get_cycles_inline(void)
+static inline cycles_t get_cycles(void)
{
- cycles_t n;
-
- __asm__ __volatile__ (
- "rdtime %0"
- : "=r" (n));
- return n;
+ return csr_read(CSR_TIME);
}
-#define get_cycles get_cycles_inline
+#define get_cycles get_cycles
#ifdef CONFIG_64BIT
-static inline uint64_t get_cycles64(void)
+static inline u64 get_cycles64(void)
+{
+ return get_cycles();
+}
+#else /* CONFIG_64BIT */
+static inline u32 get_cycles_hi(void)
{
- return get_cycles();
+ return csr_read(CSR_TIMEH);
}
-#else
-static inline uint64_t get_cycles64(void)
+
+static inline u64 get_cycles64(void)
{
- u32 lo, hi, tmp;
- __asm__ __volatile__ (
- "1:\n"
- "rdtimeh %0\n"
- "rdtime %1\n"
- "rdtimeh %2\n"
- "bne %0, %2, 1b"
- : "=&r" (hi), "=&r" (lo), "=&r" (tmp));
+ u32 hi, lo;
+
+ do {
+ hi = get_cycles_hi();
+ lo = get_cycles();
+ } while (hi != get_cycles_hi());
+
return ((u64)hi << 32) | lo;
}
-#endif
+#endif /* CONFIG_64BIT */
#define ARCH_HAS_READ_CURRENT_TIMER
-
static inline int read_current_timer(unsigned long *timer_val)
{
*timer_val = get_cycles();
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index 687dd19735a7..37ae4e367ad2 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -25,8 +25,13 @@ static inline void local_flush_tlb_page(unsigned long addr)
__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory");
}
-#ifndef CONFIG_SMP
-
+#ifdef CONFIG_SMP
+void flush_tlb_all(void);
+void flush_tlb_mm(struct mm_struct *mm);
+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);
+#else /* CONFIG_SMP */
#define flush_tlb_all() local_flush_tlb_all()
#define flush_tlb_page(vma, addr) local_flush_tlb_page(addr)
@@ -37,28 +42,6 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
}
#define flush_tlb_mm(mm) flush_tlb_all()
-
-#else /* CONFIG_SMP */
-
-#include <asm/sbi.h>
-
-static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start,
- unsigned long size)
-{
- struct cpumask hmask;
-
- cpumask_clear(&hmask);
- riscv_cpuid_to_hartid_mask(cmask, &hmask);
- sbi_remote_sfence_vma(hmask.bits, start, size);
-}
-
-#define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
-#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
-#define flush_tlb_range(vma, start, end) \
- remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
-#define flush_tlb_mm(mm) \
- remote_sfence_vma(mm_cpumask(mm), 0, -1)
-
#endif /* CONFIG_SMP */
/* Flush a range of kernel pages */
diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h
index 62716653554b..d86cb17bbabe 100644
--- a/arch/riscv/include/uapi/asm/auxvec.h
+++ b/arch/riscv/include/uapi/asm/auxvec.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 ARM Ltd.
* Copyright (C) 2015 Regents of the University of California
diff --git a/arch/riscv/include/uapi/asm/bitsperlong.h b/arch/riscv/include/uapi/asm/bitsperlong.h
index 0b9b58b57ff6..7d0b32e3b701 100644
--- a/arch/riscv/include/uapi/asm/bitsperlong.h
+++ b/arch/riscv/include/uapi/asm/bitsperlong.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 ARM Ltd.
* Copyright (C) 2015 Regents of the University of California
diff --git a/arch/riscv/include/uapi/asm/byteorder.h b/arch/riscv/include/uapi/asm/byteorder.h
index 1920debc09c0..f671e16bf6af 100644
--- a/arch/riscv/include/uapi/asm/byteorder.h
+++ b/arch/riscv/include/uapi/asm/byteorder.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 ARM Ltd.
* Copyright (C) 2015 Regents of the University of California
diff --git a/arch/riscv/include/uapi/asm/hwcap.h b/arch/riscv/include/uapi/asm/hwcap.h
index 7d786145183b..4e7646077056 100644
--- a/arch/riscv/include/uapi/asm/hwcap.h
+++ b/arch/riscv/include/uapi/asm/hwcap.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copied from arch/arm64/include/asm/hwcap.h
*
diff --git a/arch/riscv/include/uapi/asm/perf_regs.h b/arch/riscv/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..196f964bfcb4
--- /dev/null
+++ b/arch/riscv/include/uapi/asm/perf_regs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#ifndef _ASM_RISCV_PERF_REGS_H
+#define _ASM_RISCV_PERF_REGS_H
+
+enum perf_event_riscv_regs {
+ PERF_REG_RISCV_PC,
+ PERF_REG_RISCV_RA,
+ PERF_REG_RISCV_SP,
+ PERF_REG_RISCV_GP,
+ PERF_REG_RISCV_TP,
+ PERF_REG_RISCV_T0,
+ PERF_REG_RISCV_T1,
+ PERF_REG_RISCV_T2,
+ PERF_REG_RISCV_S0,
+ PERF_REG_RISCV_S1,
+ PERF_REG_RISCV_A0,
+ PERF_REG_RISCV_A1,
+ PERF_REG_RISCV_A2,
+ PERF_REG_RISCV_A3,
+ PERF_REG_RISCV_A4,
+ PERF_REG_RISCV_A5,
+ PERF_REG_RISCV_A6,
+ PERF_REG_RISCV_A7,
+ PERF_REG_RISCV_S2,
+ PERF_REG_RISCV_S3,
+ PERF_REG_RISCV_S4,
+ PERF_REG_RISCV_S5,
+ PERF_REG_RISCV_S6,
+ PERF_REG_RISCV_S7,
+ PERF_REG_RISCV_S8,
+ PERF_REG_RISCV_S9,
+ PERF_REG_RISCV_S10,
+ PERF_REG_RISCV_S11,
+ PERF_REG_RISCV_T3,
+ PERF_REG_RISCV_T4,
+ PERF_REG_RISCV_T5,
+ PERF_REG_RISCV_T6,
+ PERF_REG_RISCV_MAX,
+};
+#endif /* _ASM_RISCV_PERF_REGS_H */
diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
index 92d8f7cd8f84..882547f6bd5c 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 Regents of the University of California
*/
diff --git a/arch/riscv/include/uapi/asm/sigcontext.h b/arch/riscv/include/uapi/asm/sigcontext.h
index 053f809e52ce..84f2dfcfdbce 100644
--- a/arch/riscv/include/uapi/asm/sigcontext.h
+++ b/arch/riscv/include/uapi/asm/sigcontext.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 Regents of the University of California
*/
diff --git a/arch/riscv/include/uapi/asm/ucontext.h b/arch/riscv/include/uapi/asm/ucontext.h
index b58e00cee2ec..411dd7b52ed6 100644
--- a/arch/riscv/include/uapi/asm/ucontext.h
+++ b/arch/riscv/include/uapi/asm/ucontext.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2012 ARM Ltd.
* Copyright (C) 2017 SiFive, Inc.
diff --git a/arch/riscv/include/uapi/asm/unistd.h b/arch/riscv/include/uapi/asm/unistd.h
index 0e2eeeb1fd27..13ce76cc5aff 100644
--- a/arch/riscv/include/uapi/asm/unistd.h
+++ b/arch/riscv/include/uapi/asm/unistd.h
@@ -18,6 +18,7 @@
#ifdef __LP64__
#define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_SET_GET_RLIMIT
+#define __ARCH_WANT_SYS_CLONE3
#endif /* __LP64__ */
#include <asm-generic/unistd.h>
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 2420d37d96de..696020ff72db 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -38,6 +38,8 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
-obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
+obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
clean:
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index bc7a56e1ca6f..74ccfd464071 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -167,7 +167,7 @@ ENTRY(handle_exception)
tail do_IRQ
1:
/* Exceptions run with interrupts enabled */
- csrs sstatus, SR_SIE
+ csrs CSR_SSTATUS, SR_SIE
/* Handle syscalls */
li t0, EXC_SYSCALL
@@ -222,7 +222,7 @@ ret_from_syscall:
ret_from_exception:
REG_L s0, PT_SSTATUS(sp)
- csrc sstatus, SR_SIE
+ csrc CSR_SSTATUS, SR_SIE
andi s0, s0, SR_SPP
bnez s0, resume_kernel
@@ -265,7 +265,7 @@ work_pending:
bnez s1, work_resched
work_notifysig:
/* Handle pending signals and notify-resume requests */
- csrs sstatus, SR_SIE /* Enable interrupts for do_notify_resume() */
+ csrs CSR_SSTATUS, SR_SIE /* Enable interrupts for do_notify_resume() */
move a0, sp /* pt_regs */
move a1, s0 /* current_thread_info->flags */
tail do_notify_resume
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
index 1defb0618aff..631d31540660 100644
--- a/arch/riscv/kernel/fpu.S
+++ b/arch/riscv/kernel/fpu.S
@@ -23,7 +23,7 @@ ENTRY(__fstate_save)
li a2, TASK_THREAD_F0
add a0, a0, a2
li t1, SR_FS
- csrs sstatus, t1
+ csrs CSR_SSTATUS, t1
frcsr t0
fsd f0, TASK_THREAD_F0_F0(a0)
fsd f1, TASK_THREAD_F1_F0(a0)
@@ -58,7 +58,7 @@ ENTRY(__fstate_save)
fsd f30, TASK_THREAD_F30_F0(a0)
fsd f31, TASK_THREAD_F31_F0(a0)
sw t0, TASK_THREAD_FCSR_F0(a0)
- csrc sstatus, t1
+ csrc CSR_SSTATUS, t1
ret
ENDPROC(__fstate_save)
@@ -67,7 +67,7 @@ ENTRY(__fstate_restore)
add a0, a0, a2
li t1, SR_FS
lw t0, TASK_THREAD_FCSR_F0(a0)
- csrs sstatus, t1
+ csrs CSR_SSTATUS, t1
fld f0, TASK_THREAD_F0_F0(a0)
fld f1, TASK_THREAD_F1_F0(a0)
fld f2, TASK_THREAD_F2_F0(a0)
@@ -101,6 +101,6 @@ ENTRY(__fstate_restore)
fld f30, TASK_THREAD_F30_F0(a0)
fld f31, TASK_THREAD_F31_F0(a0)
fscsr t0
- csrc sstatus, t1
+ csrc CSR_SSTATUS, t1
ret
ENDPROC(__fstate_restore)
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 0f1ba17e476f..15a9189f91ad 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -39,9 +39,9 @@ ENTRY(_start)
.word RISCV_HEADER_VERSION
.word 0
.dword 0
- .asciz RISCV_IMAGE_MAGIC
- .word 0
+ .ascii RISCV_IMAGE_MAGIC
.balign 4
+ .ascii RISCV_IMAGE_MAGIC2
.word 0
.global _start_kernel
@@ -61,7 +61,7 @@ _start_kernel:
* floating point in kernel space
*/
li t0, SR_FS
- csrc sstatus, t0
+ csrc CSR_SSTATUS, t0
/* Pick one hart to run the main boot sequence */
la a3, hart_lottery
diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
new file mode 100644
index 000000000000..8d2804f05cf9
--- /dev/null
+++ b/arch/riscv/kernel/perf_callchain.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#include <linux/perf_event.h>
+#include <linux/uaccess.h>
+
+/* Kernel callchain */
+struct stackframe {
+ unsigned long fp;
+ unsigned long ra;
+};
+
+/*
+ * Get the return address for a single stackframe and return a pointer to the
+ * next frame tail.
+ */
+static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
+ unsigned long fp, unsigned long reg_ra)
+{
+ struct stackframe buftail;
+ unsigned long ra = 0;
+ unsigned long *user_frame_tail =
+ (unsigned long *)(fp - sizeof(struct stackframe));
+
+ /* Check accessibility of one struct frame_tail beyond */
+ if (!access_ok(user_frame_tail, sizeof(buftail)))
+ return 0;
+ if (__copy_from_user_inatomic(&buftail, user_frame_tail,
+ sizeof(buftail)))
+ return 0;
+
+ if (reg_ra != 0)
+ ra = reg_ra;
+ else
+ ra = buftail.ra;
+
+ fp = buftail.fp;
+ if (ra != 0)
+ perf_callchain_store(entry, ra);
+ else
+ return 0;
+
+ return fp;
+}
+
+/*
+ * This will be called when the target is in user mode
+ * This function will only be called when we use
+ * "PERF_SAMPLE_CALLCHAIN" in
+ * kernel/events/core.c:perf_prepare_sample()
+ *
+ * How to trigger perf_callchain_[user/kernel] :
+ * $ perf record -e cpu-clock --call-graph fp ./program
+ * $ perf report --call-graph
+ *
+ * On RISC-V platform, the program being sampled and the C library
+ * need to be compiled with -fno-omit-frame-pointer, otherwise
+ * the user stack will not contain function frame.
+ */
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+ struct pt_regs *regs)
+{
+ unsigned long fp = 0;
+
+ /* RISC-V does not support perf in guest mode. */
+ if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+ return;
+
+ fp = regs->s0;
+ perf_callchain_store(entry, regs->sepc);
+
+ fp = user_backtrace(entry, fp, regs->ra);
+ while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
+ fp = user_backtrace(entry, fp, 0);
+}
+
+bool fill_callchain(unsigned long pc, void *entry)
+{
+ return perf_callchain_store(entry, pc);
+}
+
+void notrace walk_stackframe(struct task_struct *task,
+ struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg);
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+ struct pt_regs *regs)
+{
+ /* RISC-V does not support perf in guest mode. */
+ if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+ pr_warn("RISC-V does not support perf in guest mode!");
+ return;
+ }
+
+ walk_stackframe(NULL, regs, fill_callchain, entry);
+}
diff --git a/arch/riscv/kernel/perf_regs.c b/arch/riscv/kernel/perf_regs.c
new file mode 100644
index 000000000000..04a38fbeb9c7
--- /dev/null
+++ b/arch/riscv/kernel/perf_regs.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+ if (WARN_ON_ONCE((u32)idx >= PERF_REG_RISCV_MAX))
+ return 0;
+
+ return ((unsigned long *)regs)[idx];
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_RISCV_MAX) - 1))
+
+int perf_reg_validate(u64 mask)
+{
+ if (!mask || mask & REG_RESERVED)
+ return -EINVAL;
+
+ return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+#if __riscv_xlen == 64
+ return PERF_SAMPLE_REGS_ABI_64;
+#else
+ return PERF_SAMPLE_REGS_ABI_32;
+#endif
+}
+
+void perf_get_regs_user(struct perf_regs *regs_user,
+ struct pt_regs *regs,
+ struct pt_regs *regs_user_copy)
+{
+ regs_user->regs = task_pt_regs(current);
+ regs_user->abi = perf_reg_abi(current);
+}
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index f23794bd1e90..fb3a082362eb 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -64,8 +64,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
regs->sstatus = SR_SPIE;
- if (has_fpu)
+ if (has_fpu) {
regs->sstatus |= SR_FS_INITIAL;
+ /*
+ * Restore the initial value to the FP register
+ * before starting the user program.
+ */
+ fstate_restore(current, regs);
+ }
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -75,10 +81,11 @@ void flush_thread(void)
{
#ifdef CONFIG_FPU
/*
- * Reset FPU context
+ * Reset FPU state and context
* frm: round to nearest, ties to even (IEEE default)
* fflags: accrued exceptions cleared
*/
+ fstate_off(current, task_pt_regs(current));
memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
#endif
}
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index 5a9834503a2f..3836760d7aaf 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -56,6 +56,7 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
{
int cpu;
+ cpumask_clear(out);
for_each_cpu(cpu, in)
cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);
}
@@ -78,13 +79,42 @@ static void ipi_stop(void)
wait_for_interrupt();
}
+static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op)
+{
+ struct cpumask hartid_mask;
+ int cpu;
+
+ smp_mb__before_atomic();
+ for_each_cpu(cpu, mask)
+ set_bit(op, &ipi_data[cpu].bits);
+ smp_mb__after_atomic();
+
+ riscv_cpuid_to_hartid_mask(mask, &hartid_mask);
+ sbi_send_ipi(cpumask_bits(&hartid_mask));
+}
+
+static void send_ipi_single(int cpu, enum ipi_message_type op)
+{
+ int hartid = cpuid_to_hartid_map(cpu);
+
+ smp_mb__before_atomic();
+ set_bit(op, &ipi_data[cpu].bits);
+ smp_mb__after_atomic();
+
+ sbi_send_ipi(cpumask_bits(cpumask_of(hartid)));
+}
+
+static inline void clear_ipi(void)
+{
+ csr_clear(CSR_SIP, SIE_SSIE);
+}
+
void riscv_software_interrupt(void)
{
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
unsigned long *stats = ipi_data[smp_processor_id()].stats;
- /* Clear pending IPI */
- csr_clear(CSR_SIP, SIE_SSIE);
+ clear_ipi();
while (true) {
unsigned long ops;
@@ -118,23 +148,6 @@ void riscv_software_interrupt(void)
}
}
-static void
-send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
-{
- int cpuid, hartid;
- struct cpumask hartid_mask;
-
- cpumask_clear(&hartid_mask);
- mb();
- for_each_cpu(cpuid, to_whom) {
- set_bit(operation, &ipi_data[cpuid].bits);
- hartid = cpuid_to_hartid_map(cpuid);
- cpumask_set_cpu(hartid, &hartid_mask);
- }
- mb();
- sbi_send_ipi(cpumask_bits(&hartid_mask));
-}
-
static const char * const ipi_names[] = {
[IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNC] = "Function call interrupts",
@@ -156,12 +169,12 @@ void show_ipi_stats(struct seq_file *p, int prec)
void arch_send_call_function_ipi_mask(struct cpumask *mask)
{
- send_ipi_message(mask, IPI_CALL_FUNC);
+ send_ipi_mask(mask, IPI_CALL_FUNC);
}
void arch_send_call_function_single_ipi(int cpu)
{
- send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
+ send_ipi_single(cpu, IPI_CALL_FUNC);
}
void smp_send_stop(void)
@@ -176,7 +189,7 @@ void smp_send_stop(void)
if (system_state <= SYSTEM_RUNNING)
pr_crit("SMP: stopping secondary CPUs\n");
- send_ipi_message(&mask, IPI_CPU_STOP);
+ send_ipi_mask(&mask, IPI_CPU_STOP);
}
/* Wait up to one second for other CPUs to stop */
@@ -191,6 +204,5 @@ void smp_send_stop(void)
void smp_send_reschedule(int cpu)
{
- send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+ send_ipi_single(cpu, IPI_RESCHEDULE);
}
-
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index 7462a44304fe..18ae6da5115e 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -8,6 +8,7 @@
* Copyright (C) 2017 SiFive
*/
+#include <linux/arch_topology.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -35,6 +36,7 @@ static DECLARE_COMPLETION(cpu_running);
void __init smp_prepare_boot_cpu(void)
{
+ init_cpu_topology();
}
void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -138,6 +140,7 @@ asmlinkage void __init smp_callin(void)
trap_init();
notify_cpu_starting(smp_processor_id());
+ update_siblings_masks(smp_processor_id());
set_cpu_online(smp_processor_id(), 1);
/*
* Remote TLB flushes are ignored while the CPU is offline, so emit
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index f15642715d1a..0940681d2f68 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -19,8 +19,8 @@ struct stackframe {
unsigned long ra;
};
-static void notrace walk_stackframe(struct task_struct *task,
- struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
+void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+ bool (*fn)(unsigned long, void *), void *arg)
{
unsigned long fp, sp, pc;
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index f1d6ffe43e42..49a5852fd07d 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -37,7 +37,7 @@ $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
# these symbols in the kernel code rather than hand-coded addresses.
SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
- -Wl,--hash-style=both
+ -Wl,--build-id -Wl,--hash-style=both
$(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
$(call if_changed,vdsold)
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 8e364ebf37de..267feaa10f6a 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -5,5 +5,3 @@ lib-y += memset.o
lib-y += uaccess.o
lib-$(CONFIG_64BIT) += tishift.o
-
-lib-$(CONFIG_32BIT) += udivdi3.o
diff --git a/arch/riscv/lib/delay.c b/arch/riscv/lib/delay.c
index 87ff89e88f2c..f51c9a03bca1 100644
--- a/arch/riscv/lib/delay.c
+++ b/arch/riscv/lib/delay.c
@@ -81,9 +81,13 @@ EXPORT_SYMBOL(__delay);
void udelay(unsigned long usecs)
{
u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
+ u64 n;
if (unlikely(usecs > MAX_UDELAY_US)) {
- __delay((u64)usecs * riscv_timebase / 1000000ULL);
+ n = (u64)usecs * riscv_timebase;
+ do_div(n, 1000000);
+
+ __delay(n);
return;
}
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S
index 399e6f0c2d98..ed2696c0143d 100644
--- a/arch/riscv/lib/uaccess.S
+++ b/arch/riscv/lib/uaccess.S
@@ -18,7 +18,7 @@ ENTRY(__asm_copy_from_user)
/* Enable access to user memory */
li t6, SR_SUM
- csrs sstatus, t6
+ csrs CSR_SSTATUS, t6
add a3, a1, a2
/* Use word-oriented copy only if low-order bits match */
@@ -47,7 +47,7 @@ ENTRY(__asm_copy_from_user)
3:
/* Disable access to user memory */
- csrc sstatus, t6
+ csrc CSR_SSTATUS, t6
li a0, 0
ret
4: /* Edge case: unalignment */
@@ -72,7 +72,7 @@ ENTRY(__clear_user)
/* Enable access to user memory */
li t6, SR_SUM
- csrs sstatus, t6
+ csrs CSR_SSTATUS, t6
add a3, a0, a1
addi t0, a0, SZREG-1
@@ -94,7 +94,7 @@ ENTRY(__clear_user)
3:
/* Disable access to user memory */
- csrc sstatus, t6
+ csrc CSR_SSTATUS, t6
li a0, 0
ret
4: /* Edge case: unalignment */
@@ -114,11 +114,11 @@ ENDPROC(__clear_user)
/* Fixup code for __copy_user(10) and __clear_user(11) */
10:
/* Disable access to user memory */
- csrs sstatus, t6
+ csrs CSR_SSTATUS, t6
mv a0, a2
ret
11:
- csrs sstatus, t6
+ csrs CSR_SSTATUS, t6
mv a0, a1
ret
.previous
diff --git a/arch/riscv/lib/udivdi3.S b/arch/riscv/lib/udivdi3.S
deleted file mode 100644
index 3f07476a91a9..000000000000
--- a/arch/riscv/lib/udivdi3.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2016-2017 Free Software Foundation, Inc.
- */
-
-#include <linux/linkage.h>
-
-ENTRY(__udivdi3)
- mv a2, a1
- mv a1, a0
- li a0, -1
- beqz a2, .L5
- li a3, 1
- bgeu a2, a1, .L2
-.L1:
- blez a2, .L2
- slli a2, a2, 1
- slli a3, a3, 1
- bgtu a1, a2, .L1
-.L2:
- li a0, 0
-.L3:
- bltu a1, a2, .L4
- sub a1, a1, a2
- or a0, a0, a3
-.L4:
- srli a3, a3, 1
- srli a2, a2, 1
- bnez a3, .L3
-.L5:
- ret
-ENDPROC(__udivdi3)
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index 74055e1d6f21..9d9a17335686 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -13,4 +13,7 @@ obj-y += cacheflush.o
obj-y += context.o
obj-y += sifive_l2_cache.o
+ifeq ($(CONFIG_MMU),y)
+obj-$(CONFIG_SMP) += tlbflush.o
+endif
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index 9ebcff8ba263..3f15938dec89 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -47,7 +47,6 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
local |= cpumask_empty(&others);
if (mm != current->active_mm || !local) {
- cpumask_clear(&hmask);
riscv_cpuid_to_hartid_mask(&others, &hmask);
sbi_remote_fence_i(hmask.bits);
} else {
diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c
index 89ceb3cbe218..beeb5d7f92ea 100644
--- a/arch/riscv/mm/context.c
+++ b/arch/riscv/mm/context.c
@@ -57,12 +57,7 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
cpumask_clear_cpu(cpu, mm_cpumask(prev));
cpumask_set_cpu(cpu, mm_cpumask(next));
- /*
- * Use the old spbtr name instead of using the current satp
- * name to support binutils 2.29 which doesn't know about the
- * privileged ISA 1.10 yet.
- */
- csr_write(sptbr, virt_to_pfn(next->pgd) | SATP_MODE);
+ csr_write(CSR_SATP, virt_to_pfn(next->pgd) | SATP_MODE);
local_flush_tlb_all();
flush_icache_deferred(next);
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 42bf939693d3..f0ba71304b6e 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -435,13 +435,23 @@ static void __init setup_vm_final(void)
clear_fixmap(FIX_PMD);
/* Move to swapper page table */
- csr_write(sptbr, PFN_DOWN(__pa(swapper_pg_dir)) | SATP_MODE);
+ csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | SATP_MODE);
local_flush_tlb_all();
}
void __init paging_init(void)
{
setup_vm_final();
+ memblocks_present();
+ sparse_init();
setup_zero_page();
zone_sizes_init();
}
+
+#ifdef CONFIG_SPARSEMEM
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
+ struct vmem_altmap *altmap)
+{
+ return vmemmap_populate_basepages(start, end, node);
+}
+#endif
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
new file mode 100644
index 000000000000..24cd33d2c48f
--- /dev/null
+++ b/arch/riscv/mm/tlbflush.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <asm/sbi.h>
+
+void flush_tlb_all(void)
+{
+ sbi_remote_sfence_vma(NULL, 0, -1);
+}
+
+static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start,
+ unsigned long size)
+{
+ struct cpumask hmask;
+
+ riscv_cpuid_to_hartid_mask(cmask, &hmask);
+ sbi_remote_sfence_vma(hmask.bits, start, size);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ __sbi_tlb_flush_range(mm_cpumask(mm), 0, -1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+ __sbi_tlb_flush_range(mm_cpumask(vma->vm_mm), addr, PAGE_SIZE);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ __sbi_tlb_flush_range(mm_cpumask(vma->vm_mm), start, end - start);
+}
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index 7cba96e7587b..4cf0bddb7d92 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -36,7 +36,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
-obj-y += ctype.o text_dma.o
+obj-y += version.o ctype.o text_dma.o
obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o
obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h
index ad57c2205a71..1c3b2b257637 100644
--- a/arch/s390/boot/boot.h
+++ b/arch/s390/boot/boot.h
@@ -8,10 +8,12 @@ void store_ipl_parmblock(void);
void setup_boot_command_line(void);
void parse_boot_command_line(void);
void setup_memory_end(void);
+void verify_facilities(void);
void print_missing_facilities(void);
unsigned long get_random_base(unsigned long safe_addr);
extern int kaslr_enabled;
+extern const char kernel_version[];
unsigned long read_ipl_report(unsigned long safe_offset);
diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S
index 028aab03a9e7..2087bed6e60f 100644
--- a/arch/s390/boot/head.S
+++ b/arch/s390/boot/head.S
@@ -361,6 +361,7 @@ ENTRY(startup_kdump)
.quad 0 # INITRD_SIZE
.quad 0 # OLDMEM_BASE
.quad 0 # OLDMEM_SIZE
+ .quad kernel_version # points to kernel version string
.org COMMAND_LINE
.byte "root=/dev/ram0 ro"
diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c
index 3c49bde8aa5e..b8aa6a9f937b 100644
--- a/arch/s390/boot/ipl_parm.c
+++ b/arch/s390/boot/ipl_parm.c
@@ -48,9 +48,7 @@ void store_ipl_parmblock(void)
{
int rc;
- uv_set_shared(__pa(&ipl_block));
rc = __diag308(DIAG308_STORE, &ipl_block);
- uv_remove_shared(__pa(&ipl_block));
if (rc == DIAG308_RC_OK &&
ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
ipl_block_valid = 1;
diff --git a/arch/s390/boot/kaslr.c b/arch/s390/boot/kaslr.c
index 3bdd8132e56b..c34a6387ce38 100644
--- a/arch/s390/boot/kaslr.c
+++ b/arch/s390/boot/kaslr.c
@@ -7,6 +7,7 @@
#include <asm/timex.h>
#include <asm/sclp.h>
#include "compressed/decompressor.h"
+#include "boot.h"
#define PRNG_MODE_TDES 1
#define PRNG_MODE_SHA512 2
diff --git a/arch/s390/boot/version.c b/arch/s390/boot/version.c
new file mode 100644
index 000000000000..d32e58bdda6a
--- /dev/null
+++ b/arch/s390/boot/version.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <generated/utsrelease.h>
+#include <generated/compile.h>
+#include "boot.h"
+
+const char kernel_version[] = UTS_RELEASE
+ " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION;
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index e26d4413d34c..74e78ec5beb6 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -3,6 +3,7 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
@@ -18,55 +19,71 @@ CONFIG_BLK_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
# CONFIG_SYSFS_SYSCALL is not set
-CONFIG_CHECKPOINT_RESTORE=y
CONFIG_BPF_SYSCALL=y
CONFIG_USERFAULTFD=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
+CONFIG_LIVEPATCH=y
+CONFIG_TUNE_ZEC12=y
+CONFIG_NR_CPUS=512
+CONFIG_NUMA=y
+CONFIG_HZ_100=y
+CONFIG_KEXEC_FILE=y
+CONFIG_EXPOLINE=y
+CONFIG_EXPOLINE_AUTO=y
+CONFIG_CHSC_SCH=y
+CONFIG_VFIO_CCW=m
+CONFIG_VFIO_AP=m
+CONFIG_CRASH_DUMP=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_DEBUG=y
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
CONFIG_OPROFILE=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_STATIC_KEYS_SELFTEST=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_LOCK_EVENT_COUNTS=y
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_SHA256=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_WBT=y
-CONFIG_BLK_WBT_SQ=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_IBM_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_LIVEPATCH=y
-CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=512
-CONFIG_NUMA=y
-CONFIG_PREEMPT=y
-CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_VERIFY_SIG=y
-CONFIG_EXPOLINE=y
-CONFIG_EXPOLINE_AUTO=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_KSM=y
@@ -82,17 +99,8 @@ CONFIG_ZSMALLOC=m
CONFIG_ZSMALLOC_STAT=y
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
CONFIG_IDLE_PAGE_TRACKING=y
-CONFIG_PCI=y
-CONFIG_PCI_DEBUG=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_S390=y
-CONFIG_CHSC_SCH=y
-CONFIG_VFIO_AP=m
-CONFIG_VFIO_CCW=m
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
+CONFIG_PERCPU_STATS=y
+CONFIG_GUP_BENCHMARK=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=m
@@ -121,9 +129,6 @@ CONFIG_NET_IPVTI=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_INET_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
@@ -139,10 +144,6 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_VTI=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_GRE=m
@@ -264,11 +265,8 @@ CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_PE_SIP=m
-CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_TABLES_IPV4=y
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NF_TABLES_ARP=y
-CONFIG_NFT_CHAIN_NAT_IPV4=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -287,10 +285,7 @@ CONFIG_IP_NF_SECURITY=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NF_TABLES_IPV6=y
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_CHAIN_NAT_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
@@ -309,7 +304,7 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_SECURITY=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
CONFIG_RDS=m
CONFIG_RDS_RDMA=m
CONFIG_RDS_TCP=m
@@ -375,9 +370,11 @@ CONFIG_NETLINK_DIAG=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_BPF_JIT=y
CONFIG_NET_PKTGEN=m
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
CONFIG_DEVTMPFS=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=0
CONFIG_CONNECTOR=y
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=m
@@ -395,7 +392,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=m
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=m
@@ -415,17 +411,19 @@ CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_WRITECACHE=m
CONFIG_DM_MIRROR=m
CONFIG_DM_LOG_USERSPACE=m
CONFIG_DM_RAID=m
@@ -445,23 +443,78 @@ CONFIG_EQUALIZER=m
CONFIG_IFB=m
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
-CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
+# CONFIG_MLXFW is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MYRI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=m
CONFIG_PPTP=m
CONFIG_PPPOL2TP=m
@@ -473,10 +526,13 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_NULL_TTY=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_RAW_DRIVER=m
CONFIG_HANGCHECK_TIMER=m
CONFIG_TN3270_FS=y
+CONFIG_PPS=m
+# CONFIG_PTP_1588_CLOCK is not set
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
@@ -498,8 +554,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=y
-CONFIG_S390_AP_IOMMU=y
CONFIG_S390_CCW_IOMMU=y
+CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
@@ -519,6 +575,7 @@ CONFIG_OCFS2_FS=m
CONFIG_BTRFS_FS=y
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_BTRFS_DEBUG=y
+CONFIG_BTRFS_ASSERT=y
CONFIG_NILFS2_FS=m
CONFIG_FS_DAX=y
CONFIG_EXPORTFS_BLOCK_OPS=y
@@ -552,8 +609,10 @@ CONFIG_ECRYPT_FS=m
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
CONFIG_ROMFS_FS=m
CONFIG_NFS_FS=m
CONFIG_NFS_V3_ACL=y
@@ -564,7 +623,6 @@ CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
CONFIG_CIFS=m
-CONFIG_CIFS_STATS=y
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_CIFS_UPCALL=y
@@ -580,19 +638,112 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
+CONFIG_UNICODE=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_IMA=y
+CONFIG_IMA_DEFAULT_HASH_SHA256=y
+CONFIG_IMA_WRITE_POLICY=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_USER=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
+CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_AEGIS128L=m
+CONFIG_CRYPTO_AEGIS256=m
+CONFIG_CRYPTO_MORUS640=m
+CONFIG_CRYPTO_MORUS1280=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_XXHASH=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ZSTD=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_STATS=y
+CONFIG_ZCRYPT=m
+CONFIG_PKEY=m
+CONFIG_CRYPTO_PAES_S390=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_GHASH_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CORDIC=m
+CONFIG_CRC32_SELFTEST=y
+CONFIG_CRC4=m
+CONFIG_CRC7=m
+CONFIG_CRC8=m
+CONFIG_RANDOM32_SELFTEST=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_DMA_API_DEBUG=y
+CONFIG_STRING_SELFTEST=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
CONFIG_FRAME_WARN=1024
-CONFIG_READABLE_ASM=y
CONFIG_UNUSED_SYMBOLS=y
CONFIG_HEADERS_INSTALL=y
CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_PAGE_OWNER=y
CONFIG_DEBUG_RODATA_TEST=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_SELFTEST=y
@@ -645,7 +796,6 @@ CONFIG_STACK_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_FUNCTION_PROFILER=y
CONFIG_HIST_TRIGGERS=y
-CONFIG_DMA_API_DEBUG=y
CONFIG_LKDTM=m
CONFIG_TEST_LIST_SORT=y
CONFIG_TEST_SORT=y
@@ -657,85 +807,3 @@ CONFIG_ATOMIC64_SELFTEST=y
CONFIG_TEST_BPF=m
CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_S390_PTDUMP=y
-CONFIG_PERSISTENT_KEYRINGS=y
-CONFIG_BIG_KEYS=y
-CONFIG_ENCRYPTED_KEYS=m
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_FORTIFY_SOURCE=y
-CONFIG_SECURITY_SELINUX=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
-CONFIG_SECURITY_SELINUX_DISABLE=y
-CONFIG_INTEGRITY_SIGNATURE=y
-CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
-CONFIG_IMA=y
-CONFIG_IMA_DEFAULT_HASH_SHA256=y
-CONFIG_IMA_WRITE_POLICY=y
-CONFIG_IMA_APPRAISE=y
-CONFIG_CRYPTO_DH=m
-CONFIG_CRYPTO_ECDH=m
-CONFIG_CRYPTO_USER=m
-# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
-CONFIG_CRYPTO_PCRYPT=m
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES_TI=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_842=m
-CONFIG_CRYPTO_LZ4=m
-CONFIG_CRYPTO_LZ4HC=m
-CONFIG_CRYPTO_ANSI_CPRNG=m
-CONFIG_CRYPTO_USER_API_HASH=m
-CONFIG_CRYPTO_USER_API_SKCIPHER=m
-CONFIG_CRYPTO_USER_API_RNG=m
-CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_ZCRYPT=m
-CONFIG_PKEY=m
-CONFIG_CRYPTO_PAES_S390=m
-CONFIG_CRYPTO_SHA1_S390=m
-CONFIG_CRYPTO_SHA256_S390=m
-CONFIG_CRYPTO_SHA512_S390=m
-CONFIG_CRYPTO_DES_S390=m
-CONFIG_CRYPTO_AES_S390=m
-CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_PKCS7_MESSAGE_PARSER=y
-CONFIG_SYSTEM_TRUSTED_KEYRING=y
-CONFIG_CRC7=m
-CONFIG_CRC8=m
-CONFIG_RANDOM32_SELFTEST=y
-CONFIG_CORDIC=m
-CONFIG_CMM=m
-CONFIG_APPLDATA_BASE=y
-CONFIG_KVM=m
-CONFIG_KVM_S390_UCONTROL=y
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index e4bc40073003..68d3ca83302b 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -12,30 +12,51 @@ CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_NUMA_BALANCING=y
-# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
# CONFIG_SYSFS_SYSCALL is not set
-CONFIG_CHECKPOINT_RESTORE=y
CONFIG_BPF_SYSCALL=y
CONFIG_USERFAULTFD=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
+CONFIG_LIVEPATCH=y
+CONFIG_TUNE_ZEC12=y
+CONFIG_NR_CPUS=512
+CONFIG_NUMA=y
+# CONFIG_NUMA_EMU is not set
+CONFIG_HZ_100=y
+CONFIG_KEXEC_FILE=y
+CONFIG_EXPOLINE=y
+CONFIG_EXPOLINE_AUTO=y
+CONFIG_CHSC_SCH=y
+CONFIG_VFIO_CCW=m
+CONFIG_VFIO_AP=m
+CONFIG_CRASH_DUMP=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_DEBUG=y
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
CONFIG_OPROFILE=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
@@ -47,27 +68,18 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_SHA256=y
-CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_WBT=y
-CONFIG_BLK_WBT_SQ=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_IBM_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_LIVEPATCH=y
-CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=512
-CONFIG_NUMA=y
-CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_VERIFY_SIG=y
-CONFIG_EXPOLINE=y
-CONFIG_EXPOLINE_AUTO=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_KSM=y
@@ -81,16 +93,8 @@ CONFIG_ZSMALLOC=m
CONFIG_ZSMALLOC_STAT=y
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
CONFIG_IDLE_PAGE_TRACKING=y
-CONFIG_PCI=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_S390=y
-CONFIG_CHSC_SCH=y
-CONFIG_VFIO_AP=m
-CONFIG_VFIO_CCW=m
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
+CONFIG_PERCPU_STATS=y
+CONFIG_GUP_BENCHMARK=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=m
@@ -119,9 +123,6 @@ CONFIG_NET_IPVTI=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_INET_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
@@ -137,10 +138,6 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_VTI=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_GRE=m
@@ -262,11 +259,8 @@ CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_PE_SIP=m
-CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_TABLES_IPV4=y
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NF_TABLES_ARP=y
-CONFIG_NFT_CHAIN_NAT_IPV4=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -285,10 +279,7 @@ CONFIG_IP_NF_SECURITY=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NF_TABLES_IPV6=y
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_CHAIN_NAT_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
@@ -307,7 +298,7 @@ CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_SECURITY=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
CONFIG_RDS=m
CONFIG_RDS_RDMA=m
CONFIG_RDS_TCP=m
@@ -372,9 +363,11 @@ CONFIG_NETLINK_DIAG=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_BPF_JIT=y
CONFIG_NET_PKTGEN=m
+CONFIG_PCI=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
+CONFIG_UEVENT_HELPER=y
CONFIG_DEVTMPFS=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=0
CONFIG_CONNECTOR=y
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=m
@@ -383,6 +376,7 @@ CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XPRAM is not set
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_NVME=m
@@ -392,7 +386,6 @@ CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=m
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=m
@@ -412,17 +405,19 @@ CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_WRITECACHE=m
CONFIG_DM_MIRROR=m
CONFIG_DM_LOG_USERSPACE=m
CONFIG_DM_RAID=m
@@ -435,6 +430,7 @@ CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
CONFIG_DM_SWITCH=m
+CONFIG_DM_INTEGRITY=m
CONFIG_NETDEVICES=y
CONFIG_BONDING=m
CONFIG_DUMMY=m
@@ -442,23 +438,78 @@ CONFIG_EQUALIZER=m
CONFIG_IFB=m
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
-CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
+# CONFIG_MLXFW is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MYRI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=m
CONFIG_PPTP=m
CONFIG_PPPOL2TP=m
@@ -470,17 +521,21 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_NULL_TTY=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_RAW_DRIVER=m
CONFIG_HANGCHECK_TIMER=m
CONFIG_TN3270_FS=y
+# CONFIG_PTP_1588_CLOCK is not set
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_SOFT_WATCHDOG=m
CONFIG_DIAG288_WATCHDOG=m
CONFIG_DRM=y
CONFIG_DRM_VIRTIO_GPU=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_HID is not set
# CONFIG_USB_SUPPORT is not set
@@ -495,8 +550,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=y
-CONFIG_S390_AP_IOMMU=y
CONFIG_S390_CCW_IOMMU=y
+CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
@@ -546,8 +601,10 @@ CONFIG_ECRYPT_FS=m
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
CONFIG_ROMFS_FS=m
CONFIG_NFS_FS=m
CONFIG_NFS_V3_ACL=y
@@ -558,7 +615,6 @@ CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
CONFIG_CIFS=m
-CONFIG_CIFS_STATS=y
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_CIFS_UPCALL=y
@@ -574,31 +630,7 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_INFO_DWARF4=y
-CONFIG_GDB_SCRIPTS=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=1024
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_RCU_CPU_STALL_TIMEOUT=60
-CONFIG_LATENCYTOP=y
-CONFIG_SCHED_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
-CONFIG_HIST_TRIGGERS=y
-CONFIG_LKDTM=m
-CONFIG_PERCPU_TEST=m
-CONFIG_ATOMIC64_SELFTEST=y
-CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
+CONFIG_UNICODE=y
CONFIG_PERSISTENT_KEYRINGS=y
CONFIG_BIG_KEYS=y
CONFIG_ENCRYPTED_KEYS=m
@@ -606,7 +638,6 @@ CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
@@ -615,31 +646,42 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_APPRAISE=y
CONFIG_CRYPTO_FIPS=y
-CONFIG_CRYPTO_DH=m
-CONFIG_CRYPTO_ECDH=m
CONFIG_CRYPTO_USER=m
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
+CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_AEGIS128L=m
+CONFIG_CRYPTO_AEGIS256=m
+CONFIG_CRYPTO_MORUS640=m
+CONFIG_CRYPTO_MORUS1280=m
+CONFIG_CRYPTO_CFB=m
CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m
CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_RMD256=m
CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -649,16 +691,19 @@ CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SM4=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_STATS=y
CONFIG_ZCRYPT=m
CONFIG_PKEY=m
CONFIG_CRYPTO_PAES_S390=m
@@ -669,12 +714,34 @@ CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
CONFIG_CRYPTO_GHASH_S390=m
CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CORDIC=m
+CONFIG_CRC4=m
CONFIG_CRC7=m
CONFIG_CRC8=m
-CONFIG_CORDIC=m
-CONFIG_CMM=m
-CONFIG_APPLDATA_BASE=y
-CONFIG_KVM=m
-CONFIG_KVM_S390_UCONTROL=y
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
+CONFIG_FRAME_WARN=1024
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
+CONFIG_LKDTM=m
+CONFIG_PERCPU_TEST=m
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+CONFIG_S390_PTDUMP=y
diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig
index d92bab844b73..be09a208b608 100644
--- a/arch/s390/configs/zfcpdump_defconfig
+++ b/arch/s390/configs/zfcpdump_defconfig
@@ -1,27 +1,33 @@
# CONFIG_SWAP is not set
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CPU_ISOLATION is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_COMPAT_BRK is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_IBM_PARTITION=y
-CONFIG_DEFAULT_DEADLINE=y
CONFIG_TUNE_ZEC12=y
# CONFIG_COMPAT is not set
CONFIG_NR_CPUS=2
-# CONFIG_HOTPLUG_CPU is not set
CONFIG_HZ_100=y
# CONFIG_ARCH_RANDOM is not set
-# CONFIG_COMPACTION is not set
-# CONFIG_MIGRATION is not set
-# CONFIG_BOUNCE is not set
-# CONFIG_CHECK_STACK is not set
+# CONFIG_RELOCATABLE is not set
# CONFIG_CHSC_SCH is not set
# CONFIG_SCM_BUS is not set
CONFIG_CRASH_DUMP=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SECCOMP is not set
+# CONFIG_PFAULT is not set
+# CONFIG_S390_HYPFS_FS is not set
+# CONFIG_VIRTUALIZATION is not set
+# CONFIG_S390_GUEST is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+# CONFIG_MIGRATION is not set
+# CONFIG_BOUNCE is not set
CONFIG_NET=y
# CONFIG_IUCV is not set
CONFIG_DEVTMPFS=y
@@ -43,7 +49,6 @@ CONFIG_ZFCP=y
# CONFIG_HVC_IUCV is not set
# CONFIG_HW_RANDOM_S390 is not set
CONFIG_RAW_DRIVER=y
-# CONFIG_SCLP_ASYNC is not set
# CONFIG_HMC_DRV is not set
# CONFIG_S390_TAPE is not set
# CONFIG_VMCP is not set
@@ -56,6 +61,7 @@ CONFIG_RAW_DRIVER=y
CONFIG_CONFIGFS_FS=y
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_DIMLIB is not set
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
@@ -64,7 +70,4 @@ CONFIG_PANIC_ON_OOPS=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
# CONFIG_FTRACE is not set
-# CONFIG_PFAULT is not set
-# CONFIG_S390_HYPFS_FS is not set
-# CONFIG_VIRTUALIZATION is not set
-# CONFIG_S390_GUEST is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index 42f2375c203e..e1fcc03159ef 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -118,7 +118,7 @@ do { \
return PTR_ERR(rc); \
} while(0)
-static int hpyfs_vm_create_guest(struct dentry *systems_dir,
+static int hypfs_vm_create_guest(struct dentry *systems_dir,
struct diag2fc_data *data)
{
char guest_name[NAME_LEN + 1] = {};
@@ -219,7 +219,7 @@ int hypfs_vm_create_files(struct dentry *root)
}
for (i = 0; i < count; i++) {
- rc = hpyfs_vm_create_guest(dir, &(data[i]));
+ rc = hypfs_vm_create_guest(dir, &(data[i]));
if (rc)
goto failed;
}
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 9900d655014c..b8833ac983fa 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -35,6 +35,7 @@
#include <linux/typecheck.h>
#include <linux/compiler.h>
+#include <linux/types.h>
#include <asm/atomic_ops.h>
#include <asm/barrier.h>
@@ -55,7 +56,7 @@ __bitops_byte(unsigned long nr, volatile unsigned long *ptr)
return ((unsigned char *)ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
}
-static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_set_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long mask;
@@ -76,7 +77,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
__atomic64_or(mask, (long *)addr);
}
-static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long mask;
@@ -97,7 +98,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
__atomic64_and(mask, (long *)addr);
}
-static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_change_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long mask;
@@ -118,8 +120,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
__atomic64_xor(mask, (long *)addr);
}
-static inline int
-test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_set_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long old, mask;
@@ -129,8 +131,8 @@ test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
return (old & mask) != 0;
}
-static inline int
-test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_clear_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long old, mask;
@@ -140,8 +142,8 @@ test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
return (old & ~mask) != 0;
}
-static inline int
-test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_change_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned long *addr = __bitops_word(nr, ptr);
unsigned long old, mask;
@@ -151,30 +153,31 @@ test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
return (old & mask) != 0;
}
-static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___set_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
*addr |= 1 << (nr & 7);
}
-static inline void
-__clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___clear_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
*addr &= ~(1 << (nr & 7));
}
-static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___change_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
*addr ^= 1 << (nr & 7);
}
-static inline int
-__test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_set_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
@@ -184,8 +187,8 @@ __test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
return (ch >> (nr & 7)) & 1;
}
-static inline int
-__test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_clear_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
@@ -195,8 +198,8 @@ __test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
return (ch >> (nr & 7)) & 1;
}
-static inline int
-__test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_change_bit(unsigned long nr,
+ volatile unsigned long *ptr)
{
unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
@@ -206,7 +209,8 @@ __test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
return (ch >> (nr & 7)) & 1;
}
-static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
+static inline bool arch_test_bit(unsigned long nr,
+ const volatile unsigned long *ptr)
{
const volatile unsigned char *addr;
@@ -215,28 +219,30 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
return (*addr >> (nr & 7)) & 1;
}
-static inline int test_and_set_bit_lock(unsigned long nr,
- volatile unsigned long *ptr)
+static inline bool arch_test_and_set_bit_lock(unsigned long nr,
+ volatile unsigned long *ptr)
{
- if (test_bit(nr, ptr))
+ if (arch_test_bit(nr, ptr))
return 1;
- return test_and_set_bit(nr, ptr);
+ return arch_test_and_set_bit(nr, ptr);
}
-static inline void clear_bit_unlock(unsigned long nr,
- volatile unsigned long *ptr)
+static inline void arch_clear_bit_unlock(unsigned long nr,
+ volatile unsigned long *ptr)
{
smp_mb__before_atomic();
- clear_bit(nr, ptr);
+ arch_clear_bit(nr, ptr);
}
-static inline void __clear_bit_unlock(unsigned long nr,
- volatile unsigned long *ptr)
+static inline void arch___clear_bit_unlock(unsigned long nr,
+ volatile unsigned long *ptr)
{
smp_mb();
- __clear_bit(nr, ptr);
+ arch___clear_bit(nr, ptr);
}
+#include <asm-generic/bitops-instrumented.h>
+
/*
* Functions which use MSB0 bit numbering.
* The bits are numbered:
@@ -261,7 +267,8 @@ static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-static inline int test_and_clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+static inline bool test_and_clear_bit_inv(unsigned long nr,
+ volatile unsigned long *ptr)
{
return test_and_clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
@@ -276,8 +283,8 @@ static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr
return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-static inline int test_bit_inv(unsigned long nr,
- const volatile unsigned long *ptr)
+static inline bool test_bit_inv(unsigned long nr,
+ const volatile unsigned long *ptr)
{
return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index a4d38092530a..823578c6b9e2 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -177,6 +177,8 @@ static inline int devmem_is_allowed(unsigned long pfn)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define ARCH_ZONE_DMA_BITS 31
+
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index db5ef22c46e4..f647d565bd6d 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -28,7 +28,7 @@
* @sliba: storage list information block address
* @sla: storage list address
* @slsba: storage list state block address
- * @akey: access key for DLIB
+ * @akey: access key for SLIB
* @bkey: access key for SL
* @ckey: access key for SBALs
* @dkey: access key for SLSB
@@ -50,11 +50,10 @@ struct qdesfmt0 {
/**
* struct qdr - queue description record (QDR)
* @qfmt: queue format
- * @pfmt: implementation dependent parameter format
* @ac: adapter characteristics
* @iqdcnt: input queue descriptor count
* @oqdcnt: output queue descriptor count
- * @iqdsz: inpout queue descriptor size
+ * @iqdsz: input queue descriptor size
* @oqdsz: output queue descriptor size
* @qiba: queue information block address
* @qkey: queue information block key
@@ -62,8 +61,7 @@ struct qdesfmt0 {
*/
struct qdr {
u32 qfmt : 8;
- u32 pfmt : 8;
- u32 : 8;
+ u32 : 16;
u32 ac : 8;
u32 : 8;
u32 iqdcnt : 8;
@@ -327,6 +325,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* struct qdio_initialize - qdio initialization data
* @cdev: associated ccw device
* @q_format: queue format
+ * @qdr_ac: feature flags to set
* @adapter_name: name for the adapter
* @qib_param_field_format: format for qib_parm_field
* @qib_param_field: pointer to 128 bytes or NULL, if no param field
@@ -338,6 +337,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @input_handler: handler to be called for input queues
* @output_handler: handler to be called for output queues
* @queue_start_poll_array: polling handlers (one per input queue or NULL)
+ * @scan_threshold: # of in-use buffers that triggers scan on output queue
* @int_parm: interruption parameter
* @input_sbal_addr_array: address of no_input_qs * 128 pointers
* @output_sbal_addr_array: address of no_output_qs * 128 pointers
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 82deb8fc8319..70bd65724ec4 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -54,6 +54,7 @@
#define INITRD_SIZE_OFFSET 0x10410
#define OLDMEM_BASE_OFFSET 0x10418
#define OLDMEM_SIZE_OFFSET 0x10420
+#define KERNEL_VERSION_OFFSET 0x10428
#define COMMAND_LINE_OFFSET 0x10480
#ifndef __ASSEMBLY__
@@ -74,7 +75,8 @@ struct parmarea {
unsigned long initrd_size; /* 0x10410 */
unsigned long oldmem_base; /* 0x10418 */
unsigned long oldmem_size; /* 0x10420 */
- char pad1[0x10480 - 0x10428]; /* 0x10428 - 0x10480 */
+ unsigned long kernel_version; /* 0x10428 */
+ char pad1[0x10480 - 0x10430]; /* 0x10430 - 0x10480 */
char command_line[ARCH_COMMAND_LINE_SIZE]; /* 0x10480 */
};
@@ -82,6 +84,7 @@ extern int noexec_disabled;
extern int memory_end_set;
extern unsigned long memory_end;
extern unsigned long max_physmem_end;
+extern unsigned long __swsusp_reset_dma;
#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index b6755685c7b8..9e9f75ef046a 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -34,5 +34,6 @@
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
#endif /* _ASM_S390_UNISTD_H_ */
diff --git a/arch/s390/include/uapi/asm/bpf_perf_event.h b/arch/s390/include/uapi/asm/bpf_perf_event.h
index cefe7c7cd4f6..3ed42ff6da94 100644
--- a/arch/s390/include/uapi/asm/bpf_perf_event.h
+++ b/arch/s390/include/uapi/asm/bpf_perf_event.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
#define _UAPI__ASM_BPF_PERF_EVENT_H__
diff --git a/arch/s390/include/uapi/asm/ipl.h b/arch/s390/include/uapi/asm/ipl.h
index fd32b1cd80d2..451ba7d08905 100644
--- a/arch/s390/include/uapi/asm/ipl.h
+++ b/arch/s390/include/uapi/asm/ipl.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_S390_UAPI_IPL_H
#define _ASM_S390_UAPI_IPL_H
diff --git a/arch/s390/include/uapi/asm/zcrypt.h b/arch/s390/include/uapi/asm/zcrypt.h
index 494c34c50716..8c5755f41dde 100644
--- a/arch/s390/include/uapi/asm/zcrypt.h
+++ b/arch/s390/include/uapi/asm/zcrypt.h
@@ -20,6 +20,7 @@
#include <linux/ioctl.h>
#include <linux/compiler.h>
+#include <linux/types.h>
/* Name of the zcrypt device driver. */
#define ZCRYPT_NAME "zcrypt"
@@ -160,17 +161,17 @@ struct ica_xcRB {
* @payload_len: Payload length
*/
struct ep11_cprb {
- uint16_t cprb_len;
+ __u16 cprb_len;
unsigned char cprb_ver_id;
unsigned char pad_000[2];
unsigned char flags;
unsigned char func_id[2];
- uint32_t source_id;
- uint32_t target_id;
- uint32_t ret_code;
- uint32_t reserved1;
- uint32_t reserved2;
- uint32_t payload_len;
+ __u32 source_id;
+ __u32 target_id;
+ __u32 ret_code;
+ __u32 reserved1;
+ __u32 reserved2;
+ __u32 payload_len;
} __attribute__((packed));
/**
@@ -179,8 +180,8 @@ struct ep11_cprb {
* @dom_id: Usage domain id
*/
struct ep11_target_dev {
- uint16_t ap_id;
- uint16_t dom_id;
+ __u16 ap_id;
+ __u16 dom_id;
};
/**
@@ -195,14 +196,14 @@ struct ep11_target_dev {
* @resp: Addr to response block
*/
struct ep11_urb {
- uint16_t targets_num;
- uint64_t targets;
- uint64_t weight;
- uint64_t req_no;
- uint64_t req_len;
- uint64_t req;
- uint64_t resp_len;
- uint64_t resp;
+ __u16 targets_num;
+ __u64 targets;
+ __u64 weight;
+ __u64 req_no;
+ __u64 req_len;
+ __u64 req;
+ __u64 resp_len;
+ __u64 resp;
} __attribute__((packed));
/**
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index ac06c3949ab3..34bdc60c0b11 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -114,12 +114,8 @@ recursion_check:
* If it comes up a second time then there's something wrong going on:
* just break out and report an unknown stack type.
*/
- if (*visit_mask & (1UL << info->type)) {
- printk_deferred_once(KERN_WARNING
- "WARNING: stack recursion on stack type %d\n",
- info->type);
+ if (*visit_mask & (1UL << info->type))
goto unknown;
- }
*visit_mask |= 1UL << info->type;
return 0;
unknown:
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 5aea1a527443..f384a18e6c26 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -60,12 +60,5 @@ ENTRY(startup_continue)
.align 16
.LPG1:
-.Lpcmsk:.quad 0x0000000180000000
-.L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
-.Lnop: .long 0x07000700
-.Lparmaddr:
- .quad PARMAREA
- .align 64
.Ldw: .quad 0x0002000180000000,0x0000000000000000
.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2c0a515428d6..6837affc19e8 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -31,7 +31,6 @@
#include <asm/os_info.h>
#include <asm/sections.h>
#include <asm/boot_data.h>
-#include <asm/uv.h>
#include "entry.h"
#define IPL_PARM_BLOCK_VERSION 0
@@ -892,21 +891,15 @@ static void __reipl_run(void *unused)
{
switch (reipl_type) {
case IPL_TYPE_CCW:
- uv_set_shared(__pa(reipl_block_ccw));
diag308(DIAG308_SET, reipl_block_ccw);
- uv_remove_shared(__pa(reipl_block_ccw));
diag308(DIAG308_LOAD_CLEAR, NULL);
break;
case IPL_TYPE_FCP:
- uv_set_shared(__pa(reipl_block_fcp));
diag308(DIAG308_SET, reipl_block_fcp);
- uv_remove_shared(__pa(reipl_block_fcp));
diag308(DIAG308_LOAD_CLEAR, NULL);
break;
case IPL_TYPE_NSS:
- uv_set_shared(__pa(reipl_block_nss));
diag308(DIAG308_SET, reipl_block_nss);
- uv_remove_shared(__pa(reipl_block_nss));
diag308(DIAG308_LOAD_CLEAR, NULL);
break;
case IPL_TYPE_UNKNOWN:
@@ -1176,9 +1169,7 @@ static struct kset *dump_kset;
static void diag308_dump(void *dump_block)
{
- uv_set_shared(__pa(dump_block));
diag308(DIAG308_SET, dump_block);
- uv_remove_shared(__pa(dump_block));
while (1) {
if (diag308(DIAG308_LOAD_NORMAL_DUMP, NULL) != 0x302)
break;
diff --git a/arch/s390/kernel/machine_kexec_reloc.c b/arch/s390/kernel/machine_kexec_reloc.c
index 1dded39239f8..3b664cb3ec4d 100644
--- a/arch/s390/kernel/machine_kexec_reloc.c
+++ b/arch/s390/kernel/machine_kexec_reloc.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/elf.h>
+#include <asm/kexec.h>
int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
unsigned long addr)
diff --git a/arch/s390/kernel/perf_cpum_cf_diag.c b/arch/s390/kernel/perf_cpum_cf_diag.c
index d4e031f7b9c8..5f1fd1581330 100644
--- a/arch/s390/kernel/perf_cpum_cf_diag.c
+++ b/arch/s390/kernel/perf_cpum_cf_diag.c
@@ -34,7 +34,7 @@ struct cf_diag_csd { /* Counter set data per CPU */
unsigned char start[PAGE_SIZE]; /* Counter set at event start */
unsigned char data[PAGE_SIZE]; /* Counter set at event delete */
};
-DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
+static DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
/* Counter sets are stored as data stream in a page sized memory buffer and
* exported to user space via raw data attached to the event sample data.
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2b94b0ad3588..253177900950 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -1114,8 +1114,7 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = Root_RAM0;
- /* Is init_mm really needed? */
- init_mm.start_code = PAGE_OFFSET;
+ init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) _end;
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index a90d3e945445..3054e9c035a3 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -437,4 +437,4 @@
432 common fsmount sys_fsmount sys_fsmount
433 common fspick sys_fspick sys_fspick
434 common pidfd_open sys_pidfd_open sys_pidfd_open
-# 435 reserved for clone3
+435 common clone3 sys_clone3 sys_clone3
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 243d8b1185bf..c6bc190f3c28 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -216,11 +216,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
if (!vdso_enabled)
return 0;
- /*
- * Only map the vdso for dynamically linked elf binaries.
- */
- if (!uses_interp)
- return 0;
vdso_pages = vdso64_pages;
#ifdef CONFIG_COMPAT_VDSO
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 49d55327de0b..7e0eb4020917 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -32,10 +32,9 @@ PHDRS {
SECTIONS
{
. = 0x100000;
- _stext = .; /* Start of text section */
.text : {
- /* Text and read-only data */
- _text = .;
+ _stext = .; /* Start of text section */
+ _text = .; /* Text and read-only data */
HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
@@ -47,11 +46,10 @@ SECTIONS
*(.text.*_indirect_*)
*(.fixup)
*(.gnu.warning)
+ . = ALIGN(PAGE_SIZE);
+ _etext = .; /* End of text section */
} :text = 0x0700
- . = ALIGN(PAGE_SIZE);
- _etext = .; /* End of text section */
-
NOTES :text :note
.dummy : { *(.dummy) } :data
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index b5fd6e85657c..d1ccc168c071 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -1961,6 +1961,16 @@ int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
case KVM_S390_MCHK:
irq->u.mchk.mcic = s390int->parm64;
break;
+ case KVM_S390_INT_PFAULT_INIT:
+ irq->u.ext.ext_params = s390int->parm;
+ irq->u.ext.ext_params2 = s390int->parm64;
+ break;
+ case KVM_S390_RESTART:
+ case KVM_S390_INT_CLOCK_COMP:
+ case KVM_S390_INT_CPU_TIMER:
+ break;
+ default:
+ return -EINVAL;
}
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 3f520cd837fb..39cff07bf2eb 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1018,6 +1018,8 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
/* mark all the pages in active slots as dirty */
for (slotnr = 0; slotnr < slots->used_slots; slotnr++) {
ms = slots->memslots + slotnr;
+ if (!ms->dirty_bitmap)
+ return -EINVAL;
/*
* The second half of the bitmap is only used on x86,
* and would be wasted otherwise, so we put it to good
@@ -2516,16 +2518,6 @@ out_err:
return rc;
}
-bool kvm_arch_has_vcpu_debugfs(void)
-{
- return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
- return 0;
-}
-
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
VCPU_EVENT(vcpu, 3, "%s", "free cpu");
@@ -4333,7 +4325,7 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp,
}
case KVM_S390_INTERRUPT: {
struct kvm_s390_interrupt s390int;
- struct kvm_s390_irq s390irq;
+ struct kvm_s390_irq s390irq = {};
if (copy_from_user(&s390int, argp, sizeof(s390int)))
return -EFAULT;
diff --git a/arch/s390/lib/xor.c b/arch/s390/lib/xor.c
index 96580590ccaf..29d9470dbceb 100644
--- a/arch/s390/lib/xor.c
+++ b/arch/s390/lib/xor.c
@@ -9,6 +9,7 @@
#include <linux/types.h>
#include <linux/export.h>
#include <linux/raid/xor.h>
+#include <asm/xor.h>
static void xor_xc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
{
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index 3b93ba0b5d8d..5d67b81c704a 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -161,9 +161,9 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
}
#endif
- for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++) {
+ pmd = pmd_offset(pud, addr);
+ for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++, pmd++) {
st->current_address = addr;
- pmd = pmd_offset(pud, addr);
if (!pmd_none(*pmd)) {
if (pmd_large(*pmd)) {
prot = pmd_val(*pmd) &
@@ -192,9 +192,9 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
}
#endif
- for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++) {
+ pud = pud_offset(p4d, addr);
+ for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++, pud++) {
st->current_address = addr;
- pud = pud_offset(p4d, addr);
if (!pud_none(*pud))
if (pud_large(*pud)) {
prot = pud_val(*pud) &
@@ -222,9 +222,9 @@ static void walk_p4d_level(struct seq_file *m, struct pg_state *st,
}
#endif
- for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++) {
+ p4d = p4d_offset(pgd, addr);
+ for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++, p4d++) {
st->current_address = addr;
- p4d = p4d_offset(pgd, addr);
if (!p4d_none(*p4d))
walk_pud_level(m, st, p4d, addr);
else
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 63507662828f..7b0bb475c166 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -327,6 +327,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int access,
case VM_FAULT_BADACCESS:
if (access == VM_EXEC && signal_return(regs) == 0)
break;
+ /* fallthrough */
case VM_FAULT_BADMAP:
/* Bad memory access. Check if it is kernel or user space. */
if (user_mode(regs)) {
@@ -336,7 +337,9 @@ static noinline void do_fault_error(struct pt_regs *regs, int access,
do_sigsegv(regs, si_code);
break;
}
+ /* fallthrough */
case VM_FAULT_BADCONTEXT:
+ /* fallthrough */
case VM_FAULT_PFAULT:
do_no_context(regs);
break;
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 1e668b95e0c6..39c3a6e3d262 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -2424,8 +2424,8 @@ EXPORT_SYMBOL_GPL(gmap_pmdp_idte_global);
* This function is assumed to be called with the guest_table_lock
* held.
*/
-bool gmap_test_and_clear_dirty_pmd(struct gmap *gmap, pmd_t *pmdp,
- unsigned long gaddr)
+static bool gmap_test_and_clear_dirty_pmd(struct gmap *gmap, pmd_t *pmdp,
+ unsigned long gaddr)
{
if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID)
return false;
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 99e06213a22b..54fcdf66ae96 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -17,8 +17,6 @@
#ifdef CONFIG_PGSTE
-static int page_table_allocate_pgste_min = 0;
-static int page_table_allocate_pgste_max = 1;
int page_table_allocate_pgste = 0;
EXPORT_SYMBOL(page_table_allocate_pgste);
@@ -29,8 +27,8 @@ static struct ctl_table page_table_sysctl[] = {
.maxlen = sizeof(int),
.mode = S_IRUGO | S_IWUSR,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &page_table_allocate_pgste_min,
- .extra2 = &page_table_allocate_pgste_max,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
},
{ }
};
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index e636728ab452..955eb355c2fd 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -863,7 +863,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
break;
case BPF_ALU64 | BPF_NEG: /* dst = -dst */
/* lcgr %dst,%dst */
- EMIT4(0xb9130000, dst_reg, dst_reg);
+ EMIT4(0xb9030000, dst_reg, dst_reg);
break;
/*
* BPF_FROM_BE/LE
@@ -1049,8 +1049,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
/* llgf %w1,map.max_entries(%b2) */
EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_2,
offsetof(struct bpf_array, map.max_entries));
- /* clgrj %b3,%w1,0xa,label0: if %b3 >= %w1 goto out */
- EMIT6_PCREL_LABEL(0xec000000, 0x0065, BPF_REG_3,
+ /* clrj %b3,%w1,0xa,label0: if (u32)%b3 >= (u32)%w1 goto out */
+ EMIT6_PCREL_LABEL(0xec000000, 0x0077, BPF_REG_3,
REG_W1, 0, 0xa);
/*
@@ -1076,8 +1076,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
* goto out;
*/
- /* sllg %r1,%b3,3: %r1 = index * 8 */
- EMIT6_DISP_LH(0xeb000000, 0x000d, REG_1, BPF_REG_3, REG_0, 3);
+ /* llgfr %r1,%b3: %r1 = (u32) index */
+ EMIT4(0xb9160000, REG_1, BPF_REG_3);
+ /* sllg %r1,%r1,3: %r1 *= 8 */
+ EMIT6_DISP_LH(0xeb000000, 0x000d, REG_1, REG_1, REG_0, 3);
/* lg %r1,prog(%b2,%r1) */
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_1, BPF_REG_2,
REG_1, offsetof(struct bpf_array, ptrs));
diff --git a/arch/s390/scripts/Makefile.chkbss b/arch/s390/scripts/Makefile.chkbss
index 884a9caff5fb..f4f4c2c6dee9 100644
--- a/arch/s390/scripts/Makefile.chkbss
+++ b/arch/s390/scripts/Makefile.chkbss
@@ -11,8 +11,7 @@ chkbss: $(addprefix $(obj)/, $(chkbss-files))
quiet_cmd_chkbss = CHKBSS $<
cmd_chkbss = \
- if $(OBJDUMP) -h $< | grep -q "\.bss" && \
- ! $(OBJDUMP) -j .bss -w -h $< | awk 'END { if ($$3) exit 1 }'; then \
+ if ! $(OBJSIZE) --common $< | $(AWK) 'END { if ($$3) exit 1 }'; then \
echo "error: $< .bss section is not empty" >&2; exit 1; \
fi; \
touch $@;
diff --git a/arch/sh/include/uapi/asm/setup.h b/arch/sh/include/uapi/asm/setup.h
index 1170dd2fb998..4bd19f80f9b0 100644
--- a/arch/sh/include/uapi/asm/setup.h
+++ b/arch/sh/include/uapi/asm/setup.h
@@ -1,2 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#include <asm-generic/setup.h>
diff --git a/arch/sh/include/uapi/asm/types.h b/arch/sh/include/uapi/asm/types.h
index f83795fdc0da..68100e108ea6 100644
--- a/arch/sh/include/uapi/asm/types.h
+++ b/arch/sh/include/uapi/asm/types.h
@@ -1,2 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#include <asm-generic/types.h>
diff --git a/arch/sh/kernel/disassemble.c b/arch/sh/kernel/disassemble.c
index defebf1a9c8a..845543780cc5 100644
--- a/arch/sh/kernel/disassemble.c
+++ b/arch/sh/kernel/disassemble.c
@@ -475,8 +475,6 @@ static void print_sh_insn(u32 memaddr, u16 insn)
printk("dbr");
break;
case FD_REG_N:
- if (0)
- goto d_reg_n;
case F_REG_N:
printk("fr%d", rn);
break;
@@ -488,7 +486,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
printk("xd%d", rn & ~1);
break;
}
- d_reg_n:
+ /* else, fall through */
case D_REG_N:
printk("dr%d", rn);
break;
@@ -497,6 +495,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
printk("xd%d", rm & ~1);
break;
}
+ /* else, fall through */
case D_REG_M:
printk("dr%d", rm);
break;
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index 3bd010b4c55f..f10d64311127 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -157,6 +157,7 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
switch (sh_type) {
case SH_BREAKPOINT_READ:
*gen_type = HW_BREAKPOINT_R;
+ break;
case SH_BREAKPOINT_WRITE:
*gen_type = HW_BREAKPOINT_W;
break;
diff --git a/arch/sparc/include/uapi/asm/oradax.h b/arch/sparc/include/uapi/asm/oradax.h
index 64c67f2ea33f..0dace69058ab 100644
--- a/arch/sparc/include/uapi/asm/oradax.h
+++ b/arch/sparc/include/uapi/asm/oradax.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*/
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index ccc88926bc00..9f41a6f5a032 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -336,25 +336,28 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
{
long err;
+ if (!IS_ENABLED(CONFIG_SYSVIPC))
+ return -ENOSYS;
+
/* No need for backward compatibility. We can start fresh... */
if (call <= SEMTIMEDOP) {
switch (call) {
case SEMOP:
- err = sys_semtimedop(first, ptr,
- (unsigned int)second, NULL);
+ err = ksys_semtimedop(first, ptr,
+ (unsigned int)second, NULL);
goto out;
case SEMTIMEDOP:
- err = sys_semtimedop(first, ptr, (unsigned int)second,
+ err = ksys_semtimedop(first, ptr, (unsigned int)second,
(const struct __kernel_timespec __user *)
- (unsigned long) fifth);
+ (unsigned long) fifth);
goto out;
case SEMGET:
- err = sys_semget(first, (int)second, (int)third);
+ err = ksys_semget(first, (int)second, (int)third);
goto out;
case SEMCTL: {
- err = sys_semctl(first, second,
- (int)third | IPC_64,
- (unsigned long) ptr);
+ err = ksys_old_semctl(first, second,
+ (int)third | IPC_64,
+ (unsigned long) ptr);
goto out;
}
default:
@@ -365,18 +368,18 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
if (call <= MSGCTL) {
switch (call) {
case MSGSND:
- err = sys_msgsnd(first, ptr, (size_t)second,
+ err = ksys_msgsnd(first, ptr, (size_t)second,
(int)third);
goto out;
case MSGRCV:
- err = sys_msgrcv(first, ptr, (size_t)second, fifth,
+ err = ksys_msgrcv(first, ptr, (size_t)second, fifth,
(int)third);
goto out;
case MSGGET:
- err = sys_msgget((key_t)first, (int)second);
+ err = ksys_msgget((key_t)first, (int)second);
goto out;
case MSGCTL:
- err = sys_msgctl(first, (int)second | IPC_64, ptr);
+ err = ksys_old_msgctl(first, (int)second | IPC_64, ptr);
goto out;
default:
err = -ENOSYS;
@@ -396,13 +399,13 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
goto out;
}
case SHMDT:
- err = sys_shmdt(ptr);
+ err = ksys_shmdt(ptr);
goto out;
case SHMGET:
- err = sys_shmget(first, (size_t)second, (int)third);
+ err = ksys_shmget(first, (size_t)second, (int)third);
goto out;
case SHMCTL:
- err = sys_shmctl(first, (int)second | IPC_64, ptr);
+ err = ksys_old_shmctl(first, (int)second | IPC_64, ptr);
goto out;
default:
err = -ENOSYS;
diff --git a/arch/um/include/shared/timer-internal.h b/arch/um/include/shared/timer-internal.h
index 8574338bf23b..9991ec2371e4 100644
--- a/arch/um/include/shared/timer-internal.h
+++ b/arch/um/include/shared/timer-internal.h
@@ -34,10 +34,13 @@ static inline void time_travel_set_time(unsigned long long ns)
time_travel_time = ns;
}
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
- unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
{
time_travel_timer_mode = mode;
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
+{
time_travel_timer_expiry = expiry;
}
#else
@@ -50,8 +53,11 @@ static inline void time_travel_set_time(unsigned long long ns)
{
}
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
- unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
+{
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
{
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 67c0d1a860e9..6bede7888fc2 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -213,7 +213,7 @@ static void time_travel_sleep(unsigned long long duration)
if (time_travel_timer_mode != TT_TMR_DISABLED ||
time_travel_timer_expiry < next) {
if (time_travel_timer_mode == TT_TMR_ONESHOT)
- time_travel_set_timer(TT_TMR_DISABLED, 0);
+ time_travel_set_timer_mode(TT_TMR_DISABLED);
/*
* time_travel_time will be adjusted in the timer
* IRQ handler so it works even when the signal
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 6a051b078359..234757233355 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -50,7 +50,7 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
static int itimer_shutdown(struct clock_event_device *evt)
{
if (time_travel_mode != TT_MODE_OFF)
- time_travel_set_timer(TT_TMR_DISABLED, 0);
+ time_travel_set_timer_mode(TT_TMR_DISABLED);
if (time_travel_mode != TT_MODE_INFCPU)
os_timer_disable();
@@ -62,9 +62,10 @@ static int itimer_set_periodic(struct clock_event_device *evt)
{
unsigned long long interval = NSEC_PER_SEC / HZ;
- if (time_travel_mode != TT_MODE_OFF)
- time_travel_set_timer(TT_TMR_PERIODIC,
- time_travel_time + interval);
+ if (time_travel_mode != TT_MODE_OFF) {
+ time_travel_set_timer_mode(TT_TMR_PERIODIC);
+ time_travel_set_timer_expiry(time_travel_time + interval);
+ }
if (time_travel_mode != TT_MODE_INFCPU)
os_timer_set_interval(interval);
@@ -77,9 +78,10 @@ static int itimer_next_event(unsigned long delta,
{
delta += 1;
- if (time_travel_mode != TT_MODE_OFF)
- time_travel_set_timer(TT_TMR_ONESHOT,
- time_travel_time + delta);
+ if (time_travel_mode != TT_MODE_OFF) {
+ time_travel_set_timer_mode(TT_TMR_ONESHOT);
+ time_travel_set_timer_expiry(time_travel_time + delta);
+ }
if (time_travel_mode != TT_MODE_INFCPU)
return os_timer_one_shot(delta);
diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
index d1129828c41e..c014ae3c3e48 100644
--- a/arch/unicore32/kernel/irq.c
+++ b/arch/unicore32/kernel/irq.c
@@ -21,7 +21,6 @@
#include <linux/kallsyms.h>
#include <linux/proc_fs.h>
#include <linux/syscore_ops.h>
-#include <linux/gpio.h>
#include <mach/hardware.h>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 222855cc0158..58eae28c3dd6 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1503,7 +1503,7 @@ config X86_5LEVEL
config X86_DIRECT_GBPAGES
def_bool y
- depends on X86_64 && !DEBUG_PAGEALLOC
+ depends on X86_64
---help---
Certain kernel features effectively disable kernel
linear 1 GB mappings (even if the CPU otherwise
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 71c92db47c41..bf9cd83de777 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -171,7 +171,7 @@ config HAVE_MMIOTRACE_SUPPORT
config X86_DECODER_SELFTEST
bool "x86 instruction decoder selftest"
- depends on DEBUG_KERNEL && KPROBES
+ depends on DEBUG_KERNEL && INSTRUCTION_DECODER
depends on !COMPILE_TEST
---help---
Perform x86 instruction decoder selftests at build time.
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 56e748a7679f..94df0868804b 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -38,6 +38,7 @@ REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \
REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding)
REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector)
+REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -Wno-address-of-packed-member)
REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4))
export REALMODE_CFLAGS
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 19eca14b49a0..ca866f1cca2e 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -28,8 +28,6 @@
#include "cpuflags.h"
/* Useful macros */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
extern struct setup_header hdr;
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 37380c0d5999..5e30eaaf8576 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -140,7 +140,7 @@ ENTRY(startup_32)
/*
* Jump to the relocated address.
*/
- leal relocated(%ebx), %eax
+ leal .Lrelocated(%ebx), %eax
jmp *%eax
ENDPROC(startup_32)
@@ -209,7 +209,7 @@ ENDPROC(efi32_stub_entry)
#endif
.text
-relocated:
+.Lrelocated:
/*
* Clear BSS (stack is currently empty)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 6233ae35d0d9..d98cd483377e 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -87,7 +87,7 @@ ENTRY(startup_32)
call verify_cpu
testl %eax, %eax
- jnz no_longmode
+ jnz .Lno_longmode
/*
* Compute the delta between where we were compiled to run at
@@ -322,7 +322,7 @@ ENTRY(startup_64)
1: popq %rdi
subq $1b, %rdi
- call adjust_got
+ call .Ladjust_got
/*
* At this point we are in long mode with 4-level paging enabled,
@@ -421,7 +421,7 @@ trampoline_return:
/* The new adjustment is the relocation address */
movq %rbx, %rdi
- call adjust_got
+ call .Ladjust_got
/*
* Copy the compressed kernel to the end of our buffer
@@ -440,7 +440,7 @@ trampoline_return:
/*
* Jump to the relocated address.
*/
- leaq relocated(%rbx), %rax
+ leaq .Lrelocated(%rbx), %rax
jmp *%rax
#ifdef CONFIG_EFI_STUB
@@ -511,7 +511,7 @@ ENDPROC(efi64_stub_entry)
#endif
.text
-relocated:
+.Lrelocated:
/*
* Clear BSS (stack is currently empty)
@@ -548,7 +548,7 @@ relocated:
* first time we touch GOT).
* RDI is the new adjustment to apply.
*/
-adjust_got:
+.Ladjust_got:
/* Walk through the GOT adding the address to the entries */
leaq _got(%rip), %rdx
leaq _egot(%rip), %rcx
@@ -622,7 +622,7 @@ ENTRY(trampoline_32bit_src)
movl %eax, %cr4
/* Calculate address of paging_enabled() once we are executing in the trampoline */
- leal paging_enabled - trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_OFFSET(%ecx), %eax
+ leal .Lpaging_enabled - trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_OFFSET(%ecx), %eax
/* Prepare the stack for far return to Long Mode */
pushl $__KERNEL_CS
@@ -635,7 +635,7 @@ ENTRY(trampoline_32bit_src)
lret
.code64
-paging_enabled:
+.Lpaging_enabled:
/* Return from the trampoline */
jmp *%rdi
@@ -647,7 +647,7 @@ paging_enabled:
.org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
.code32
-no_longmode:
+.Lno_longmode:
/* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */
1:
hlt
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 5f2d03067ae5..c8862696a47b 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
/* Find the first usable memory region under bios_start. */
for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+ unsigned long new = bios_start;
+
entry = &boot_params->e820_table[i];
/* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
/* Adjust bios_start to the end of the entry if needed. */
if (bios_start > entry->addr + entry->size)
- bios_start = entry->addr + entry->size;
+ new = entry->addr + entry->size;
/* Keep bios_start page-aligned. */
- bios_start = round_down(bios_start, PAGE_SIZE);
+ new = round_down(new, PAGE_SIZE);
/* Skip the entry if it's too small. */
- if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+ if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
continue;
+ /* Protect against underflow. */
+ if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+ break;
+
+ bios_start = new;
break;
}
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 996df3d586f0..e3add857c2c9 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -10,6 +10,7 @@
/*
* Main module for the real-mode kernel code
*/
+#include <linux/build_bug.h>
#include "boot.h"
#include "string.h"
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
index 401e30ca0a75..8272a4492844 100644
--- a/arch/x86/boot/string.c
+++ b/arch/x86/boot/string.c
@@ -37,6 +37,14 @@ int memcmp(const void *s1, const void *s2, size_t len)
return diff;
}
+/*
+ * Clang may lower `memcmp == 0` to `bcmp == 0`.
+ */
+int bcmp(const void *s1, const void *s2, size_t len)
+{
+ return memcmp(s1, s2, len);
+}
+
int strcmp(const char *str1, const char *str2)
{
const unsigned char *s1 = (const unsigned char *)str1;
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 830bd984182b..515c0ceeb4a3 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -314,6 +314,23 @@ For 32-bit we have the following conventions - kernel is built with
#endif
+/*
+ * Mitigate Spectre v1 for conditional swapgs code paths.
+ *
+ * FENCE_SWAPGS_USER_ENTRY is used in the user entry swapgs code path, to
+ * prevent a speculative swapgs when coming from kernel space.
+ *
+ * FENCE_SWAPGS_KERNEL_ENTRY is used in the kernel entry non-swapgs code path,
+ * to prevent the swapgs from getting speculatively skipped when coming from
+ * user space.
+ */
+.macro FENCE_SWAPGS_USER_ENTRY
+ ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_USER
+.endm
+.macro FENCE_SWAPGS_KERNEL_ENTRY
+ ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_KERNEL
+.endm
+
.macro STACKLEAK_ERASE_NOCLOBBER
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
PUSH_AND_CLEAR_REGS
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 536b574b6161..3f8e22615812 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -285,15 +285,16 @@ __visible void do_syscall_64(unsigned long nr, struct pt_regs *regs)
if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY)
nr = syscall_trace_enter(regs);
- /*
- * NB: Native and x32 syscalls are dispatched from the same
- * table. The only functional difference is the x32 bit in
- * regs->orig_ax, which changes the behavior of some syscalls.
- */
- nr &= __SYSCALL_MASK;
if (likely(nr < NR_syscalls)) {
nr = array_index_nospec(nr, NR_syscalls);
regs->ax = sys_call_table[nr](regs);
+#ifdef CONFIG_X86_X32_ABI
+ } else if (likely((nr & __X32_SYSCALL_BIT) &&
+ (nr & ~__X32_SYSCALL_BIT) < X32_NR_syscalls)) {
+ nr = array_index_nospec(nr & ~__X32_SYSCALL_BIT,
+ X32_NR_syscalls);
+ regs->ax = x32_sys_call_table[nr](regs);
+#endif
}
syscall_return_slowpath(regs);
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 2bb986f305ac..f83ca5aa8b77 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -63,7 +63,7 @@
* enough to patch inline, increasing performance.
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
# define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
#else
# define preempt_stop(clobbers)
@@ -1084,7 +1084,7 @@ restore_all:
INTERRUPT_RETURN
restore_all_kernel:
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
DISABLE_INTERRUPTS(CLBR_ANY)
cmpl $0, PER_CPU_VAR(__preempt_count)
jnz .Lno_preempt
@@ -1364,7 +1364,7 @@ ENTRY(xen_hypervisor_callback)
ENTRY(xen_do_upcall)
1: mov %esp, %eax
call xen_evtchn_do_upcall
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
call xen_maybe_preempt_hcall
#endif
jmp ret_from_intr
@@ -1443,8 +1443,12 @@ BUILD_INTERRUPT3(hv_stimer0_callback_vector, HYPERV_STIMER0_VECTOR,
ENTRY(page_fault)
ASM_CLAC
- pushl $0; /* %gs's slot on the stack */
+ pushl $do_page_fault
+ jmp common_exception_read_cr2
+END(page_fault)
+common_exception_read_cr2:
+ /* the function address is in %gs's slot on the stack */
SAVE_ALL switch_stacks=1 skip_gs=1
ENCODE_FRAME_POINTER
@@ -1452,6 +1456,7 @@ ENTRY(page_fault)
/* fixup %gs */
GS_TO_REG %ecx
+ movl PT_GS(%esp), %edi
REG_TO_PTGS %ecx
SET_KERNEL_GS %ecx
@@ -1463,9 +1468,9 @@ ENTRY(page_fault)
TRACE_IRQS_OFF
movl %esp, %eax # pt_regs pointer
- call do_page_fault
+ CALL_NOSPEC %edi
jmp ret_from_exception
-END(page_fault)
+END(common_exception_read_cr2)
common_exception:
/* the function address is in %gs's slot on the stack */
@@ -1595,7 +1600,7 @@ END(general_protection)
ENTRY(async_page_fault)
ASM_CLAC
pushl $do_async_page_fault
- jmp common_exception
+ jmp common_exception_read_cr2
END(async_page_fault)
#endif
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 3f5a978a02a7..b7c3ea4cb19d 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -519,7 +519,7 @@ ENTRY(interrupt_entry)
testb $3, CS-ORIG_RAX+8(%rsp)
jz 1f
SWAPGS
-
+ FENCE_SWAPGS_USER_ENTRY
/*
* Switch to the thread stack. The IRET frame and orig_ax are
* on the stack, as well as the return address. RDI..R12 are
@@ -549,8 +549,10 @@ ENTRY(interrupt_entry)
UNWIND_HINT_FUNC
movq (%rdi), %rdi
+ jmp 2f
1:
-
+ FENCE_SWAPGS_KERNEL_ENTRY
+2:
PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER 8
@@ -662,7 +664,7 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode)
/* Returning to kernel space */
retint_kernel:
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
/* Interrupts are off */
/* Check if we need preemption */
btl $9, EFLAGS(%rsp) /* were interrupts off? */
@@ -1056,10 +1058,10 @@ ENTRY(native_load_gs_index)
ENDPROC(native_load_gs_index)
EXPORT_SYMBOL(native_load_gs_index)
- _ASM_EXTABLE(.Lgs_change, bad_gs)
+ _ASM_EXTABLE(.Lgs_change, .Lbad_gs)
.section .fixup, "ax"
/* running with kernelgs */
-bad_gs:
+.Lbad_gs:
SWAPGS /* switch back to user gs */
.macro ZAP_GS
/* This can't be a string because the preprocessor needs to see it. */
@@ -1113,7 +1115,7 @@ ENTRY(xen_do_hypervisor_callback) /* do_hypervisor_callback(struct *pt_regs) */
call xen_evtchn_do_upcall
LEAVE_IRQ_STACK
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
call xen_maybe_preempt_hcall
#endif
jmp error_exit
@@ -1238,6 +1240,13 @@ ENTRY(paranoid_entry)
*/
SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
+ /*
+ * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an
+ * unconditional CR3 write, even in the PTI case. So do an lfence
+ * to prevent GS speculation, regardless of whether PTI is enabled.
+ */
+ FENCE_SWAPGS_KERNEL_ENTRY
+
ret
END(paranoid_entry)
@@ -1288,6 +1297,7 @@ ENTRY(error_entry)
* from user mode due to an IRET fault.
*/
SWAPGS
+ FENCE_SWAPGS_USER_ENTRY
/* We have user CR3. Change to kernel CR3. */
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
@@ -1301,6 +1311,8 @@ ENTRY(error_entry)
pushq %r12
ret
+.Lerror_entry_done_lfence:
+ FENCE_SWAPGS_KERNEL_ENTRY
.Lerror_entry_done:
ret
@@ -1318,7 +1330,7 @@ ENTRY(error_entry)
cmpq %rax, RIP+8(%rsp)
je .Lbstep_iret
cmpq $.Lgs_change, RIP+8(%rsp)
- jne .Lerror_entry_done
+ jne .Lerror_entry_done_lfence
/*
* hack: .Lgs_change can fail with user gsbase. If this happens, fix up
@@ -1326,6 +1338,7 @@ ENTRY(error_entry)
* .Lgs_change's error handler with kernel gsbase.
*/
SWAPGS
+ FENCE_SWAPGS_USER_ENTRY
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
jmp .Lerror_entry_done
@@ -1340,6 +1353,7 @@ ENTRY(error_entry)
* gsbase and CR3. Switch to kernel gsbase and CR3:
*/
SWAPGS
+ FENCE_SWAPGS_USER_ENTRY
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
/*
@@ -1431,6 +1445,7 @@ ENTRY(nmi)
swapgs
cld
+ FENCE_SWAPGS_USER_ENTRY
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx
movq %rsp, %rdx
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index d5252bc1e380..b1bf31713374 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -10,10 +10,13 @@
/* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */
extern asmlinkage long sys_ni_syscall(const struct pt_regs *);
#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
+#define __SYSCALL_X32(nr, sym, qual) __SYSCALL_64(nr, sym, qual)
#include <asm/syscalls_64.h>
#undef __SYSCALL_64
+#undef __SYSCALL_X32
#define __SYSCALL_64(nr, sym, qual) [nr] = sym,
+#define __SYSCALL_X32(nr, sym, qual)
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
/*
@@ -23,3 +26,25 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
[0 ... __NR_syscall_max] = &sys_ni_syscall,
#include <asm/syscalls_64.h>
};
+
+#undef __SYSCALL_64
+#undef __SYSCALL_X32
+
+#ifdef CONFIG_X86_X32_ABI
+
+#define __SYSCALL_64(nr, sym, qual)
+#define __SYSCALL_X32(nr, sym, qual) [nr] = sym,
+
+asmlinkage const sys_call_ptr_t x32_sys_call_table[__NR_syscall_x32_max+1] = {
+ /*
+ * Smells like a compiler bug -- it doesn't work
+ * when the & below is removed.
+ */
+ [0 ... __NR_syscall_x32_max] = &sys_ni_syscall,
+#include <asm/syscalls_64.h>
+};
+
+#undef __SYSCALL_64
+#undef __SYSCALL_X32
+
+#endif
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index c00019abd076..3fe02546aed3 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -186,11 +186,11 @@
172 i386 prctl sys_prctl __ia32_sys_prctl
173 i386 rt_sigreturn sys_rt_sigreturn sys32_rt_sigreturn
174 i386 rt_sigaction sys_rt_sigaction __ia32_compat_sys_rt_sigaction
-175 i386 rt_sigprocmask sys_rt_sigprocmask __ia32_sys_rt_sigprocmask
+175 i386 rt_sigprocmask sys_rt_sigprocmask __ia32_compat_sys_rt_sigprocmask
176 i386 rt_sigpending sys_rt_sigpending __ia32_compat_sys_rt_sigpending
177 i386 rt_sigtimedwait sys_rt_sigtimedwait_time32 __ia32_compat_sys_rt_sigtimedwait_time32
178 i386 rt_sigqueueinfo sys_rt_sigqueueinfo __ia32_compat_sys_rt_sigqueueinfo
-179 i386 rt_sigsuspend sys_rt_sigsuspend __ia32_sys_rt_sigsuspend
+179 i386 rt_sigsuspend sys_rt_sigsuspend __ia32_compat_sys_rt_sigsuspend
180 i386 pread64 sys_pread64 __ia32_compat_sys_x86_pread
181 i386 pwrite64 sys_pwrite64 __ia32_compat_sys_x86_pwrite
182 i386 chown sys_chown16 __ia32_sys_chown16
diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh
index 94fcd1951aca..1af2be39e7d9 100644
--- a/arch/x86/entry/syscalls/syscalltbl.sh
+++ b/arch/x86/entry/syscalls/syscalltbl.sh
@@ -1,13 +1,13 @@
-#!/bin/sh
+#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
in="$1"
out="$2"
syscall_macro() {
- abi="$1"
- nr="$2"
- entry="$3"
+ local abi="$1"
+ local nr="$2"
+ local entry="$3"
# Entry can be either just a function name or "function/qualifier"
real_entry="${entry%%/*}"
@@ -21,14 +21,14 @@ syscall_macro() {
}
emit() {
- abi="$1"
- nr="$2"
- entry="$3"
- compat="$4"
- umlentry=""
+ local abi="$1"
+ local nr="$2"
+ local entry="$3"
+ local compat="$4"
+ local umlentry=""
- if [ "$abi" = "64" -a -n "$compat" ]; then
- echo "a compat entry for a 64-bit syscall makes no sense" >&2
+ if [ "$abi" != "I386" -a -n "$compat" ]; then
+ echo "a compat entry ($abi: $compat) for a 64-bit syscall makes no sense" >&2
exit 1
fi
@@ -62,14 +62,17 @@ grep '^[0-9]' "$in" | sort -n | (
while read nr abi name entry compat; do
abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
if [ "$abi" = "COMMON" -o "$abi" = "64" ]; then
- # COMMON is the same as 64, except that we don't expect X32
- # programs to use it. Our expectation has nothing to do with
- # any generated code, so treat them the same.
emit 64 "$nr" "$entry" "$compat"
+ if [ "$abi" = "COMMON" ]; then
+ # COMMON means that this syscall exists in the same form for
+ # 64-bit and X32.
+ echo "#ifdef CONFIG_X86_X32_ABI"
+ emit X32 "$nr" "$entry" "$compat"
+ echo "#endif"
+ fi
elif [ "$abi" = "X32" ]; then
- # X32 is equivalent to 64 on an X32-compatible kernel.
echo "#ifdef CONFIG_X86_X32_ABI"
- emit 64 "$nr" "$entry" "$compat"
+ emit X32 "$nr" "$entry" "$compat"
echo "#endif"
elif [ "$abi" = "I386" ]; then
emit "$abi" "$nr" "$entry" "$compat"
diff --git a/arch/x86/entry/thunk_32.S b/arch/x86/entry/thunk_32.S
index cb3464525b37..2713490611a3 100644
--- a/arch/x86/entry/thunk_32.S
+++ b/arch/x86/entry/thunk_32.S
@@ -34,7 +34,7 @@
THUNK trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1
#endif
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
THUNK ___preempt_schedule, preempt_schedule
THUNK ___preempt_schedule_notrace, preempt_schedule_notrace
EXPORT_SYMBOL(___preempt_schedule)
diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S
index cc20465b2867..ea5c4167086c 100644
--- a/arch/x86/entry/thunk_64.S
+++ b/arch/x86/entry/thunk_64.S
@@ -46,7 +46,7 @@
THUNK lockdep_sys_exit_thunk,lockdep_sys_exit
#endif
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
THUNK ___preempt_schedule, preempt_schedule
THUNK ___preempt_schedule_notrace, preempt_schedule_notrace
EXPORT_SYMBOL(___preempt_schedule)
@@ -55,7 +55,7 @@
#if defined(CONFIG_TRACE_IRQFLAGS) \
|| defined(CONFIG_DEBUG_LOCK_ALLOC) \
- || defined(CONFIG_PREEMPT)
+ || defined(CONFIG_PREEMPTION)
.L_restore:
popq %r11
popq %r10
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index 62f317c9113a..5b35b7ea5d72 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -661,10 +661,17 @@ fail:
throttle = perf_event_overflow(event, &data, &regs);
out:
- if (throttle)
+ if (throttle) {
perf_ibs_stop(event, 0);
- else
- perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+ } else {
+ period >>= 4;
+
+ if ((ibs_caps & IBS_CAPS_RDWROPCNT) &&
+ (*config & IBS_OP_CNT_CTL))
+ period |= *config & IBS_OP_CUR_CNT_RAND;
+
+ perf_ibs_enable_event(perf_ibs, hwc, period);
+ }
perf_event_update_userpage(event);
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 81b005e4c7d9..7b21455d7504 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1005,6 +1005,27 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
/* current number of events already accepted */
n = cpuc->n_events;
+ if (!cpuc->n_events)
+ cpuc->pebs_output = 0;
+
+ if (!cpuc->is_fake && leader->attr.precise_ip) {
+ /*
+ * For PEBS->PT, if !aux_event, the group leader (PT) went
+ * away, the group was broken down and this singleton event
+ * can't schedule any more.
+ */
+ if (is_pebs_pt(leader) && !leader->aux_event)
+ return -EINVAL;
+
+ /*
+ * pebs_output: 0: no PEBS so far, 1: PT, 2: DS
+ */
+ if (cpuc->pebs_output &&
+ cpuc->pebs_output != is_pebs_pt(leader) + 1)
+ return -EINVAL;
+
+ cpuc->pebs_output = is_pebs_pt(leader) + 1;
+ }
if (is_x86_event(leader)) {
if (n >= max_count)
@@ -1236,7 +1257,7 @@ void x86_pmu_enable_event(struct perf_event *event)
* Add a single event to the PMU.
*
* The event is added to the group of enabled events
- * but only if it can be scehduled with existing events.
+ * but only if it can be scheduled with existing events.
*/
static int x86_pmu_add(struct perf_event *event, int flags)
{
@@ -2087,7 +2108,7 @@ static int x86_pmu_event_init(struct perf_event *event)
static void refresh_pce(void *ignored)
{
- load_mm_cr4(this_cpu_read(cpu_tlbstate.loaded_mm));
+ load_mm_cr4_irqsoff(this_cpu_read(cpu_tlbstate.loaded_mm));
}
static void x86_pmu_event_mapped(struct perf_event *event, struct mm_struct *mm)
@@ -2241,6 +2262,17 @@ static int x86_pmu_check_period(struct perf_event *event, u64 value)
return 0;
}
+static int x86_pmu_aux_output_match(struct perf_event *event)
+{
+ if (!(pmu.capabilities & PERF_PMU_CAP_AUX_OUTPUT))
+ return 0;
+
+ if (x86_pmu.aux_output_match)
+ return x86_pmu.aux_output_match(event);
+
+ return 0;
+}
+
static struct pmu pmu = {
.pmu_enable = x86_pmu_enable,
.pmu_disable = x86_pmu_disable,
@@ -2266,6 +2298,8 @@ static struct pmu pmu = {
.sched_task = x86_pmu_sched_task,
.task_ctx_size = sizeof(struct x86_perf_task_context),
.check_period = x86_pmu_check_period,
+
+ .aux_output_match = x86_pmu_aux_output_match,
};
void arch_perf_update_userpage(struct perf_event *event,
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 9e911a96972b..27ee47a7be66 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -18,9 +18,9 @@
#include <asm/cpufeature.h>
#include <asm/hardirq.h>
#include <asm/intel-family.h>
+#include <asm/intel_pt.h>
#include <asm/apic.h>
#include <asm/cpu_device_id.h>
-#include <asm/hypervisor.h>
#include "../perf_event.h"
@@ -263,8 +263,8 @@ static struct event_constraint intel_icl_event_constraints[] = {
};
static struct extra_reg intel_icl_extra_regs[] __read_mostly = {
- INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff9fffull, RSP_0),
- INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff9fffull, RSP_1),
+ INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffffbfffull, RSP_0),
+ INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffffbfffull, RSP_1),
INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
EVENT_EXTRA_END
@@ -3299,6 +3299,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
}
}
+ if (event->attr.aux_output) {
+ if (!event->attr.precise_ip)
+ return -EINVAL;
+
+ event->hw.flags |= PERF_X86_EVENT_PEBS_VIA_PT;
+ }
+
if (event->attr.type != PERF_TYPE_RAW)
return 0;
@@ -3573,6 +3580,11 @@ static u64 bdw_limit_period(struct perf_event *event, u64 left)
return left;
}
+static u64 nhm_limit_period(struct perf_event *event, u64 left)
+{
+ return max(left, 32ULL);
+}
+
PMU_FORMAT_ATTR(event, "config:0-7" );
PMU_FORMAT_ATTR(umask, "config:8-15" );
PMU_FORMAT_ATTR(edge, "config:18" );
@@ -3812,6 +3824,14 @@ static int intel_pmu_check_period(struct perf_event *event, u64 value)
return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
}
+static int intel_pmu_aux_output_match(struct perf_event *event)
+{
+ if (!x86_pmu.intel_cap.pebs_output_pt_available)
+ return 0;
+
+ return is_intel_pt_event(event);
+}
+
PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3936,6 +3956,8 @@ static __initconst const struct x86_pmu intel_pmu = {
.sched_task = intel_pmu_sched_task,
.check_period = intel_pmu_check_period,
+
+ .aux_output_match = intel_pmu_aux_output_match,
};
static __init void intel_clovertown_quirk(void)
@@ -3965,31 +3987,31 @@ static __init void intel_clovertown_quirk(void)
}
static const struct x86_cpu_desc isolation_ucodes[] = {
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_CORE, 3, 0x0000001f),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_ULT, 1, 0x0000001e),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_GT3E, 1, 0x00000015),
+ INTEL_CPU_DESC(INTEL_FAM6_HASWELL, 3, 0x0000001f),
+ INTEL_CPU_DESC(INTEL_FAM6_HASWELL_L, 1, 0x0000001e),
+ INTEL_CPU_DESC(INTEL_FAM6_HASWELL_G, 1, 0x00000015),
INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X, 2, 0x00000037),
INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X, 4, 0x0000000a),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_CORE, 4, 0x00000023),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_GT3E, 1, 0x00000014),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D, 2, 0x00000010),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D, 3, 0x07000009),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D, 4, 0x0f000009),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D, 5, 0x0e000002),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL, 4, 0x00000023),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_G, 1, 0x00000014),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 2, 0x00000010),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 3, 0x07000009),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 4, 0x0f000009),
+ INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 5, 0x0e000002),
INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X, 2, 0x0b000014),
INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 3, 0x00000021),
INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 4, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_MOBILE, 3, 0x0000007c),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_DESKTOP, 3, 0x0000007c),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP, 9, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE, 9, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE, 10, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE, 11, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE, 12, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP, 10, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP, 11, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP, 12, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP, 13, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_L, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 9, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 9, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 10, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 11, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 12, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 10, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 11, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 12, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 13, 0x0000004e),
{}
};
@@ -4053,7 +4075,7 @@ static bool check_msr(unsigned long msr, u64 mask)
* Disable the check for real HW, so we don't
* mess with potentionaly enabled registers:
*/
- if (hypervisor_is_type(X86_HYPER_NATIVE))
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
return true;
/*
@@ -4147,7 +4169,7 @@ static const struct x86_cpu_desc counter_freezing_ucodes[] = {
INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT, 2, 0x0000000e),
INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT, 9, 0x0000002e),
INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT, 10, 0x00000008),
- INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_X, 1, 0x00000028),
+ INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_D, 1, 0x00000028),
INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS, 1, 0x00000028),
INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS, 8, 0x00000006),
{}
@@ -4607,6 +4629,7 @@ __init int intel_pmu_init(void)
x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
x86_pmu.enable_all = intel_pmu_nhm_enable_all;
x86_pmu.extra_regs = intel_nehalem_extra_regs;
+ x86_pmu.limit_period = nhm_limit_period;
mem_attr = nhm_mem_events_attrs;
@@ -4644,7 +4667,7 @@ __init int intel_pmu_init(void)
break;
case INTEL_FAM6_ATOM_SILVERMONT:
- case INTEL_FAM6_ATOM_SILVERMONT_X:
+ case INTEL_FAM6_ATOM_SILVERMONT_D:
case INTEL_FAM6_ATOM_SILVERMONT_MID:
case INTEL_FAM6_ATOM_AIRMONT:
case INTEL_FAM6_ATOM_AIRMONT_MID:
@@ -4666,7 +4689,7 @@ __init int intel_pmu_init(void)
break;
case INTEL_FAM6_ATOM_GOLDMONT:
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
x86_add_quirk(intel_counter_freezing_quirk);
memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -4722,7 +4745,7 @@ __init int intel_pmu_init(void)
name = "goldmont_plus";
break;
- case INTEL_FAM6_ATOM_TREMONT_X:
+ case INTEL_FAM6_ATOM_TREMONT_D:
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -4858,10 +4881,10 @@ __init int intel_pmu_init(void)
break;
- case INTEL_FAM6_HASWELL_CORE:
+ case INTEL_FAM6_HASWELL:
case INTEL_FAM6_HASWELL_X:
- case INTEL_FAM6_HASWELL_ULT:
- case INTEL_FAM6_HASWELL_GT3E:
+ case INTEL_FAM6_HASWELL_L:
+ case INTEL_FAM6_HASWELL_G:
x86_add_quirk(intel_ht_bug);
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
@@ -4891,9 +4914,9 @@ __init int intel_pmu_init(void)
name = "haswell";
break;
- case INTEL_FAM6_BROADWELL_CORE:
- case INTEL_FAM6_BROADWELL_XEON_D:
- case INTEL_FAM6_BROADWELL_GT3E:
+ case INTEL_FAM6_BROADWELL:
+ case INTEL_FAM6_BROADWELL_D:
+ case INTEL_FAM6_BROADWELL_G:
case INTEL_FAM6_BROADWELL_X:
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
@@ -4955,10 +4978,11 @@ __init int intel_pmu_init(void)
case INTEL_FAM6_SKYLAKE_X:
pmem = true;
- case INTEL_FAM6_SKYLAKE_MOBILE:
- case INTEL_FAM6_SKYLAKE_DESKTOP:
- case INTEL_FAM6_KABYLAKE_MOBILE:
- case INTEL_FAM6_KABYLAKE_DESKTOP:
+ /* fall through */
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
@@ -5002,10 +5026,11 @@ __init int intel_pmu_init(void)
break;
case INTEL_FAM6_ICELAKE_X:
- case INTEL_FAM6_ICELAKE_XEON_D:
+ case INTEL_FAM6_ICELAKE_D:
pmem = true;
- case INTEL_FAM6_ICELAKE_MOBILE:
- case INTEL_FAM6_ICELAKE_DESKTOP:
+ /* fall through */
+ case INTEL_FAM6_ICELAKE_L:
+ case INTEL_FAM6_ICELAKE:
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
index 688592b34564..9f2f39003d96 100644
--- a/arch/x86/events/intel/cstate.c
+++ b/arch/x86/events/intel/cstate.c
@@ -446,7 +446,7 @@ static int cstate_cpu_init(unsigned int cpu)
return 0;
}
-const struct attribute_group *core_attr_update[] = {
+static const struct attribute_group *core_attr_update[] = {
&group_cstate_core_c1,
&group_cstate_core_c3,
&group_cstate_core_c6,
@@ -454,7 +454,7 @@ const struct attribute_group *core_attr_update[] = {
NULL,
};
-const struct attribute_group *pkg_attr_update[] = {
+static const struct attribute_group *pkg_attr_update[] = {
&group_cstate_pkg_c2,
&group_cstate_pkg_c3,
&group_cstate_pkg_c6,
@@ -593,40 +593,40 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
X86_CSTATES_MODEL(INTEL_FAM6_IVYBRIDGE, snb_cstates),
X86_CSTATES_MODEL(INTEL_FAM6_IVYBRIDGE_X, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_CORE, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_X, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_GT3E, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_HASWELL, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_X, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_G, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_ULT, hswult_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_L, hswult_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT, slm_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT_X, slm_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_AIRMONT, slm_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT, slm_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT_D, slm_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_AIRMONT, slm_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_CORE, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_XEON_D, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_GT3E, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_X, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_D, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_G, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_X, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_L, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE, snb_cstates),
X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_X, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_MOBILE, hswult_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_DESKTOP, hswult_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_L, hswult_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE, hswult_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_CANNONLAKE_MOBILE, cnl_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_CANNONLAKE_L, cnl_cstates),
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_X, glm_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_D, glm_cstates),
X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_PLUS, glm_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE_MOBILE, snb_cstates),
- X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE_DESKTOP, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE_L, snb_cstates),
+ X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE, snb_cstates),
{ },
};
MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 2c8db2c19328..ce83950036c5 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -851,7 +851,7 @@ struct event_constraint intel_skl_pebs_event_constraints[] = {
struct event_constraint intel_icl_pebs_event_constraints[] = {
INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */
- INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x400000000ULL), /* SLOTS */
+ INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), /* SLOTS */
INTEL_PLD_CONSTRAINT(0x1cd, 0xff), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x1d0, 0xf), /* MEM_INST_RETIRED.LOAD */
@@ -902,6 +902,9 @@ struct event_constraint *intel_pebs_constraints(struct perf_event *event)
*/
static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc)
{
+ if (cpuc->n_pebs == cpuc->n_pebs_via_pt)
+ return false;
+
return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs);
}
@@ -919,6 +922,9 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
u64 threshold;
int reserved;
+ if (cpuc->n_pebs_via_pt)
+ return;
+
if (x86_pmu.flags & PMU_FL_PEBS_ALL)
reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed;
else
@@ -1059,10 +1065,40 @@ void intel_pmu_pebs_add(struct perf_event *event)
cpuc->n_pebs++;
if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
cpuc->n_large_pebs++;
+ if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT)
+ cpuc->n_pebs_via_pt++;
pebs_update_state(needed_cb, cpuc, event, true);
}
+static void intel_pmu_pebs_via_pt_disable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+ if (!is_pebs_pt(event))
+ return;
+
+ if (!(cpuc->pebs_enabled & ~PEBS_VIA_PT_MASK))
+ cpuc->pebs_enabled &= ~PEBS_VIA_PT_MASK;
+}
+
+static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+ struct debug_store *ds = cpuc->ds;
+
+ if (!is_pebs_pt(event))
+ return;
+
+ if (!(event->hw.flags & PERF_X86_EVENT_LARGE_PEBS))
+ cpuc->pebs_enabled |= PEBS_PMI_AFTER_EACH_RECORD;
+
+ cpuc->pebs_enabled |= PEBS_OUTPUT_PT;
+
+ wrmsrl(MSR_RELOAD_PMC0 + hwc->idx, ds->pebs_event_reset[hwc->idx]);
+}
+
void intel_pmu_pebs_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1100,6 +1136,8 @@ void intel_pmu_pebs_enable(struct perf_event *event)
} else {
ds->pebs_event_reset[hwc->idx] = 0;
}
+
+ intel_pmu_pebs_via_pt_enable(event);
}
void intel_pmu_pebs_del(struct perf_event *event)
@@ -1111,6 +1149,8 @@ void intel_pmu_pebs_del(struct perf_event *event)
cpuc->n_pebs--;
if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
cpuc->n_large_pebs--;
+ if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT)
+ cpuc->n_pebs_via_pt--;
pebs_update_state(needed_cb, cpuc, event, false);
}
@@ -1120,7 +1160,8 @@ void intel_pmu_pebs_disable(struct perf_event *event)
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
- if (cpuc->n_pebs == cpuc->n_large_pebs)
+ if (cpuc->n_pebs == cpuc->n_large_pebs &&
+ cpuc->n_pebs != cpuc->n_pebs_via_pt)
intel_pmu_drain_pebs_buffer();
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
@@ -1131,6 +1172,8 @@ void intel_pmu_pebs_disable(struct perf_event *event)
else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
cpuc->pebs_enabled &= ~(1ULL << 63);
+ intel_pmu_pebs_via_pt_disable(event);
+
if (cpuc->enabled)
wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
@@ -2031,6 +2074,12 @@ void __init intel_ds_init(void)
PERF_SAMPLE_REGS_INTR);
}
pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual);
+
+ if (x86_pmu.intel_cap.pebs_output_pt_available) {
+ pr_cont("PEBS-via-PT, ");
+ x86_get_pmu()->capabilities |= PERF_PMU_CAP_AUX_OUTPUT;
+ }
+
break;
default:
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 6f814a27416b..ea54634eabf3 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -273,7 +273,7 @@ static inline bool lbr_from_signext_quirk_needed(void)
return !tsx_support && (lbr_desc[lbr_format] & LBR_TSX);
}
-DEFINE_STATIC_KEY_FALSE(lbr_from_quirk_key);
+static DEFINE_STATIC_KEY_FALSE(lbr_from_quirk_key);
/* If quirk is enabled, ensure sign extension is 63 bits: */
inline u64 lbr_from_signext_quirk_wr(u64 val)
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index d3dc2274ddd4..74e80ed9c6c4 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -204,9 +204,9 @@ static int __init pt_pmu_hw_init(void)
/* model-specific quirks */
switch (boot_cpu_data.x86_model) {
- case INTEL_FAM6_BROADWELL_CORE:
- case INTEL_FAM6_BROADWELL_XEON_D:
- case INTEL_FAM6_BROADWELL_GT3E:
+ case INTEL_FAM6_BROADWELL:
+ case INTEL_FAM6_BROADWELL_D:
+ case INTEL_FAM6_BROADWELL_G:
case INTEL_FAM6_BROADWELL_X:
/* not setting BRANCH_EN will #GP, erratum BDM106 */
pt_pmu.branch_en_always_on = true;
@@ -545,33 +545,62 @@ static void pt_config_buffer(void *buf, unsigned int topa_idx,
wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
}
-/*
- * Keep ToPA table-related metadata on the same page as the actual table,
- * taking up a few words from the top
- */
-
-#define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1)
-
/**
- * struct topa - page-sized ToPA table with metadata at the top
- * @table: actual ToPA table entries, as understood by PT hardware
+ * struct topa - ToPA metadata
* @list: linkage to struct pt_buffer's list of tables
- * @phys: physical address of this page
* @offset: offset of the first entry in this table in the buffer
* @size: total size of all entries in this table
* @last: index of the last initialized entry in this table
+ * @z_count: how many times the first entry repeats
*/
struct topa {
- struct topa_entry table[TENTS_PER_PAGE];
struct list_head list;
- u64 phys;
u64 offset;
size_t size;
int last;
+ unsigned int z_count;
};
+/*
+ * Keep ToPA table-related metadata on the same page as the actual table,
+ * taking up a few words from the top
+ */
+
+#define TENTS_PER_PAGE \
+ ((PAGE_SIZE - sizeof(struct topa)) / sizeof(struct topa_entry))
+
+/**
+ * struct topa_page - page-sized ToPA table with metadata at the top
+ * @table: actual ToPA table entries, as understood by PT hardware
+ * @topa: metadata
+ */
+struct topa_page {
+ struct topa_entry table[TENTS_PER_PAGE];
+ struct topa topa;
+};
+
+static inline struct topa_page *topa_to_page(struct topa *topa)
+{
+ return container_of(topa, struct topa_page, topa);
+}
+
+static inline struct topa_page *topa_entry_to_page(struct topa_entry *te)
+{
+ return (struct topa_page *)((unsigned long)te & PAGE_MASK);
+}
+
+static inline phys_addr_t topa_pfn(struct topa *topa)
+{
+ return PFN_DOWN(virt_to_phys(topa_to_page(topa)));
+}
+
/* make -1 stand for the last table entry */
-#define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)])
+#define TOPA_ENTRY(t, i) \
+ ((i) == -1 \
+ ? &topa_to_page(t)->table[(t)->last] \
+ : &topa_to_page(t)->table[(i)])
+#define TOPA_ENTRY_SIZE(t, i) (sizes(TOPA_ENTRY((t), (i))->size))
+#define TOPA_ENTRY_PAGES(t, i) (1 << TOPA_ENTRY((t), (i))->size)
/**
* topa_alloc() - allocate page-sized ToPA table
@@ -583,27 +612,26 @@ struct topa {
static struct topa *topa_alloc(int cpu, gfp_t gfp)
{
int node = cpu_to_node(cpu);
- struct topa *topa;
+ struct topa_page *tp;
struct page *p;
p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
if (!p)
return NULL;
- topa = page_address(p);
- topa->last = 0;
- topa->phys = page_to_phys(p);
+ tp = page_address(p);
+ tp->topa.last = 0;
/*
* In case of singe-entry ToPA, always put the self-referencing END
* link as the 2nd entry in the table
*/
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
- TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT;
- TOPA_ENTRY(topa, 1)->end = 1;
+ TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p);
+ TOPA_ENTRY(&tp->topa, 1)->end = 1;
}
- return topa;
+ return &tp->topa;
}
/**
@@ -643,7 +671,7 @@ static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
BUG_ON(last->last != TENTS_PER_PAGE - 1);
- TOPA_ENTRY(last, -1)->base = topa->phys >> TOPA_SHIFT;
+ TOPA_ENTRY(last, -1)->base = topa_pfn(topa);
TOPA_ENTRY(last, -1)->end = 1;
}
@@ -670,7 +698,7 @@ static bool topa_table_full(struct topa *topa)
*
* Return: 0 on success or error code.
*/
-static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
+static int topa_insert_pages(struct pt_buffer *buf, int cpu, gfp_t gfp)
{
struct topa *topa = buf->last;
int order = 0;
@@ -681,13 +709,18 @@ static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
order = page_private(p);
if (topa_table_full(topa)) {
- topa = topa_alloc(buf->cpu, gfp);
+ topa = topa_alloc(cpu, gfp);
if (!topa)
return -ENOMEM;
topa_insert_table(buf, topa);
}
+ if (topa->z_count == topa->last - 1) {
+ if (order == TOPA_ENTRY(topa, topa->last - 1)->size)
+ topa->z_count++;
+ }
+
TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
TOPA_ENTRY(topa, -1)->size = order;
if (!buf->snapshot &&
@@ -713,23 +746,26 @@ static void pt_topa_dump(struct pt_buffer *buf)
struct topa *topa;
list_for_each_entry(topa, &buf->tables, list) {
+ struct topa_page *tp = topa_to_page(topa);
int i;
- pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table,
- topa->phys, topa->offset, topa->size);
+ pr_debug("# table @%p, off %llx size %zx\n", tp->table,
+ topa->offset, topa->size);
for (i = 0; i < TENTS_PER_PAGE; i++) {
pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
- &topa->table[i],
- (unsigned long)topa->table[i].base << TOPA_SHIFT,
- sizes(topa->table[i].size),
- topa->table[i].end ? 'E' : ' ',
- topa->table[i].intr ? 'I' : ' ',
- topa->table[i].stop ? 'S' : ' ',
- *(u64 *)&topa->table[i]);
+ &tp->table[i],
+ (unsigned long)tp->table[i].base << TOPA_SHIFT,
+ sizes(tp->table[i].size),
+ tp->table[i].end ? 'E' : ' ',
+ tp->table[i].intr ? 'I' : ' ',
+ tp->table[i].stop ? 'S' : ' ',
+ *(u64 *)&tp->table[i]);
if ((intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) &&
- topa->table[i].stop) ||
- topa->table[i].end)
+ tp->table[i].stop) ||
+ tp->table[i].end)
break;
+ if (!i && topa->z_count)
+ i += topa->z_count;
}
}
}
@@ -771,7 +807,7 @@ static void pt_update_head(struct pt *pt)
/* offset of the current output region within this table */
for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++)
- base += sizes(buf->cur->table[topa_idx].size);
+ base += TOPA_ENTRY_SIZE(buf->cur, topa_idx);
if (buf->snapshot) {
local_set(&buf->data_size, base);
@@ -791,7 +827,7 @@ static void pt_update_head(struct pt *pt)
*/
static void *pt_buffer_region(struct pt_buffer *buf)
{
- return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT);
+ return phys_to_virt(TOPA_ENTRY(buf->cur, buf->cur_idx)->base << TOPA_SHIFT);
}
/**
@@ -800,7 +836,7 @@ static void *pt_buffer_region(struct pt_buffer *buf)
*/
static size_t pt_buffer_region_size(struct pt_buffer *buf)
{
- return sizes(buf->cur->table[buf->cur_idx].size);
+ return TOPA_ENTRY_SIZE(buf->cur, buf->cur_idx);
}
/**
@@ -830,7 +866,7 @@ static void pt_handle_status(struct pt *pt)
* know.
*/
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) ||
- buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
+ buf->output_off == pt_buffer_region_size(buf)) {
perf_aux_output_flag(&pt->handle,
PERF_AUX_FLAG_TRUNCATED);
advance++;
@@ -868,9 +904,11 @@ static void pt_handle_status(struct pt *pt)
static void pt_read_offset(struct pt_buffer *buf)
{
u64 offset, base_topa;
+ struct topa_page *tp;
rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa);
- buf->cur = phys_to_virt(base_topa);
+ tp = phys_to_virt(base_topa);
+ buf->cur = &tp->topa;
rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
/* offset within current output region */
@@ -879,29 +917,97 @@ static void pt_read_offset(struct pt_buffer *buf)
buf->cur_idx = (offset & 0xffffff80) >> 7;
}
-/**
- * pt_topa_next_entry() - obtain index of the first page in the next ToPA entry
- * @buf: PT buffer.
- * @pg: Page offset in the buffer.
- *
- * When advancing to the next output region (ToPA entry), given a page offset
- * into the buffer, we need to find the offset of the first page in the next
- * region.
- */
-static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg)
+static struct topa_entry *
+pt_topa_entry_for_page(struct pt_buffer *buf, unsigned int pg)
{
- struct topa_entry *te = buf->topa_index[pg];
+ struct topa_page *tp;
+ struct topa *topa;
+ unsigned int idx, cur_pg = 0, z_pg = 0, start_idx = 0;
- /* one region */
- if (buf->first == buf->last && buf->first->last == 1)
- return pg;
+ /*
+ * Indicates a bug in the caller.
+ */
+ if (WARN_ON_ONCE(pg >= buf->nr_pages))
+ return NULL;
+
+ /*
+ * First, find the ToPA table where @pg fits. With high
+ * order allocations, there shouldn't be many of these.
+ */
+ list_for_each_entry(topa, &buf->tables, list) {
+ if (topa->offset + topa->size > pg << PAGE_SHIFT)
+ goto found;
+ }
+
+ /*
+ * Hitting this means we have a problem in the ToPA
+ * allocation code.
+ */
+ WARN_ON_ONCE(1);
- do {
- pg++;
- pg &= buf->nr_pages - 1;
- } while (buf->topa_index[pg] == te);
+ return NULL;
- return pg;
+found:
+ /*
+ * Indicates a problem in the ToPA allocation code.
+ */
+ if (WARN_ON_ONCE(topa->last == -1))
+ return NULL;
+
+ tp = topa_to_page(topa);
+ cur_pg = PFN_DOWN(topa->offset);
+ if (topa->z_count) {
+ z_pg = TOPA_ENTRY_PAGES(topa, 0) * (topa->z_count + 1);
+ start_idx = topa->z_count + 1;
+ }
+
+ /*
+ * Multiple entries at the beginning of the table have the same size,
+ * ideally all of them; if @pg falls there, the search is done.
+ */
+ if (pg >= cur_pg && pg < cur_pg + z_pg) {
+ idx = (pg - cur_pg) / TOPA_ENTRY_PAGES(topa, 0);
+ return &tp->table[idx];
+ }
+
+ /*
+ * Otherwise, slow path: iterate through the remaining entries.
+ */
+ for (idx = start_idx, cur_pg += z_pg; idx < topa->last; idx++) {
+ if (cur_pg + TOPA_ENTRY_PAGES(topa, idx) > pg)
+ return &tp->table[idx];
+
+ cur_pg += TOPA_ENTRY_PAGES(topa, idx);
+ }
+
+ /*
+ * Means we couldn't find a ToPA entry in the table that does match.
+ */
+ WARN_ON_ONCE(1);
+
+ return NULL;
+}
+
+static struct topa_entry *
+pt_topa_prev_entry(struct pt_buffer *buf, struct topa_entry *te)
+{
+ unsigned long table = (unsigned long)te & ~(PAGE_SIZE - 1);
+ struct topa_page *tp;
+ struct topa *topa;
+
+ tp = (struct topa_page *)table;
+ if (tp->table != te)
+ return --te;
+
+ topa = &tp->topa;
+ if (topa == buf->first)
+ topa = buf->last;
+ else
+ topa = list_prev_entry(topa, list);
+
+ tp = topa_to_page(topa);
+
+ return &tp->table[topa->last - 1];
}
/**
@@ -925,8 +1031,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
unsigned long idx, npages, wakeup;
/* can't stop in the middle of an output region */
- if (buf->output_off + handle->size + 1 <
- sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
+ if (buf->output_off + handle->size + 1 < pt_buffer_region_size(buf)) {
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
return -EINVAL;
}
@@ -937,9 +1042,13 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
return 0;
/* clear STOP and INT from current entry */
- buf->topa_index[buf->stop_pos]->stop = 0;
- buf->topa_index[buf->stop_pos]->intr = 0;
- buf->topa_index[buf->intr_pos]->intr = 0;
+ if (buf->stop_te) {
+ buf->stop_te->stop = 0;
+ buf->stop_te->intr = 0;
+ }
+
+ if (buf->intr_te)
+ buf->intr_te->intr = 0;
/* how many pages till the STOP marker */
npages = handle->size >> PAGE_SHIFT;
@@ -950,7 +1059,12 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
idx = (head >> PAGE_SHIFT) + npages;
idx &= buf->nr_pages - 1;
- buf->stop_pos = idx;
+
+ if (idx != buf->stop_pos) {
+ buf->stop_pos = idx;
+ buf->stop_te = pt_topa_entry_for_page(buf, idx);
+ buf->stop_te = pt_topa_prev_entry(buf, buf->stop_te);
+ }
wakeup = handle->wakeup >> PAGE_SHIFT;
@@ -960,51 +1074,20 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
idx = wakeup;
idx &= buf->nr_pages - 1;
- buf->intr_pos = idx;
+ if (idx != buf->intr_pos) {
+ buf->intr_pos = idx;
+ buf->intr_te = pt_topa_entry_for_page(buf, idx);
+ buf->intr_te = pt_topa_prev_entry(buf, buf->intr_te);
+ }
- buf->topa_index[buf->stop_pos]->stop = 1;
- buf->topa_index[buf->stop_pos]->intr = 1;
- buf->topa_index[buf->intr_pos]->intr = 1;
+ buf->stop_te->stop = 1;
+ buf->stop_te->intr = 1;
+ buf->intr_te->intr = 1;
return 0;
}
/**
- * pt_buffer_setup_topa_index() - build topa_index[] table of regions
- * @buf: PT buffer.
- *
- * topa_index[] references output regions indexed by offset into the
- * buffer for purposes of quick reverse lookup.
- */
-static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
-{
- struct topa *cur = buf->first, *prev = buf->last;
- struct topa_entry *te_cur = TOPA_ENTRY(cur, 0),
- *te_prev = TOPA_ENTRY(prev, prev->last - 1);
- int pg = 0, idx = 0;
-
- while (pg < buf->nr_pages) {
- int tidx;
-
- /* pages within one topa entry */
- for (tidx = 0; tidx < 1 << te_cur->size; tidx++, pg++)
- buf->topa_index[pg] = te_prev;
-
- te_prev = te_cur;
-
- if (idx == cur->last - 1) {
- /* advance to next topa table */
- idx = 0;
- cur = list_entry(cur->list.next, struct topa, list);
- } else {
- idx++;
- }
- te_cur = TOPA_ENTRY(cur, idx);
- }
-
-}
-
-/**
* pt_buffer_reset_offsets() - adjust buffer's write pointers from aux_head
* @buf: PT buffer.
* @head: Write pointer (aux_head) from AUX buffer.
@@ -1021,18 +1104,20 @@ static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
*/
static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
{
+ struct topa_page *cur_tp;
+ struct topa_entry *te;
int pg;
if (buf->snapshot)
head &= (buf->nr_pages << PAGE_SHIFT) - 1;
pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
- pg = pt_topa_next_entry(buf, pg);
+ te = pt_topa_entry_for_page(buf, pg);
- buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK);
- buf->cur_idx = ((unsigned long)buf->topa_index[pg] -
- (unsigned long)buf->cur) / sizeof(struct topa_entry);
- buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1);
+ cur_tp = topa_entry_to_page(te);
+ buf->cur = &cur_tp->topa;
+ buf->cur_idx = te - TOPA_ENTRY(buf->cur, 0);
+ buf->output_off = head & (pt_buffer_region_size(buf) - 1);
local64_set(&buf->head, head);
local_set(&buf->data_size, 0);
@@ -1061,31 +1146,29 @@ static void pt_buffer_fini_topa(struct pt_buffer *buf)
* @size: Total size of all regions within this ToPA.
* @gfp: Allocation flags.
*/
-static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
- gfp_t gfp)
+static int pt_buffer_init_topa(struct pt_buffer *buf, int cpu,
+ unsigned long nr_pages, gfp_t gfp)
{
struct topa *topa;
int err;
- topa = topa_alloc(buf->cpu, gfp);
+ topa = topa_alloc(cpu, gfp);
if (!topa)
return -ENOMEM;
topa_insert_table(buf, topa);
while (buf->nr_pages < nr_pages) {
- err = topa_insert_pages(buf, gfp);
+ err = topa_insert_pages(buf, cpu, gfp);
if (err) {
pt_buffer_fini_topa(buf);
return -ENOMEM;
}
}
- pt_buffer_setup_topa_index(buf);
-
/* link last table to the first one, unless we're double buffering */
if (intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
- TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT;
+ TOPA_ENTRY(buf->last, -1)->base = topa_pfn(buf->first);
TOPA_ENTRY(buf->last, -1)->end = 1;
}
@@ -1119,18 +1202,18 @@ pt_buffer_setup_aux(struct perf_event *event, void **pages,
cpu = raw_smp_processor_id();
node = cpu_to_node(cpu);
- buf = kzalloc_node(offsetof(struct pt_buffer, topa_index[nr_pages]),
- GFP_KERNEL, node);
+ buf = kzalloc_node(sizeof(struct pt_buffer), GFP_KERNEL, node);
if (!buf)
return NULL;
- buf->cpu = cpu;
buf->snapshot = snapshot;
buf->data_pages = pages;
+ buf->stop_pos = -1;
+ buf->intr_pos = -1;
INIT_LIST_HEAD(&buf->tables);
- ret = pt_buffer_init_topa(buf, nr_pages, GFP_KERNEL);
+ ret = pt_buffer_init_topa(buf, cpu, nr_pages, GFP_KERNEL);
if (ret) {
kfree(buf);
return NULL;
@@ -1296,7 +1379,7 @@ void intel_pt_interrupt(void)
return;
}
- pt_config_buffer(buf->cur->table, buf->cur_idx,
+ pt_config_buffer(topa_to_page(buf->cur)->table, buf->cur_idx,
buf->output_off);
pt_config(event);
}
@@ -1361,7 +1444,7 @@ static void pt_event_start(struct perf_event *event, int mode)
WRITE_ONCE(pt->handle_nmi, 1);
hwc->state = 0;
- pt_config_buffer(buf->cur->table, buf->cur_idx,
+ pt_config_buffer(topa_to_page(buf->cur)->table, buf->cur_idx,
buf->output_off);
pt_config(event);
@@ -1481,6 +1564,11 @@ void cpu_emergency_stop_pt(void)
pt_event_stop(pt->handle.event, PERF_EF_UPDATE);
}
+int is_intel_pt_event(struct perf_event *event)
+{
+ return event->pmu == &pt_pmu.pmu;
+}
+
static __init int pt_init(void)
{
int ret, cpu, prior_warn = 0;
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
index 63fe4063fbd6..1d2bb7572374 100644
--- a/arch/x86/events/intel/pt.h
+++ b/arch/x86/events/intel/pt.h
@@ -53,7 +53,6 @@ struct pt_pmu {
/**
* struct pt_buffer - buffer configuration; one buffer per task_struct or
* cpu, depending on perf event configuration
- * @cpu: cpu for per-cpu allocation
* @tables: list of ToPA tables in this buffer
* @first: shorthand for first topa table
* @last: shorthand for last topa table
@@ -65,13 +64,14 @@ struct pt_pmu {
* @lost: if data was lost/truncated
* @head: logical write offset inside the buffer
* @snapshot: if this is for a snapshot/overwrite counter
- * @stop_pos: STOP topa entry in the buffer
- * @intr_pos: INT topa entry in the buffer
+ * @stop_pos: STOP topa entry index
+ * @intr_pos: INT topa entry index
+ * @stop_te: STOP topa entry pointer
+ * @intr_te: INT topa entry pointer
* @data_pages: array of pages from perf
* @topa_index: table of topa entries indexed by page offset
*/
struct pt_buffer {
- int cpu;
struct list_head tables;
struct topa *first, *last, *cur;
unsigned int cur_idx;
@@ -80,9 +80,9 @@ struct pt_buffer {
local_t data_size;
local64_t head;
bool snapshot;
- unsigned long stop_pos, intr_pos;
+ long stop_pos, intr_pos;
+ struct topa_entry *stop_te, *intr_te;
void **data_pages;
- struct topa_entry *topa_index[0];
};
#define PT_FILTERS_NUM 4
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index 64ab51ffdf06..5053a403e4ae 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -634,7 +634,7 @@ static void cleanup_rapl_pmus(void)
kfree(rapl_pmus);
}
-const struct attribute_group *rapl_attr_update[] = {
+static const struct attribute_group *rapl_attr_update[] = {
&rapl_events_cores_group,
&rapl_events_pkg_group,
&rapl_events_ram_group,
@@ -720,27 +720,27 @@ static const struct x86_cpu_id rapl_model_match[] __initconst = {
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SANDYBRIDGE_X, model_snbep),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE, model_snb),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE_X, model_snbep),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_CORE, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL, model_hsw),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_X, model_hsx),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_ULT, model_hsw),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_GT3E, model_hsw),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, model_hsw),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_L, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_G, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_G, model_hsw),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, model_hsx),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, model_hsx),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_D, model_hsx),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, model_knl),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, model_knl),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, model_skl),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_L, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE, model_skl),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, model_hsx),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_MOBILE, model_skl),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_DESKTOP, model_skl),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_CANNONLAKE_MOBILE, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_L, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_CANNONLAKE_L, model_skl),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, model_hsw),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_X, model_hsw),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_D, model_hsw),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_PLUS, model_hsw),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE_MOBILE, model_skl),
- X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE_DESKTOP, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE_L, model_skl),
+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE, model_skl),
{},
};
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 3694a5d0703d..6fc2e06ab4c6 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1451,29 +1451,29 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_WESTMERE_EP, nhm_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SANDYBRIDGE, snb_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE, ivb_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_CORE, hsw_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_ULT, hsw_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_GT3E, hsw_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, bdw_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, bdw_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL, hsw_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_L, hsw_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_G, hsw_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL, bdw_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_G, bdw_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SANDYBRIDGE_X, snbep_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_NEHALEM_EX, nhmex_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_WESTMERE_EX, nhmex_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE_X, ivbep_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_HASWELL_X, hswep_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, bdx_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, bdx_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_D, bdx_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, knl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE, skl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_L, skl_uncore_init),
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, skx_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE_MOBILE, skl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE_DESKTOP, skl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE_MOBILE, icl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE_NNPI, icl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE_DESKTOP, icl_uncore_init),
- X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ATOM_TREMONT_X, snr_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE_L, skl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE, skl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE_L, icl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE_NNPI, icl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ICELAKE, icl_uncore_init),
+ X86_UNCORE_MODEL_MATCH(INTEL_FAM6_ATOM_TREMONT_D, snr_uncore_init),
{},
};
diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
index 9431447541e9..b1afc77f0704 100644
--- a/arch/x86/events/msr.c
+++ b/arch/x86/events/msr.c
@@ -59,22 +59,22 @@ static bool test_intel(int idx, void *data)
case INTEL_FAM6_IVYBRIDGE:
case INTEL_FAM6_IVYBRIDGE_X:
- case INTEL_FAM6_HASWELL_CORE:
+ case INTEL_FAM6_HASWELL:
case INTEL_FAM6_HASWELL_X:
- case INTEL_FAM6_HASWELL_ULT:
- case INTEL_FAM6_HASWELL_GT3E:
+ case INTEL_FAM6_HASWELL_L:
+ case INTEL_FAM6_HASWELL_G:
- case INTEL_FAM6_BROADWELL_CORE:
- case INTEL_FAM6_BROADWELL_XEON_D:
- case INTEL_FAM6_BROADWELL_GT3E:
+ case INTEL_FAM6_BROADWELL:
+ case INTEL_FAM6_BROADWELL_D:
+ case INTEL_FAM6_BROADWELL_G:
case INTEL_FAM6_BROADWELL_X:
case INTEL_FAM6_ATOM_SILVERMONT:
- case INTEL_FAM6_ATOM_SILVERMONT_X:
+ case INTEL_FAM6_ATOM_SILVERMONT_D:
case INTEL_FAM6_ATOM_AIRMONT:
case INTEL_FAM6_ATOM_GOLDMONT:
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
@@ -84,12 +84,12 @@ static bool test_intel(int idx, void *data)
return true;
break;
- case INTEL_FAM6_SKYLAKE_MOBILE:
- case INTEL_FAM6_SKYLAKE_DESKTOP:
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
case INTEL_FAM6_SKYLAKE_X:
- case INTEL_FAM6_KABYLAKE_MOBILE:
- case INTEL_FAM6_KABYLAKE_DESKTOP:
- case INTEL_FAM6_ICELAKE_MOBILE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
+ case INTEL_FAM6_ICELAKE_L:
if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
return true;
break;
@@ -167,7 +167,7 @@ static const struct attribute_group *attr_groups[] = {
NULL,
};
-const struct attribute_group *attr_update[] = {
+static const struct attribute_group *attr_update[] = {
&group_aperf,
&group_mperf,
&group_pperf,
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 8751008fc170..ecacfbf4ebc1 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -76,6 +76,7 @@ static inline bool constraint_match(struct event_constraint *c, u64 ecode)
#define PERF_X86_EVENT_EXCL_ACCT 0x0100 /* accounted EXCL event */
#define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */
#define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */
+#define PERF_X86_EVENT_PEBS_VIA_PT 0x0800 /* use PT buffer for PEBS */
struct amd_nb {
int nb_id; /* NorthBridge id */
@@ -85,6 +86,11 @@ struct amd_nb {
};
#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1)
+#define PEBS_PMI_AFTER_EACH_RECORD BIT_ULL(60)
+#define PEBS_OUTPUT_OFFSET 61
+#define PEBS_OUTPUT_MASK (3ull << PEBS_OUTPUT_OFFSET)
+#define PEBS_OUTPUT_PT (1ull << PEBS_OUTPUT_OFFSET)
+#define PEBS_VIA_PT_MASK (PEBS_OUTPUT_PT | PEBS_PMI_AFTER_EACH_RECORD)
/*
* Flags PEBS can handle without an PMI.
@@ -211,6 +217,8 @@ struct cpu_hw_events {
u64 pebs_enabled;
int n_pebs;
int n_large_pebs;
+ int n_pebs_via_pt;
+ int pebs_output;
/* Current super set of events hardware configuration */
u64 pebs_data_cfg;
@@ -510,6 +518,8 @@ union perf_capabilities {
*/
u64 full_width_write:1;
u64 pebs_baseline:1;
+ u64 pebs_metrics_available:1;
+ u64 pebs_output_pt_available:1;
};
u64 capabilities;
};
@@ -692,6 +702,8 @@ struct x86_pmu {
* Check period value for PERF_EVENT_IOC_PERIOD ioctl.
*/
int (*check_period) (struct perf_event *event, u64 period);
+
+ int (*aux_output_match) (struct perf_event *event);
};
struct x86_perf_task_context {
@@ -901,6 +913,11 @@ static inline int amd_pmu_init(void)
#endif /* CONFIG_CPU_SUP_AMD */
+static inline int is_pebs_pt(struct perf_event *event)
+{
+ return !!(event->hw.flags & PERF_X86_EVENT_PEBS_VIA_PT);
+}
+
#ifdef CONFIG_CPU_SUP_INTEL
static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 866dfb3dca48..2db3972c0e0f 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -37,6 +37,20 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
u32 hv_max_vp_index;
EXPORT_SYMBOL_GPL(hv_max_vp_index);
+void *hv_alloc_hyperv_page(void)
+{
+ BUILD_BUG_ON(PAGE_SIZE != HV_HYP_PAGE_SIZE);
+
+ return (void *)__get_free_page(GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page);
+
+void hv_free_hyperv_page(unsigned long addr)
+{
+ free_page(addr);
+}
+EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
+
static int hv_cpu_init(unsigned int cpu)
{
u64 msr_vp_index;
diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
index e65d7fe6489f..5208ba49c89a 100644
--- a/arch/x86/hyperv/mmu.c
+++ b/arch/x86/hyperv/mmu.c
@@ -37,12 +37,14 @@ static inline int fill_gva_list(u64 gva_list[], int offset,
* Lower 12 bits encode the number of additional
* pages to flush (in addition to the 'cur' page).
*/
- if (diff >= HV_TLB_FLUSH_UNIT)
+ if (diff >= HV_TLB_FLUSH_UNIT) {
gva_list[gva_n] |= ~PAGE_MASK;
- else if (diff)
+ cur += HV_TLB_FLUSH_UNIT;
+ } else if (diff) {
gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT;
+ cur = end;
+ }
- cur += HV_TLB_FLUSH_UNIT;
gva_n++;
} while (cur < end);
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index e647aa095867..2ebc17d9c72c 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -136,6 +136,7 @@ extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void disconnect_bsp_APIC(int virt_wire_setup);
extern void disable_local_APIC(void);
+extern void apic_soft_disable(void);
extern void lapic_shutdown(void);
extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
@@ -176,6 +177,8 @@ extern void lapic_online(void);
extern void lapic_offline(void);
extern bool apic_needs_pit(void);
+extern void apic_send_IPI_allbutself(unsigned int vector);
+
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
@@ -465,12 +468,6 @@ static inline unsigned default_get_apic_id(unsigned long x)
#define TRAMPOLINE_PHYS_LOW 0x467
#define TRAMPOLINE_PHYS_HIGH 0x469
-#ifdef CONFIG_X86_64
-extern void apic_send_IPI_self(int vector);
-
-DECLARE_PER_CPU(int, x2apic_extra_bits);
-#endif
-
extern void generic_bigsmp_probe(void);
#ifdef CONFIG_X86_LOCAL_APIC
@@ -506,8 +503,10 @@ extern int default_check_phys_apicid_present(int phys_apicid);
#ifdef CONFIG_SMP
bool apic_id_is_primary_thread(unsigned int id);
+void apic_smt_update(void);
#else
static inline bool apic_id_is_primary_thread(unsigned int id) { return false; }
+static inline void apic_smt_update(void) { }
#endif
extern void irq_enter(void);
diff --git a/arch/x86/include/asm/apic_flat_64.h b/arch/x86/include/asm/apic_flat_64.h
deleted file mode 100644
index d3a2b3876ce6..000000000000
--- a/arch/x86/include/asm/apic_flat_64.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_APIC_FLAT_64_H
-#define _ASM_X86_APIC_FLAT_64_H
-
-extern void flat_init_apic_ldr(void);
-
-#endif
-
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 84f848c2541a..7f828fe49797 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -49,8 +49,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
#define array_index_mask_nospec array_index_mask_nospec
/* Prevent speculative execution past this barrier. */
-#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \
- "lfence", X86_FEATURE_LFENCE_RDTSC)
+#define barrier_nospec() alternative("", "lfence", X86_FEATURE_LFENCE_RDTSC)
#define dma_rmb() barrier()
#define dma_wmb() barrier()
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index ba15d53c1ca7..7d1f6a49bfae 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -45,14 +45,13 @@
* We do the locked ops that don't return the old value as
* a mask operation on a byte.
*/
-#define IS_IMMEDIATE(nr) (__builtin_constant_p(nr))
#define CONST_MASK_ADDR(nr, addr) WBYTE_ADDR((void *)(addr) + ((nr)>>3))
#define CONST_MASK(nr) (1 << ((nr) & 7))
static __always_inline void
arch_set_bit(long nr, volatile unsigned long *addr)
{
- if (IS_IMMEDIATE(nr)) {
+ if (__builtin_constant_p(nr)) {
asm volatile(LOCK_PREFIX "orb %1,%0"
: CONST_MASK_ADDR(nr, addr)
: "iq" ((u8)CONST_MASK(nr))
@@ -72,7 +71,7 @@ arch___set_bit(long nr, volatile unsigned long *addr)
static __always_inline void
arch_clear_bit(long nr, volatile unsigned long *addr)
{
- if (IS_IMMEDIATE(nr)) {
+ if (__builtin_constant_p(nr)) {
asm volatile(LOCK_PREFIX "andb %1,%0"
: CONST_MASK_ADDR(nr, addr)
: "iq" ((u8)~CONST_MASK(nr)));
@@ -123,7 +122,7 @@ arch___change_bit(long nr, volatile unsigned long *addr)
static __always_inline void
arch_change_bit(long nr, volatile unsigned long *addr)
{
- if (IS_IMMEDIATE(nr)) {
+ if (__builtin_constant_p(nr)) {
asm volatile(LOCK_PREFIX "xorb %1,%0"
: CONST_MASK_ADDR(nr, addr)
: "iq" ((u8)CONST_MASK(nr)));
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
index 101eb944f13c..981fe923a59f 100644
--- a/arch/x86/include/asm/bootparam_utils.h
+++ b/arch/x86/include/asm/bootparam_utils.h
@@ -18,6 +18,20 @@
* Note: efi_info is commonly left uninitialized, but that field has a
* private magic, so it is better to leave it unchanged.
*/
+
+#define sizeof_mbr(type, member) ({ sizeof(((type *)0)->member); })
+
+#define BOOT_PARAM_PRESERVE(struct_member) \
+ { \
+ .start = offsetof(struct boot_params, struct_member), \
+ .len = sizeof_mbr(struct boot_params, struct_member), \
+ }
+
+struct boot_params_to_save {
+ unsigned int start;
+ unsigned int len;
+};
+
static void sanitize_boot_params(struct boot_params *boot_params)
{
/*
@@ -35,21 +49,41 @@ static void sanitize_boot_params(struct boot_params *boot_params)
* problems again.
*/
if (boot_params->sentinel) {
- /* fields in boot_params are left uninitialized, clear them */
- boot_params->acpi_rsdp_addr = 0;
- memset(&boot_params->ext_ramdisk_image, 0,
- (char *)&boot_params->efi_info -
- (char *)&boot_params->ext_ramdisk_image);
- memset(&boot_params->kbd_status, 0,
- (char *)&boot_params->hdr -
- (char *)&boot_params->kbd_status);
- memset(&boot_params->_pad7[0], 0,
- (char *)&boot_params->edd_mbr_sig_buffer[0] -
- (char *)&boot_params->_pad7[0]);
- memset(&boot_params->_pad8[0], 0,
- (char *)&boot_params->eddbuf[0] -
- (char *)&boot_params->_pad8[0]);
- memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+ static struct boot_params scratch;
+ char *bp_base = (char *)boot_params;
+ char *save_base = (char *)&scratch;
+ int i;
+
+ const struct boot_params_to_save to_save[] = {
+ BOOT_PARAM_PRESERVE(screen_info),
+ BOOT_PARAM_PRESERVE(apm_bios_info),
+ BOOT_PARAM_PRESERVE(tboot_addr),
+ BOOT_PARAM_PRESERVE(ist_info),
+ BOOT_PARAM_PRESERVE(hd0_info),
+ BOOT_PARAM_PRESERVE(hd1_info),
+ BOOT_PARAM_PRESERVE(sys_desc_table),
+ BOOT_PARAM_PRESERVE(olpc_ofw_header),
+ BOOT_PARAM_PRESERVE(efi_info),
+ BOOT_PARAM_PRESERVE(alt_mem_k),
+ BOOT_PARAM_PRESERVE(scratch),
+ BOOT_PARAM_PRESERVE(e820_entries),
+ BOOT_PARAM_PRESERVE(eddbuf_entries),
+ BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
+ BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+ BOOT_PARAM_PRESERVE(secure_boot),
+ BOOT_PARAM_PRESERVE(hdr),
+ BOOT_PARAM_PRESERVE(e820_table),
+ BOOT_PARAM_PRESERVE(eddbuf),
+ };
+
+ memset(&scratch, 0, sizeof(scratch));
+
+ for (i = 0; i < ARRAY_SIZE(to_save); i++) {
+ memcpy(save_base + to_save[i].start,
+ bp_base + to_save[i].start, to_save[i].len);
+ }
+
+ memcpy(boot_params, save_base, sizeof(*boot_params));
}
}
diff --git a/arch/x86/include/asm/bugs.h b/arch/x86/include/asm/bugs.h
index 542509b53e0f..794eb2129bc6 100644
--- a/arch/x86/include/asm/bugs.h
+++ b/arch/x86/include/asm/bugs.h
@@ -18,4 +18,6 @@ int ppro_with_ram_bug(void);
static inline int ppro_with_ram_bug(void) { return 0; }
#endif
+extern void cpu_bugs_smt_update(void);
+
#endif /* _ASM_X86_BUGS_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 58acda503817..59bf91c57aa8 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -61,6 +61,13 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define CHECK_BIT_IN_MASK_WORD(maskname, word, bit) \
(((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word ))
+/*
+ * {REQUIRED,DISABLED}_MASK_CHECK below may seem duplicated with the
+ * following BUILD_BUG_ON_ZERO() check but when NCAPINTS gets changed, all
+ * header macros which use NCAPINTS need to be changed. The duplicated macro
+ * use causes the compiler to issue errors for all headers so that all usage
+ * sites can be corrected.
+ */
#define REQUIRED_MASK_BIT_SET(feature_bit) \
( CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 0, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 1, feature_bit) || \
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 998c2cc08363..0652d3eed9bd 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -96,7 +96,6 @@
#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */
#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */
#define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */
-#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" MFENCE synchronizes RDTSC */
#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" LFENCE synchronizes RDTSC */
#define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */
#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */
@@ -232,6 +231,8 @@
#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */
#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
+#define X86_FEATURE_VMCALL ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */
+#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
@@ -281,6 +282,8 @@
#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */
#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
+#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
+#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
@@ -353,6 +356,7 @@
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
+#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
@@ -394,5 +398,6 @@
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
+#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/include/asm/div64.h b/arch/x86/include/asm/div64.h
index 20a46150e0a8..9b8cb50768c2 100644
--- a/arch/x86/include/asm/div64.h
+++ b/arch/x86/include/asm/div64.h
@@ -73,6 +73,19 @@ static inline u64 mul_u32_u32(u32 a, u32 b)
#else
# include <asm-generic/div64.h>
+
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 div)
+{
+ u64 q;
+
+ asm ("mulq %2; divq %3" : "=a" (q)
+ : "a" (a), "rm" ((u64)mul), "rm" ((u64)div)
+ : "rdx");
+
+ return q;
+}
+#define mul_u64_u32_div mul_u64_u32_div
+
#endif /* CONFIG_X86_32 */
#endif /* _ASM_X86_DIV64_H */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 606a4b6a9812..43a82e59c59d 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -242,6 +242,7 @@ static inline bool efi_is_64bit(void)
__efi_early()->runtime_services), __VA_ARGS__)
extern bool efi_reboot_required(void);
+extern bool efi_is_table_address(unsigned long phys_addr);
#else
static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
@@ -249,6 +250,10 @@ static inline bool efi_reboot_required(void)
{
return false;
}
+static inline bool efi_is_table_address(unsigned long phys_addr)
+{
+ return false;
+}
#endif /* CONFIG_EFI */
#endif /* _ASM_X86_EFI_H */
diff --git a/arch/x86/include/asm/error-injection.h b/arch/x86/include/asm/error-injection.h
deleted file mode 100644
index 47b7a1296245..000000000000
--- a/arch/x86/include/asm/error-injection.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_ERROR_INJECTION_H
-#define _ASM_ERROR_INJECTION_H
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-#include <asm-generic/error-injection.h>
-
-asmlinkage void just_return_func(void);
-void override_function_with_return(struct pt_regs *regs);
-
-#endif /* _ASM_ERROR_INJECTION_H */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 9da8cccdf3fb..0c47aa82e2e2 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -42,8 +42,7 @@
* Because of this, FIXADDR_TOP x86 integration was left as later work.
*/
#ifdef CONFIG_X86_32
-/* used by vmalloc.c, vsyscall.lds.S.
- *
+/*
* Leave one empty page between vmalloc'ed areas and
* the start of the fixmap.
*/
@@ -120,7 +119,7 @@ enum fixed_addresses {
* before ioremap() is functional.
*
* If necessary we round it up to the next 512 pages boundary so
- * that we can have a single pgd entry and a single pte table:
+ * that we can have a single pmd entry and a single pte table:
*/
#define NR_FIX_BTMAPS 64
#define FIX_BTMAPS_SLOTS 8
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 287f1f7b2e52..c38a66661576 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -16,7 +16,6 @@
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
#ifndef __ASSEMBLY__
-extern void mcount(void);
extern atomic_t modifying_ftrace_code;
extern void __fentry__(void);
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index cbd97e22d2f3..4154bc5f6a4e 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -153,8 +153,8 @@ extern char irq_entries_start[];
extern char spurious_entries_start[];
#define VECTOR_UNUSED NULL
-#define VECTOR_SHUTDOWN ((void *)~0UL)
-#define VECTOR_RETRIGGERED ((void *)~1UL)
+#define VECTOR_SHUTDOWN ((void *)-1L)
+#define VECTOR_RETRIGGERED ((void *)-2L)
typedef struct irq_desc* vector_irq_t[NR_VECTORS];
DECLARE_PER_CPU(vector_irq_t, vector_irq);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index af78cd72b8f3..7a2705694f5b 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -13,6 +13,16 @@
#include <asm/page.h>
/*
+ * While not explicitly listed in the TLFS, Hyper-V always runs with a page size
+ * of 4096. These definitions are used when communicating with Hyper-V using
+ * guest physical pages and guest physical page addresses, since the guest page
+ * size may not be 4096 on all architectures.
+ */
+#define HV_HYP_PAGE_SHIFT 12
+#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT)
+#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1))
+
+/*
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
* is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
*/
@@ -847,7 +857,7 @@ union hv_gpa_page_range {
* count is equal with how many entries of union hv_gpa_page_range can
* be populated into the input parameter page.
*/
-#define HV_MAX_FLUSH_REP_COUNT ((PAGE_SIZE - 2 * sizeof(u64)) / \
+#define HV_MAX_FLUSH_REP_COUNT ((HV_HYP_PAGE_SIZE - 2 * sizeof(u64)) / \
sizeof(union hv_gpa_page_range))
struct hv_guest_mapping_flush_list {
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
index 0278aa66ef62..f04622500da3 100644
--- a/arch/x86/include/asm/intel-family.h
+++ b/arch/x86/include/asm/intel-family.h
@@ -5,12 +5,34 @@
/*
* "Big Core" Processors (Branded as Core, Xeon, etc...)
*
- * The "_X" parts are generally the EP and EX Xeons, or the
- * "Extreme" ones, like Broadwell-E, or Atom microserver.
- *
* While adding a new CPUID for a new microarchitecture, add a new
* group to keep logically sorted out in chronological order. Within
* that group keep the CPUID for the variants sorted by model number.
+ *
+ * The defined symbol names have the following form:
+ * INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF}
+ * where:
+ * OPTFAMILY Describes the family of CPUs that this belongs to. Default
+ * is assumed to be "_CORE" (and should be omitted). Other values
+ * currently in use are _ATOM and _XEON_PHI
+ * MICROARCH Is the code name for the micro-architecture for this core.
+ * N.B. Not the platform name.
+ * OPTDIFF If needed, a short string to differentiate by market segment.
+ *
+ * Common OPTDIFFs:
+ *
+ * - regular client parts
+ * _L - regular mobile parts
+ * _G - parts with extra graphics on
+ * _X - regular server parts
+ * _D - micro server parts
+ *
+ * Historical OPTDIFFs:
+ *
+ * _EP - 2 socket server parts
+ * _EX - 4+ socket server parts
+ *
+ * The #define line may optionally include a comment including platform names.
*/
#define INTEL_FAM6_CORE_YONAH 0x0E
@@ -34,30 +56,33 @@
#define INTEL_FAM6_IVYBRIDGE 0x3A
#define INTEL_FAM6_IVYBRIDGE_X 0x3E
-#define INTEL_FAM6_HASWELL_CORE 0x3C
+#define INTEL_FAM6_HASWELL 0x3C
#define INTEL_FAM6_HASWELL_X 0x3F
-#define INTEL_FAM6_HASWELL_ULT 0x45
-#define INTEL_FAM6_HASWELL_GT3E 0x46
+#define INTEL_FAM6_HASWELL_L 0x45
+#define INTEL_FAM6_HASWELL_G 0x46
-#define INTEL_FAM6_BROADWELL_CORE 0x3D
-#define INTEL_FAM6_BROADWELL_GT3E 0x47
+#define INTEL_FAM6_BROADWELL 0x3D
+#define INTEL_FAM6_BROADWELL_G 0x47
#define INTEL_FAM6_BROADWELL_X 0x4F
-#define INTEL_FAM6_BROADWELL_XEON_D 0x56
+#define INTEL_FAM6_BROADWELL_D 0x56
-#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E
-#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E
+#define INTEL_FAM6_SKYLAKE_L 0x4E
+#define INTEL_FAM6_SKYLAKE 0x5E
#define INTEL_FAM6_SKYLAKE_X 0x55
-#define INTEL_FAM6_KABYLAKE_MOBILE 0x8E
-#define INTEL_FAM6_KABYLAKE_DESKTOP 0x9E
+#define INTEL_FAM6_KABYLAKE_L 0x8E
+#define INTEL_FAM6_KABYLAKE 0x9E
-#define INTEL_FAM6_CANNONLAKE_MOBILE 0x66
+#define INTEL_FAM6_CANNONLAKE_L 0x66
#define INTEL_FAM6_ICELAKE_X 0x6A
-#define INTEL_FAM6_ICELAKE_XEON_D 0x6C
-#define INTEL_FAM6_ICELAKE_DESKTOP 0x7D
-#define INTEL_FAM6_ICELAKE_MOBILE 0x7E
+#define INTEL_FAM6_ICELAKE_D 0x6C
+#define INTEL_FAM6_ICELAKE 0x7D
+#define INTEL_FAM6_ICELAKE_L 0x7E
#define INTEL_FAM6_ICELAKE_NNPI 0x9D
+#define INTEL_FAM6_TIGERLAKE_L 0x8C
+#define INTEL_FAM6_TIGERLAKE 0x8D
+
/* "Small Core" Processors (Atom) */
#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */
@@ -68,17 +93,21 @@
#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */
#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */
-#define INTEL_FAM6_ATOM_SILVERMONT_X 0x4D /* Avaton, Rangely */
+#define INTEL_FAM6_ATOM_SILVERMONT_D 0x4D /* Avaton, Rangely */
#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */
#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */
+#define INTEL_FAM6_ATOM_AIRMONT_NP 0x75 /* Lightning Mountain */
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */
-#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */
+#define INTEL_FAM6_ATOM_GOLDMONT_D 0x5F /* Denverton */
+
+/* Note: the micro-architecture is "Goldmont Plus" */
#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */
-#define INTEL_FAM6_ATOM_TREMONT_X 0x86 /* Jacobsville */
+#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */
+#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */
/* Xeon Phi */
diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h
index 634f99b1dc22..423b788f495e 100644
--- a/arch/x86/include/asm/intel_pt.h
+++ b/arch/x86/include/asm/intel_pt.h
@@ -28,10 +28,12 @@ enum pt_capabilities {
void cpu_emergency_stop_pt(void);
extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap);
extern u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities cap);
+extern int is_intel_pt_event(struct perf_event *event);
#else
static inline void cpu_emergency_stop_pt(void) {}
static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; }
static inline u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities capability) { return 0; }
+static inline int is_intel_pt_event(struct perf_event *event) { return 0; }
#endif
#endif /* _ASM_X86_INTEL_PT_H */
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index baedab8ac538..b91623d521d9 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -4,7 +4,6 @@
extern int force_iommu, no_iommu;
extern int iommu_detected;
-extern int iommu_pass_through;
/* 10 seconds */
#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h
deleted file mode 100644
index f73076be546a..000000000000
--- a/arch/x86/include/asm/ipi.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef _ASM_X86_IPI_H
-#define _ASM_X86_IPI_H
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-/*
- * Copyright 2004 James Cleverdon, IBM.
- *
- * Generic APIC InterProcessor Interrupt code.
- *
- * Moved to include file by James Cleverdon from
- * arch/x86-64/kernel/smp.c
- *
- * Copyrights from kernel/smp.c:
- *
- * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
- * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
- * (c) 2002,2003 Andi Kleen, SuSE Labs.
- */
-
-#include <asm/hw_irq.h>
-#include <asm/apic.h>
-#include <asm/smp.h>
-
-/*
- * the following functions deal with sending IPIs between CPUs.
- *
- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
- */
-
-static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
- unsigned int dest)
-{
- unsigned int icr = shortcut | dest;
-
- switch (vector) {
- default:
- icr |= APIC_DM_FIXED | vector;
- break;
- case NMI_VECTOR:
- icr |= APIC_DM_NMI;
- break;
- }
- return icr;
-}
-
-static inline int __prepare_ICR2(unsigned int mask)
-{
- return SET_APIC_DEST_FIELD(mask);
-}
-
-static inline void __xapic_wait_icr_idle(void)
-{
- while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
- cpu_relax();
-}
-
-void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest);
-
-/*
- * This is used to send an IPI with no shorthand notation (the destination is
- * specified in bits 56 to 63 of the ICR).
- */
-void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest);
-
-extern void default_send_IPI_single(int cpu, int vector);
-extern void default_send_IPI_single_phys(int cpu, int vector);
-extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask,
- int vector);
-extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
- int vector);
-
-/* Avoid include hell */
-#define NMI_VECTOR 0x02
-
-extern int no_broadcast;
-
-static inline void __default_local_send_IPI_allbutself(int vector)
-{
- if (no_broadcast || vector == NMI_VECTOR)
- apic->send_IPI_mask_allbutself(cpu_online_mask, vector);
- else
- __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->dest_logical);
-}
-
-static inline void __default_local_send_IPI_all(int vector)
-{
- if (no_broadcast || vector == NMI_VECTOR)
- apic->send_IPI_mask(cpu_online_mask, vector);
- else
- __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical);
-}
-
-#ifdef CONFIG_X86_32
-extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
- int vector);
-extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
- int vector);
-extern void default_send_IPI_mask_logical(const struct cpumask *mask,
- int vector);
-extern void default_send_IPI_allbutself(int vector);
-extern void default_send_IPI_all(int vector);
-extern void default_send_IPI_self(int vector);
-#endif
-
-#endif
-
-#endif /* _ASM_X86_IPI_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 8f95686ec27e..a176f6165d85 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -34,7 +34,7 @@ extern __visible void smp_kvm_posted_intr_nested_ipi(struct pt_regs *regs);
extern void (*x86_platform_ipi_callback)(void);
extern void native_init_IRQ(void);
-extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs);
+extern void handle_irq(struct irq_desc *desc, struct pt_regs *regs);
extern __visible unsigned int do_IRQ(struct pt_regs *regs);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 8282b8d41209..bdc16b0aa7c6 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -35,6 +35,8 @@
#include <asm/kvm_vcpu_regs.h>
#include <asm/hyperv-tlfs.h>
+#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+
#define KVM_MAX_VCPUS 288
#define KVM_SOFT_MAX_VCPUS 240
#define KVM_MAX_VCPU_ID 1023
@@ -333,6 +335,7 @@ struct kvm_mmu_page {
int root_count; /* Currently serving as active root */
unsigned int unsync_children;
struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
+ unsigned long mmu_valid_gen;
DECLARE_BITMAP(unsync_child_bitmap, 512);
#ifdef CONFIG_X86_32
@@ -607,15 +610,16 @@ struct kvm_vcpu_arch {
/*
* QEMU userspace and the guest each have their own FPU state.
- * In vcpu_run, we switch between the user, maintained in the
- * task_struct struct, and guest FPU contexts. While running a VCPU,
- * the VCPU thread will have the guest FPU context.
+ * In vcpu_run, we switch between the user and guest FPU contexts.
+ * While running a VCPU, the VCPU thread will have the guest FPU
+ * context.
*
* Note that while the PKRU state lives inside the fpu registers,
* it is switched out separately at VMENTER and VMEXIT time. The
* "guest_fpu" state here contains the guest FPU context, with the
* host PRKU bits.
*/
+ struct fpu *user_fpu;
struct fpu *guest_fpu;
u64 xcr0;
@@ -853,6 +857,7 @@ struct kvm_arch {
unsigned long n_requested_mmu_pages;
unsigned long n_max_mmu_pages;
unsigned int indirect_shadow_pages;
+ unsigned long mmu_valid_gen;
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
/*
* Hash table of struct kvm_mmu_page.
@@ -1174,6 +1179,7 @@ struct kvm_x86_ops {
int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
uint32_t guest_irq, bool set);
void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
+ bool (*dy_apicv_has_pending_interrupt)(struct kvm_vcpu *vcpu);
int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
bool *expired);
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 9024236693d2..16ae821483c8 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -28,16 +28,16 @@ static inline void paravirt_activate_mm(struct mm_struct *prev,
DECLARE_STATIC_KEY_FALSE(rdpmc_always_available_key);
-static inline void load_mm_cr4(struct mm_struct *mm)
+static inline void load_mm_cr4_irqsoff(struct mm_struct *mm)
{
if (static_branch_unlikely(&rdpmc_always_available_key) ||
atomic_read(&mm->context.perf_rdpmc_allowed))
- cr4_set_bits(X86_CR4_PCE);
+ cr4_set_bits_irqsoff(X86_CR4_PCE);
else
- cr4_clear_bits(X86_CR4_PCE);
+ cr4_clear_bits_irqsoff(X86_CR4_PCE);
}
#else
-static inline void load_mm_cr4(struct mm_struct *mm) {}
+static inline void load_mm_cr4_irqsoff(struct mm_struct *mm) {}
#endif
#ifdef CONFIG_MODIFY_LDT_SYSCALL
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 2ef31cc8c529..f4138aeb4280 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -218,7 +218,8 @@ static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
void __init hyperv_init(void);
void hyperv_setup_mmu_ops(void);
-
+void *hv_alloc_hyperv_page(void);
+void hv_free_hyperv_page(unsigned long addr);
void hyperv_reenlightenment_intr(struct pt_regs *regs);
void set_hv_tscchange_cb(void (*cb)(void));
void clear_hv_tscchange_cb(void);
@@ -241,6 +242,8 @@ static inline void hv_apic_init(void) {}
#else /* CONFIG_HYPERV */
static inline void hyperv_init(void) {}
static inline void hyperv_setup_mmu_ops(void) {}
+static inline void *hv_alloc_hyperv_page(void) { return NULL; }
+static inline void hv_free_hyperv_page(unsigned long addr) {}
static inline void set_hv_tscchange_cb(void (*cb)(void)) {}
static inline void clear_hv_tscchange_cb(void) {}
static inline void hyperv_stop_tsc_emulation(void) {};
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 6b4fc2788078..20ce682a2540 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -375,13 +375,22 @@
/* Alternative perfctr range with full access. */
#define MSR_IA32_PMC0 0x000004c1
-/* AMD64 MSRs. Not complete. See the architecture manual for a more
- complete list. */
+/* Auto-reload via MSR instead of DS area */
+#define MSR_RELOAD_PMC0 0x000014c1
+#define MSR_RELOAD_FIXED_CTR0 0x00001309
+/*
+ * AMD64 MSRs. Not complete. See the architecture manual for a more
+ * complete list.
+ */
#define MSR_AMD64_PATCH_LEVEL 0x0000008b
#define MSR_AMD64_TSC_RATIO 0xc0000104
#define MSR_AMD64_NB_CFG 0xc001001f
+#define MSR_AMD64_CPUID_FN_1 0xc0011004
#define MSR_AMD64_PATCH_LOADER 0xc0010020
+#define MSR_AMD_PERF_CTL 0xc0010062
+#define MSR_AMD_PERF_STATUS 0xc0010063
+#define MSR_AMD_PSTATE_DEF_BASE 0xc0010064
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
#define MSR_AMD64_OSVW_STATUS 0xc0010141
#define MSR_AMD64_LS_CFG 0xc0011020
@@ -560,9 +569,6 @@
#define MSR_IA32_PERF_STATUS 0x00000198
#define MSR_IA32_PERF_CTL 0x00000199
#define INTEL_PERF_CTL_MASK 0xffff
-#define MSR_AMD_PSTATE_DEF_BASE 0xc0010064
-#define MSR_AMD_PERF_STATUS 0xc0010063
-#define MSR_AMD_PERF_CTL 0xc0010062
#define MSR_IA32_MPERF 0x000000e7
#define MSR_IA32_APERF 0x000000e8
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 5cc3930cb465..86f20d520a07 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -233,8 +233,7 @@ static __always_inline unsigned long long rdtsc_ordered(void)
* Thus, use the preferred barrier on the respective CPU, aiming for
* RDTSCP as the default.
*/
- asm volatile(ALTERNATIVE_3("rdtsc",
- "mfence; rdtsc", X86_FEATURE_MFENCE_RDTSC,
+ asm volatile(ALTERNATIVE_2("rdtsc",
"lfence; rdtsc", X86_FEATURE_LFENCE_RDTSC,
"rdtscp", X86_FEATURE_RDTSCP)
: EAX_EDX_RET(val, low, high)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 109f974f9835..80bc209c0708 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -192,7 +192,7 @@
" lfence;\n" \
" jmp 902b;\n" \
" .align 16\n" \
- "903: addl $4, %%esp;\n" \
+ "903: lea 4(%%esp), %%esp;\n" \
" pushl %[thunk_target];\n" \
" ret;\n" \
" .align 16\n" \
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index dce26f1d13e1..69089d46f128 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -139,18 +139,6 @@ static inline void __write_cr4(unsigned long x)
PVOP_VCALL1(cpu.write_cr4, x);
}
-#ifdef CONFIG_X86_64
-static inline unsigned long read_cr8(void)
-{
- return PVOP_CALL0(unsigned long, cpu.read_cr8);
-}
-
-static inline void write_cr8(unsigned long x)
-{
- PVOP_VCALL1(cpu.write_cr8, x);
-}
-#endif
-
static inline void arch_safe_halt(void)
{
PVOP_VCALL0(irq.safe_halt);
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 639b2df445ee..70b654f3ffe5 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -119,11 +119,6 @@ struct pv_cpu_ops {
void (*write_cr4)(unsigned long);
-#ifdef CONFIG_X86_64
- unsigned long (*read_cr8)(void);
- void (*write_cr8)(unsigned long);
-#endif
-
/* Segment descriptor handling */
void (*load_tr_desc)(void);
void (*load_gdt)(const struct desc_ptr *);
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 1392d5e6e8d6..ee26e9215f18 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -252,16 +252,20 @@ struct pebs_lbr {
#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
#define IBSCTL_LVT_OFFSET_MASK 0x0F
-/* ibs fetch bits/masks */
+/* IBS fetch bits/masks */
#define IBS_FETCH_RAND_EN (1ULL<<57)
#define IBS_FETCH_VAL (1ULL<<49)
#define IBS_FETCH_ENABLE (1ULL<<48)
#define IBS_FETCH_CNT 0xFFFF0000ULL
#define IBS_FETCH_MAX_CNT 0x0000FFFFULL
-/* ibs op bits/masks */
-/* lower 4 bits of the current count are ignored: */
-#define IBS_OP_CUR_CNT (0xFFFF0ULL<<32)
+/*
+ * IBS op bits/masks
+ * The lower 7 bits of the current count are random bits
+ * preloaded by hardware and ignored in software
+ */
+#define IBS_OP_CUR_CNT (0xFFF80ULL<<32)
+#define IBS_OP_CUR_CNT_RAND (0x0007FULL<<32)
#define IBS_OP_CNT_CTL (1ULL<<19)
#define IBS_OP_VAL (1ULL<<18)
#define IBS_OP_ENABLE (1ULL<<17)
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index 99a7fa9ab0a3..3d4cb83a8828 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -102,7 +102,7 @@ static __always_inline bool should_resched(int preempt_offset)
return unlikely(raw_cpu_read_4(__preempt_count) == preempt_offset);
}
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
extern asmlinkage void ___preempt_schedule(void);
# define __preempt_schedule() \
asm volatile ("call ___preempt_schedule" : ASM_CALL_CONSTRAINT)
diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h
index bd5ac6cc37db..444d6fd9a6d8 100644
--- a/arch/x86/include/asm/qspinlock.h
+++ b/arch/x86/include/asm/qspinlock.h
@@ -63,10 +63,25 @@ static inline bool vcpu_is_preempted(long cpu)
#endif
#ifdef CONFIG_PARAVIRT
+/*
+ * virt_spin_lock_key - enables (by default) the virt_spin_lock() hijack.
+ *
+ * Native (and PV wanting native due to vCPU pinning) should disable this key.
+ * It is done in this backwards fashion to only have a single direction change,
+ * which removes ordering between native_pv_spin_init() and HV setup.
+ */
DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key);
void native_pv_lock_init(void) __init;
+/*
+ * Shortcut for the queued_spin_lock_slowpath() function that allows
+ * virt to hijack it.
+ *
+ * Returns:
+ * true - lock has been negotiated, all done;
+ * false - queued_spin_lock_slowpath() will do its thing.
+ */
#define virt_spin_lock virt_spin_lock
static inline bool virt_spin_lock(struct qspinlock *lock)
{
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index c53682303c9c..09ecc32f6524 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -20,7 +20,6 @@ struct real_mode_header {
u32 ro_end;
/* SMP trampoline */
u32 trampoline_start;
- u32 trampoline_status;
u32 trampoline_header;
#ifdef CONFIG_X86_64
u32 trampoline_pgd;
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index ae7b909dc242..2ee8e469dcf5 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -40,7 +40,6 @@ int _set_memory_wt(unsigned long addr, int numpages);
int _set_memory_wb(unsigned long addr, int numpages);
int set_memory_uc(unsigned long addr, int numpages);
int set_memory_wc(unsigned long addr, int numpages);
-int set_memory_wt(unsigned long addr, int numpages);
int set_memory_wb(unsigned long addr, int numpages);
int set_memory_np(unsigned long addr, int numpages);
int set_memory_4k(unsigned long addr, int numpages);
@@ -48,11 +47,6 @@ int set_memory_encrypted(unsigned long addr, int numpages);
int set_memory_decrypted(unsigned long addr, int numpages);
int set_memory_np_noalias(unsigned long addr, int numpages);
-int set_memory_array_uc(unsigned long *addr, int addrinarray);
-int set_memory_array_wc(unsigned long *addr, int addrinarray);
-int set_memory_array_wt(unsigned long *addr, int addrinarray);
-int set_memory_array_wb(unsigned long *addr, int addrinarray);
-
int set_pages_array_uc(struct page **pages, int addrinarray);
int set_pages_array_wc(struct page **pages, int addrinarray);
int set_pages_array_wt(struct page **pages, int addrinarray);
@@ -80,8 +74,6 @@ int set_pages_array_wb(struct page **pages, int addrinarray);
int set_pages_uc(struct page *page, int numpages);
int set_pages_wb(struct page *page, int numpages);
-int set_pages_x(struct page *page, int numpages);
-int set_pages_nx(struct page *page, int numpages);
int set_pages_ro(struct page *page, int numpages);
int set_pages_rw(struct page *page, int numpages);
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index e1356a3b8223..e15f364efbcc 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -143,6 +143,7 @@ void play_dead_common(void);
void wbinvd_on_cpu(int cpu);
int wbinvd_on_all_cpus(void);
+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);
void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 219be88a59d2..6d37b8fcfc77 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -73,20 +73,6 @@ static inline unsigned long native_read_cr4(void)
void native_write_cr4(unsigned long val);
-#ifdef CONFIG_X86_64
-static inline unsigned long native_read_cr8(void)
-{
- unsigned long cr8;
- asm volatile("movq %%cr8,%0" : "=r" (cr8));
- return cr8;
-}
-
-static inline void native_write_cr8(unsigned long val)
-{
- asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
-}
-#endif
-
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
static inline u32 rdpkru(void)
{
@@ -200,16 +186,6 @@ static inline void wbinvd(void)
#ifdef CONFIG_X86_64
-static inline unsigned long read_cr8(void)
-{
- return native_read_cr8();
-}
-
-static inline void write_cr8(unsigned long x)
-{
- native_write_cr8(x);
-}
-
static inline void load_gs_index(unsigned selector)
{
native_load_gs_index(selector);
diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h
index a7af9f53c0cb..35bb35d28733 100644
--- a/arch/x86/include/asm/suspend_64.h
+++ b/arch/x86/include/asm/suspend_64.h
@@ -34,7 +34,7 @@ struct saved_context {
*/
unsigned long kernelmode_gs_base, usermode_gs_base, fs_base;
- unsigned long cr0, cr2, cr3, cr4, cr8;
+ unsigned long cr0, cr2, cr3, cr4;
u64 misc_enable;
bool misc_enable_saved;
struct saved_msrs saved_msrs;
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index 2dc4a021beea..8db3fdb6102e 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -36,6 +36,10 @@ extern const sys_call_ptr_t sys_call_table[];
extern const sys_call_ptr_t ia32_sys_call_table[];
#endif
+#ifdef CONFIG_X86_X32_ABI
+extern const sys_call_ptr_t x32_sys_call_table[];
+#endif
+
/*
* Only the low 32 bits of orig_ax are meaningful, so we return int.
* This importantly ignores the high bits on 64-bit, so comparisons
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index 70c09967a999..5e8319bb207a 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -45,8 +45,8 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len);
* no thread can be preempted in the instructions being modified (no iret to an
* invalid instruction possible) or if the instructions are changed from a
* consistent state to another consistent state atomically.
- * On the local CPU you need to be protected again NMI or MCE handlers seeing an
- * inconsistent instruction while you patch.
+ * On the local CPU you need to be protected against NMI or MCE handlers seeing
+ * an inconsistent instruction while you patch.
*/
extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index dee375831962..6f66d841262d 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -290,26 +290,42 @@ static inline void __cr4_set(unsigned long cr4)
}
/* Set in this cpu's CR4. */
-static inline void cr4_set_bits(unsigned long mask)
+static inline void cr4_set_bits_irqsoff(unsigned long mask)
{
- unsigned long cr4, flags;
+ unsigned long cr4;
- local_irq_save(flags);
cr4 = this_cpu_read(cpu_tlbstate.cr4);
if ((cr4 | mask) != cr4)
__cr4_set(cr4 | mask);
- local_irq_restore(flags);
}
/* Clear in this cpu's CR4. */
-static inline void cr4_clear_bits(unsigned long mask)
+static inline void cr4_clear_bits_irqsoff(unsigned long mask)
{
- unsigned long cr4, flags;
+ unsigned long cr4;
- local_irq_save(flags);
cr4 = this_cpu_read(cpu_tlbstate.cr4);
if ((cr4 & ~mask) != cr4)
__cr4_set(cr4 & ~mask);
+}
+
+/* Set in this cpu's CR4. */
+static inline void cr4_set_bits(unsigned long mask)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cr4_set_bits_irqsoff(mask);
+ local_irq_restore(flags);
+}
+
+/* Clear in this cpu's CR4. */
+static inline void cr4_clear_bits(unsigned long mask)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cr4_clear_bits_irqsoff(mask);
local_irq_restore(flags);
}
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 9c4435307ff8..35c225ede0e4 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -444,8 +444,10 @@ __pu_label: \
({ \
int __gu_err; \
__inttype(*(ptr)) __gu_val; \
+ __typeof__(ptr) __gu_ptr = (ptr); \
+ __typeof__(size) __gu_size = (size); \
__uaccess_begin_nospec(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
+ __get_user_size(__gu_val, __gu_ptr, __gu_size, __gu_err, -EFAULT); \
__uaccess_end(); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \
__builtin_expect(__gu_err, 0); \
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 097589753fec..a7dd080749ce 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -5,12 +5,6 @@
#include <uapi/asm/unistd.h>
-# ifdef CONFIG_X86_X32_ABI
-# define __SYSCALL_MASK (~(__X32_SYSCALL_BIT))
-# else
-# define __SYSCALL_MASK (~0)
-# endif
-
# ifdef CONFIG_X86_32
# include <asm/unistd_32.h>
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h
index e60c45fd3679..6bc6d89d8e2a 100644
--- a/arch/x86/include/asm/uv/uv.h
+++ b/arch/x86/include/asm/uv/uv.h
@@ -12,10 +12,12 @@ struct mm_struct;
#ifdef CONFIG_X86_UV
#include <linux/efi.h>
+extern unsigned long uv_systab_phys;
+
extern enum uv_system_type get_uv_system_type(void);
static inline bool is_early_uv_system(void)
{
- return !((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab);
+ return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR;
}
extern int is_uv_system(void);
extern int is_uv_hubless(void);
diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index bcbf901befbe..e9ee139cf29e 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,8 @@ long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
#else
+#define VDSO_HAS_32BIT_FALLBACK 1
+
static __always_inline
long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
@@ -114,6 +116,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
}
static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+ long ret;
+
+ asm (
+ "mov %%ebx, %%edx \n"
+ "mov %[clock], %%ebx \n"
+ "call __kernel_vsyscall \n"
+ "mov %%edx, %%ebx \n"
+ : "=a" (ret), "=m" (*_ts)
+ : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
+ : "edx");
+
+ return ret;
+}
+
+static __always_inline
long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
struct timezone *_tz)
{
@@ -148,6 +167,23 @@ clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
return ret;
}
+static __always_inline
+long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+ long ret;
+
+ asm (
+ "mov %%ebx, %%edx \n"
+ "mov %[clock], %%ebx \n"
+ "call __kernel_vsyscall \n"
+ "mov %%edx, %%ebx \n"
+ : "=a" (ret), "=m" (*_ts)
+ : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
+ : "edx");
+
+ return ret;
+}
+
#endif
#ifdef CONFIG_PARAVIRT_CLOCK
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
new file mode 100644
index 000000000000..e00c9e875933
--- /dev/null
+++ b/arch/x86/include/asm/vmware.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+#ifndef _ASM_X86_VMWARE_H
+#define _ASM_X86_VMWARE_H
+
+#include <asm/cpufeatures.h>
+#include <asm/alternative.h>
+
+/*
+ * The hypercall definitions differ in the low word of the %edx argument
+ * in the following way: the old port base interface uses the port
+ * number to distinguish between high- and low bandwidth versions.
+ *
+ * The new vmcall interface instead uses a set of flags to select
+ * bandwidth mode and transfer direction. The flags should be loaded
+ * into %dx by any user and are automatically replaced by the port
+ * number if the VMWARE_HYPERVISOR_PORT method is used.
+ *
+ * In short, new driver code should strictly use the new definition of
+ * %dx content.
+ */
+
+/* Old port-based version */
+#define VMWARE_HYPERVISOR_PORT "0x5658"
+#define VMWARE_HYPERVISOR_PORT_HB "0x5659"
+
+/* Current vmcall / vmmcall version */
+#define VMWARE_HYPERVISOR_HB BIT(0)
+#define VMWARE_HYPERVISOR_OUT BIT(1)
+
+/* The low bandwidth call. The low word of edx is presumed clear. */
+#define VMWARE_HYPERCALL \
+ ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT ", %%dx; inl (%%dx)", \
+ "vmcall", X86_FEATURE_VMCALL, \
+ "vmmcall", X86_FEATURE_VMW_VMMCALL)
+
+/*
+ * The high bandwidth out call. The low word of edx is presumed to have the
+ * HB and OUT bits set.
+ */
+#define VMWARE_HYPERCALL_HB_OUT \
+ ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep outsb", \
+ "vmcall", X86_FEATURE_VMCALL, \
+ "vmmcall", X86_FEATURE_VMW_VMMCALL)
+
+/*
+ * The high bandwidth in call. The low word of edx is presumed to have the
+ * HB bit set.
+ */
+#define VMWARE_HYPERCALL_HB_IN \
+ ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep insb", \
+ "vmcall", X86_FEATURE_VMCALL, \
+ "vmmcall", X86_FEATURE_VMW_VMMCALL)
+#endif
diff --git a/arch/x86/include/uapi/asm/byteorder.h b/arch/x86/include/uapi/asm/byteorder.h
index 484e3cfd7ef2..149143cab9ff 100644
--- a/arch/x86/include/uapi/asm/byteorder.h
+++ b/arch/x86/include/uapi/asm/byteorder.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_X86_BYTEORDER_H
#define _ASM_X86_BYTEORDER_H
diff --git a/arch/x86/include/uapi/asm/errno.h b/arch/x86/include/uapi/asm/errno.h
deleted file mode 100644
index 4c82b503d92f..000000000000
--- a/arch/x86/include/uapi/asm/errno.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/x86/include/uapi/asm/fcntl.h b/arch/x86/include/uapi/asm/fcntl.h
deleted file mode 100644
index 46ab12db5739..000000000000
--- a/arch/x86/include/uapi/asm/fcntl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/x86/include/uapi/asm/hwcap2.h b/arch/x86/include/uapi/asm/hwcap2.h
index 6ebaae90e207..8b2effe6efb8 100644
--- a/arch/x86/include/uapi/asm/hwcap2.h
+++ b/arch/x86/include/uapi/asm/hwcap2.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_X86_HWCAP2_H
#define _ASM_X86_HWCAP2_H
diff --git a/arch/x86/include/uapi/asm/ioctl.h b/arch/x86/include/uapi/asm/ioctl.h
deleted file mode 100644
index b279fe06dfe5..000000000000
--- a/arch/x86/include/uapi/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/x86/include/uapi/asm/ioctls.h b/arch/x86/include/uapi/asm/ioctls.h
deleted file mode 100644
index ec34c760665e..000000000000
--- a/arch/x86/include/uapi/asm/ioctls.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctls.h>
diff --git a/arch/x86/include/uapi/asm/ipcbuf.h b/arch/x86/include/uapi/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51cb6d0..000000000000
--- a/arch/x86/include/uapi/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/x86/include/uapi/asm/param.h b/arch/x86/include/uapi/asm/param.h
deleted file mode 100644
index 965d45427975..000000000000
--- a/arch/x86/include/uapi/asm/param.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/x86/include/uapi/asm/resource.h b/arch/x86/include/uapi/asm/resource.h
deleted file mode 100644
index 04bc4db8921b..000000000000
--- a/arch/x86/include/uapi/asm/resource.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/x86/include/uapi/asm/sigcontext32.h b/arch/x86/include/uapi/asm/sigcontext32.h
index 6b18e88de8a6..7114801d0499 100644
--- a/arch/x86/include/uapi/asm/sigcontext32.h
+++ b/arch/x86/include/uapi/asm/sigcontext32.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_X86_SIGCONTEXT32_H
#define _ASM_X86_SIGCONTEXT32_H
diff --git a/arch/x86/include/uapi/asm/termbits.h b/arch/x86/include/uapi/asm/termbits.h
deleted file mode 100644
index 3935b106de79..000000000000
--- a/arch/x86/include/uapi/asm/termbits.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/x86/include/uapi/asm/termios.h b/arch/x86/include/uapi/asm/termios.h
deleted file mode 100644
index 280d78a9d966..000000000000
--- a/arch/x86/include/uapi/asm/termios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/x86/include/uapi/asm/types.h b/arch/x86/include/uapi/asm/types.h
deleted file mode 100644
index df55e1ddb0c9..000000000000
--- a/arch/x86/include/uapi/asm/types.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_TYPES_H
-#define _ASM_X86_TYPES_H
-
-#include <asm-generic/types.h>
-
-#endif /* _ASM_X86_TYPES_H */
diff --git a/arch/x86/include/uapi/asm/unistd.h b/arch/x86/include/uapi/asm/unistd.h
index 30d7d04d72d6..196fdd02b8b1 100644
--- a/arch/x86/include/uapi/asm/unistd.h
+++ b/arch/x86/include/uapi/asm/unistd.h
@@ -3,7 +3,7 @@
#define _UAPI_ASM_X86_UNISTD_H
/* x32 syscall flag bit */
-#define __X32_SYSCALL_BIT 0x40000000
+#define __X32_SYSCALL_BIT 0x40000000UL
#ifndef __KERNEL__
# ifdef __i386__
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index b0715c3ac18d..7f9ade13bbcf 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -18,8 +18,13 @@ ENTRY(wakeup_long64)
movq saved_magic, %rax
movq $0x123456789abcdef0, %rdx
cmpq %rdx, %rax
- jne bogus_64_magic
+ je 2f
+ /* stop here on a saved_magic mismatch */
+ movq $0xbad6d61676963, %rcx
+1:
+ jmp 1b
+2:
movw $__KERNEL_DS, %ax
movw %ax, %ss
movw %ax, %ds
@@ -37,9 +42,6 @@ ENTRY(wakeup_long64)
jmp *%rax
ENDPROC(wakeup_long64)
-bogus_64_magic:
- jmp bogus_64_magic
-
ENTRY(do_suspend_lowlevel)
FRAME_BEGIN
subq $8, %rsp
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index ccd32013c47a..9d3a971ea364 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -713,7 +713,7 @@ void __init alternative_instructions(void)
* Don't stop machine check exceptions while patching.
* MCEs only happen when something got corrupted and in this
* case we must do something about the corruption.
- * Ignoring it is worse than a unlikely patching race.
+ * Ignoring it is worse than an unlikely patching race.
* Also machine checks tend to be broadcast and if one CPU
* goes into machine check the others follow quickly, so we don't
* expect a machine check to cause undue problems during to code
@@ -753,8 +753,8 @@ void __init alternative_instructions(void)
* When you use this code to patch more than one byte of an instruction
* you need to make sure that other CPUs cannot execute this code in parallel.
* Also no thread must be currently preempted in the middle of these
- * instructions. And on the local CPU you need to be protected again NMI or MCE
- * handlers seeing an inconsistent instruction while you patch.
+ * instructions. And on the local CPU you need to be protected against NMI or
+ * MCE handlers seeing an inconsistent instruction while you patch.
*/
void __init_or_module text_poke_early(void *addr, const void *opcode,
size_t len)
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index d63e63b7d1d9..251c795b4eb3 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -21,6 +21,7 @@
#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494
+#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444
/* Protect the PCI config register pairs used for SMN and DF indirect access. */
static DEFINE_MUTEX(smn_mutex);
@@ -50,6 +51,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
{}
};
EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
@@ -63,6 +65,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
{}
};
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f5291362da1a..9e2dd2b296cd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -65,10 +65,10 @@ unsigned int num_processors;
unsigned disabled_cpus;
/* Processor that is doing the boot up */
-unsigned int boot_cpu_physical_apicid = -1U;
+unsigned int boot_cpu_physical_apicid __ro_after_init = -1U;
EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
-u8 boot_cpu_apic_version;
+u8 boot_cpu_apic_version __ro_after_init;
/*
* The highest APIC ID seen during enumeration.
@@ -85,13 +85,13 @@ 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 __read_mostly = BAD_APICID;
+static unsigned int disabled_cpu_apicid __ro_after_init = BAD_APICID;
/*
* This variable controls which CPUs receive external NMIs. By default,
* external NMIs are delivered only to the BSP.
*/
-static int apic_extnmi = APIC_EXTNMI_BSP;
+static int apic_extnmi __ro_after_init = APIC_EXTNMI_BSP;
/*
* Map cpu index to physical APIC ID
@@ -114,7 +114,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_acpiid);
DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
/* Local APIC was disabled by the BIOS and enabled by the kernel */
-static int enabled_via_apicbase;
+static int enabled_via_apicbase __ro_after_init;
/*
* Handle interrupt mode configuration register (IMCR).
@@ -172,23 +172,23 @@ static __init int setup_apicpmtimer(char *s)
__setup("apicpmtimer", setup_apicpmtimer);
#endif
-unsigned long mp_lapic_addr;
-int disable_apic;
+unsigned long mp_lapic_addr __ro_after_init;
+int disable_apic __ro_after_init;
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
static int disable_apic_timer __initdata;
/* Local APIC timer works in C2 */
-int local_apic_timer_c2_ok;
+int local_apic_timer_c2_ok __ro_after_init;
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
/*
* Debug level, exported for io_apic.c
*/
-int apic_verbosity;
+int apic_verbosity __ro_after_init;
-int pic_mode;
+int pic_mode __ro_after_init;
/* Have we found an MP table */
-int smp_found_config;
+int smp_found_config __ro_after_init;
static struct resource lapic_resource = {
.name = "Local APIC",
@@ -199,7 +199,7 @@ unsigned int lapic_timer_period = 0;
static void apic_pm_activate(void);
-static unsigned long apic_phys;
+static unsigned long apic_phys __ro_after_init;
/*
* Get the LAPIC version
@@ -590,21 +590,21 @@ static u32 skx_deadline_rev(void)
static const struct x86_cpu_id deadline_match[] = {
DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_HASWELL_X, hsx_deadline_rev),
DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_X, 0x0b000020),
- DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_XEON_D, bdx_deadline_rev),
+ DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_D, bdx_deadline_rev),
DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_SKYLAKE_X, skx_deadline_rev),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_CORE, 0x22),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_ULT, 0x20),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_GT3E, 0x17),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL, 0x22),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_L, 0x20),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_G, 0x17),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_CORE, 0x25),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_GT3E, 0x17),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL, 0x25),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_G, 0x17),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_MOBILE, 0xb2),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_DESKTOP, 0xb2),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_L, 0xb2),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE, 0xb2),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_MOBILE, 0x52),
- DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_DESKTOP, 0x52),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_L, 0x52),
+ DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE, 0x52),
{},
};
@@ -722,7 +722,7 @@ static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
/*
- * Temporary interrupt handler.
+ * Temporary interrupt handler and polled calibration function.
*/
static void __init lapic_cal_handler(struct clock_event_device *dev)
{
@@ -834,6 +834,10 @@ bool __init apic_needs_pit(void)
if (!boot_cpu_has(X86_FEATURE_APIC))
return true;
+ /* Virt guests may lack ARAT, but still have DEADLINE */
+ if (!boot_cpu_has(X86_FEATURE_ARAT))
+ return true;
+
/* Deadline timer is based on TSC so no further PIT action required */
if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
return false;
@@ -851,7 +855,8 @@ bool __init apic_needs_pit(void)
static int __init calibrate_APIC_clock(void)
{
struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
- void (*real_handler)(struct clock_event_device *dev);
+ u64 tsc_perj = 0, tsc_start = 0;
+ unsigned long jif_start;
unsigned long deltaj;
long delta, deltatsc;
int pm_referenced = 0;
@@ -878,28 +883,64 @@ static int __init calibrate_APIC_clock(void)
apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
"calibrating APIC timer ...\n");
+ /*
+ * There are platforms w/o global clockevent devices. Instead of
+ * making the calibration conditional on that, use a polling based
+ * approach everywhere.
+ */
local_irq_disable();
- /* Replace the global interrupt handler */
- real_handler = global_clock_event->event_handler;
- global_clock_event->event_handler = lapic_cal_handler;
-
/*
* Setup the APIC counter to maximum. There is no way the lapic
* can underflow in the 100ms detection time frame
*/
__setup_APIC_LVTT(0xffffffff, 0, 0);
- /* Let the interrupts run */
+ /*
+ * Methods to terminate the calibration loop:
+ * 1) Global clockevent if available (jiffies)
+ * 2) TSC if available and frequency is known
+ */
+ jif_start = READ_ONCE(jiffies);
+
+ if (tsc_khz) {
+ tsc_start = rdtsc();
+ tsc_perj = div_u64((u64)tsc_khz * 1000, HZ);
+ }
+
+ /*
+ * Enable interrupts so the tick can fire, if a global
+ * clockevent device is available
+ */
local_irq_enable();
- while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
- cpu_relax();
+ while (lapic_cal_loops <= LAPIC_CAL_LOOPS) {
+ /* Wait for a tick to elapse */
+ while (1) {
+ if (tsc_khz) {
+ u64 tsc_now = rdtsc();
+ if ((tsc_now - tsc_start) >= tsc_perj) {
+ tsc_start += tsc_perj;
+ break;
+ }
+ } else {
+ unsigned long jif_now = READ_ONCE(jiffies);
- local_irq_disable();
+ if (time_after(jif_now, jif_start)) {
+ jif_start = jif_now;
+ break;
+ }
+ }
+ cpu_relax();
+ }
+
+ /* Invoke the calibration routine */
+ local_irq_disable();
+ lapic_cal_handler(NULL);
+ local_irq_enable();
+ }
- /* Restore the real event handler */
- global_clock_event->event_handler = real_handler;
+ local_irq_disable();
/* Build delta t1-t2 as apic timer counts down */
delta = lapic_cal_t1 - lapic_cal_t2;
@@ -943,10 +984,11 @@ static int __init calibrate_APIC_clock(void)
levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
/*
- * PM timer calibration failed or not turned on
- * so lets try APIC timer based calibration
+ * PM timer calibration failed or not turned on so lets try APIC
+ * timer based calibration, if a global clockevent device is
+ * available.
*/
- if (!pm_referenced) {
+ if (!pm_referenced && global_clock_event) {
apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
/*
@@ -1182,25 +1224,38 @@ void clear_local_APIC(void)
}
/**
- * disable_local_APIC - clear and disable the local APIC
+ * apic_soft_disable - Clears and software disables the local APIC on hotplug
+ *
+ * Contrary to disable_local_APIC() this does not touch the enable bit in
+ * MSR_IA32_APICBASE. Clearing that bit on systems based on the 3 wire APIC
+ * bus would require a hardware reset as the APIC would lose track of bus
+ * arbitration. On systems with FSB delivery APICBASE could be disabled,
+ * but it has to be guaranteed that no interrupt is sent to the APIC while
+ * in that state and it's not clear from the SDM whether it still responds
+ * to INIT/SIPI messages. Stay on the safe side and use software disable.
*/
-void disable_local_APIC(void)
+void apic_soft_disable(void)
{
- unsigned int value;
-
- /* APIC hasn't been mapped yet */
- if (!x2apic_mode && !apic_phys)
- return;
+ u32 value;
clear_local_APIC();
- /*
- * Disable APIC (implies clearing of registers
- * for 82489DX!).
- */
+ /* Soft disable APIC (implies clearing of registers for 82489DX!). */
value = apic_read(APIC_SPIV);
value &= ~APIC_SPIV_APIC_ENABLED;
apic_write(APIC_SPIV, value);
+}
+
+/**
+ * disable_local_APIC - clear and disable the local APIC
+ */
+void disable_local_APIC(void)
+{
+ /* APIC hasn't been mapped yet */
+ if (!x2apic_mode && !apic_phys)
+ return;
+
+ apic_soft_disable();
#ifdef CONFIG_X86_32
/*
@@ -1265,7 +1320,7 @@ void __init sync_Arb_IDs(void)
APIC_INT_LEVELTRIG | APIC_DM_INIT);
}
-enum apic_intr_mode_id apic_intr_mode;
+enum apic_intr_mode_id apic_intr_mode __ro_after_init;
static int __init apic_intr_mode_select(void)
{
@@ -1453,54 +1508,72 @@ static void lapic_setup_esr(void)
oldvalue, value);
}
-static void apic_pending_intr_clear(void)
+#define APIC_IR_REGS APIC_ISR_NR
+#define APIC_IR_BITS (APIC_IR_REGS * 32)
+#define APIC_IR_MAPSIZE (APIC_IR_BITS / BITS_PER_LONG)
+
+union apic_ir {
+ unsigned long map[APIC_IR_MAPSIZE];
+ u32 regs[APIC_IR_REGS];
+};
+
+static bool apic_check_and_ack(union apic_ir *irr, union apic_ir *isr)
{
- long long max_loops = cpu_khz ? cpu_khz : 1000000;
- unsigned long long tsc = 0, ntsc;
- unsigned int queued;
- unsigned long value;
- int i, j, acked = 0;
+ int i, bit;
+
+ /* Read the IRRs */
+ for (i = 0; i < APIC_IR_REGS; i++)
+ irr->regs[i] = apic_read(APIC_IRR + i * 0x10);
+
+ /* Read the ISRs */
+ for (i = 0; i < APIC_IR_REGS; i++)
+ isr->regs[i] = apic_read(APIC_ISR + i * 0x10);
- if (boot_cpu_has(X86_FEATURE_TSC))
- tsc = rdtsc();
/*
- * After a crash, we no longer service the interrupts and a pending
- * interrupt from previous kernel might still have ISR bit set.
- *
- * Most probably by now CPU has serviced that pending interrupt and
- * it might not have done the ack_APIC_irq() because it thought,
- * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
- * does not clear the ISR bit and cpu thinks it has already serivced
- * the interrupt. Hence a vector might get locked. It was noticed
- * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
+ * If the ISR map is not empty. ACK the APIC and run another round
+ * to verify whether a pending IRR has been unblocked and turned
+ * into a ISR.
*/
- do {
- queued = 0;
- for (i = APIC_ISR_NR - 1; i >= 0; i--)
- queued |= apic_read(APIC_IRR + i*0x10);
-
- for (i = APIC_ISR_NR - 1; i >= 0; i--) {
- value = apic_read(APIC_ISR + i*0x10);
- for_each_set_bit(j, &value, 32) {
- ack_APIC_irq();
- acked++;
- }
- }
- if (acked > 256) {
- pr_err("LAPIC pending interrupts after %d EOI\n", acked);
- break;
- }
- if (queued) {
- if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) {
- ntsc = rdtsc();
- max_loops = (long long)cpu_khz << 10;
- max_loops -= ntsc - tsc;
- } else {
- max_loops--;
- }
- }
- } while (queued && max_loops > 0);
- WARN_ON(max_loops <= 0);
+ if (!bitmap_empty(isr->map, APIC_IR_BITS)) {
+ /*
+ * There can be multiple ISR bits set when a high priority
+ * interrupt preempted a lower priority one. Issue an ACK
+ * per set bit.
+ */
+ for_each_set_bit(bit, isr->map, APIC_IR_BITS)
+ ack_APIC_irq();
+ return true;
+ }
+
+ return !bitmap_empty(irr->map, APIC_IR_BITS);
+}
+
+/*
+ * After a crash, we no longer service the interrupts and a pending
+ * interrupt from previous kernel might still have ISR bit set.
+ *
+ * Most probably by now the CPU has serviced that pending interrupt and it
+ * might not have done the ack_APIC_irq() because it thought, interrupt
+ * came from i8259 as ExtInt. LAPIC did not get EOI so it does not clear
+ * the ISR bit and cpu thinks it has already serivced the interrupt. Hence
+ * a vector might get locked. It was noticed for timer irq (vector
+ * 0x31). Issue an extra EOI to clear ISR.
+ *
+ * If there are pending IRR bits they turn into ISR bits after a higher
+ * priority ISR bit has been acked.
+ */
+static void apic_pending_intr_clear(void)
+{
+ union apic_ir irr, isr;
+ unsigned int i;
+
+ /* 512 loops are way oversized and give the APIC a chance to obey. */
+ for (i = 0; i < 512; i++) {
+ if (!apic_check_and_ack(&irr, &isr))
+ return;
+ }
+ /* Dump the IRR/ISR content if that failed */
+ pr_warn("APIC: Stale IRR: %256pb ISR: %256pb\n", irr.map, isr.map);
}
/**
@@ -1517,12 +1590,19 @@ static void setup_local_APIC(void)
int logical_apicid, ldr_apicid;
#endif
-
if (disable_apic) {
disable_ioapic_support();
return;
}
+ /*
+ * If this comes from kexec/kcrash the APIC might be enabled in
+ * SPIV. Soft disable it before doing further initialization.
+ */
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_SPIV_APIC_ENABLED;
+ apic_write(APIC_SPIV, value);
+
#ifdef CONFIG_X86_32
/* Pound the ESR really hard over the head with a big hammer - mbligh */
if (lapic_is_integrated() && apic->disable_esr) {
@@ -1532,8 +1612,6 @@ static void setup_local_APIC(void)
apic_write(APIC_ESR, 0);
}
#endif
- perf_events_lapic_init();
-
/*
* Double-check whether this APIC is really registered.
* This is meaningless in clustered apic mode, so we skip it.
@@ -1561,13 +1639,17 @@ static void setup_local_APIC(void)
#endif
/*
- * Set Task Priority to 'accept all'. We never change this
- * later on.
+ * Set Task Priority to 'accept all except vectors 0-31'. An APIC
+ * vector in the 16-31 range could be delivered if TPR == 0, but we
+ * would think it's an exception and terrible things will happen. We
+ * never change this later on.
*/
value = apic_read(APIC_TASKPRI);
value &= ~APIC_TPRI_MASK;
+ value |= 0x10;
apic_write(APIC_TASKPRI, value);
+ /* Clear eventually stale ISR/IRR bits */
apic_pending_intr_clear();
/*
@@ -1614,6 +1696,8 @@ static void setup_local_APIC(void)
value |= SPURIOUS_APIC_VECTOR;
apic_write(APIC_SPIV, value);
+ perf_events_lapic_init();
+
/*
* Set up LVT0, LVT1:
*
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index bbdca603f94a..7862b152a052 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -8,21 +8,14 @@
* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
* James Cleverdon.
*/
-#include <linux/acpi.h>
-#include <linux/errno.h>
-#include <linux/threads.h>
#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/hardirq.h>
#include <linux/export.h>
+#include <linux/acpi.h>
-#include <asm/smp.h>
-#include <asm/ipi.h>
-#include <asm/apic.h>
-#include <asm/apic_flat_64.h>
#include <asm/jailhouse_para.h>
+#include <asm/apic.h>
+
+#include "local.h"
static struct apic apic_physflat;
static struct apic apic_flat;
@@ -83,35 +76,6 @@ flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
_flat_send_IPI_mask(mask, vector);
}
-static void flat_send_IPI_allbutself(int vector)
-{
- int cpu = smp_processor_id();
-
- if (IS_ENABLED(CONFIG_HOTPLUG_CPU) || vector == NMI_VECTOR) {
- if (!cpumask_equal(cpu_online_mask, cpumask_of(cpu))) {
- unsigned long mask = cpumask_bits(cpu_online_mask)[0];
-
- if (cpu < BITS_PER_LONG)
- __clear_bit(cpu, &mask);
-
- _flat_send_IPI_mask(mask, vector);
- }
- } else if (num_online_cpus() > 1) {
- __default_send_IPI_shortcut(APIC_DEST_ALLBUT,
- vector, apic->dest_logical);
- }
-}
-
-static void flat_send_IPI_all(int vector)
-{
- if (vector == NMI_VECTOR) {
- flat_send_IPI_mask(cpu_online_mask, vector);
- } else {
- __default_send_IPI_shortcut(APIC_DEST_ALLINC,
- vector, apic->dest_logical);
- }
-}
-
static unsigned int flat_get_apic_id(unsigned long x)
{
return (x >> 24) & 0xFF;
@@ -173,9 +137,9 @@ static struct apic apic_flat __ro_after_init = {
.send_IPI = default_send_IPI_single,
.send_IPI_mask = flat_send_IPI_mask,
.send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
- .send_IPI_allbutself = flat_send_IPI_allbutself,
- .send_IPI_all = flat_send_IPI_all,
- .send_IPI_self = apic_send_IPI_self,
+ .send_IPI_allbutself = default_send_IPI_allbutself,
+ .send_IPI_all = default_send_IPI_all,
+ .send_IPI_self = default_send_IPI_self,
.inquire_remote_apic = default_inquire_remote_apic,
@@ -225,16 +189,6 @@ static void physflat_init_apic_ldr(void)
*/
}
-static void physflat_send_IPI_allbutself(int vector)
-{
- default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
-}
-
-static void physflat_send_IPI_all(int vector)
-{
- default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
-}
-
static int physflat_probe(void)
{
if (apic == &apic_physflat || num_possible_cpus() > 8 ||
@@ -276,9 +230,9 @@ static struct apic apic_physflat __ro_after_init = {
.send_IPI = default_send_IPI_single_phys,
.send_IPI_mask = default_send_IPI_mask_sequence_phys,
.send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_phys,
- .send_IPI_allbutself = physflat_send_IPI_allbutself,
- .send_IPI_all = physflat_send_IPI_all,
- .send_IPI_self = apic_send_IPI_self,
+ .send_IPI_allbutself = default_send_IPI_allbutself,
+ .send_IPI_all = default_send_IPI_all,
+ .send_IPI_self = default_send_IPI_self,
.inquire_remote_apic = default_inquire_remote_apic,
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 5078b5ce63a7..98c9bb75d185 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -9,25 +9,9 @@
* to not uglify the caller's code and allow to call (some) apic routines
* like self-ipi, etc...
*/
-
-#include <linux/threads.h>
#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/errno.h>
-#include <asm/fixmap.h>
-#include <asm/mpspec.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/setup.h>
-#include <linux/smp.h>
-#include <asm/ipi.h>
-
-#include <linux/interrupt.h>
-#include <asm/acpi.h>
-#include <asm/e820/api.h>
+#include <asm/apic.h>
static void noop_init_apic_ldr(void) { }
static void noop_send_IPI(int cpu, int vector) { }
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index a5464b8b6c46..cdf45b4700f2 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -10,15 +10,15 @@
* Send feedback to <support@numascale.com>
*
*/
-
+#include <linux/types.h>
#include <linux/init.h>
#include <asm/numachip/numachip.h>
#include <asm/numachip/numachip_csr.h>
-#include <asm/ipi.h>
-#include <asm/apic_flat_64.h>
+
#include <asm/pgtable.h>
-#include <asm/pci_x86.h>
+
+#include "local.h"
u8 numachip_system __read_mostly;
static const struct apic apic_numachip1;
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index afee386ff711..38b5b51d42f6 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -4,18 +4,13 @@
*
* Drives the local APIC in "clustered mode".
*/
-#include <linux/threads.h>
#include <linux/cpumask.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/dmi.h>
#include <linux/smp.h>
-#include <asm/apicdef.h>
-#include <asm/fixmap.h>
-#include <asm/mpspec.h>
#include <asm/apic.h>
-#include <asm/ipi.h>
+
+#include "local.h"
static unsigned bigsmp_get_apic_id(unsigned long x)
{
@@ -38,32 +33,12 @@ static int bigsmp_early_logical_apicid(int cpu)
return early_per_cpu(x86_cpu_to_apicid, cpu);
}
-static inline unsigned long calculate_ldr(int cpu)
-{
- unsigned long val, id;
-
- val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
- id = per_cpu(x86_bios_cpu_apicid, cpu);
- val |= SET_APIC_LOGICAL_ID(id);
-
- return val;
-}
-
/*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116). So here it goes...
+ * bigsmp enables physical destination mode
+ * and doesn't use LDR and DFR
*/
static void bigsmp_init_apic_ldr(void)
{
- unsigned long val;
- int cpu = smp_processor_id();
-
- apic_write(APIC_DFR, APIC_DFR_FLAT);
- val = calculate_ldr(cpu);
- apic_write(APIC_LDR, val);
}
static void bigsmp_setup_apic_routing(void)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index c7bb6c69f21c..d6af97fd170a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2438,7 +2438,13 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
* dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
* gsi_top if ioapic_dynirq_base hasn't been initialized yet.
*/
- return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
+ if (!ioapic_initialized)
+ return gsi_top;
+ /*
+ * For DT enabled machines ioapic_dynirq_base is irrelevant and not
+ * updated. So simply return @from if ioapic_dynirq_base == 0.
+ */
+ return ioapic_dynirq_base ? : from;
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c
index 82f9244fe61f..6ca0f91372fd 100644
--- a/arch/x86/kernel/apic/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
@@ -1,24 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
+
#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/cache.h>
-#include <linux/cpu.h>
-
-#include <asm/smp.h>
-#include <asm/mtrr.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-#include <asm/apic.h>
-#include <asm/proto.h>
-#include <asm/ipi.h>
-
-void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
+#include <linux/smp.h>
+
+#include "local.h"
+
+DEFINE_STATIC_KEY_FALSE(apic_use_ipi_shorthand);
+
+#ifdef CONFIG_SMP
+static int apic_ipi_shorthand_off __ro_after_init;
+
+static __init int apic_ipi_shorthand(char *str)
+{
+ get_option(&str, &apic_ipi_shorthand_off);
+ return 1;
+}
+__setup("no_ipi_broadcast=", apic_ipi_shorthand);
+
+static int __init print_ipi_mode(void)
+{
+ pr_info("IPI shorthand broadcast: %s\n",
+ apic_ipi_shorthand_off ? "disabled" : "enabled");
+ return 0;
+}
+late_initcall(print_ipi_mode);
+
+void apic_smt_update(void)
+{
+ /*
+ * Do not switch to broadcast mode if:
+ * - Disabled on the command line
+ * - Only a single CPU is online
+ * - Not all present CPUs have been at least booted once
+ *
+ * The latter is important as the local APIC might be in some
+ * random state and a broadcast might cause havoc. That's
+ * especially true for NMI broadcasting.
+ */
+ if (apic_ipi_shorthand_off || num_online_cpus() == 1 ||
+ !cpumask_equal(cpu_present_mask, &cpus_booted_once_mask)) {
+ static_branch_disable(&apic_use_ipi_shorthand);
+ } else {
+ static_branch_enable(&apic_use_ipi_shorthand);
+ }
+}
+
+void apic_send_IPI_allbutself(unsigned int vector)
+{
+ if (num_online_cpus() < 2)
+ return;
+
+ if (static_branch_likely(&apic_use_ipi_shorthand))
+ apic->send_IPI_allbutself(vector);
+ else
+ apic->send_IPI_mask_allbutself(cpu_online_mask, vector);
+}
+
+/*
+ * Send a 'reschedule' IPI to another CPU. It goes straight through and
+ * wastes no time serializing anything. Worst case is that we lose a
+ * reschedule ...
+ */
+void native_smp_send_reschedule(int cpu)
+{
+ if (unlikely(cpu_is_offline(cpu))) {
+ WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu);
+ return;
+ }
+ apic->send_IPI(cpu, RESCHEDULE_VECTOR);
+}
+
+void native_send_call_func_single_ipi(int cpu)
+{
+ apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR);
+}
+
+void native_send_call_func_ipi(const struct cpumask *mask)
+{
+ if (static_branch_likely(&apic_use_ipi_shorthand)) {
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpumask_or_equal(mask, cpumask_of(cpu), cpu_online_mask))
+ goto sendmask;
+
+ if (cpumask_test_cpu(cpu, mask))
+ apic->send_IPI_all(CALL_FUNCTION_VECTOR);
+ else if (num_online_cpus() > 1)
+ apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+ return;
+ }
+
+sendmask:
+ apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+}
+
+#endif /* CONFIG_SMP */
+
+static inline int __prepare_ICR2(unsigned int mask)
+{
+ return SET_APIC_DEST_FIELD(mask);
+}
+
+static inline void __xapic_wait_icr_idle(void)
+{
+ while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
+ cpu_relax();
+}
+
+void __default_send_IPI_shortcut(unsigned int shortcut, int vector)
{
/*
* Subtle. In the case of the 'never do double writes' workaround
@@ -32,12 +121,16 @@ void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int
/*
* Wait for idle.
*/
- __xapic_wait_icr_idle();
+ if (unlikely(vector == NMI_VECTOR))
+ safe_apic_wait_icr_idle();
+ else
+ __xapic_wait_icr_idle();
/*
- * No need to touch the target chip field
+ * No need to touch the target chip field. Also the destination
+ * mode is ignored when a shorthand is used.
*/
- cfg = __prepare_ICR(shortcut, vector, dest);
+ cfg = __prepare_ICR(shortcut, vector, 0);
/*
* Send the IPI. The write to APIC_ICR fires this off.
@@ -133,6 +226,21 @@ void default_send_IPI_single(int cpu, int vector)
apic->send_IPI_mask(cpumask_of(cpu), vector);
}
+void default_send_IPI_allbutself(int vector)
+{
+ __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+}
+
+void default_send_IPI_all(int vector)
+{
+ __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+}
+
+void default_send_IPI_self(int vector)
+{
+ __default_send_IPI_shortcut(APIC_DEST_SELF, vector);
+}
+
#ifdef CONFIG_X86_32
void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
@@ -192,28 +300,6 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
local_irq_restore(flags);
}
-void default_send_IPI_allbutself(int vector)
-{
- /*
- * if there are no other CPUs in the system then we get an APIC send
- * error if we try to broadcast, thus avoid sending IPIs in this case.
- */
- if (!(num_online_cpus() > 1))
- return;
-
- __default_local_send_IPI_allbutself(vector);
-}
-
-void default_send_IPI_all(int vector)
-{
- __default_local_send_IPI_all(vector);
-}
-
-void default_send_IPI_self(int vector)
-{
- __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical);
-}
-
/* must come after the send_IPI functions above for inlining */
static int convert_apicid_to_cpu(int apic_id)
{
diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h
new file mode 100644
index 000000000000..04797f05ce94
--- /dev/null
+++ b/arch/x86/kernel/apic/local.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Historical copyright notices:
+ *
+ * Copyright 2004 James Cleverdon, IBM.
+ * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+ * (c) 2002,2003 Andi Kleen, SuSE Labs.
+ */
+
+#include <linux/jump_label.h>
+
+#include <asm/apic.h>
+
+/* APIC flat 64 */
+void flat_init_apic_ldr(void);
+
+/* X2APIC */
+int x2apic_apic_id_valid(u32 apicid);
+int x2apic_apic_id_registered(void);
+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);
+void x2apic_send_IPI_self(int vector);
+void __x2apic_send_IPI_shorthand(int vector, u32 which);
+
+/* IPI */
+
+DECLARE_STATIC_KEY_FALSE(apic_use_ipi_shorthand);
+
+static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
+ unsigned int dest)
+{
+ unsigned int icr = shortcut | dest;
+
+ switch (vector) {
+ default:
+ icr |= APIC_DM_FIXED | vector;
+ break;
+ case NMI_VECTOR:
+ icr |= APIC_DM_NMI;
+ break;
+ }
+ return icr;
+}
+
+void __default_send_IPI_shortcut(unsigned int shortcut, int vector);
+
+/*
+ * This is used to send an IPI with no shorthand notation (the destination is
+ * specified in bits 56 to 63 of the ICR).
+ */
+void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest);
+
+void default_send_IPI_single(int cpu, int vector);
+void default_send_IPI_single_phys(int cpu, int vector);
+void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector);
+void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector);
+void default_send_IPI_allbutself(int vector);
+void default_send_IPI_all(int vector);
+void default_send_IPI_self(int vector);
+
+#ifdef CONFIG_X86_32
+void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector);
+void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector);
+void default_send_IPI_mask_logical(const struct cpumask *mask, int vector);
+#endif
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 1492799b8f43..67b33d67002f 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -6,51 +6,14 @@
*
* Generic x86 APIC driver probe layer.
*/
-#include <linux/threads.h>
-#include <linux/cpumask.h>
#include <linux/export.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
#include <linux/errno.h>
-#include <asm/fixmap.h>
-#include <asm/mpspec.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/setup.h>
-
#include <linux/smp.h>
-#include <asm/ipi.h>
-#include <linux/interrupt.h>
+#include <asm/apic.h>
#include <asm/acpi.h>
-#include <asm/e820/api.h>
-#ifdef CONFIG_HOTPLUG_CPU
-#define DEFAULT_SEND_IPI (1)
-#else
-#define DEFAULT_SEND_IPI (0)
-#endif
-
-int no_broadcast = DEFAULT_SEND_IPI;
-
-static __init int no_ipi_broadcast(char *str)
-{
- get_option(&str, &no_broadcast);
- pr_info("Using %s mode\n",
- no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
- return 1;
-}
-__setup("no_ipi_broadcast=", no_ipi_broadcast);
-
-static int __init print_ipi_mode(void)
-{
- pr_info("Using IPI %s mode\n",
- no_broadcast ? "No-Shortcut" : "Shortcut");
- return 0;
-}
-late_initcall(print_ipi_mode);
+#include "local.h"
static int default_x86_32_early_logical_apicid(int cpu)
{
@@ -184,7 +147,8 @@ void __init default_setup_apic_routing(void)
def_to_bigsmp = 0;
break;
}
- /* If P4 and above fall through */
+ /* P4 and above */
+ /* fall through */
case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
def_to_bigsmp = 1;
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index e6560a02eb46..29f0e0984557 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -8,19 +8,9 @@
* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
* James Cleverdon.
*/
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/hardirq.h>
-#include <linux/dmar.h>
-
-#include <asm/smp.h>
#include <asm/apic.h>
-#include <asm/ipi.h>
-#include <asm/setup.h>
+
+#include "local.h"
/*
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
@@ -46,13 +36,6 @@ void __init default_setup_apic_routing(void)
x86_platform.apic_post_init();
}
-/* Same for both flat and physical. */
-
-void apic_send_IPI_self(int vector)
-{
- __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
-}
-
int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
struct apic **drv;
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index fdacb864c3dd..2c5676b0a6e7 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -398,6 +398,17 @@ static int activate_reserved(struct irq_data *irqd)
if (!irqd_can_reserve(irqd))
apicd->can_reserve = false;
}
+
+ /*
+ * Check to ensure that the effective affinity mask is a subset
+ * the user supplied affinity mask, and warn the user if it is not
+ */
+ if (!cpumask_subset(irq_data_get_effective_affinity_mask(irqd),
+ irq_data_get_affinity_mask(irqd))) {
+ pr_warn("irq %u: Affinity broken due to vector space exhaustion.\n",
+ irqd->irq);
+ }
+
return ret;
}
diff --git a/arch/x86/kernel/apic/x2apic.h b/arch/x86/kernel/apic/x2apic.h
deleted file mode 100644
index a49b3604027f..000000000000
--- a/arch/x86/kernel/apic/x2apic.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Common bits for X2APIC cluster/physical modes. */
-
-int x2apic_apic_id_valid(u32 apicid);
-int x2apic_apic_id_registered(void);
-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);
-void x2apic_send_IPI_self(int vector);
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 609e499387a1..45e92cba92f5 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -1,15 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/threads.h>
+
+#include <linux/cpuhotplug.h>
#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/dmar.h>
-#include <linux/irq.h>
-#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include <asm/apic.h>
-#include <asm/smp.h>
-#include "x2apic.h"
+#include "local.h"
struct cluster_mask {
unsigned int clusterid;
@@ -84,12 +82,12 @@ x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
static void x2apic_send_IPI_allbutself(int vector)
{
- __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT);
+ __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT);
}
static void x2apic_send_IPI_all(int vector)
{
- __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
+ __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC);
}
static u32 x2apic_calc_apicid(unsigned int cpu)
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index b5cf9e7b3830..bc9693841353 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -1,14 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/threads.h>
+
#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/dmar.h>
+#include <linux/acpi.h>
-#include <asm/smp.h>
-#include <asm/ipi.h>
-#include "x2apic.h"
+#include "local.h"
int x2apic_phys;
@@ -80,12 +75,12 @@ static void
static void x2apic_send_IPI_allbutself(int vector)
{
- __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT);
+ __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT);
}
static void x2apic_send_IPI_all(int vector)
{
- __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
+ __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC);
}
static void init_x2apic_ldr(void)
@@ -117,6 +112,14 @@ void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
native_x2apic_icr_write(cfg, apicid);
}
+void __x2apic_send_IPI_shorthand(int vector, u32 which)
+{
+ unsigned long cfg = __prepare_ICR(which, vector, 0);
+
+ x2apic_wrmsr_fence();
+ native_x2apic_icr_write(cfg, 0);
+}
+
unsigned int x2apic_get_apic_id(unsigned long id)
{
return id;
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 1e225528f0d7..e6230af19864 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -7,42 +7,22 @@
*
* Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
*/
+#include <linux/crash_dump.h>
+#include <linux/cpuhotplug.h>
#include <linux/cpumask.h>
-#include <linux/hardirq.h>
#include <linux/proc_fs.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
+#include <linux/memory.h>
#include <linux/export.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
-#include <linux/init.h>
-#include <linux/io.h>
#include <linux/pci.h>
-#include <linux/kdebug.h>
-#include <linux/delay.h>
-#include <linux/crash_dump.h>
-#include <linux/reboot.h>
-#include <linux/memory.h>
-#include <linux/numa.h>
+#include <asm/e820/api.h>
#include <asm/uv/uv_mmrs.h>
#include <asm/uv/uv_hub.h>
-#include <asm/current.h>
-#include <asm/pgtable.h>
#include <asm/uv/bios.h>
#include <asm/uv/uv.h>
#include <asm/apic.h>
-#include <asm/e820/api.h>
-#include <asm/ipi.h>
-#include <asm/smp.h>
-#include <asm/x86_init.h>
-#include <asm/nmi.h>
-DEFINE_PER_CPU(int, x2apic_extra_bits);
+static DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
static bool uv_hubless_system;
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index d3d075226c0a..24d2fde30d00 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -6,13 +6,28 @@
#include <asm/ia32.h>
#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
+#define __SYSCALL_X32(nr, sym, qual)
static char syscalls_64[] = {
#include <asm/syscalls_64.h>
};
+#undef __SYSCALL_64
+#undef __SYSCALL_X32
+
+#ifdef CONFIG_X86_X32_ABI
+#define __SYSCALL_64(nr, sym, qual)
+#define __SYSCALL_X32(nr, sym, qual) [nr] = 1,
+static char syscalls_x32[] = {
+#include <asm/syscalls_64.h>
+};
+#undef __SYSCALL_64
+#undef __SYSCALL_X32
+#endif
+
#define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
static char syscalls_ia32[] = {
#include <asm/syscalls_32.h>
};
+#undef __SYSCALL_I386
#if defined(CONFIG_KVM_GUEST) && defined(CONFIG_PARAVIRT_SPINLOCKS)
#include <asm/kvm_para.h>
@@ -62,7 +77,6 @@ int main(void)
ENTRY(cr2);
ENTRY(cr3);
ENTRY(cr4);
- ENTRY(cr8);
ENTRY(gdt_desc);
BLANK();
#undef ENTRY
@@ -80,6 +94,11 @@ int main(void)
DEFINE(__NR_syscall_max, sizeof(syscalls_64) - 1);
DEFINE(NR_syscalls, sizeof(syscalls_64));
+#ifdef CONFIG_X86_X32_ABI
+ DEFINE(__NR_syscall_x32_max, sizeof(syscalls_x32) - 1);
+ DEFINE(X32_NR_syscalls, sizeof(syscalls_x32));
+#endif
+
DEFINE(__NR_syscall_compat_max, sizeof(syscalls_ia32) - 1);
DEFINE(IA32_NR_syscalls, sizeof(syscalls_ia32));
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 8d4e50428b68..90f75e515876 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/random.h>
+#include <linux/topology.h>
#include <asm/processor.h>
#include <asm/apic.h>
#include <asm/cacheinfo.h>
@@ -804,6 +805,64 @@ static void init_amd_ln(struct cpuinfo_x86 *c)
msr_set_bit(MSR_AMD64_DE_CFG, 31);
}
+static bool rdrand_force;
+
+static int __init rdrand_cmdline(char *str)
+{
+ if (!str)
+ return -EINVAL;
+
+ if (!strcmp(str, "force"))
+ rdrand_force = true;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+early_param("rdrand", rdrand_cmdline);
+
+static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c)
+{
+ /*
+ * Saving of the MSR used to hide the RDRAND support during
+ * suspend/resume is done by arch/x86/power/cpu.c, which is
+ * dependent on CONFIG_PM_SLEEP.
+ */
+ if (!IS_ENABLED(CONFIG_PM_SLEEP))
+ return;
+
+ /*
+ * The nordrand option can clear X86_FEATURE_RDRAND, so check for
+ * RDRAND support using the CPUID function directly.
+ */
+ if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force)
+ return;
+
+ msr_clear_bit(MSR_AMD64_CPUID_FN_1, 62);
+
+ /*
+ * Verify that the CPUID change has occurred in case the kernel is
+ * running virtualized and the hypervisor doesn't support the MSR.
+ */
+ if (cpuid_ecx(1) & BIT(30)) {
+ pr_info_once("BIOS may not properly restore RDRAND after suspend, but hypervisor does not support hiding RDRAND via CPUID.\n");
+ return;
+ }
+
+ clear_cpu_cap(c, X86_FEATURE_RDRAND);
+ pr_info_once("BIOS may not properly restore RDRAND after suspend, hiding RDRAND via CPUID. Use rdrand=force to reenable.\n");
+}
+
+static void init_amd_jg(struct cpuinfo_x86 *c)
+{
+ /*
+ * Some BIOS implementations do not restore proper RDRAND support
+ * across suspend and resume. Check on whether to hide the RDRAND
+ * instruction support via CPUID.
+ */
+ clear_rdrand_cpuid_bit(c);
+}
+
static void init_amd_bd(struct cpuinfo_x86 *c)
{
u64 value;
@@ -818,12 +877,23 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
wrmsrl_safe(MSR_F15H_IC_CFG, value);
}
}
+
+ /*
+ * Some BIOS implementations do not restore proper RDRAND support
+ * across suspend and resume. Check on whether to hide the RDRAND
+ * instruction support via CPUID.
+ */
+ clear_rdrand_cpuid_bit(c);
}
static void init_amd_zn(struct cpuinfo_x86 *c)
{
set_cpu_cap(c, X86_FEATURE_ZEN);
+#ifdef CONFIG_NUMA
+ node_reclaim_distance = 32;
+#endif
+
/*
* Fix erratum 1076: CPB feature bit not being set in CPUID.
* Always set it, except when running under a hypervisor.
@@ -860,6 +930,7 @@ static void init_amd(struct cpuinfo_x86 *c)
case 0x10: init_amd_gh(c); break;
case 0x12: init_amd_ln(c); break;
case 0x15: init_amd_bd(c); break;
+ case 0x16: init_amd_jg(c); break;
case 0x17: init_amd_zn(c); break;
}
@@ -879,12 +950,8 @@ static void init_amd(struct cpuinfo_x86 *c)
init_amd_cacheinfo(c);
if (cpu_has(c, X86_FEATURE_XMM2)) {
- unsigned long long val;
- int ret;
-
/*
- * A serializing LFENCE has less overhead than MFENCE, so
- * use it for execution serialization. On families which
+ * Use LFENCE for execution serialization. On families which
* don't have that MSR, LFENCE is already serializing.
* msr_set_bit() uses the safe accessors, too, even if the MSR
* is not present.
@@ -892,19 +959,8 @@ static void init_amd(struct cpuinfo_x86 *c)
msr_set_bit(MSR_F10H_DECFG,
MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
- /*
- * Verify that the MSR write was successful (could be running
- * under a hypervisor) and only then assume that LFENCE is
- * serializing.
- */
- ret = rdmsrl_safe(MSR_F10H_DECFG, &val);
- if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) {
- /* A serializing LFENCE stops RDTSC speculation */
- set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
- } else {
- /* MFENCE stops RDTSC speculation */
- set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
- }
+ /* A serializing LFENCE stops RDTSC speculation */
+ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
}
/*
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 66ca906aa790..91c2561b905f 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -34,6 +34,7 @@
#include "cpu.h"
+static void __init spectre_v1_select_mitigation(void);
static void __init spectre_v2_select_mitigation(void);
static void __init ssb_select_mitigation(void);
static void __init l1tf_select_mitigation(void);
@@ -98,17 +99,11 @@ void __init check_bugs(void)
if (boot_cpu_has(X86_FEATURE_STIBP))
x86_spec_ctrl_mask |= SPEC_CTRL_STIBP;
- /* Select the proper spectre mitigation before patching alternatives */
+ /* Select the proper CPU mitigations before patching alternatives: */
+ spectre_v1_select_mitigation();
spectre_v2_select_mitigation();
-
- /*
- * Select proper mitigation for any exposure to the Speculative Store
- * Bypass vulnerability.
- */
ssb_select_mitigation();
-
l1tf_select_mitigation();
-
mds_select_mitigation();
arch_smt_update();
@@ -274,6 +269,98 @@ static int __init mds_cmdline(char *str)
early_param("mds", mds_cmdline);
#undef pr_fmt
+#define pr_fmt(fmt) "Spectre V1 : " fmt
+
+enum spectre_v1_mitigation {
+ SPECTRE_V1_MITIGATION_NONE,
+ SPECTRE_V1_MITIGATION_AUTO,
+};
+
+static enum spectre_v1_mitigation spectre_v1_mitigation __ro_after_init =
+ SPECTRE_V1_MITIGATION_AUTO;
+
+static const char * const spectre_v1_strings[] = {
+ [SPECTRE_V1_MITIGATION_NONE] = "Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers",
+ [SPECTRE_V1_MITIGATION_AUTO] = "Mitigation: usercopy/swapgs barriers and __user pointer sanitization",
+};
+
+/*
+ * Does SMAP provide full mitigation against speculative kernel access to
+ * userspace?
+ */
+static bool smap_works_speculatively(void)
+{
+ if (!boot_cpu_has(X86_FEATURE_SMAP))
+ return false;
+
+ /*
+ * On CPUs which are vulnerable to Meltdown, SMAP does not
+ * prevent speculative access to user data in the L1 cache.
+ * Consider SMAP to be non-functional as a mitigation on these
+ * CPUs.
+ */
+ if (boot_cpu_has(X86_BUG_CPU_MELTDOWN))
+ return false;
+
+ return true;
+}
+
+static void __init spectre_v1_select_mitigation(void)
+{
+ if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1) || cpu_mitigations_off()) {
+ spectre_v1_mitigation = SPECTRE_V1_MITIGATION_NONE;
+ return;
+ }
+
+ if (spectre_v1_mitigation == SPECTRE_V1_MITIGATION_AUTO) {
+ /*
+ * With Spectre v1, a user can speculatively control either
+ * path of a conditional swapgs with a user-controlled GS
+ * value. The mitigation is to add lfences to both code paths.
+ *
+ * If FSGSBASE is enabled, the user can put a kernel address in
+ * GS, in which case SMAP provides no protection.
+ *
+ * [ NOTE: Don't check for X86_FEATURE_FSGSBASE until the
+ * FSGSBASE enablement patches have been merged. ]
+ *
+ * If FSGSBASE is disabled, the user can only put a user space
+ * address in GS. That makes an attack harder, but still
+ * possible if there's no SMAP protection.
+ */
+ if (!smap_works_speculatively()) {
+ /*
+ * Mitigation can be provided from SWAPGS itself or
+ * PTI as the CR3 write in the Meltdown mitigation
+ * is serializing.
+ *
+ * If neither is there, mitigate with an LFENCE to
+ * stop speculation through swapgs.
+ */
+ if (boot_cpu_has_bug(X86_BUG_SWAPGS) &&
+ !boot_cpu_has(X86_FEATURE_PTI))
+ setup_force_cpu_cap(X86_FEATURE_FENCE_SWAPGS_USER);
+
+ /*
+ * Enable lfences in the kernel entry (non-swapgs)
+ * paths, to prevent user entry from speculatively
+ * skipping swapgs.
+ */
+ setup_force_cpu_cap(X86_FEATURE_FENCE_SWAPGS_KERNEL);
+ }
+ }
+
+ pr_info("%s\n", spectre_v1_strings[spectre_v1_mitigation]);
+}
+
+static int __init nospectre_v1_cmdline(char *str)
+{
+ spectre_v1_mitigation = SPECTRE_V1_MITIGATION_NONE;
+ return 0;
+}
+early_param("nospectre_v1", nospectre_v1_cmdline);
+
+#undef pr_fmt
#define pr_fmt(fmt) "Spectre V2 : " fmt
static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
@@ -700,7 +787,7 @@ static void update_mds_branch_idle(void)
#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
-void arch_smt_update(void)
+void cpu_bugs_smt_update(void)
{
/* Enhanced IBRS implies STIBP. No update required. */
if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
@@ -1097,15 +1184,15 @@ static void override_cache_bits(struct cpuinfo_x86 *c)
case INTEL_FAM6_WESTMERE:
case INTEL_FAM6_SANDYBRIDGE:
case INTEL_FAM6_IVYBRIDGE:
- case INTEL_FAM6_HASWELL_CORE:
- case INTEL_FAM6_HASWELL_ULT:
- case INTEL_FAM6_HASWELL_GT3E:
- case INTEL_FAM6_BROADWELL_CORE:
- case INTEL_FAM6_BROADWELL_GT3E:
- case INTEL_FAM6_SKYLAKE_MOBILE:
- case INTEL_FAM6_SKYLAKE_DESKTOP:
- case INTEL_FAM6_KABYLAKE_MOBILE:
- case INTEL_FAM6_KABYLAKE_DESKTOP:
+ case INTEL_FAM6_HASWELL:
+ case INTEL_FAM6_HASWELL_L:
+ case INTEL_FAM6_HASWELL_G:
+ case INTEL_FAM6_BROADWELL:
+ case INTEL_FAM6_BROADWELL_G:
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
if (c->x86_cache_bits < 44)
c->x86_cache_bits = 44;
break;
@@ -1226,7 +1313,7 @@ static ssize_t l1tf_show_state(char *buf)
static ssize_t mds_show_state(char *buf)
{
- if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
+ if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
return sprintf(buf, "%s; SMT Host state unknown\n",
mds_strings[mds_mitigation]);
}
@@ -1290,7 +1377,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
break;
case X86_BUG_SPECTRE_V1:
- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+ return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
case X86_BUG_SPECTRE_V2:
return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 11472178e17f..9ae7d1bcd4f4 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1022,6 +1022,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
#define NO_L1TF BIT(3)
#define NO_MDS BIT(4)
#define MSBDS_ONLY BIT(5)
+#define NO_SWAPGS BIT(6)
#define VULNWL(_vendor, _family, _model, _whitelist) \
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
@@ -1048,30 +1049,39 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION),
VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION),
- VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
- VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY),
- VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY),
- VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
- VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY),
- VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY),
+ VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_SILVERMONT_D, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
VULNWL_INTEL(CORE_YONAH, NO_SSB),
- VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY),
+ VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_AIRMONT_NP, NO_L1TF | NO_SWAPGS),
- VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF),
- VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF),
- VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF),
+ VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_GOLDMONT_D, NO_MDS | NO_L1TF | NO_SWAPGS),
+ VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS),
+
+ /*
+ * Technically, swapgs isn't serializing on AMD (despite it previously
+ * being documented as such in the APM). But according to AMD, %gs is
+ * updated non-speculatively, and the issuing of %gs-relative memory
+ * operands will be blocked until the %gs update completes, which is
+ * good enough for our purposes.
+ */
/* AMD Family 0xf - 0x12 */
- VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
- VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
- VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
- VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+ VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+ VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+ VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+ VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
- VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
- VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
+ VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
+ VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
{}
};
@@ -1108,6 +1118,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
}
+ if (!cpu_matches(NO_SWAPGS))
+ setup_force_cpu_bug(X86_BUG_SWAPGS);
+
if (cpu_matches(NO_MELTDOWN))
return;
@@ -1945,3 +1958,14 @@ void microcode_check(void)
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
}
+
+/*
+ * Invoked from core CPU hotplug code after hotplug operations
+ */
+void arch_smt_update(void)
+{
+ /* Handle the speculative execution misfeatures */
+ cpu_bugs_smt_update();
+ /* Check whether IPI broadcasting can be enabled */
+ apic_smt_update();
+}
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index b5353244749b..3cbe24ca80ab 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -20,54 +20,55 @@ struct cpuid_dep {
* but it's difficult to tell that to the init reference checker.
*/
static const struct cpuid_dep cpuid_deps[] = {
- { X86_FEATURE_FXSR, X86_FEATURE_FPU },
- { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
- { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
- { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
- { X86_FEATURE_AVX, X86_FEATURE_XSAVE },
- { X86_FEATURE_PKU, X86_FEATURE_XSAVE },
- { X86_FEATURE_MPX, X86_FEATURE_XSAVE },
- { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE },
- { X86_FEATURE_CMOV, X86_FEATURE_FXSR },
- { X86_FEATURE_MMX, X86_FEATURE_FXSR },
- { X86_FEATURE_MMXEXT, X86_FEATURE_MMX },
- { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
- { X86_FEATURE_XSAVE, X86_FEATURE_FXSR },
- { X86_FEATURE_XMM, X86_FEATURE_FXSR },
- { X86_FEATURE_XMM2, X86_FEATURE_XMM },
- { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
- { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
- { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
- { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
- { X86_FEATURE_AES, X86_FEATURE_XMM2 },
- { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
- { X86_FEATURE_FMA, X86_FEATURE_AVX },
- { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
- { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
- { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
- { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
- { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
- { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
- { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC },
- { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
- { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
- { X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_FXSR, X86_FEATURE_FPU },
+ { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
+ { X86_FEATURE_AVX, X86_FEATURE_XSAVE },
+ { X86_FEATURE_PKU, X86_FEATURE_XSAVE },
+ { X86_FEATURE_MPX, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE },
+ { X86_FEATURE_CMOV, X86_FEATURE_FXSR },
+ { X86_FEATURE_MMX, X86_FEATURE_FXSR },
+ { X86_FEATURE_MMXEXT, X86_FEATURE_MMX },
+ { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
+ { X86_FEATURE_XSAVE, X86_FEATURE_FXSR },
+ { X86_FEATURE_XMM, X86_FEATURE_FXSR },
+ { X86_FEATURE_XMM2, X86_FEATURE_XMM },
+ { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
+ { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
+ { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
+ { X86_FEATURE_AES, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
+ { X86_FEATURE_FMA, X86_FEATURE_AVX },
+ { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VP2INTERSECT, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC },
+ { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
+ { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
+ { X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL },
{}
};
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index 415621ddb8a2..4e28c1fc8749 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -330,12 +330,8 @@ static void init_hygon(struct cpuinfo_x86 *c)
init_hygon_cacheinfo(c);
if (cpu_has(c, X86_FEATURE_XMM2)) {
- unsigned long long val;
- int ret;
-
/*
- * A serializing LFENCE has less overhead than MFENCE, so
- * use it for execution serialization. On families which
+ * Use LFENCE for execution serialization. On families which
* don't have that MSR, LFENCE is already serializing.
* msr_set_bit() uses the safe accessors, too, even if the MSR
* is not present.
@@ -343,19 +339,8 @@ static void init_hygon(struct cpuinfo_x86 *c)
msr_set_bit(MSR_F10H_DECFG,
MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
- /*
- * Verify that the MSR write was successful (could be running
- * under a hypervisor) and only then assume that LFENCE is
- * serializing.
- */
- ret = rdmsrl_safe(MSR_F10H_DECFG, &val);
- if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) {
- /* A serializing LFENCE stops RDTSC speculation */
- set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
- } else {
- /* MFENCE stops RDTSC speculation */
- set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
- }
+ /* A serializing LFENCE stops RDTSC speculation */
+ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
}
/*
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 8d6d92ebeb54..c2fdc00df163 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -142,21 +142,21 @@ struct sku_microcode {
u32 microcode;
};
static const struct sku_microcode spectre_bad_microcodes[] = {
- { INTEL_FAM6_KABYLAKE_DESKTOP, 0x0B, 0x80 },
- { INTEL_FAM6_KABYLAKE_DESKTOP, 0x0A, 0x80 },
- { INTEL_FAM6_KABYLAKE_DESKTOP, 0x09, 0x80 },
- { INTEL_FAM6_KABYLAKE_MOBILE, 0x0A, 0x80 },
- { INTEL_FAM6_KABYLAKE_MOBILE, 0x09, 0x80 },
+ { INTEL_FAM6_KABYLAKE, 0x0B, 0x80 },
+ { INTEL_FAM6_KABYLAKE, 0x0A, 0x80 },
+ { INTEL_FAM6_KABYLAKE, 0x09, 0x80 },
+ { INTEL_FAM6_KABYLAKE_L, 0x0A, 0x80 },
+ { INTEL_FAM6_KABYLAKE_L, 0x09, 0x80 },
{ INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e },
{ INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c },
- { INTEL_FAM6_BROADWELL_CORE, 0x04, 0x28 },
- { INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x1b },
- { INTEL_FAM6_BROADWELL_XEON_D, 0x02, 0x14 },
- { INTEL_FAM6_BROADWELL_XEON_D, 0x03, 0x07000011 },
+ { INTEL_FAM6_BROADWELL, 0x04, 0x28 },
+ { INTEL_FAM6_BROADWELL_G, 0x01, 0x1b },
+ { INTEL_FAM6_BROADWELL_D, 0x02, 0x14 },
+ { INTEL_FAM6_BROADWELL_D, 0x03, 0x07000011 },
{ INTEL_FAM6_BROADWELL_X, 0x01, 0x0b000025 },
- { INTEL_FAM6_HASWELL_ULT, 0x01, 0x21 },
- { INTEL_FAM6_HASWELL_GT3E, 0x01, 0x18 },
- { INTEL_FAM6_HASWELL_CORE, 0x03, 0x23 },
+ { INTEL_FAM6_HASWELL_L, 0x01, 0x21 },
+ { INTEL_FAM6_HASWELL_G, 0x01, 0x18 },
+ { INTEL_FAM6_HASWELL, 0x03, 0x23 },
{ INTEL_FAM6_HASWELL_X, 0x02, 0x3b },
{ INTEL_FAM6_HASWELL_X, 0x04, 0x10 },
{ INTEL_FAM6_IVYBRIDGE_X, 0x04, 0x42a },
@@ -265,9 +265,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
/* Penwell and Cloverview have the TSC which doesn't sleep on S3 */
if (c->x86 == 6) {
switch (c->x86_model) {
- case 0x27: /* Penwell */
- case 0x35: /* Cloverview */
- case 0x4a: /* Merrifield */
+ case INTEL_FAM6_ATOM_SALTWELL_MID:
+ case INTEL_FAM6_ATOM_SALTWELL_TABLET:
+ case INTEL_FAM6_ATOM_SILVERMONT_MID:
+ case INTEL_FAM6_ATOM_AIRMONT_NP:
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
break;
default:
diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c
index e43eb6732630..88cd9598fa57 100644
--- a/arch/x86/kernel/cpu/mce/intel.c
+++ b/arch/x86/kernel/cpu/mce/intel.c
@@ -479,7 +479,7 @@ static void intel_ppin_init(struct cpuinfo_x86 *c)
switch (c->x86_model) {
case INTEL_FAM6_IVYBRIDGE_X:
case INTEL_FAM6_HASWELL_X:
- case INTEL_FAM6_BROADWELL_XEON_D:
+ case INTEL_FAM6_BROADWELL_D:
case INTEL_FAM6_BROADWELL_X:
case INTEL_FAM6_SKYLAKE_X:
case INTEL_FAM6_XEON_PHI_KNL:
diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
index 210f1f5db5f7..87bcdc6dc2f0 100644
--- a/arch/x86/kernel/cpu/mce/severity.c
+++ b/arch/x86/kernel/cpu/mce/severity.c
@@ -107,11 +107,11 @@ static struct severity {
*/
MCESEV(
AO, "Action optional: memory scrubbing error",
- SER, MASK(MCI_STATUS_OVER|MCI_UC_AR|MCACOD_SCRUBMSK, MCI_STATUS_UC|MCACOD_SCRUB)
+ SER, MASK(MCI_UC_AR|MCACOD_SCRUBMSK, MCI_STATUS_UC|MCACOD_SCRUB)
),
MCESEV(
AO, "Action optional: last level cache writeback error",
- SER, MASK(MCI_STATUS_OVER|MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB)
+ SER, MASK(MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB)
),
/* ignore OVER for UCNA */
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index 4296c702a3f7..72182809b333 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -98,6 +98,7 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
case 7:
if (size < 0x40)
break;
+ /* Else, fall through */
case 6:
case 5:
case 4:
diff --git a/arch/x86/kernel/cpu/umwait.c b/arch/x86/kernel/cpu/umwait.c
index 6a204e7336c1..32b4dc9030aa 100644
--- a/arch/x86/kernel/cpu/umwait.c
+++ b/arch/x86/kernel/cpu/umwait.c
@@ -18,6 +18,12 @@
static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
/*
+ * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
+ * hardware or BIOS before kernel boot.
+ */
+static u32 orig_umwait_control_cached __ro_after_init;
+
+/*
* Serialize access to umwait_control_cached and IA32_UMWAIT_CONTROL MSR in
* the sysfs write functions.
*/
@@ -53,6 +59,23 @@ static int umwait_cpu_online(unsigned int cpu)
}
/*
+ * The CPU hotplug callback sets the control MSR to the original control
+ * value.
+ */
+static int umwait_cpu_offline(unsigned int cpu)
+{
+ /*
+ * This code is protected by the CPU hotplug already and
+ * orig_umwait_control_cached is never changed after it caches
+ * the original control MSR value in umwait_init(). So there
+ * is no race condition here.
+ */
+ wrmsr(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached, 0);
+
+ return 0;
+}
+
+/*
* On resume, restore IA32_UMWAIT_CONTROL MSR on the boot processor which
* is the only active CPU at this time. The MSR is set up on the APs via the
* CPU hotplug callback.
@@ -185,8 +208,22 @@ static int __init umwait_init(void)
if (!boot_cpu_has(X86_FEATURE_WAITPKG))
return -ENODEV;
+ /*
+ * Cache the original control MSR value before the control MSR is
+ * changed. This is the only place where orig_umwait_control_cached
+ * is modified.
+ */
+ rdmsrl(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
+
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait:online",
- umwait_cpu_online, NULL);
+ umwait_cpu_online, umwait_cpu_offline);
+ if (ret < 0) {
+ /*
+ * On failure, the control MSR on all CPUs has the
+ * original control value.
+ */
+ return ret;
+ }
register_syscore_ops(&umwait_syscore_ops);
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 3c648476d4fb..9735139cfdf8 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -30,34 +30,69 @@
#include <asm/hypervisor.h>
#include <asm/timer.h>
#include <asm/apic.h>
+#include <asm/vmware.h>
#undef pr_fmt
#define pr_fmt(fmt) "vmware: " fmt
-#define CPUID_VMWARE_INFO_LEAF 0x40000000
+#define CPUID_VMWARE_INFO_LEAF 0x40000000
+#define CPUID_VMWARE_FEATURES_LEAF 0x40000010
+#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0)
+#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1)
+
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
-#define VMWARE_HYPERVISOR_PORT 0x5658
-#define VMWARE_PORT_CMD_GETVERSION 10
-#define VMWARE_PORT_CMD_GETHZ 45
-#define VMWARE_PORT_CMD_GETVCPU_INFO 68
-#define VMWARE_PORT_CMD_LEGACY_X2APIC 3
-#define VMWARE_PORT_CMD_VCPU_RESERVED 31
+#define VMWARE_CMD_GETVERSION 10
+#define VMWARE_CMD_GETHZ 45
+#define VMWARE_CMD_GETVCPU_INFO 68
+#define VMWARE_CMD_LEGACY_X2APIC 3
+#define VMWARE_CMD_VCPU_RESERVED 31
#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \
__asm__("inl (%%dx)" : \
- "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
- "0"(VMWARE_HYPERVISOR_MAGIC), \
- "1"(VMWARE_PORT_CMD_##cmd), \
- "2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) : \
- "memory");
+ "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
+ "a"(VMWARE_HYPERVISOR_MAGIC), \
+ "c"(VMWARE_CMD_##cmd), \
+ "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) : \
+ "memory")
+
+#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \
+ __asm__("vmcall" : \
+ "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
+ "a"(VMWARE_HYPERVISOR_MAGIC), \
+ "c"(VMWARE_CMD_##cmd), \
+ "d"(0), "b"(UINT_MAX) : \
+ "memory")
+
+#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \
+ __asm__("vmmcall" : \
+ "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
+ "a"(VMWARE_HYPERVISOR_MAGIC), \
+ "c"(VMWARE_CMD_##cmd), \
+ "d"(0), "b"(UINT_MAX) : \
+ "memory")
+
+#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \
+ switch (vmware_hypercall_mode) { \
+ case CPUID_VMWARE_FEATURES_ECX_VMCALL: \
+ VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \
+ break; \
+ case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \
+ VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx); \
+ break; \
+ default: \
+ VMWARE_PORT(cmd, eax, ebx, ecx, edx); \
+ break; \
+ } \
+ } while (0)
static unsigned long vmware_tsc_khz __ro_after_init;
+static u8 vmware_hypercall_mode __ro_after_init;
static inline int __vmware_platform(void)
{
uint32_t eax, ebx, ecx, edx;
- VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx);
+ VMWARE_CMD(GETVERSION, eax, ebx, ecx, edx);
return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;
}
@@ -129,6 +164,10 @@ static void __init vmware_set_capabilities(void)
{
setup_force_cpu_cap(X86_FEATURE_CONSTANT_TSC);
setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+ if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMCALL)
+ setup_force_cpu_cap(X86_FEATURE_VMCALL);
+ else if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMMCALL)
+ setup_force_cpu_cap(X86_FEATURE_VMW_VMMCALL);
}
static void __init vmware_platform_setup(void)
@@ -136,7 +175,7 @@ static void __init vmware_platform_setup(void)
uint32_t eax, ebx, ecx, edx;
uint64_t lpj, tsc_khz;
- VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
+ VMWARE_CMD(GETHZ, eax, ebx, ecx, edx);
if (ebx != UINT_MAX) {
lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
@@ -174,10 +213,21 @@ static void __init vmware_platform_setup(void)
vmware_set_capabilities();
}
+static u8 vmware_select_hypercall(void)
+{
+ int eax, ebx, ecx, edx;
+
+ cpuid(CPUID_VMWARE_FEATURES_LEAF, &eax, &ebx, &ecx, &edx);
+ return (ecx & (CPUID_VMWARE_FEATURES_ECX_VMMCALL |
+ CPUID_VMWARE_FEATURES_ECX_VMCALL));
+}
+
/*
* While checking the dmi string information, just checking the product
* serial key should be enough, as this will always have a VMware
* specific string when running under VMware hypervisor.
+ * If !boot_cpu_has(X86_FEATURE_HYPERVISOR), vmware_hypercall_mode
+ * intentionally defaults to 0.
*/
static uint32_t __init vmware_platform(void)
{
@@ -187,8 +237,16 @@ static uint32_t __init vmware_platform(void)
cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0],
&hyper_vendor_id[1], &hyper_vendor_id[2]);
- if (!memcmp(hyper_vendor_id, "VMwareVMware", 12))
+ if (!memcmp(hyper_vendor_id, "VMwareVMware", 12)) {
+ if (eax >= CPUID_VMWARE_FEATURES_LEAF)
+ vmware_hypercall_mode =
+ vmware_select_hypercall();
+
+ pr_info("hypercall mode: 0x%02x\n",
+ (unsigned int) vmware_hypercall_mode);
+
return CPUID_VMWARE_INFO_LEAF;
+ }
} else if (dmi_available && dmi_name_in_serial("VMware") &&
__vmware_platform())
return 1;
@@ -200,9 +258,9 @@ static uint32_t __init vmware_platform(void)
static bool __init vmware_legacy_x2apic_available(void)
{
uint32_t eax, ebx, ecx, edx;
- VMWARE_PORT(GETVCPU_INFO, eax, ebx, ecx, edx);
- return (eax & (1 << VMWARE_PORT_CMD_VCPU_RESERVED)) == 0 &&
- (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
+ VMWARE_CMD(GETVCPU_INFO, eax, ebx, ecx, edx);
+ return (eax & (1 << VMWARE_CMD_VCPU_RESERVED)) == 0 &&
+ (eax & (1 << VMWARE_CMD_LEGACY_X2APIC)) != 0;
}
const __initconst struct hypervisor_x86 x86_hyper_vmware = {
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 2bf70a2fed90..eb651fbde92a 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -225,8 +225,6 @@ static int elf_header_exclude_ranges(struct crash_mem *cmem)
if (crashk_low_res.end) {
ret = crash_exclude_mem_range(cmem, crashk_low_res.start,
crashk_low_res.end);
- if (ret)
- return ret;
}
return ret;
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 2b5886401e5f..e07424e19274 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -367,13 +367,18 @@ NOKPROBE_SYMBOL(oops_end);
int __die(const char *str, struct pt_regs *regs, long err)
{
+ const char *pr = "";
+
/* Save the regs of the first oops for the executive summary later. */
if (!die_counter)
exec_summary_regs = *regs;
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT";
+
printk(KERN_DEFAULT
"%s: %04lx [#%d]%s%s%s%s%s\n", str, err & 0xffff, ++die_counter,
- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
+ pr,
IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
IS_ENABLED(CONFIG_KASAN) ? " KASAN" : "",
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index a6342c899be5..f3d3e9646a99 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -193,10 +193,10 @@ ENTRY(secondary_startup_64)
/* Set up %gs.
*
- * The base of %gs always points to the bottom of the irqstack
- * union. If the stack protector canary is enabled, it is
- * located at %gs:40. Note that, on SMP, the boot cpu uses
- * init data section till per cpu areas are set up.
+ * The base of %gs always points to fixed_percpu_data. If the
+ * stack protector canary is enabled, it is located at %gs:40.
+ * Note that, on SMP, the boot cpu uses init data section until
+ * the per cpu areas are set up.
*/
movl $MSR_GS_BASE,%ecx
movl initial_gs(%rip),%eax
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index c43e96a938d0..c6f791bc481e 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -827,10 +827,6 @@ int __init hpet_enable(void)
if (!hpet_cfg_working())
goto out_nohpet;
- /* Validate that the counter is counting */
- if (!hpet_counting())
- goto out_nohpet;
-
/*
* Read the period and check for a sane value:
*/
@@ -896,6 +892,14 @@ int __init hpet_enable(void)
}
hpet_print_config();
+ /*
+ * Validate that the counter is counting. This needs to be done
+ * after sanitizing the config registers to properly deal with
+ * force enabled HPETs.
+ */
+ if (!hpet_counting())
+ goto out_nohpet;
+
clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
if (id & HPET_ID_LEGSUP) {
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 4215653f8a8e..21efee32e2b1 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -243,11 +243,15 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU");
desc = __this_cpu_read(vector_irq[vector]);
-
- if (!handle_irq(desc, regs)) {
+ if (likely(!IS_ERR_OR_NULL(desc))) {
+ if (IS_ENABLED(CONFIG_X86_32))
+ handle_irq(desc, regs);
+ else
+ generic_handle_irq_desc(desc);
+ } else {
ack_APIC_irq();
- if (desc != VECTOR_RETRIGGERED && desc != VECTOR_SHUTDOWN) {
+ if (desc == VECTOR_UNUSED) {
pr_emerg_ratelimited("%s: %d.%d No irq handler for vector\n",
__func__, smp_processor_id(),
vector);
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index fc34816c6f04..a759ca97cd01 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -148,18 +148,13 @@ void do_softirq_own_stack(void)
call_on_stack(__do_softirq, isp);
}
-bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)
+void handle_irq(struct irq_desc *desc, struct pt_regs *regs)
{
int overflow = check_stack_overflow();
- if (IS_ERR_OR_NULL(desc))
- return false;
-
if (user_mode(regs) || !execute_on_irq_stack(overflow, desc)) {
if (unlikely(overflow))
print_stack_overflow();
generic_handle_irq_desc(desc);
}
-
- return true;
}
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 6bf6517a05bb..12df3a4abfdd 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -26,15 +26,6 @@
DEFINE_PER_CPU_PAGE_ALIGNED(struct irq_stack, irq_stack_backing_store) __visible;
DECLARE_INIT_PER_CPU(irq_stack_backing_store);
-bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)
-{
- if (IS_ERR_OR_NULL(desc))
- return false;
-
- generic_handle_irq_desc(desc);
- return true;
-}
-
#ifdef CONFIG_VMAP_STACK
/*
* VMAP the backing store with guard pages
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 23297ea64f5f..c44fe7d8d9a4 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -416,7 +416,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs)
*/
void kgdb_roundup_cpus(void)
{
- apic->send_IPI_allbutself(APIC_DM_NMI);
+ apic_send_IPI_allbutself(NMI_VECTOR);
}
#endif
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 0e0b08008b5a..43fc13c831af 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,7 +580,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
if (setup_detour_execution(p, regs, reenter))
return;
-#if !defined(CONFIG_PREEMPT)
+#if !defined(CONFIG_PREEMPTION)
if (p->ainsn.boostable && !p->post_handler) {
/* Boost up -- we can execute copied instructions directly */
if (!reenter)
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 9d4aedece363..b348dd506d58 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -403,7 +403,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
(u8 *)op->kp.addr + op->optinsn.size);
len += RELATIVEJUMP_SIZE;
- /* We have to use text_poke for instuction buffer because it is RO */
+ /* We have to use text_poke() for instruction buffer because it is RO */
text_poke(slot, buf, len);
ret = 0;
out:
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index b7f34fe2171e..4cc967178bf9 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -308,13 +308,10 @@ static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
static void kvm_guest_cpu_init(void)
{
- if (!kvm_para_available())
- return;
-
if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) {
u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason));
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
pa |= KVM_ASYNC_PF_SEND_ALWAYS;
#endif
pa |= KVM_ASYNC_PF_ENABLED;
@@ -625,9 +622,6 @@ static void __init kvm_guest_init(void)
{
int i;
- if (!kvm_para_available())
- return;
-
paravirt_ops_setup();
register_reboot_notifier(&kvm_pv_reboot_nb);
for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++)
@@ -848,8 +842,6 @@ asm(
*/
void __init kvm_spinlock_init(void)
{
- if (!kvm_para_available())
- return;
/* Does host kernel support KVM_FEATURE_PV_UNHALT? */
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
return;
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 77854b192fef..7b45e8daad22 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -148,7 +148,7 @@ int machine_kexec_prepare(struct kimage *image)
{
int error;
- set_pages_x(image->control_code_page, 1);
+ set_memory_x((unsigned long)page_address(image->control_code_page), 1);
error = machine_kexec_alloc_page_tables(image);
if (error)
return error;
@@ -162,7 +162,7 @@ int machine_kexec_prepare(struct kimage *image)
*/
void machine_kexec_cleanup(struct kimage *image)
{
- set_pages_nx(image->control_code_page, 1);
+ set_memory_nx((unsigned long)page_address(image->control_code_page), 1);
machine_kexec_free_page_tables(image);
}
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 4df7705022b9..e676a9916c49 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -512,6 +512,9 @@ NOKPROBE_SYMBOL(is_debug_stack);
dotraplinkage notrace void
do_nmi(struct pt_regs *regs, long error_code)
{
+ if (IS_ENABLED(CONFIG_SMP) && cpu_is_offline(smp_processor_id()))
+ return;
+
if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
this_cpu_write(nmi_state, NMI_LATCHED);
return;
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 0aa6256eedd8..59d3d2763a9e 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -311,10 +311,6 @@ struct paravirt_patch_template pv_ops = {
.cpu.read_cr0 = native_read_cr0,
.cpu.write_cr0 = native_write_cr0,
.cpu.write_cr4 = native_write_cr4,
-#ifdef CONFIG_X86_64
- .cpu.read_cr8 = native_read_cr8,
- .cpu.write_cr8 = native_write_cr8,
-#endif
.cpu.wbinvd = native_wbinvd,
.cpu.read_msr = native_read_msr,
.cpu.write_msr = native_write_msr,
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index f62b498b18fb..fa4352dce491 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/dma-direct.h>
#include <linux/dma-debug.h>
+#include <linux/iommu.h>
#include <linux/dmar.h>
#include <linux/export.h>
#include <linux/memblock.h>
@@ -34,21 +35,6 @@ int no_iommu __read_mostly;
/* Set this to 1 if there is a HW IOMMU in the system */
int iommu_detected __read_mostly = 0;
-/*
- * This variable becomes 1 if iommu=pt is passed on the kernel command line.
- * If this variable is 1, IOMMU implementations do no DMA translation for
- * devices and allow every device to access to whole physical memory. This is
- * useful if a user wants to use an IOMMU only for KVM device assignment to
- * guests and not for driver dma translation.
- * It is also possible to disable by default in kernel config, and enable with
- * iommu=nopt at boot time.
- */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
-
extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
void __init pci_iommu_alloc(void)
@@ -120,9 +106,9 @@ static __init int iommu_setup(char *p)
swiotlb = 1;
#endif
if (!strncmp(p, "pt", 2))
- iommu_pass_through = 1;
+ iommu_set_default_passthrough(true);
if (!strncmp(p, "nopt", 4))
- iommu_pass_through = 0;
+ iommu_set_default_translated(true);
gart_parse_options(p);
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 0fdbe89d0754..3c5bbe8e4120 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -201,6 +201,7 @@ static int set_segment_reg(struct task_struct *task,
case offsetof(struct user_regs_struct, ss):
if (unlikely(value == 0))
return -EIO;
+ /* Else, fall through */
default:
*pt_regs_access(task_pt_regs(task), offset) = value;
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 8451f38ad399..1daf8f2aa21f 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -90,8 +90,6 @@ static void ich_force_hpet_resume(void)
BUG();
else
printk(KERN_DEBUG "Force enabled HPET at resume\n");
-
- return;
}
static void ich_force_enable_hpet(struct pci_dev *dev)
@@ -448,7 +446,6 @@ static void nvidia_force_enable_hpet(struct pci_dev *dev)
dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
force_hpet_address);
cached_dev = dev;
- return;
}
/* ISA Bridges */
@@ -513,7 +510,6 @@ static void e6xx_force_enable_hpet(struct pci_dev *dev)
force_hpet_resume_type = NONE_FORCE_HPET_RESUME;
dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
"0x%lx\n", force_hpet_address);
- return;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E6XX_CU,
e6xx_force_enable_hpet);
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 09d6bded3c1e..0cc7c0b106bb 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -828,11 +828,6 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
return NMI_HANDLED;
}
-static void smp_send_nmi_allbutself(void)
-{
- apic->send_IPI_allbutself(NMI_VECTOR);
-}
-
/*
* Halt all other CPUs, calling the specified function on each of them
*
@@ -861,7 +856,7 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
*/
wmb();
- smp_send_nmi_allbutself();
+ apic_send_IPI_allbutself(NMI_VECTOR);
/* Kick CPUs looping in NMI context. */
WRITE_ONCE(crash_ipi_issued, 1);
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 96421f97e75c..b8d4e9c3c070 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -115,46 +115,6 @@
static atomic_t stopping_cpu = ATOMIC_INIT(-1);
static bool smp_no_nmi_ipi = false;
-/*
- * this function sends a 'reschedule' IPI to another CPU.
- * it goes straight through and wastes no time serializing
- * anything. Worst case is that we lose a reschedule ...
- */
-static void native_smp_send_reschedule(int cpu)
-{
- if (unlikely(cpu_is_offline(cpu))) {
- WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu);
- return;
- }
- apic->send_IPI(cpu, RESCHEDULE_VECTOR);
-}
-
-void native_send_call_func_single_ipi(int cpu)
-{
- apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR);
-}
-
-void native_send_call_func_ipi(const struct cpumask *mask)
-{
- cpumask_var_t allbutself;
-
- if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) {
- apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
- return;
- }
-
- cpumask_copy(allbutself, cpu_online_mask);
- __cpumask_clear_cpu(smp_processor_id(), allbutself);
-
- if (cpumask_equal(mask, allbutself) &&
- cpumask_equal(cpu_online_mask, cpu_callout_mask))
- apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR);
- else
- apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
-
- free_cpumask_var(allbutself);
-}
-
static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
{
/* We are registered on stopping cpu too, avoid spurious NMI */
@@ -179,6 +139,12 @@ asmlinkage __visible void smp_reboot_interrupt(void)
irq_exit();
}
+static int register_stop_handler(void)
+{
+ return register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
+ NMI_FLAG_FIRST, "smp_stop");
+}
+
static void native_stop_other_cpus(int wait)
{
unsigned long flags;
@@ -209,42 +175,44 @@ static void native_stop_other_cpus(int wait)
/* sync above data before sending IRQ */
wmb();
- apic->send_IPI_allbutself(REBOOT_VECTOR);
+ apic_send_IPI_allbutself(REBOOT_VECTOR);
/*
- * Don't wait longer than a second if the caller
- * didn't ask us to wait.
+ * Don't wait longer than a second for IPI completion. The
+ * wait request is not checked here because that would
+ * prevent an NMI shutdown attempt in case that not all
+ * CPUs reach shutdown state.
*/
timeout = USEC_PER_SEC;
- while (num_online_cpus() > 1 && (wait || timeout--))
+ while (num_online_cpus() > 1 && timeout--)
udelay(1);
}
-
- /* if the REBOOT_VECTOR didn't work, try with the NMI */
- if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) {
- if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
- NMI_FLAG_FIRST, "smp_stop"))
- /* Note: we ignore failures here */
- /* Hope the REBOOT_IRQ is good enough */
- goto finish;
- /* sync above data before sending IRQ */
- wmb();
-
- pr_emerg("Shutting down cpus with NMI\n");
+ /* if the REBOOT_VECTOR didn't work, try with the NMI */
+ if (num_online_cpus() > 1) {
+ /*
+ * If NMI IPI is enabled, try to register the stop handler
+ * and send the IPI. In any case try to wait for the other
+ * CPUs to stop.
+ */
+ if (!smp_no_nmi_ipi && !register_stop_handler()) {
+ /* Sync above data before sending IRQ */
+ wmb();
- apic->send_IPI_allbutself(NMI_VECTOR);
+ pr_emerg("Shutting down cpus with NMI\n");
+ apic_send_IPI_allbutself(NMI_VECTOR);
+ }
/*
- * Don't wait longer than a 10 ms if the caller
- * didn't ask us to wait.
+ * Don't wait longer than 10 ms if the caller didn't
+ * reqeust it. If wait is true, the machine hangs here if
+ * one or more CPUs do not reach shutdown state.
*/
timeout = USEC_PER_MSEC * 10;
while (num_online_cpus() > 1 && (wait || timeout--))
udelay(1);
}
-finish:
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 fdbd47ceb84d..69881b2d446c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1023,8 +1023,6 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
int *cpu0_nmi_registered)
{
- volatile u32 *trampoline_status =
- (volatile u32 *) __va(real_mode_header->trampoline_status);
/* start_ip had better be page-aligned! */
unsigned long start_ip = real_mode_header->trampoline_start;
@@ -1116,9 +1114,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
}
}
- /* mark "stuck" area as not stuck */
- *trampoline_status = 0;
-
if (x86_platform.legacy.warm_reset) {
/*
* Cleanup possible dangling ends...
@@ -1596,7 +1591,12 @@ int native_cpu_disable(void)
if (ret)
return ret;
- clear_local_APIC();
+ /*
+ * Disable the local APIC. Otherwise IPI broadcasts will reach
+ * it. It still responds normally to INIT, NMI, SMI, and SIPI
+ * messages.
+ */
+ apic_soft_disable();
cpu_disable_common();
return 0;
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 4f36d3241faf..2d6898c2cb64 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -100,7 +100,7 @@ copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)
{
int ret;
- if (!access_ok(fp, sizeof(*frame)))
+ if (__range_not_ok(fp, sizeof(*frame), TASK_SIZE))
return 0;
ret = 1;
diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c
index 8eb67a670b10..653b7f617b61 100644
--- a/arch/x86/kernel/sysfb_efi.c
+++ b/arch/x86/kernel/sysfb_efi.c
@@ -230,9 +230,55 @@ static const struct dmi_system_id efifb_dmi_system_table[] __initconst = {
{},
};
+/*
+ * Some devices have a portrait LCD but advertise a landscape resolution (and
+ * pitch). We simply swap width and height for these devices so that we can
+ * correctly deal with some of them coming with multiple resolutions.
+ */
+static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
+ {
+ /*
+ * Lenovo MIIX310-10ICR, only some batches have the troublesome
+ * 800x1280 portrait screen. Luckily the portrait version has
+ * its own BIOS version, so we match on that.
+ */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
+ DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1HCN44WW"),
+ },
+ },
+ {
+ /* Lenovo MIIX 320-10ICR with 800x1280 portrait screen */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+ "Lenovo MIIX 320-10ICR"),
+ },
+ },
+ {
+ /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+ "Lenovo ideapad D330-10IGM"),
+ },
+ },
+ {},
+};
+
__init void sysfb_apply_efi_quirks(void)
{
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
!(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
dmi_check_system(efifb_dmi_system_table);
+
+ if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
+ dmi_check_system(efifb_dmi_swap_width_height)) {
+ u16 temp = screen_info.lfb_width;
+
+ screen_info.lfb_width = screen_info.lfb_height;
+ screen_info.lfb_height = temp;
+ screen_info.lfb_linelength = 4 * screen_info.lfb_width;
+ }
}
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 57d87f79558f..c59454c382fd 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -638,7 +638,7 @@ unsigned long native_calibrate_tsc(void)
* clock.
*/
if (crystal_khz == 0 &&
- boot_cpu_data.x86_model == INTEL_FAM6_ATOM_GOLDMONT_X)
+ boot_cpu_data.x86_model == INTEL_FAM6_ATOM_GOLDMONT_D)
crystal_khz = 25000;
/*
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 067858fe4db8..e0cbe4f2af49 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -58,6 +58,10 @@ static const struct freq_desc freq_desc_ann = {
1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 }
};
+static const struct freq_desc freq_desc_lgm = {
+ 1, { 78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000 }
+};
+
static const struct x86_cpu_id tsc_msr_cpu_ids[] = {
INTEL_CPU_FAM6(ATOM_SALTWELL_MID, freq_desc_pnw),
INTEL_CPU_FAM6(ATOM_SALTWELL_TABLET, freq_desc_clv),
@@ -65,6 +69,7 @@ static const struct x86_cpu_id tsc_msr_cpu_ids[] = {
INTEL_CPU_FAM6(ATOM_SILVERMONT_MID, freq_desc_tng),
INTEL_CPU_FAM6(ATOM_AIRMONT, freq_desc_cht),
INTEL_CPU_FAM6(ATOM_AIRMONT_MID, freq_desc_ann),
+ INTEL_CPU_FAM6(ATOM_AIRMONT_NP, freq_desc_lgm),
{}
};
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 5b345add550f..548fefed71ee 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -19,7 +19,7 @@
/** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
*
* The feature User-Mode Instruction Prevention present in recent Intel
- * processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and str)
+ * processor prevents a group of instructions (SGDT, SIDT, SLDT, SMSW and STR)
* from being executed with CPL > 0. Otherwise, a general protection fault is
* issued.
*
@@ -36,8 +36,8 @@
* DOSEMU2) rely on this subset of instructions to function.
*
* The instructions protected by UMIP can be split in two groups. Those which
- * return a kernel memory address (sgdt and sidt) and those which return a
- * value (sldt, str and smsw).
+ * return a kernel memory address (SGDT and SIDT) and those which return a
+ * value (SLDT, STR and SMSW).
*
* For the instructions that return a kernel memory address, applications
* such as WineHQ rely on the result being located in the kernel memory space,
@@ -45,15 +45,13 @@
* value that, lies close to the top of the kernel memory. The limit for the GDT
* and the IDT are set to zero.
*
- * Given that sldt and str are not commonly used in programs that run on WineHQ
+ * Given that SLDT and STR are not commonly used in programs that run on WineHQ
* or DOSEMU2, they are not emulated.
*
* The instruction smsw is emulated to return the value that the register CR0
* has at boot time as set in the head_32.
*
- * Also, emulation is provided only for 32-bit processes; 64-bit processes
- * that attempt to use the instructions that UMIP protects will receive the
- * SIGSEGV signal issued as a consequence of the general protection fault.
+ * Emulation is provided for both 32-bit and 64-bit processes.
*
* Care is taken to appropriately emulate the results when segmentation is
* used. That is, rather than relying on USER_DS and USER_CS, the function
@@ -63,17 +61,18 @@
* application uses a local descriptor table.
*/
-#define UMIP_DUMMY_GDT_BASE 0xfffe0000
-#define UMIP_DUMMY_IDT_BASE 0xffff0000
+#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL
+#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL
/*
* The SGDT and SIDT instructions store the contents of the global descriptor
* table and interrupt table registers, respectively. The destination is a
* memory operand of X+2 bytes. X bytes are used to store the base address of
- * the table and 2 bytes are used to store the limit. In 32-bit processes, the
- * only processes for which emulation is provided, X has a value of 4.
+ * the table and 2 bytes are used to store the limit. In 32-bit processes X
+ * has a value of 4, in 64-bit processes X has a value of 8.
*/
-#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8
+#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4
#define UMIP_GDT_IDT_LIMIT_SIZE 2
#define UMIP_INST_SGDT 0 /* 0F 01 /0 */
@@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn)
* @umip_inst: A constant indicating the instruction to emulate
* @data: Buffer into which the dummy result is stored
* @data_size: Size of the emulated result
+ * @x86_64: true if process is 64-bit, false otherwise
*
* Emulate an instruction protected by UMIP and provide a dummy result. The
* result of the emulation is saved in @data. The size of the results depends
@@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn)
* 0 on success, -EINVAL on error while emulating.
*/
static int emulate_umip_insn(struct insn *insn, int umip_inst,
- unsigned char *data, int *data_size)
+ unsigned char *data, int *data_size, bool x86_64)
{
- unsigned long dummy_base_addr, dummy_value;
- unsigned short dummy_limit = 0;
-
if (!data || !data_size || !insn)
return -EINVAL;
/*
@@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
* is always returned irrespective of the operand size.
*/
if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+ u64 dummy_base_addr;
+ u16 dummy_limit = 0;
+
/* SGDT and SIDT do not use registers operands. */
if (X86_MODRM_MOD(insn->modrm.value) == 3)
return -EINVAL;
@@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
else
dummy_base_addr = UMIP_DUMMY_IDT_BASE;
- *data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+ /*
+ * 64-bit processes use the entire dummy base address.
+ * 32-bit processes use the lower 32 bits of the base address.
+ * dummy_base_addr is always 64 bits, but we memcpy the correct
+ * number of bytes from it to the destination.
+ */
+ if (x86_64)
+ *data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT;
+ else
+ *data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT;
+
+ memcpy(data + 2, &dummy_base_addr, *data_size);
- memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+ *data_size += UMIP_GDT_IDT_LIMIT_SIZE;
memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
} else if (umip_inst == UMIP_INST_SMSW) {
- dummy_value = CR0_STATE;
+ unsigned long dummy_value = CR0_STATE;
/*
* Even though the CR0 register has 4 bytes, the number
@@ -290,11 +301,10 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
* fixup_umip_exception() - Fixup a general protection fault caused by UMIP
* @regs: Registers as saved when entering the #GP handler
*
- * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
- * fault if executed with CPL > 0 (i.e., from user space). If the offending
- * user-space process is not in long mode, this function fixes the exception
- * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
- * fixed up. Also long mode user-space processes are not fixed up.
+ * The instructions SGDT, SIDT, STR, SMSW and SLDT cause a general protection
+ * fault if executed with CPL > 0 (i.e., from user space). This function fixes
+ * the exception up and provides dummy results for SGDT, SIDT and SMSW; STR
+ * and SLDT are not fixed up.
*
* If operands are memory addresses, results are copied to user-space memory as
* indicated by the instruction pointed by eIP using the registers indicated in
@@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
umip_pr_warning(regs, "%s instruction cannot be used by applications.\n",
umip_insns[umip_inst]);
- /* Do not emulate SLDT, STR or user long mode processes. */
- if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
+ /* Do not emulate (spoof) SLDT or STR. */
+ if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT)
return false;
umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n");
- if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+ if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
+ user_64bit_mode(regs)))
return false;
/*
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index d8359ebeea70..8cd745ef8c7b 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -508,9 +508,12 @@ struct uprobe_xol_ops {
void (*abort)(struct arch_uprobe *, struct pt_regs *);
};
-static inline int sizeof_long(void)
+static inline int sizeof_long(struct pt_regs *regs)
{
- return in_ia32_syscall() ? 4 : 8;
+ /*
+ * Check registers for mode as in_xxx_syscall() does not apply here.
+ */
+ return user_64bit_mode(regs) ? 8 : 4;
}
static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
@@ -521,9 +524,9 @@ static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
static int emulate_push_stack(struct pt_regs *regs, unsigned long val)
{
- unsigned long new_sp = regs->sp - sizeof_long();
+ unsigned long new_sp = regs->sp - sizeof_long(regs);
- if (copy_to_user((void __user *)new_sp, &val, sizeof_long()))
+ if (copy_to_user((void __user *)new_sp, &val, sizeof_long(regs)))
return -EFAULT;
regs->sp = new_sp;
@@ -556,7 +559,7 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
long correction = utask->vaddr - utask->xol_vaddr;
regs->ip += correction;
} else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) {
- regs->sp += sizeof_long(); /* Pop incorrect return address */
+ regs->sp += sizeof_long(regs); /* Pop incorrect return address */
if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen))
return -ERESTART;
}
@@ -675,7 +678,7 @@ static int branch_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
* "call" insn was executed out-of-line. Just restore ->sp and restart.
* We could also restore ->ip and try to call branch_emulate_op() again.
*/
- regs->sp += sizeof_long();
+ regs->sp += sizeof_long(regs);
return -ERESTART;
}
@@ -1056,7 +1059,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
unsigned long
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
{
- int rasize = sizeof_long(), nleft;
+ int rasize = sizeof_long(regs), nleft;
unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize))
diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c
index 329361b69d5e..018aebce33ff 100644
--- a/arch/x86/kvm/debugfs.c
+++ b/arch/x86/kvm/debugfs.c
@@ -8,11 +8,6 @@
#include <linux/debugfs.h>
#include "lapic.h"
-bool kvm_arch_has_vcpu_debugfs(void)
-{
- return true;
-}
-
static int vcpu_get_timer_advance_ns(void *data, u64 *val)
{
struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
@@ -48,37 +43,22 @@ static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n");
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
{
- struct dentry *ret;
-
- ret = debugfs_create_file("tsc-offset", 0444,
- vcpu->debugfs_dentry,
- vcpu, &vcpu_tsc_offset_fops);
- if (!ret)
- return -ENOMEM;
+ debugfs_create_file("tsc-offset", 0444, vcpu->debugfs_dentry, vcpu,
+ &vcpu_tsc_offset_fops);
- if (lapic_in_kernel(vcpu)) {
- ret = debugfs_create_file("lapic_timer_advance_ns", 0444,
- vcpu->debugfs_dentry,
- vcpu, &vcpu_timer_advance_ns_fops);
- if (!ret)
- return -ENOMEM;
- }
+ if (lapic_in_kernel(vcpu))
+ debugfs_create_file("lapic_timer_advance_ns", 0444,
+ vcpu->debugfs_dentry, vcpu,
+ &vcpu_timer_advance_ns_fops);
if (kvm_has_tsc_control) {
- ret = debugfs_create_file("tsc-scaling-ratio", 0444,
- vcpu->debugfs_dentry,
- vcpu, &vcpu_tsc_scaling_fops);
- if (!ret)
- return -ENOMEM;
- ret = debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
- vcpu->debugfs_dentry,
- vcpu, &vcpu_tsc_scaling_frac_fops);
- if (!ret)
- return -ENOMEM;
-
+ debugfs_create_file("tsc-scaling-ratio", 0444,
+ vcpu->debugfs_dentry, vcpu,
+ &vcpu_tsc_scaling_fops);
+ debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
+ vcpu->debugfs_dentry, vcpu,
+ &vcpu_tsc_scaling_frac_fops);
}
-
- return 0;
}
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index c10a8b10b203..fff790a3f4ee 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1781,7 +1781,7 @@ int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args)
int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *entries)
{
- uint16_t evmcs_ver = kvm_x86_ops->nested_get_evmcs_version(vcpu);
+ uint16_t evmcs_ver = 0;
struct kvm_cpuid_entry2 cpuid_entries[] = {
{ .function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS },
{ .function = HYPERV_CPUID_INTERFACE },
@@ -1793,6 +1793,9 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
};
int i, nent = ARRAY_SIZE(cpuid_entries);
+ if (kvm_x86_ops->nested_get_evmcs_version)
+ evmcs_ver = kvm_x86_ops->nested_get_evmcs_version(vcpu);
+
/* Skip NESTED_FEATURES if eVMCS is not supported */
if (!evmcs_ver)
--nent;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index b9e516099d07..2a4f278f3b56 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -216,6 +216,9 @@ static void recalculate_apic_map(struct kvm *kvm)
if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
new->phys_map[xapic_id] = apic;
+ if (!kvm_apic_sw_enabled(apic))
+ continue;
+
ldr = kvm_lapic_get_reg(apic, APIC_LDR);
if (apic_x2apic_mode(apic)) {
@@ -258,6 +261,8 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
static_key_slow_dec_deferred(&apic_sw_disabled);
else
static_key_slow_inc(&apic_sw_disabled.key);
+
+ recalculate_apic_map(apic->vcpu->kvm);
}
}
@@ -1548,7 +1553,6 @@ static void kvm_apic_inject_pending_timer_irqs(struct kvm_lapic *apic)
static void apic_timer_expired(struct kvm_lapic *apic)
{
struct kvm_vcpu *vcpu = apic->vcpu;
- struct swait_queue_head *q = &vcpu->wq;
struct kvm_timer *ktimer = &apic->lapic_timer;
if (atomic_read(&apic->lapic_timer.pending))
@@ -1566,13 +1570,6 @@ static void apic_timer_expired(struct kvm_lapic *apic)
atomic_inc(&apic->lapic_timer.pending);
kvm_set_pending_timer(vcpu);
-
- /*
- * For x86, the atomic_inc() is serialized, thus
- * using swait_active() is safe.
- */
- if (swait_active(q))
- swake_up_one(q);
}
static void start_sw_tscdeadline(struct kvm_lapic *apic)
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 8f72526e2f68..a63964e7cec7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2095,6 +2095,12 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct
if (!direct)
sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache);
set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
+
+ /*
+ * active_mmu_pages must be a FIFO list, as kvm_zap_obsolete_pages()
+ * depends on valid pages being added to the head of the list. See
+ * comments in kvm_zap_obsolete_pages().
+ */
list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
kvm_mod_used_mmu_pages(vcpu->kvm, +1);
return sp;
@@ -2244,7 +2250,7 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
#define for_each_valid_sp(_kvm, _sp, _gfn) \
hlist_for_each_entry(_sp, \
&(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \
- if ((_sp)->role.invalid) { \
+ if (is_obsolete_sp((_kvm), (_sp)) || (_sp)->role.invalid) { \
} else
#define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn) \
@@ -2301,6 +2307,11 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, int point) { }
static void mmu_audit_disable(void) { }
#endif
+static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+ return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen);
+}
+
static bool kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
struct list_head *invalid_list)
{
@@ -2525,6 +2536,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
if (level > PT_PAGE_TABLE_LEVEL && need_sync)
flush |= kvm_sync_pages(vcpu, gfn, &invalid_list);
}
+ sp->mmu_valid_gen = vcpu->kvm->arch.mmu_valid_gen;
clear_page(sp->spt);
trace_kvm_mmu_get_page(sp, true);
@@ -3466,7 +3478,7 @@ static bool fast_page_fault(struct kvm_vcpu *vcpu, gva_t gva, int level,
/*
* Currently, fast page fault only works for direct mapping
* since the gfn is not stable for indirect shadow page. See
- * Documentation/virtual/kvm/locking.txt to get more detail.
+ * Documentation/virt/kvm/locking.txt to get more detail.
*/
fault_handled = fast_pf_fix_direct_spte(vcpu, sp,
iterator.sptep, spte,
@@ -4233,6 +4245,13 @@ static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3,
return false;
if (cached_root_available(vcpu, new_cr3, new_role)) {
+ /*
+ * It is possible that the cached previous root page is
+ * obsolete because of a change in the MMU generation
+ * number. However, changing the generation number is
+ * accompanied by KVM_REQ_MMU_RELOAD, which will free
+ * the root set here and allocate a new one.
+ */
kvm_make_request(KVM_REQ_LOAD_CR3, vcpu);
if (!skip_tlb_flush) {
kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
@@ -5649,44 +5668,91 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu)
return alloc_mmu_pages(vcpu);
}
-static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
- struct kvm_memory_slot *slot,
- struct kvm_page_track_notifier_node *node)
+
+static void kvm_zap_obsolete_pages(struct kvm *kvm)
{
- struct kvm_mmu_page *sp;
+ struct kvm_mmu_page *sp, *node;
LIST_HEAD(invalid_list);
- unsigned long i;
- bool flush;
- gfn_t gfn;
-
- spin_lock(&kvm->mmu_lock);
-
- if (list_empty(&kvm->arch.active_mmu_pages))
- goto out_unlock;
-
- flush = slot_handle_all_level(kvm, slot, kvm_zap_rmapp, false);
+ int ign;
- for (i = 0; i < slot->npages; i++) {
- gfn = slot->base_gfn + i;
+restart:
+ list_for_each_entry_safe_reverse(sp, node,
+ &kvm->arch.active_mmu_pages, link) {
+ /*
+ * No obsolete valid page exists before a newly created page
+ * since active_mmu_pages is a FIFO list.
+ */
+ if (!is_obsolete_sp(kvm, sp))
+ break;
- for_each_valid_sp(kvm, sp, gfn) {
- if (sp->gfn != gfn)
- continue;
+ /*
+ * Do not repeatedly zap a root page to avoid unnecessary
+ * KVM_REQ_MMU_RELOAD, otherwise we may not be able to
+ * progress:
+ * vcpu 0 vcpu 1
+ * call vcpu_enter_guest():
+ * 1): handle KVM_REQ_MMU_RELOAD
+ * and require mmu-lock to
+ * load mmu
+ * repeat:
+ * 1): zap root page and
+ * send KVM_REQ_MMU_RELOAD
+ *
+ * 2): if (cond_resched_lock(mmu-lock))
+ *
+ * 2): hold mmu-lock and load mmu
+ *
+ * 3): see KVM_REQ_MMU_RELOAD bit
+ * on vcpu->requests is set
+ * then return 1 to call
+ * vcpu_enter_guest() again.
+ * goto repeat;
+ *
+ * Since we are reversely walking the list and the invalid
+ * list will be moved to the head, skip the invalid page
+ * can help us to avoid the infinity list walking.
+ */
+ if (sp->role.invalid)
+ continue;
- kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list);
- }
if (need_resched() || spin_needbreak(&kvm->mmu_lock)) {
- kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
- flush = false;
+ kvm_mmu_commit_zap_page(kvm, &invalid_list);
cond_resched_lock(&kvm->mmu_lock);
+ goto restart;
}
+
+ if (__kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list, &ign))
+ goto restart;
}
- kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
-out_unlock:
+ kvm_mmu_commit_zap_page(kvm, &invalid_list);
+}
+
+/*
+ * Fast invalidate all shadow pages and use lock-break technique
+ * to zap obsolete pages.
+ *
+ * It's required when memslot is being deleted or VM is being
+ * destroyed, in these cases, we should ensure that KVM MMU does
+ * not use any resource of the being-deleted slot or all slots
+ * after calling the function.
+ */
+static void kvm_mmu_zap_all_fast(struct kvm *kvm)
+{
+ spin_lock(&kvm->mmu_lock);
+ kvm->arch.mmu_valid_gen++;
+
+ kvm_zap_obsolete_pages(kvm);
spin_unlock(&kvm->mmu_lock);
}
+static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
+ struct kvm_memory_slot *slot,
+ struct kvm_page_track_notifier_node *node)
+{
+ kvm_mmu_zap_all_fast(kvm);
+}
+
void kvm_mmu_init_vm(struct kvm *kvm)
{
struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 19f69df96758..e0368076a1ef 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1714,7 +1714,6 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
if (!entry)
return -EINVAL;
- new_entry = READ_ONCE(*entry);
new_entry = __sme_set((page_to_phys(svm->avic_backing_page) &
AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
AVIC_PHYSICAL_ID_ENTRY_VALID_MASK);
@@ -2143,12 +2142,20 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
goto out;
}
+ svm->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache,
+ GFP_KERNEL_ACCOUNT);
+ if (!svm->vcpu.arch.user_fpu) {
+ printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n");
+ err = -ENOMEM;
+ goto free_partial_svm;
+ }
+
svm->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache,
GFP_KERNEL_ACCOUNT);
if (!svm->vcpu.arch.guest_fpu) {
printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n");
err = -ENOMEM;
- goto free_partial_svm;
+ goto free_user_fpu;
}
err = kvm_vcpu_init(&svm->vcpu, kvm, id);
@@ -2211,6 +2218,8 @@ uninit:
kvm_vcpu_uninit(&svm->vcpu);
free_svm:
kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu);
+free_user_fpu:
+ kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu);
free_partial_svm:
kmem_cache_free(kvm_vcpu_cache, svm);
out:
@@ -2241,6 +2250,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
__free_page(virt_to_page(svm->nested.hsave));
__free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu);
kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu);
kmem_cache_free(kvm_vcpu_cache, svm);
}
@@ -5179,6 +5189,11 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
kvm_vcpu_wake_up(vcpu);
}
+static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
static void svm_ir_list_del(struct vcpu_svm *svm, struct amd_iommu_pi_data *pi)
{
unsigned long flags;
@@ -7113,12 +7128,6 @@ failed:
return ret;
}
-static uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu)
-{
- /* Not supported */
- return 0;
-}
-
static int nested_enable_evmcs(struct kvm_vcpu *vcpu,
uint16_t *vmcs_version)
{
@@ -7303,6 +7312,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.pmu_ops = &amd_pmu_ops,
.deliver_posted_interrupt = svm_deliver_avic_intr,
+ .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt,
.update_pi_irte = svm_update_pi_irte,
.setup_mce = svm_setup_mce,
@@ -7316,7 +7326,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.mem_enc_unreg_region = svm_unregister_enc_region,
.nested_enable_evmcs = nested_enable_evmcs,
- .nested_get_evmcs_version = nested_get_evmcs_version,
+ .nested_get_evmcs_version = NULL,
.need_emulation_on_page_fault = svm_need_emulation_on_page_fault,
};
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 0f1378789bd0..a3cba321b5c5 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -220,6 +220,8 @@ static void free_nested(struct kvm_vcpu *vcpu)
if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
return;
+ kvm_clear_request(KVM_REQ_GET_VMCS12_PAGES, vcpu);
+
vmx->nested.vmxon = false;
vmx->nested.smm.vmxon = false;
free_vpid(vmx->nested.vpid02);
@@ -232,7 +234,9 @@ static void free_nested(struct kvm_vcpu *vcpu)
vmx->vmcs01.shadow_vmcs = NULL;
}
kfree(vmx->nested.cached_vmcs12);
+ vmx->nested.cached_vmcs12 = NULL;
kfree(vmx->nested.cached_shadow_vmcs12);
+ vmx->nested.cached_shadow_vmcs12 = NULL;
/* Unpin physical memory we referred to in the vmcs02 */
if (vmx->nested.apic_access_page) {
kvm_release_page_dirty(vmx->nested.apic_access_page);
@@ -4536,6 +4540,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
int len;
gva_t gva = 0;
struct vmcs12 *vmcs12;
+ struct x86_exception e;
short offset;
if (!nested_vmx_check_permission(vcpu))
@@ -4584,7 +4589,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
vmx_instruction_info, true, len, &gva))
return 1;
/* _system ok, nested_vmx_check_permission has verified cpl=0 */
- kvm_write_guest_virt_system(vcpu, gva, &field_value, len, NULL);
+ if (kvm_write_guest_virt_system(vcpu, gva, &field_value, len, &e))
+ kvm_inject_page_fault(vcpu, &e);
}
return nested_vmx_succeed(vcpu);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index a279447eb75b..c030c96fc81a 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6117,6 +6117,11 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
return max_irr;
}
+static bool vmx_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+ return pi_test_on(vcpu_to_pi_desc(vcpu));
+}
+
static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
{
if (!kvm_vcpu_apicv_active(vcpu))
@@ -6598,6 +6603,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
free_loaded_vmcs(vmx->loaded_vmcs);
kfree(vmx->guest_msrs);
kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu);
kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu);
kmem_cache_free(kvm_vcpu_cache, vmx);
}
@@ -6613,12 +6619,20 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
if (!vmx)
return ERR_PTR(-ENOMEM);
+ vmx->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache,
+ GFP_KERNEL_ACCOUNT);
+ if (!vmx->vcpu.arch.user_fpu) {
+ printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n");
+ err = -ENOMEM;
+ goto free_partial_vcpu;
+ }
+
vmx->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache,
GFP_KERNEL_ACCOUNT);
if (!vmx->vcpu.arch.guest_fpu) {
printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n");
err = -ENOMEM;
- goto free_partial_vcpu;
+ goto free_user_fpu;
}
vmx->vpid = allocate_vpid();
@@ -6721,6 +6735,8 @@ uninit_vcpu:
free_vcpu:
free_vpid(vmx->vpid);
kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu);
+free_user_fpu:
+ kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu);
free_partial_vcpu:
kmem_cache_free(kvm_vcpu_cache, vmx);
return ERR_PTR(err);
@@ -7715,6 +7731,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
.sync_pir_to_irr = vmx_sync_pir_to_irr,
.deliver_posted_interrupt = vmx_deliver_posted_interrupt,
+ .dy_apicv_has_pending_interrupt = vmx_dy_apicv_has_pending_interrupt,
.set_tss_addr = vmx_set_tss_addr,
.set_identity_map_addr = vmx_set_identity_map_addr,
@@ -7780,6 +7797,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.set_nested_state = NULL,
.get_vmcs12_pages = NULL,
.nested_enable_evmcs = NULL,
+ .nested_get_evmcs_version = NULL,
.need_emulation_on_page_fault = vmx_need_emulation_on_page_fault,
};
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 58305cf81182..91602d310a3f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3306,6 +3306,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_x86_ops->vcpu_load(vcpu, cpu);
+ fpregs_assert_state_consistent();
+ if (test_thread_flag(TIF_NEED_FPU_LOAD))
+ switch_fpu_return();
+
/* Apply any externally detected TSC adjustments (due to suspend) */
if (unlikely(vcpu->arch.tsc_offset_adjustment)) {
adjust_tsc_offset_host(vcpu, vcpu->arch.tsc_offset_adjustment);
@@ -5308,6 +5312,13 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
/* kvm_write_guest_virt_system can pull in tons of pages. */
vcpu->arch.l1tf_flush_l1d = true;
+ /*
+ * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
+ * is returned, but our callers are not ready for that and they blindly
+ * call kvm_inject_page_fault. Ensure that they at least do not leak
+ * uninitialized kernel stack memory into cr2 and error code.
+ */
+ memset(exception, 0, sizeof(*exception));
return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
PFERR_WRITE_MASK, exception);
}
@@ -6590,12 +6601,13 @@ restart:
unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
toggle_interruptibility(vcpu, ctxt->interruptibility);
vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
- kvm_rip_write(vcpu, ctxt->eip);
- if (r == EMULATE_DONE && ctxt->tf)
- kvm_vcpu_do_singlestep(vcpu, &r);
if (!ctxt->have_exception ||
- exception_type(ctxt->exception.vector) == EXCPT_TRAP)
+ exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
+ kvm_rip_write(vcpu, ctxt->eip);
+ if (r == EMULATE_DONE && ctxt->tf)
+ kvm_vcpu_do_singlestep(vcpu, &r);
__kvm_set_rflags(vcpu, ctxt->eflags);
+ }
/*
* For STI, interrupts are shadowed; so KVM_REQ_EVENT will
@@ -7202,7 +7214,7 @@ static void kvm_sched_yield(struct kvm *kvm, unsigned long dest_id)
rcu_read_unlock();
- if (target)
+ if (target && READ_ONCE(target->ready))
kvm_vcpu_yield_to(target);
}
@@ -7242,6 +7254,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
break;
case KVM_HC_KICK_CPU:
kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
+ kvm_sched_yield(vcpu->kvm, a1);
ret = 0;
break;
#ifdef CONFIG_X86_64
@@ -7990,9 +8003,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
trace_kvm_entry(vcpu->vcpu_id);
guest_enter_irqoff();
- fpregs_assert_state_consistent();
- if (test_thread_flag(TIF_NEED_FPU_LOAD))
- switch_fpu_return();
+ /* The preempt notifier should have taken care of the FPU already. */
+ WARN_ON_ONCE(test_thread_flag(TIF_NEED_FPU_LOAD));
if (unlikely(vcpu->arch.switch_db_regs)) {
set_debugreg(0, 7);
@@ -8270,7 +8282,7 @@ static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
{
fpregs_lock();
- copy_fpregs_to_fpstate(&current->thread.fpu);
+ copy_fpregs_to_fpstate(vcpu->arch.user_fpu);
/* PKRU is separately restored in kvm_x86_ops->run. */
__copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state,
~XFEATURE_MASK_PKRU);
@@ -8287,7 +8299,7 @@ static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
fpregs_lock();
copy_fpregs_to_fpstate(vcpu->arch.guest_fpu);
- copy_kernel_to_fpregs(&current->thread.fpu.state);
+ copy_kernel_to_fpregs(&vcpu->arch.user_fpu->state);
fpregs_mark_activate();
fpregs_unlock();
@@ -9694,6 +9706,22 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
}
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+ if (READ_ONCE(vcpu->arch.pv.pv_unhalted))
+ return true;
+
+ if (kvm_test_request(KVM_REQ_NMI, vcpu) ||
+ kvm_test_request(KVM_REQ_SMI, vcpu) ||
+ kvm_test_request(KVM_REQ_EVENT, vcpu))
+ return true;
+
+ if (vcpu->arch.apicv_active && kvm_x86_ops->dy_apicv_has_pending_interrupt(vcpu))
+ return true;
+
+ return false;
+}
+
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
{
return vcpu->arch.preempted_in_kernel;
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 4fe1601dbc5d..86976b55ae74 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -33,7 +33,7 @@
102:
.section .fixup,"ax"
103: addl %ecx,%edx /* ecx is zerorest also */
- jmp copy_user_handle_tail
+ jmp .Lcopy_user_handle_tail
.previous
_ASM_EXTABLE_UA(100b, 103b)
@@ -113,7 +113,7 @@ ENTRY(copy_user_generic_unrolled)
40: leal (%rdx,%rcx,8),%edx
jmp 60f
50: movl %ecx,%edx
-60: jmp copy_user_handle_tail /* ecx is zerorest also */
+60: jmp .Lcopy_user_handle_tail /* ecx is zerorest also */
.previous
_ASM_EXTABLE_UA(1b, 30b)
@@ -177,7 +177,7 @@ ENTRY(copy_user_generic_string)
.section .fixup,"ax"
11: leal (%rdx,%rcx,8),%ecx
12: movl %ecx,%edx /* ecx is zerorest also */
- jmp copy_user_handle_tail
+ jmp .Lcopy_user_handle_tail
.previous
_ASM_EXTABLE_UA(1b, 11b)
@@ -210,7 +210,7 @@ ENTRY(copy_user_enhanced_fast_string)
.section .fixup,"ax"
12: movl %ecx,%edx /* ecx is zerorest also */
- jmp copy_user_handle_tail
+ jmp .Lcopy_user_handle_tail
.previous
_ASM_EXTABLE_UA(1b, 12b)
@@ -231,7 +231,7 @@ EXPORT_SYMBOL(copy_user_enhanced_fast_string)
* eax uncopied bytes or 0 if successful.
*/
ALIGN;
-copy_user_handle_tail:
+.Lcopy_user_handle_tail:
movl %edx,%ecx
1: rep movsb
2: mov %ecx,%eax
@@ -239,7 +239,7 @@ copy_user_handle_tail:
ret
_ASM_EXTABLE_UA(1b, 2b)
-END(copy_user_handle_tail)
+END(.Lcopy_user_handle_tail)
/*
* copy_user_nocache - Uncached memory copy with exception handling
@@ -364,7 +364,7 @@ ENTRY(__copy_user_nocache)
movl %ecx,%edx
.L_fixup_handle_tail:
sfence
- jmp copy_user_handle_tail
+ jmp .Lcopy_user_handle_tail
.previous
_ASM_EXTABLE_UA(1b, .L_fixup_4x8b_copy)
diff --git a/arch/x86/lib/cpu.c b/arch/x86/lib/cpu.c
index 04967cdce5d1..7ad68917a51e 100644
--- a/arch/x86/lib/cpu.c
+++ b/arch/x86/lib/cpu.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/types.h>
#include <linux/export.h>
+#include <asm/cpu.h>
unsigned int x86_family(unsigned int sig)
{
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index 304f958c27b2..9578eb88fc87 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -115,7 +115,7 @@ ENDPROC(__get_user_8)
EXPORT_SYMBOL(__get_user_8)
-bad_get_user_clac:
+.Lbad_get_user_clac:
ASM_CLAC
bad_get_user:
xor %edx,%edx
@@ -123,7 +123,7 @@ bad_get_user:
ret
#ifdef CONFIG_X86_32
-bad_get_user_8_clac:
+.Lbad_get_user_8_clac:
ASM_CLAC
bad_get_user_8:
xor %edx,%edx
@@ -132,12 +132,12 @@ bad_get_user_8:
ret
#endif
- _ASM_EXTABLE_UA(1b, bad_get_user_clac)
- _ASM_EXTABLE_UA(2b, bad_get_user_clac)
- _ASM_EXTABLE_UA(3b, bad_get_user_clac)
+ _ASM_EXTABLE_UA(1b, .Lbad_get_user_clac)
+ _ASM_EXTABLE_UA(2b, .Lbad_get_user_clac)
+ _ASM_EXTABLE_UA(3b, .Lbad_get_user_clac)
#ifdef CONFIG_X86_64
- _ASM_EXTABLE_UA(4b, bad_get_user_clac)
+ _ASM_EXTABLE_UA(4b, .Lbad_get_user_clac)
#else
- _ASM_EXTABLE_UA(4b, bad_get_user_8_clac)
- _ASM_EXTABLE_UA(5b, bad_get_user_8_clac)
+ _ASM_EXTABLE_UA(4b, .Lbad_get_user_8_clac)
+ _ASM_EXTABLE_UA(5b, .Lbad_get_user_8_clac)
#endif
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index 14bf78341d3c..126dd6a9ec9b 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -37,7 +37,7 @@
ENTRY(__put_user_1)
ENTER
cmp TASK_addr_limit(%_ASM_BX),%_ASM_CX
- jae bad_put_user
+ jae .Lbad_put_user
ASM_STAC
1: movb %al,(%_ASM_CX)
xor %eax,%eax
@@ -51,7 +51,7 @@ ENTRY(__put_user_2)
mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
sub $1,%_ASM_BX
cmp %_ASM_BX,%_ASM_CX
- jae bad_put_user
+ jae .Lbad_put_user
ASM_STAC
2: movw %ax,(%_ASM_CX)
xor %eax,%eax
@@ -65,7 +65,7 @@ ENTRY(__put_user_4)
mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
sub $3,%_ASM_BX
cmp %_ASM_BX,%_ASM_CX
- jae bad_put_user
+ jae .Lbad_put_user
ASM_STAC
3: movl %eax,(%_ASM_CX)
xor %eax,%eax
@@ -79,7 +79,7 @@ ENTRY(__put_user_8)
mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
sub $7,%_ASM_BX
cmp %_ASM_BX,%_ASM_CX
- jae bad_put_user
+ jae .Lbad_put_user
ASM_STAC
4: mov %_ASM_AX,(%_ASM_CX)
#ifdef CONFIG_X86_32
@@ -91,16 +91,16 @@ ENTRY(__put_user_8)
ENDPROC(__put_user_8)
EXPORT_SYMBOL(__put_user_8)
-bad_put_user_clac:
+.Lbad_put_user_clac:
ASM_CLAC
-bad_put_user:
+.Lbad_put_user:
movl $-EFAULT,%eax
RET
- _ASM_EXTABLE_UA(1b, bad_put_user_clac)
- _ASM_EXTABLE_UA(2b, bad_put_user_clac)
- _ASM_EXTABLE_UA(3b, bad_put_user_clac)
- _ASM_EXTABLE_UA(4b, bad_put_user_clac)
+ _ASM_EXTABLE_UA(1b, .Lbad_put_user_clac)
+ _ASM_EXTABLE_UA(2b, .Lbad_put_user_clac)
+ _ASM_EXTABLE_UA(3b, .Lbad_put_user_clac)
+ _ASM_EXTABLE_UA(4b, .Lbad_put_user_clac)
#ifdef CONFIG_X86_32
- _ASM_EXTABLE_UA(5b, bad_put_user_clac)
+ _ASM_EXTABLE_UA(5b, .Lbad_put_user_clac)
#endif
diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c
index 6b468517ab71..73dc66d887f3 100644
--- a/arch/x86/math-emu/errors.c
+++ b/arch/x86/math-emu/errors.c
@@ -178,13 +178,15 @@ void FPU_printall(void)
for (i = 0; i < 8; i++) {
FPU_REG *r = &st(i);
u_char tagi = FPU_gettagi(i);
+
switch (tagi) {
case TAG_Empty:
continue;
- break;
case TAG_Zero:
case TAG_Special:
+ /* Update tagi for the printk below */
tagi = FPU_Special(r);
+ /* fall through */
case TAG_Valid:
printk("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
getsign(r) ? '-' : '+',
@@ -198,7 +200,6 @@ void FPU_printall(void)
printk("Whoops! Error in errors.c: tag%d is %d ", i,
tagi);
continue;
- break;
}
printk("%s\n", tag_desc[(int)(unsigned)tagi]);
}
diff --git a/arch/x86/math-emu/fpu_trig.c b/arch/x86/math-emu/fpu_trig.c
index 783c509f957a..127ea54122d7 100644
--- a/arch/x86/math-emu/fpu_trig.c
+++ b/arch/x86/math-emu/fpu_trig.c
@@ -1352,7 +1352,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
case TW_Denormal:
if (denormal_operand() < 0)
return;
-
+ /* fall through */
case TAG_Zero:
case TAG_Valid:
setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 6c46095cd0d9..9ceacd1156db 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -177,13 +177,14 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
- if (!pmd_present(*pmd_k))
- return NULL;
- if (!pmd_present(*pmd))
+ if (pmd_present(*pmd) != pmd_present(*pmd_k))
set_pmd(pmd, *pmd_k);
+
+ if (!pmd_present(*pmd_k))
+ return NULL;
else
- BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+ BUG_ON(pmd_pfn(*pmd) != pmd_pfn(*pmd_k));
return pmd_k;
}
@@ -203,17 +204,13 @@ void vmalloc_sync_all(void)
spin_lock(&pgd_lock);
list_for_each_entry(page, &pgd_list, lru) {
spinlock_t *pgt_lock;
- pmd_t *ret;
/* the pgt_lock only for Xen */
pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
spin_lock(pgt_lock);
- ret = vmalloc_sync_one(page_address(page), address);
+ vmalloc_sync_one(page_address(page), address);
spin_unlock(pgt_lock);
-
- if (!ret)
- break;
}
spin_unlock(&pgd_lock);
}
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 4068abb9427f..930edeb41ec3 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -916,7 +916,7 @@ static void mark_nxdata_nx(void)
if (__supported_pte_mask & _PAGE_NX)
printk(KERN_INFO "NX-protecting the kernel data: %luk\n", size >> 10);
- set_pages_nx(virt_to_page(start), size >> PAGE_SHIFT);
+ set_memory_nx(start, size >> PAGE_SHIFT);
}
void mark_rodata_ro(void)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 63e99f15d7cf..a39dcdb5ae34 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -19,6 +19,7 @@
#include <asm/set_memory.h>
#include <asm/e820/api.h>
+#include <asm/efi.h>
#include <asm/fixmap.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index e6dad600614c..4123100e0eaf 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -861,9 +861,9 @@ void numa_remove_cpu(int cpu)
*/
const struct cpumask *cpumask_of_node(int node)
{
- if (node >= nr_node_ids) {
+ if ((unsigned)node >= nr_node_ids) {
printk(KERN_WARNING
- "cpumask_of_node(%d): node > nr_node_ids(%u)\n",
+ "cpumask_of_node(%d): (unsigned)node >= nr_node_ids(%u)\n",
node, nr_node_ids);
dump_stack();
return cpu_none_mask;
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 6a9a77a403c9..0d09cc5aad61 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -516,7 +516,7 @@ static inline void check_conflict(int warnlvl, pgprot_t prot, pgprotval_t val,
*/
static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
unsigned long pfn, unsigned long npg,
- int warnlvl)
+ unsigned long lpsize, int warnlvl)
{
pgprotval_t forbidden, res;
unsigned long end;
@@ -535,9 +535,17 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX");
forbidden = res;
- res = protect_kernel_text_ro(start, end);
- check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO");
- forbidden |= res;
+ /*
+ * Special case to preserve a large page. If the change spawns the
+ * full large page mapping then there is no point to split it
+ * up. Happens with ftrace and is going to be removed once ftrace
+ * switched to text_poke().
+ */
+ if (lpsize != (npg * PAGE_SIZE) || (start & (lpsize - 1))) {
+ res = protect_kernel_text_ro(start, end);
+ check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO");
+ forbidden |= res;
+ }
/* Check the PFN directly */
res = protect_pci_bios(pfn, pfn + npg - 1);
@@ -819,7 +827,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
* extra conditional required here.
*/
chk_prot = static_protections(old_prot, lpaddr, old_pfn, numpages,
- CPA_CONFLICT);
+ psize, CPA_CONFLICT);
if (WARN_ON_ONCE(pgprot_val(chk_prot) != pgprot_val(old_prot))) {
/*
@@ -855,7 +863,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
* protection requirement in the large page.
*/
new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages,
- CPA_DETECT);
+ psize, CPA_DETECT);
/*
* If there is a conflict, split the large page.
@@ -906,7 +914,8 @@ static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
if (!cpa->force_static_prot)
goto set;
- prot = static_protections(ref_prot, address, pfn, npg, CPA_PROTECT);
+ /* Hand in lpsize = 0 to enforce the protection mechanism */
+ prot = static_protections(ref_prot, address, pfn, npg, 0, CPA_PROTECT);
if (pgprot_val(prot) == pgprot_val(ref_prot))
goto set;
@@ -1503,7 +1512,8 @@ repeat:
pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
cpa_inc_4k_install();
- new_prot = static_protections(new_prot, address, pfn, 1,
+ /* Hand in lpsize = 0 to enforce the protection mechanism */
+ new_prot = static_protections(new_prot, address, pfn, 1, 0,
CPA_PROTECT);
new_prot = pgprot_clear_protnone_bits(new_prot);
@@ -1809,63 +1819,6 @@ out_err:
}
EXPORT_SYMBOL(set_memory_uc);
-static int _set_memory_array(unsigned long *addr, int numpages,
- enum page_cache_mode new_type)
-{
- enum page_cache_mode set_type;
- int i, j;
- int ret;
-
- for (i = 0; i < numpages; i++) {
- ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE,
- new_type, NULL);
- if (ret)
- goto out_free;
- }
-
- /* If WC, set to UC- first and then WC */
- set_type = (new_type == _PAGE_CACHE_MODE_WC) ?
- _PAGE_CACHE_MODE_UC_MINUS : new_type;
-
- ret = change_page_attr_set(addr, numpages,
- cachemode2pgprot(set_type), 1);
-
- if (!ret && new_type == _PAGE_CACHE_MODE_WC)
- ret = change_page_attr_set_clr(addr, numpages,
- cachemode2pgprot(
- _PAGE_CACHE_MODE_WC),
- __pgprot(_PAGE_CACHE_MASK),
- 0, CPA_ARRAY, NULL);
- if (ret)
- goto out_free;
-
- return 0;
-
-out_free:
- for (j = 0; j < i; j++)
- free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE);
-
- return ret;
-}
-
-int set_memory_array_uc(unsigned long *addr, int numpages)
-{
- return _set_memory_array(addr, numpages, _PAGE_CACHE_MODE_UC_MINUS);
-}
-EXPORT_SYMBOL(set_memory_array_uc);
-
-int set_memory_array_wc(unsigned long *addr, int numpages)
-{
- return _set_memory_array(addr, numpages, _PAGE_CACHE_MODE_WC);
-}
-EXPORT_SYMBOL(set_memory_array_wc);
-
-int set_memory_array_wt(unsigned long *addr, int numpages)
-{
- return _set_memory_array(addr, numpages, _PAGE_CACHE_MODE_WT);
-}
-EXPORT_SYMBOL_GPL(set_memory_array_wt);
-
int _set_memory_wc(unsigned long addr, int numpages)
{
int ret;
@@ -1905,23 +1858,6 @@ int _set_memory_wt(unsigned long addr, int numpages)
cachemode2pgprot(_PAGE_CACHE_MODE_WT), 0);
}
-int set_memory_wt(unsigned long addr, int numpages)
-{
- int ret;
-
- ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
- _PAGE_CACHE_MODE_WT, NULL);
- if (ret)
- return ret;
-
- ret = _set_memory_wt(addr, numpages);
- if (ret)
- free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(set_memory_wt);
-
int _set_memory_wb(unsigned long addr, int numpages)
{
/* WB cache mode is hard wired to all cache attribute bits being 0 */
@@ -1942,24 +1878,6 @@ int set_memory_wb(unsigned long addr, int numpages)
}
EXPORT_SYMBOL(set_memory_wb);
-int set_memory_array_wb(unsigned long *addr, int numpages)
-{
- int i;
- int ret;
-
- /* WB cache mode is hard wired to all cache attribute bits being 0 */
- ret = change_page_attr_clear(addr, numpages,
- __pgprot(_PAGE_CACHE_MASK), 1);
- if (ret)
- return ret;
-
- for (i = 0; i < numpages; i++)
- free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE);
-
- return 0;
-}
-EXPORT_SYMBOL(set_memory_array_wb);
-
int set_memory_x(unsigned long addr, int numpages)
{
if (!(__supported_pte_mask & _PAGE_NX))
@@ -1967,7 +1885,6 @@ int set_memory_x(unsigned long addr, int numpages)
return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0);
}
-EXPORT_SYMBOL(set_memory_x);
int set_memory_nx(unsigned long addr, int numpages)
{
@@ -1976,7 +1893,6 @@ int set_memory_nx(unsigned long addr, int numpages)
return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0);
}
-EXPORT_SYMBOL(set_memory_nx);
int set_memory_ro(unsigned long addr, int numpages)
{
@@ -2180,22 +2096,6 @@ int set_pages_array_wb(struct page **pages, int numpages)
}
EXPORT_SYMBOL(set_pages_array_wb);
-int set_pages_x(struct page *page, int numpages)
-{
- unsigned long addr = (unsigned long)page_address(page);
-
- return set_memory_x(addr, numpages);
-}
-EXPORT_SYMBOL(set_pages_x);
-
-int set_pages_nx(struct page *page, int numpages)
-{
- unsigned long addr = (unsigned long)page_address(page);
-
- return set_memory_nx(addr, numpages);
-}
-EXPORT_SYMBOL(set_pages_nx);
-
int set_pages_ro(struct page *page, int numpages)
{
unsigned long addr = (unsigned long)page_address(page);
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index b196524759ec..7f2140414440 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -330,13 +330,15 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
pud = pud_offset(p4d, addr);
if (pud_none(*pud)) {
- addr += PUD_SIZE;
+ WARN_ON_ONCE(addr & ~PUD_MASK);
+ addr = round_up(addr + 1, PUD_SIZE);
continue;
}
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
- addr += PMD_SIZE;
+ WARN_ON_ONCE(addr & ~PMD_MASK);
+ addr = round_up(addr + 1, PMD_SIZE);
continue;
}
@@ -666,6 +668,8 @@ void __init pti_init(void)
*/
void pti_finalize(void)
{
+ if (!boot_cpu_has(X86_FEATURE_PTI))
+ return;
/*
* We need to clone everything (again) that maps parts of the
* kernel image.
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 4de9704c4aaf..e6a9edc5baaf 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -440,7 +440,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid);
if (next != real_prev) {
- load_mm_cr4(next);
+ load_mm_cr4_irqsoff(next);
switch_ldt(real_prev, next);
}
}
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index eaaed5bfc4a4..991549a1c5f3 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -390,8 +390,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
emit_prologue(&prog, bpf_prog->aux->stack_depth,
bpf_prog_was_classic(bpf_prog));
+ addrs[0] = prog - temp;
- for (i = 0; i < insn_cnt; i++, insn++) {
+ for (i = 1; i <= insn_cnt; i++, insn++) {
const s32 imm32 = insn->imm;
u32 dst_reg = insn->dst_reg;
u32 src_reg = insn->src_reg;
@@ -1105,7 +1106,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
extra_pass = true;
goto skip_init_addrs;
}
- addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
+ addrs = kmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
if (!addrs) {
prog = orig_prog;
goto out_addrs;
@@ -1115,7 +1116,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
* Before first pass, make a rough estimation of addrs[]
* each BPF instruction is translated to less than 64 bytes
*/
- for (proglen = 0, i = 0; i < prog->len; i++) {
+ for (proglen = 0, i = 0; i <= prog->len; i++) {
proglen += 64;
addrs[i] = proglen;
}
@@ -1180,7 +1181,7 @@ out_image:
if (!image || !prog->is_func || extra_pass) {
if (image)
- bpf_prog_fill_jited_linfo(prog, addrs);
+ bpf_prog_fill_jited_linfo(prog, addrs + 1);
out_addrs:
kfree(addrs);
kfree(jit_data);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 7389db538c30..6fa42e9c4e6f 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -29,6 +29,7 @@
static bool pci_mmcfg_running_state;
static bool pci_mmcfg_arch_init_failed;
static DEFINE_MUTEX(pci_mmcfg_lock);
+#define pci_mmcfg_lock_held() lock_is_held(&(pci_mmcfg_lock).dep_map)
LIST_HEAD(pci_mmcfg_list);
@@ -54,7 +55,7 @@ static void list_add_sorted(struct pci_mmcfg_region *new)
struct pci_mmcfg_region *cfg;
/* keep list sorted by segment and starting bus number */
- list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
+ list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list, pci_mmcfg_lock_held()) {
if (cfg->segment > new->segment ||
(cfg->segment == new->segment &&
cfg->start_bus >= new->start_bus)) {
@@ -118,7 +119,7 @@ struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
{
struct pci_mmcfg_region *cfg;
- list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
+ list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list, pci_mmcfg_lock_held())
if (cfg->segment == segment &&
cfg->start_bus <= bus && bus <= cfg->end_bus)
return cfg;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index a7189a3b4d70..c202e1b07e29 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -59,11 +59,34 @@ static efi_system_table_t efi_systab __initdata;
static efi_config_table_type_t arch_tables[] __initdata = {
#ifdef CONFIG_X86_UV
- {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab},
+ {UV_SYSTEM_TABLE_GUID, "UVsystab", &uv_systab_phys},
#endif
{NULL_GUID, NULL, NULL},
};
+static const unsigned long * const efi_tables[] = {
+ &efi.mps,
+ &efi.acpi,
+ &efi.acpi20,
+ &efi.smbios,
+ &efi.smbios3,
+ &efi.boot_info,
+ &efi.hcdp,
+ &efi.uga,
+#ifdef CONFIG_X86_UV
+ &uv_systab_phys,
+#endif
+ &efi.fw_vendor,
+ &efi.runtime,
+ &efi.config_table,
+ &efi.esrt,
+ &efi.properties_table,
+ &efi.mem_attr_table,
+#ifdef CONFIG_EFI_RCI2_TABLE
+ &rci2_table_phys,
+#endif
+};
+
u64 efi_setup; /* efi setup_data physical address */
static int add_efi_memmap __initdata;
@@ -1049,3 +1072,17 @@ static int __init arch_parse_efi_cmdline(char *str)
return 0;
}
early_param("efi", arch_parse_efi_cmdline);
+
+bool efi_is_table_address(unsigned long phys_addr)
+{
+ unsigned int i;
+
+ if (phys_addr == EFI_INVALID_TABLE_ADDR)
+ return false;
+
+ for (i = 0; i < ARRAY_SIZE(efi_tables); i++)
+ if (*(efi_tables[i]) == phys_addr)
+ return true;
+
+ return false;
+}
diff --git a/arch/x86/platform/intel/iosf_mbi.c b/arch/x86/platform/intel/iosf_mbi.c
index 2e796b54cbde..9e2444500428 100644
--- a/arch/x86/platform/intel/iosf_mbi.c
+++ b/arch/x86/platform/intel/iosf_mbi.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include <linux/capability.h>
#include <linux/pm_qos.h>
+#include <linux/wait.h>
#include <asm/iosf_mbi.h>
@@ -201,23 +202,45 @@ EXPORT_SYMBOL(iosf_mbi_available);
#define PUNIT_SEMAPHORE_BIT BIT(0)
#define PUNIT_SEMAPHORE_ACQUIRE BIT(1)
-static DEFINE_MUTEX(iosf_mbi_punit_mutex);
-static DEFINE_MUTEX(iosf_mbi_block_punit_i2c_access_count_mutex);
+static DEFINE_MUTEX(iosf_mbi_pmic_access_mutex);
static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier);
-static u32 iosf_mbi_block_punit_i2c_access_count;
+static DECLARE_WAIT_QUEUE_HEAD(iosf_mbi_pmic_access_waitq);
+static u32 iosf_mbi_pmic_punit_access_count;
+static u32 iosf_mbi_pmic_i2c_access_count;
static u32 iosf_mbi_sem_address;
static unsigned long iosf_mbi_sem_acquired;
static struct pm_qos_request iosf_mbi_pm_qos;
void iosf_mbi_punit_acquire(void)
{
- mutex_lock(&iosf_mbi_punit_mutex);
+ /* Wait for any I2C PMIC accesses from in kernel drivers to finish. */
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
+ while (iosf_mbi_pmic_i2c_access_count != 0) {
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
+ wait_event(iosf_mbi_pmic_access_waitq,
+ iosf_mbi_pmic_i2c_access_count == 0);
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
+ }
+ /*
+ * We do not need to do anything to allow the PUNIT to safely access
+ * the PMIC, other then block in kernel accesses to the PMIC.
+ */
+ iosf_mbi_pmic_punit_access_count++;
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
}
EXPORT_SYMBOL(iosf_mbi_punit_acquire);
void iosf_mbi_punit_release(void)
{
- mutex_unlock(&iosf_mbi_punit_mutex);
+ bool do_wakeup;
+
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
+ iosf_mbi_pmic_punit_access_count--;
+ do_wakeup = iosf_mbi_pmic_punit_access_count == 0;
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
+
+ if (do_wakeup)
+ wake_up(&iosf_mbi_pmic_access_waitq);
}
EXPORT_SYMBOL(iosf_mbi_punit_release);
@@ -256,34 +279,32 @@ static void iosf_mbi_reset_semaphore(void)
* already blocked P-Unit accesses because it wants them blocked over multiple
* i2c-transfers, for e.g. read-modify-write of an I2C client register.
*
- * The P-Unit accesses already being blocked is tracked through the
- * iosf_mbi_block_punit_i2c_access_count variable which is protected by the
- * iosf_mbi_block_punit_i2c_access_count_mutex this mutex is hold for the
- * entire duration of the function.
- *
- * If access is not blocked yet, this function takes the following steps:
+ * To allow safe PMIC i2c bus accesses this function takes the following steps:
*
* 1) Some code sends request to the P-Unit which make it access the PMIC
* I2C bus. Testing has shown that the P-Unit does not check its internal
* PMIC bus semaphore for these requests. Callers of these requests call
* iosf_mbi_punit_acquire()/_release() around their P-Unit accesses, these
- * functions lock/unlock the iosf_mbi_punit_mutex.
- * As the first step we lock the iosf_mbi_punit_mutex, to wait for any in
- * flight requests to finish and to block any new requests.
+ * functions increase/decrease iosf_mbi_pmic_punit_access_count, so first
+ * we wait for iosf_mbi_pmic_punit_access_count to become 0.
+ *
+ * 2) Check iosf_mbi_pmic_i2c_access_count, if access has already
+ * been blocked by another caller, we only need to increment
+ * iosf_mbi_pmic_i2c_access_count and we can skip the other steps.
*
- * 2) Some code makes such P-Unit requests from atomic contexts where it
+ * 3) Some code makes such P-Unit requests from atomic contexts where it
* cannot call iosf_mbi_punit_acquire() as that may sleep.
* As the second step we call a notifier chain which allows any code
* needing P-Unit resources from atomic context to acquire them before
* we take control over the PMIC I2C bus.
*
- * 3) When CPU cores enter C6 or C7 the P-Unit needs to talk to the PMIC
+ * 4) When CPU cores enter C6 or C7 the P-Unit needs to talk to the PMIC
* if this happens while the kernel itself is accessing the PMIC I2C bus
* the SoC hangs.
* As the third step we call pm_qos_update_request() to disallow the CPU
* to enter C6 or C7.
*
- * 4) The P-Unit has a PMIC bus semaphore which we can request to stop
+ * 5) The P-Unit has a PMIC bus semaphore which we can request to stop
* autonomous P-Unit tasks from accessing the PMIC I2C bus while we hold it.
* As the fourth and final step we request this semaphore and wait for our
* request to be acknowledged.
@@ -297,12 +318,18 @@ int iosf_mbi_block_punit_i2c_access(void)
if (WARN_ON(!mbi_pdev || !iosf_mbi_sem_address))
return -ENXIO;
- mutex_lock(&iosf_mbi_block_punit_i2c_access_count_mutex);
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
- if (iosf_mbi_block_punit_i2c_access_count > 0)
+ while (iosf_mbi_pmic_punit_access_count != 0) {
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
+ wait_event(iosf_mbi_pmic_access_waitq,
+ iosf_mbi_pmic_punit_access_count == 0);
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
+ }
+
+ if (iosf_mbi_pmic_i2c_access_count > 0)
goto success;
- mutex_lock(&iosf_mbi_punit_mutex);
blocking_notifier_call_chain(&iosf_mbi_pmic_bus_access_notifier,
MBI_PMIC_BUS_ACCESS_BEGIN, NULL);
@@ -330,10 +357,6 @@ int iosf_mbi_block_punit_i2c_access(void)
iosf_mbi_sem_acquired = jiffies;
dev_dbg(&mbi_pdev->dev, "P-Unit semaphore acquired after %ums\n",
jiffies_to_msecs(jiffies - start));
- /*
- * Success, keep iosf_mbi_punit_mutex locked till
- * iosf_mbi_unblock_punit_i2c_access() gets called.
- */
goto success;
}
@@ -344,15 +367,13 @@ int iosf_mbi_block_punit_i2c_access(void)
dev_err(&mbi_pdev->dev, "Error P-Unit semaphore timed out, resetting\n");
error:
iosf_mbi_reset_semaphore();
- mutex_unlock(&iosf_mbi_punit_mutex);
-
if (!iosf_mbi_get_sem(&sem))
dev_err(&mbi_pdev->dev, "P-Unit semaphore: %d\n", sem);
success:
if (!WARN_ON(ret))
- iosf_mbi_block_punit_i2c_access_count++;
+ iosf_mbi_pmic_i2c_access_count++;
- mutex_unlock(&iosf_mbi_block_punit_i2c_access_count_mutex);
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
return ret;
}
@@ -360,17 +381,20 @@ EXPORT_SYMBOL(iosf_mbi_block_punit_i2c_access);
void iosf_mbi_unblock_punit_i2c_access(void)
{
- mutex_lock(&iosf_mbi_block_punit_i2c_access_count_mutex);
+ bool do_wakeup = false;
- iosf_mbi_block_punit_i2c_access_count--;
- if (iosf_mbi_block_punit_i2c_access_count == 0) {
+ mutex_lock(&iosf_mbi_pmic_access_mutex);
+ iosf_mbi_pmic_i2c_access_count--;
+ if (iosf_mbi_pmic_i2c_access_count == 0) {
iosf_mbi_reset_semaphore();
- mutex_unlock(&iosf_mbi_punit_mutex);
dev_dbg(&mbi_pdev->dev, "punit semaphore held for %ums\n",
jiffies_to_msecs(jiffies - iosf_mbi_sem_acquired));
+ do_wakeup = true;
}
+ mutex_unlock(&iosf_mbi_pmic_access_mutex);
- mutex_unlock(&iosf_mbi_block_punit_i2c_access_count_mutex);
+ if (do_wakeup)
+ wake_up(&iosf_mbi_pmic_access_waitq);
}
EXPORT_SYMBOL(iosf_mbi_unblock_punit_i2c_access);
@@ -379,10 +403,10 @@ int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb)
int ret;
/* Wait for the bus to go inactive before registering */
- mutex_lock(&iosf_mbi_punit_mutex);
+ iosf_mbi_punit_acquire();
ret = blocking_notifier_chain_register(
&iosf_mbi_pmic_bus_access_notifier, nb);
- mutex_unlock(&iosf_mbi_punit_mutex);
+ iosf_mbi_punit_release();
return ret;
}
@@ -403,9 +427,9 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb)
int ret;
/* Wait for the bus to go inactive before unregistering */
- mutex_lock(&iosf_mbi_punit_mutex);
+ iosf_mbi_punit_acquire();
ret = iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(nb);
- mutex_unlock(&iosf_mbi_punit_mutex);
+ iosf_mbi_punit_release();
return ret;
}
@@ -413,7 +437,7 @@ EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier);
void iosf_mbi_assert_punit_acquired(void)
{
- WARN_ON(!mutex_is_locked(&iosf_mbi_punit_mutex));
+ WARN_ON(iosf_mbi_pmic_punit_access_count == 0);
}
EXPORT_SYMBOL(iosf_mbi_assert_punit_acquired);
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 7c69652ffeea..c2ee31953372 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -14,6 +14,8 @@
#include <asm/uv/bios.h>
#include <asm/uv/uv_hub.h>
+unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR;
+
struct uv_systab *uv_systab;
static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -185,13 +187,13 @@ EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
void uv_bios_init(void)
{
uv_systab = NULL;
- if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
- !efi.uv_systab || efi_runtime_disabled()) {
+ if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||
+ !uv_systab_phys || efi_runtime_disabled()) {
pr_crit("UV: UVsystab: missing\n");
return;
}
- uv_systab = ioremap(efi.uv_systab, sizeof(struct uv_systab));
+ uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab));
if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
pr_err("UV: UVsystab: bad signature!\n");
iounmap(uv_systab);
@@ -203,7 +205,7 @@ void uv_bios_init(void)
int size = uv_systab->size;
iounmap(uv_systab);
- uv_systab = ioremap(efi.uv_systab, size);
+ uv_systab = ioremap(uv_systab_phys, size);
if (!uv_systab) {
pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
return;
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 20c389a91b80..5f0a96bf27a1 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1804,9 +1804,9 @@ static void pq_init(int node, int pnode)
plsize = (DEST_Q_SIZE + 1) * sizeof(struct bau_pq_entry);
vp = kmalloc_node(plsize, GFP_KERNEL, node);
- pqp = (struct bau_pq_entry *)vp;
- BUG_ON(!pqp);
+ BUG_ON(!vp);
+ pqp = (struct bau_pq_entry *)vp;
cp = (char *)pqp + 31;
pqp = (struct bau_pq_entry *)(((unsigned long)cp >> 5) << 5);
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 24b079e94bc2..915bb1639763 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -12,6 +12,7 @@
#include <linux/smp.h>
#include <linux/perf_event.h>
#include <linux/tboot.h>
+#include <linux/dmi.h>
#include <asm/pgtable.h>
#include <asm/proto.h>
@@ -23,7 +24,7 @@
#include <asm/debugreg.h>
#include <asm/cpu.h>
#include <asm/mmu_context.h>
-#include <linux/dmi.h>
+#include <asm/cpu_device_id.h>
#ifdef CONFIG_X86_32
__visible unsigned long saved_context_ebx;
@@ -122,9 +123,6 @@ static void __save_processor_state(struct saved_context *ctxt)
ctxt->cr2 = read_cr2();
ctxt->cr3 = __read_cr3();
ctxt->cr4 = __read_cr4();
-#ifdef CONFIG_X86_64
- ctxt->cr8 = read_cr8();
-#endif
ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
&ctxt->misc_enable);
msr_save_context(ctxt);
@@ -207,7 +205,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
#else
/* CONFIG X86_64 */
wrmsrl(MSR_EFER, ctxt->efer);
- write_cr8(ctxt->cr8);
__write_cr4(ctxt->cr4);
#endif
write_cr3(ctxt->cr3);
@@ -397,15 +394,14 @@ static int __init bsp_pm_check_init(void)
core_initcall(bsp_pm_check_init);
-static int msr_init_context(const u32 *msr_id, const int total_num)
+static int msr_build_context(const u32 *msr_id, const int num)
{
- int i = 0;
+ struct saved_msrs *saved_msrs = &saved_context.saved_msrs;
struct saved_msr *msr_array;
+ int total_num;
+ int i, j;
- if (saved_context.saved_msrs.array || saved_context.saved_msrs.num > 0) {
- pr_err("x86/pm: MSR quirk already applied, please check your DMI match table.\n");
- return -EINVAL;
- }
+ total_num = saved_msrs->num + num;
msr_array = kmalloc_array(total_num, sizeof(struct saved_msr), GFP_KERNEL);
if (!msr_array) {
@@ -413,19 +409,30 @@ static int msr_init_context(const u32 *msr_id, const int total_num)
return -ENOMEM;
}
- for (i = 0; i < total_num; i++) {
- msr_array[i].info.msr_no = msr_id[i];
+ if (saved_msrs->array) {
+ /*
+ * Multiple callbacks can invoke this function, so copy any
+ * MSR save requests from previous invocations.
+ */
+ memcpy(msr_array, saved_msrs->array,
+ sizeof(struct saved_msr) * saved_msrs->num);
+
+ kfree(saved_msrs->array);
+ }
+
+ for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
+ msr_array[i].info.msr_no = msr_id[j];
msr_array[i].valid = false;
msr_array[i].info.reg.q = 0;
}
- saved_context.saved_msrs.num = total_num;
- saved_context.saved_msrs.array = msr_array;
+ saved_msrs->num = total_num;
+ saved_msrs->array = msr_array;
return 0;
}
/*
- * The following section is a quirk framework for problematic BIOSen:
+ * The following sections are a quirk framework for problematic BIOSen:
* Sometimes MSRs are modified by the BIOSen after suspended to
* RAM, this might cause unexpected behavior after wakeup.
* Thus we save/restore these specified MSRs across suspend/resume
@@ -440,7 +447,7 @@ static int msr_initialize_bdw(const struct dmi_system_id *d)
u32 bdw_msr_id[] = { MSR_IA32_THERM_CONTROL };
pr_info("x86/pm: %s detected, MSR saving is needed during suspending.\n", d->ident);
- return msr_init_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
+ return msr_build_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
}
static const struct dmi_system_id msr_save_dmi_table[] = {
@@ -455,9 +462,58 @@ static const struct dmi_system_id msr_save_dmi_table[] = {
{}
};
+static int msr_save_cpuid_features(const struct x86_cpu_id *c)
+{
+ u32 cpuid_msr_id[] = {
+ MSR_AMD64_CPUID_FN_1,
+ };
+
+ pr_info("x86/pm: family %#hx cpu detected, MSR saving is needed during suspending.\n",
+ c->family);
+
+ return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
+}
+
+static const struct x86_cpu_id msr_save_cpu_table[] = {
+ {
+ .vendor = X86_VENDOR_AMD,
+ .family = 0x15,
+ .model = X86_MODEL_ANY,
+ .feature = X86_FEATURE_ANY,
+ .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+ },
+ {
+ .vendor = X86_VENDOR_AMD,
+ .family = 0x16,
+ .model = X86_MODEL_ANY,
+ .feature = X86_FEATURE_ANY,
+ .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+ },
+ {}
+};
+
+typedef int (*pm_cpu_match_t)(const struct x86_cpu_id *);
+static int pm_cpu_check(const struct x86_cpu_id *c)
+{
+ const struct x86_cpu_id *m;
+ int ret = 0;
+
+ m = x86_match_cpu(msr_save_cpu_table);
+ if (m) {
+ pm_cpu_match_t fn;
+
+ fn = (pm_cpu_match_t)m->driver_data;
+ ret = fn(m);
+ }
+
+ return ret;
+}
+
static int pm_check_save_msr(void)
{
dmi_check_system(msr_save_dmi_table);
+ pm_cpu_check(msr_save_cpu_table);
+
return 0;
}
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 3cf302b26332..10fb42da0007 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -6,6 +6,9 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string
targets += $(purgatory-y)
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+$(obj)/string.o: $(srctree)/arch/x86/boot/compressed/string.c FORCE
+ $(call if_changed_rule,cc_o_c)
+
$(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE
$(call if_changed_rule,cc_o_c)
@@ -15,13 +18,39 @@ targets += purgatory.ro
KASAN_SANITIZE := n
KCOV_INSTRUMENT := n
+# These are adjustments to the compiler flags used for objects that
+# make up the standalone purgatory.ro
+
+PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
+PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
+
# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
# in turn leaves some undefined symbols like __fentry__ in purgatory and not
-# sure how to relocate those. Like kexec-tools, use custom flags.
+# sure how to relocate those.
+ifdef CONFIG_FUNCTION_TRACER
+PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_FTRACE)
+endif
+
+ifdef CONFIG_STACKPROTECTOR
+PURGATORY_CFLAGS_REMOVE += -fstack-protector
+endif
+
+ifdef CONFIG_STACKPROTECTOR_STRONG
+PURGATORY_CFLAGS_REMOVE += -fstack-protector-strong
+endif
+
+ifdef CONFIG_RETPOLINE
+PURGATORY_CFLAGS_REMOVE += $(RETPOLINE_CFLAGS)
+endif
+
+CFLAGS_REMOVE_purgatory.o += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_purgatory.o += $(PURGATORY_CFLAGS)
+
+CFLAGS_REMOVE_sha256.o += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_sha256.o += $(PURGATORY_CFLAGS)
-KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -Os -mcmodel=large
-KBUILD_CFLAGS += -m$(BITS)
-KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
+CFLAGS_REMOVE_string.o += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_string.o += $(PURGATORY_CFLAGS)
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
$(call if_changed,ld)
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c
index 6d8d5a34c377..b607bda786f6 100644
--- a/arch/x86/purgatory/purgatory.c
+++ b/arch/x86/purgatory/purgatory.c
@@ -68,3 +68,9 @@ void purgatory(void)
}
copy_backup_region();
}
+
+/*
+ * Defined in order to reuse memcpy() and memset() from
+ * arch/x86/boot/compressed/string.c
+ */
+void warn(const char *msg) {}
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c
deleted file mode 100644
index 01ad43873ad9..000000000000
--- a/arch/x86/purgatory/string.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Simple string functions.
- *
- * Copyright (C) 2014 Red Hat Inc.
- *
- * Author:
- * Vivek Goyal <vgoyal@redhat.com>
- */
-
-#include <linux/types.h>
-
-#include "../boot/string.c"
-
-void *memcpy(void *dst, const void *src, size_t len)
-{
- return __builtin_memcpy(dst, src, len);
-}
-
-void *memset(void *dst, int c, size_t len)
-{
- return __builtin_memset(dst, c, len);
-}
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index 30b0d30d861a..6363761cc74c 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -19,7 +19,6 @@ GLOBAL(real_mode_header)
.long pa_ro_end
/* SMP trampoline */
.long pa_trampoline_start
- .long pa_trampoline_status
.long pa_trampoline_header
#ifdef CONFIG_X86_64
.long pa_trampoline_pgd;
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S
index 2dd866c9e21e..1868b158480d 100644
--- a/arch/x86/realmode/rm/trampoline_32.S
+++ b/arch/x86/realmode/rm/trampoline_32.S
@@ -41,9 +41,6 @@ ENTRY(trampoline_start)
movl tr_start, %eax # where we need to go
- movl $0xA5A5A5A5, trampoline_status
- # write marker for master knows we're running
-
/*
* GDT tables in non default location kernel can be beyond 16MB and
* lgdt will not be able to load the address as in real mode default
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index 24bb7598774e..aee2b45d83b8 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -49,9 +49,6 @@ ENTRY(trampoline_start)
mov %ax, %es
mov %ax, %ss
- movl $0xA5A5A5A5, trampoline_status
- # write marker for master knows we're running
-
# Setup stack
movl $rm_stack_end, %esp
diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S
index 7c706772ab59..8d8208dcca24 100644
--- a/arch/x86/realmode/rm/trampoline_common.S
+++ b/arch/x86/realmode/rm/trampoline_common.S
@@ -2,7 +2,3 @@
.section ".rodata","a"
.balign 16
tr_idt: .fill 1, 6, 0
-
- .bss
- .balign 4
-GLOBAL(trampoline_status) .space 4
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 7ceb32821093..58f79ab32358 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -877,16 +877,6 @@ static void xen_write_cr4(unsigned long cr4)
native_write_cr4(cr4);
}
-#ifdef CONFIG_X86_64
-static inline unsigned long xen_read_cr8(void)
-{
- return 0;
-}
-static inline void xen_write_cr8(unsigned long val)
-{
- BUG_ON(val);
-}
-#endif
static u64 xen_read_msr_safe(unsigned int msr, int *err)
{
@@ -1023,11 +1013,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.write_cr4 = xen_write_cr4,
-#ifdef CONFIG_X86_64
- .read_cr8 = xen_read_cr8,
- .write_cr8 = xen_write_cr8,
-#endif
-
.wbinvd = native_wbinvd,
.read_msr = xen_read_msr,
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 60c220020054..80828b95a51f 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -14,6 +14,7 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
+#include <asm/asmmacro.h>
#include <asm/processor.h>
#include <asm/coprocessor.h>
#include <asm/thread_info.h>
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 5cb8a62e091c..7c3106093c75 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -511,6 +511,7 @@ void cpu_reset(void)
"add %2, %2, %7\n\t"
"addi %0, %0, -1\n\t"
"bnez %0, 1b\n\t"
+ "isync\n\t"
/* Jump to identity mapping */
"jx %3\n"
"2:\n\t"
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 72860325245a..b33be928d164 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -1924,12 +1924,13 @@ static void bfq_add_request(struct request *rq)
* confirmed no later than during the next
* I/O-plugging interval for bfqq.
*/
- if (!bfq_bfqq_has_short_ttime(bfqq) &&
+ if (bfqd->last_completed_rq_bfqq &&
+ !bfq_bfqq_has_short_ttime(bfqq) &&
ktime_get_ns() - bfqd->last_completion <
200 * NSEC_PER_USEC) {
if (bfqd->last_completed_rq_bfqq != bfqq &&
- bfqd->last_completed_rq_bfqq !=
- bfqq->waker_bfqq) {
+ bfqd->last_completed_rq_bfqq !=
+ bfqq->waker_bfqq) {
/*
* First synchronization detected with
* a candidate waker queue, or with a
@@ -2250,9 +2251,14 @@ static void bfq_request_merged(struct request_queue *q, struct request *req,
blk_rq_pos(container_of(rb_prev(&req->rb_node),
struct request, rb_node))) {
struct bfq_queue *bfqq = bfq_init_rq(req);
- struct bfq_data *bfqd = bfqq->bfqd;
+ struct bfq_data *bfqd;
struct request *prev, *next_rq;
+ if (!bfqq)
+ return;
+
+ bfqd = bfqq->bfqd;
+
/* Reposition request in its sort_list */
elv_rb_del(&bfqq->sort_list, req);
elv_rb_add(&bfqq->sort_list, req);
@@ -2299,6 +2305,9 @@ static void bfq_requests_merged(struct request_queue *q, struct request *rq,
struct bfq_queue *bfqq = bfq_init_rq(rq),
*next_bfqq = bfq_init_rq(next);
+ if (!bfqq)
+ return;
+
/*
* If next and rq belong to the same bfq_queue and next is older
* than rq, then reposition rq in the fifo (by substituting next
@@ -3354,38 +3363,57 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq)
* there is no active group, then the primary expectation for
* this device is probably a high throughput.
*
- * We are now left only with explaining the additional
- * compound condition that is checked below for deciding
- * whether the scenario is asymmetric. To explain this
- * compound condition, we need to add that the function
+ * We are now left only with explaining the two sub-conditions in the
+ * additional compound condition that is checked below for deciding
+ * whether the scenario is asymmetric. To explain the first
+ * sub-condition, we need to add that the function
* bfq_asymmetric_scenario checks the weights of only
- * non-weight-raised queues, for efficiency reasons (see
- * comments on bfq_weights_tree_add()). Then the fact that
- * bfqq is weight-raised is checked explicitly here. More
- * precisely, the compound condition below takes into account
- * also the fact that, even if bfqq is being weight-raised,
- * the scenario is still symmetric if all queues with requests
- * waiting for completion happen to be
- * weight-raised. Actually, we should be even more precise
- * here, and differentiate between interactive weight raising
- * and soft real-time weight raising.
+ * non-weight-raised queues, for efficiency reasons (see comments on
+ * bfq_weights_tree_add()). Then the fact that bfqq is weight-raised
+ * is checked explicitly here. More precisely, the compound condition
+ * below takes into account also the fact that, even if bfqq is being
+ * weight-raised, the scenario is still symmetric if all queues with
+ * requests waiting for completion happen to be
+ * weight-raised. Actually, we should be even more precise here, and
+ * differentiate between interactive weight raising and soft real-time
+ * weight raising.
+ *
+ * The second sub-condition checked in the compound condition is
+ * whether there is a fair amount of already in-flight I/O not
+ * belonging to bfqq. If so, I/O dispatching is to be plugged, for the
+ * following reason. The drive may decide to serve in-flight
+ * non-bfqq's I/O requests before bfqq's ones, thereby delaying the
+ * arrival of new I/O requests for bfqq (recall that bfqq is sync). If
+ * I/O-dispatching is not plugged, then, while bfqq remains empty, a
+ * basically uncontrolled amount of I/O from other queues may be
+ * dispatched too, possibly causing the service of bfqq's I/O to be
+ * delayed even longer in the drive. This problem gets more and more
+ * serious as the speed and the queue depth of the drive grow,
+ * because, as these two quantities grow, the probability to find no
+ * queue busy but many requests in flight grows too. By contrast,
+ * plugging I/O dispatching minimizes the delay induced by already
+ * in-flight I/O, and enables bfqq to recover the bandwidth it may
+ * lose because of this delay.
*
* As a side note, it is worth considering that the above
- * device-idling countermeasures may however fail in the
- * following unlucky scenario: if idling is (correctly)
- * disabled in a time period during which all symmetry
- * sub-conditions hold, and hence the device is allowed to
- * enqueue many requests, but at some later point in time some
- * sub-condition stops to hold, then it may become impossible
- * to let requests be served in the desired order until all
- * the requests already queued in the device have been served.
+ * device-idling countermeasures may however fail in the following
+ * unlucky scenario: if I/O-dispatch plugging is (correctly) disabled
+ * in a time period during which all symmetry sub-conditions hold, and
+ * therefore the device is allowed to enqueue many requests, but at
+ * some later point in time some sub-condition stops to hold, then it
+ * may become impossible to make requests be served in the desired
+ * order until all the requests already queued in the device have been
+ * served. The last sub-condition commented above somewhat mitigates
+ * this problem for weight-raised queues.
*/
static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
struct bfq_queue *bfqq)
{
return (bfqq->wr_coeff > 1 &&
- bfqd->wr_busy_queues <
- bfq_tot_busy_queues(bfqd)) ||
+ (bfqd->wr_busy_queues <
+ bfq_tot_busy_queues(bfqd) ||
+ bfqd->rq_in_driver >=
+ bfqq->dispatched + 4)) ||
bfq_asymmetric_scenario(bfqd, bfqq);
}
@@ -4745,6 +4773,8 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
*/
void bfq_put_queue(struct bfq_queue *bfqq)
{
+ struct bfq_queue *item;
+ struct hlist_node *n;
#ifdef CONFIG_BFQ_GROUP_IOSCHED
struct bfq_group *bfqg = bfqq_group(bfqq);
#endif
@@ -4789,6 +4819,36 @@ void bfq_put_queue(struct bfq_queue *bfqq)
bfqq->bfqd->burst_size--;
}
+ /*
+ * bfqq does not exist any longer, so it cannot be woken by
+ * any other queue, and cannot wake any other queue. Then bfqq
+ * must be removed from the woken list of its possible waker
+ * queue, and all queues in the woken list of bfqq must stop
+ * having a waker queue. Strictly speaking, these updates
+ * should be performed when bfqq remains with no I/O source
+ * attached to it, which happens before bfqq gets freed. In
+ * particular, this happens when the last process associated
+ * with bfqq exits or gets associated with a different
+ * queue. However, both events lead to bfqq being freed soon,
+ * and dangling references would come out only after bfqq gets
+ * freed. So these updates are done here, as a simple and safe
+ * way to handle all cases.
+ */
+ /* remove bfqq from woken list */
+ if (!hlist_unhashed(&bfqq->woken_list_node))
+ hlist_del_init(&bfqq->woken_list_node);
+
+ /* reset waker for all queues in woken list */
+ hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
+ woken_list_node) {
+ item->waker_bfqq = NULL;
+ bfq_clear_bfqq_has_waker(item);
+ hlist_del_init(&item->woken_list_node);
+ }
+
+ if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
+ bfqq->bfqd->last_completed_rq_bfqq = NULL;
+
kmem_cache_free(bfq_pool, bfqq);
#ifdef CONFIG_BFQ_GROUP_IOSCHED
bfqg_and_blkg_put(bfqg);
@@ -4816,9 +4876,6 @@ static void bfq_put_cooperator(struct bfq_queue *bfqq)
static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
{
- struct bfq_queue *item;
- struct hlist_node *n;
-
if (bfqq == bfqd->in_service_queue) {
__bfq_bfqq_expire(bfqd, bfqq, BFQQE_BUDGET_TIMEOUT);
bfq_schedule_dispatch(bfqd);
@@ -4828,18 +4885,6 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_put_cooperator(bfqq);
- /* remove bfqq from woken list */
- if (!hlist_unhashed(&bfqq->woken_list_node))
- hlist_del_init(&bfqq->woken_list_node);
-
- /* reset waker for all queues in woken list */
- hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
- woken_list_node) {
- item->waker_bfqq = NULL;
- bfq_clear_bfqq_has_waker(item);
- hlist_del_init(&item->woken_list_node);
- }
-
bfq_put_queue(bfqq); /* release process reference */
}
@@ -5417,12 +5462,12 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
spin_lock_irq(&bfqd->lock);
bfqq = bfq_init_rq(rq);
- if (at_head || blk_rq_is_passthrough(rq)) {
+ if (!bfqq || at_head || blk_rq_is_passthrough(rq)) {
if (at_head)
list_add(&rq->queuelist, &bfqd->dispatch);
else
list_add_tail(&rq->queuelist, &bfqd->dispatch);
- } else { /* bfqq is assumed to be non null here */
+ } else {
idle_timer_disabled = __bfq_insert_request(bfqd, rq);
/*
* Update bfqq, because, if a queue merge has occurred
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 24ed26957367..55a7dc227dfb 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -54,7 +54,7 @@ static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
static LIST_HEAD(all_blkcgs); /* protected by blkcg_pol_mutex */
-static bool blkcg_debug_stats = false;
+bool blkcg_debug_stats = false;
static struct workqueue_struct *blkcg_punt_bio_wq;
static bool blkcg_policy_enabled(struct request_queue *q,
@@ -944,10 +944,7 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
dbytes, dios);
}
- if (!blkcg_debug_stats)
- goto next;
-
- if (atomic_read(&blkg->use_delay)) {
+ if (blkcg_debug_stats && atomic_read(&blkg->use_delay)) {
has_stats = true;
off += scnprintf(buf+off, size-off,
" use_delay=%d delay_nsec=%llu",
@@ -967,7 +964,7 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
has_stats = true;
off += written;
}
-next:
+
if (has_stats) {
if (off < size - 1) {
off += scnprintf(buf+off, size-off, "\n");
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
index d973c38ee4fd..0fff7b56df0e 100644
--- a/block/blk-iolatency.c
+++ b/block/blk-iolatency.c
@@ -917,6 +917,9 @@ static size_t iolatency_pd_stat(struct blkg_policy_data *pd, char *buf,
unsigned long long avg_lat;
unsigned long long cur_win;
+ if (!blkcg_debug_stats)
+ return 0;
+
if (iolat->ssd)
return iolatency_ssd_stat(iolat, buf, size);
diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h
index cf22ab00fefb..126021fc3a11 100644
--- a/block/blk-mq-sched.h
+++ b/block/blk-mq-sched.h
@@ -61,15 +61,6 @@ static inline void blk_mq_sched_completed_request(struct request *rq, u64 now)
e->type->ops.completed_request(rq, now);
}
-static inline void blk_mq_sched_started_request(struct request *rq)
-{
- struct request_queue *q = rq->q;
- struct elevator_queue *e = q->elevator;
-
- if (e && e->type->ops.started_request)
- e->type->ops.started_request(rq);
-}
-
static inline void blk_mq_sched_requeue_request(struct request *rq)
{
struct request_queue *q = rq->q;
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f567146f9ed7..e0b849bfe74d 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -669,8 +669,6 @@ void blk_mq_start_request(struct request *rq)
{
struct request_queue *q = rq->q;
- blk_mq_sched_started_request(rq);
-
trace_block_rq_issue(q, rq);
if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
@@ -2664,8 +2662,6 @@ void blk_mq_release(struct request_queue *q)
struct blk_mq_hw_ctx *hctx, *next;
int i;
- cancel_delayed_work_sync(&q->requeue_work);
-
queue_for_each_hw_ctx(q, hctx, i)
WARN_ON_ONCE(hctx && list_empty(&hctx->hctx_list));
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index 659ccb8b693f..3954c0dc1443 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -202,6 +202,7 @@ static int rq_qos_wake_function(struct wait_queue_entry *curr,
return -1;
data->got_token = true;
+ smp_wmb();
list_del_init(&curr->entry);
wake_up_process(data->task);
return 1;
@@ -244,7 +245,9 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
return;
prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
+ has_sleeper = !wq_has_single_sleeper(&rqw->wait);
do {
+ /* The memory barrier in set_task_state saves us here. */
if (data.got_token)
break;
if (!has_sleeper && acquire_inflight_cb(rqw, private_data)) {
@@ -255,12 +258,14 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
* which means we now have two. Put our local token
* and wake anyone else potentially waiting for one.
*/
+ smp_rmb();
if (data.got_token)
cleanup_cb(rqw, private_data);
break;
}
io_schedule();
- has_sleeper = false;
+ has_sleeper = true;
+ set_current_state(TASK_UNINTERRUPTIBLE);
} while (1);
finish_wait(&rqw->wait, &data.wq);
}
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 2ae348c101a0..2c1831207a8f 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -752,7 +752,8 @@ void blk_queue_virt_boundary(struct request_queue *q, unsigned long mask)
* page (which might not be idential to the Linux PAGE_SIZE). Because
* of that they are not limited by our notion of "segment size".
*/
- q->limits.max_segment_size = UINT_MAX;
+ if (mask)
+ q->limits.max_segment_size = UINT_MAX;
}
EXPORT_SYMBOL(blk_queue_virt_boundary);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 977c659dcd18..9bfa3ea4ed63 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -892,6 +892,9 @@ static void __blk_release_queue(struct work_struct *work)
blk_free_queue_stats(q->stats);
+ if (queue_is_mq(q))
+ cancel_delayed_work_sync(&q->requeue_work);
+
blk_exit_queue(q);
blk_queue_free_zone_bitmaps(q);
diff --git a/block/genhd.c b/block/genhd.c
index 97887e59f3b2..54f1f0d381f4 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1969,7 +1969,7 @@ static const struct attribute *disk_events_attrs[] = {
* The default polling interval can be specified by the kernel
* parameter block.events_dfl_poll_msecs which defaults to 0
* (disable). This can also be modified runtime by writing to
- * /sys/module/block/events_dfl_poll_msecs.
+ * /sys/module/block/parameters/events_dfl_poll_msecs.
*/
static int disk_events_set_dfl_poll_msecs(const char *val,
const struct kernel_param *kp)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 61cf4ea2c229..477d63d0364d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -30,8 +30,6 @@ source "drivers/block/Kconfig"
source "drivers/nvme/Kconfig"
-# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4
-
source "drivers/misc/Kconfig"
source "drivers/ide/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 6d37564e783c..05be8c798c51 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -132,7 +132,6 @@ obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
-obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5f6158973289..ebe1e9e5fd81 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -323,7 +323,7 @@ config ACPI_NUMA
bool "NUMA support"
depends on NUMA
depends on (X86 || IA64 || ARM64)
- default y if IA64_GENERIC || IA64_SGI_SN2 || ARM64
+ default y if IA64 || ARM64
config ACPI_CUSTOM_DSDT_FILE
string "Custom DSDT Table file to include"
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index d4551e33fa71..5a7551d060f2 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -611,8 +611,8 @@ static int iort_dev_find_its_id(struct device *dev, u32 req_id,
/* Move to ITS specific data */
its = (struct acpi_iort_its_group *)node->node_data;
- if (idx > its->its_count) {
- dev_err(dev, "requested ITS ID index [%d] is greater than available [%d]\n",
+ if (idx >= its->its_count) {
+ dev_err(dev, "requested ITS ID index [%d] overruns ITS entries [%d]\n",
idx, its->its_count);
return -ENXIO;
}
@@ -1256,12 +1256,12 @@ static int __init arm_smmu_v3_set_proximity(struct device *dev,
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
if (smmu->flags & ACPI_IORT_SMMU_V3_PXM_VALID) {
- int node = acpi_map_pxm_to_node(smmu->pxm);
+ int dev_node = acpi_map_pxm_to_node(smmu->pxm);
- if (node != NUMA_NO_NODE && !node_online(node))
+ if (dev_node != NUMA_NO_NODE && !node_online(dev_node))
return -EINVAL;
- set_dev_node(dev, node);
+ set_dev_node(dev, dev_node);
pr_info("SMMU-v3[%llx] Mapped to Proximity domain %d\n",
smmu->base_address,
smmu->pxm);
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 28cffaaf9d82..f616b16c1f0b 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -232,13 +232,15 @@ int acpi_device_set_power(struct acpi_device *device, int state)
if (device->power.flags.power_resources)
result = acpi_power_transition(device, target_state);
} else {
+ int cur_state = device->power.state;
+
if (device->power.flags.power_resources) {
result = acpi_power_transition(device, ACPI_STATE_D0);
if (result)
goto end;
}
- if (device->power.state == ACPI_STATE_D0) {
+ if (cur_state == ACPI_STATE_D0) {
int psc;
/* Nothing to do here if _PSC is not present. */
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index c02fa27dd3f3..1413324982f0 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1282,7 +1282,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
if (rc)
return rc;
- device_lock(dev);
+ nfit_device_lock(dev);
nd_desc = dev_get_drvdata(dev);
if (nd_desc) {
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
@@ -1299,7 +1299,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
break;
}
}
- device_unlock(dev);
+ nfit_device_unlock(dev);
if (rc)
return rc;
return size;
@@ -1319,7 +1319,7 @@ static ssize_t scrub_show(struct device *dev,
ssize_t rc = -ENXIO;
bool busy;
- device_lock(dev);
+ nfit_device_lock(dev);
nd_desc = dev_get_drvdata(dev);
if (!nd_desc) {
device_unlock(dev);
@@ -1339,7 +1339,7 @@ static ssize_t scrub_show(struct device *dev,
}
mutex_unlock(&acpi_desc->init_mutex);
- device_unlock(dev);
+ nfit_device_unlock(dev);
return rc;
}
@@ -1356,14 +1356,14 @@ static ssize_t scrub_store(struct device *dev,
if (val != 1)
return -EINVAL;
- device_lock(dev);
+ nfit_device_lock(dev);
nd_desc = dev_get_drvdata(dev);
if (nd_desc) {
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
rc = acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG);
}
- device_unlock(dev);
+ nfit_device_unlock(dev);
if (rc)
return rc;
return size;
@@ -1749,9 +1749,9 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
struct acpi_device *adev = data;
struct device *dev = &adev->dev;
- device_lock(dev->parent);
+ nfit_device_lock(dev->parent);
__acpi_nvdimm_notify(dev, event);
- device_unlock(dev->parent);
+ nfit_device_unlock(dev->parent);
}
static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
@@ -3457,8 +3457,8 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
struct device *dev = acpi_desc->dev;
/* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
- device_lock(dev);
- device_unlock(dev);
+ nfit_device_lock(dev);
+ nfit_device_unlock(dev);
/* Bounce the init_mutex to complete initial registration */
mutex_lock(&acpi_desc->init_mutex);
@@ -3602,8 +3602,8 @@ void acpi_nfit_shutdown(void *data)
* acpi_nfit_ars_rescan() submissions have had a chance to
* either submit or see ->cancel set.
*/
- device_lock(bus_dev);
- device_unlock(bus_dev);
+ nfit_device_lock(bus_dev);
+ nfit_device_unlock(bus_dev);
flush_workqueue(nfit_wq);
}
@@ -3746,9 +3746,9 @@ EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
{
- device_lock(&adev->dev);
+ nfit_device_lock(&adev->dev);
__acpi_nfit_notify(&adev->dev, adev->handle, event);
- device_unlock(&adev->dev);
+ nfit_device_unlock(&adev->dev);
}
static const struct acpi_device_id acpi_nfit_ids[] = {
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 6ee2b02af73e..24241941181c 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -312,6 +312,30 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
}
+#ifdef CONFIG_PROVE_LOCKING
+static inline void nfit_device_lock(struct device *dev)
+{
+ device_lock(dev);
+ mutex_lock(&dev->lockdep_mutex);
+}
+
+static inline void nfit_device_unlock(struct device *dev)
+{
+ mutex_unlock(&dev->lockdep_mutex);
+ device_unlock(dev);
+}
+#else
+static inline void nfit_device_lock(struct device *dev)
+{
+ device_lock(dev);
+}
+
+static inline void nfit_device_unlock(struct device *dev)
+{
+ device_unlock(dev);
+}
+#endif
+
const guid_t *to_nfit_uuid(enum nfit_uuids id);
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
void acpi_nfit_shutdown(void *data);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 9c0edf2fc0dd..2f9d0d20b836 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/lockdep.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
@@ -80,6 +81,7 @@ struct acpi_ioremap {
static LIST_HEAD(acpi_ioremaps);
static DEFINE_MUTEX(acpi_ioremap_lock);
+#define acpi_ioremap_lock_held() lock_is_held(&acpi_ioremap_lock.dep_map)
static void __init acpi_request_region (struct acpi_generic_address *gas,
unsigned int length, char *desc)
@@ -206,7 +208,7 @@ acpi_map_lookup(acpi_physical_address phys, acpi_size size)
{
struct acpi_ioremap *map;
- list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+ list_for_each_entry_rcu(map, &acpi_ioremaps, list, acpi_ioremap_lock_held())
if (map->phys <= phys &&
phys + size <= map->phys + map->size)
return map;
@@ -249,7 +251,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;
- list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+ list_for_each_entry_rcu(map, &acpi_ioremaps, list, acpi_ioremap_lock_held())
if (map->virt <= virt &&
virt + size <= map->virt + map->size)
return map;
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 1e7ac0bd0d3a..f31544d3656e 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -541,6 +541,44 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag)
}
/**
+ * check_acpi_cpu_flag() - Determine if CPU node has a flag set
+ * @cpu: Kernel logical CPU number
+ * @rev: The minimum PPTT revision defining the flag
+ * @flag: The flag itself
+ *
+ * Check the node representing a CPU for a given flag.
+ *
+ * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or
+ * the table revision isn't new enough.
+ * 1, any passed flag set
+ * 0, flag unset
+ */
+static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag)
+{
+ struct acpi_table_header *table;
+ acpi_status status;
+ u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ struct acpi_pptt_processor *cpu_node = NULL;
+ int ret = -ENOENT;
+
+ status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
+ if (ACPI_FAILURE(status)) {
+ acpi_pptt_warn_missing();
+ return ret;
+ }
+
+ if (table->revision >= rev)
+ cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
+
+ if (cpu_node)
+ ret = (cpu_node->flags & flag) != 0;
+
+ acpi_put_table(table);
+
+ return ret;
+}
+
+/**
* acpi_find_last_cache_level() - Determines the number of cache levels for a PE
* @cpu: Kernel logical CPU number
*
@@ -605,6 +643,20 @@ int cache_setup_acpi(unsigned int cpu)
}
/**
+ * acpi_pptt_cpu_is_thread() - Determine if CPU is a thread
+ * @cpu: Kernel logical CPU number
+ *
+ * Return: 1, a thread
+ * 0, not a thread
+ * -ENOENT ,if the PPTT doesn't exist, the CPU cannot be found or
+ * the table revision isn't new enough.
+ */
+int acpi_pptt_cpu_is_thread(unsigned int cpu)
+{
+ return check_acpi_cpu_flag(cpu, 2, ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD);
+}
+
+/**
* find_acpi_cpu_topology() - Determine a unique topology value for a given CPU
* @cpu: Kernel logical CPU number
* @level: The topological level for which we would like a unique ID
@@ -664,7 +716,6 @@ int find_acpi_cpu_cache_topology(unsigned int cpu, int level)
return ret;
}
-
/**
* find_acpi_cpu_topology_package() - Determine a unique CPU package value
* @cpu: Kernel logical CPU number
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 0e28270b0fd8..aad6be5c0af0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2204,6 +2204,12 @@ int __init acpi_scan_init(void)
acpi_gpe_apply_masked_gpes();
acpi_update_all_gpes();
+ /*
+ * Although we call __add_memory() that is documented to require the
+ * device_hotplug_lock, it is not necessary here because this is an
+ * early code when userspace or any other code path cannot trigger
+ * hotplug/hotunplug operations.
+ */
mutex_lock(&acpi_scan_lock);
/*
* Enumerate devices in the ACPI namespace.
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index ba277cd5c7fa..697a6b12d6b9 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -69,11 +69,11 @@ static const struct always_present_id always_present_ids[] = {
* after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
* *and* _STA has been called at least 3 times since.
*/
- ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
+ ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_L), {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
}),
- ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
+ ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_L), {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
}),
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 38a59a630cd4..dc1c83eafc22 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2988,7 +2988,7 @@ static void binder_transaction(struct binder_proc *proc,
else
return_error = BR_DEAD_REPLY;
mutex_unlock(&context->context_mgr_node_lock);
- if (target_node && target_proc == proc) {
+ if (target_node && target_proc->pid == proc->pid) {
binder_user_error("%d:%d got transaction to context manager from process owning it\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3239,7 +3239,8 @@ static void binder_transaction(struct binder_proc *proc,
buffer_offset = off_start_offset;
off_end_offset = off_start_offset + tr->offsets_size;
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
- sg_buf_end_offset = sg_buf_offset + extra_buffers_size;
+ sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
+ ALIGN(secctx_sz, sizeof(u64));
off_min = 0;
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
buffer_offset += sizeof(binder_size_t)) {
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 72312ad2e142..9e9583a6bba9 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -338,6 +338,9 @@ static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,
hpriv->phys[port] = NULL;
rc = 0;
break;
+ case -EPROBE_DEFER:
+ /* Do not complain yet */
+ break;
default:
dev_err(dev,
@@ -408,7 +411,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
hpriv->mmio = devm_ioremap_resource(dev,
platform_get_resource(pdev, IORESOURCE_MEM, 0));
if (IS_ERR(hpriv->mmio)) {
- dev_err(dev, "no mmio space\n");
rc = PTR_ERR(hpriv->mmio);
goto err_out;
}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 391ac0503dc0..76d0f9de767b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1786,6 +1786,21 @@ nothing_to_do:
return 1;
}
+static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
+{
+ struct request *rq = scmd->request;
+ u32 req_blocks;
+
+ if (!blk_rq_is_passthrough(rq))
+ return true;
+
+ req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
+ if (n_blocks > req_blocks)
+ return false;
+
+ return true;
+}
+
/**
* ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
* @qc: Storage for translated ATA taskfile
@@ -1830,6 +1845,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
scsi_10_lba_len(cdb, &block, &n_block);
if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA;
+ if (!ata_check_nblocks(scmd, n_block))
+ goto invalid_fld;
break;
case READ_6:
case WRITE_6:
@@ -1844,6 +1861,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
*/
if (!n_block)
n_block = 256;
+ if (!ata_check_nblocks(scmd, n_block))
+ goto invalid_fld;
break;
case READ_16:
case WRITE_16:
@@ -1854,6 +1873,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
scsi_16_lba_len(cdb, &block, &n_block);
if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA;
+ if (!ata_check_nblocks(scmd, n_block))
+ goto invalid_fld;
break;
default:
DPRINTK("no-byte command\n");
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 10aa27882142..4f115adb4ee8 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -658,6 +658,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
unsigned int offset;
unsigned char *buf;
+ if (!qc->cursg) {
+ qc->curbytes = qc->nbytes;
+ return;
+ }
if (qc->curbytes == qc->nbytes - qc->sect_size)
ap->hsm_task_state = HSM_ST_LAST;
@@ -683,6 +687,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
if (qc->cursg_ofs == qc->cursg->length) {
qc->cursg = sg_next(qc->cursg);
+ if (!qc->cursg)
+ ap->hsm_task_state = HSM_ST_LAST;
qc->cursg_ofs = 0;
}
}
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index 173e6f2dd9af..eefda51f97d3 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -56,7 +56,7 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
unsigned int ret;
struct rm_feature_desc *desc;
struct ata_taskfile tf;
- static const char cdb[] = { GPCMD_GET_CONFIGURATION,
+ static const char cdb[ATAPI_CDB_LEN] = { GPCMD_GET_CONFIGURATION,
2, /* only 1 feature descriptor requested */
0, 3, /* 3, removable medium feature */
0, 0, 0,/* reserved */
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index 7c37f2ff09e4..deae466395de 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -158,7 +158,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
static int rb532_pata_driver_remove(struct platform_device *pdev)
{
struct ata_host *ah = platform_get_drvdata(pdev);
- struct rb532_cf_info *info = ah->private_data;
ata_host_detach(ah);
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index 2e2efa577437..8c37294f1d1e 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -200,7 +200,7 @@ config ATM_NICSTAR_USE_SUNI
make the card work).
config ATM_NICSTAR_USE_IDT77105
- bool "Use IDT77015 PHY driver (25Mbps)"
+ bool "Use IDT77105 PHY driver (25Mbps)"
depends on ATM_NICSTAR
help
Support for the PHYsical layer chip in ForeRunner LE25 cards. In
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 302cf0ba1600..8c7a996d1f16 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -63,6 +63,7 @@
#include <asm/byteorder.h>
#include <linux/vmalloc.h>
#include <linux/jiffies.h>
+#include <linux/nospec.h>
#include "iphase.h"
#include "suni.h"
#define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
@@ -2760,8 +2761,11 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
}
if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT;
board = ia_cmds.status;
- if ((board < 0) || (board > iadev_count))
- board = 0;
+
+ if ((board < 0) || (board > iadev_count))
+ board = 0;
+ board = array_index_nospec(board, iadev_count + 1);
+
iadev = ia_dev[board];
switch (ia_cmds.cmd) {
case MEMDUMP:
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index dd61fdd400f0..68489d1f00bb 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -448,6 +448,11 @@ config PANEL_BOOT_MESSAGE
choice
prompt "Backlight initial state"
default CHARLCD_BL_FLASH
+ ---help---
+ Select the initial backlight state on boot or module load.
+
+ Previously, there was no option for this: the backlight flashed
+ briefly on init. Now you can also turn it off/on.
config CHARLCD_BL_OFF
bool "Off"
diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 92745efefb54..bef6b85778b6 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -20,7 +20,7 @@
#include <generated/utsrelease.h>
-#include <misc/charlcd.h>
+#include "charlcd.h"
#define LCD_MINOR 156
diff --git a/include/misc/charlcd.h b/drivers/auxdisplay/charlcd.h
index 8cf6c18b0adb..00911ad0f3de 100644
--- a/include/misc/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -6,6 +6,9 @@
* Copyright (C) 2016-2017 Glider bvba
*/
+#ifndef _CHARLCD_H
+#define _CHARLCD_H
+
struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -37,3 +40,5 @@ int charlcd_register(struct charlcd *lcd);
int charlcd_unregister(struct charlcd *lcd);
void charlcd_poke(struct charlcd *lcd);
+
+#endif /* CHARLCD_H */
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index ab15b64707ad..bcbe13092327 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -14,8 +14,7 @@
#include <linux/property.h>
#include <linux/slab.h>
-#include <misc/charlcd.h>
-
+#include "charlcd.h"
enum hd44780_pin {
/* Order does matter due to writing to GPIO array subsets! */
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index 9c0bb771751d..a2fcde582e2a 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -74,7 +74,7 @@ struct ht16k33_priv {
struct ht16k33_fbdev fbdev;
};
-static struct fb_fix_screeninfo ht16k33_fb_fix = {
+static const struct fb_fix_screeninfo ht16k33_fb_fix = {
.id = DRIVER_NAME,
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_MONO10,
@@ -85,7 +85,7 @@ static struct fb_fix_screeninfo ht16k33_fb_fix = {
.accel = FB_ACCEL_NONE,
};
-static struct fb_var_screeninfo ht16k33_fb_var = {
+static const struct fb_var_screeninfo ht16k33_fb_var = {
.xres = HT16K33_MATRIX_LED_MAX_ROWS,
.yres = HT16K33_MATRIX_LED_MAX_COLS,
.xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS,
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index e06de63497cf..85965953683e 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -55,7 +55,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <misc/charlcd.h>
+#include "charlcd.h"
#define KEYPAD_MINOR 185
@@ -1617,6 +1617,8 @@ static void panel_attach(struct parport *port)
return;
err_lcd_unreg:
+ if (scan_timer.function)
+ del_timer_sync(&scan_timer);
if (lcd.enabled)
charlcd_unregister(lcd.charlcd);
err_unreg_device:
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index dc404492381d..28b92e3cc570 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -202,7 +202,7 @@ config GENERIC_ARCH_TOPOLOGY
help
Enable support for architectures common topology code: e.g., parsing
CPU capacity information from DT, usage of such information for
- appropriate scaling, sysfs interface for changing capacity values at
+ appropriate scaling, sysfs interface for reading capacity values at
runtime.
endmenu
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 63c1e76739f1..b54d241a2ff5 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -15,6 +15,11 @@
#include <linux/string.h>
#include <linux/sched/topology.h>
#include <linux/cpuset.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
@@ -241,3 +246,296 @@ static void parsing_done_workfn(struct work_struct *work)
#else
core_initcall(free_raw_capacity);
#endif
+
+#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
+static int __init get_cpu_for_node(struct device_node *node)
+{
+ struct device_node *cpu_node;
+ int cpu;
+
+ cpu_node = of_parse_phandle(node, "cpu", 0);
+ if (!cpu_node)
+ return -1;
+
+ cpu = of_cpu_node_to_id(cpu_node);
+ if (cpu >= 0)
+ topology_parse_cpu_capacity(cpu_node, cpu);
+ else
+ pr_crit("Unable to find CPU node for %pOF\n", cpu_node);
+
+ of_node_put(cpu_node);
+ return cpu;
+}
+
+static int __init parse_core(struct device_node *core, int package_id,
+ int core_id)
+{
+ char name[10];
+ bool leaf = true;
+ int i = 0;
+ int cpu;
+ struct device_node *t;
+
+ do {
+ snprintf(name, sizeof(name), "thread%d", i);
+ t = of_get_child_by_name(core, name);
+ if (t) {
+ leaf = false;
+ cpu = get_cpu_for_node(t);
+ if (cpu >= 0) {
+ cpu_topology[cpu].package_id = package_id;
+ cpu_topology[cpu].core_id = core_id;
+ cpu_topology[cpu].thread_id = i;
+ } else {
+ pr_err("%pOF: Can't get CPU for thread\n",
+ t);
+ of_node_put(t);
+ return -EINVAL;
+ }
+ of_node_put(t);
+ }
+ i++;
+ } while (t);
+
+ cpu = get_cpu_for_node(core);
+ if (cpu >= 0) {
+ if (!leaf) {
+ pr_err("%pOF: Core has both threads and CPU\n",
+ core);
+ return -EINVAL;
+ }
+
+ cpu_topology[cpu].package_id = package_id;
+ cpu_topology[cpu].core_id = core_id;
+ } else if (leaf) {
+ pr_err("%pOF: Can't get CPU for leaf core\n", core);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_cluster(struct device_node *cluster, int depth)
+{
+ char name[10];
+ bool leaf = true;
+ bool has_cores = false;
+ struct device_node *c;
+ static int package_id __initdata;
+ int core_id = 0;
+ int i, ret;
+
+ /*
+ * First check for child clusters; we currently ignore any
+ * information about the nesting of clusters and present the
+ * scheduler with a flat list of them.
+ */
+ i = 0;
+ do {
+ snprintf(name, sizeof(name), "cluster%d", i);
+ c = of_get_child_by_name(cluster, name);
+ if (c) {
+ leaf = false;
+ ret = parse_cluster(c, depth + 1);
+ of_node_put(c);
+ if (ret != 0)
+ return ret;
+ }
+ i++;
+ } while (c);
+
+ /* Now check for cores */
+ i = 0;
+ do {
+ snprintf(name, sizeof(name), "core%d", i);
+ c = of_get_child_by_name(cluster, name);
+ if (c) {
+ has_cores = true;
+
+ if (depth == 0) {
+ pr_err("%pOF: cpu-map children should be clusters\n",
+ c);
+ of_node_put(c);
+ return -EINVAL;
+ }
+
+ if (leaf) {
+ ret = parse_core(c, package_id, core_id++);
+ } else {
+ pr_err("%pOF: Non-leaf cluster with core %s\n",
+ cluster, name);
+ ret = -EINVAL;
+ }
+
+ of_node_put(c);
+ if (ret != 0)
+ return ret;
+ }
+ i++;
+ } while (c);
+
+ if (leaf && !has_cores)
+ pr_warn("%pOF: empty cluster\n", cluster);
+
+ if (leaf)
+ package_id++;
+
+ return 0;
+}
+
+static int __init parse_dt_topology(void)
+{
+ struct device_node *cn, *map;
+ int ret = 0;
+ int cpu;
+
+ cn = of_find_node_by_path("/cpus");
+ if (!cn) {
+ pr_err("No CPU information found in DT\n");
+ return 0;
+ }
+
+ /*
+ * When topology is provided cpu-map is essentially a root
+ * cluster with restricted subnodes.
+ */
+ map = of_get_child_by_name(cn, "cpu-map");
+ if (!map)
+ goto out;
+
+ ret = parse_cluster(map, 0);
+ if (ret != 0)
+ goto out_map;
+
+ topology_normalize_cpu_scale();
+
+ /*
+ * Check that all cores are in the topology; the SMP code will
+ * only mark cores described in the DT as possible.
+ */
+ for_each_possible_cpu(cpu)
+ if (cpu_topology[cpu].package_id == -1)
+ ret = -EINVAL;
+
+out_map:
+ of_node_put(map);
+out:
+ of_node_put(cn);
+ return ret;
+}
+#endif
+
+/*
+ * cpu topology table
+ */
+struct cpu_topology cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+ const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu));
+
+ /* Find the smaller of NUMA, core or LLC siblings */
+ if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) {
+ /* not numa in package, lets use the package siblings */
+ core_mask = &cpu_topology[cpu].core_sibling;
+ }
+ if (cpu_topology[cpu].llc_id != -1) {
+ if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask))
+ core_mask = &cpu_topology[cpu].llc_sibling;
+ }
+
+ return core_mask;
+}
+
+void update_siblings_masks(unsigned int cpuid)
+{
+ struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
+ int cpu;
+
+ /* update core and thread sibling masks */
+ for_each_online_cpu(cpu) {
+ cpu_topo = &cpu_topology[cpu];
+
+ if (cpuid_topo->llc_id == cpu_topo->llc_id) {
+ cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
+ cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
+ }
+
+ if (cpuid_topo->package_id != cpu_topo->package_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+ cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
+
+ if (cpuid_topo->core_id != cpu_topo->core_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
+ cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
+ }
+}
+
+static void clear_cpu_topology(int cpu)
+{
+ struct cpu_topology *cpu_topo = &cpu_topology[cpu];
+
+ cpumask_clear(&cpu_topo->llc_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
+
+ cpumask_clear(&cpu_topo->core_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
+ cpumask_clear(&cpu_topo->thread_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
+}
+
+void __init reset_cpu_topology(void)
+{
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct cpu_topology *cpu_topo = &cpu_topology[cpu];
+
+ cpu_topo->thread_id = -1;
+ cpu_topo->core_id = -1;
+ cpu_topo->package_id = -1;
+ cpu_topo->llc_id = -1;
+
+ clear_cpu_topology(cpu);
+ }
+}
+
+void remove_cpu_topology(unsigned int cpu)
+{
+ int sibling;
+
+ for_each_cpu(sibling, topology_core_cpumask(cpu))
+ cpumask_clear_cpu(cpu, topology_core_cpumask(sibling));
+ for_each_cpu(sibling, topology_sibling_cpumask(cpu))
+ cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
+ for_each_cpu(sibling, topology_llc_cpumask(cpu))
+ cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling));
+
+ clear_cpu_topology(cpu);
+}
+
+__weak int __init parse_acpi_topology(void)
+{
+ return 0;
+}
+
+#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
+void __init init_cpu_topology(void)
+{
+ reset_cpu_topology();
+
+ /*
+ * Discard anything that was parsed if we hit an error so we
+ * don't use partial information.
+ */
+ if (parse_acpi_topology())
+ reset_cpu_topology();
+ else if (of_have_populated_dt() && parse_dt_topology())
+ reset_cpu_topology();
+}
+#endif
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b405436ee28e..0d32544b6f91 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -165,6 +165,7 @@ static inline int devtmpfs_init(void) { return 0; }
/* Device links support */
extern int device_links_read_lock(void);
extern void device_links_read_unlock(int idx);
+extern int device_links_read_lock_held(void);
extern int device_links_check_suppliers(struct device *dev);
extern void device_links_driver_bound(struct device *dev);
extern void device_links_driver_cleanup(struct device *dev);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index da84a73f2ba6..f0dd8e38fee3 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -68,6 +68,11 @@ void device_links_read_unlock(int idx)
{
srcu_read_unlock(&device_links_srcu, idx);
}
+
+int device_links_read_lock_held(void)
+{
+ return srcu_read_lock_held(&device_links_srcu);
+}
#else /* !CONFIG_SRCU */
static DECLARE_RWSEM(device_links_lock);
@@ -91,6 +96,13 @@ void device_links_read_unlock(int not_used)
{
up_read(&device_links_lock);
}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+int device_links_read_lock_held(void)
+{
+ return lockdep_is_held(&device_links_lock);
+}
+#endif
#endif /* !CONFIG_SRCU */
/**
@@ -1663,6 +1675,9 @@ void device_initialize(struct device *dev)
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
+#ifdef CONFIG_PROVE_LOCKING
+ mutex_init(&dev->lockdep_mutex);
+#endif
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
@@ -1820,12 +1835,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
*/
static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
{
+ unsigned int ref;
+
/* see if we live in a "glue" directory */
if (!live_in_glue_dir(glue_dir, dev))
return;
mutex_lock(&gdp_mutex);
- if (!kobject_has_children(glue_dir))
+ /**
+ * There is a race condition between removing glue directory
+ * and adding a new device under the glue directory.
+ *
+ * CPU1: CPU2:
+ *
+ * device_add()
+ * get_device_parent()
+ * class_dir_create_and_add()
+ * kobject_add_internal()
+ * create_dir() // create glue_dir
+ *
+ * device_add()
+ * get_device_parent()
+ * kobject_get() // get glue_dir
+ *
+ * device_del()
+ * cleanup_glue_dir()
+ * kobject_del(glue_dir)
+ *
+ * kobject_add()
+ * kobject_add_internal()
+ * create_dir() // in glue_dir
+ * sysfs_create_dir_ns()
+ * kernfs_create_dir_ns(sd)
+ *
+ * sysfs_remove_dir() // glue_dir->sd=NULL
+ * sysfs_put() // free glue_dir->sd
+ *
+ * // sd is freed
+ * kernfs_new_node(sd)
+ * kernfs_get(glue_dir)
+ * kernfs_add_one()
+ * kernfs_put()
+ *
+ * Before CPU1 remove last child device under glue dir, if CPU2 add
+ * a new device under glue dir, the glue_dir kobject reference count
+ * will be increase to 2 in kobject_get(k). And CPU2 has been called
+ * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
+ * and sysfs_put(). This result in glue_dir->sd is freed.
+ *
+ * Then the CPU2 will see a stale "empty" but still potentially used
+ * glue dir around in kernfs_new_node().
+ *
+ * In order to avoid this happening, we also should make sure that
+ * kernfs_node for glue_dir is released in CPU1 only when refcount
+ * for glue_dir kobj is 1.
+ */
+ ref = kref_read(&glue_dir->kref);
+ if (!kobject_has_children(glue_dir) && !--ref)
kobject_del(glue_dir);
kobject_put(glue_dir);
mutex_unlock(&gdp_mutex);
@@ -2211,6 +2277,24 @@ void put_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(put_device);
+bool kill_device(struct device *dev)
+{
+ /*
+ * Require the device lock and set the "dead" flag to guarantee that
+ * the update behavior is consistent with the other bitfields near
+ * it and that we cannot have an asynchronous probe routine trying
+ * to run while we are tearing out the bus/class/sysfs from
+ * underneath the device.
+ */
+ lockdep_assert_held(&dev->mutex);
+
+ if (dev->p->dead)
+ return false;
+ dev->p->dead = true;
+ return true;
+}
+EXPORT_SYMBOL_GPL(kill_device);
+
/**
* device_del - delete device from system.
* @dev: device.
@@ -2230,15 +2314,8 @@ void device_del(struct device *dev)
struct kobject *glue_dir = NULL;
struct class_interface *class_intf;
- /*
- * Hold the device lock and set the "dead" flag to guarantee that
- * the update behavior is consistent with the other bitfields near
- * it and that we cannot have an asynchronous probe routine trying
- * to run while we are tearing out the bus/class/sysfs from
- * underneath the device.
- */
device_lock(dev);
- dev->p->dead = true;
+ kill_device(dev);
device_unlock(dev);
/* Notify clients of device removal. This call must come
diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h
index 7048a41973ed..7ecd590e67fe 100644
--- a/drivers/base/firmware_loader/firmware.h
+++ b/drivers/base/firmware_loader/firmware.h
@@ -141,8 +141,8 @@ int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
int fw_map_paged_buf(struct fw_priv *fw_priv);
#else
static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
-int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
-int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
+static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
+static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
#endif
#endif /* __FIRMWARE_LOADER_H */
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 506a0175a5a7..ec974ba9c0c4 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -157,8 +157,13 @@ int platform_get_irq(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))
- return acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+ if (num == 0 && has_acpi_companion(&dev->dev)) {
+ int ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+
+ /* Our callers expect -ENXIO for missing IRQs. */
+ if (ret >= 0 || ret == -EPROBE_DEFER)
+ return ret;
+ }
return -ENXIO;
#endif
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b75335508d2c..50def99df970 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -287,7 +287,8 @@ static int rpm_get_suppliers(struct device *dev)
{
struct device_link *link;
- list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+ device_links_read_lock_held()) {
int retval;
if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
@@ -309,7 +310,8 @@ static void rpm_put_suppliers(struct device *dev)
{
struct device_link *link;
- list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+ device_links_read_lock_held()) {
if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
continue;
@@ -1640,7 +1642,8 @@ void pm_runtime_clean_up_links(struct device *dev)
idx = device_links_read_lock();
- list_for_each_entry_rcu(link, &dev->links.consumers, s_node) {
+ list_for_each_entry_rcu(link, &dev->links.consumers, s_node,
+ device_links_read_lock_held()) {
if (link->flags & DL_FLAG_STATELESS)
continue;
@@ -1662,7 +1665,8 @@ void pm_runtime_get_suppliers(struct device *dev)
idx = device_links_read_lock();
- list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+ device_links_read_lock_held())
if (link->flags & DL_FLAG_PM_RUNTIME) {
link->supplier_preactivated = true;
refcount_inc(&link->rpm_active);
@@ -1683,7 +1687,8 @@ void pm_runtime_put_suppliers(struct device *dev)
idx = device_links_read_lock();
- list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+ device_links_read_lock_held())
if (link->supplier_preactivated) {
link->supplier_preactivated = false;
if (refcount_dec_not_one(&link->rpm_active))
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index a4984136c19d..0fd6f97ee523 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -44,7 +44,7 @@ config REGMAP_IRQ
config REGMAP_SOUNDWIRE
tristate
- depends on SOUNDWIRE_BUS
+ depends on SOUNDWIRE
config REGMAP_SCCB
tristate
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index e5e1b3a01b1a..e72843fe41df 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -588,14 +588,6 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
}
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
- if (!map->debugfs) {
- dev_warn(map->dev,
- "Failed to create %s debugfs directory\n", name);
-
- kfree(map->debugfs_name);
- map->debugfs_name = NULL;
- return;
- }
debugfs_create_file("name", 0400, map->debugfs,
map, &regmap_name_fops);
@@ -672,10 +664,6 @@ void regmap_debugfs_initcall(void)
struct regmap_debugfs_node *node, *tmp;
regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
- if (!regmap_debugfs_root) {
- pr_warn("regmap: Failed to create debugfs root\n");
- return;
- }
mutex_lock(&regmap_debugfs_early_lock);
list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) {
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index c9dc70ceca5f..3d64c9331a82 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -370,7 +370,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
if (ret < 0) {
dev_err(map->dev, "IRQ thread failed to resume: %d\n",
ret);
- pm_runtime_put(map->dev);
goto exit;
}
}
@@ -425,8 +424,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
dev_err(map->dev,
"Failed to read IRQ status %d\n",
ret);
- if (chip->runtime_pm)
- pm_runtime_put(map->dev);
goto exit;
}
}
@@ -478,8 +475,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
dev_err(map->dev,
"Failed to read IRQ status: %d\n",
ret);
- if (chip->runtime_pm)
- pm_runtime_put(map->dev);
goto exit;
}
}
@@ -513,10 +508,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
}
+exit:
if (chip->runtime_pm)
pm_runtime_put(map->dev);
-exit:
if (chip->handle_post_irq)
chip->handle_post_irq(chip->irq_drv_data);
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 10b280f30217..7c0c5ca5953d 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -33,6 +33,7 @@ static struct bus_type soc_bus_type = {
static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL);
+static DEVICE_ATTR(serial_number, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL);
@@ -57,6 +58,9 @@ static umode_t soc_attribute_mode(struct kobject *kobj,
if ((attr == &dev_attr_revision.attr)
&& (soc_dev->attr->revision != NULL))
return attr->mode;
+ if ((attr == &dev_attr_serial_number.attr)
+ && (soc_dev->attr->serial_number != NULL))
+ return attr->mode;
if ((attr == &dev_attr_soc_id.attr)
&& (soc_dev->attr->soc_id != NULL))
return attr->mode;
@@ -77,6 +81,8 @@ static ssize_t soc_info_get(struct device *dev,
return sprintf(buf, "%s\n", soc_dev->attr->family);
if (attr == &dev_attr_revision)
return sprintf(buf, "%s\n", soc_dev->attr->revision);
+ if (attr == &dev_attr_serial_number)
+ return sprintf(buf, "%s\n", soc_dev->attr->serial_number);
if (attr == &dev_attr_soc_id)
return sprintf(buf, "%s\n", soc_dev->attr->soc_id);
@@ -87,6 +93,7 @@ static ssize_t soc_info_get(struct device *dev,
static struct attribute *soc_attr[] = {
&dev_attr_machine.attr,
&dev_attr_family.attr,
+ &dev_attr_serial_number.attr,
&dev_attr_soc_id.attr,
&dev_attr_revision.attr,
NULL,
@@ -157,6 +164,7 @@ out2:
out1:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(soc_device_register);
/* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */
void soc_device_unregister(struct soc_device *soc_dev)
@@ -166,6 +174,7 @@ void soc_device_unregister(struct soc_device *soc_dev)
device_unregister(&soc_dev->dev);
early_soc_dev_attr = NULL;
}
+EXPORT_SYMBOL_GPL(soc_device_unregister);
static int __init soc_bus_register(void)
{
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 5b49f1b33ebe..e2ea2356da06 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -323,10 +323,14 @@ flush(const char __user *str, size_t cnt, int exiting)
}
flush_scheduled_work();
- /* pass one: without sleeping, do aoedev_downdev */
+ /* pass one: do aoedev_downdev, which might sleep */
+restart1:
spin_lock_irqsave(&devlist_lock, flags);
for (d = devlist; d; d = d->next) {
spin_lock(&d->lock);
+ if (d->flags & DEVFL_TKILL)
+ goto cont;
+
if (exiting) {
/* unconditionally take each device down */
} else if (specified) {
@@ -338,8 +342,11 @@ flush(const char __user *str, size_t cnt, int exiting)
|| d->ref)
goto cont;
+ spin_unlock(&d->lock);
+ spin_unlock_irqrestore(&devlist_lock, flags);
aoedev_downdev(d);
d->flags |= DEVFL_TKILL;
+ goto restart1;
cont:
spin_unlock(&d->lock);
}
@@ -348,7 +355,7 @@ cont:
/* pass two: call freedev, which might sleep,
* for aoedevs marked with DEVFL_TKILL
*/
-restart:
+restart2:
spin_lock_irqsave(&devlist_lock, flags);
for (d = devlist; d; d = d->next) {
spin_lock(&d->lock);
@@ -357,7 +364,7 @@ restart:
spin_unlock(&d->lock);
spin_unlock_irqrestore(&devlist_lock, flags);
freedev(d);
- goto restart;
+ goto restart2;
}
spin_unlock(&d->lock);
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 85f20e371f2f..bd7d3bb8b890 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1726,6 +1726,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
/* MSch: invalidate default_params */
default_params[drive].blocks = 0;
set_capacity(floppy->disk, MAX_DISK_SIZE * 2);
+ /* Fall through */
case FDFMTEND:
case FDFLUSH:
/* invalidate the buffer track to force a reread */
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 9bd4ddd12b25..5b248763a672 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -322,6 +322,8 @@ static int drbd_thread_setup(void *arg)
thi->name[0],
resource->name);
+ allow_kernel_signal(DRBD_SIGKILL);
+ allow_kernel_signal(SIGXCPU);
restart:
retval = thi->function(thi);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 90ebfcae0ce6..2b3103c30857 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -5417,7 +5417,7 @@ static int drbd_do_auth(struct drbd_connection *connection)
unsigned int key_len;
char secret[SHARED_SECRET_MAX]; /* 64 byte */
unsigned int resp_size;
- SHASH_DESC_ON_STACK(desc, connection->cram_hmac_tfm);
+ struct shash_desc *desc;
struct packet_info pi;
struct net_conf *nc;
int err, rv;
@@ -5430,6 +5430,13 @@ static int drbd_do_auth(struct drbd_connection *connection)
memcpy(secret, nc->shared_secret, key_len);
rcu_read_unlock();
+ desc = kmalloc(sizeof(struct shash_desc) +
+ crypto_shash_descsize(connection->cram_hmac_tfm),
+ GFP_KERNEL);
+ if (!desc) {
+ rv = -1;
+ goto fail;
+ }
desc->tfm = connection->cram_hmac_tfm;
rv = crypto_shash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len);
@@ -5571,7 +5578,10 @@ static int drbd_do_auth(struct drbd_connection *connection)
kfree(peers_ch);
kfree(response);
kfree(right_response);
- shash_desc_zero(desc);
+ if (desc) {
+ shash_desc_zero(desc);
+ kfree(desc);
+ }
return rv;
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 44c9985f352a..ab7ca5989097 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -885,7 +885,7 @@ static void loop_unprepare_queue(struct loop_device *lo)
static int loop_kthread_worker_fn(void *worker_ptr)
{
- current->flags |= PF_LESS_THROTTLE;
+ current->flags |= PF_LESS_THROTTLE | PF_MEMALLOC_NOIO;
return kthread_worker_fn(worker_ptr);
}
@@ -924,6 +924,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
struct file *file;
struct inode *inode;
struct address_space *mapping;
+ struct block_device *claimed_bdev = NULL;
int lo_flags = 0;
int error;
loff_t size;
@@ -942,10 +943,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
* here to avoid changing device under exclusive owner.
*/
if (!(mode & FMODE_EXCL)) {
- bdgrab(bdev);
- error = blkdev_get(bdev, mode | FMODE_EXCL, loop_set_fd);
- if (error)
+ claimed_bdev = bd_start_claiming(bdev, loop_set_fd);
+ if (IS_ERR(claimed_bdev)) {
+ error = PTR_ERR(claimed_bdev);
goto out_putf;
+ }
}
error = mutex_lock_killable(&loop_ctl_mutex);
@@ -1015,15 +1017,15 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
mutex_unlock(&loop_ctl_mutex);
if (partscan)
loop_reread_partitions(lo, bdev);
- if (!(mode & FMODE_EXCL))
- blkdev_put(bdev, mode | FMODE_EXCL);
+ if (claimed_bdev)
+ bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
return 0;
out_unlock:
mutex_unlock(&loop_ctl_mutex);
out_bdev:
- if (!(mode & FMODE_EXCL))
- blkdev_put(bdev, mode | FMODE_EXCL);
+ if (claimed_bdev)
+ bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
out_putf:
fput(file);
out:
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 9bcde2325893..e21d2ded732b 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1231,7 +1231,7 @@ static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
struct block_device *bdev)
{
sock_shutdown(nbd);
- kill_bdev(bdev);
+ __invalidate_device(bdev, true);
nbd_bdev_reset(bdev);
if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
&nbd->config->runtime_flags))
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 3327192bb71f..c8fb886aebd4 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -3038,6 +3038,17 @@ again:
}
return true;
case RBD_OBJ_READ_PARENT:
+ /*
+ * The parent image is read only up to the overlap -- zero-fill
+ * from the overlap to the end of the request.
+ */
+ if (!*result) {
+ u32 obj_overlap = rbd_obj_img_extents_bytes(obj_req);
+
+ if (obj_overlap < obj_req->ex.oe_len)
+ rbd_obj_zero_range(obj_req, obj_overlap,
+ obj_req->ex.oe_len - obj_overlap);
+ }
return true;
default:
BUG();
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 3ac6a5d18071..b90dbcd99c03 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -965,6 +965,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
}
}
+ err = -ENOMEM;
for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
@@ -987,7 +988,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
err = xen_blkif_map(ring, ring_ref, nr_grefs, evtchn);
if (err) {
xenbus_dev_fatal(dev, err, "mapping ring-ref port %u", evtchn);
- return err;
+ goto fail;
}
return 0;
@@ -1007,8 +1008,7 @@ fail:
}
kfree(req);
}
- return -ENOMEM;
-
+ return err;
}
static int connect_ring(struct backend_info *be)
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index a0e84538cec8..1fa58c059cbf 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -337,7 +337,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
usb_free_urb(urb);
- return 0;
+ return err;
}
static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 8b33128dccee..0875470a7806 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -99,6 +99,27 @@ static int qca_send_reset(struct hci_dev *hdev)
return 0;
}
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ int err;
+
+ bt_dev_dbg(hdev, "QCA pre shutdown cmd");
+
+ skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
+ NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
+ return err;
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
static void qca_tlv_check_data(struct rome_config *config,
const struct firmware *fw)
{
@@ -119,6 +140,7 @@ static void qca_tlv_check_data(struct rome_config *config,
BT_DBG("Length\t\t : %d bytes", length);
config->dnld_mode = ROME_SKIP_EVT_NONE;
+ config->dnld_type = ROME_SKIP_EVT_NONE;
switch (config->type) {
case TLV_TYPE_PATCH:
@@ -268,7 +290,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
evt = skb_put(skb, sizeof(*evt));
evt->ncmd = 1;
- evt->opcode = QCA_HCI_CC_OPCODE;
+ evt->opcode = cpu_to_le16(QCA_HCI_CC_OPCODE);
skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
@@ -323,7 +345,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
*/
if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
config->dnld_type == ROME_SKIP_EVT_VSE)
- return qca_inject_cmd_complete_event(hdev);
+ ret = qca_inject_cmd_complete_event(hdev);
out:
release_firmware(fw);
@@ -388,6 +410,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
+ /* Give the controller some time to get ready to receive the NVM */
+ msleep(10);
+
/* Download NVM configuration */
config.type = TLV_TYPE_NVM;
if (firmware_name)
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index 6a291a7a5d96..69c5315a65fd 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -13,6 +13,7 @@
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
#define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
#define MAX_SIZE_PER_TLV_SEGMENT (243)
+#define QCA_PRE_SHUTDOWN_CMD (0xFC08)
#define EDL_CMD_REQ_RES_EVT (0x00)
#define EDL_PATCH_VER_RES_EVT (0x19)
@@ -135,6 +136,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
const char *firmware_name);
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
{
return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
@@ -167,4 +169,9 @@ static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
{
return false;
}
+
+static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 3876fee6ad13..ba4149054304 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -384,6 +384,9 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
+ /* Additional Realtek 8822CE Bluetooth devices */
+ { USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK },
+
/* Silicon Wave based devices */
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
@@ -1170,10 +1173,6 @@ static int btusb_open(struct hci_dev *hdev)
}
data->intf->needs_remote_wakeup = 1;
- /* device specific wakeup source enabled and required for USB
- * remote wakeup while host is suspended
- */
- device_wakeup_enable(&data->udev->dev);
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done;
@@ -1238,7 +1237,6 @@ static int btusb_close(struct hci_dev *hdev)
goto failed;
data->intf->needs_remote_wakeup = 0;
- device_wakeup_disable(&data->udev->dev);
usb_autopm_put_interface(data->intf);
failed:
@@ -2762,8 +2760,10 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
fw_size = fw->size;
/* The size of patch header is 30 bytes, should be skip */
- if (fw_size < 30)
+ if (fw_size < 30) {
+ err = -EINVAL;
goto err_release_fw;
+ }
fw_size -= 30;
fw_ptr += 30;
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index a55be205b91a..dbfe34664633 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -98,6 +98,9 @@ static int ath_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
+ if (!hci_uart_has_flow_control(hu))
+ return -EOPNOTSUPP;
+
ath = kzalloc(sizeof(*ath), GFP_KERNEL);
if (!ath)
return -ENOMEM;
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 8905ad2edde7..ae2624fce913 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -406,6 +406,9 @@ static int bcm_open(struct hci_uart *hu)
bt_dev_dbg(hu->hdev, "hu %p", hu);
+ if (!hci_uart_has_flow_control(hu))
+ return -EOPNOTSUPP;
+
bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
if (!bcm)
return -ENOMEM;
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 207bae5e0d46..31f25153087d 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -391,6 +391,9 @@ static int intel_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
+ if (!hci_uart_has_flow_control(hu))
+ return -EOPNOTSUPP;
+
intel = kzalloc(sizeof(*intel), GFP_KERNEL);
if (!intel)
return -ENOMEM;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 8950e07889fe..85a30fb9177b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -292,6 +292,19 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
+/* Check the underlying device or tty has flow control support */
+bool hci_uart_has_flow_control(struct hci_uart *hu)
+{
+ /* serdev nodes check if the needed operations are present */
+ if (hu->serdev)
+ return true;
+
+ if (hu->tty->driver->ops->tiocmget && hu->tty->driver->ops->tiocmset)
+ return true;
+
+ return false;
+}
+
/* Flow control or un-flow control the device */
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
{
diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c
index f98e5cc343b2..fbc3f7c3a5c7 100644
--- a/drivers/bluetooth/hci_mrvl.c
+++ b/drivers/bluetooth/hci_mrvl.c
@@ -59,6 +59,9 @@ static int mrvl_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
+ if (!hci_uart_has_flow_control(hu))
+ return -EOPNOTSUPP;
+
mrvl = kzalloc(sizeof(*mrvl), GFP_KERNEL);
if (!mrvl)
return -ENOMEM;
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 9a5c9c1f9484..31dec435767b 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -309,13 +309,14 @@ static void qca_wq_awake_device(struct work_struct *work)
ws_awake_device);
struct hci_uart *hu = qca->hu;
unsigned long retrans_delay;
+ unsigned long flags;
BT_DBG("hu %p wq awake device", hu);
/* Vote for serial clock */
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
- spin_lock(&qca->hci_ibs_lock);
+ spin_lock_irqsave(&qca->hci_ibs_lock, flags);
/* Send wake indication to device */
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
@@ -327,7 +328,7 @@ static void qca_wq_awake_device(struct work_struct *work)
retrans_delay = msecs_to_jiffies(qca->wake_retrans);
mod_timer(&qca->wake_retrans_timer, jiffies + retrans_delay);
- spin_unlock(&qca->hci_ibs_lock);
+ spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
/* Actually send the packets */
hci_uart_tx_wakeup(hu);
@@ -338,12 +339,13 @@ static void qca_wq_awake_rx(struct work_struct *work)
struct qca_data *qca = container_of(work, struct qca_data,
ws_awake_rx);
struct hci_uart *hu = qca->hu;
+ unsigned long flags;
BT_DBG("hu %p wq awake rx", hu);
serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- spin_lock(&qca->hci_ibs_lock);
+ spin_lock_irqsave(&qca->hci_ibs_lock, flags);
qca->rx_ibs_state = HCI_IBS_RX_AWAKE;
/* Always acknowledge device wake up,
@@ -354,7 +356,7 @@ static void qca_wq_awake_rx(struct work_struct *work)
qca->ibs_sent_wacks++;
- spin_unlock(&qca->hci_ibs_lock);
+ spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
/* Actually send the packets */
hci_uart_tx_wakeup(hu);
@@ -473,6 +475,9 @@ static int qca_open(struct hci_uart *hu)
BT_DBG("hu %p qca_open", hu);
+ if (!hci_uart_has_flow_control(hu))
+ return -EOPNOTSUPP;
+
qca = kzalloc(sizeof(struct qca_data), GFP_KERNEL);
if (!qca)
return -ENOMEM;
@@ -702,7 +707,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
unsigned long flags;
struct qca_data *qca = hu->priv;
- BT_DBG("hu %p want to sleep", hu);
+ BT_DBG("hu %p want to sleep in %d state", hu, qca->rx_ibs_state);
spin_lock_irqsave(&qca->hci_ibs_lock, flags);
@@ -717,7 +722,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
break;
case HCI_IBS_RX_ASLEEP:
- /* Fall through */
+ break;
default:
/* Any other state is illegal */
@@ -909,7 +914,7 @@ static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
if (hdr->evt == HCI_EV_VENDOR)
complete(&qca->drop_ev_comp);
- kfree(skb);
+ kfree_skb(skb);
return 0;
}
@@ -1383,6 +1388,9 @@ static int qca_power_off(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
+ /* Perform pre shutdown command */
+ qca_send_pre_shutdown_cmd(hdev);
+
qca_power_shutdown(hu);
return 0;
}
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index f11af3912ce6..6ab631101019 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -104,6 +104,7 @@ int hci_uart_wait_until_sent(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu);
void hci_uart_init_work(struct work_struct *work);
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
+bool hci_uart_has_flow_control(struct hci_uart *hu);
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
unsigned int oper_speed);
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 1851112ccc29..6b331061d34b 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -29,6 +29,16 @@ config BRCMSTB_GISB_ARB
arbiter. This driver provides timeout and target abort error handling
and internal bus master decoding.
+config MOXTET
+ tristate "CZ.NIC Turris Mox module configuration bus"
+ depends on SPI_MASTER && OF
+ help
+ Say yes here to add support for the module configuration bus found
+ on CZ.NIC's Turris Mox. This is needed for the ability to discover
+ the order in which the modules are connected and to get/set some of
+ their settings. For example the GPIOs on Mox SFP module are
+ configured through this bus.
+
config HISILICON_LPC
bool "Support for ISA I/O space on HiSilicon Hip06/7"
depends on ARM64 && (ARCH_HISI || COMPILE_TEST)
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index ca300b1914ce..16b43d3468c6 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o
obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
+obj-$(CONFIG_MOXTET) += moxtet.o
# DPAA2 fsl-mc bus
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
index 8ad77246f322..cc7bb900f524 100644
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -330,7 +330,6 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
fsl_mc_resource_free(resource);
- device_link_del(mc_adev->consumer_link);
mc_adev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_object_free);
diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
index 3ae574a58cce..d9629fc13a15 100644
--- a/drivers/bus/fsl-mc/mc-io.c
+++ b/drivers/bus/fsl-mc/mc-io.c
@@ -255,7 +255,6 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
fsl_destroy_mc_io(mc_io);
fsl_mc_resource_free(resource);
- device_link_del(dpmcp_dev->consumer_link);
dpmcp_dev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 19d7b6ff2f17..20c957185af2 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -456,6 +456,17 @@ struct hisi_lpc_acpi_cell {
size_t pdata_size;
};
+static void hisi_lpc_acpi_remove(struct device *hostdev)
+{
+ struct acpi_device *adev = ACPI_COMPANION(hostdev);
+ struct acpi_device *child;
+
+ device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
+
+ list_for_each_entry(child, &adev->children, node)
+ acpi_device_clear_enumerated(child);
+}
+
/*
* hisi_lpc_acpi_probe - probe children for ACPI FW
* @hostdev: LPC host device pointer
@@ -555,8 +566,7 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
return 0;
fail:
- device_for_each_child(hostdev, NULL,
- hisi_lpc_acpi_remove_subdev);
+ hisi_lpc_acpi_remove(hostdev);
return ret;
}
@@ -569,6 +579,10 @@ static int hisi_lpc_acpi_probe(struct device *dev)
{
return -ENODEV;
}
+
+static void hisi_lpc_acpi_remove(struct device *hostdev)
+{
+}
#endif // CONFIG_ACPI
/*
@@ -606,24 +620,27 @@ static int hisi_lpc_probe(struct platform_device *pdev)
range->fwnode = dev->fwnode;
range->flags = LOGIC_PIO_INDIRECT;
range->size = PIO_INDIRECT_SIZE;
+ range->hostdata = lpcdev;
+ range->ops = &hisi_lpc_ops;
+ lpcdev->io_host = range;
ret = logic_pio_register_range(range);
if (ret) {
dev_err(dev, "register IO range failed (%d)!\n", ret);
return ret;
}
- lpcdev->io_host = range;
/* register the LPC host PIO resources */
if (acpi_device)
ret = hisi_lpc_acpi_probe(dev);
else
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
- if (ret)
+ if (ret) {
+ logic_pio_unregister_range(range);
return ret;
+ }
- lpcdev->io_host->hostdata = lpcdev;
- lpcdev->io_host->ops = &hisi_lpc_ops;
+ dev_set_drvdata(dev, lpcdev);
io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
dev_info(dev, "registered range [%pa - %pa]\n",
@@ -632,6 +649,23 @@ static int hisi_lpc_probe(struct platform_device *pdev)
return ret;
}
+static int hisi_lpc_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct acpi_device *acpi_device = ACPI_COMPANION(dev);
+ struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
+ struct logic_pio_hwaddr *range = lpcdev->io_host;
+
+ if (acpi_device)
+ hisi_lpc_acpi_remove(dev);
+ else
+ of_platform_depopulate(dev);
+
+ logic_pio_unregister_range(range);
+
+ return 0;
+}
+
static const struct of_device_id hisi_lpc_of_match[] = {
{ .compatible = "hisilicon,hip06-lpc", },
{ .compatible = "hisilicon,hip07-lpc", },
@@ -645,5 +679,6 @@ static struct platform_driver hisi_lpc_driver = {
.acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
},
.probe = hisi_lpc_probe,
+ .remove = hisi_lpc_remove,
};
builtin_platform_driver(hisi_lpc_driver);
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index db74334ca5ef..28bb65a5613f 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -19,6 +19,8 @@ struct imx_weim_devtype {
unsigned int cs_count;
unsigned int cs_regs_count;
unsigned int cs_stride;
+ unsigned int wcr_offset;
+ unsigned int wcr_bcm;
};
static const struct imx_weim_devtype imx1_weim_devtype = {
@@ -37,6 +39,8 @@ static const struct imx_weim_devtype imx50_weim_devtype = {
.cs_count = 4,
.cs_regs_count = 6,
.cs_stride = 0x18,
+ .wcr_offset = 0x90,
+ .wcr_bcm = BIT(0),
};
static const struct imx_weim_devtype imx51_weim_devtype = {
@@ -72,7 +76,7 @@ static const struct of_device_id weim_id_table[] = {
};
MODULE_DEVICE_TABLE(of, weim_id_table);
-static int __init imx_weim_gpr_setup(struct platform_device *pdev)
+static int imx_weim_gpr_setup(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct property *prop;
@@ -122,10 +126,10 @@ err:
}
/* Parse and set the timing for this device. */
-static int __init weim_timing_setup(struct device *dev,
- struct device_node *np, void __iomem *base,
- const struct imx_weim_devtype *devtype,
- struct cs_timing_state *ts)
+static int weim_timing_setup(struct device *dev,
+ struct device_node *np, void __iomem *base,
+ const struct imx_weim_devtype *devtype,
+ struct cs_timing_state *ts)
{
u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
@@ -183,8 +187,7 @@ static int __init weim_timing_setup(struct device *dev,
return 0;
}
-static int __init weim_parse_dt(struct platform_device *pdev,
- void __iomem *base)
+static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
{
const struct of_device_id *of_id = of_match_device(weim_id_table,
&pdev->dev);
@@ -192,6 +195,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
struct device_node *child;
int ret, have_child = 0;
struct cs_timing_state ts = {};
+ u32 reg;
if (devtype == &imx50_weim_devtype) {
ret = imx_weim_gpr_setup(pdev);
@@ -199,6 +203,17 @@ static int __init weim_parse_dt(struct platform_device *pdev,
return ret;
}
+ if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) {
+ if (devtype->wcr_bcm) {
+ reg = readl(base + devtype->wcr_offset);
+ writel(reg | devtype->wcr_bcm,
+ base + devtype->wcr_offset);
+ } else {
+ dev_err(&pdev->dev, "burst clk mode not supported.\n");
+ return -EINVAL;
+ }
+ }
+
for_each_available_child_of_node(pdev->dev.of_node, child) {
ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
if (ret)
@@ -217,7 +232,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
return ret;
}
-static int __init weim_probe(struct platform_device *pdev)
+static int weim_probe(struct platform_device *pdev)
{
struct resource *res;
struct clk *clk;
@@ -254,8 +269,9 @@ static struct platform_driver weim_driver = {
.name = "imx-weim",
.of_match_table = weim_id_table,
},
+ .probe = weim_probe,
};
-module_platform_driver_probe(weim_driver, weim_probe);
+module_platform_driver(weim_driver);
MODULE_AUTHOR("Freescale Semiconductor Inc.");
MODULE_DESCRIPTION("i.MX EIM Controller Driver");
diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c
new file mode 100644
index 000000000000..36cf13eee6b8
--- /dev/null
+++ b/drivers/bus/moxtet.c
@@ -0,0 +1,885 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Turris Mox module configuration bus driver
+ *
+ * Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <dt-bindings/bus/moxtet.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moxtet.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/spi/spi.h>
+
+/*
+ * @name: module name for sysfs
+ * @hwirq_base: base index for IRQ for this module (-1 if no IRQs)
+ * @nirqs: how many interrupts does the shift register provide
+ * @desc: module description for kernel log
+ */
+static const struct {
+ const char *name;
+ int hwirq_base;
+ int nirqs;
+ const char *desc;
+} mox_module_table[] = {
+ /* do not change order of this array! */
+ { NULL, 0, 0, NULL },
+ { "sfp", -1, 0, "MOX D (SFP cage)" },
+ { "pci", MOXTET_IRQ_PCI, 1, "MOX B (Mini-PCIe)" },
+ { "topaz", MOXTET_IRQ_TOPAZ, 1, "MOX C (4 port switch)" },
+ { "peridot", MOXTET_IRQ_PERIDOT(0), 1, "MOX E (8 port switch)" },
+ { "usb3", MOXTET_IRQ_USB3, 2, "MOX F (USB 3.0)" },
+ { "pci-bridge", -1, 0, "MOX G (Mini-PCIe bridge)" },
+};
+
+static inline bool mox_module_known(unsigned int id)
+{
+ return id >= TURRIS_MOX_MODULE_FIRST && id <= TURRIS_MOX_MODULE_LAST;
+}
+
+static inline const char *mox_module_name(unsigned int id)
+{
+ if (mox_module_known(id))
+ return mox_module_table[id].name;
+ else
+ return "unknown";
+}
+
+#define DEF_MODULE_ATTR(name, fmt, ...) \
+static ssize_t \
+module_##name##_show(struct device *dev, struct device_attribute *a, \
+ char *buf) \
+{ \
+ struct moxtet_device *mdev = to_moxtet_device(dev); \
+ return sprintf(buf, (fmt), __VA_ARGS__); \
+} \
+static DEVICE_ATTR_RO(module_##name)
+
+DEF_MODULE_ATTR(id, "0x%x\n", mdev->id);
+DEF_MODULE_ATTR(name, "%s\n", mox_module_name(mdev->id));
+DEF_MODULE_ATTR(description, "%s\n",
+ mox_module_known(mdev->id) ? mox_module_table[mdev->id].desc
+ : "");
+
+static struct attribute *moxtet_dev_attrs[] = {
+ &dev_attr_module_id.attr,
+ &dev_attr_module_name.attr,
+ &dev_attr_module_description.attr,
+ NULL,
+};
+
+static const struct attribute_group moxtet_dev_group = {
+ .attrs = moxtet_dev_attrs,
+};
+
+static const struct attribute_group *moxtet_dev_groups[] = {
+ &moxtet_dev_group,
+ NULL,
+};
+
+static int moxtet_match(struct device *dev, struct device_driver *drv)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+ struct moxtet_driver *tdrv = to_moxtet_driver(drv);
+ const enum turris_mox_module_id *t;
+
+ if (of_driver_match_device(dev, drv))
+ return 1;
+
+ if (!tdrv->id_table)
+ return 0;
+
+ for (t = tdrv->id_table; *t; ++t)
+ if (*t == mdev->id)
+ return 1;
+
+ return 0;
+}
+
+struct bus_type moxtet_bus_type = {
+ .name = "moxtet",
+ .dev_groups = moxtet_dev_groups,
+ .match = moxtet_match,
+};
+EXPORT_SYMBOL_GPL(moxtet_bus_type);
+
+int __moxtet_register_driver(struct module *owner,
+ struct moxtet_driver *mdrv)
+{
+ mdrv->driver.owner = owner;
+ mdrv->driver.bus = &moxtet_bus_type;
+ return driver_register(&mdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__moxtet_register_driver);
+
+static int moxtet_dev_check(struct device *dev, void *data)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+ struct moxtet_device *new_dev = data;
+
+ if (mdev->moxtet == new_dev->moxtet && mdev->id == new_dev->id &&
+ mdev->idx == new_dev->idx)
+ return -EBUSY;
+ return 0;
+}
+
+static void moxtet_dev_release(struct device *dev)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+
+ put_device(mdev->moxtet->dev);
+ kfree(mdev);
+}
+
+static struct moxtet_device *
+moxtet_alloc_device(struct moxtet *moxtet)
+{
+ struct moxtet_device *dev;
+
+ if (!get_device(moxtet->dev))
+ return NULL;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ put_device(moxtet->dev);
+ return NULL;
+ }
+
+ dev->moxtet = moxtet;
+ dev->dev.parent = moxtet->dev;
+ dev->dev.bus = &moxtet_bus_type;
+ dev->dev.release = moxtet_dev_release;
+
+ device_initialize(&dev->dev);
+
+ return dev;
+}
+
+static int moxtet_add_device(struct moxtet_device *dev)
+{
+ static DEFINE_MUTEX(add_mutex);
+ int ret;
+
+ if (dev->idx >= TURRIS_MOX_MAX_MODULES || dev->id > 0xf)
+ return -EINVAL;
+
+ dev_set_name(&dev->dev, "moxtet-%s.%u", mox_module_name(dev->id),
+ dev->idx);
+
+ mutex_lock(&add_mutex);
+
+ ret = bus_for_each_dev(&moxtet_bus_type, NULL, dev,
+ moxtet_dev_check);
+ if (ret)
+ goto done;
+
+ ret = device_add(&dev->dev);
+ if (ret < 0)
+ dev_err(dev->moxtet->dev, "can't add %s, status %d\n",
+ dev_name(dev->moxtet->dev), ret);
+
+done:
+ mutex_unlock(&add_mutex);
+ return ret;
+}
+
+static int __unregister(struct device *dev, void *null)
+{
+ if (dev->of_node) {
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
+ of_node_put(dev->of_node);
+ }
+
+ device_unregister(dev);
+
+ return 0;
+}
+
+static struct moxtet_device *
+of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
+{
+ struct moxtet_device *dev;
+ u32 val;
+ int ret;
+
+ dev = moxtet_alloc_device(moxtet);
+ if (!dev) {
+ dev_err(moxtet->dev,
+ "Moxtet device alloc error for %pOF\n", nc);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ret = of_property_read_u32(nc, "reg", &val);
+ if (ret) {
+ dev_err(moxtet->dev, "%pOF has no valid 'reg' property (%d)\n",
+ nc, ret);
+ goto err_put;
+ }
+
+ dev->idx = val;
+
+ if (dev->idx >= TURRIS_MOX_MAX_MODULES) {
+ dev_err(moxtet->dev, "%pOF Moxtet address 0x%x out of range\n",
+ nc, dev->idx);
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ dev->id = moxtet->modules[dev->idx];
+
+ if (!dev->id) {
+ dev_err(moxtet->dev, "%pOF Moxtet address 0x%x is empty\n", nc,
+ dev->idx);
+ ret = -ENODEV;
+ goto err_put;
+ }
+
+ of_node_get(nc);
+ dev->dev.of_node = nc;
+
+ ret = moxtet_add_device(dev);
+ if (ret) {
+ dev_err(moxtet->dev,
+ "Moxtet device register error for %pOF\n", nc);
+ of_node_put(nc);
+ goto err_put;
+ }
+
+ return dev;
+
+err_put:
+ put_device(&dev->dev);
+ return ERR_PTR(ret);
+}
+
+static void of_register_moxtet_devices(struct moxtet *moxtet)
+{
+ struct moxtet_device *dev;
+ struct device_node *nc;
+
+ if (!moxtet->dev->of_node)
+ return;
+
+ for_each_available_child_of_node(moxtet->dev->of_node, nc) {
+ if (of_node_test_and_set_flag(nc, OF_POPULATED))
+ continue;
+ dev = of_register_moxtet_device(moxtet, nc);
+ if (IS_ERR(dev)) {
+ dev_warn(moxtet->dev,
+ "Failed to create Moxtet device for %pOF\n",
+ nc);
+ of_node_clear_flag(nc, OF_POPULATED);
+ }
+ }
+}
+
+static void
+moxtet_register_devices_from_topology(struct moxtet *moxtet)
+{
+ struct moxtet_device *dev;
+ int i, ret;
+
+ for (i = 0; i < moxtet->count; ++i) {
+ dev = moxtet_alloc_device(moxtet);
+ if (!dev) {
+ dev_err(moxtet->dev, "Moxtet device %u alloc error\n",
+ i);
+ continue;
+ }
+
+ dev->idx = i;
+ dev->id = moxtet->modules[i];
+
+ ret = moxtet_add_device(dev);
+ if (ret && ret != -EBUSY) {
+ put_device(&dev->dev);
+ dev_err(moxtet->dev,
+ "Moxtet device %u register error: %i\n", i,
+ ret);
+ }
+ }
+}
+
+/*
+ * @nsame: how many modules with same id are already in moxtet->modules
+ */
+static int moxtet_set_irq(struct moxtet *moxtet, int idx, int id, int nsame)
+{
+ int i, first;
+ struct moxtet_irqpos *pos;
+
+ first = mox_module_table[id].hwirq_base +
+ nsame * mox_module_table[id].nirqs;
+
+ if (first + mox_module_table[id].nirqs > MOXTET_NIRQS)
+ return -EINVAL;
+
+ for (i = 0; i < mox_module_table[id].nirqs; ++i) {
+ pos = &moxtet->irq.position[first + i];
+ pos->idx = idx;
+ pos->bit = i;
+ moxtet->irq.exists |= BIT(first + i);
+ }
+
+ return 0;
+}
+
+static int moxtet_find_topology(struct moxtet *moxtet)
+{
+ u8 buf[TURRIS_MOX_MAX_MODULES];
+ int cnts[TURRIS_MOX_MODULE_LAST];
+ int i, ret;
+
+ memset(cnts, 0, sizeof(cnts));
+
+ ret = spi_read(to_spi_device(moxtet->dev), buf, TURRIS_MOX_MAX_MODULES);
+ if (ret < 0)
+ return ret;
+
+ if (buf[0] == TURRIS_MOX_CPU_ID_EMMC) {
+ dev_info(moxtet->dev, "Found MOX A (eMMC CPU) module\n");
+ } else if (buf[0] == TURRIS_MOX_CPU_ID_SD) {
+ dev_info(moxtet->dev, "Found MOX A (CPU) module\n");
+ } else {
+ dev_err(moxtet->dev, "Invalid Turris MOX A CPU module 0x%02x\n",
+ buf[0]);
+ return -ENODEV;
+ }
+
+ moxtet->count = 0;
+
+ for (i = 1; i < TURRIS_MOX_MAX_MODULES; ++i) {
+ int id;
+
+ if (buf[i] == 0xff)
+ break;
+
+ id = buf[i] & 0xf;
+
+ moxtet->modules[i-1] = id;
+ ++moxtet->count;
+
+ if (mox_module_known(id)) {
+ dev_info(moxtet->dev, "Found %s module\n",
+ mox_module_table[id].desc);
+
+ if (moxtet_set_irq(moxtet, i-1, id, cnts[id]++) < 0)
+ dev_err(moxtet->dev,
+ " Cannot set IRQ for module %s\n",
+ mox_module_table[id].desc);
+ } else {
+ dev_warn(moxtet->dev,
+ "Unknown Moxtet module found (ID 0x%02x)\n",
+ id);
+ }
+ }
+
+ return 0;
+}
+
+static int moxtet_spi_read(struct moxtet *moxtet, u8 *buf)
+{
+ struct spi_transfer xfer = {
+ .rx_buf = buf,
+ .tx_buf = moxtet->tx,
+ .len = moxtet->count + 1
+ };
+ int ret;
+
+ mutex_lock(&moxtet->lock);
+
+ ret = spi_sync_transfer(to_spi_device(moxtet->dev), &xfer, 1);
+
+ mutex_unlock(&moxtet->lock);
+
+ return ret;
+}
+
+int moxtet_device_read(struct device *dev)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+ struct moxtet *moxtet = mdev->moxtet;
+ u8 buf[TURRIS_MOX_MAX_MODULES];
+ int ret;
+
+ if (mdev->idx >= moxtet->count)
+ return -EINVAL;
+
+ ret = moxtet_spi_read(moxtet, buf);
+ if (ret < 0)
+ return ret;
+
+ return buf[mdev->idx + 1] >> 4;
+}
+EXPORT_SYMBOL_GPL(moxtet_device_read);
+
+int moxtet_device_write(struct device *dev, u8 val)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+ struct moxtet *moxtet = mdev->moxtet;
+ int ret;
+
+ if (mdev->idx >= moxtet->count)
+ return -EINVAL;
+
+ mutex_lock(&moxtet->lock);
+
+ moxtet->tx[moxtet->count - mdev->idx] = val;
+
+ ret = spi_write(to_spi_device(moxtet->dev), moxtet->tx,
+ moxtet->count + 1);
+
+ mutex_unlock(&moxtet->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(moxtet_device_write);
+
+int moxtet_device_written(struct device *dev)
+{
+ struct moxtet_device *mdev = to_moxtet_device(dev);
+ struct moxtet *moxtet = mdev->moxtet;
+
+ if (mdev->idx >= moxtet->count)
+ return -EINVAL;
+
+ return moxtet->tx[moxtet->count - mdev->idx];
+}
+EXPORT_SYMBOL_GPL(moxtet_device_written);
+
+#ifdef CONFIG_DEBUG_FS
+static int moxtet_debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t input_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct moxtet *moxtet = file->private_data;
+ u8 bin[TURRIS_MOX_MAX_MODULES];
+ u8 hex[sizeof(buf) * 2 + 1];
+ int ret, n;
+
+ ret = moxtet_spi_read(moxtet, bin);
+ if (ret < 0)
+ return ret;
+
+ n = moxtet->count + 1;
+ bin2hex(hex, bin, n);
+
+ hex[2*n] = '\n';
+
+ return simple_read_from_buffer(buf, len, ppos, hex, 2*n + 1);
+}
+
+static const struct file_operations input_fops = {
+ .owner = THIS_MODULE,
+ .open = moxtet_debug_open,
+ .read = input_read,
+ .llseek = no_llseek,
+};
+
+static ssize_t output_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct moxtet *moxtet = file->private_data;
+ u8 hex[TURRIS_MOX_MAX_MODULES * 2 + 1];
+ u8 *p = hex;
+ int i;
+
+ mutex_lock(&moxtet->lock);
+
+ for (i = 0; i < moxtet->count; ++i)
+ p = hex_byte_pack(p, moxtet->tx[moxtet->count - i]);
+
+ mutex_unlock(&moxtet->lock);
+
+ *p++ = '\n';
+
+ return simple_read_from_buffer(buf, len, ppos, hex, p - hex);
+}
+
+static ssize_t output_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct moxtet *moxtet = file->private_data;
+ u8 bin[TURRIS_MOX_MAX_MODULES];
+ u8 hex[sizeof(bin) * 2 + 1];
+ ssize_t res;
+ loff_t dummy = 0;
+ int err, i;
+
+ if (len > 2 * moxtet->count + 1 || len < 2 * moxtet->count)
+ return -EINVAL;
+
+ res = simple_write_to_buffer(hex, sizeof(hex), &dummy, buf, len);
+ if (res < 0)
+ return res;
+
+ if (len % 2 == 1 && hex[len - 1] != '\n')
+ return -EINVAL;
+
+ err = hex2bin(bin, hex, moxtet->count);
+ if (err < 0)
+ return -EINVAL;
+
+ mutex_lock(&moxtet->lock);
+
+ for (i = 0; i < moxtet->count; ++i)
+ moxtet->tx[moxtet->count - i] = bin[i];
+
+ err = spi_write(to_spi_device(moxtet->dev), moxtet->tx,
+ moxtet->count + 1);
+
+ mutex_unlock(&moxtet->lock);
+
+ return err < 0 ? err : len;
+}
+
+static const struct file_operations output_fops = {
+ .owner = THIS_MODULE,
+ .open = moxtet_debug_open,
+ .read = output_read,
+ .write = output_write,
+ .llseek = no_llseek,
+};
+
+static int moxtet_register_debugfs(struct moxtet *moxtet)
+{
+ struct dentry *root, *entry;
+
+ root = debugfs_create_dir("moxtet", NULL);
+
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+
+ entry = debugfs_create_file_unsafe("input", 0444, root, moxtet,
+ &input_fops);
+ if (IS_ERR(entry))
+ goto err_remove;
+
+ entry = debugfs_create_file_unsafe("output", 0644, root, moxtet,
+ &output_fops);
+ if (IS_ERR(entry))
+ goto err_remove;
+
+ moxtet->debugfs_root = root;
+
+ return 0;
+err_remove:
+ debugfs_remove_recursive(root);
+ return PTR_ERR(entry);
+}
+
+static void moxtet_unregister_debugfs(struct moxtet *moxtet)
+{
+ debugfs_remove_recursive(moxtet->debugfs_root);
+}
+#else
+static inline int moxtet_register_debugfs(struct moxtet *moxtet)
+{
+ return 0;
+}
+
+static inline void moxtet_unregister_debugfs(struct moxtet *moxtet)
+{
+}
+#endif
+
+static int moxtet_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct moxtet *moxtet = d->host_data;
+
+ if (hw >= MOXTET_NIRQS || !(moxtet->irq.exists & BIT(hw))) {
+ dev_err(moxtet->dev, "Invalid hw irq number\n");
+ return -EINVAL;
+ }
+
+ irq_set_chip_data(irq, d->host_data);
+ irq_set_chip_and_handler(irq, &moxtet->irq.chip, handle_level_irq);
+
+ return 0;
+}
+
+static int moxtet_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ struct moxtet *moxtet = d->host_data;
+ int irq;
+
+ if (WARN_ON(intsize < 1))
+ return -EINVAL;
+
+ irq = intspec[0];
+
+ if (irq >= MOXTET_NIRQS || !(moxtet->irq.exists & BIT(irq)))
+ return -EINVAL;
+
+ *out_hwirq = irq;
+ *out_type = IRQ_TYPE_NONE;
+ return 0;
+}
+
+static const struct irq_domain_ops moxtet_irq_domain = {
+ .map = moxtet_irq_domain_map,
+ .xlate = moxtet_irq_domain_xlate,
+};
+
+static void moxtet_irq_mask(struct irq_data *d)
+{
+ struct moxtet *moxtet = irq_data_get_irq_chip_data(d);
+
+ moxtet->irq.masked |= BIT(d->hwirq);
+}
+
+static void moxtet_irq_unmask(struct irq_data *d)
+{
+ struct moxtet *moxtet = irq_data_get_irq_chip_data(d);
+
+ moxtet->irq.masked &= ~BIT(d->hwirq);
+}
+
+static void moxtet_irq_print_chip(struct irq_data *d, struct seq_file *p)
+{
+ struct moxtet *moxtet = irq_data_get_irq_chip_data(d);
+ struct moxtet_irqpos *pos = &moxtet->irq.position[d->hwirq];
+ int id;
+
+ id = moxtet->modules[pos->idx];
+
+ seq_printf(p, " moxtet-%s.%i#%i", mox_module_name(id), pos->idx,
+ pos->bit);
+}
+
+static const struct irq_chip moxtet_irq_chip = {
+ .name = "moxtet",
+ .irq_mask = moxtet_irq_mask,
+ .irq_unmask = moxtet_irq_unmask,
+ .irq_print_chip = moxtet_irq_print_chip,
+};
+
+static int moxtet_irq_read(struct moxtet *moxtet, unsigned long *map)
+{
+ struct moxtet_irqpos *pos = moxtet->irq.position;
+ u8 buf[TURRIS_MOX_MAX_MODULES];
+ int i, ret;
+
+ ret = moxtet_spi_read(moxtet, buf);
+ if (ret < 0)
+ return ret;
+
+ *map = 0;
+
+ for_each_set_bit(i, &moxtet->irq.exists, MOXTET_NIRQS) {
+ if (!(buf[pos[i].idx + 1] & BIT(4 + pos[i].bit)))
+ set_bit(i, map);
+ }
+
+ return 0;
+}
+
+static irqreturn_t moxtet_irq_thread_fn(int irq, void *data)
+{
+ struct moxtet *moxtet = data;
+ unsigned long set;
+ int nhandled = 0, i, sub_irq, ret;
+
+ ret = moxtet_irq_read(moxtet, &set);
+ if (ret < 0)
+ goto out;
+
+ set &= ~moxtet->irq.masked;
+
+ do {
+ for_each_set_bit(i, &set, MOXTET_NIRQS) {
+ sub_irq = irq_find_mapping(moxtet->irq.domain, i);
+ handle_nested_irq(sub_irq);
+ dev_dbg(moxtet->dev, "%i irq\n", i);
+ ++nhandled;
+ }
+
+ ret = moxtet_irq_read(moxtet, &set);
+ if (ret < 0)
+ goto out;
+
+ set &= ~moxtet->irq.masked;
+ } while (set);
+
+out:
+ return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void moxtet_irq_free(struct moxtet *moxtet)
+{
+ int i, irq;
+
+ for (i = 0; i < MOXTET_NIRQS; ++i) {
+ if (moxtet->irq.exists & BIT(i)) {
+ irq = irq_find_mapping(moxtet->irq.domain, i);
+ irq_dispose_mapping(irq);
+ }
+ }
+
+ irq_domain_remove(moxtet->irq.domain);
+}
+
+static int moxtet_irq_setup(struct moxtet *moxtet)
+{
+ int i, ret;
+
+ moxtet->irq.domain = irq_domain_add_simple(moxtet->dev->of_node,
+ MOXTET_NIRQS, 0,
+ &moxtet_irq_domain, moxtet);
+ if (moxtet->irq.domain == NULL) {
+ dev_err(moxtet->dev, "Could not add IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < MOXTET_NIRQS; ++i)
+ if (moxtet->irq.exists & BIT(i))
+ irq_create_mapping(moxtet->irq.domain, i);
+
+ moxtet->irq.chip = moxtet_irq_chip;
+ moxtet->irq.masked = ~0;
+
+ ret = request_threaded_irq(moxtet->dev_irq, NULL, moxtet_irq_thread_fn,
+ IRQF_ONESHOT, "moxtet", moxtet);
+ if (ret < 0)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ moxtet_irq_free(moxtet);
+ return ret;
+}
+
+static int moxtet_probe(struct spi_device *spi)
+{
+ struct moxtet *moxtet;
+ int ret;
+
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
+ moxtet = devm_kzalloc(&spi->dev, sizeof(struct moxtet),
+ GFP_KERNEL);
+ if (!moxtet)
+ return -ENOMEM;
+
+ moxtet->dev = &spi->dev;
+ spi_set_drvdata(spi, moxtet);
+
+ mutex_init(&moxtet->lock);
+
+ moxtet->dev_irq = of_irq_get(moxtet->dev->of_node, 0);
+ if (moxtet->dev_irq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (moxtet->dev_irq <= 0) {
+ dev_err(moxtet->dev, "No IRQ resource found\n");
+ return -ENXIO;
+ }
+
+ ret = moxtet_find_topology(moxtet);
+ if (ret < 0)
+ return ret;
+
+ if (moxtet->irq.exists) {
+ ret = moxtet_irq_setup(moxtet);
+ if (ret < 0)
+ return ret;
+ }
+
+ of_register_moxtet_devices(moxtet);
+ moxtet_register_devices_from_topology(moxtet);
+
+ ret = moxtet_register_debugfs(moxtet);
+ if (ret < 0)
+ dev_warn(moxtet->dev, "Failed creating debugfs entries: %i\n",
+ ret);
+
+ return 0;
+}
+
+static int moxtet_remove(struct spi_device *spi)
+{
+ struct moxtet *moxtet = spi_get_drvdata(spi);
+
+ free_irq(moxtet->dev_irq, moxtet);
+
+ moxtet_irq_free(moxtet);
+
+ moxtet_unregister_debugfs(moxtet);
+
+ device_for_each_child(moxtet->dev, NULL, __unregister);
+
+ mutex_destroy(&moxtet->lock);
+
+ return 0;
+}
+
+static const struct of_device_id moxtet_dt_ids[] = {
+ { .compatible = "cznic,moxtet" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, moxtet_dt_ids);
+
+static struct spi_driver moxtet_spi_driver = {
+ .driver = {
+ .name = "moxtet",
+ .of_match_table = moxtet_dt_ids,
+ },
+ .probe = moxtet_probe,
+ .remove = moxtet_remove,
+};
+
+static int __init moxtet_init(void)
+{
+ int ret;
+
+ ret = bus_register(&moxtet_bus_type);
+ if (ret < 0) {
+ pr_err("moxtet bus registration failed: %d\n", ret);
+ goto error;
+ }
+
+ ret = spi_register_driver(&moxtet_spi_driver);
+ if (ret < 0) {
+ pr_err("moxtet spi driver registration failed: %d\n", ret);
+ goto error_bus;
+ }
+
+ return 0;
+
+error_bus:
+ bus_unregister(&moxtet_bus_type);
+error:
+ return ret;
+}
+postcore_initcall_sync(moxtet_init);
+
+static void __exit moxtet_exit(void)
+{
+ spi_unregister_driver(&moxtet_spi_driver);
+ bus_unregister(&moxtet_bus_type);
+}
+module_exit(moxtet_exit);
+
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
+MODULE_DESCRIPTION("CZ.NIC's Turris Mox module configuration bus");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index 1b76d9585902..be79d6c6a4e4 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -651,10 +651,8 @@ static int sunxi_rsb_probe(struct platform_device *pdev)
return PTR_ERR(rsb->regs);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "failed to retrieve irq: %d\n", irq);
+ if (irq < 0)
return irq;
- }
rsb->clk = devm_clk_get(dev, NULL);
if (IS_ERR(rsb->clk)) {
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index e6deabd8305d..2db474ab4c6b 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -949,7 +949,7 @@ static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode)
*best_mode = SYSC_IDLE_SMART_WKUP;
else if (idlemodes & BIT(SYSC_IDLE_SMART))
*best_mode = SYSC_IDLE_SMART;
- else if (idlemodes & SYSC_IDLE_FORCE)
+ else if (idlemodes & BIT(SYSC_IDLE_FORCE))
*best_mode = SYSC_IDLE_FORCE;
else
return -EINVAL;
@@ -1267,7 +1267,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),
SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
0xffff00f0, 0),
- SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
+ SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0xa3170504, 0xffffffff, 0),
+ SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0x4edb1902, 0xffffffff, 0),
SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
@@ -1692,10 +1693,7 @@ static int sysc_init_sysc_mask(struct sysc *ddata)
if (error)
return 0;
- if (val)
- ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
- else
- ddata->cfg.sysc_val = ddata->cap->sysc_mask;
+ ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
return 0;
}
@@ -2385,27 +2383,27 @@ static int sysc_probe(struct platform_device *pdev)
error = sysc_init_dts_quirks(ddata);
if (error)
- goto unprepare;
+ return error;
error = sysc_map_and_check_registers(ddata);
if (error)
- goto unprepare;
+ return error;
error = sysc_init_sysc_mask(ddata);
if (error)
- goto unprepare;
+ return error;
error = sysc_init_idlemodes(ddata);
if (error)
- goto unprepare;
+ return error;
error = sysc_init_syss_mask(ddata);
if (error)
- goto unprepare;
+ return error;
error = sysc_init_pdata(ddata);
if (error)
- goto unprepare;
+ return error;
sysc_init_early_quirks(ddata);
@@ -2415,7 +2413,7 @@ static int sysc_probe(struct platform_device *pdev)
error = sysc_init_resets(ddata);
if (error)
- return error;
+ goto unprepare;
error = sysc_init_module(ddata);
if (error)
diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c
index e845c1a93f21..f70dedace20b 100644
--- a/drivers/bus/uniphier-system-bus.c
+++ b/drivers/bus/uniphier-system-bus.c
@@ -176,7 +176,6 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct uniphier_system_bus_priv *priv;
- struct resource *regs;
const __be32 *ranges;
u32 cells, addr, size;
u64 paddr;
@@ -186,8 +185,7 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->membase = devm_ioremap_resource(dev, regs);
+ priv->membase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->membase))
return PTR_ERR(priv->membase);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3e866885a405..df0fc997dc3e 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -26,28 +26,6 @@ config DEVKMEM
kind of kernel debugging operations.
When in doubt, say "N".
-config SGI_SNSC
- bool "SGI Altix system controller communication support"
- depends on (IA64_SGI_SN2 || IA64_GENERIC)
- help
- If you have an SGI Altix and you want to enable system
- controller communication from user space (you want this!),
- say Y. Otherwise, say N.
-
-config SGI_TIOCX
- bool "SGI TIO CX driver support"
- depends on (IA64_SGI_SN2 || IA64_GENERIC)
- help
- If you have an SGI Altix and you have fpga devices attached
- to your TIO, say Y here, otherwise say N.
-
-config SGI_MBCS
- tristate "SGI FPGA Core Services driver support"
- depends on SGI_TIOCX
- help
- If you have an SGI Altix with an attached SABrick
- say Y or M here, otherwise say N.
-
source "drivers/tty/serial/Kconfig"
source "drivers/tty/serdev/Kconfig"
@@ -573,3 +551,12 @@ config RANDOM_TRUST_CPU
has not installed a hidden back door to compromise the CPU's
random number generation facilities. This can also be configured
at boot with "random.trust_cpu=on/off".
+
+config RANDOM_TRUST_BOOTLOADER
+ bool "Trust the bootloader to initialize Linux's CRNG"
+ help
+ Some bootloaders can provide entropy to increase the kernel's initial
+ device randomness. Say Y here to assume the entropy provided by the
+ booloader is trustworthy so it will be added to the kernel's entropy
+ pool. Otherwise, say N here so it will be regarded as device input that
+ only mixes the entropy pool. \ No newline at end of file
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index fbea7dd12932..7c5ea6f9df14 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -9,11 +9,9 @@ obj-y += misc.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
-obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MSPEC) += mspec.o
obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o
obj-$(CONFIG_IBM_BSR) += bsr.o
-obj-$(CONFIG_SGI_MBCS) += mbcs.o
obj-$(CONFIG_PRINTER) += lp.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 6231714ef3c8..812d6aa6e013 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -111,14 +111,14 @@ config AGP_VIA
config AGP_I460
tristate "Intel 460GX chipset support"
- depends on AGP && (IA64_DIG || IA64_GENERIC)
+ 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_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
+ depends on AGP && IA64
help
This option gives you AGP GART support for the HP ZX1 chipset
for IA64 processors.
@@ -150,13 +150,6 @@ config AGP_EFFICEON
This option gives you AGP support for the Transmeta Efficeon
series processors with integrated northbridges.
-config AGP_SGI_TIOCA
- tristate "SGI TIO chipset AGP support"
- depends on AGP && (IA64_SGI_SN2 || IA64_GENERIC)
- help
- This option gives you AGP GART support for the SGI TIO chipset
- for IA64 processors.
-
config INTEL_GTT
tristate
depends on X86 && PCI
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 4a786ffd9dee..cb2497d157f6 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -16,7 +16,6 @@ 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
-obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o
obj-$(CONFIG_AGP_UNINORTH) += uninorth-agp.o
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
deleted file mode 100644
index e7d5bdc02d93..000000000000
--- a/drivers/char/agp/sgi-agp.c
+++ /dev/null
@@ -1,338 +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) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * SGI TIOCA AGPGART routines.
- *
- */
-
-#include <linux/acpi.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/agp_backend.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/io.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/tioca_provider.h>
-#include "agp.h"
-
-extern int agp_memory_reserved;
-extern uint32_t tioca_gart_found;
-extern struct list_head tioca_list;
-static struct agp_bridge_data **sgi_tioca_agp_bridges;
-
-/*
- * The aperature size and related information is set up at TIOCA init time.
- * Values for this table will be extracted and filled in at
- * sgi_tioca_fetch_size() time.
- */
-
-static struct aper_size_info_fixed sgi_tioca_sizes[] = {
- {0, 0, 0},
-};
-
-static struct page *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
-{
- struct page *page;
- int nid;
- struct tioca_kernel *info =
- (struct tioca_kernel *)bridge->dev_private_data;
-
- nid = info->ca_closest_node;
- page = alloc_pages_node(nid, GFP_KERNEL, 0);
- if (!page)
- return NULL;
-
- get_page(page);
- atomic_inc(&agp_bridge->current_memory_agp);
- return page;
-}
-
-/*
- * Flush GART tlb's. Cannot selectively flush based on memory so the mem
- * arg is ignored.
- */
-
-static void sgi_tioca_tlbflush(struct agp_memory *mem)
-{
- tioca_tlbflush(mem->bridge->dev_private_data);
-}
-
-/*
- * Given an address of a host physical page, turn it into a valid gart
- * entry.
- */
-static unsigned long
-sgi_tioca_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
- int type)
-{
- return tioca_physpage_to_gart(addr);
-}
-
-static void sgi_tioca_agp_enable(struct agp_bridge_data *bridge, u32 mode)
-{
- tioca_fastwrite_enable(bridge->dev_private_data);
-}
-
-/*
- * sgi_tioca_configure() doesn't have anything to do since the base CA driver
- * has alreay set up the GART.
- */
-
-static int sgi_tioca_configure(void)
-{
- return 0;
-}
-
-/*
- * Determine gfx aperature size. This has already been determined by the
- * CA driver init, so just need to set agp_bridge values accordingly.
- */
-
-static int sgi_tioca_fetch_size(void)
-{
- struct tioca_kernel *info =
- (struct tioca_kernel *)agp_bridge->dev_private_data;
-
- sgi_tioca_sizes[0].size = info->ca_gfxap_size / MB(1);
- sgi_tioca_sizes[0].num_entries = info->ca_gfxgart_entries;
-
- return sgi_tioca_sizes[0].size;
-}
-
-static int sgi_tioca_create_gatt_table(struct agp_bridge_data *bridge)
-{
- struct tioca_kernel *info =
- (struct tioca_kernel *)bridge->dev_private_data;
-
- bridge->gatt_table_real = (u32 *) info->ca_gfxgart;
- bridge->gatt_table = bridge->gatt_table_real;
- bridge->gatt_bus_addr = info->ca_gfxgart_base;
-
- return 0;
-}
-
-static int sgi_tioca_free_gatt_table(struct agp_bridge_data *bridge)
-{
- return 0;
-}
-
-static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
- int type)
-{
- int num_entries;
- size_t i;
- off_t j;
- void *temp;
- struct agp_bridge_data *bridge;
- u64 *table;
-
- bridge = mem->bridge;
- if (!bridge)
- return -EINVAL;
-
- table = (u64 *)bridge->gatt_table;
-
- temp = bridge->current_size;
-
- switch (bridge->driver->size_type) {
- case U8_APER_SIZE:
- num_entries = A_SIZE_8(temp)->num_entries;
- break;
- case U16_APER_SIZE:
- num_entries = A_SIZE_16(temp)->num_entries;
- break;
- case U32_APER_SIZE:
- num_entries = A_SIZE_32(temp)->num_entries;
- break;
- case FIXED_APER_SIZE:
- num_entries = A_SIZE_FIX(temp)->num_entries;
- break;
- case LVL2_APER_SIZE:
- return -EINVAL;
- default:
- num_entries = 0;
- break;
- }
-
- num_entries -= agp_memory_reserved / PAGE_SIZE;
- if (num_entries < 0)
- num_entries = 0;
-
- if (type != 0 || mem->type != 0) {
- return -EINVAL;
- }
-
- if ((pg_start + mem->page_count) > num_entries)
- return -EINVAL;
-
- j = pg_start;
-
- while (j < (pg_start + mem->page_count)) {
- if (table[j])
- return -EBUSY;
- j++;
- }
-
- if (!mem->is_flushed) {
- bridge->driver->cache_flush();
- mem->is_flushed = true;
- }
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- table[j] =
- bridge->driver->mask_memory(bridge,
- page_to_phys(mem->pages[i]),
- mem->type);
- }
-
- bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
- int type)
-{
- size_t i;
- struct agp_bridge_data *bridge;
- u64 *table;
-
- bridge = mem->bridge;
- if (!bridge)
- return -EINVAL;
-
- if (type != 0 || mem->type != 0) {
- return -EINVAL;
- }
-
- table = (u64 *)bridge->gatt_table;
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- table[i] = 0;
- }
-
- bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static void sgi_tioca_cache_flush(void)
-{
-}
-
-/*
- * Cleanup. Nothing to do as the CA driver owns the GART.
- */
-
-static void sgi_tioca_cleanup(void)
-{
-}
-
-static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev)
-{
- struct agp_bridge_data *bridge;
-
- list_for_each_entry(bridge, &agp_bridges, list) {
- if (bridge->dev->bus == pdev->bus)
- break;
- }
- return bridge;
-}
-
-const struct agp_bridge_driver sgi_tioca_driver = {
- .owner = THIS_MODULE,
- .size_type = U16_APER_SIZE,
- .configure = sgi_tioca_configure,
- .fetch_size = sgi_tioca_fetch_size,
- .cleanup = sgi_tioca_cleanup,
- .tlb_flush = sgi_tioca_tlbflush,
- .mask_memory = sgi_tioca_mask_memory,
- .agp_enable = sgi_tioca_agp_enable,
- .cache_flush = sgi_tioca_cache_flush,
- .create_gatt_table = sgi_tioca_create_gatt_table,
- .free_gatt_table = sgi_tioca_free_gatt_table,
- .insert_memory = sgi_tioca_insert_memory,
- .remove_memory = sgi_tioca_remove_memory,
- .alloc_by_type = agp_generic_alloc_by_type,
- .free_by_type = agp_generic_free_by_type,
- .agp_alloc_page = sgi_tioca_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
- .agp_type_to_mask_type = agp_generic_type_to_mask_type,
- .cant_use_aperture = true,
- .needs_scratch_page = false,
- .num_aperture_sizes = 1,
-};
-
-static int agp_sgi_init(void)
-{
- unsigned int j;
- struct tioca_kernel *info;
- struct pci_dev *pdev = NULL;
-
- if (tioca_gart_found)
- printk(KERN_INFO PFX "SGI TIO CA GART driver initialized.\n");
- else
- return 0;
-
- sgi_tioca_agp_bridges = kmalloc_array(tioca_gart_found,
- sizeof(struct agp_bridge_data *),
- GFP_KERNEL);
- if (!sgi_tioca_agp_bridges)
- return -ENOMEM;
-
- j = 0;
- list_for_each_entry(info, &tioca_list, ca_list) {
- if (list_empty(info->ca_devices))
- continue;
- list_for_each_entry(pdev, info->ca_devices, bus_list) {
- u8 cap_ptr;
-
- if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
- continue;
- cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
- if (!cap_ptr)
- continue;
- }
- sgi_tioca_agp_bridges[j] = agp_alloc_bridge();
- printk(KERN_INFO PFX "bridge %d = 0x%p\n", j,
- sgi_tioca_agp_bridges[j]);
- if (sgi_tioca_agp_bridges[j]) {
- sgi_tioca_agp_bridges[j]->dev = pdev;
- sgi_tioca_agp_bridges[j]->dev_private_data = info;
- sgi_tioca_agp_bridges[j]->driver = &sgi_tioca_driver;
- sgi_tioca_agp_bridges[j]->gart_bus_addr =
- info->ca_gfxap_base;
- sgi_tioca_agp_bridges[j]->mode = (0x7D << 24) | /* 126 requests */
- (0x1 << 9) | /* SBA supported */
- (0x1 << 5) | /* 64-bit addresses supported */
- (0x1 << 4) | /* FW supported */
- (0x1 << 3) | /* AGP 3.0 mode */
- 0x2; /* 8x transfer only */
- sgi_tioca_agp_bridges[j]->current_size =
- sgi_tioca_agp_bridges[j]->previous_size =
- (void *)&sgi_tioca_sizes[0];
- agp_add_bridge(sgi_tioca_agp_bridges[j]);
- }
- j++;
- }
-
- agp_find_bridge = &sgi_tioca_find_bridge;
- return 0;
-}
-
-static void agp_sgi_cleanup(void)
-{
- kfree(sgi_tioca_agp_bridges);
- sgi_tioca_agp_bridges = NULL;
-}
-
-module_init(agp_sgi_init);
-module_exit(agp_sgi_cleanup);
-
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5c39f20378b8..9ac6671bb514 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -567,8 +567,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
unsigned long long m;
m = hpets->hp_tick_freq + (dis >> 1);
- do_div(m, dis);
- return (unsigned long)m;
+ return div64_ul(m, dis);
}
static int
diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c
index 57204335c5f5..285e0b8f9a97 100644
--- a/drivers/char/ipmi/ipmb_dev_int.c
+++ b/drivers/char/ipmi/ipmb_dev_int.c
@@ -76,7 +76,7 @@ static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count,
struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);
struct ipmb_request_elem *queue_elem;
struct ipmb_msg msg;
- ssize_t ret;
+ ssize_t ret = 0;
memset(&msg, 0, sizeof(msg));
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
deleted file mode 100644
index 0a31b60bee7b..000000000000
--- a/drivers/char/mbcs.c
+++ /dev/null
@@ -1,831 +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) 2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * MOATB Core Services driver.
- */
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/uio.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/tiocx.h>
-#include "mbcs.h"
-
-#define MBCS_DEBUG 0
-#if MBCS_DEBUG
-#define DBG(fmt...) printk(KERN_ALERT fmt)
-#else
-#define DBG(fmt...)
-#endif
-static DEFINE_MUTEX(mbcs_mutex);
-static int mbcs_major;
-
-static LIST_HEAD(soft_list);
-
-/*
- * file operations
- */
-static const struct file_operations mbcs_ops = {
- .owner = THIS_MODULE,
- .open = mbcs_open,
- .llseek = mbcs_sram_llseek,
- .read = mbcs_sram_read,
- .write = mbcs_sram_write,
- .mmap = mbcs_gscr_mmap,
-};
-
-struct mbcs_callback_arg {
- int minor;
- struct cx_dev *cx_dev;
-};
-
-static inline void mbcs_getdma_init(struct getdma *gdma)
-{
- memset(gdma, 0, sizeof(struct getdma));
- gdma->DoneIntEnable = 1;
-}
-
-static inline void mbcs_putdma_init(struct putdma *pdma)
-{
- memset(pdma, 0, sizeof(struct putdma));
- pdma->DoneIntEnable = 1;
-}
-
-static inline void mbcs_algo_init(struct algoblock *algo_soft)
-{
- memset(algo_soft, 0, sizeof(struct algoblock));
-}
-
-static inline void mbcs_getdma_set(void *mmr,
- uint64_t hostAddr,
- uint64_t localAddr,
- uint64_t localRamSel,
- uint64_t numPkts,
- uint64_t amoEnable,
- uint64_t intrEnable,
- uint64_t peerIO,
- uint64_t amoHostDest,
- uint64_t amoModType, uint64_t intrHostDest,
- uint64_t intrVector)
-{
- union dma_control rdma_control;
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union dma_localaddr local_addr;
- union dma_hostaddr host_addr;
-
- rdma_control.dma_control_reg = 0;
- amo_dest.dma_amo_dest_reg = 0;
- intr_dest.intr_dest_reg = 0;
- local_addr.dma_localaddr_reg = 0;
- host_addr.dma_hostaddr_reg = 0;
-
- host_addr.dma_sys_addr = hostAddr;
- MBCS_MMR_SET(mmr, MBCS_RD_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
-
- local_addr.dma_ram_addr = localAddr;
- local_addr.dma_ram_sel = localRamSel;
- MBCS_MMR_SET(mmr, MBCS_RD_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
-
- rdma_control.dma_op_length = numPkts;
- rdma_control.done_amo_en = amoEnable;
- rdma_control.done_int_en = intrEnable;
- rdma_control.pio_mem_n = peerIO;
- MBCS_MMR_SET(mmr, MBCS_RD_DMA_CTRL, rdma_control.dma_control_reg);
-
- amo_dest.dma_amo_sys_addr = amoHostDest;
- amo_dest.dma_amo_mod_type = amoModType;
- MBCS_MMR_SET(mmr, MBCS_RD_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
-
- intr_dest.address = intrHostDest;
- intr_dest.int_vector = intrVector;
- MBCS_MMR_SET(mmr, MBCS_RD_DMA_INT_DEST, intr_dest.intr_dest_reg);
-
-}
-
-static inline void mbcs_putdma_set(void *mmr,
- uint64_t hostAddr,
- uint64_t localAddr,
- uint64_t localRamSel,
- uint64_t numPkts,
- uint64_t amoEnable,
- uint64_t intrEnable,
- uint64_t peerIO,
- uint64_t amoHostDest,
- uint64_t amoModType,
- uint64_t intrHostDest, uint64_t intrVector)
-{
- union dma_control wdma_control;
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union dma_localaddr local_addr;
- union dma_hostaddr host_addr;
-
- wdma_control.dma_control_reg = 0;
- amo_dest.dma_amo_dest_reg = 0;
- intr_dest.intr_dest_reg = 0;
- local_addr.dma_localaddr_reg = 0;
- host_addr.dma_hostaddr_reg = 0;
-
- host_addr.dma_sys_addr = hostAddr;
- MBCS_MMR_SET(mmr, MBCS_WR_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
-
- local_addr.dma_ram_addr = localAddr;
- local_addr.dma_ram_sel = localRamSel;
- MBCS_MMR_SET(mmr, MBCS_WR_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
-
- wdma_control.dma_op_length = numPkts;
- wdma_control.done_amo_en = amoEnable;
- wdma_control.done_int_en = intrEnable;
- wdma_control.pio_mem_n = peerIO;
- MBCS_MMR_SET(mmr, MBCS_WR_DMA_CTRL, wdma_control.dma_control_reg);
-
- amo_dest.dma_amo_sys_addr = amoHostDest;
- amo_dest.dma_amo_mod_type = amoModType;
- MBCS_MMR_SET(mmr, MBCS_WR_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
-
- intr_dest.address = intrHostDest;
- intr_dest.int_vector = intrVector;
- MBCS_MMR_SET(mmr, MBCS_WR_DMA_INT_DEST, intr_dest.intr_dest_reg);
-
-}
-
-static inline void mbcs_algo_set(void *mmr,
- uint64_t amoHostDest,
- uint64_t amoModType,
- uint64_t intrHostDest,
- uint64_t intrVector, uint64_t algoStepCount)
-{
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union algo_step step;
-
- step.algo_step_reg = 0;
- intr_dest.intr_dest_reg = 0;
- amo_dest.dma_amo_dest_reg = 0;
-
- amo_dest.dma_amo_sys_addr = amoHostDest;
- amo_dest.dma_amo_mod_type = amoModType;
- MBCS_MMR_SET(mmr, MBCS_ALG_AMO_DEST, amo_dest.dma_amo_dest_reg);
-
- intr_dest.address = intrHostDest;
- intr_dest.int_vector = intrVector;
- MBCS_MMR_SET(mmr, MBCS_ALG_INT_DEST, intr_dest.intr_dest_reg);
-
- step.alg_step_cnt = algoStepCount;
- MBCS_MMR_SET(mmr, MBCS_ALG_STEP, step.algo_step_reg);
-}
-
-static inline int mbcs_getdma_start(struct mbcs_soft *soft)
-{
- void *mmr_base;
- struct getdma *gdma;
- uint64_t numPkts;
- union cm_control cm_control;
-
- mmr_base = soft->mmr_base;
- gdma = &soft->getdma;
-
- /* check that host address got setup */
- if (!gdma->hostAddr)
- return -1;
-
- numPkts =
- (gdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
-
- /* program engine */
- mbcs_getdma_set(mmr_base, tiocx_dma_addr(gdma->hostAddr),
- gdma->localAddr,
- (gdma->localAddr < MB2) ? 0 :
- (gdma->localAddr < MB4) ? 1 :
- (gdma->localAddr < MB6) ? 2 : 3,
- numPkts,
- gdma->DoneAmoEnable,
- gdma->DoneIntEnable,
- gdma->peerIO,
- gdma->amoHostDest,
- gdma->amoModType,
- gdma->intrHostDest, gdma->intrVector);
-
- /* start engine */
- cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.rd_dma_go = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
-
- return 0;
-
-}
-
-static inline int mbcs_putdma_start(struct mbcs_soft *soft)
-{
- void *mmr_base;
- struct putdma *pdma;
- uint64_t numPkts;
- union cm_control cm_control;
-
- mmr_base = soft->mmr_base;
- pdma = &soft->putdma;
-
- /* check that host address got setup */
- if (!pdma->hostAddr)
- return -1;
-
- numPkts =
- (pdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
-
- /* program engine */
- mbcs_putdma_set(mmr_base, tiocx_dma_addr(pdma->hostAddr),
- pdma->localAddr,
- (pdma->localAddr < MB2) ? 0 :
- (pdma->localAddr < MB4) ? 1 :
- (pdma->localAddr < MB6) ? 2 : 3,
- numPkts,
- pdma->DoneAmoEnable,
- pdma->DoneIntEnable,
- pdma->peerIO,
- pdma->amoHostDest,
- pdma->amoModType,
- pdma->intrHostDest, pdma->intrVector);
-
- /* start engine */
- cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.wr_dma_go = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
-
- return 0;
-
-}
-
-static inline int mbcs_algo_start(struct mbcs_soft *soft)
-{
- struct algoblock *algo_soft = &soft->algo;
- void *mmr_base = soft->mmr_base;
- union cm_control cm_control;
-
- if (mutex_lock_interruptible(&soft->algolock))
- return -ERESTARTSYS;
-
- atomic_set(&soft->algo_done, 0);
-
- mbcs_algo_set(mmr_base,
- algo_soft->amoHostDest,
- algo_soft->amoModType,
- algo_soft->intrHostDest,
- algo_soft->intrVector, algo_soft->algoStepCount);
-
- /* start algorithm */
- cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.alg_done_int_en = 1;
- cm_control.alg_go = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
-
- mutex_unlock(&soft->algolock);
-
- return 0;
-}
-
-static inline ssize_t
-do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr,
- size_t len, loff_t * off)
-{
- int rv = 0;
-
- if (mutex_lock_interruptible(&soft->dmawritelock))
- return -ERESTARTSYS;
-
- atomic_set(&soft->dmawrite_done, 0);
-
- soft->putdma.hostAddr = hostAddr;
- soft->putdma.localAddr = *off;
- soft->putdma.bytes = len;
-
- if (mbcs_putdma_start(soft) < 0) {
- DBG(KERN_ALERT "do_mbcs_sram_dmawrite: "
- "mbcs_putdma_start failed\n");
- rv = -EAGAIN;
- goto dmawrite_exit;
- }
-
- if (wait_event_interruptible(soft->dmawrite_queue,
- atomic_read(&soft->dmawrite_done))) {
- rv = -ERESTARTSYS;
- goto dmawrite_exit;
- }
-
- rv = len;
- *off += len;
-
-dmawrite_exit:
- mutex_unlock(&soft->dmawritelock);
-
- return rv;
-}
-
-static inline ssize_t
-do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr,
- size_t len, loff_t * off)
-{
- int rv = 0;
-
- if (mutex_lock_interruptible(&soft->dmareadlock))
- return -ERESTARTSYS;
-
- atomic_set(&soft->dmawrite_done, 0);
-
- soft->getdma.hostAddr = hostAddr;
- soft->getdma.localAddr = *off;
- soft->getdma.bytes = len;
-
- if (mbcs_getdma_start(soft) < 0) {
- DBG(KERN_ALERT "mbcs_strategy: mbcs_getdma_start failed\n");
- rv = -EAGAIN;
- goto dmaread_exit;
- }
-
- if (wait_event_interruptible(soft->dmaread_queue,
- atomic_read(&soft->dmaread_done))) {
- rv = -ERESTARTSYS;
- goto dmaread_exit;
- }
-
- rv = len;
- *off += len;
-
-dmaread_exit:
- mutex_unlock(&soft->dmareadlock);
-
- return rv;
-}
-
-static int mbcs_open(struct inode *ip, struct file *fp)
-{
- struct mbcs_soft *soft;
- int minor;
-
- mutex_lock(&mbcs_mutex);
- minor = iminor(ip);
-
- /* Nothing protects access to this list... */
- list_for_each_entry(soft, &soft_list, list) {
- if (soft->nasid == minor) {
- fp->private_data = soft->cxdev;
- mutex_unlock(&mbcs_mutex);
- return 0;
- }
- }
-
- mutex_unlock(&mbcs_mutex);
- return -ENODEV;
-}
-
-static ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off)
-{
- struct cx_dev *cx_dev = fp->private_data;
- struct mbcs_soft *soft = cx_dev->soft;
- uint64_t hostAddr;
- int rv = 0;
-
- hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
- if (hostAddr == 0)
- return -ENOMEM;
-
- rv = do_mbcs_sram_dmawrite(soft, hostAddr, len, off);
- if (rv < 0)
- goto exit;
-
- if (copy_to_user(buf, (void *)hostAddr, len))
- rv = -EFAULT;
-
- exit:
- free_pages(hostAddr, get_order(len));
-
- return rv;
-}
-
-static ssize_t
-mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off)
-{
- struct cx_dev *cx_dev = fp->private_data;
- struct mbcs_soft *soft = cx_dev->soft;
- uint64_t hostAddr;
- int rv = 0;
-
- hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
- if (hostAddr == 0)
- return -ENOMEM;
-
- if (copy_from_user((void *)hostAddr, buf, len)) {
- rv = -EFAULT;
- goto exit;
- }
-
- rv = do_mbcs_sram_dmaread(soft, hostAddr, len, off);
-
- exit:
- free_pages(hostAddr, get_order(len));
-
- return rv;
-}
-
-static loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
-{
- return generic_file_llseek_size(filp, off, whence, MAX_LFS_FILESIZE,
- MBCS_SRAM_SIZE);
-}
-
-static uint64_t mbcs_pioaddr(struct mbcs_soft *soft, uint64_t offset)
-{
- uint64_t mmr_base;
-
- mmr_base = (uint64_t) (soft->mmr_base + offset);
-
- return mmr_base;
-}
-
-static void mbcs_debug_pioaddr_set(struct mbcs_soft *soft)
-{
- soft->debug_addr = mbcs_pioaddr(soft, MBCS_DEBUG_START);
-}
-
-static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft)
-{
- soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START);
-}
-
-static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
-{
- struct cx_dev *cx_dev = fp->private_data;
- struct mbcs_soft *soft = cx_dev->soft;
-
- if (vma->vm_pgoff != 0)
- return -EINVAL;
-
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- /* Remap-pfn-range will mark the range VM_IO */
- if (remap_pfn_range(vma,
- vma->vm_start,
- __pa(soft->gscr_addr) >> PAGE_SHIFT,
- PAGE_SIZE,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
-
-/**
- * mbcs_completion_intr_handler - Primary completion handler.
- * @irq: irq
- * @arg: soft struct for device
- *
- */
-static irqreturn_t
-mbcs_completion_intr_handler(int irq, void *arg)
-{
- struct mbcs_soft *soft = (struct mbcs_soft *)arg;
- void *mmr_base;
- union cm_status cm_status;
- union cm_control cm_control;
-
- mmr_base = soft->mmr_base;
- cm_status.cm_status_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_STATUS);
-
- if (cm_status.rd_dma_done) {
- /* stop dma-read engine, clear status */
- cm_control.cm_control_reg =
- MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.rd_dma_clr = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
- cm_control.cm_control_reg);
- atomic_set(&soft->dmaread_done, 1);
- wake_up(&soft->dmaread_queue);
- }
- if (cm_status.wr_dma_done) {
- /* stop dma-write engine, clear status */
- cm_control.cm_control_reg =
- MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.wr_dma_clr = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
- cm_control.cm_control_reg);
- atomic_set(&soft->dmawrite_done, 1);
- wake_up(&soft->dmawrite_queue);
- }
- if (cm_status.alg_done) {
- /* clear status */
- cm_control.cm_control_reg =
- MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.alg_done_clr = 1;
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
- cm_control.cm_control_reg);
- atomic_set(&soft->algo_done, 1);
- wake_up(&soft->algo_queue);
- }
-
- return IRQ_HANDLED;
-}
-
-/**
- * mbcs_intr_alloc - Allocate interrupts.
- * @dev: device pointer
- *
- */
-static int mbcs_intr_alloc(struct cx_dev *dev)
-{
- struct sn_irq_info *sn_irq;
- struct mbcs_soft *soft;
- struct getdma *getdma;
- struct putdma *putdma;
- struct algoblock *algo;
-
- soft = dev->soft;
- getdma = &soft->getdma;
- putdma = &soft->putdma;
- algo = &soft->algo;
-
- soft->get_sn_irq = NULL;
- soft->put_sn_irq = NULL;
- soft->algo_sn_irq = NULL;
-
- sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
- if (sn_irq == NULL)
- return -EAGAIN;
- soft->get_sn_irq = sn_irq;
- getdma->intrHostDest = sn_irq->irq_xtalkaddr;
- getdma->intrVector = sn_irq->irq_irq;
- if (request_irq(sn_irq->irq_irq,
- (void *)mbcs_completion_intr_handler, IRQF_SHARED,
- "MBCS get intr", (void *)soft)) {
- tiocx_irq_free(soft->get_sn_irq);
- return -EAGAIN;
- }
-
- sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
- if (sn_irq == NULL) {
- free_irq(soft->get_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->get_sn_irq);
- return -EAGAIN;
- }
- soft->put_sn_irq = sn_irq;
- putdma->intrHostDest = sn_irq->irq_xtalkaddr;
- putdma->intrVector = sn_irq->irq_irq;
- if (request_irq(sn_irq->irq_irq,
- (void *)mbcs_completion_intr_handler, IRQF_SHARED,
- "MBCS put intr", (void *)soft)) {
- tiocx_irq_free(soft->put_sn_irq);
- free_irq(soft->get_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->get_sn_irq);
- return -EAGAIN;
- }
-
- sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
- if (sn_irq == NULL) {
- free_irq(soft->put_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->put_sn_irq);
- free_irq(soft->get_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->get_sn_irq);
- return -EAGAIN;
- }
- soft->algo_sn_irq = sn_irq;
- algo->intrHostDest = sn_irq->irq_xtalkaddr;
- algo->intrVector = sn_irq->irq_irq;
- if (request_irq(sn_irq->irq_irq,
- (void *)mbcs_completion_intr_handler, IRQF_SHARED,
- "MBCS algo intr", (void *)soft)) {
- tiocx_irq_free(soft->algo_sn_irq);
- free_irq(soft->put_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->put_sn_irq);
- free_irq(soft->get_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->get_sn_irq);
- return -EAGAIN;
- }
-
- return 0;
-}
-
-/**
- * mbcs_intr_dealloc - Remove interrupts.
- * @dev: device pointer
- *
- */
-static void mbcs_intr_dealloc(struct cx_dev *dev)
-{
- struct mbcs_soft *soft;
-
- soft = dev->soft;
-
- free_irq(soft->get_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->get_sn_irq);
- free_irq(soft->put_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->put_sn_irq);
- free_irq(soft->algo_sn_irq->irq_irq, soft);
- tiocx_irq_free(soft->algo_sn_irq);
-}
-
-static inline int mbcs_hw_init(struct mbcs_soft *soft)
-{
- void *mmr_base = soft->mmr_base;
- union cm_control cm_control;
- union cm_req_timeout cm_req_timeout;
- uint64_t err_stat;
-
- cm_req_timeout.cm_req_timeout_reg =
- MBCS_MMR_GET(mmr_base, MBCS_CM_REQ_TOUT);
-
- cm_req_timeout.time_out = MBCS_CM_CONTROL_REQ_TOUT_MASK;
- MBCS_MMR_SET(mmr_base, MBCS_CM_REQ_TOUT,
- cm_req_timeout.cm_req_timeout_reg);
-
- mbcs_gscr_pioaddr_set(soft);
- mbcs_debug_pioaddr_set(soft);
-
- /* clear errors */
- err_stat = MBCS_MMR_GET(mmr_base, MBCS_CM_ERR_STAT);
- MBCS_MMR_SET(mmr_base, MBCS_CM_CLR_ERR_STAT, err_stat);
- MBCS_MMR_ZERO(mmr_base, MBCS_CM_ERROR_DETAIL1);
-
- /* enable interrupts */
- /* turn off 2^23 (INT_EN_PIO_REQ_ADDR_INV) */
- MBCS_MMR_SET(mmr_base, MBCS_CM_ERR_INT_EN, 0x3ffffff7e00ffUL);
-
- /* arm status regs and clear engines */
- cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
- cm_control.rearm_stat_regs = 1;
- cm_control.alg_clr = 1;
- cm_control.wr_dma_clr = 1;
- cm_control.rd_dma_clr = 1;
-
- MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
-
- return 0;
-}
-
-static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct cx_dev *cx_dev = to_cx_dev(dev);
- struct mbcs_soft *soft = cx_dev->soft;
- uint64_t debug0;
-
- /*
- * By convention, the first debug register contains the
- * algorithm number and revision.
- */
- debug0 = *(uint64_t *) soft->debug_addr;
-
- return sprintf(buf, "0x%x 0x%x\n",
- upper_32_bits(debug0), lower_32_bits(debug0));
-}
-
-static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
- int n;
- struct cx_dev *cx_dev = to_cx_dev(dev);
- struct mbcs_soft *soft = cx_dev->soft;
-
- if (count <= 0)
- return 0;
-
- n = simple_strtoul(buf, NULL, 0);
-
- if (n == 1) {
- mbcs_algo_start(soft);
- if (wait_event_interruptible(soft->algo_queue,
- atomic_read(&soft->algo_done)))
- return -ERESTARTSYS;
- }
-
- return count;
-}
-
-DEVICE_ATTR(algo, 0644, show_algo, store_algo);
-
-/**
- * mbcs_probe - Initialize for device
- * @dev: device pointer
- * @device_id: id table pointer
- *
- */
-static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
-{
- struct mbcs_soft *soft;
-
- dev->soft = NULL;
-
- soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL);
- if (soft == NULL)
- return -ENOMEM;
-
- soft->nasid = dev->cx_id.nasid;
- list_add(&soft->list, &soft_list);
- soft->mmr_base = (void *)tiocx_swin_base(dev->cx_id.nasid);
- dev->soft = soft;
- soft->cxdev = dev;
-
- init_waitqueue_head(&soft->dmawrite_queue);
- init_waitqueue_head(&soft->dmaread_queue);
- init_waitqueue_head(&soft->algo_queue);
-
- mutex_init(&soft->dmawritelock);
- mutex_init(&soft->dmareadlock);
- mutex_init(&soft->algolock);
-
- mbcs_getdma_init(&soft->getdma);
- mbcs_putdma_init(&soft->putdma);
- mbcs_algo_init(&soft->algo);
-
- mbcs_hw_init(soft);
-
- /* Allocate interrupts */
- mbcs_intr_alloc(dev);
-
- device_create_file(&dev->dev, &dev_attr_algo);
-
- return 0;
-}
-
-static int mbcs_remove(struct cx_dev *dev)
-{
- if (dev->soft) {
- mbcs_intr_dealloc(dev);
- kfree(dev->soft);
- }
-
- device_remove_file(&dev->dev, &dev_attr_algo);
-
- return 0;
-}
-
-static const struct cx_device_id mbcs_id_table[] = {
- {
- .part_num = MBCS_PART_NUM,
- .mfg_num = MBCS_MFG_NUM,
- },
- {
- .part_num = MBCS_PART_NUM_ALG0,
- .mfg_num = MBCS_MFG_NUM,
- },
- {0, 0}
-};
-
-MODULE_DEVICE_TABLE(cx, mbcs_id_table);
-
-static struct cx_drv mbcs_driver = {
- .name = DEVICE_NAME,
- .id_table = mbcs_id_table,
- .probe = mbcs_probe,
- .remove = mbcs_remove,
-};
-
-static void __exit mbcs_exit(void)
-{
- unregister_chrdev(mbcs_major, DEVICE_NAME);
- cx_driver_unregister(&mbcs_driver);
-}
-
-static int __init mbcs_init(void)
-{
- int rv;
-
- if (!ia64_platform_is("sn2"))
- return -ENODEV;
-
- // Put driver into chrdevs[]. Get major number.
- rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops);
- if (rv < 0) {
- DBG(KERN_ALERT "mbcs_init: can't get major number. %d\n", rv);
- return rv;
- }
- mbcs_major = rv;
-
- return cx_driver_register(&mbcs_driver);
-}
-
-module_init(mbcs_init);
-module_exit(mbcs_exit);
-
-MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
-MODULE_DESCRIPTION("Driver for MOATB Core Services");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h
deleted file mode 100644
index 1a36884c48b5..000000000000
--- a/drivers/char/mbcs.h
+++ /dev/null
@@ -1,553 +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) 2005 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef __MBCS_H__
-#define __MBCS_H__
-
-/*
- * General macros
- */
-#define MB (1024*1024)
-#define MB2 (2*MB)
-#define MB4 (4*MB)
-#define MB6 (6*MB)
-
-/*
- * Offsets and masks
- */
-#define MBCS_CM_ID 0x0000 /* Identification */
-#define MBCS_CM_STATUS 0x0008 /* Status */
-#define MBCS_CM_ERROR_DETAIL1 0x0010 /* Error Detail1 */
-#define MBCS_CM_ERROR_DETAIL2 0x0018 /* Error Detail2 */
-#define MBCS_CM_CONTROL 0x0020 /* Control */
-#define MBCS_CM_REQ_TOUT 0x0028 /* Request Time-out */
-#define MBCS_CM_ERR_INT_DEST 0x0038 /* Error Interrupt Destination */
-#define MBCS_CM_TARG_FL 0x0050 /* Target Flush */
-#define MBCS_CM_ERR_STAT 0x0060 /* Error Status */
-#define MBCS_CM_CLR_ERR_STAT 0x0068 /* Clear Error Status */
-#define MBCS_CM_ERR_INT_EN 0x0070 /* Error Interrupt Enable */
-#define MBCS_RD_DMA_SYS_ADDR 0x0100 /* Read DMA System Address */
-#define MBCS_RD_DMA_LOC_ADDR 0x0108 /* Read DMA Local Address */
-#define MBCS_RD_DMA_CTRL 0x0110 /* Read DMA Control */
-#define MBCS_RD_DMA_AMO_DEST 0x0118 /* Read DMA AMO Destination */
-#define MBCS_RD_DMA_INT_DEST 0x0120 /* Read DMA Interrupt Destination */
-#define MBCS_RD_DMA_AUX_STAT 0x0130 /* Read DMA Auxiliary Status */
-#define MBCS_WR_DMA_SYS_ADDR 0x0200 /* Write DMA System Address */
-#define MBCS_WR_DMA_LOC_ADDR 0x0208 /* Write DMA Local Address */
-#define MBCS_WR_DMA_CTRL 0x0210 /* Write DMA Control */
-#define MBCS_WR_DMA_AMO_DEST 0x0218 /* Write DMA AMO Destination */
-#define MBCS_WR_DMA_INT_DEST 0x0220 /* Write DMA Interrupt Destination */
-#define MBCS_WR_DMA_AUX_STAT 0x0230 /* Write DMA Auxiliary Status */
-#define MBCS_ALG_AMO_DEST 0x0300 /* Algorithm AMO Destination */
-#define MBCS_ALG_INT_DEST 0x0308 /* Algorithm Interrupt Destination */
-#define MBCS_ALG_OFFSETS 0x0310
-#define MBCS_ALG_STEP 0x0318 /* Algorithm Step */
-
-#define MBCS_GSCR_START 0x0000000
-#define MBCS_DEBUG_START 0x0100000
-#define MBCS_RAM0_START 0x0200000
-#define MBCS_RAM1_START 0x0400000
-#define MBCS_RAM2_START 0x0600000
-
-#define MBCS_CM_CONTROL_REQ_TOUT_MASK 0x0000000000ffffffUL
-//#define PIO_BASE_ADDR_BASE_OFFSET_MASK 0x00fffffffff00000UL
-
-#define MBCS_SRAM_SIZE (1024*1024)
-#define MBCS_CACHELINE_SIZE 128
-
-/*
- * MMR get's and put's
- */
-#define MBCS_MMR_ADDR(mmr_base, offset)((uint64_t *)(mmr_base + offset))
-#define MBCS_MMR_SET(mmr_base, offset, value) { \
- uint64_t *mbcs_mmr_set_u64p, readback; \
- mbcs_mmr_set_u64p = (uint64_t *)(mmr_base + offset); \
- *mbcs_mmr_set_u64p = value; \
- readback = *mbcs_mmr_set_u64p; \
-}
-#define MBCS_MMR_GET(mmr_base, offset) *(uint64_t *)(mmr_base + offset)
-#define MBCS_MMR_ZERO(mmr_base, offset) MBCS_MMR_SET(mmr_base, offset, 0)
-
-/*
- * MBCS mmr structures
- */
-union cm_id {
- uint64_t cm_id_reg;
- struct {
- uint64_t always_one:1, // 0
- mfg_id:11, // 11:1
- part_num:16, // 27:12
- bitstream_rev:8, // 35:28
- :28; // 63:36
- };
-};
-
-union cm_status {
- uint64_t cm_status_reg;
- struct {
- uint64_t pending_reads:8, // 7:0
- pending_writes:8, // 15:8
- ice_rsp_credits:8, // 23:16
- ice_req_credits:8, // 31:24
- cm_req_credits:8, // 39:32
- :1, // 40
- rd_dma_in_progress:1, // 41
- rd_dma_done:1, // 42
- :1, // 43
- wr_dma_in_progress:1, // 44
- wr_dma_done:1, // 45
- alg_waiting:1, // 46
- alg_pipe_running:1, // 47
- alg_done:1, // 48
- :3, // 51:49
- pending_int_reqs:8, // 59:52
- :3, // 62:60
- alg_half_speed_sel:1; // 63
- };
-};
-
-union cm_error_detail1 {
- uint64_t cm_error_detail1_reg;
- struct {
- uint64_t packet_type:4, // 3:0
- source_id:2, // 5:4
- data_size:2, // 7:6
- tnum:8, // 15:8
- byte_enable:8, // 23:16
- gfx_cred:8, // 31:24
- read_type:2, // 33:32
- pio_or_memory:1, // 34
- head_cw_error:1, // 35
- :12, // 47:36
- head_error_bit:1, // 48
- data_error_bit:1, // 49
- :13, // 62:50
- valid:1; // 63
- };
-};
-
-union cm_error_detail2 {
- uint64_t cm_error_detail2_reg;
- struct {
- uint64_t address:56, // 55:0
- :8; // 63:56
- };
-};
-
-union cm_control {
- uint64_t cm_control_reg;
- struct {
- uint64_t cm_id:2, // 1:0
- :2, // 3:2
- max_trans:5, // 8:4
- :3, // 11:9
- address_mode:1, // 12
- :7, // 19:13
- credit_limit:8, // 27:20
- :5, // 32:28
- rearm_stat_regs:1, // 33
- prescalar_byp:1, // 34
- force_gap_war:1, // 35
- rd_dma_go:1, // 36
- wr_dma_go:1, // 37
- alg_go:1, // 38
- rd_dma_clr:1, // 39
- wr_dma_clr:1, // 40
- alg_clr:1, // 41
- :2, // 43:42
- alg_wait_step:1, // 44
- alg_done_amo_en:1, // 45
- alg_done_int_en:1, // 46
- :1, // 47
- alg_sram0_locked:1, // 48
- alg_sram1_locked:1, // 49
- alg_sram2_locked:1, // 50
- alg_done_clr:1, // 51
- :12; // 63:52
- };
-};
-
-union cm_req_timeout {
- uint64_t cm_req_timeout_reg;
- struct {
- uint64_t time_out:24, // 23:0
- :40; // 63:24
- };
-};
-
-union intr_dest {
- uint64_t intr_dest_reg;
- struct {
- uint64_t address:56, // 55:0
- int_vector:8; // 63:56
- };
-};
-
-union cm_error_status {
- uint64_t cm_error_status_reg;
- struct {
- uint64_t ecc_sbe:1, // 0
- ecc_mbe:1, // 1
- unsupported_req:1, // 2
- unexpected_rsp:1, // 3
- bad_length:1, // 4
- bad_datavalid:1, // 5
- buffer_overflow:1, // 6
- request_timeout:1, // 7
- :8, // 15:8
- head_inv_data_size:1, // 16
- rsp_pactype_inv:1, // 17
- head_sb_err:1, // 18
- missing_head:1, // 19
- head_inv_rd_type:1, // 20
- head_cmd_err_bit:1, // 21
- req_addr_align_inv:1, // 22
- pio_req_addr_inv:1, // 23
- req_range_dsize_inv:1, // 24
- early_term:1, // 25
- early_tail:1, // 26
- missing_tail:1, // 27
- data_flit_sb_err:1, // 28
- cm2hcm_req_cred_of:1, // 29
- cm2hcm_rsp_cred_of:1, // 30
- rx_bad_didn:1, // 31
- rd_dma_err_rsp:1, // 32
- rd_dma_tnum_tout:1, // 33
- rd_dma_multi_tnum_tou:1, // 34
- wr_dma_err_rsp:1, // 35
- wr_dma_tnum_tout:1, // 36
- wr_dma_multi_tnum_tou:1, // 37
- alg_data_overflow:1, // 38
- alg_data_underflow:1, // 39
- ram0_access_conflict:1, // 40
- ram1_access_conflict:1, // 41
- ram2_access_conflict:1, // 42
- ram0_perr:1, // 43
- ram1_perr:1, // 44
- ram2_perr:1, // 45
- int_gen_rsp_err:1, // 46
- int_gen_tnum_tout:1, // 47
- rd_dma_prog_err:1, // 48
- wr_dma_prog_err:1, // 49
- :14; // 63:50
- };
-};
-
-union cm_clr_error_status {
- uint64_t cm_clr_error_status_reg;
- struct {
- uint64_t clr_ecc_sbe:1, // 0
- clr_ecc_mbe:1, // 1
- clr_unsupported_req:1, // 2
- clr_unexpected_rsp:1, // 3
- clr_bad_length:1, // 4
- clr_bad_datavalid:1, // 5
- clr_buffer_overflow:1, // 6
- clr_request_timeout:1, // 7
- :8, // 15:8
- clr_head_inv_data_siz:1, // 16
- clr_rsp_pactype_inv:1, // 17
- clr_head_sb_err:1, // 18
- clr_missing_head:1, // 19
- clr_head_inv_rd_type:1, // 20
- clr_head_cmd_err_bit:1, // 21
- clr_req_addr_align_in:1, // 22
- clr_pio_req_addr_inv:1, // 23
- clr_req_range_dsize_i:1, // 24
- clr_early_term:1, // 25
- clr_early_tail:1, // 26
- clr_missing_tail:1, // 27
- clr_data_flit_sb_err:1, // 28
- clr_cm2hcm_req_cred_o:1, // 29
- clr_cm2hcm_rsp_cred_o:1, // 30
- clr_rx_bad_didn:1, // 31
- clr_rd_dma_err_rsp:1, // 32
- clr_rd_dma_tnum_tout:1, // 33
- clr_rd_dma_multi_tnum:1, // 34
- clr_wr_dma_err_rsp:1, // 35
- clr_wr_dma_tnum_tout:1, // 36
- clr_wr_dma_multi_tnum:1, // 37
- clr_alg_data_overflow:1, // 38
- clr_alg_data_underflo:1, // 39
- clr_ram0_access_confl:1, // 40
- clr_ram1_access_confl:1, // 41
- clr_ram2_access_confl:1, // 42
- clr_ram0_perr:1, // 43
- clr_ram1_perr:1, // 44
- clr_ram2_perr:1, // 45
- clr_int_gen_rsp_err:1, // 46
- clr_int_gen_tnum_tout:1, // 47
- clr_rd_dma_prog_err:1, // 48
- clr_wr_dma_prog_err:1, // 49
- :14; // 63:50
- };
-};
-
-union cm_error_intr_enable {
- uint64_t cm_error_intr_enable_reg;
- struct {
- uint64_t int_en_ecc_sbe:1, // 0
- int_en_ecc_mbe:1, // 1
- int_en_unsupported_re:1, // 2
- int_en_unexpected_rsp:1, // 3
- int_en_bad_length:1, // 4
- int_en_bad_datavalid:1, // 5
- int_en_buffer_overflo:1, // 6
- int_en_request_timeou:1, // 7
- :8, // 15:8
- int_en_head_inv_data_:1, // 16
- int_en_rsp_pactype_in:1, // 17
- int_en_head_sb_err:1, // 18
- int_en_missing_head:1, // 19
- int_en_head_inv_rd_ty:1, // 20
- int_en_head_cmd_err_b:1, // 21
- int_en_req_addr_align:1, // 22
- int_en_pio_req_addr_i:1, // 23
- int_en_req_range_dsiz:1, // 24
- int_en_early_term:1, // 25
- int_en_early_tail:1, // 26
- int_en_missing_tail:1, // 27
- int_en_data_flit_sb_e:1, // 28
- int_en_cm2hcm_req_cre:1, // 29
- int_en_cm2hcm_rsp_cre:1, // 30
- int_en_rx_bad_didn:1, // 31
- int_en_rd_dma_err_rsp:1, // 32
- int_en_rd_dma_tnum_to:1, // 33
- int_en_rd_dma_multi_t:1, // 34
- int_en_wr_dma_err_rsp:1, // 35
- int_en_wr_dma_tnum_to:1, // 36
- int_en_wr_dma_multi_t:1, // 37
- int_en_alg_data_overf:1, // 38
- int_en_alg_data_under:1, // 39
- int_en_ram0_access_co:1, // 40
- int_en_ram1_access_co:1, // 41
- int_en_ram2_access_co:1, // 42
- int_en_ram0_perr:1, // 43
- int_en_ram1_perr:1, // 44
- int_en_ram2_perr:1, // 45
- int_en_int_gen_rsp_er:1, // 46
- int_en_int_gen_tnum_t:1, // 47
- int_en_rd_dma_prog_er:1, // 48
- int_en_wr_dma_prog_er:1, // 49
- :14; // 63:50
- };
-};
-
-struct cm_mmr {
- union cm_id id;
- union cm_status status;
- union cm_error_detail1 err_detail1;
- union cm_error_detail2 err_detail2;
- union cm_control control;
- union cm_req_timeout req_timeout;
- uint64_t reserved1[1];
- union intr_dest int_dest;
- uint64_t reserved2[2];
- uint64_t targ_flush;
- uint64_t reserved3[1];
- union cm_error_status err_status;
- union cm_clr_error_status clr_err_status;
- union cm_error_intr_enable int_enable;
-};
-
-union dma_hostaddr {
- uint64_t dma_hostaddr_reg;
- struct {
- uint64_t dma_sys_addr:56, // 55:0
- :8; // 63:56
- };
-};
-
-union dma_localaddr {
- uint64_t dma_localaddr_reg;
- struct {
- uint64_t dma_ram_addr:21, // 20:0
- dma_ram_sel:2, // 22:21
- :41; // 63:23
- };
-};
-
-union dma_control {
- uint64_t dma_control_reg;
- struct {
- uint64_t dma_op_length:16, // 15:0
- :18, // 33:16
- done_amo_en:1, // 34
- done_int_en:1, // 35
- :1, // 36
- pio_mem_n:1, // 37
- :26; // 63:38
- };
-};
-
-union dma_amo_dest {
- uint64_t dma_amo_dest_reg;
- struct {
- uint64_t dma_amo_sys_addr:56, // 55:0
- dma_amo_mod_type:3, // 58:56
- :5; // 63:59
- };
-};
-
-union rdma_aux_status {
- uint64_t rdma_aux_status_reg;
- struct {
- uint64_t op_num_pacs_left:17, // 16:0
- :5, // 21:17
- lrsp_buff_empty:1, // 22
- :17, // 39:23
- pending_reqs_left:6, // 45:40
- :18; // 63:46
- };
-};
-
-struct rdma_mmr {
- union dma_hostaddr host_addr;
- union dma_localaddr local_addr;
- union dma_control control;
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union rdma_aux_status aux_status;
-};
-
-union wdma_aux_status {
- uint64_t wdma_aux_status_reg;
- struct {
- uint64_t op_num_pacs_left:17, // 16:0
- :4, // 20:17
- lreq_buff_empty:1, // 21
- :18, // 39:22
- pending_reqs_left:6, // 45:40
- :18; // 63:46
- };
-};
-
-struct wdma_mmr {
- union dma_hostaddr host_addr;
- union dma_localaddr local_addr;
- union dma_control control;
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union wdma_aux_status aux_status;
-};
-
-union algo_step {
- uint64_t algo_step_reg;
- struct {
- uint64_t alg_step_cnt:16, // 15:0
- :48; // 63:16
- };
-};
-
-struct algo_mmr {
- union dma_amo_dest amo_dest;
- union intr_dest intr_dest;
- union {
- uint64_t algo_offset_reg;
- struct {
- uint64_t sram0_offset:7, // 6:0
- reserved0:1, // 7
- sram1_offset:7, // 14:8
- reserved1:1, // 15
- sram2_offset:7, // 22:16
- reserved2:14; // 63:23
- };
- } sram_offset;
- union algo_step step;
-};
-
-struct mbcs_mmr {
- struct cm_mmr cm;
- uint64_t reserved1[17];
- struct rdma_mmr rdDma;
- uint64_t reserved2[25];
- struct wdma_mmr wrDma;
- uint64_t reserved3[25];
- struct algo_mmr algo;
- uint64_t reserved4[156];
-};
-
-/*
- * defines
- */
-#define DEVICE_NAME "mbcs"
-#define MBCS_PART_NUM 0xfff0
-#define MBCS_PART_NUM_ALG0 0xf001
-#define MBCS_MFG_NUM 0x1
-
-struct algoblock {
- uint64_t amoHostDest;
- uint64_t amoModType;
- uint64_t intrHostDest;
- uint64_t intrVector;
- uint64_t algoStepCount;
-};
-
-struct getdma {
- uint64_t hostAddr;
- uint64_t localAddr;
- uint64_t bytes;
- uint64_t DoneAmoEnable;
- uint64_t DoneIntEnable;
- uint64_t peerIO;
- uint64_t amoHostDest;
- uint64_t amoModType;
- uint64_t intrHostDest;
- uint64_t intrVector;
-};
-
-struct putdma {
- uint64_t hostAddr;
- uint64_t localAddr;
- uint64_t bytes;
- uint64_t DoneAmoEnable;
- uint64_t DoneIntEnable;
- uint64_t peerIO;
- uint64_t amoHostDest;
- uint64_t amoModType;
- uint64_t intrHostDest;
- uint64_t intrVector;
-};
-
-struct mbcs_soft {
- struct list_head list;
- struct cx_dev *cxdev;
- int major;
- int nasid;
- void *mmr_base;
- wait_queue_head_t dmawrite_queue;
- wait_queue_head_t dmaread_queue;
- wait_queue_head_t algo_queue;
- struct sn_irq_info *get_sn_irq;
- struct sn_irq_info *put_sn_irq;
- struct sn_irq_info *algo_sn_irq;
- struct getdma getdma;
- struct putdma putdma;
- struct algoblock algo;
- uint64_t gscr_addr; // pio addr
- uint64_t ram0_addr; // pio addr
- uint64_t ram1_addr; // pio addr
- uint64_t ram2_addr; // pio addr
- uint64_t debug_addr; // pio addr
- atomic_t dmawrite_done;
- atomic_t dmaread_done;
- atomic_t algo_done;
- struct mutex dmawritelock;
- struct mutex dmareadlock;
- struct mutex algolock;
-};
-
-static int mbcs_open(struct inode *ip, struct file *fp);
-static ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len,
- loff_t * off);
-static ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len,
- loff_t * off);
-static loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence);
-static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma);
-
-#endif // __MBCS_H__
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index e75c9df7c2d8..a9d9f074fbd6 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -9,11 +9,8 @@
*
* This driver exports the SN special memory (mspec) facility to user
* processes.
- * There are three types of memory made available thru this driver:
- * fetchops, uncached and cached.
- *
- * Fetchops are atomic memory operations that are implemented in the
- * memory controller on SGI SN hardware.
+ * 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.
@@ -46,16 +43,8 @@
#include <linux/atomic.h>
#include <asm/tlbflush.h>
#include <asm/uncached.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/mspec.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/io.h>
-#include <asm/sn/bte.h>
-#include <asm/sn/shubio.h>
-#define FETCHOP_ID "SGI Fetchop,"
#define CACHED_ID "Cached,"
#define UNCACHED_ID "Uncached"
#define REVISION "4.0"
@@ -65,17 +54,10 @@
* Page types allocated by the device.
*/
enum mspec_page_type {
- MSPEC_FETCHOP = 1,
- MSPEC_CACHED,
+ MSPEC_CACHED = 2,
MSPEC_UNCACHED
};
-#ifdef CONFIG_SGI_SN
-static int is_sn2;
-#else
-#define is_sn2 0
-#endif
-
/*
* 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.
@@ -96,39 +78,6 @@ struct vma_data {
unsigned long maddr[0]; /* Array of MSPEC addresses. */
};
-/* used on shub2 to clear FOP cache in the HUB */
-static unsigned long scratch_page[MAX_NUMNODES];
-#define SH2_AMO_CACHE_ENTRIES 4
-
-static inline int
-mspec_zero_block(unsigned long addr, int len)
-{
- int status;
-
- if (is_sn2) {
- if (is_shub2()) {
- int nid;
- void *p;
- int i;
-
- nid = nasid_to_cnodeid(get_node_number(__pa(addr)));
- p = (void *)TO_AMO(scratch_page[nid]);
-
- for (i=0; i < SH2_AMO_CACHE_ENTRIES; i++) {
- FETCHOP_LOAD_OP(p, FETCHOP_LOAD);
- p += FETCHOP_VAR_SIZE;
- }
- }
-
- status = bte_copy(0, addr & ~__IA64_UNCACHED_OFFSET, len,
- BTE_WACQUIRE | BTE_ZERO_FILL, NULL);
- } else {
- memset((char *) addr, 0, len);
- status = 0;
- }
- return status;
-}
-
/*
* mspec_open
*
@@ -173,11 +122,8 @@ mspec_close(struct vm_area_struct *vma)
*/
my_page = vdata->maddr[index];
vdata->maddr[index] = 0;
- if (!mspec_zero_block(my_page, PAGE_SIZE))
- uncached_free_page(my_page, 1);
- else
- printk(KERN_WARNING "mspec_close(): "
- "failed to zero page %ld\n", my_page);
+ memset((char *)my_page, 0, PAGE_SIZE);
+ uncached_free_page(my_page, 1);
}
kvfree(vdata);
@@ -213,11 +159,7 @@ mspec_fault(struct vm_fault *vmf)
spin_unlock(&vdata->lock);
}
- if (vdata->type == MSPEC_FETCHOP)
- paddr = TO_AMO(maddr);
- else
- paddr = maddr & ~__IA64_UNCACHED_OFFSET;
-
+ paddr = maddr & ~__IA64_UNCACHED_OFFSET;
pfn = paddr >> PAGE_SHIFT;
return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
@@ -269,7 +211,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
vma->vm_private_data = vdata;
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
+ if (vdata->type == MSPEC_UNCACHED)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_ops = &mspec_vm_ops;
@@ -277,12 +219,6 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
}
static int
-fetchop_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return mspec_mmap(file, vma, MSPEC_FETCHOP);
-}
-
-static int
cached_mmap(struct file *file, struct vm_area_struct *vma)
{
return mspec_mmap(file, vma, MSPEC_CACHED);
@@ -294,18 +230,6 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma)
return mspec_mmap(file, vma, MSPEC_UNCACHED);
}
-static const struct file_operations fetchop_fops = {
- .owner = THIS_MODULE,
- .mmap = fetchop_mmap,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice fetchop_miscdev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "sgi_fetchop",
- .fops = &fetchop_fops
-};
-
static const struct file_operations cached_fops = {
.owner = THIS_MODULE,
.mmap = cached_mmap,
@@ -339,89 +263,32 @@ static int __init
mspec_init(void)
{
int ret;
- int nid;
-
- /*
- * The fetchop device only works on SN2 hardware, uncached and cached
- * memory drivers should both be valid on all ia64 hardware
- */
-#ifdef CONFIG_SGI_SN
- if (ia64_platform_is("sn2")) {
- is_sn2 = 1;
- if (is_shub2()) {
- ret = -ENOMEM;
- for_each_node_state(nid, N_ONLINE) {
- int actual_nid;
- int nasid;
- unsigned long phys;
-
- scratch_page[nid] = uncached_alloc_page(nid, 1);
- if (scratch_page[nid] == 0)
- goto free_scratch_pages;
- phys = __pa(scratch_page[nid]);
- nasid = get_node_number(phys);
- actual_nid = nasid_to_cnodeid(nasid);
- if (actual_nid != nid)
- goto free_scratch_pages;
- }
- }
- ret = misc_register(&fetchop_miscdev);
- if (ret) {
- printk(KERN_ERR
- "%s: failed to register device %i\n",
- FETCHOP_ID, ret);
- goto free_scratch_pages;
- }
- }
-#endif
ret = misc_register(&cached_miscdev);
if (ret) {
printk(KERN_ERR "%s: failed to register device %i\n",
CACHED_ID, ret);
- if (is_sn2)
- misc_deregister(&fetchop_miscdev);
- goto free_scratch_pages;
+ 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);
- if (is_sn2)
- misc_deregister(&fetchop_miscdev);
- goto free_scratch_pages;
+ return ret;
}
- printk(KERN_INFO "%s %s initialized devices: %s %s %s\n",
- MSPEC_BASENAME, REVISION, is_sn2 ? FETCHOP_ID : "",
- CACHED_ID, UNCACHED_ID);
+ printk(KERN_INFO "%s %s initialized devices: %s %s\n",
+ MSPEC_BASENAME, REVISION, CACHED_ID, UNCACHED_ID);
return 0;
-
- free_scratch_pages:
- for_each_node(nid) {
- if (scratch_page[nid] != 0)
- uncached_free_page(scratch_page[nid], 1);
- }
- return ret;
}
static void __exit
mspec_exit(void)
{
- int nid;
-
misc_deregister(&uncached_miscdev);
misc_deregister(&cached_miscdev);
- if (is_sn2) {
- misc_deregister(&fetchop_miscdev);
-
- for_each_node(nid) {
- if (scratch_page[nid] != 0)
- uncached_free_page(scratch_page[nid], 1);
- }
- }
}
module_init(mspec_init);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5d5ea4ce1442..566922df4b7b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -2445,3 +2445,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
credit_entropy_bits(poolp, entropy);
}
EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/* Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+ if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+ add_hwgenerator_randomness(buf, size, size * 8);
+ else
+ add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness); \ No newline at end of file
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
deleted file mode 100644
index 5918ea7499bb..000000000000
--- a/drivers/char/snsc.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004, 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * System controller communication driver
- *
- * This driver allows a user process to communicate with the system
- * controller (a.k.a. "IRouter") network in an SGI SN system.
- */
-
-#include <linux/interrupt.h>
-#include <linux/sched/signal.h>
-#include <linux/device.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <asm/sn/io.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/module.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/nodepda.h>
-#include "snsc.h"
-
-#define SYSCTL_BASENAME "snsc"
-
-#define SCDRV_BUFSZ 2048
-#define SCDRV_TIMEOUT 1000
-
-static DEFINE_MUTEX(scdrv_mutex);
-static irqreturn_t
-scdrv_interrupt(int irq, void *subch_data)
-{
- struct subch_data_s *sd = subch_data;
- unsigned long flags;
- int status;
-
- spin_lock_irqsave(&sd->sd_rlock, flags);
- spin_lock(&sd->sd_wlock);
- status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
-
- if (status > 0) {
- if (status & SAL_IROUTER_INTR_RECV) {
- wake_up(&sd->sd_rq);
- }
- if (status & SAL_IROUTER_INTR_XMIT) {
- ia64_sn_irtr_intr_disable
- (sd->sd_nasid, sd->sd_subch,
- SAL_IROUTER_INTR_XMIT);
- wake_up(&sd->sd_wq);
- }
- }
- spin_unlock(&sd->sd_wlock);
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
- return IRQ_HANDLED;
-}
-
-/*
- * scdrv_open
- *
- * Reserve a subchannel for system controller communication.
- */
-
-static int
-scdrv_open(struct inode *inode, struct file *file)
-{
- struct sysctl_data_s *scd;
- struct subch_data_s *sd;
- int rv;
-
- /* look up device info for this device file */
- scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
-
- /* allocate memory for subchannel data */
- sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
- if (sd == NULL) {
- printk("%s: couldn't allocate subchannel data\n",
- __func__);
- return -ENOMEM;
- }
-
- /* initialize subch_data_s fields */
- sd->sd_nasid = scd->scd_nasid;
- sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
-
- if (sd->sd_subch < 0) {
- kfree(sd);
- printk("%s: couldn't allocate subchannel\n", __func__);
- return -EBUSY;
- }
-
- spin_lock_init(&sd->sd_rlock);
- spin_lock_init(&sd->sd_wlock);
- init_waitqueue_head(&sd->sd_rq);
- init_waitqueue_head(&sd->sd_wq);
- sema_init(&sd->sd_rbs, 1);
- sema_init(&sd->sd_wbs, 1);
-
- file->private_data = sd;
-
- /* hook this subchannel up to the system controller interrupt */
- mutex_lock(&scdrv_mutex);
- rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
- IRQF_SHARED, SYSCTL_BASENAME, sd);
- if (rv) {
- ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
- kfree(sd);
- printk("%s: irq request failed (%d)\n", __func__, rv);
- mutex_unlock(&scdrv_mutex);
- return -EBUSY;
- }
- mutex_unlock(&scdrv_mutex);
- return 0;
-}
-
-/*
- * scdrv_release
- *
- * Release a previously-reserved subchannel.
- */
-
-static int
-scdrv_release(struct inode *inode, struct file *file)
-{
- struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
- int rv;
-
- /* free the interrupt */
- free_irq(SGI_UART_VECTOR, sd);
-
- /* ask SAL to close the subchannel */
- rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
-
- kfree(sd);
- return rv;
-}
-
-/*
- * scdrv_read
- *
- * Called to read bytes from the open IRouter pipe.
- *
- */
-
-static inline int
-read_status_check(struct subch_data_s *sd, int *len)
-{
- return ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch, sd->sd_rb, len);
-}
-
-static ssize_t
-scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
-{
- int status;
- int len;
- unsigned long flags;
- struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-
- /* try to get control of the read buffer */
- if (down_trylock(&sd->sd_rbs)) {
- /* somebody else has it now;
- * if we're non-blocking, then exit...
- */
- if (file->f_flags & O_NONBLOCK) {
- return -EAGAIN;
- }
- /* ...or if we want to block, then do so here */
- if (down_interruptible(&sd->sd_rbs)) {
- /* something went wrong with wait */
- return -ERESTARTSYS;
- }
- }
-
- /* anything to read? */
- len = CHUNKSIZE;
- spin_lock_irqsave(&sd->sd_rlock, flags);
- status = read_status_check(sd, &len);
-
- /* if not, and we're blocking I/O, loop */
- while (status < 0) {
- DECLARE_WAITQUEUE(wait, current);
-
- if (file->f_flags & O_NONBLOCK) {
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
- up(&sd->sd_rbs);
- return -EAGAIN;
- }
-
- len = CHUNKSIZE;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&sd->sd_rq, &wait);
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
- schedule_timeout(msecs_to_jiffies(SCDRV_TIMEOUT));
-
- remove_wait_queue(&sd->sd_rq, &wait);
- if (signal_pending(current)) {
- /* wait was interrupted */
- up(&sd->sd_rbs);
- return -ERESTARTSYS;
- }
-
- spin_lock_irqsave(&sd->sd_rlock, flags);
- status = read_status_check(sd, &len);
- }
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
- if (len > 0) {
- /* we read something in the last read_status_check(); copy
- * it out to user space
- */
- if (count < len) {
- pr_debug("%s: only accepting %d of %d bytes\n",
- __func__, (int) count, len);
- }
- len = min((int) count, len);
- if (copy_to_user(buf, sd->sd_rb, len))
- len = -EFAULT;
- }
-
- /* release the read buffer and wake anyone who might be
- * waiting for it
- */
- up(&sd->sd_rbs);
-
- /* return the number of characters read in */
- return len;
-}
-
-/*
- * scdrv_write
- *
- * Writes a chunk of an IRouter packet (or other system controller data)
- * to the system controller.
- *
- */
-static inline int
-write_status_check(struct subch_data_s *sd, int count)
-{
- return ia64_sn_irtr_send(sd->sd_nasid, sd->sd_subch, sd->sd_wb, count);
-}
-
-static ssize_t
-scdrv_write(struct file *file, const char __user *buf,
- size_t count, loff_t *f_pos)
-{
- unsigned long flags;
- int status;
- struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-
- /* try to get control of the write buffer */
- if (down_trylock(&sd->sd_wbs)) {
- /* somebody else has it now;
- * if we're non-blocking, then exit...
- */
- if (file->f_flags & O_NONBLOCK) {
- return -EAGAIN;
- }
- /* ...or if we want to block, then do so here */
- if (down_interruptible(&sd->sd_wbs)) {
- /* something went wrong with wait */
- return -ERESTARTSYS;
- }
- }
-
- count = min((int) count, CHUNKSIZE);
- if (copy_from_user(sd->sd_wb, buf, count)) {
- up(&sd->sd_wbs);
- return -EFAULT;
- }
-
- /* try to send the buffer */
- spin_lock_irqsave(&sd->sd_wlock, flags);
- status = write_status_check(sd, count);
-
- /* if we failed, and we want to block, then loop */
- while (status <= 0) {
- DECLARE_WAITQUEUE(wait, current);
-
- if (file->f_flags & O_NONBLOCK) {
- spin_unlock_irqrestore(&sd->sd_wlock, flags);
- up(&sd->sd_wbs);
- return -EAGAIN;
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&sd->sd_wq, &wait);
- spin_unlock_irqrestore(&sd->sd_wlock, flags);
-
- schedule_timeout(msecs_to_jiffies(SCDRV_TIMEOUT));
-
- remove_wait_queue(&sd->sd_wq, &wait);
- if (signal_pending(current)) {
- /* wait was interrupted */
- up(&sd->sd_wbs);
- return -ERESTARTSYS;
- }
-
- spin_lock_irqsave(&sd->sd_wlock, flags);
- status = write_status_check(sd, count);
- }
- spin_unlock_irqrestore(&sd->sd_wlock, flags);
-
- /* release the write buffer and wake anyone who's waiting for it */
- up(&sd->sd_wbs);
-
- /* return the number of characters accepted (should be the complete
- * "chunk" as requested)
- */
- if ((status >= 0) && (status < count)) {
- pr_debug("Didn't accept the full chunk; %d of %d\n",
- status, (int) count);
- }
- return status;
-}
-
-static __poll_t
-scdrv_poll(struct file *file, struct poll_table_struct *wait)
-{
- __poll_t mask = 0;
- int status = 0;
- struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
- unsigned long flags;
-
- poll_wait(file, &sd->sd_rq, wait);
- poll_wait(file, &sd->sd_wq, wait);
-
- spin_lock_irqsave(&sd->sd_rlock, flags);
- spin_lock(&sd->sd_wlock);
- status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
- spin_unlock(&sd->sd_wlock);
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
- if (status > 0) {
- if (status & SAL_IROUTER_INTR_RECV) {
- mask |= EPOLLIN | EPOLLRDNORM;
- }
- if (status & SAL_IROUTER_INTR_XMIT) {
- mask |= EPOLLOUT | EPOLLWRNORM;
- }
- }
-
- return mask;
-}
-
-static const struct file_operations scdrv_fops = {
- .owner = THIS_MODULE,
- .read = scdrv_read,
- .write = scdrv_write,
- .poll = scdrv_poll,
- .open = scdrv_open,
- .release = scdrv_release,
- .llseek = noop_llseek,
-};
-
-static struct class *snsc_class;
-
-/*
- * scdrv_init
- *
- * Called at boot time to initialize the system controller communication
- * facility.
- */
-int __init
-scdrv_init(void)
-{
- geoid_t geoid;
- cnodeid_t cnode;
- char devname[32];
- char *devnamep;
- struct sysctl_data_s *scd;
- void *salbuf;
- dev_t first_dev, dev;
- nasid_t event_nasid;
-
- if (!ia64_platform_is("sn2"))
- return -ENODEV;
-
- event_nasid = ia64_sn_get_console_nasid();
-
- snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
- if (IS_ERR(snsc_class)) {
- printk("%s: failed to allocate class\n", __func__);
- return PTR_ERR(snsc_class);
- }
-
- if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
- SYSCTL_BASENAME) < 0) {
- printk("%s: failed to register SN system controller device\n",
- __func__);
- return -ENODEV;
- }
-
- for (cnode = 0; cnode < num_cnodes; cnode++) {
- geoid = cnodeid_get_geoid(cnode);
- devnamep = devname;
- format_module_id(devnamep, geo_module(geoid),
- MODULE_FORMAT_BRIEF);
- devnamep = devname + strlen(devname);
- sprintf(devnamep, "^%d#%d", geo_slot(geoid),
- geo_slab(geoid));
-
- /* allocate sysctl device data */
- scd = kzalloc(sizeof (struct sysctl_data_s),
- GFP_KERNEL);
- if (!scd) {
- printk("%s: failed to allocate device info"
- "for %s/%s\n", __func__,
- SYSCTL_BASENAME, devname);
- continue;
- }
-
- /* initialize sysctl device data fields */
- scd->scd_nasid = cnodeid_to_nasid(cnode);
- if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
- printk("%s: failed to allocate driver buffer"
- "(%s%s)\n", __func__,
- SYSCTL_BASENAME, devname);
- kfree(scd);
- continue;
- }
-
- if (ia64_sn_irtr_init(scd->scd_nasid, salbuf,
- SCDRV_BUFSZ) < 0) {
- printk
- ("%s: failed to initialize SAL for"
- " system controller communication"
- " (%s/%s): outdated PROM?\n",
- __func__, SYSCTL_BASENAME, devname);
- kfree(scd);
- kfree(salbuf);
- continue;
- }
-
- dev = first_dev + cnode;
- cdev_init(&scd->scd_cdev, &scdrv_fops);
- if (cdev_add(&scd->scd_cdev, dev, 1)) {
- printk("%s: failed to register system"
- " controller device (%s%s)\n",
- __func__, SYSCTL_BASENAME, devname);
- kfree(scd);
- kfree(salbuf);
- continue;
- }
-
- device_create(snsc_class, NULL, dev, NULL,
- "%s", devname);
-
- ia64_sn_irtr_intr_enable(scd->scd_nasid,
- 0 /*ignored */ ,
- SAL_IROUTER_INTR_RECV);
-
- /* on the console nasid, prepare to receive
- * system controller environmental events
- */
- if(scd->scd_nasid == event_nasid) {
- scdrv_event_init(scd);
- }
- }
- return 0;
-}
-device_initcall(scdrv_init);
diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
deleted file mode 100644
index e8c52c882b21..000000000000
--- a/drivers/char/snsc.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * This file contains macros and data types for communication with the
- * system controllers in SGI SN systems.
- */
-
-#ifndef _SN_SYSCTL_H_
-#define _SN_SYSCTL_H_
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/semaphore.h>
-#include <asm/sn/types.h>
-
-#define CHUNKSIZE 127
-
-/* This structure is used to track an open subchannel. */
-struct subch_data_s {
- nasid_t sd_nasid; /* node on which the subchannel was opened */
- int sd_subch; /* subchannel number */
- spinlock_t sd_rlock; /* monitor lock for rsv */
- spinlock_t sd_wlock; /* monitor lock for wsv */
- wait_queue_head_t sd_rq; /* wait queue for readers */
- wait_queue_head_t sd_wq; /* wait queue for writers */
- struct semaphore sd_rbs; /* semaphore for read buffer */
- struct semaphore sd_wbs; /* semaphore for write buffer */
-
- char sd_rb[CHUNKSIZE]; /* read buffer */
- char sd_wb[CHUNKSIZE]; /* write buffer */
-};
-
-struct sysctl_data_s {
- struct cdev scd_cdev; /* Character device info */
- nasid_t scd_nasid; /* Node on which subchannels are opened. */
-};
-
-
-/* argument types */
-#define IR_ARG_INT 0x00 /* 4-byte integer (big-endian) */
-#define IR_ARG_ASCII 0x01 /* null-terminated ASCII string */
-#define IR_ARG_UNKNOWN 0x80 /* unknown data type. The low
- * 7 bits will contain the data
- * length. */
-#define IR_ARG_UNKNOWN_LENGTH_MASK 0x7f
-
-
-/* system controller event codes */
-#define EV_CLASS_MASK 0xf000ul
-#define EV_SEVERITY_MASK 0x0f00ul
-#define EV_COMPONENT_MASK 0x00fful
-
-#define EV_CLASS_POWER 0x1000ul
-#define EV_CLASS_FAN 0x2000ul
-#define EV_CLASS_TEMP 0x3000ul
-#define EV_CLASS_ENV 0x4000ul
-#define EV_CLASS_TEST_FAULT 0x5000ul
-#define EV_CLASS_TEST_WARNING 0x6000ul
-#define EV_CLASS_PWRD_NOTIFY 0x8000ul
-
-/* ENV class codes */
-#define ENV_PWRDN_PEND 0x4101ul
-
-#define EV_SEVERITY_POWER_STABLE 0x0000ul
-#define EV_SEVERITY_POWER_LOW_WARNING 0x0100ul
-#define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul
-#define EV_SEVERITY_POWER_HIGH_FAULT 0x0300ul
-#define EV_SEVERITY_POWER_LOW_FAULT 0x0400ul
-
-#define EV_SEVERITY_FAN_STABLE 0x0000ul
-#define EV_SEVERITY_FAN_WARNING 0x0100ul
-#define EV_SEVERITY_FAN_FAULT 0x0200ul
-
-#define EV_SEVERITY_TEMP_STABLE 0x0000ul
-#define EV_SEVERITY_TEMP_ADVISORY 0x0100ul
-#define EV_SEVERITY_TEMP_CRITICAL 0x0200ul
-#define EV_SEVERITY_TEMP_FAULT 0x0300ul
-
-void scdrv_event_init(struct sysctl_data_s *);
-
-#endif /* _SN_SYSCTL_H_ */
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
deleted file mode 100644
index e452673dff66..000000000000
--- a/drivers/char/snsc_event.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * System controller event handler
- *
- * These routines deal with environmental events arriving from the
- * system controllers.
- */
-
-#include <linux/interrupt.h>
-#include <linux/sched/signal.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/unaligned.h>
-#include "snsc.h"
-
-static struct subch_data_s *event_sd;
-
-void scdrv_event(unsigned long);
-DECLARE_TASKLET(sn_sysctl_event, scdrv_event, 0);
-
-/*
- * scdrv_event_interrupt
- *
- * Pull incoming environmental events off the physical link to the
- * system controller and put them in a temporary holding area in SAL.
- * Schedule scdrv_event() to move them along to their ultimate
- * destination.
- */
-static irqreturn_t
-scdrv_event_interrupt(int irq, void *subch_data)
-{
- struct subch_data_s *sd = subch_data;
- unsigned long flags;
- int status;
-
- spin_lock_irqsave(&sd->sd_rlock, flags);
- status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
-
- if ((status > 0) && (status & SAL_IROUTER_INTR_RECV)) {
- tasklet_schedule(&sn_sysctl_event);
- }
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
- return IRQ_HANDLED;
-}
-
-
-/*
- * scdrv_parse_event
- *
- * Break an event (as read from SAL) into useful pieces so we can decide
- * what to do with it.
- */
-static int
-scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
-{
- char *desc_end;
-
- /* record event source address */
- *src = get_unaligned_be32(event);
- event += 4; /* move on to event code */
-
- /* record the system controller's event code */
- *code = get_unaligned_be32(event);
- event += 4; /* move on to event arguments */
-
- /* how many arguments are in the packet? */
- if (*event++ != 2) {
- /* if not 2, give up */
- return -1;
- }
-
- /* parse out the ESP code */
- if (*event++ != IR_ARG_INT) {
- /* not an integer argument, so give up */
- return -1;
- }
- *esp_code = get_unaligned_be32(event);
- event += 4;
-
- /* parse out the event description */
- if (*event++ != IR_ARG_ASCII) {
- /* not an ASCII string, so give up */
- return -1;
- }
- event[CHUNKSIZE-1] = '\0'; /* ensure this string ends! */
- event += 2; /* skip leading CR/LF */
- desc_end = desc + sprintf(desc, "%s", event);
-
- /* strip trailing CR/LF (if any) */
- for (desc_end--;
- (desc_end != desc) && ((*desc_end == 0xd) || (*desc_end == 0xa));
- desc_end--) {
- *desc_end = '\0';
- }
-
- return 0;
-}
-
-
-/*
- * scdrv_event_severity
- *
- * Figure out how urgent a message we should write to the console/syslog
- * via printk.
- */
-static char *
-scdrv_event_severity(int code)
-{
- int ev_class = (code & EV_CLASS_MASK);
- int ev_severity = (code & EV_SEVERITY_MASK);
- char *pk_severity = KERN_NOTICE;
-
- switch (ev_class) {
- case EV_CLASS_POWER:
- switch (ev_severity) {
- case EV_SEVERITY_POWER_LOW_WARNING:
- case EV_SEVERITY_POWER_HIGH_WARNING:
- pk_severity = KERN_WARNING;
- break;
- case EV_SEVERITY_POWER_HIGH_FAULT:
- case EV_SEVERITY_POWER_LOW_FAULT:
- pk_severity = KERN_ALERT;
- break;
- }
- break;
- case EV_CLASS_FAN:
- switch (ev_severity) {
- case EV_SEVERITY_FAN_WARNING:
- pk_severity = KERN_WARNING;
- break;
- case EV_SEVERITY_FAN_FAULT:
- pk_severity = KERN_CRIT;
- break;
- }
- break;
- case EV_CLASS_TEMP:
- switch (ev_severity) {
- case EV_SEVERITY_TEMP_ADVISORY:
- pk_severity = KERN_WARNING;
- break;
- case EV_SEVERITY_TEMP_CRITICAL:
- pk_severity = KERN_CRIT;
- break;
- case EV_SEVERITY_TEMP_FAULT:
- pk_severity = KERN_ALERT;
- break;
- }
- break;
- case EV_CLASS_ENV:
- pk_severity = KERN_ALERT;
- break;
- case EV_CLASS_TEST_FAULT:
- pk_severity = KERN_ALERT;
- break;
- case EV_CLASS_TEST_WARNING:
- pk_severity = KERN_WARNING;
- break;
- case EV_CLASS_PWRD_NOTIFY:
- pk_severity = KERN_ALERT;
- break;
- }
-
- return pk_severity;
-}
-
-
-/*
- * scdrv_dispatch_event
- *
- * Do the right thing with an incoming event. That's often nothing
- * more than printing it to the system log. For power-down notifications
- * we start a graceful shutdown.
- */
-static void
-scdrv_dispatch_event(char *event, int len)
-{
- static int snsc_shutting_down = 0;
- int code, esp_code, src, class;
- char desc[CHUNKSIZE];
- char *severity;
-
- if (scdrv_parse_event(event, &src, &code, &esp_code, desc) < 0) {
- /* ignore uninterpretible event */
- return;
- }
-
- /* how urgent is the message? */
- severity = scdrv_event_severity(code);
-
- class = (code & EV_CLASS_MASK);
-
- if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
- if (snsc_shutting_down)
- return;
-
- snsc_shutting_down = 1;
-
- /* give a message for each type of event */
- if (class == EV_CLASS_PWRD_NOTIFY)
- printk(KERN_NOTICE "Power off indication received."
- " Sending SIGPWR to init...\n");
- else if (code == ENV_PWRDN_PEND)
- printk(KERN_CRIT "WARNING: Shutting down the system"
- " due to a critical environmental condition."
- " Sending SIGPWR to init...\n");
-
- /* give a SIGPWR signal to init proc */
- kill_cad_pid(SIGPWR, 0);
- } else {
- /* print to system log */
- printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
- }
-}
-
-
-/*
- * scdrv_event
- *
- * Called as a tasklet when an event arrives from the L1. Read the event
- * from where it's temporarily stored in SAL and call scdrv_dispatch_event()
- * to send it on its way. Keep trying to read events until SAL indicates
- * that there are no more immediately available.
- */
-void
-scdrv_event(unsigned long dummy)
-{
- int status;
- int len;
- unsigned long flags;
- struct subch_data_s *sd = event_sd;
-
- /* anything to read? */
- len = CHUNKSIZE;
- spin_lock_irqsave(&sd->sd_rlock, flags);
- status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
- sd->sd_rb, &len);
-
- while (!(status < 0)) {
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
- scdrv_dispatch_event(sd->sd_rb, len);
- len = CHUNKSIZE;
- spin_lock_irqsave(&sd->sd_rlock, flags);
- status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
- sd->sd_rb, &len);
- }
- spin_unlock_irqrestore(&sd->sd_rlock, flags);
-}
-
-
-/*
- * scdrv_event_init
- *
- * Sets up a system controller subchannel to begin receiving event
- * messages. This is sort of a specialized version of scdrv_open()
- * in drivers/char/sn_sysctl.c.
- */
-void
-scdrv_event_init(struct sysctl_data_s *scd)
-{
- int rv;
-
- event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
- if (event_sd == NULL) {
- printk(KERN_WARNING "%s: couldn't allocate subchannel info"
- " for event monitoring\n", __func__);
- return;
- }
-
- /* initialize subch_data_s fields */
- event_sd->sd_nasid = scd->scd_nasid;
- spin_lock_init(&event_sd->sd_rlock);
-
- /* ask the system controllers to send events to this node */
- event_sd->sd_subch = ia64_sn_sysctl_event_init(scd->scd_nasid);
-
- if (event_sd->sd_subch < 0) {
- kfree(event_sd);
- printk(KERN_WARNING "%s: couldn't open event subchannel\n",
- __func__);
- return;
- }
-
- /* hook event subchannel up to the system controller interrupt */
- rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
- IRQF_SHARED, "system controller events", event_sd);
- if (rv) {
- printk(KERN_WARNING "%s: irq request failed (%d)\n",
- __func__, rv);
- ia64_sn_irtr_close(event_sd->sd_nasid, event_sd->sd_subch);
- kfree(event_sd);
- return;
- }
-}
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 88a3c06fc153..9c37047f4b56 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -164,6 +164,11 @@ config TCG_VTPM_PROXY
/dev/vtpmX and a server-side file descriptor on which the vTPM
can receive commands.
+config TCG_FTPM_TEE
+ tristate "TEE based fTPM Interface"
+ depends on TEE && OPTEE
+ help
+ This driver proxies for firmware TPM running in TEE.
source "drivers/char/tpm/st33zp24/Kconfig"
endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index a01c4cab902a..c354cdff9c62 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -33,3 +33,4 @@ obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
+obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index d47ad10a35fe..3d6d394a8661 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -77,6 +77,18 @@ static int tpm_go_idle(struct tpm_chip *chip)
return chip->ops->go_idle(chip);
}
+static void tpm_clk_enable(struct tpm_chip *chip)
+{
+ if (chip->ops->clk_enable)
+ chip->ops->clk_enable(chip, true);
+}
+
+static void tpm_clk_disable(struct tpm_chip *chip)
+{
+ if (chip->ops->clk_enable)
+ chip->ops->clk_enable(chip, false);
+}
+
/**
* tpm_chip_start() - power on the TPM
* @chip: a TPM chip to use
@@ -89,13 +101,12 @@ int tpm_chip_start(struct tpm_chip *chip)
{
int ret;
- if (chip->ops->clk_enable)
- chip->ops->clk_enable(chip, true);
+ tpm_clk_enable(chip);
if (chip->locality == -1) {
ret = tpm_request_locality(chip);
if (ret) {
- chip->ops->clk_enable(chip, false);
+ tpm_clk_disable(chip);
return ret;
}
}
@@ -103,8 +114,7 @@ int tpm_chip_start(struct tpm_chip *chip)
ret = tpm_cmd_ready(chip);
if (ret) {
tpm_relinquish_locality(chip);
- if (chip->ops->clk_enable)
- chip->ops->clk_enable(chip, false);
+ tpm_clk_disable(chip);
return ret;
}
@@ -124,8 +134,7 @@ void tpm_chip_stop(struct tpm_chip *chip)
{
tpm_go_idle(chip);
tpm_relinquish_locality(chip);
- if (chip->ops->clk_enable)
- chip->ops->clk_enable(chip, false);
+ tpm_clk_disable(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_stop);
@@ -278,12 +287,9 @@ static void tpm_devs_release(struct device *dev)
* @dev: device to which the chip is associated.
*
* Issues a TPM2_Shutdown command prior to loss of power, as required by the
- * TPM 2.0 spec.
- * Then, calls bus- and device- specific shutdown code.
+ * TPM 2.0 spec. Then, calls bus- and device- specific shutdown code.
*
- * XXX: This codepath relies on the fact that sysfs is not enabled for
- * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2
- * has sysfs support enabled before TPM sysfs's implicit locking is fixed.
+ * Return: always 0 (i.e. success)
*/
static int tpm_class_shutdown(struct device *dev)
{
@@ -545,6 +551,20 @@ static int tpm_add_hwrng(struct tpm_chip *chip)
return hwrng_register(&chip->hwrng);
}
+static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+{
+ int rc;
+
+ rc = (chip->flags & TPM_CHIP_FLAG_TPM2) ?
+ tpm2_get_pcr_allocation(chip) :
+ tpm1_get_pcr_allocation(chip);
+
+ if (rc > 0)
+ return -ENODEV;
+
+ return rc;
+}
+
/*
* tpm_chip_register() - create a character device for the TPM chip
* @chip: TPM chip to use.
@@ -564,6 +584,12 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
rc = tpm_auto_startup(chip);
+ if (rc) {
+ tpm_chip_stop(chip);
+ return rc;
+ }
+
+ rc = tpm_get_pcr_allocation(chip);
tpm_chip_stop(chip);
if (rc)
return rc;
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index d9caedda075b..edfa89160010 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -329,16 +329,9 @@ static const struct attribute_group tpm_dev_group = {
void tpm_sysfs_add_device(struct tpm_chip *chip)
{
- /* XXX: If you wish to remove this restriction, you must first update
- * tpm_sysfs to explicitly lock chip->ops.
- */
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return;
- /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
- * is called before ops is null'd and the sysfs core synchronizes this
- * removal so that no callbacks are running or can run again
- */
WARN_ON(chip->groups_cnt != 0);
chip->groups[chip->groups_cnt++] = &tpm_dev_group;
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e503ffc3aa39..a7fea3e0ca86 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -394,6 +394,7 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm1_get_pcr_allocation(struct tpm_chip *chip);
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);
@@ -449,6 +450,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
int tpm2_auto_startup(struct tpm_chip *chip);
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index faacbe1ffa1a..149e953ca369 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -699,18 +699,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
goto out;
}
- chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
- GFP_KERNEL);
- if (!chip->allocated_banks) {
- rc = -ENOMEM;
- goto out;
- }
-
- chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
- chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
- chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
- chip->nr_allocated_banks = 1;
-
return rc;
out:
if (rc > 0)
@@ -779,3 +767,27 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
return rc;
}
+/**
+ * tpm1_get_pcr_allocation() - initialize the allocated bank
+ * @chip: TPM chip to use.
+ *
+ * The function initializes the SHA1 allocated bank to extend PCR
+ *
+ * Return:
+ * * 0 on success,
+ * * < 0 on error.
+ */
+int tpm1_get_pcr_allocation(struct tpm_chip *chip)
+{
+ chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+ GFP_KERNEL);
+ if (!chip->allocated_banks)
+ return -ENOMEM;
+
+ chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
+ chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
+ chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
+ chip->nr_allocated_banks = 1;
+
+ return 0;
+}
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index d103545e4055..ba9acae83bff 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -840,7 +840,7 @@ struct tpm2_pcr_selection {
u8 pcr_select[3];
} __packed;
-static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
{
struct tpm2_pcr_selection pcr_selection;
struct tpm_buf buf;
@@ -1040,10 +1040,6 @@ int tpm2_auto_startup(struct tpm_chip *chip)
goto out;
}
- rc = tpm2_get_pcr_allocation(chip);
- if (rc)
- goto out;
-
rc = tpm2_get_cc_attrs_tbl(chip);
out:
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c
new file mode 100644
index 000000000000..6640a14dbe48
--- /dev/null
+++ b/drivers/char/tpm/tpm_ftpm_tee.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Microsoft Corporation
+ *
+ * Implements a firmware TPM as described here:
+ * https://www.microsoft.com/en-us/research/publication/ftpm-software-implementation-tpm-chip/
+ *
+ * A reference implementation is available here:
+ * https://github.com/microsoft/ms-tpm-20-ref/tree/master/Samples/ARM32-FirmwareTPM/optee_ta/fTPM
+ */
+
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/tee_drv.h>
+#include <linux/tpm.h>
+#include <linux/uuid.h>
+
+#include "tpm.h"
+#include "tpm_ftpm_tee.h"
+
+/*
+ * TA_FTPM_UUID: BC50D971-D4C9-42C4-82CB-343FB7F37896
+ *
+ * Randomly generated, and must correspond to the GUID on the TA side.
+ * Defined here in the reference implementation:
+ * https://github.com/microsoft/ms-tpm-20-ref/blob/master/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h#L42
+ */
+static const uuid_t ftpm_ta_uuid =
+ UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
+
+/**
+ * ftpm_tee_tpm_op_recv - retrieve fTPM response.
+ * @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @buf: the buffer to store data.
+ * @count: the number of bytes to read.
+ *
+ * Return:
+ * In case of success the number of bytes received.
+ * On failure, -errno.
+ */
+static int ftpm_tee_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ struct ftpm_tee_private *pvt_data = dev_get_drvdata(chip->dev.parent);
+ size_t len;
+
+ len = pvt_data->resp_len;
+ if (count < len) {
+ dev_err(&chip->dev,
+ "%s: Invalid size in recv: count=%zd, resp_len=%zd\n",
+ __func__, count, len);
+ return -EIO;
+ }
+
+ memcpy(buf, pvt_data->resp_buf, len);
+ pvt_data->resp_len = 0;
+
+ return len;
+}
+
+/**
+ * ftpm_tee_tpm_op_send - send TPM commands through the TEE shared memory.
+ * @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h
+ * @buf: the buffer to send.
+ * @len: the number of bytes to send.
+ *
+ * Return:
+ * In case of success, returns 0.
+ * On failure, -errno
+ */
+static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+ struct ftpm_tee_private *pvt_data = dev_get_drvdata(chip->dev.parent);
+ size_t resp_len;
+ int rc;
+ u8 *temp_buf;
+ struct tpm_header *resp_header;
+ struct tee_ioctl_invoke_arg transceive_args;
+ struct tee_param command_params[4];
+ struct tee_shm *shm = pvt_data->shm;
+
+ if (len > MAX_COMMAND_SIZE) {
+ dev_err(&chip->dev,
+ "%s: len=%zd exceeds MAX_COMMAND_SIZE supported by fTPM TA\n",
+ __func__, len);
+ return -EIO;
+ }
+
+ memset(&transceive_args, 0, sizeof(transceive_args));
+ memset(command_params, 0, sizeof(command_params));
+ pvt_data->resp_len = 0;
+
+ /* Invoke FTPM_OPTEE_TA_SUBMIT_COMMAND function of fTPM TA */
+ transceive_args = (struct tee_ioctl_invoke_arg) {
+ .func = FTPM_OPTEE_TA_SUBMIT_COMMAND,
+ .session = pvt_data->session,
+ .num_params = 4,
+ };
+
+ /* Fill FTPM_OPTEE_TA_SUBMIT_COMMAND parameters */
+ command_params[0] = (struct tee_param) {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
+ .u.memref = {
+ .shm = shm,
+ .size = len,
+ .shm_offs = 0,
+ },
+ };
+
+ temp_buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(temp_buf)) {
+ dev_err(&chip->dev, "%s: tee_shm_get_va failed for transmit\n",
+ __func__);
+ return PTR_ERR(temp_buf);
+ }
+ memset(temp_buf, 0, (MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE));
+ memcpy(temp_buf, buf, len);
+
+ command_params[1] = (struct tee_param) {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT,
+ .u.memref = {
+ .shm = shm,
+ .size = MAX_RESPONSE_SIZE,
+ .shm_offs = MAX_COMMAND_SIZE,
+ },
+ };
+
+ rc = tee_client_invoke_func(pvt_data->ctx, &transceive_args,
+ command_params);
+ if ((rc < 0) || (transceive_args.ret != 0)) {
+ dev_err(&chip->dev, "%s: SUBMIT_COMMAND invoke error: 0x%x\n",
+ __func__, transceive_args.ret);
+ return (rc < 0) ? rc : transceive_args.ret;
+ }
+
+ temp_buf = tee_shm_get_va(shm, command_params[1].u.memref.shm_offs);
+ if (IS_ERR(temp_buf)) {
+ dev_err(&chip->dev, "%s: tee_shm_get_va failed for receive\n",
+ __func__);
+ return PTR_ERR(temp_buf);
+ }
+
+ resp_header = (struct tpm_header *)temp_buf;
+ resp_len = be32_to_cpu(resp_header->length);
+
+ /* sanity check resp_len */
+ if (resp_len < TPM_HEADER_SIZE) {
+ dev_err(&chip->dev, "%s: tpm response header too small\n",
+ __func__);
+ return -EIO;
+ }
+ if (resp_len > MAX_RESPONSE_SIZE) {
+ dev_err(&chip->dev,
+ "%s: resp_len=%zd exceeds MAX_RESPONSE_SIZE\n",
+ __func__, resp_len);
+ return -EIO;
+ }
+
+ /* sanity checks look good, cache the response */
+ memcpy(pvt_data->resp_buf, temp_buf, resp_len);
+ pvt_data->resp_len = resp_len;
+
+ return 0;
+}
+
+static void ftpm_tee_tpm_op_cancel(struct tpm_chip *chip)
+{
+ /* not supported */
+}
+
+static u8 ftpm_tee_tpm_op_status(struct tpm_chip *chip)
+{
+ return 0;
+}
+
+static bool ftpm_tee_tpm_req_canceled(struct tpm_chip *chip, u8 status)
+{
+ return 0;
+}
+
+static const struct tpm_class_ops ftpm_tee_tpm_ops = {
+ .flags = TPM_OPS_AUTO_STARTUP,
+ .recv = ftpm_tee_tpm_op_recv,
+ .send = ftpm_tee_tpm_op_send,
+ .cancel = ftpm_tee_tpm_op_cancel,
+ .status = ftpm_tee_tpm_op_status,
+ .req_complete_mask = 0,
+ .req_complete_val = 0,
+ .req_canceled = ftpm_tee_tpm_req_canceled,
+};
+
+/*
+ * Check whether this driver supports the fTPM TA in the TEE instance
+ * represented by the params (ver/data) to this function.
+ */
+static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+ /*
+ * Currently this driver only support GP Complaint OPTEE based fTPM TA
+ */
+ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
+ (ver->gen_caps & TEE_GEN_CAP_GP))
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * ftpm_tee_probe - initialize the fTPM
+ * @pdev: the platform_device description.
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+static int ftpm_tee_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct tpm_chip *chip;
+ struct device *dev = &pdev->dev;
+ struct ftpm_tee_private *pvt_data = NULL;
+ struct tee_ioctl_open_session_arg sess_arg;
+
+ pvt_data = devm_kzalloc(dev, sizeof(struct ftpm_tee_private),
+ GFP_KERNEL);
+ if (!pvt_data)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, pvt_data);
+
+ /* Open context with TEE driver */
+ pvt_data->ctx = tee_client_open_context(NULL, ftpm_tee_match, NULL,
+ NULL);
+ if (IS_ERR(pvt_data->ctx)) {
+ if (PTR_ERR(pvt_data->ctx) == -ENOENT)
+ return -EPROBE_DEFER;
+ dev_err(dev, "%s: tee_client_open_context failed\n", __func__);
+ return PTR_ERR(pvt_data->ctx);
+ }
+
+ /* Open a session with fTPM TA */
+ memset(&sess_arg, 0, sizeof(sess_arg));
+ memcpy(sess_arg.uuid, ftpm_ta_uuid.b, TEE_IOCTL_UUID_LEN);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+ sess_arg.num_params = 0;
+
+ rc = tee_client_open_session(pvt_data->ctx, &sess_arg, NULL);
+ if ((rc < 0) || (sess_arg.ret != 0)) {
+ dev_err(dev, "%s: tee_client_open_session failed, err=%x\n",
+ __func__, sess_arg.ret);
+ rc = -EINVAL;
+ goto out_tee_session;
+ }
+ pvt_data->session = sess_arg.session;
+
+ /* Allocate dynamic shared memory with fTPM TA */
+ pvt_data->shm = tee_shm_alloc(pvt_data->ctx,
+ MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE,
+ TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ if (IS_ERR(pvt_data->shm)) {
+ dev_err(dev, "%s: tee_shm_alloc failed\n", __func__);
+ rc = -ENOMEM;
+ goto out_shm_alloc;
+ }
+
+ /* Allocate new struct tpm_chip instance */
+ chip = tpm_chip_alloc(dev, &ftpm_tee_tpm_ops);
+ if (IS_ERR(chip)) {
+ dev_err(dev, "%s: tpm_chip_alloc failed\n", __func__);
+ rc = PTR_ERR(chip);
+ goto out_chip_alloc;
+ }
+
+ pvt_data->chip = chip;
+ pvt_data->chip->flags |= TPM_CHIP_FLAG_TPM2;
+
+ /* Create a character device for the fTPM */
+ rc = tpm_chip_register(pvt_data->chip);
+ if (rc) {
+ dev_err(dev, "%s: tpm_chip_register failed with rc=%d\n",
+ __func__, rc);
+ goto out_chip;
+ }
+
+ return 0;
+
+out_chip:
+ put_device(&pvt_data->chip->dev);
+out_chip_alloc:
+ tee_shm_free(pvt_data->shm);
+out_shm_alloc:
+ tee_client_close_session(pvt_data->ctx, pvt_data->session);
+out_tee_session:
+ tee_client_close_context(pvt_data->ctx);
+
+ return rc;
+}
+
+/**
+ * ftpm_tee_remove - remove the TPM device
+ * @pdev: the platform_device description.
+ *
+ * Return:
+ * 0 always.
+ */
+static int ftpm_tee_remove(struct platform_device *pdev)
+{
+ struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
+
+ /* Release the chip */
+ tpm_chip_unregister(pvt_data->chip);
+
+ /* frees chip */
+ put_device(&pvt_data->chip->dev);
+
+ /* Free the shared memory pool */
+ tee_shm_free(pvt_data->shm);
+
+ /* close the existing session with fTPM TA*/
+ tee_client_close_session(pvt_data->ctx, pvt_data->session);
+
+ /* close the context with TEE driver */
+ tee_client_close_context(pvt_data->ctx);
+
+ /* memory allocated with devm_kzalloc() is freed automatically */
+
+ return 0;
+}
+
+static const struct of_device_id of_ftpm_tee_ids[] = {
+ { .compatible = "microsoft,ftpm" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, of_ftpm_tee_ids);
+
+static struct platform_driver ftpm_tee_driver = {
+ .driver = {
+ .name = "ftpm-tee",
+ .of_match_table = of_match_ptr(of_ftpm_tee_ids),
+ },
+ .probe = ftpm_tee_probe,
+ .remove = ftpm_tee_remove,
+};
+
+module_platform_driver(ftpm_tee_driver);
+
+MODULE_AUTHOR("Thirupathaiah Annapureddy <thiruan@microsoft.com>");
+MODULE_DESCRIPTION("TPM Driver for fTPM TA in TEE");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/tpm/tpm_ftpm_tee.h b/drivers/char/tpm/tpm_ftpm_tee.h
new file mode 100644
index 000000000000..f98daa7bf68c
--- /dev/null
+++ b/drivers/char/tpm/tpm_ftpm_tee.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Microsoft Corporation
+ */
+
+#ifndef __TPM_FTPM_TEE_H__
+#define __TPM_FTPM_TEE_H__
+
+#include <linux/tee_drv.h>
+#include <linux/tpm.h>
+#include <linux/uuid.h>
+
+/* The TAFs ID implemented in this TA */
+#define FTPM_OPTEE_TA_SUBMIT_COMMAND (0)
+#define FTPM_OPTEE_TA_EMULATE_PPI (1)
+
+/* max. buffer size supported by fTPM */
+#define MAX_COMMAND_SIZE 4096
+#define MAX_RESPONSE_SIZE 4096
+
+/**
+ * struct ftpm_tee_private - fTPM's private data
+ * @chip: struct tpm_chip instance registered with tpm framework.
+ * @state: internal state
+ * @session: fTPM TA session identifier.
+ * @resp_len: cached response buffer length.
+ * @resp_buf: cached response buffer.
+ * @ctx: TEE context handler.
+ * @shm: Memory pool shared with fTPM TA in TEE.
+ */
+struct ftpm_tee_private {
+ struct tpm_chip *chip;
+ u32 session;
+ size_t resp_len;
+ u8 resp_buf[MAX_RESPONSE_SIZE];
+ struct tee_context *ctx;
+ struct tee_shm *shm;
+};
+
+#endif /* __TPM_FTPM_TEE_H__ */
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index c3181ea9f271..270f43acbb77 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -980,6 +980,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
goto out_err;
}
+ tpm_chip_start(chip);
+ chip->flags |= TPM_CHIP_FLAG_IRQ;
if (irq) {
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
irq);
@@ -989,6 +991,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
} else {
tpm_tis_probe_irq(chip, intmask);
}
+ tpm_chip_stop(chip);
}
rc = tpm_chip_register(chip);
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index 44db83a6d01c..44a46dcc0518 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -141,6 +141,8 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
continue;
div = DIV_ROUND_CLOSEST(parent_rate, req->rate);
+ if (div > GENERATED_MAX_DIV + 1)
+ div = GENERATED_MAX_DIV + 1;
clk_generated_best_diff(req, parent, parent_rate, div,
&best_diff, &best_rate);
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index a2287c770d5c..886f7c5df51a 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -69,7 +69,7 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct scmi_clk *clk = to_scmi_clk(hw);
- return clk->handle->clk_ops->rate_set(clk->handle, clk->id, 0, rate);
+ return clk->handle->clk_ops->rate_set(clk->handle, clk->id, rate);
}
static int scmi_clk_enable(struct clk_hw *hw)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c0990703ce54..ca99e9db6575 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -324,6 +324,25 @@ static struct clk_core *clk_core_lookup(const char *name)
return NULL;
}
+#ifdef CONFIG_OF
+static int of_parse_clkspec(const struct device_node *np, int index,
+ const char *name, struct of_phandle_args *out_args);
+static struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec);
+#else
+static inline int of_parse_clkspec(const struct device_node *np, int index,
+ const char *name,
+ struct of_phandle_args *out_args)
+{
+ return -ENOENT;
+}
+static inline struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
+{
+ return ERR_PTR(-ENOENT);
+}
+#endif
+
/**
* clk_core_get - Find the clk_core parent of a clk
* @core: clk to find parent of
@@ -355,8 +374,9 @@ static struct clk_core *clk_core_lookup(const char *name)
* };
*
* Returns: -ENOENT when the provider can't be found or the clk doesn't
- * exist in the provider. -EINVAL when the name can't be found. NULL when the
- * provider knows about the clk but it isn't provided on this system.
+ * exist in the provider or the name can't be found in the DT node or
+ * in a clkdev lookup. NULL when the provider knows about the clk but it
+ * isn't provided on this system.
* A valid clk_core pointer when the clk can be found in the provider.
*/
static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
@@ -367,17 +387,19 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
struct device *dev = core->dev;
const char *dev_id = dev ? dev_name(dev) : NULL;
struct device_node *np = core->of_node;
+ struct of_phandle_args clkspec;
- if (np && (name || index >= 0))
- hw = of_clk_get_hw(np, index, name);
-
- /*
- * If the DT search above couldn't find the provider or the provider
- * didn't know about this clk, fallback to looking up via clkdev based
- * clk_lookups
- */
- if (PTR_ERR(hw) == -ENOENT && name)
+ if (np && (name || index >= 0) &&
+ !of_parse_clkspec(np, index, name, &clkspec)) {
+ hw = of_clk_get_hw_from_clkspec(&clkspec);
+ of_node_put(clkspec.np);
+ } else if (name) {
+ /*
+ * If the DT search above couldn't find the provider fallback to
+ * looking up via clkdev based clk_lookups.
+ */
hw = clk_find_hw(dev_id, name);
+ }
if (IS_ERR(hw))
return ERR_CAST(hw);
@@ -401,7 +423,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
parent = ERR_PTR(-EPROBE_DEFER);
} else {
parent = clk_core_get(core, index);
- if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
+ if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
parent = clk_core_lookup(entry->name);
}
@@ -1632,7 +1654,8 @@ static int clk_fetch_parent_index(struct clk_core *core,
break;
/* Fallback to comparing globally unique names */
- if (!strcmp(parent->name, core->parents[i].name))
+ if (core->parents[i].name &&
+ !strcmp(parent->name, core->parents[i].name))
break;
}
@@ -2487,6 +2510,12 @@ runtime_put:
return ret;
}
+int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *parent)
+{
+ return clk_core_set_parent_nolock(hw->core, parent->core);
+}
+EXPORT_SYMBOL_GPL(clk_hw_set_parent);
+
/**
* clk_set_parent - switch the parent of a mux clk
* @clk: the mux clk whose input we are switching
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 0eaf41848280..1ac0c7990392 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -14,6 +14,12 @@ config CLK_IMX8MM
help
Build the driver for i.MX8MM CCM Clock Driver
+config CLK_IMX8MN
+ bool "IMX8MN CCM Clock Driver"
+ depends on ARCH_MXC && ARM64
+ help
+ Build the driver for i.MX8MN CCM Clock Driver
+
config CLK_IMX8MQ
bool "IMX8MQ CCM Clock Driver"
depends on ARCH_MXC && ARM64
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 05641c64b317..77a3d714f1d5 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MXC_CLK_SCU) += \
clk-lpcg-scu.o
obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
+obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 6b8e75df994d..43fa9c361fcb 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -26,23 +26,6 @@ static u32 share_count_dcss;
static u32 share_count_pdm;
static u32 share_count_nand;
-#define PLL_1416X_RATE(_rate, _m, _p, _s) \
- { \
- .rate = (_rate), \
- .mdiv = (_m), \
- .pdiv = (_p), \
- .sdiv = (_s), \
- }
-
-#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \
- { \
- .rate = (_rate), \
- .mdiv = (_m), \
- .pdiv = (_p), \
- .sdiv = (_s), \
- .kdiv = (_k), \
- }
-
static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
PLL_1416X_RATE(1800000000U, 225, 3, 0),
PLL_1416X_RATE(1600000000U, 200, 3, 0),
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
new file mode 100644
index 000000000000..07481a53e336
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -0,0 +1,636 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018-2019 NXP.
+ */
+
+#include <dt-bindings/clock/imx8mn-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_sai7;
+static u32 share_count_disp;
+static u32 share_count_pdm;
+static u32 share_count_nand;
+
+enum {
+ ARM_PLL,
+ GPU_PLL,
+ VPU_PLL,
+ SYS_PLL1,
+ SYS_PLL2,
+ SYS_PLL3,
+ DRAM_PLL,
+ AUDIO_PLL1,
+ AUDIO_PLL2,
+ VIDEO_PLL2,
+ NR_PLLS,
+};
+
+static const struct imx_pll14xx_rate_table imx8mn_pll1416x_tbl[] = {
+ PLL_1416X_RATE(1800000000U, 225, 3, 0),
+ PLL_1416X_RATE(1600000000U, 200, 3, 0),
+ PLL_1416X_RATE(1200000000U, 300, 3, 1),
+ PLL_1416X_RATE(1000000000U, 250, 3, 1),
+ PLL_1416X_RATE(800000000U, 200, 3, 1),
+ PLL_1416X_RATE(750000000U, 250, 2, 2),
+ PLL_1416X_RATE(700000000U, 350, 3, 2),
+ PLL_1416X_RATE(600000000U, 300, 3, 2),
+};
+
+static const struct imx_pll14xx_rate_table imx8mn_audiopll_tbl[] = {
+ PLL_1443X_RATE(786432000U, 655, 5, 2, 23593),
+ PLL_1443X_RATE(722534400U, 301, 5, 1, 3670),
+};
+
+static const struct imx_pll14xx_rate_table imx8mn_videopll_tbl[] = {
+ PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+ PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
+};
+
+static const struct imx_pll14xx_rate_table imx8mn_drampll_tbl[] = {
+ PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+};
+
+static struct imx_pll14xx_clk imx8mn_audio_pll = {
+ .type = PLL_1443X,
+ .rate_table = imx8mn_audiopll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_video_pll = {
+ .type = PLL_1443X,
+ .rate_table = imx8mn_videopll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_dram_pll = {
+ .type = PLL_1443X,
+ .rate_table = imx8mn_drampll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_arm_pll = {
+ .type = PLL_1416X,
+ .rate_table = imx8mn_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_gpu_pll = {
+ .type = PLL_1416X,
+ .rate_table = imx8mn_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_vpu_pll = {
+ .type = PLL_1416X,
+ .rate_table = imx8mn_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mn_sys_pll = {
+ .type = PLL_1416X,
+ .rate_table = imx8mn_pll1416x_tbl,
+};
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m",
+ "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
+ "audio_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll1_100m",};
+
+static const char * const imx8mn_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mn_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll1_out", };
+
+static const char * const imx8mn_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
+ "clk_ext1", "clk_ext4", };
+
+static const char * const imx8mn_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m",
+ "sys_pll3_out", "sys1_pll_40m", "audio_pll2_out",
+ "clk_ext1", "clk_ext3", };
+
+static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m",
+ "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mn_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mn_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m",
+ "sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll1_out", "sys_pll1_266m", };
+
+static const char * const imx8mn_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+ "audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "clk_ext4", };
+
+static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
+ "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+ "video_pll1_out", "clk_ext4", };
+
+static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out", };
+
+static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m",
+ "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
+ "audio_pll2_out", };
+
+static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
+ "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
+ "sys_pll2_250m", "video_pll1_out", };
+
+static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys1_pll_400m", "sys_pll1_800m",
+ "sys2_pll_500m", "audio_pll2_out", "sys1_pll_266m",
+ "sys3_pll2_out", "sys1_pll_100m", };
+
+static const char * const imx8mn_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_usb_core_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys3_pll2_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m",
+ "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
+ "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out",
+ "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m",
+ "sys_pll2_500m", "sys_pll1_100m", };
+
+static const char * const imx8mn_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_clk", "sys_pll1_100m", };
+
+static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
+static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
+ "sys_pll1_200m", "audio_pll2_clk", "vpu_pll",
+ "sys_pll1_80m", };
+static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
+ "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "osc_32k", };
+
+static struct clk *clks[IMX8MN_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int imx8mn_clocks_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void __iomem *base;
+ int ret;
+
+ clks[IMX8MN_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+ clks[IMX8MN_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
+ clks[IMX8MN_CLK_32K] = of_clk_get_by_name(np, "osc_32k");
+ clks[IMX8MN_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
+ clks[IMX8MN_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2");
+ clks[IMX8MN_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3");
+ clks[IMX8MN_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4");
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
+ base = of_iomap(np, 0);
+ if (WARN_ON(!base)) {
+ ret = -ENOMEM;
+ goto unregister_clks;
+ }
+
+ clks[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_SYS_PLL1_REF_SEL] = imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_SYS_PLL2_REF_SEL] = imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+ clks[IMX8MN_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx8mn_audio_pll);
+ clks[IMX8MN_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx8mn_audio_pll);
+ clks[IMX8MN_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx8mn_video_pll);
+ clks[IMX8MN_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mn_dram_pll);
+ clks[IMX8MN_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx8mn_gpu_pll);
+ clks[IMX8MN_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx8mn_vpu_pll);
+ clks[IMX8MN_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mn_arm_pll);
+ clks[IMX8MN_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mn_sys_pll);
+ clks[IMX8MN_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mn_sys_pll);
+ clks[IMX8MN_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mn_sys_pll);
+
+ /* PLL bypass out */
+ clks[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+
+ /* unbypass all the plls */
+ clk_set_parent(clks[IMX8MN_AUDIO_PLL1_BYPASS], clks[IMX8MN_AUDIO_PLL1]);
+ clk_set_parent(clks[IMX8MN_AUDIO_PLL2_BYPASS], clks[IMX8MN_AUDIO_PLL2]);
+ clk_set_parent(clks[IMX8MN_VIDEO_PLL1_BYPASS], clks[IMX8MN_VIDEO_PLL1]);
+ clk_set_parent(clks[IMX8MN_DRAM_PLL_BYPASS], clks[IMX8MN_DRAM_PLL]);
+ clk_set_parent(clks[IMX8MN_GPU_PLL_BYPASS], clks[IMX8MN_GPU_PLL]);
+ clk_set_parent(clks[IMX8MN_VPU_PLL_BYPASS], clks[IMX8MN_VPU_PLL]);
+ clk_set_parent(clks[IMX8MN_ARM_PLL_BYPASS], clks[IMX8MN_ARM_PLL]);
+ clk_set_parent(clks[IMX8MN_SYS_PLL1_BYPASS], clks[IMX8MN_SYS_PLL1]);
+ clk_set_parent(clks[IMX8MN_SYS_PLL2_BYPASS], clks[IMX8MN_SYS_PLL2]);
+ clk_set_parent(clks[IMX8MN_SYS_PLL3_BYPASS], clks[IMX8MN_SYS_PLL3]);
+
+ /* PLL out gate */
+ clks[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
+ clks[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
+ clks[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
+ clks[IMX8MN_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
+ clks[IMX8MN_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13);
+ clks[IMX8MN_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13);
+ clks[IMX8MN_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13);
+ clks[IMX8MN_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13);
+ clks[IMX8MN_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13);
+ clks[IMX8MN_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13);
+
+ /* SYS PLL fixed output */
+ clks[IMX8MN_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+ clks[IMX8MN_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+ clks[IMX8MN_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+ clks[IMX8MN_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+ clks[IMX8MN_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+ clks[IMX8MN_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+ clks[IMX8MN_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+ clks[IMX8MN_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+ clks[IMX8MN_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+ clks[IMX8MN_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+ clks[IMX8MN_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+ clks[IMX8MN_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+ clks[IMX8MN_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+ clks[IMX8MN_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+ clks[IMX8MN_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+ clks[IMX8MN_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+ clks[IMX8MN_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+ clks[IMX8MN_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+ np = dev->of_node;
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (WARN_ON(IS_ERR(base))) {
+ ret = PTR_ERR(base);
+ goto unregister_clks;
+ }
+
+ /* CORE */
+ clks[IMX8MN_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mn_a53_sels, ARRAY_SIZE(imx8mn_a53_sels));
+ clks[IMX8MN_CLK_GPU_CORE_SRC] = imx_clk_mux2("gpu_core_src", base + 0x8180, 24, 3, imx8mn_gpu_core_sels, ARRAY_SIZE(imx8mn_gpu_core_sels));
+ clks[IMX8MN_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mn_gpu_shader_sels, ARRAY_SIZE(imx8mn_gpu_shader_sels));
+ clks[IMX8MN_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28);
+ clks[IMX8MN_CLK_GPU_CORE_CG] = imx_clk_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28);
+ clks[IMX8MN_CLK_GPU_SHADER_CG] = imx_clk_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28);
+
+ clks[IMX8MN_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
+ clks[IMX8MN_CLK_GPU_CORE_DIV] = imx_clk_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3);
+ clks[IMX8MN_CLK_GPU_SHADER_DIV] = imx_clk_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3);
+
+ /* BUS */
+ clks[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
+ clks[IMX8MN_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
+ clks[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_composite("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
+ clks[IMX8MN_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
+ clks[IMX8MN_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mn_disp_apb_sels, base + 0x8a80);
+ clks[IMX8MN_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
+ clks[IMX8MN_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
+ clks[IMX8MN_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
+ clks[IMX8MN_CLK_NOC] = imx8m_clk_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00);
+
+ clks[IMX8MN_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
+ clks[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
+ clks[IMX8MN_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
+ clks[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
+ clks[IMX8MN_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mn_dram_core_sels, ARRAY_SIZE(imx8mn_dram_core_sels), CLK_IS_CRITICAL);
+ clks[IMX8MN_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000);
+ clks[IMX8MN_CLK_DRAM_APB] = imx8m_clk_composite_critical("dram_apb", imx8mn_dram_apb_sels, base + 0xa080);
+ clks[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500);
+ clks[IMX8MN_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mn_sai2_sels, base + 0xa600);
+ clks[IMX8MN_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mn_sai3_sels, base + 0xa680);
+ clks[IMX8MN_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mn_sai5_sels, base + 0xa780);
+ clks[IMX8MN_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mn_sai6_sels, base + 0xa800);
+ clks[IMX8MN_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mn_spdif1_sels, base + 0xa880);
+ clks[IMX8MN_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mn_enet_ref_sels, base + 0xa980);
+ clks[IMX8MN_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mn_enet_timer_sels, base + 0xaa00);
+ clks[IMX8MN_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mn_enet_phy_sels, base + 0xaa80);
+ clks[IMX8MN_CLK_NAND] = imx8m_clk_composite("nand", imx8mn_nand_sels, base + 0xab00);
+ clks[IMX8MN_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mn_qspi_sels, base + 0xab80);
+ clks[IMX8MN_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mn_usdhc1_sels, base + 0xac00);
+ clks[IMX8MN_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mn_usdhc2_sels, base + 0xac80);
+ clks[IMX8MN_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mn_i2c1_sels, base + 0xad00);
+ clks[IMX8MN_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mn_i2c2_sels, base + 0xad80);
+ clks[IMX8MN_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mn_i2c3_sels, base + 0xae00);
+ clks[IMX8MN_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mn_i2c4_sels, base + 0xae80);
+ clks[IMX8MN_CLK_UART1] = imx8m_clk_composite("uart1", imx8mn_uart1_sels, base + 0xaf00);
+ clks[IMX8MN_CLK_UART2] = imx8m_clk_composite("uart2", imx8mn_uart2_sels, base + 0xaf80);
+ clks[IMX8MN_CLK_UART3] = imx8m_clk_composite("uart3", imx8mn_uart3_sels, base + 0xb000);
+ clks[IMX8MN_CLK_UART4] = imx8m_clk_composite("uart4", imx8mn_uart4_sels, base + 0xb080);
+ clks[IMX8MN_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mn_usb_core_sels, base + 0xb100);
+ clks[IMX8MN_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mn_usb_phy_sels, base + 0xb180);
+ clks[IMX8MN_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mn_ecspi1_sels, base + 0xb280);
+ clks[IMX8MN_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mn_ecspi2_sels, base + 0xb300);
+ clks[IMX8MN_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mn_pwm1_sels, base + 0xb380);
+ clks[IMX8MN_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mn_pwm2_sels, base + 0xb400);
+ clks[IMX8MN_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mn_pwm3_sels, base + 0xb480);
+ clks[IMX8MN_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mn_pwm4_sels, base + 0xb500);
+ clks[IMX8MN_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mn_wdog_sels, base + 0xb900);
+ clks[IMX8MN_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mn_wrclk_sels, base + 0xb980);
+ clks[IMX8MN_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mn_clko1_sels, base + 0xba00);
+ clks[IMX8MN_CLK_CLKO2] = imx8m_clk_composite("clko2", imx8mn_clko2_sels, base + 0xba80);
+ clks[IMX8MN_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mn_dsi_core_sels, base + 0xbb00);
+ clks[IMX8MN_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mn_dsi_phy_sels, base + 0xbb80);
+ clks[IMX8MN_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mn_dsi_dbi_sels, base + 0xbc00);
+ clks[IMX8MN_CLK_USDHC3] = imx8m_clk_composite("usdhc3", imx8mn_usdhc3_sels, base + 0xbc80);
+ clks[IMX8MN_CLK_CAMERA_PIXEL] = imx8m_clk_composite("camera_pixel", imx8mn_camera_pixel_sels, base + 0xbd00);
+ clks[IMX8MN_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mn_csi1_phy_sels, base + 0xbd80);
+ clks[IMX8MN_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mn_csi2_phy_sels, base + 0xbf00);
+ clks[IMX8MN_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mn_csi2_esc_sels, base + 0xbf80);
+ clks[IMX8MN_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mn_ecspi3_sels, base + 0xc180);
+ clks[IMX8MN_CLK_PDM] = imx8m_clk_composite("pdm", imx8mn_pdm_sels, base + 0xc200);
+ clks[IMX8MN_CLK_SAI7] = imx8m_clk_composite("sai7", imx8mn_sai7_sels, base + 0xc300);
+
+ clks[IMX8MN_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0);
+ clks[IMX8MN_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
+ clks[IMX8MN_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
+ clks[IMX8MN_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+ clks[IMX8MN_CLK_GPIO1_ROOT] = imx_clk_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0);
+ clks[IMX8MN_CLK_GPIO2_ROOT] = imx_clk_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0);
+ clks[IMX8MN_CLK_GPIO3_ROOT] = imx_clk_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0);
+ clks[IMX8MN_CLK_GPIO4_ROOT] = imx_clk_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0);
+ clks[IMX8MN_CLK_GPIO5_ROOT] = imx_clk_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0);
+ clks[IMX8MN_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
+ clks[IMX8MN_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
+ clks[IMX8MN_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0);
+ clks[IMX8MN_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0);
+ clks[IMX8MN_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0);
+ clks[IMX8MN_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0);
+ clks[IMX8MN_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0);
+ clks[IMX8MN_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0);
+ clks[IMX8MN_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0);
+ clks[IMX8MN_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0);
+ clks[IMX8MN_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0);
+ clks[IMX8MN_CLK_NAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand);
+ clks[IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0, &share_count_nand);
+ clks[IMX8MN_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", base + 0x4340, 0, &share_count_sai2);
+ clks[IMX8MN_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_audio_root", base + 0x4340, 0, &share_count_sai2);
+ clks[IMX8MN_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", base + 0x4350, 0, &share_count_sai3);
+ clks[IMX8MN_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_audio_root", base + 0x4350, 0, &share_count_sai3);
+ clks[IMX8MN_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", base + 0x4370, 0, &share_count_sai5);
+ clks[IMX8MN_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5);
+ clks[IMX8MN_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6);
+ clks[IMX8MN_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6);
+ clks[IMX8MN_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
+ clks[IMX8MN_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
+ clks[IMX8MN_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
+ clks[IMX8MN_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
+ clks[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
+ clks[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_gate4("gpu_core_root_clk", "gpu_core_div", base + 0x44f0, 0);
+ clks[IMX8MN_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
+ clks[IMX8MN_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
+ clks[IMX8MN_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0);
+ clks[IMX8MN_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0);
+ clks[IMX8MN_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0);
+ clks[IMX8MN_CLK_GPU_BUS_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_axi", base + 0x4570, 0);
+ clks[IMX8MN_CLK_ASRC_ROOT] = imx_clk_gate4("asrc_root_clk", "audio_ahb", base + 0x4580, 0);
+ clks[IMX8MN_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", base + 0x45b0, 0, &share_count_pdm);
+ clks[IMX8MN_CLK_PDM_IPG] = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", base + 0x45b0, 0, &share_count_pdm);
+ clks[IMX8MN_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_disp);
+ clks[IMX8MN_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_disp);
+ clks[IMX8MN_CLK_CAMERA_PIXEL_ROOT] = imx_clk_gate2_shared2("camera_pixel_clk", "camera_pixel", base + 0x45d0, 0, &share_count_disp);
+ clks[IMX8MN_CLK_DISP_PIXEL_ROOT] = imx_clk_gate2_shared2("disp_pixel_clk", "disp_pixel", base + 0x45d0, 0, &share_count_disp);
+ clks[IMX8MN_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0);
+ clks[IMX8MN_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0);
+ clks[IMX8MN_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0);
+ clks[IMX8MN_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0);
+ clks[IMX8MN_CLK_SDMA3_ROOT] = imx_clk_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0);
+ clks[IMX8MN_CLK_SAI7_ROOT] = imx_clk_gate2_shared2("sai7_root_clk", "sai7", base + 0x4650, 0, &share_count_sai7);
+
+ clks[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
+
+ clks[IMX8MN_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div",
+ clks[IMX8MN_CLK_A53_DIV],
+ clks[IMX8MN_CLK_A53_SRC],
+ clks[IMX8MN_ARM_PLL_OUT],
+ clks[IMX8MN_CLK_24M]);
+
+ imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ if (ret < 0) {
+ dev_err(dev, "failed to register clks for i.MX8MN\n");
+ goto unregister_clks;
+ }
+
+ return 0;
+
+unregister_clks:
+ imx_unregister_clocks(clks, ARRAY_SIZE(clks));
+
+ return ret;
+}
+
+static const struct of_device_id imx8mn_clk_of_match[] = {
+ { .compatible = "fsl,imx8mn-ccm" },
+ { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mn_clk_of_match);
+
+static struct platform_driver imx8mn_clk_driver = {
+ .probe = imx8mn_clocks_probe,
+ .driver = {
+ .name = "imx8mn-ccm",
+ .of_match_table = of_match_ptr(imx8mn_clk_of_match),
+ },
+};
+module_platform_driver(imx8mn_clk_driver);
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
index fb6edf1b8aa2..c0aff7ca6374 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -72,6 +72,11 @@ static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
{ IMX_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, },
{ IMX_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, },
{ IMX_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, },
+
+ { IMX_ADMA_LPCG_DSP_CORE_CLK, "dsp_lpcg_core_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 28, 0, },
+ { IMX_ADMA_LPCG_DSP_IPG_CLK, "dsp_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 20, 0, },
+ { IMX_ADMA_LPCG_DSP_ADB_CLK, "dsp_lpcg_adb_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 16, 0, },
+ { IMX_ADMA_LPCG_OCRAM_IPG_CLK, "ocram_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_OCRAM_LPCG, 16, 0, },
};
static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = {
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index f628071f6605..cfc05e43c343 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -14,6 +14,14 @@
DEFINE_SPINLOCK(imx_ccm_lock);
+void imx_unregister_clocks(struct clk *clks[], unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ clk_unregister(clks[i]);
+}
+
void __init imx_mmdc_mask_handshake(void __iomem *ccm_base,
unsigned int chn)
{
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index d94d9cb079d3..bb4ec1b33faf 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -12,6 +12,7 @@ void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count);
void imx_register_uart_clocks(struct clk ** const clks[]);
void imx_register_uart_clocks_hws(struct clk_hw ** const hws[]);
void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn);
+void imx_unregister_clocks(struct clk *clks[], unsigned int count);
extern void imx_cscmr1_fixup(u32 *val);
@@ -153,6 +154,23 @@ enum imx_pllv3_type {
struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base, u32 div_mask);
+#define PLL_1416X_RATE(_rate, _m, _p, _s) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ }
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ }
+
struct clk_hw *imx_clk_pllv4(const char *name, const char *parent_name,
void __iomem *base);
diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
index 1aa5f4059251..73b7e238eee7 100644
--- a/drivers/clk/mediatek/clk-mt8183.c
+++ b/drivers/clk/mediatek/clk-mt8183.c
@@ -25,9 +25,11 @@ static const struct mtk_fixed_clk top_fixed_clks[] = {
FIXED_CLK(CLK_TOP_UNIVP_192M, "univpll_192m", "univpll", 192000000),
};
+static const struct mtk_fixed_factor top_early_divs[] = {
+ FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1, 2),
+};
+
static const struct mtk_fixed_factor top_divs[] = {
- FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1,
- 2),
FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1,
2),
FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1,
@@ -1148,37 +1150,57 @@ static int clk_mt8183_apmixed_probe(struct platform_device *pdev)
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
+static struct clk_onecell_data *top_clk_data;
+
+static void clk_mt8183_top_init_early(struct device_node *node)
+{
+ int i;
+
+ top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+ for (i = 0; i < CLK_TOP_NR_CLK; i++)
+ top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+
+ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs),
+ top_clk_data);
+
+ of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
+}
+
+CLK_OF_DECLARE_DRIVER(mt8183_topckgen, "mediatek,mt8183-topckgen",
+ clk_mt8183_top_init_early);
+
static int clk_mt8183_top_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *base;
- struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
- clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
-
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
- clk_data);
+ top_clk_data);
+
+ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs),
+ top_clk_data);
- mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data);
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes),
- node, &mt8183_clk_lock, clk_data);
+ node, &mt8183_clk_lock, top_clk_data);
mtk_clk_register_composites(top_aud_muxes, ARRAY_SIZE(top_aud_muxes),
- base, &mt8183_clk_lock, clk_data);
+ base, &mt8183_clk_lock, top_clk_data);
mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs),
- base, &mt8183_clk_lock, clk_data);
+ base, &mt8183_clk_lock, top_clk_data);
mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
- clk_data);
+ top_clk_data);
- return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ return of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
}
static int clk_mt8183_infra_probe(struct platform_device *pdev)
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index a6b20e123e0c..dabeb435d067 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -1,7 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-config COMMON_CLK_MESON_INPUT
- tristate
-
config COMMON_CLK_MESON_REGMAP
tristate
select REGMAP
@@ -33,13 +30,15 @@ config COMMON_CLK_MESON_VID_PLL_DIV
config COMMON_CLK_MESON_AO_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
- select COMMON_CLK_MESON_INPUT
select RESET_CONTROLLER
config COMMON_CLK_MESON_EE_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
- select COMMON_CLK_MESON_INPUT
+
+config COMMON_CLK_MESON_CPU_DYNDIV
+ tristate
+ select COMMON_CLK_MESON_REGMAP
config COMMON_CLK_MESON8B
bool
@@ -86,7 +85,6 @@ config COMMON_CLK_AXG
config COMMON_CLK_AXG_AUDIO
tristate "Meson AXG Audio Clock Controller Driver"
depends on ARCH_MESON
- select COMMON_CLK_MESON_INPUT
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_PHASE
select COMMON_CLK_MESON_SCLK_DIV
@@ -104,6 +102,7 @@ config COMMON_CLK_G12A
select COMMON_CLK_MESON_PLL
select COMMON_CLK_MESON_AO_CLKC
select COMMON_CLK_MESON_EE_CLKC
+ select COMMON_CLK_MESON_CPU_DYNDIV
select MFD_SYSCON
help
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index bc35a4efd6b7..3939f218587a 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -2,9 +2,9 @@
# Amlogic clock drivers
obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o
+obj-$(CONFIG_COMMON_CLK_MESON_CPU_DYNDIV) += clk-cpu-dyndiv.o
obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o
obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
-obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o
obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o
diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c
index 0086f31288eb..b488b40c9d0e 100644
--- a/drivers/clk/meson/axg-aoclk.c
+++ b/drivers/clk/meson/axg-aoclk.c
@@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
-#define IN_PREFIX "ao-in-"
-
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@@ -42,7 +40,9 @@ static struct clk_regmap axg_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "axg_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .fw_name = "mpeg-clk", \
+ }, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -64,7 +64,9 @@ static struct clk_regmap axg_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -77,7 +79,9 @@ static struct clk_regmap axg_aoclk_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_pre",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_oscin" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_cts_oscin.hw
+ },
.num_parents = 1,
},
};
@@ -124,7 +128,9 @@ static struct clk_regmap axg_aoclk_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
- .parent_names = (const char *[]){ "axg_ao_32k_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_32k_pre.hw
+ },
.num_parents = 1,
},
};
@@ -139,8 +145,10 @@ static struct clk_regmap axg_aoclk_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "axg_ao_32k_div",
- "axg_ao_32k_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_32k_div.hw,
+ &axg_aoclk_32k_pre.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -154,7 +162,9 @@ static struct clk_regmap axg_aoclk_32k = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "axg_ao_32k_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_32k_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -170,8 +180,10 @@ static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "axg_ao_32k",
- IN_PREFIX "ext_32k-0" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &axg_aoclk_32k.hw },
+ { .fw_name = "ext_32k-0", },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -187,8 +199,10 @@ static struct clk_regmap axg_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
- "axg_ao_cts_rtc_oscin"},
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "mpeg-clk", },
+ { .hw = &axg_aoclk_cts_rtc_oscin.hw },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -203,8 +217,10 @@ static struct clk_regmap axg_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "axg_ao_clk81" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &axg_aoclk_clk81.hw },
+ },
.num_parents = 2,
},
};
@@ -218,7 +234,9 @@ static struct clk_regmap axg_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "axg_ao_saradc_mux" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_saradc_mux.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -232,7 +250,9 @@ static struct clk_regmap axg_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "axg_ao_saradc_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_aoclk_saradc_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -290,12 +310,6 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
.num = NR_CLKS,
};
-static const struct meson_aoclk_input axg_aoclk_inputs[] = {
- { .name = "xtal", .required = true },
- { .name = "mpeg-clk", .required = true },
- { .name = "ext-32k-0", .required = false },
-};
-
static const struct meson_aoclk_data axg_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(axg_aoclk_reset),
@@ -303,9 +317,6 @@ static const struct meson_aoclk_data axg_aoclkc_data = {
.num_clks = ARRAY_SIZE(axg_aoclk_regmap),
.clks = axg_aoclk_regmap,
.hw_data = &axg_aoclk_onecell_data,
- .inputs = axg_aoclk_inputs,
- .num_inputs = ARRAY_SIZE(axg_aoclk_inputs),
- .input_prefix = IN_PREFIX,
};
static const struct of_device_id axg_aoclkc_match_table[] = {
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 8028ff6f6610..741df7e955ca 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include "axg-audio.h"
-#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-phase.h"
#include "sclk-div.h"
@@ -24,7 +23,7 @@
#define AUD_SLV_SCLK_COUNT 10
#define AUD_SLV_LRCLK_COUNT 10
-#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) \
+#define AUD_GATE(_name, _reg, _bit, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@@ -33,13 +32,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &clk_regmap_gate_ops, \
- .parent_names = (const char *[]){ _pname }, \
+ .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
-#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
+#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_mux_data){ \
.offset = (_reg), \
@@ -50,13 +49,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_mux_ops, \
- .parent_names = (_pnames), \
- .num_parents = ARRAY_SIZE(_pnames), \
+ .parent_data = _pdata, \
+ .num_parents = ARRAY_SIZE(_pdata), \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
-#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
+#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_div_data){ \
.offset = (_reg), \
@@ -67,15 +66,27 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_divider_ops, \
- .parent_names = (const char *[]) { _pname }, \
+ .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
}
#define AUD_PCLK_GATE(_name, _bit) \
- AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0)
-
+struct clk_regmap aud_##_name = { \
+ .data = &(struct clk_regmap_gate_data){ \
+ .offset = (AUDIO_CLK_GATE_EN), \
+ .bit_idx = (_bit), \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = "aud_"#_name, \
+ .ops = &clk_regmap_gate_ops, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .fw_name = "pclk", \
+ }, \
+ .num_parents = 1, \
+ }, \
+}
/* Audio peripheral clocks */
static AUD_PCLK_GATE(ddr_arb, 0);
static AUD_PCLK_GATE(pdm, 1);
@@ -100,14 +111,20 @@ static AUD_PCLK_GATE(power_detect, 19);
static AUD_PCLK_GATE(spdifout_b, 21);
/* Audio Master Clocks */
-static const char * const mst_mux_parent_names[] = {
- "aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3",
- "aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7",
+static const struct clk_parent_data mst_mux_parent_data[] = {
+ { .fw_name = "mst_in0", },
+ { .fw_name = "mst_in1", },
+ { .fw_name = "mst_in2", },
+ { .fw_name = "mst_in3", },
+ { .fw_name = "mst_in4", },
+ { .fw_name = "mst_in5", },
+ { .fw_name = "mst_in6", },
+ { .fw_name = "mst_in7", },
};
#define AUD_MST_MUX(_name, _reg, _flag) \
AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
- mst_mux_parent_names, CLK_SET_RATE_PARENT)
+ mst_mux_parent_data, 0)
#define AUD_MST_MCLK_MUX(_name, _reg) \
AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
@@ -129,7 +146,7 @@ static AUD_MST_MCLK_MUX(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_DIV(_name, _reg, _flag) \
AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
- "aud_"#_name"_sel", CLK_SET_RATE_PARENT) \
+ aud_##_name##_sel, CLK_SET_RATE_PARENT) \
#define AUD_MST_MCLK_DIV(_name, _reg) \
AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
@@ -150,7 +167,7 @@ static AUD_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
static AUD_MST_MCLK_DIV(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_MCLK_GATE(_name, _reg) \
- AUD_GATE(_name, _reg, 31, "aud_"#_name"_div", \
+ AUD_GATE(_name, _reg, 31, aud_##_name##_div, \
CLK_SET_RATE_PARENT)
static AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
@@ -168,7 +185,7 @@ static AUD_MST_MCLK_GATE(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
/* Sample Clocks */
#define AUD_MST_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \
- "aud_mst_"#_name"_mclk", 0)
+ aud_mst_##_name##_mclk, 0)
static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -178,7 +195,7 @@ static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \
- _hi_shift, _hi_width, _pname, _iflags) \
+ _hi_shift, _hi_width, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_sclk_div_data) { \
.div = { \
@@ -195,7 +212,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_sclk_div_ops, \
- .parent_names = (const char *[]) { _pname }, \
+ .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
@@ -203,7 +220,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \
- "aud_mst_"#_name"_sclk_pre_en", \
+ aud_mst_##_name##_sclk_pre_en, \
CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
@@ -214,8 +231,8 @@ static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_SCLK_POST_EN(_name, _reg) \
- AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
- "aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
+ AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
+ aud_mst_##_name##_sclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -224,8 +241,8 @@ static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
-#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
- _pname, _iflags) \
+#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
+ _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_clk_triphase_data) { \
.ph0 = { \
@@ -247,7 +264,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_clk_triphase_ops, \
- .parent_names = (const char *[]) { _pname }, \
+ .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
@@ -255,7 +272,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \
- "aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
+ aud_mst_##_name##_sclk_post_en, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@@ -266,7 +283,7 @@ static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
#define AUD_MST_LRCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \
- "aud_mst_"#_name"_sclk_post_en", 0) \
+ aud_mst_##_name##_sclk_post_en, 0) \
static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -277,7 +294,7 @@ static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_LRCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \
- "aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
+ aud_mst_##_name##_lrclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@@ -286,19 +303,29 @@ static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
-static const char * const tdm_sclk_parent_names[] = {
- "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
- "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
- "aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2",
- "aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5",
- "aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8",
- "aud_slv_sclk9"
+static const struct clk_parent_data tdm_sclk_parent_data[] = {
+ { .hw = &aud_mst_a_sclk.hw, },
+ { .hw = &aud_mst_b_sclk.hw, },
+ { .hw = &aud_mst_c_sclk.hw, },
+ { .hw = &aud_mst_d_sclk.hw, },
+ { .hw = &aud_mst_e_sclk.hw, },
+ { .hw = &aud_mst_f_sclk.hw, },
+ { .fw_name = "slv_sclk0", },
+ { .fw_name = "slv_sclk1", },
+ { .fw_name = "slv_sclk2", },
+ { .fw_name = "slv_sclk3", },
+ { .fw_name = "slv_sclk4", },
+ { .fw_name = "slv_sclk5", },
+ { .fw_name = "slv_sclk6", },
+ { .fw_name = "slv_sclk7", },
+ { .fw_name = "slv_sclk8", },
+ { .fw_name = "slv_sclk9", },
};
#define AUD_TDM_SCLK_MUX(_name, _reg) \
AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \
CLK_MUX_ROUND_CLOSEST, \
- tdm_sclk_parent_names, 0)
+ tdm_sclk_parent_data, 0)
static AUD_TDM_SCLK_MUX(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_MUX(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -310,7 +337,7 @@ static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \
- "aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
+ aud_tdm##_name##_sclk_sel, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_PRE_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_PRE_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -322,7 +349,7 @@ static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_POST_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \
- "aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
+ aud_tdm##_name##_sclk_pre_en, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_POST_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_POST_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -344,8 +371,9 @@ static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
.hw.init = &(struct clk_init_data) { \
.name = "aud_tdm"#_name"_sclk", \
.ops = &meson_clk_phase_ops, \
- .parent_names = (const char *[]) \
- { "aud_tdm"#_name"_sclk_post_en" }, \
+ .parent_hws = (const struct clk_hw *[]) { \
+ &aud_tdm##_name##_sclk_post_en.hw \
+ }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \
}, \
@@ -359,19 +387,29 @@ static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
-static const char * const tdm_lrclk_parent_names[] = {
- "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
- "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
- "aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2",
- "aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5",
- "aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8",
- "aud_slv_lrclk9"
+static const struct clk_parent_data tdm_lrclk_parent_data[] = {
+ { .hw = &aud_mst_a_lrclk.hw, },
+ { .hw = &aud_mst_b_lrclk.hw, },
+ { .hw = &aud_mst_c_lrclk.hw, },
+ { .hw = &aud_mst_d_lrclk.hw, },
+ { .hw = &aud_mst_e_lrclk.hw, },
+ { .hw = &aud_mst_f_lrclk.hw, },
+ { .fw_name = "slv_lrclk0", },
+ { .fw_name = "slv_lrclk1", },
+ { .fw_name = "slv_lrclk2", },
+ { .fw_name = "slv_lrclk3", },
+ { .fw_name = "slv_lrclk4", },
+ { .fw_name = "slv_lrclk5", },
+ { .fw_name = "slv_lrclk6", },
+ { .fw_name = "slv_lrclk7", },
+ { .fw_name = "slv_lrclk8", },
+ { .fw_name = "slv_lrclk9", },
};
-#define AUD_TDM_LRLCK(_name, _reg) \
- AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
- CLK_MUX_ROUND_CLOSEST, \
- tdm_lrclk_parent_names, 0)
+#define AUD_TDM_LRLCK(_name, _reg) \
+ AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
+ CLK_MUX_ROUND_CLOSEST, \
+ tdm_lrclk_parent_data, 0)
static AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_LRLCK(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -386,39 +424,51 @@ static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
AUD_MUX(tdm_##_name, _reg, 0x7, _shift, 0, _parents, \
CLK_SET_RATE_NO_REPARENT)
-static const char * const mclk_pad_ctrl_parent_names[] = {
- "aud_mst_a_mclk", "aud_mst_b_mclk", "aud_mst_c_mclk",
- "aud_mst_d_mclk", "aud_mst_e_mclk", "aud_mst_f_mclk",
+static const struct clk_parent_data mclk_pad_ctrl_parent_data[] = {
+ { .hw = &aud_mst_a_mclk.hw },
+ { .hw = &aud_mst_b_mclk.hw },
+ { .hw = &aud_mst_c_mclk.hw },
+ { .hw = &aud_mst_d_mclk.hw },
+ { .hw = &aud_mst_e_mclk.hw },
+ { .hw = &aud_mst_f_mclk.hw },
};
static AUD_TDM_PAD_CTRL(mclk_pad_0, AUDIO_MST_PAD_CTRL0, 0,
- mclk_pad_ctrl_parent_names);
+ mclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(mclk_pad_1, AUDIO_MST_PAD_CTRL0, 4,
- mclk_pad_ctrl_parent_names);
-
-static const char * const lrclk_pad_ctrl_parent_names[] = {
- "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
- "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
+ mclk_pad_ctrl_parent_data);
+
+static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
+ { .hw = &aud_mst_a_lrclk.hw },
+ { .hw = &aud_mst_b_lrclk.hw },
+ { .hw = &aud_mst_c_lrclk.hw },
+ { .hw = &aud_mst_d_lrclk.hw },
+ { .hw = &aud_mst_e_lrclk.hw },
+ { .hw = &aud_mst_f_lrclk.hw },
};
static AUD_TDM_PAD_CTRL(lrclk_pad_0, AUDIO_MST_PAD_CTRL1, 16,
- lrclk_pad_ctrl_parent_names);
+ lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_1, AUDIO_MST_PAD_CTRL1, 20,
- lrclk_pad_ctrl_parent_names);
+ lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_2, AUDIO_MST_PAD_CTRL1, 24,
- lrclk_pad_ctrl_parent_names);
-
-static const char * const sclk_pad_ctrl_parent_names[] = {
- "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
- "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
+ lrclk_pad_ctrl_parent_data);
+
+static const struct clk_parent_data sclk_pad_ctrl_parent_data[] = {
+ { .hw = &aud_mst_a_sclk.hw },
+ { .hw = &aud_mst_b_sclk.hw },
+ { .hw = &aud_mst_c_sclk.hw },
+ { .hw = &aud_mst_d_sclk.hw },
+ { .hw = &aud_mst_e_sclk.hw },
+ { .hw = &aud_mst_f_sclk.hw },
};
static AUD_TDM_PAD_CTRL(sclk_pad_0, AUDIO_MST_PAD_CTRL1, 0,
- sclk_pad_ctrl_parent_names);
+ sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_1, AUDIO_MST_PAD_CTRL1, 4,
- sclk_pad_ctrl_parent_names);
+ sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8,
- sclk_pad_ctrl_parent_names);
+ sclk_pad_ctrl_parent_data);
/*
* Array of all clocks provided by this provider
@@ -868,54 +918,6 @@ static int devm_clk_get_enable(struct device *dev, char *id)
return 0;
}
-static int axg_register_clk_hw_input(struct device *dev,
- const char *name)
-{
- char *clk_name;
- struct clk_hw *hw;
- int err = 0;
-
- clk_name = kasprintf(GFP_KERNEL, "aud_%s", name);
- if (!clk_name)
- return -ENOMEM;
-
- hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
- if (IS_ERR(hw)) {
- /* It is ok if an input clock is missing */
- if (PTR_ERR(hw) == -ENOENT) {
- dev_dbg(dev, "%s not provided", name);
- } else {
- err = PTR_ERR(hw);
- if (err != -EPROBE_DEFER)
- dev_err(dev, "failed to get %s clock", name);
- }
- }
-
- kfree(clk_name);
- return err;
-}
-
-static int axg_register_clk_hw_inputs(struct device *dev,
- const char *basename,
- unsigned int count)
-{
- char *name;
- int i, ret;
-
- for (i = 0; i < count; i++) {
- name = kasprintf(GFP_KERNEL, "%s%d", basename, i);
- if (!name)
- return -ENOMEM;
-
- ret = axg_register_clk_hw_input(dev, name);
- kfree(name);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static const struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@@ -963,29 +965,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
return ret;
}
- /* Register the peripheral input clock */
- hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
-
- /* Register optional input master clocks */
- ret = axg_register_clk_hw_inputs(dev, "mst_in",
- AUD_MST_IN_COUNT);
- if (ret)
- return ret;
-
- /* Register optional input slave sclks */
- ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
- AUD_SLV_SCLK_COUNT);
- if (ret)
- return ret;
-
- /* Register optional input slave lrclks */
- ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
- AUD_SLV_LRCLK_COUNT);
- if (ret)
- return ret;
-
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
aud_clk_regmaps[i]->map = map;
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 3ddd0efc9ee0..13fc0006f63d 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -14,7 +14,6 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
-#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-pll.h"
#include "clk-mpll.h"
@@ -59,7 +58,9 @@ static struct clk_regmap axg_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -74,7 +75,9 @@ static struct clk_regmap axg_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fixed_pll_dco.hw
+ },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@@ -114,7 +117,9 @@ static struct clk_regmap axg_sys_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -129,7 +134,9 @@ static struct clk_regmap axg_sys_pll = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "sys_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_sys_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -215,7 +222,9 @@ static struct clk_regmap axg_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -230,7 +239,9 @@ static struct clk_regmap axg_gp0_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gp0_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_gp0_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -284,7 +295,9 @@ static struct clk_regmap axg_hifi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -299,7 +312,9 @@ static struct clk_regmap axg_hifi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "hifi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_hifi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -311,7 +326,7 @@ static struct clk_fixed_factor axg_fclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -324,7 +339,9 @@ static struct clk_regmap axg_fclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fclk_div2_div.hw
+ },
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@@ -336,7 +353,7 @@ static struct clk_fixed_factor axg_fclk_div3_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -349,7 +366,9 @@ static struct clk_regmap axg_fclk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div3_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fclk_div3_div.hw
+ },
.num_parents = 1,
/*
* FIXME:
@@ -372,7 +391,7 @@ static struct clk_fixed_factor axg_fclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -385,7 +404,9 @@ static struct clk_regmap axg_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div4_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fclk_div4_div.hw
+ },
.num_parents = 1,
},
};
@@ -396,7 +417,7 @@ static struct clk_fixed_factor axg_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -409,7 +430,9 @@ static struct clk_regmap axg_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div5_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fclk_div5_div.hw
+ },
.num_parents = 1,
},
};
@@ -420,7 +443,9 @@ static struct clk_fixed_factor axg_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -433,7 +458,9 @@ static struct clk_regmap axg_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div7_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fclk_div7_div.hw
+ },
.num_parents = 1,
},
};
@@ -447,7 +474,9 @@ static struct clk_regmap axg_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -480,7 +509,9 @@ static struct clk_regmap axg_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -493,7 +524,9 @@ static struct clk_regmap axg_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -527,7 +560,9 @@ static struct clk_regmap axg_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -540,7 +575,9 @@ static struct clk_regmap axg_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -579,7 +616,9 @@ static struct clk_regmap axg_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -592,7 +631,9 @@ static struct clk_regmap axg_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -626,7 +667,9 @@ static struct clk_regmap axg_mpll3_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -639,7 +682,9 @@ static struct clk_regmap axg_mpll3 = {
.hw.init = &(struct clk_init_data){
.name = "mpll3",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll3_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpll3_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -702,7 +747,9 @@ static struct clk_regmap axg_pcie_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -717,7 +764,9 @@ static struct clk_regmap axg_pcie_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "pcie_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_pcie_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -733,7 +782,9 @@ static struct clk_regmap axg_pcie_pll = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "pcie_pll_od" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_pcie_pll_od.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -750,7 +801,7 @@ static struct clk_regmap axg_pcie_mux = {
.hw.init = &(struct clk_init_data){
.name = "pcie_mux",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "pcie_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_pcie_pll.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -767,7 +818,7 @@ static struct clk_regmap axg_pcie_ref = {
.hw.init = &(struct clk_init_data){
.name = "pcie_ref",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "pcie_mux" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_pcie_mux.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -781,7 +832,7 @@ static struct clk_regmap axg_pcie_cml_en0 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "pcie_ref" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -796,16 +847,21 @@ static struct clk_regmap axg_pcie_cml_en1 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "pcie_ref" },
+ .parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
-static const char * const clk81_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
- "fclk_div3", "fclk_div5"
+static const struct clk_parent_data clk81_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &axg_fclk_div7.hw },
+ { .hw = &axg_mpll1.hw },
+ { .hw = &axg_mpll2.hw },
+ { .hw = &axg_fclk_div4.hw },
+ { .hw = &axg_fclk_div3.hw },
+ { .hw = &axg_fclk_div5.hw },
};
static struct clk_regmap axg_mpeg_clk_sel = {
@@ -818,8 +874,8 @@ static struct clk_regmap axg_mpeg_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = clk81_parent_names,
- .num_parents = ARRAY_SIZE(clk81_parent_names),
+ .parent_data = clk81_parent_data,
+ .num_parents = ARRAY_SIZE(clk81_parent_data),
},
};
@@ -832,7 +888,9 @@ static struct clk_regmap axg_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mpeg_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpeg_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -846,15 +904,20 @@ static struct clk_regmap axg_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpeg_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_mpeg_clk_div.hw
+ },
.num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
},
};
-static const char * const axg_sd_emmc_clk0_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
-
+static const struct clk_parent_data axg_sd_emmc_clk0_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &axg_fclk_div2.hw },
+ { .hw = &axg_fclk_div3.hw },
+ { .hw = &axg_fclk_div5.hw },
+ { .hw = &axg_fclk_div7.hw },
/*
* Following these parent clocks, we should also have had mpll2, mpll3
* and gp0_pll but these clocks are too precious to be used here. All
@@ -873,8 +936,8 @@ static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = axg_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
+ .parent_data = axg_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -889,7 +952,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_sd_emmc_b_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -903,7 +968,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_sd_emmc_b_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -919,8 +986,8 @@ static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = axg_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
+ .parent_data = axg_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -935,7 +1002,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_sd_emmc_c_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -949,7 +1018,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_sd_emmc_c_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -957,9 +1028,18 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
9, 10, 11, 13, 14, };
-static const char * const gen_clk_parent_names[] = {
- IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
+static const struct clk_parent_data gen_clk_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &axg_hifi_pll.hw },
+ { .hw = &axg_mpll0.hw },
+ { .hw = &axg_mpll1.hw },
+ { .hw = &axg_mpll2.hw },
+ { .hw = &axg_mpll3.hw },
+ { .hw = &axg_fclk_div4.hw },
+ { .hw = &axg_fclk_div3.hw },
+ { .hw = &axg_fclk_div5.hw },
+ { .hw = &axg_fclk_div7.hw },
+ { .hw = &axg_gp0_pll.hw },
};
static struct clk_regmap axg_gen_clk_sel = {
@@ -978,8 +1058,8 @@ static struct clk_regmap axg_gen_clk_sel = {
* hifi_pll, mpll0, mpll1, mpll2, mpll3, fdiv4,
* fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
*/
- .parent_names = gen_clk_parent_names,
- .num_parents = ARRAY_SIZE(gen_clk_parent_names),
+ .parent_data = gen_clk_parent_data,
+ .num_parents = ARRAY_SIZE(gen_clk_parent_data),
},
};
@@ -992,7 +1072,9 @@ static struct clk_regmap axg_gen_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gen_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_gen_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1006,12 +1088,17 @@ static struct clk_regmap axg_gen_clk = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "gen_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &axg_gen_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &axg_clk81.hw)
+
/* Everything Else (EE) domain gates */
static MESON_GATE(axg_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(axg_audio_locker, HHI_GCLK_MPEG0, 2);
diff --git a/drivers/clk/meson/clk-cpu-dyndiv.c b/drivers/clk/meson/clk-cpu-dyndiv.c
new file mode 100644
index 000000000000..36976927fe82
--- /dev/null
+++ b/drivers/clk/meson/clk-cpu-dyndiv.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+
+#include "clk-regmap.h"
+#include "clk-cpu-dyndiv.h"
+
+static inline struct meson_clk_cpu_dyndiv_data *
+meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
+{
+ return (struct meson_clk_cpu_dyndiv_data *)clk->data;
+}
+
+static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
+ unsigned long prate)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
+
+ return divider_recalc_rate(hw, prate,
+ meson_parm_read(clk->map, &data->div),
+ NULL, 0, data->div.width);
+}
+
+static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
+
+ return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
+}
+
+static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
+ unsigned int val;
+ int ret;
+
+ ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
+ if (ret < 0)
+ return ret;
+
+ val = (unsigned int)ret << data->div.shift;
+
+ /* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
+ meson_parm_write(clk->map, &data->dyn, 1);
+
+ /* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
+ return regmap_update_bits(clk->map, data->div.reg_off,
+ SETPMASK(data->div.width, data->div.shift) |
+ SETPMASK(data->dyn.width, data->dyn.shift),
+ val);
+};
+
+const struct clk_ops meson_clk_cpu_dyndiv_ops = {
+ .recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
+ .round_rate = meson_clk_cpu_dyndiv_round_rate,
+ .set_rate = meson_clk_cpu_dyndiv_set_rate,
+};
+EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
+
+MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-cpu-dyndiv.h b/drivers/clk/meson/clk-cpu-dyndiv.h
new file mode 100644
index 000000000000..f4908404792e
--- /dev/null
+++ b/drivers/clk/meson/clk-cpu-dyndiv.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_CPU_DYNDIV_H
+#define __MESON_CLK_CPU_DYNDIV_H
+
+#include <linux/clk-provider.h>
+#include "parm.h"
+
+struct meson_clk_cpu_dyndiv_data {
+ struct parm div;
+ struct parm dyn;
+};
+
+extern const struct clk_ops meson_clk_cpu_dyndiv_ops;
+
+#endif /* __MESON_CLK_CPU_DYNDIV_H */
diff --git a/drivers/clk/meson/clk-input.c b/drivers/clk/meson/clk-input.c
deleted file mode 100644
index 086226e9dba6..000000000000
--- a/drivers/clk/meson/clk-input.c
+++ /dev/null
@@ -1,49 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright (c) 2018 BayLibre, SAS.
- * Author: Jerome Brunet <jbrunet@baylibre.com>
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include "clk-input.h"
-
-static const struct clk_ops meson_clk_no_ops = {};
-
-struct clk_hw *meson_clk_hw_register_input(struct device *dev,
- const char *of_name,
- const char *clk_name,
- unsigned long flags)
-{
- struct clk *parent_clk = devm_clk_get(dev, of_name);
- struct clk_init_data init;
- const char *parent_name;
- struct clk_hw *hw;
- int ret;
-
- if (IS_ERR(parent_clk))
- return (struct clk_hw *)parent_clk;
-
- hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
- if (!hw)
- return ERR_PTR(-ENOMEM);
-
- parent_name = __clk_get_name(parent_clk);
- init.name = clk_name;
- init.ops = &meson_clk_no_ops;
- init.flags = flags;
- init.parent_names = &parent_name;
- init.num_parents = 1;
- hw->init = &init;
-
- ret = devm_clk_hw_register(dev, hw);
-
- return ret ? ERR_PTR(ret) : hw;
-}
-EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
-
-MODULE_DESCRIPTION("Amlogic clock input helper");
-MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-input.h b/drivers/clk/meson/clk-input.h
deleted file mode 100644
index 4a541b9685a6..000000000000
--- a/drivers/clk/meson/clk-input.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2019 BayLibre, SAS.
- * Author: Jerome Brunet <jbrunet@baylibre.com>
- */
-
-#ifndef __MESON_CLK_INPUT_H
-#define __MESON_CLK_INPUT_H
-
-#include <linux/clk-provider.h>
-
-struct device;
-
-struct clk_hw *meson_clk_hw_register_input(struct device *dev,
- const char *of_name,
- const char *clk_name,
- unsigned long flags);
-
-#endif /* __MESON_CLK_INPUT_H */
diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h
index 1dd0abe3ba91..c4a39604cffd 100644
--- a/drivers/clk/meson/clk-regmap.h
+++ b/drivers/clk/meson/clk-regmap.h
@@ -111,7 +111,7 @@ clk_get_regmap_mux_data(struct clk_regmap *clk)
extern const struct clk_ops clk_regmap_mux_ops;
extern const struct clk_ops clk_regmap_mux_ro_ops;
-#define __MESON_GATE(_name, _reg, _bit, _ops) \
+#define __MESON_PCLK(_name, _reg, _bit, _ops, _pname) \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@@ -120,15 +120,15 @@ struct clk_regmap _name = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = _ops, \
- .parent_names = (const char *[]){ "clk81" }, \
+ .parent_hws = (const struct clk_hw *[]) { _pname }, \
.num_parents = 1, \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
}, \
}
-#define MESON_GATE(_name, _reg, _bit) \
- __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops)
+#define MESON_PCLK(_name, _reg, _bit, _pname) \
+ __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname)
-#define MESON_GATE_RO(_name, _reg, _bit) \
- __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops)
+#define MESON_PCLK_RO(_name, _reg, _bit, _pname) \
+ __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname)
#endif /* __CLK_REGMAP_H */
diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c
index 1994e735396b..62499563e4f5 100644
--- a/drivers/clk/meson/g12a-aoclk.c
+++ b/drivers/clk/meson/g12a-aoclk.c
@@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
-#define IN_PREFIX "ao-in-"
-
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@@ -51,7 +49,9 @@ static struct clk_regmap g12a_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "g12a_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .fw_name = "mpeg-clk", \
+ }, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -81,7 +81,9 @@ static struct clk_regmap g12a_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -106,7 +108,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_pre",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_oscin" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_cts_oscin.hw
+ },
.num_parents = 1,
},
};
@@ -143,7 +147,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_div",
.ops = &meson_clk_dualdiv_ops,
- .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_32k_by_oscin_pre.hw
+ },
.num_parents = 1,
},
};
@@ -158,8 +164,10 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div",
- "g12a_ao_32k_by_oscin_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_32k_by_oscin_div.hw,
+ &g12a_aoclk_32k_by_oscin_pre.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -173,7 +181,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_32k_by_oscin_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -189,7 +199,9 @@ static struct clk_regmap g12a_aoclk_cec_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_pre",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_oscin" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_cts_oscin.hw
+ },
.num_parents = 1,
},
};
@@ -226,7 +238,9 @@ static struct clk_regmap g12a_aoclk_cec_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_div",
.ops = &meson_clk_dualdiv_ops,
- .parent_names = (const char *[]){ "g12a_ao_cec_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_cec_pre.hw
+ },
.num_parents = 1,
},
};
@@ -241,8 +255,10 @@ static struct clk_regmap g12a_aoclk_cec_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "g12a_ao_cec_div",
- "g12a_ao_cec_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_cec_div.hw,
+ &g12a_aoclk_cec_pre.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -256,7 +272,9 @@ static struct clk_regmap g12a_aoclk_cec = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "g12a_ao_cec_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_cec_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -272,8 +290,10 @@ static struct clk_regmap g12a_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin",
- IN_PREFIX "ext_32k-0" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &g12a_aoclk_32k_by_oscin.hw },
+ { .fw_name = "ext-32k-0", },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -289,8 +309,10 @@ static struct clk_regmap g12a_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
- "g12a_ao_cts_rtc_oscin"},
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "mpeg-clk", },
+ { .hw = &g12a_aoclk_cts_rtc_oscin.hw },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -305,8 +327,10 @@ static struct clk_regmap g12a_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "g12a_ao_clk81" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_aoclk_clk81.hw },
+ },
.num_parents = 2,
},
};
@@ -320,7 +344,9 @@ static struct clk_regmap g12a_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "g12a_ao_saradc_mux" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_saradc_mux.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -334,7 +360,9 @@ static struct clk_regmap g12a_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "g12a_ao_saradc_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_aoclk_saradc_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -417,12 +445,6 @@ static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = {
.num = NR_CLKS,
};
-static const struct meson_aoclk_input g12a_aoclk_inputs[] = {
- { .name = "xtal", .required = true },
- { .name = "mpeg-clk", .required = true },
- { .name = "ext-32k-0", .required = false },
-};
-
static const struct meson_aoclk_data g12a_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(g12a_aoclk_reset),
@@ -430,9 +452,6 @@ static const struct meson_aoclk_data g12a_aoclkc_data = {
.num_clks = ARRAY_SIZE(g12a_aoclk_regmap),
.clks = g12a_aoclk_regmap,
.hw_data = &g12a_aoclk_onecell_data,
- .inputs = g12a_aoclk_inputs,
- .num_inputs = ARRAY_SIZE(g12a_aoclk_inputs),
- .input_prefix = IN_PREFIX,
};
static const struct of_device_id g12a_aoclkc_match_table[] = {
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index db1c4ed9d54e..c3f0ffc3280d 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -14,11 +14,12 @@
#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
-#include "clk-input.h"
#include "clk-mpll.h"
#include "clk-pll.h"
#include "clk-regmap.h"
+#include "clk-cpu-dyndiv.h"
#include "vid-pll-div.h"
#include "meson-eeclk.h"
#include "g12a.h"
@@ -61,7 +62,9 @@ static struct clk_regmap g12a_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -76,7 +79,9 @@ static struct clk_regmap g12a_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fixed_pll_dco.hw
+ },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@@ -85,16 +90,9 @@ static struct clk_regmap g12a_fixed_pll = {
},
};
-/*
- * Internal sys pll emulation configuration parameters
- */
-static const struct reg_sequence g12a_sys_init_regs[] = {
- { .reg = HHI_SYS_PLL_CNTL1, .def = 0x00000000 },
- { .reg = HHI_SYS_PLL_CNTL2, .def = 0x00000000 },
- { .reg = HHI_SYS_PLL_CNTL3, .def = 0x48681c00 },
- { .reg = HHI_SYS_PLL_CNTL4, .def = 0x88770290 },
- { .reg = HHI_SYS_PLL_CNTL5, .def = 0x39272000 },
- { .reg = HHI_SYS_PLL_CNTL6, .def = 0x56540000 },
+static const struct pll_mult_range g12a_sys_pll_mult_range = {
+ .min = 128,
+ .max = 250,
};
static struct clk_regmap g12a_sys_pll_dco = {
@@ -124,14 +122,17 @@ static struct clk_regmap g12a_sys_pll_dco = {
.shift = 29,
.width = 1,
},
- .init_regs = g12a_sys_init_regs,
- .init_count = ARRAY_SIZE(g12a_sys_init_regs),
+ .range = &g12a_sys_pll_mult_range,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
- .ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
+ /* This clock feeds the CPU, avoid disabling it */
+ .flags = CLK_IS_CRITICAL,
},
};
@@ -144,9 +145,12 @@ static struct clk_regmap g12a_sys_pll = {
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
- .ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "sys_pll_dco" },
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sys_pll_dco.hw
+ },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -177,12 +181,17 @@ static struct clk_regmap g12b_sys1_pll_dco = {
.shift = 29,
.width = 1,
},
+ .range = &g12a_sys_pll_mult_range,
},
.hw.init = &(struct clk_init_data){
.name = "sys1_pll_dco",
- .ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
+ /* This clock feeds the CPU, avoid disabling it */
+ .flags = CLK_IS_CRITICAL,
},
};
@@ -195,9 +204,12 @@ static struct clk_regmap g12b_sys1_pll = {
},
.hw.init = &(struct clk_init_data){
.name = "sys1_pll",
- .ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "sys1_pll_dco" },
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_sys1_pll_dco.hw
+ },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -209,7 +221,7 @@ static struct clk_regmap g12a_sys_pll_div16_en = {
.hw.init = &(struct clk_init_data) {
.name = "sys_pll_div16_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "sys_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_sys_pll.hw },
.num_parents = 1,
/*
* This clock is used to debug the sys_pll range
@@ -226,7 +238,9 @@ static struct clk_regmap g12b_sys1_pll_div16_en = {
.hw.init = &(struct clk_init_data) {
.name = "sys1_pll_div16_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "sys1_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_sys1_pll.hw
+ },
.num_parents = 1,
/*
* This clock is used to debug the sys_pll range
@@ -241,7 +255,9 @@ static struct clk_fixed_factor g12a_sys_pll_div16 = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_div16",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "sys_pll_div16_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sys_pll_div16_en.hw
+ },
.num_parents = 1,
},
};
@@ -252,11 +268,75 @@ static struct clk_fixed_factor g12b_sys1_pll_div16 = {
.hw.init = &(struct clk_init_data){
.name = "sys1_pll_div16",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "sys1_pll_div16_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_sys1_pll_div16_en.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap g12a_fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_FIX_PLL_CNTL1,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div2_div.hw
+ },
.num_parents = 1,
},
};
+static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap g12a_fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_FIX_PLL_CNTL1,
+ .bit_idx = 20,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div3_div.hw
+ },
+ .num_parents = 1,
+ /*
+ * This clock is used by the resident firmware and is required
+ * by the platform to operate correctly.
+ * Until the following condition are met, we need this clock to
+ * be marked as critical:
+ * a) Mark the clock used by a firmware resource, if possible
+ * b) CCF has a clock hand-off mechanism to make the sure the
+ * clock stays on until the proper driver comes along
+ */
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
/* Datasheet names this field as "premux0" */
static struct clk_regmap g12a_cpu_clk_premux0 = {
.data = &(struct clk_regmap_mux_data){
@@ -266,26 +346,61 @@ static struct clk_regmap g12a_cpu_clk_premux0 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn0_sel",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "fclk_div2",
- "fclk_div3" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div2.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ },
.num_parents = 3,
+ /* This sub-tree is used a parking clock */
+ .flags = CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+/* Datasheet names this field as "premux1" */
+static struct clk_regmap g12a_cpu_clk_premux1 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SYS_CPU_CLK_CNTL0,
+ .mask = 0x3,
+ .shift = 16,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_clk_dyn1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div2.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ },
+ .num_parents = 3,
+ /* This sub-tree is used a parking clock */
+ .flags = CLK_SET_RATE_NO_REPARENT
},
};
/* Datasheet names this field as "mux0_divn_tcnt" */
static struct clk_regmap g12a_cpu_clk_mux0_div = {
- .data = &(struct clk_regmap_div_data){
- .offset = HHI_SYS_CPU_CLK_CNTL0,
- .shift = 4,
- .width = 6,
+ .data = &(struct meson_clk_cpu_dyndiv_data){
+ .div = {
+ .reg_off = HHI_SYS_CPU_CLK_CNTL0,
+ .shift = 4,
+ .width = 6,
+ },
+ .dyn = {
+ .reg_off = HHI_SYS_CPU_CLK_CNTL0,
+ .shift = 26,
+ .width = 1,
+ },
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn0_div",
- .ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn0_sel" },
+ .ops = &meson_clk_cpu_dyndiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_premux0.hw
+ },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -298,27 +413,13 @@ static struct clk_regmap g12a_cpu_clk_postmux0 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn0",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn0_sel",
- "cpu_clk_dyn0_div" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_premux0.hw,
+ &g12a_cpu_clk_mux0_div.hw,
+ },
.num_parents = 2,
- },
-};
-
-/* Datasheet names this field as "premux1" */
-static struct clk_regmap g12a_cpu_clk_premux1 = {
- .data = &(struct clk_regmap_mux_data){
- .offset = HHI_SYS_CPU_CLK_CNTL0,
- .mask = 0x3,
- .shift = 16,
- },
- .hw.init = &(struct clk_init_data){
- .name = "cpu_clk_dyn1_sel",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "fclk_div2",
- "fclk_div3" },
- .num_parents = 3,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -332,7 +433,9 @@ static struct clk_regmap g12a_cpu_clk_mux1_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn1_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_premux1.hw
+ },
.num_parents = 1,
},
};
@@ -346,10 +449,14 @@ static struct clk_regmap g12a_cpu_clk_postmux1 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn1",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn1_sel",
- "cpu_clk_dyn1_div" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_premux1.hw,
+ &g12a_cpu_clk_mux1_div.hw,
+ },
.num_parents = 2,
+ /* This sub-tree is used a parking clock */
+ .flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -362,10 +469,13 @@ static struct clk_regmap g12a_cpu_clk_dyn = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_dyn",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn0",
- "cpu_clk_dyn1" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_postmux0.hw,
+ &g12a_cpu_clk_postmux1.hw,
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -378,10 +488,13 @@ static struct clk_regmap g12a_cpu_clk = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn",
- "sys_pll" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_dyn.hw,
+ &g12a_sys_pll.hw,
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -394,10 +507,13 @@ static struct clk_regmap g12b_cpu_clk = {
},
.hw.init = &(struct clk_init_data){
.name = "cpu_clk",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_dyn",
- "sys1_pll" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_dyn.hw,
+ &g12b_sys1_pll.hw
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -410,26 +526,38 @@ static struct clk_regmap g12b_cpub_clk_premux0 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn0_sel",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "fclk_div2",
- "fclk_div3" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div2.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ },
.num_parents = 3,
},
};
/* Datasheet names this field as "mux0_divn_tcnt" */
static struct clk_regmap g12b_cpub_clk_mux0_div = {
- .data = &(struct clk_regmap_div_data){
- .offset = HHI_SYS_CPUB_CLK_CNTL,
- .shift = 4,
- .width = 6,
+ .data = &(struct meson_clk_cpu_dyndiv_data){
+ .div = {
+ .reg_off = HHI_SYS_CPUB_CLK_CNTL,
+ .shift = 4,
+ .width = 6,
+ },
+ .dyn = {
+ .reg_off = HHI_SYS_CPUB_CLK_CNTL,
+ .shift = 26,
+ .width = 1,
+ },
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn0_div",
- .ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn0_sel" },
+ .ops = &meson_clk_cpu_dyndiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_premux0.hw
+ },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -442,10 +570,13 @@ static struct clk_regmap g12b_cpub_clk_postmux0 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn0",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn0_sel",
- "cpub_clk_dyn0_div" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_premux0.hw,
+ &g12b_cpub_clk_mux0_div.hw
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -458,11 +589,15 @@ static struct clk_regmap g12b_cpub_clk_premux1 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn1_sel",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "fclk_div2",
- "fclk_div3" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div2.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ },
.num_parents = 3,
+ /* This sub-tree is used a parking clock */
+ .flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -476,7 +611,9 @@ static struct clk_regmap g12b_cpub_clk_mux1_div = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn1_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_premux1.hw
+ },
.num_parents = 1,
},
};
@@ -490,10 +627,14 @@ static struct clk_regmap g12b_cpub_clk_postmux1 = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn1",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn1_sel",
- "cpub_clk_dyn1_div" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_premux1.hw,
+ &g12b_cpub_clk_mux1_div.hw
+ },
.num_parents = 2,
+ /* This sub-tree is used a parking clock */
+ .flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -506,10 +647,13 @@ static struct clk_regmap g12b_cpub_clk_dyn = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_dyn",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn0",
- "cpub_clk_dyn1" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_postmux0.hw,
+ &g12b_cpub_clk_postmux1.hw
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -522,13 +666,227 @@ static struct clk_regmap g12b_cpub_clk = {
},
.hw.init = &(struct clk_init_data){
.name = "cpub_clk",
- .ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_dyn",
- "sys_pll" },
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_dyn.hw,
+ &g12a_sys_pll.hw
+ },
.num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
},
};
+static int g12a_cpu_clk_mux_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if (event == POST_RATE_CHANGE || event == PRE_RATE_CHANGE) {
+ /* Wait for clock propagation before/after changing the mux */
+ udelay(100);
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block g12a_cpu_clk_mux_nb = {
+ .notifier_call = g12a_cpu_clk_mux_notifier_cb,
+};
+
+struct g12a_cpu_clk_postmux_nb_data {
+ struct notifier_block nb;
+ struct clk_hw *xtal;
+ struct clk_hw *cpu_clk_dyn;
+ struct clk_hw *cpu_clk_postmux0;
+ struct clk_hw *cpu_clk_postmux1;
+ struct clk_hw *cpu_clk_premux1;
+};
+
+static int g12a_cpu_clk_postmux_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct g12a_cpu_clk_postmux_nb_data *nb_data =
+ container_of(nb, struct g12a_cpu_clk_postmux_nb_data, nb);
+
+ switch (event) {
+ case PRE_RATE_CHANGE:
+ /*
+ * This notifier means cpu_clk_postmux0 clock will be changed
+ * to feed cpu_clk, this is the current path :
+ * cpu_clk
+ * \- cpu_clk_dyn
+ * \- cpu_clk_postmux0
+ * \- cpu_clk_muxX_div
+ * \- cpu_clk_premux0
+ * \- fclk_div3 or fclk_div2
+ * OR
+ * \- cpu_clk_premux0
+ * \- fclk_div3 or fclk_div2
+ */
+
+ /* Setup cpu_clk_premux1 to xtal */
+ clk_hw_set_parent(nb_data->cpu_clk_premux1,
+ nb_data->xtal);
+
+ /* Setup cpu_clk_postmux1 to bypass divider */
+ clk_hw_set_parent(nb_data->cpu_clk_postmux1,
+ nb_data->cpu_clk_premux1);
+
+ /* Switch to parking clk on cpu_clk_postmux1 */
+ clk_hw_set_parent(nb_data->cpu_clk_dyn,
+ nb_data->cpu_clk_postmux1);
+
+ /*
+ * Now, cpu_clk is 24MHz in the current path :
+ * cpu_clk
+ * \- cpu_clk_dyn
+ * \- cpu_clk_postmux1
+ * \- cpu_clk_premux1
+ * \- xtal
+ */
+
+ udelay(100);
+
+ return NOTIFY_OK;
+
+ case POST_RATE_CHANGE:
+ /*
+ * The cpu_clk_postmux0 has ben updated, now switch back
+ * cpu_clk_dyn to cpu_clk_postmux0 and take the changes
+ * in account.
+ */
+
+ /* Configure cpu_clk_dyn back to cpu_clk_postmux0 */
+ clk_hw_set_parent(nb_data->cpu_clk_dyn,
+ nb_data->cpu_clk_postmux0);
+
+ /*
+ * new path :
+ * cpu_clk
+ * \- cpu_clk_dyn
+ * \- cpu_clk_postmux0
+ * \- cpu_clk_muxX_div
+ * \- cpu_clk_premux0
+ * \- fclk_div3 or fclk_div2
+ * OR
+ * \- cpu_clk_premux0
+ * \- fclk_div3 or fclk_div2
+ */
+
+ udelay(100);
+
+ return NOTIFY_OK;
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct g12a_cpu_clk_postmux_nb_data g12a_cpu_clk_postmux0_nb_data = {
+ .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
+ .cpu_clk_postmux0 = &g12a_cpu_clk_postmux0.hw,
+ .cpu_clk_postmux1 = &g12a_cpu_clk_postmux1.hw,
+ .cpu_clk_premux1 = &g12a_cpu_clk_premux1.hw,
+ .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb,
+};
+
+static struct g12a_cpu_clk_postmux_nb_data g12b_cpub_clk_postmux0_nb_data = {
+ .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw,
+ .cpu_clk_postmux0 = &g12b_cpub_clk_postmux0.hw,
+ .cpu_clk_postmux1 = &g12b_cpub_clk_postmux1.hw,
+ .cpu_clk_premux1 = &g12b_cpub_clk_premux1.hw,
+ .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb,
+};
+
+struct g12a_sys_pll_nb_data {
+ struct notifier_block nb;
+ struct clk_hw *sys_pll;
+ struct clk_hw *cpu_clk;
+ struct clk_hw *cpu_clk_dyn;
+};
+
+static int g12a_sys_pll_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct g12a_sys_pll_nb_data *nb_data =
+ container_of(nb, struct g12a_sys_pll_nb_data, nb);
+
+ switch (event) {
+ case PRE_RATE_CHANGE:
+ /*
+ * This notifier means sys_pll clock will be changed
+ * to feed cpu_clk, this the current path :
+ * cpu_clk
+ * \- sys_pll
+ * \- sys_pll_dco
+ */
+
+ /* Configure cpu_clk to use cpu_clk_dyn */
+ clk_hw_set_parent(nb_data->cpu_clk,
+ nb_data->cpu_clk_dyn);
+
+ /*
+ * Now, cpu_clk uses the dyn path
+ * cpu_clk
+ * \- cpu_clk_dyn
+ * \- cpu_clk_dynX
+ * \- cpu_clk_dynX_sel
+ * \- cpu_clk_dynX_div
+ * \- xtal/fclk_div2/fclk_div3
+ * \- xtal/fclk_div2/fclk_div3
+ */
+
+ udelay(100);
+
+ return NOTIFY_OK;
+
+ case POST_RATE_CHANGE:
+ /*
+ * The sys_pll has ben updated, now switch back cpu_clk to
+ * sys_pll
+ */
+
+ /* Configure cpu_clk to use sys_pll */
+ clk_hw_set_parent(nb_data->cpu_clk,
+ nb_data->sys_pll);
+
+ udelay(100);
+
+ /* new path :
+ * cpu_clk
+ * \- sys_pll
+ * \- sys_pll_dco
+ */
+
+ return NOTIFY_OK;
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct g12a_sys_pll_nb_data g12a_sys_pll_nb_data = {
+ .sys_pll = &g12a_sys_pll.hw,
+ .cpu_clk = &g12a_cpu_clk.hw,
+ .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
+ .nb.notifier_call = g12a_sys_pll_notifier_cb,
+};
+
+/* G12B first CPU cluster uses sys1_pll */
+static struct g12a_sys_pll_nb_data g12b_cpu_clk_sys1_pll_nb_data = {
+ .sys_pll = &g12b_sys1_pll.hw,
+ .cpu_clk = &g12b_cpu_clk.hw,
+ .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
+ .nb.notifier_call = g12a_sys_pll_notifier_cb,
+};
+
+/* G12B second CPU cluster uses sys_pll */
+static struct g12a_sys_pll_nb_data g12b_cpub_clk_sys_pll_nb_data = {
+ .sys_pll = &g12a_sys_pll.hw,
+ .cpu_clk = &g12b_cpub_clk.hw,
+ .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw,
+ .nb.notifier_call = g12a_sys_pll_notifier_cb,
+};
+
static struct clk_regmap g12a_cpu_clk_div16_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_SYS_CPU_CLK_CNTL1,
@@ -537,7 +895,9 @@ static struct clk_regmap g12a_cpu_clk_div16_en = {
.hw.init = &(struct clk_init_data) {
.name = "cpu_clk_div16_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk.hw
+ },
.num_parents = 1,
/*
* This clock is used to debug the cpu_clk range
@@ -554,7 +914,9 @@ static struct clk_regmap g12b_cpub_clk_div16_en = {
.hw.init = &(struct clk_init_data) {
.name = "cpub_clk_div16_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
/*
* This clock is used to debug the cpu_clk range
@@ -569,7 +931,9 @@ static struct clk_fixed_factor g12a_cpu_clk_div16 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div16",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk_div16_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_div16_en.hw
+ },
.num_parents = 1,
},
};
@@ -580,7 +944,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div16 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div16",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk_div16_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_div16_en.hw
+ },
.num_parents = 1,
},
};
@@ -595,7 +961,7 @@ static struct clk_regmap g12a_cpu_clk_apb_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_apb_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
.num_parents = 1,
},
};
@@ -608,7 +974,9 @@ static struct clk_regmap g12a_cpu_clk_apb = {
.hw.init = &(struct clk_init_data) {
.name = "cpu_clk_apb",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_apb_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_apb_div.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -627,7 +995,7 @@ static struct clk_regmap g12a_cpu_clk_atb_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_atb_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
.num_parents = 1,
},
};
@@ -640,7 +1008,9 @@ static struct clk_regmap g12a_cpu_clk_atb = {
.hw.init = &(struct clk_init_data) {
.name = "cpu_clk_atb",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_atb_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_atb_div.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -659,7 +1029,7 @@ static struct clk_regmap g12a_cpu_clk_axi_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_axi_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
.num_parents = 1,
},
};
@@ -672,7 +1042,9 @@ static struct clk_regmap g12a_cpu_clk_axi = {
.hw.init = &(struct clk_init_data) {
.name = "cpu_clk_axi",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_axi_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_axi_div.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -691,7 +1063,17 @@ static struct clk_regmap g12a_cpu_clk_trace_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_trace_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_data = &(const struct clk_parent_data) {
+ /*
+ * Note:
+ * G12A and G12B have different cpu_clks (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so cpu_clk_trace_div picks
+ * up the appropriate one.
+ */
+ .name = "cpu_clk",
+ .index = -1,
+ },
.num_parents = 1,
},
};
@@ -704,7 +1086,9 @@ static struct clk_regmap g12a_cpu_clk_trace = {
.hw.init = &(struct clk_init_data) {
.name = "cpu_clk_trace",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpu_clk_trace_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cpu_clk_trace_div.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -719,7 +1103,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -730,7 +1116,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div3",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -741,7 +1129,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -752,7 +1142,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div5",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -763,7 +1155,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div6 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -774,7 +1168,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div7",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -785,7 +1181,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div8 = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_div8",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpub_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk.hw
+ },
.num_parents = 1,
},
};
@@ -801,13 +1199,15 @@ static struct clk_regmap g12b_cpub_clk_apb_sel = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_apb_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_div2",
- "cpub_clk_div3",
- "cpub_clk_div4",
- "cpub_clk_div5",
- "cpub_clk_div6",
- "cpub_clk_div7",
- "cpub_clk_div8" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_div2.hw,
+ &g12b_cpub_clk_div3.hw,
+ &g12b_cpub_clk_div4.hw,
+ &g12b_cpub_clk_div5.hw,
+ &g12b_cpub_clk_div6.hw,
+ &g12b_cpub_clk_div7.hw,
+ &g12b_cpub_clk_div8.hw
+ },
.num_parents = 7,
},
};
@@ -821,7 +1221,9 @@ static struct clk_regmap g12b_cpub_clk_apb = {
.hw.init = &(struct clk_init_data) {
.name = "cpub_clk_apb",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_apb_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_apb_sel.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -840,13 +1242,15 @@ static struct clk_regmap g12b_cpub_clk_atb_sel = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_atb_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_div2",
- "cpub_clk_div3",
- "cpub_clk_div4",
- "cpub_clk_div5",
- "cpub_clk_div6",
- "cpub_clk_div7",
- "cpub_clk_div8" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_div2.hw,
+ &g12b_cpub_clk_div3.hw,
+ &g12b_cpub_clk_div4.hw,
+ &g12b_cpub_clk_div5.hw,
+ &g12b_cpub_clk_div6.hw,
+ &g12b_cpub_clk_div7.hw,
+ &g12b_cpub_clk_div8.hw
+ },
.num_parents = 7,
},
};
@@ -860,7 +1264,9 @@ static struct clk_regmap g12b_cpub_clk_atb = {
.hw.init = &(struct clk_init_data) {
.name = "cpub_clk_atb",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_atb_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_atb_sel.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -879,13 +1285,15 @@ static struct clk_regmap g12b_cpub_clk_axi_sel = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_axi_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_div2",
- "cpub_clk_div3",
- "cpub_clk_div4",
- "cpub_clk_div5",
- "cpub_clk_div6",
- "cpub_clk_div7",
- "cpub_clk_div8" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_div2.hw,
+ &g12b_cpub_clk_div3.hw,
+ &g12b_cpub_clk_div4.hw,
+ &g12b_cpub_clk_div5.hw,
+ &g12b_cpub_clk_div6.hw,
+ &g12b_cpub_clk_div7.hw,
+ &g12b_cpub_clk_div8.hw
+ },
.num_parents = 7,
},
};
@@ -899,7 +1307,9 @@ static struct clk_regmap g12b_cpub_clk_axi = {
.hw.init = &(struct clk_init_data) {
.name = "cpub_clk_axi",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_axi_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_axi_sel.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -918,13 +1328,15 @@ static struct clk_regmap g12b_cpub_clk_trace_sel = {
.hw.init = &(struct clk_init_data){
.name = "cpub_clk_trace_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_div2",
- "cpub_clk_div3",
- "cpub_clk_div4",
- "cpub_clk_div5",
- "cpub_clk_div6",
- "cpub_clk_div7",
- "cpub_clk_div8" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_div2.hw,
+ &g12b_cpub_clk_div3.hw,
+ &g12b_cpub_clk_div4.hw,
+ &g12b_cpub_clk_div5.hw,
+ &g12b_cpub_clk_div6.hw,
+ &g12b_cpub_clk_div7.hw,
+ &g12b_cpub_clk_div8.hw
+ },
.num_parents = 7,
},
};
@@ -938,7 +1350,9 @@ static struct clk_regmap g12b_cpub_clk_trace = {
.hw.init = &(struct clk_init_data) {
.name = "cpub_clk_trace",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cpub_clk_trace_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12b_cpub_clk_trace_sel.hw
+ },
.num_parents = 1,
/*
* This clock is set by the ROM monitor code,
@@ -1003,7 +1417,9 @@ static struct clk_regmap g12a_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -1019,7 +1435,9 @@ static struct clk_regmap g12a_gp0_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gp0_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_gp0_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1077,7 +1495,9 @@ static struct clk_regmap g12a_hifi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -1093,7 +1513,9 @@ static struct clk_regmap g12a_hifi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "hifi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_hifi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1164,7 +1586,9 @@ static struct clk_regmap g12a_pcie_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_dco",
.ops = &meson_clk_pcie_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -1175,7 +1599,9 @@ static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_dco_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "pcie_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_pcie_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1193,7 +1619,9 @@ static struct clk_regmap g12a_pcie_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "pcie_pll_dco_div2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_pcie_pll_dco_div2.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1205,7 +1633,9 @@ static struct clk_fixed_factor g12a_pcie_pll = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_pll",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "pcie_pll_od" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_pcie_pll_od.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1247,7 +1677,9 @@ static struct clk_regmap g12a_hdmi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
/*
* Display directly handle hdmi pll registers ATM, we need
@@ -1267,7 +1699,9 @@ static struct clk_regmap g12a_hdmi_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -1283,7 +1717,9 @@ static struct clk_regmap g12a_hdmi_pll_od2 = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_hdmi_pll_od.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -1299,77 +1735,21 @@ static struct clk_regmap g12a_hdmi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_hdmi_pll_od2.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
-static struct clk_fixed_factor g12a_fclk_div2_div = {
- .mult = 1,
- .div = 2,
- .hw.init = &(struct clk_init_data){
- .name = "fclk_div2_div",
- .ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
- .num_parents = 1,
- },
-};
-
-static struct clk_regmap g12a_fclk_div2 = {
- .data = &(struct clk_regmap_gate_data){
- .offset = HHI_FIX_PLL_CNTL1,
- .bit_idx = 24,
- },
- .hw.init = &(struct clk_init_data){
- .name = "fclk_div2",
- .ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div2_div" },
- .num_parents = 1,
- },
-};
-
-static struct clk_fixed_factor g12a_fclk_div3_div = {
- .mult = 1,
- .div = 3,
- .hw.init = &(struct clk_init_data){
- .name = "fclk_div3_div",
- .ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
- .num_parents = 1,
- },
-};
-
-static struct clk_regmap g12a_fclk_div3 = {
- .data = &(struct clk_regmap_gate_data){
- .offset = HHI_FIX_PLL_CNTL1,
- .bit_idx = 20,
- },
- .hw.init = &(struct clk_init_data){
- .name = "fclk_div3",
- .ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div3_div" },
- .num_parents = 1,
- /*
- * This clock is used by the resident firmware and is required
- * by the platform to operate correctly.
- * Until the following condition are met, we need this clock to
- * be marked as critical:
- * a) Mark the clock used by a firmware resource, if possible
- * b) CCF has a clock hand-off mechanism to make the sure the
- * clock stays on until the proper driver comes along
- */
- .flags = CLK_IS_CRITICAL,
- },
-};
-
static struct clk_fixed_factor g12a_fclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -1382,7 +1762,9 @@ static struct clk_regmap g12a_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div4_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div4_div.hw
+ },
.num_parents = 1,
},
};
@@ -1393,7 +1775,7 @@ static struct clk_fixed_factor g12a_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -1406,7 +1788,9 @@ static struct clk_regmap g12a_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div5_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div5_div.hw
+ },
.num_parents = 1,
},
};
@@ -1417,7 +1801,7 @@ static struct clk_fixed_factor g12a_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -1430,7 +1814,9 @@ static struct clk_regmap g12a_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div7_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div7_div.hw
+ },
.num_parents = 1,
},
};
@@ -1441,7 +1827,9 @@ static struct clk_fixed_factor g12a_fclk_div2p5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2p5_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fixed_pll_dco.hw
+ },
.num_parents = 1,
},
};
@@ -1454,7 +1842,9 @@ static struct clk_regmap g12a_fclk_div2p5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2p5",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div2p5_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fclk_div2p5_div.hw
+ },
.num_parents = 1,
},
};
@@ -1465,7 +1855,9 @@ static struct clk_fixed_factor g12a_mpll_50m_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll_50m_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fixed_pll_dco.hw
+ },
.num_parents = 1,
},
};
@@ -1479,8 +1871,10 @@ static struct clk_regmap g12a_mpll_50m = {
.hw.init = &(struct clk_init_data){
.name = "mpll_50m",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal",
- "mpll_50m_div" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_mpll_50m_div.hw },
+ },
.num_parents = 2,
},
};
@@ -1491,7 +1885,9 @@ static struct clk_fixed_factor g12a_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_fixed_pll_dco.hw
+ },
.num_parents = 1,
},
};
@@ -1529,7 +1925,9 @@ static struct clk_regmap g12a_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -1542,7 +1940,7 @@ static struct clk_regmap g12a_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll0_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_mpll0_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1581,7 +1979,9 @@ static struct clk_regmap g12a_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -1594,7 +1994,7 @@ static struct clk_regmap g12a_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll1_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_mpll1_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1633,7 +2033,9 @@ static struct clk_regmap g12a_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -1646,7 +2048,7 @@ static struct clk_regmap g12a_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll2_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_mpll2_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1685,7 +2087,9 @@ static struct clk_regmap g12a_mpll3_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -1698,16 +2102,21 @@ static struct clk_regmap g12a_mpll3 = {
.hw.init = &(struct clk_init_data){
.name = "mpll3",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll3_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_mpll3_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
-static const char * const clk81_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
- "fclk_div3", "fclk_div5"
+static const struct clk_parent_data clk81_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div7.hw },
+ { .hw = &g12a_mpll1.hw },
+ { .hw = &g12a_mpll2.hw },
+ { .hw = &g12a_fclk_div4.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ { .hw = &g12a_fclk_div5.hw },
};
static struct clk_regmap g12a_mpeg_clk_sel = {
@@ -1720,8 +2129,8 @@ static struct clk_regmap g12a_mpeg_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = clk81_parent_names,
- .num_parents = ARRAY_SIZE(clk81_parent_names),
+ .parent_data = clk81_parent_data,
+ .num_parents = ARRAY_SIZE(clk81_parent_data),
},
};
@@ -1734,7 +2143,9 @@ static struct clk_regmap g12a_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mpeg_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpeg_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1748,15 +2159,20 @@ static struct clk_regmap g12a_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpeg_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mpeg_clk_div.hw
+ },
.num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
},
};
-static const char * const g12a_sd_emmc_clk0_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
-
+static const struct clk_parent_data g12a_sd_emmc_clk0_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div2.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ { .hw = &g12a_fclk_div5.hw },
+ { .hw = &g12a_fclk_div7.hw },
/*
* Following these parent clocks, we should also have had mpll2, mpll3
* and gp0_pll but these clocks are too precious to be used here. All
@@ -1775,8 +2191,8 @@ static struct clk_regmap g12a_sd_emmc_a_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+ .parent_data = g12a_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1790,7 +2206,9 @@ static struct clk_regmap g12a_sd_emmc_a_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_a_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1804,7 +2222,9 @@ static struct clk_regmap g12a_sd_emmc_a_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_a_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_a_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1820,8 +2240,8 @@ static struct clk_regmap g12a_sd_emmc_b_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+ .parent_data = g12a_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1835,7 +2255,9 @@ static struct clk_regmap g12a_sd_emmc_b_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_b_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1849,7 +2271,9 @@ static struct clk_regmap g12a_sd_emmc_b_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_b_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1865,8 +2289,8 @@ static struct clk_regmap g12a_sd_emmc_c_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+ .parent_data = g12a_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1880,7 +2304,9 @@ static struct clk_regmap g12a_sd_emmc_c_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_c_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1894,17 +2320,89 @@ static struct clk_regmap g12a_sd_emmc_c_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_sd_emmc_c_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
+/* Video Clocks */
+
+static struct clk_regmap g12a_vid_pll_div = {
+ .data = &(struct meson_vid_pll_div_data){
+ .val = {
+ .reg_off = HHI_VID_PLL_CLK_DIV,
+ .shift = 0,
+ .width = 15,
+ },
+ .sel = {
+ .reg_off = HHI_VID_PLL_CLK_DIV,
+ .shift = 16,
+ .width = 2,
+ },
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vid_pll_div",
+ .ops = &meson_vid_pll_div_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_pll.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct clk_hw *g12a_vid_pll_parent_hws[] = {
+ &g12a_vid_pll_div.hw,
+ &g12a_hdmi_pll.hw,
+};
+
+static struct clk_regmap g12a_vid_pll_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VID_PLL_CLK_DIV,
+ .mask = 0x1,
+ .shift = 18,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vid_pll_sel",
+ .ops = &clk_regmap_mux_ops,
+ /*
+ * bit 18 selects from 2 possible parents:
+ * vid_pll_div or hdmi_pll
+ */
+ .parent_hws = g12a_vid_pll_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_hws),
+ .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap g12a_vid_pll = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_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 *[]) {
+ &g12a_vid_pll_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ },
+};
+
/* VPU Clock */
-static const char * const g12a_vpu_parent_names[] = {
- "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7",
- "mpll1", "vid_pll", "hifi_pll", "gp0_pll",
+static const struct clk_hw *g12a_vpu_parent_hws[] = {
+ &g12a_fclk_div3.hw,
+ &g12a_fclk_div4.hw,
+ &g12a_fclk_div5.hw,
+ &g12a_fclk_div7.hw,
+ &g12a_mpll1.hw,
+ &g12a_vid_pll.hw,
+ &g12a_hifi_pll.hw,
+ &g12a_gp0_pll.hw,
};
static struct clk_regmap g12a_vpu_0_sel = {
@@ -1916,8 +2414,8 @@ static struct clk_regmap g12a_vpu_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vpu_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
+ .parent_hws = g12a_vpu_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vpu_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1931,7 +2429,7 @@ static struct clk_regmap g12a_vpu_0_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_0_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1945,7 +2443,7 @@ static struct clk_regmap g12a_vpu_0 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_0_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_0_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1960,8 +2458,8 @@ static struct clk_regmap g12a_vpu_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vpu_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
+ .parent_hws = g12a_vpu_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vpu_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1975,7 +2473,7 @@ static struct clk_regmap g12a_vpu_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_1_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1989,7 +2487,7 @@ static struct clk_regmap g12a_vpu_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_1_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_1_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2008,7 +2506,10 @@ static struct clk_regmap g12a_vpu = {
* bit 31 selects from 2 possible parents:
* vpu_0 or vpu_1
*/
- .parent_names = (const char *[]){ "vpu_0", "vpu_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vpu_0.hw,
+ &g12a_vpu_1.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2016,9 +2517,14 @@ static struct clk_regmap g12a_vpu = {
/* VDEC clocks */
-static const char * const g12a_vdec_parent_names[] = {
- "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7",
- "hifi_pll", "gp0_pll",
+static const struct clk_hw *g12a_vdec_parent_hws[] = {
+ &g12a_fclk_div2p5.hw,
+ &g12a_fclk_div3.hw,
+ &g12a_fclk_div4.hw,
+ &g12a_fclk_div5.hw,
+ &g12a_fclk_div7.hw,
+ &g12a_hifi_pll.hw,
+ &g12a_gp0_pll.hw,
};
static struct clk_regmap g12a_vdec_1_sel = {
@@ -2031,8 +2537,8 @@ static struct clk_regmap g12a_vdec_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vdec_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+ .parent_hws = g12a_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2047,7 +2553,9 @@ static struct clk_regmap g12a_vdec_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2061,7 +2569,9 @@ static struct clk_regmap g12a_vdec_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2077,8 +2587,8 @@ static struct clk_regmap g12a_vdec_hevcf_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevcf_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vdec_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+ .parent_hws = g12a_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2093,7 +2603,9 @@ static struct clk_regmap g12a_vdec_hevcf_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevcf_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_hevcf_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_hevcf_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2107,7 +2619,9 @@ static struct clk_regmap g12a_vdec_hevcf = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_hevcf",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_hevcf_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_hevcf_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2123,8 +2637,8 @@ static struct clk_regmap g12a_vdec_hevc_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vdec_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+ .parent_hws = g12a_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2139,7 +2653,9 @@ static struct clk_regmap g12a_vdec_hevc_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_hevc_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_hevc_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2153,7 +2669,9 @@ static struct clk_regmap g12a_vdec_hevc = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_hevc",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_hevc_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vdec_hevc_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2161,9 +2679,15 @@ static struct clk_regmap g12a_vdec_hevc = {
/* VAPB Clock */
-static const char * const g12a_vapb_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
- "mpll1", "vid_pll", "mpll2", "fclk_div2p5",
+static const struct clk_hw *g12a_vapb_parent_hws[] = {
+ &g12a_fclk_div4.hw,
+ &g12a_fclk_div3.hw,
+ &g12a_fclk_div5.hw,
+ &g12a_fclk_div7.hw,
+ &g12a_mpll1.hw,
+ &g12a_vid_pll.hw,
+ &g12a_mpll2.hw,
+ &g12a_fclk_div2p5.hw,
};
static struct clk_regmap g12a_vapb_0_sel = {
@@ -2175,8 +2699,8 @@ static struct clk_regmap g12a_vapb_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "vapb_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vapb_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
+ .parent_hws = g12a_vapb_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vapb_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -2190,7 +2714,9 @@ static struct clk_regmap g12a_vapb_0_div = {
.hw.init = &(struct clk_init_data){
.name = "vapb_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vapb_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vapb_0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2204,7 +2730,9 @@ static struct clk_regmap g12a_vapb_0 = {
.hw.init = &(struct clk_init_data) {
.name = "vapb_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vapb_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2219,8 +2747,8 @@ static struct clk_regmap g12a_vapb_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vapb_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vapb_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
+ .parent_hws = g12a_vapb_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vapb_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -2234,7 +2762,9 @@ static struct clk_regmap g12a_vapb_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vapb_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vapb_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vapb_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2248,7 +2778,9 @@ static struct clk_regmap g12a_vapb_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vapb_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vapb_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2267,7 +2799,10 @@ static struct clk_regmap g12a_vapb_sel = {
* bit 31 selects from 2 possible parents:
* vapb_0 or vapb_1
*/
- .parent_names = (const char *[]){ "vapb_0", "vapb_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vapb_0.hw,
+ &g12a_vapb_1.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2281,75 +2816,21 @@ static struct clk_regmap g12a_vapb = {
.hw.init = &(struct clk_init_data) {
.name = "vapb",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vapb_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-/* Video Clocks */
-
-static struct clk_regmap g12a_vid_pll_div = {
- .data = &(struct meson_vid_pll_div_data){
- .val = {
- .reg_off = HHI_VID_PLL_CLK_DIV,
- .shift = 0,
- .width = 15,
- },
- .sel = {
- .reg_off = HHI_VID_PLL_CLK_DIV,
- .shift = 16,
- .width = 2,
- },
- },
- .hw.init = &(struct clk_init_data) {
- .name = "vid_pll_div",
- .ops = &meson_vid_pll_div_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll" },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
- },
-};
-
-static const char * const g12a_vid_pll_parent_names[] = { "vid_pll_div",
- "hdmi_pll" };
-
-static struct clk_regmap g12a_vid_pll_sel = {
- .data = &(struct clk_regmap_mux_data){
- .offset = HHI_VID_PLL_CLK_DIV,
- .mask = 0x1,
- .shift = 18,
- },
- .hw.init = &(struct clk_init_data){
- .name = "vid_pll_sel",
- .ops = &clk_regmap_mux_ops,
- /*
- * bit 18 selects from 2 possible parents:
- * vid_pll_div or hdmi_pll
- */
- .parent_names = g12a_vid_pll_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_names),
- .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
- },
-};
-
-static struct clk_regmap g12a_vid_pll = {
- .data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_PLL_CLK_DIV,
- .bit_idx = 19,
- },
- .hw.init = &(struct clk_init_data) {
- .name = "vid_pll",
- .ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vid_pll_sel" },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
- },
-};
-
-static const char * const g12a_vclk_parent_names[] = {
- "vid_pll", "gp0_pll", "hifi_pll", "mpll1", "fclk_div3", "fclk_div4",
- "fclk_div5", "fclk_div7"
+static const struct clk_hw *g12a_vclk_parent_hws[] = {
+ &g12a_vid_pll.hw,
+ &g12a_gp0_pll.hw,
+ &g12a_hifi_pll.hw,
+ &g12a_mpll1.hw,
+ &g12a_fclk_div3.hw,
+ &g12a_fclk_div4.hw,
+ &g12a_fclk_div5.hw,
+ &g12a_fclk_div7.hw,
};
static struct clk_regmap g12a_vclk_sel = {
@@ -2361,8 +2842,8 @@ static struct clk_regmap g12a_vclk_sel = {
.hw.init = &(struct clk_init_data){
.name = "vclk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vclk_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
+ .parent_hws = g12a_vclk_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2376,8 +2857,8 @@ static struct clk_regmap g12a_vclk2_sel = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_vclk_parent_names,
- .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
+ .parent_hws = g12a_vclk_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2390,7 +2871,7 @@ static struct clk_regmap g12a_vclk_input = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_input",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2404,7 +2885,7 @@ static struct clk_regmap g12a_vclk2_input = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_input",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2419,7 +2900,9 @@ static struct clk_regmap g12a_vclk_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vclk_input" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk_input.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -2434,7 +2917,9 @@ static struct clk_regmap g12a_vclk2_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vclk2_input" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk2_input.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -2448,7 +2933,7 @@ static struct clk_regmap g12a_vclk = {
.hw.init = &(struct clk_init_data) {
.name = "vclk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2462,7 +2947,7 @@ static struct clk_regmap g12a_vclk2 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2476,7 +2961,7 @@ static struct clk_regmap g12a_vclk_div1 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2490,7 +2975,7 @@ static struct clk_regmap g12a_vclk_div2_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div2_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2504,7 +2989,7 @@ static struct clk_regmap g12a_vclk_div4_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div4_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2518,7 +3003,7 @@ static struct clk_regmap g12a_vclk_div6_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div6_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2532,7 +3017,7 @@ static struct clk_regmap g12a_vclk_div12_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div12_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2546,7 +3031,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2560,7 +3045,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div2_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2574,7 +3059,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div4_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2588,7 +3073,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div6_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2602,7 +3087,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div12_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2614,7 +3099,9 @@ static struct clk_fixed_factor g12a_vclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div2_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk_div2_en.hw
+ },
.num_parents = 1,
},
};
@@ -2625,7 +3112,9 @@ static struct clk_fixed_factor g12a_vclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div4_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk_div4_en.hw
+ },
.num_parents = 1,
},
};
@@ -2636,7 +3125,9 @@ static struct clk_fixed_factor g12a_vclk_div6 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div6_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk_div6_en.hw
+ },
.num_parents = 1,
},
};
@@ -2647,7 +3138,9 @@ static struct clk_fixed_factor g12a_vclk_div12 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div12_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk_div12_en.hw
+ },
.num_parents = 1,
},
};
@@ -2658,7 +3151,9 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div2_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk2_div2_en.hw
+ },
.num_parents = 1,
},
};
@@ -2669,7 +3164,9 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div4_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk2_div4_en.hw
+ },
.num_parents = 1,
},
};
@@ -2680,7 +3177,9 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div6_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk2_div6_en.hw
+ },
.num_parents = 1,
},
};
@@ -2691,16 +3190,25 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div12_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_vclk2_div12_en.hw
+ },
.num_parents = 1,
},
};
static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
-static const char * const g12a_cts_parent_names[] = {
- "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
- "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
- "vclk2_div6", "vclk2_div12"
+static const struct clk_hw *g12a_cts_parent_hws[] = {
+ &g12a_vclk_div1.hw,
+ &g12a_vclk_div2.hw,
+ &g12a_vclk_div4.hw,
+ &g12a_vclk_div6.hw,
+ &g12a_vclk_div12.hw,
+ &g12a_vclk2_div1.hw,
+ &g12a_vclk2_div2.hw,
+ &g12a_vclk2_div4.hw,
+ &g12a_vclk2_div6.hw,
+ &g12a_vclk2_div12.hw,
};
static struct clk_regmap g12a_cts_enci_sel = {
@@ -2713,8 +3221,8 @@ static struct clk_regmap g12a_cts_enci_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_enci_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_cts_parent_names,
- .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+ .parent_hws = g12a_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2729,8 +3237,8 @@ static struct clk_regmap g12a_cts_encp_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_encp_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_cts_parent_names,
- .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+ .parent_hws = g12a_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2745,18 +3253,25 @@ static struct clk_regmap g12a_cts_vdac_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_vdac_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_cts_parent_names,
- .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+ .parent_hws = g12a_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
/* TOFIX: add support for cts_tcon */
static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
-static const char * const g12a_cts_hdmi_tx_parent_names[] = {
- "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
- "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
- "vclk2_div6", "vclk2_div12"
+static const struct clk_hw *g12a_cts_hdmi_tx_parent_hws[] = {
+ &g12a_vclk_div1.hw,
+ &g12a_vclk_div2.hw,
+ &g12a_vclk_div4.hw,
+ &g12a_vclk_div6.hw,
+ &g12a_vclk_div12.hw,
+ &g12a_vclk2_div1.hw,
+ &g12a_vclk2_div2.hw,
+ &g12a_vclk2_div4.hw,
+ &g12a_vclk2_div6.hw,
+ &g12a_vclk2_div12.hw,
};
static struct clk_regmap g12a_hdmi_tx_sel = {
@@ -2769,8 +3284,8 @@ static struct clk_regmap g12a_hdmi_tx_sel = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_tx_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_cts_hdmi_tx_parent_names,
- .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_names),
+ .parent_hws = g12a_cts_hdmi_tx_parent_hws,
+ .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2783,7 +3298,9 @@ static struct clk_regmap g12a_cts_enci = {
.hw.init = &(struct clk_init_data) {
.name = "cts_enci",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_enci_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cts_enci_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2797,7 +3314,9 @@ static struct clk_regmap g12a_cts_encp = {
.hw.init = &(struct clk_init_data) {
.name = "cts_encp",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_encp_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cts_encp_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2811,7 +3330,9 @@ static struct clk_regmap g12a_cts_vdac = {
.hw.init = &(struct clk_init_data) {
.name = "cts_vdac",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_vdac_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_cts_vdac_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2825,7 +3346,9 @@ static struct clk_regmap g12a_hdmi_tx = {
.hw.init = &(struct clk_init_data) {
.name = "hdmi_tx",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "hdmi_tx_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_hdmi_tx_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2833,8 +3356,11 @@ static struct clk_regmap g12a_hdmi_tx = {
/* HDMI Clocks */
-static const char * const g12a_hdmi_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
+static const struct clk_parent_data g12a_hdmi_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_fclk_div4.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ { .hw = &g12a_fclk_div5.hw },
};
static struct clk_regmap g12a_hdmi_sel = {
@@ -2847,8 +3373,8 @@ static struct clk_regmap g12a_hdmi_sel = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_hdmi_parent_names,
- .num_parents = ARRAY_SIZE(g12a_hdmi_parent_names),
+ .parent_data = g12a_hdmi_parent_data,
+ .num_parents = ARRAY_SIZE(g12a_hdmi_parent_data),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2862,7 +3388,7 @@ static struct clk_regmap g12a_hdmi_div = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "hdmi_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_sel.hw },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -2876,7 +3402,7 @@ static struct clk_regmap g12a_hdmi = {
.hw.init = &(struct clk_init_data) {
.name = "hdmi",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "hdmi_div" },
+ .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2886,10 +3412,15 @@ static struct clk_regmap g12a_hdmi = {
* The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
* muxed by a glitch-free switch.
*/
-
-static const char * const g12a_mali_0_1_parent_names[] = {
- IN_PREFIX "xtal", "gp0_pll", "hihi_pll", "fclk_div2p5",
- "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7"
+static const struct clk_parent_data g12a_mali_0_1_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &g12a_gp0_pll.hw },
+ { .hw = &g12a_hifi_pll.hw },
+ { .hw = &g12a_fclk_div2p5.hw },
+ { .hw = &g12a_fclk_div3.hw },
+ { .hw = &g12a_fclk_div4.hw },
+ { .hw = &g12a_fclk_div5.hw },
+ { .hw = &g12a_fclk_div7.hw },
};
static struct clk_regmap g12a_mali_0_sel = {
@@ -2901,7 +3432,7 @@ static struct clk_regmap g12a_mali_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_mali_0_1_parent_names,
+ .parent_data = g12a_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2916,7 +3447,9 @@ static struct clk_regmap g12a_mali_0_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mali_0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2930,7 +3463,9 @@ static struct clk_regmap g12a_mali_0 = {
.hw.init = &(struct clk_init_data){
.name = "mali_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mali_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2945,7 +3480,7 @@ static struct clk_regmap g12a_mali_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_mali_0_1_parent_names,
+ .parent_data = g12a_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2960,7 +3495,9 @@ static struct clk_regmap g12a_mali_1_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mali_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -2974,14 +3511,17 @@ static struct clk_regmap g12a_mali_1 = {
.hw.init = &(struct clk_init_data){
.name = "mali_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_mali_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const g12a_mali_parent_names[] = {
- "mali_0", "mali_1"
+static const struct clk_hw *g12a_mali_parent_hws[] = {
+ &g12a_mali_0.hw,
+ &g12a_mali_1.hw,
};
static struct clk_regmap g12a_mali = {
@@ -2993,7 +3533,7 @@ static struct clk_regmap g12a_mali = {
.hw.init = &(struct clk_init_data){
.name = "mali",
.ops = &clk_regmap_mux_ops,
- .parent_names = g12a_mali_parent_names,
+ .parent_hws = g12a_mali_parent_hws,
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -3008,7 +3548,9 @@ static struct clk_regmap g12a_ts_div = {
.hw.init = &(struct clk_init_data){
.name = "ts_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -3021,11 +3563,19 @@ static struct clk_regmap g12a_ts = {
.hw.init = &(struct clk_init_data){
.name = "ts",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "ts_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &g12a_ts_div.hw
+ },
.num_parents = 1,
},
};
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw)
+
+#define MESON_GATE_RO(_name, _reg, _bit) \
+ MESON_PCLK_RO(_name, _reg, _bit, &g12a_clk81.hw)
+
/* Everything Else (EE) domain gates */
static MESON_GATE(g12a_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(g12a_dos, HHI_GCLK_MPEG0, 1);
@@ -3792,28 +4342,210 @@ static const struct reg_sequence g12a_init_regs[] = {
{ .reg = HHI_MPLL_CNTL0, .def = 0x00000543 },
};
-static const struct meson_eeclkc_data g12a_clkc_data = {
- .regmap_clks = g12a_clk_regmaps,
- .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
- .hw_onecell_data = &g12a_hw_onecell_data,
- .init_regs = g12a_init_regs,
- .init_count = ARRAY_SIZE(g12a_init_regs),
-};
-
-static const struct meson_eeclkc_data g12b_clkc_data = {
- .regmap_clks = g12a_clk_regmaps,
- .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
- .hw_onecell_data = &g12b_hw_onecell_data
+static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
+ struct clk_hw **hws)
+{
+ const char *notifier_clk_name;
+ struct clk *notifier_clk;
+ struct clk_hw *xtal;
+ int ret;
+
+ xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0);
+
+ /* Setup clock notifier for cpu_clk_postmux0 */
+ g12a_cpu_clk_postmux0_nb_data.xtal = xtal;
+ notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk,
+ &g12a_cpu_clk_postmux0_nb_data.nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for cpu_clk_dyn mux */
+ notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_g12b_dvfs_setup(struct platform_device *pdev)
+{
+ struct clk_hw **hws = g12b_hw_onecell_data.hws;
+ const char *notifier_clk_name;
+ struct clk *notifier_clk;
+ struct clk_hw *xtal;
+ int ret;
+
+ ret = meson_g12a_dvfs_setup_common(pdev, hws);
+ if (ret)
+ return ret;
+
+ xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0);
+
+ /* Setup clock notifier for cpu_clk mux */
+ notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for sys1_pll */
+ notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk,
+ &g12b_cpu_clk_sys1_pll_nb_data.nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n");
+ return ret;
+ }
+
+ /* Add notifiers for the second CPU cluster */
+
+ /* Setup clock notifier for cpub_clk_postmux0 */
+ g12b_cpub_clk_postmux0_nb_data.xtal = xtal;
+ notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk,
+ &g12b_cpub_clk_postmux0_nb_data.nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for cpub_clk_dyn mux */
+ notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for cpub_clk mux */
+ notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for sys_pll */
+ notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk,
+ &g12b_cpub_clk_sys_pll_nb_data.nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_g12a_dvfs_setup(struct platform_device *pdev)
+{
+ struct clk_hw **hws = g12a_hw_onecell_data.hws;
+ const char *notifier_clk_name;
+ struct clk *notifier_clk;
+ int ret;
+
+ ret = meson_g12a_dvfs_setup_common(pdev, hws);
+ if (ret)
+ return ret;
+
+ /* Setup clock notifier for cpu_clk mux */
+ notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
+ return ret;
+ }
+
+ /* Setup clock notifier for sys_pll */
+ notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
+ notifier_clk = __clk_lookup(notifier_clk_name);
+ ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+struct meson_g12a_data {
+ const struct meson_eeclkc_data eeclkc_data;
+ int (*dvfs_setup)(struct platform_device *pdev);
+};
+
+static int meson_g12a_probe(struct platform_device *pdev)
+{
+ const struct meson_eeclkc_data *eeclkc_data;
+ const struct meson_g12a_data *g12a_data;
+ int ret;
+
+ eeclkc_data = of_device_get_match_data(&pdev->dev);
+ if (!eeclkc_data)
+ return -EINVAL;
+
+ ret = meson_eeclkc_probe(pdev);
+ if (ret)
+ return ret;
+
+ g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
+ eeclkc_data);
+
+ if (g12a_data->dvfs_setup)
+ return g12a_data->dvfs_setup(pdev);
+
+ return 0;
+}
+
+static const struct meson_g12a_data g12a_clkc_data = {
+ .eeclkc_data = {
+ .regmap_clks = g12a_clk_regmaps,
+ .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
+ .hw_onecell_data = &g12a_hw_onecell_data,
+ .init_regs = g12a_init_regs,
+ .init_count = ARRAY_SIZE(g12a_init_regs),
+ },
+ .dvfs_setup = meson_g12a_dvfs_setup,
+};
+
+static const struct meson_g12a_data g12b_clkc_data = {
+ .eeclkc_data = {
+ .regmap_clks = g12a_clk_regmaps,
+ .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
+ .hw_onecell_data = &g12b_hw_onecell_data,
+ },
+ .dvfs_setup = meson_g12b_dvfs_setup,
};
static const struct of_device_id clkc_match_table[] = {
- { .compatible = "amlogic,g12a-clkc", .data = &g12a_clkc_data },
- { .compatible = "amlogic,g12b-clkc", .data = &g12b_clkc_data },
+ {
+ .compatible = "amlogic,g12a-clkc",
+ .data = &g12a_clkc_data.eeclkc_data
+ },
+ {
+ .compatible = "amlogic,g12b-clkc",
+ .data = &g12b_clkc_data.eeclkc_data
+ },
{}
};
static struct platform_driver g12a_driver = {
- .probe = meson_eeclkc_probe,
+ .probe = meson_g12a_probe,
.driver = {
.name = "g12a-clkc",
.of_match_table = clkc_match_table,
diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h
index c8aed31fbe17..559a34cfdfeb 100644
--- a/drivers/clk/meson/g12a.h
+++ b/drivers/clk/meson/g12a.h
@@ -216,7 +216,6 @@
#define CLKID_CPUB_CLK_DYN1_DIV 221
#define CLKID_CPUB_CLK_DYN1 222
#define CLKID_CPUB_CLK_DYN 223
-#define CLKID_CPUB_CLK 224
#define CLKID_CPUB_CLK_DIV16_EN 225
#define CLKID_CPUB_CLK_DIV16 226
#define CLKID_CPUB_CLK_DIV2 227
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 449f6ac189d8..e940861a396b 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -11,8 +11,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
-#define IN_PREFIX "ao-in-"
-
/* AO Configuration Clock registers offsets */
#define AO_RTI_PWR_CNTL_REG1 0x0c
#define AO_RTI_PWR_CNTL_REG0 0x10
@@ -31,7 +29,9 @@ static struct clk_regmap _name##_ao = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name "_ao", \
.ops = &clk_regmap_gate_ops, \
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .fw_name = "mpeg-clk", \
+ }, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -52,7 +52,9 @@ static struct clk_regmap ao_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -65,7 +67,7 @@ static struct clk_regmap ao_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_pre",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "ao_cts_oscin" },
+ .parent_hws = (const struct clk_hw *[]) { &ao_cts_oscin.hw },
.num_parents = 1,
},
};
@@ -112,7 +114,7 @@ static struct clk_regmap ao_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
- .parent_names = (const char *[]){ "ao_32k_pre" },
+ .parent_hws = (const struct clk_hw *[]) { &ao_32k_pre.hw },
.num_parents = 1,
},
};
@@ -127,8 +129,10 @@ static struct clk_regmap ao_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "ao_32k_div",
- "ao_32k_pre" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &ao_32k_div.hw,
+ &ao_32k_pre.hw
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -142,7 +146,7 @@ static struct clk_regmap ao_32k = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "ao_32k_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &ao_32k_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -159,10 +163,12 @@ static struct clk_regmap ao_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ IN_PREFIX "ext-32k-0",
- IN_PREFIX "ext-32k-1",
- IN_PREFIX "ext-32k-2",
- "ao_32k" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "ext-32k-0", },
+ { .fw_name = "ext-32k-1", },
+ { .fw_name = "ext-32k-2", },
+ { .hw = &ao_32k.hw },
+ },
.num_parents = 4,
.flags = CLK_SET_RATE_PARENT,
},
@@ -178,8 +184,10 @@ static struct clk_regmap ao_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
- "ao_cts_rtc_oscin" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "mpeg-clk", },
+ { .hw = &ao_cts_rtc_oscin.hw },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -208,8 +216,10 @@ static struct clk_regmap ao_cts_cec = {
* Until CCF gets fixed, adding this fake parent that won't
* ever be registered should work around the problem
*/
- .parent_names = (const char *[]){ "fixme",
- "ao_cts_rtc_oscin" },
+ .parent_data = (const struct clk_parent_data []) {
+ { .name = "fixme", .index = -1, },
+ { .hw = &ao_cts_rtc_oscin.hw },
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -261,14 +271,6 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
.num = NR_CLKS,
};
-static const struct meson_aoclk_input gxbb_aoclk_inputs[] = {
- { .name = "xtal", .required = true, },
- { .name = "mpeg-clk", .required = true, },
- {. name = "ext-32k-0", .required = false, },
- {. name = "ext-32k-1", .required = false, },
- {. name = "ext-32k-2", .required = false, },
-};
-
static const struct meson_aoclk_data gxbb_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(gxbb_aoclk_reset),
@@ -276,9 +278,6 @@ static const struct meson_aoclk_data gxbb_aoclkc_data = {
.num_clks = ARRAY_SIZE(gxbb_aoclk),
.clks = gxbb_aoclk,
.hw_data = &gxbb_aoclk_onecell_data,
- .inputs = gxbb_aoclk_inputs,
- .num_inputs = ARRAY_SIZE(gxbb_aoclk_inputs),
- .input_prefix = IN_PREFIX,
};
static const struct of_device_id gxbb_aoclkc_match_table[] = {
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index dab16d9b1af8..7cfb998eeb3e 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -10,15 +10,12 @@
#include <linux/platform_device.h>
#include "gxbb.h"
-#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-pll.h"
#include "clk-mpll.h"
#include "meson-eeclk.h"
#include "vid-pll-div.h"
-#define IN_PREFIX "ee-in-"
-
static DEFINE_SPINLOCK(meson_clk_lock);
static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
@@ -121,7 +118,9 @@ static struct clk_regmap gxbb_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -136,7 +135,9 @@ static struct clk_regmap gxbb_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fixed_pll_dco.hw
+ },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@@ -151,7 +152,9 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_pre_mult",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -192,7 +195,9 @@ static struct clk_regmap gxbb_hdmi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_hdmi_pll_pre_mult.hw
+ },
.num_parents = 1,
/*
* Display directly handle hdmi pll registers ATM, we need
@@ -244,7 +249,9 @@ static struct clk_regmap gxl_hdmi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
/*
* Display directly handle hdmi pll registers ATM, we need
@@ -264,7 +271,9 @@ static struct clk_regmap gxbb_hdmi_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -280,7 +289,9 @@ static struct clk_regmap gxbb_hdmi_pll_od2 = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_hdmi_pll_od.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -296,7 +307,9 @@ static struct clk_regmap gxbb_hdmi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_hdmi_pll_od2.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -312,7 +325,9 @@ static struct clk_regmap gxl_hdmi_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxl_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -328,7 +343,9 @@ static struct clk_regmap gxl_hdmi_pll_od2 = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxl_hdmi_pll_od.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -344,7 +361,9 @@ static struct clk_regmap gxl_hdmi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_od2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxl_hdmi_pll_od2.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
@@ -381,7 +400,9 @@ static struct clk_regmap gxbb_sys_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -396,7 +417,9 @@ static struct clk_regmap gxbb_sys_pll = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "sys_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sys_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -442,7 +465,9 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -494,7 +519,9 @@ static struct clk_regmap gxl_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
.num_parents = 1,
},
};
@@ -509,7 +536,17 @@ static struct clk_regmap gxbb_gp0_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gp0_pll_dco" },
+ .parent_data = &(const struct clk_parent_data) {
+ /*
+ * Note:
+ * GXL and GXBB have different gp0_pll_dco (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so gp0_pll picks up the
+ * appropriate one.
+ */
+ .name = "gp0_pll_dco",
+ .index = -1,
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -521,7 +558,9 @@ static struct clk_fixed_factor gxbb_fclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -534,7 +573,9 @@ static struct clk_regmap gxbb_fclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fclk_div2_div.hw
+ },
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@@ -546,7 +587,7 @@ static struct clk_fixed_factor gxbb_fclk_div3_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -559,7 +600,9 @@ static struct clk_regmap gxbb_fclk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div3_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fclk_div3_div.hw
+ },
.num_parents = 1,
/*
* FIXME:
@@ -582,7 +625,7 @@ static struct clk_fixed_factor gxbb_fclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -595,7 +638,9 @@ static struct clk_regmap gxbb_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div4_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fclk_div4_div.hw
+ },
.num_parents = 1,
},
};
@@ -606,7 +651,7 @@ static struct clk_fixed_factor gxbb_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -619,7 +664,9 @@ static struct clk_regmap gxbb_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div5_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fclk_div5_div.hw
+ },
.num_parents = 1,
},
};
@@ -630,7 +677,7 @@ static struct clk_fixed_factor gxbb_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -643,7 +690,9 @@ static struct clk_regmap gxbb_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div7_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_fclk_div7_div.hw
+ },
.num_parents = 1,
},
};
@@ -657,7 +706,7 @@ static struct clk_regmap gxbb_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -684,7 +733,9 @@ static struct clk_regmap gxbb_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -697,7 +748,7 @@ static struct clk_regmap gxbb_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll0_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -725,7 +776,9 @@ static struct clk_regmap gxbb_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -738,7 +791,7 @@ static struct clk_regmap gxbb_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll1_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll1_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -766,7 +819,9 @@ static struct clk_regmap gxbb_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -779,16 +834,21 @@ static struct clk_regmap gxbb_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll2_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll2_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
-static const char * const clk81_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
- "fclk_div3", "fclk_div5"
+static const struct clk_parent_data clk81_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_fclk_div7.hw },
+ { .hw = &gxbb_mpll1.hw },
+ { .hw = &gxbb_mpll2.hw },
+ { .hw = &gxbb_fclk_div4.hw },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
};
static struct clk_regmap gxbb_mpeg_clk_sel = {
@@ -806,8 +866,8 @@ static struct clk_regmap gxbb_mpeg_clk_sel = {
* xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
* fclk_div4, fclk_div3, fclk_div5
*/
- .parent_names = clk81_parent_names,
- .num_parents = ARRAY_SIZE(clk81_parent_names),
+ .parent_data = clk81_parent_data,
+ .num_parents = ARRAY_SIZE(clk81_parent_data),
},
};
@@ -820,7 +880,9 @@ static struct clk_regmap gxbb_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "mpeg_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpeg_clk_sel.hw
+ },
.num_parents = 1,
},
};
@@ -834,7 +896,9 @@ static struct clk_regmap gxbb_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpeg_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpeg_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@@ -850,7 +914,10 @@ static struct clk_regmap gxbb_sar_adc_clk_sel = {
.name = "sar_adc_clk_sel",
.ops = &clk_regmap_mux_ops,
/* NOTE: The datasheet doesn't list the parents for bit 10 */
- .parent_names = (const char *[]){ IN_PREFIX "xtal", "clk81", },
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_clk81.hw },
+ },
.num_parents = 2,
},
};
@@ -864,7 +931,9 @@ static struct clk_regmap gxbb_sar_adc_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "sar_adc_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sar_adc_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sar_adc_clk_sel.hw
+ },
.num_parents = 1,
},
};
@@ -877,7 +946,9 @@ static struct clk_regmap gxbb_sar_adc_clk = {
.hw.init = &(struct clk_init_data){
.name = "sar_adc_clk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sar_adc_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sar_adc_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -888,9 +959,15 @@ static struct clk_regmap gxbb_sar_adc_clk = {
* muxed by a glitch-free switch.
*/
-static const char * const gxbb_mali_0_1_parent_names[] = {
- IN_PREFIX "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
- "fclk_div4", "fclk_div3", "fclk_div5"
+static const struct clk_parent_data gxbb_mali_0_1_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_gp0_pll.hw },
+ { .hw = &gxbb_mpll2.hw },
+ { .hw = &gxbb_mpll1.hw },
+ { .hw = &gxbb_fclk_div7.hw },
+ { .hw = &gxbb_fclk_div4.hw },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
};
static struct clk_regmap gxbb_mali_0_sel = {
@@ -907,7 +984,7 @@ static struct clk_regmap gxbb_mali_0_sel = {
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
* fclk_div4, fclk_div3, fclk_div5
*/
- .parent_names = gxbb_mali_0_1_parent_names,
+ .parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -922,7 +999,9 @@ static struct clk_regmap gxbb_mali_0_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mali_0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -936,7 +1015,9 @@ static struct clk_regmap gxbb_mali_0 = {
.hw.init = &(struct clk_init_data){
.name = "mali_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mali_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -956,7 +1037,7 @@ static struct clk_regmap gxbb_mali_1_sel = {
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
* fclk_div4, fclk_div3, fclk_div5
*/
- .parent_names = gxbb_mali_0_1_parent_names,
+ .parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -971,7 +1052,9 @@ static struct clk_regmap gxbb_mali_1_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mali_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -985,14 +1068,17 @@ static struct clk_regmap gxbb_mali_1 = {
.hw.init = &(struct clk_init_data){
.name = "mali_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mali_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const gxbb_mali_parent_names[] = {
- "mali_0", "mali_1"
+static const struct clk_hw *gxbb_mali_parent_hws[] = {
+ &gxbb_mali_0.hw,
+ &gxbb_mali_1.hw,
};
static struct clk_regmap gxbb_mali = {
@@ -1004,7 +1090,7 @@ static struct clk_regmap gxbb_mali = {
.hw.init = &(struct clk_init_data){
.name = "mali",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_mali_parent_names,
+ .parent_hws = gxbb_mali_parent_hws,
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -1021,7 +1107,11 @@ static struct clk_regmap gxbb_cts_amclk_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpll0.hw,
+ &gxbb_mpll1.hw,
+ &gxbb_mpll2.hw,
+ },
.num_parents = 3,
},
};
@@ -1036,7 +1126,9 @@ static struct clk_regmap gxbb_cts_amclk_div = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "cts_amclk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_amclk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1050,7 +1142,9 @@ static struct clk_regmap gxbb_cts_amclk = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_amclk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_amclk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1067,7 +1161,11 @@ static struct clk_regmap gxbb_cts_mclk_i958_sel = {
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_mpll0.hw,
+ &gxbb_mpll1.hw,
+ &gxbb_mpll2.hw,
+ },
.num_parents = 3,
},
};
@@ -1082,7 +1180,9 @@ static struct clk_regmap gxbb_cts_mclk_i958_div = {
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_mclk_i958_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1096,7 +1196,9 @@ static struct clk_regmap gxbb_cts_mclk_i958 = {
.hw.init = &(struct clk_init_data){
.name = "cts_mclk_i958",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_mclk_i958_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_mclk_i958_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1111,7 +1213,10 @@ static struct clk_regmap gxbb_cts_i958 = {
.hw.init = &(struct clk_init_data){
.name = "cts_i958",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_amclk.hw,
+ &gxbb_cts_mclk_i958.hw
+ },
.num_parents = 2,
/*
*The parent is specific to origin of the audio data. Let the
@@ -1121,6 +1226,33 @@ static struct clk_regmap gxbb_cts_i958 = {
},
};
+static const struct clk_parent_data gxbb_32k_clk_parent_data[] = {
+ { .fw_name = "xtal", },
+ /*
+ * FIXME: This clock is provided by the ao clock controller but the
+ * clock is not yet part of the binding of this controller, so string
+ * name must be use to set this parent.
+ */
+ { .name = "cts_slow_oscin", .index = -1 },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
+};
+
+static struct clk_regmap gxbb_32k_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_32K_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 16,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "32k_clk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = gxbb_32k_clk_parent_data,
+ .num_parents = 4,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
static struct clk_regmap gxbb_32k_clk_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_32K_CLK_CNTL,
@@ -1130,7 +1262,9 @@ static struct clk_regmap gxbb_32k_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "32k_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "32k_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_32k_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
},
@@ -1144,34 +1278,20 @@ static struct clk_regmap gxbb_32k_clk = {
.hw.init = &(struct clk_init_data){
.name = "32k_clk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "32k_clk_div" },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- },
-};
-
-static const char * const gxbb_32k_clk_parent_names[] = {
- IN_PREFIX "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
-};
-
-static struct clk_regmap gxbb_32k_clk_sel = {
- .data = &(struct clk_regmap_mux_data){
- .offset = HHI_32K_CLK_CNTL,
- .mask = 0x3,
- .shift = 16,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_32k_clk_div.hw
},
- .hw.init = &(struct clk_init_data){
- .name = "32k_clk_sel",
- .ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_32k_clk_parent_names,
- .num_parents = 4,
+ .num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
-
+static const struct clk_parent_data gxbb_sd_emmc_clk0_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_fclk_div2.hw },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
+ { .hw = &gxbb_fclk_div7.hw },
/*
* Following these parent clocks, we should also have had mpll2, mpll3
* and gp0_pll but these clocks are too precious to be used here. All
@@ -1190,8 +1310,8 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+ .parent_data = gxbb_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1206,7 +1326,9 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_a_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1220,7 +1342,9 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_a_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_a_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1236,8 +1360,8 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+ .parent_data = gxbb_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1252,7 +1376,9 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_b_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1266,7 +1392,9 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_b_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1282,8 +1410,8 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_sd_emmc_clk0_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+ .parent_data = gxbb_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1298,7 +1426,9 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_c_clk0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1312,7 +1442,9 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_sd_emmc_c_clk0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1320,8 +1452,11 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0 = {
/* VPU Clock */
-static const char * const gxbb_vpu_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+static const struct clk_hw *gxbb_vpu_parent_hws[] = {
+ &gxbb_fclk_div4.hw,
+ &gxbb_fclk_div3.hw,
+ &gxbb_fclk_div5.hw,
+ &gxbb_fclk_div7.hw,
};
static struct clk_regmap gxbb_vpu_0_sel = {
@@ -1337,8 +1472,8 @@ static struct clk_regmap gxbb_vpu_0_sel = {
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
- .parent_names = gxbb_vpu_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
+ .parent_hws = gxbb_vpu_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1352,7 +1487,7 @@ static struct clk_regmap gxbb_vpu_0_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1366,7 +1501,7 @@ static struct clk_regmap gxbb_vpu_0 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_0_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1385,8 +1520,8 @@ static struct clk_regmap gxbb_vpu_1_sel = {
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
- .parent_names = gxbb_vpu_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
+ .parent_hws = gxbb_vpu_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1400,7 +1535,7 @@ static struct clk_regmap gxbb_vpu_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1414,7 +1549,7 @@ static struct clk_regmap gxbb_vpu_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_1_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1433,7 +1568,10 @@ static struct clk_regmap gxbb_vpu = {
* bit 31 selects from 2 possible parents:
* vpu_0 or vpu_1
*/
- .parent_names = (const char *[]){ "vpu_0", "vpu_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vpu_0.hw,
+ &gxbb_vpu_1.hw
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -1441,8 +1579,11 @@ static struct clk_regmap gxbb_vpu = {
/* VAPB Clock */
-static const char * const gxbb_vapb_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+static const struct clk_hw *gxbb_vapb_parent_hws[] = {
+ &gxbb_fclk_div4.hw,
+ &gxbb_fclk_div3.hw,
+ &gxbb_fclk_div5.hw,
+ &gxbb_fclk_div7.hw,
};
static struct clk_regmap gxbb_vapb_0_sel = {
@@ -1458,8 +1599,8 @@ static struct clk_regmap gxbb_vapb_0_sel = {
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
- .parent_names = gxbb_vapb_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
+ .parent_hws = gxbb_vapb_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1473,7 +1614,9 @@ static struct clk_regmap gxbb_vapb_0_div = {
.hw.init = &(struct clk_init_data){
.name = "vapb_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vapb_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vapb_0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1487,7 +1630,9 @@ static struct clk_regmap gxbb_vapb_0 = {
.hw.init = &(struct clk_init_data) {
.name = "vapb_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vapb_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1506,8 +1651,8 @@ static struct clk_regmap gxbb_vapb_1_sel = {
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
- .parent_names = gxbb_vapb_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
+ .parent_hws = gxbb_vapb_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
@@ -1521,7 +1666,9 @@ static struct clk_regmap gxbb_vapb_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vapb_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vapb_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vapb_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1535,7 +1682,9 @@ static struct clk_regmap gxbb_vapb_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vapb_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vapb_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1554,7 +1703,10 @@ static struct clk_regmap gxbb_vapb_sel = {
* bit 31 selects from 2 possible parents:
* vapb_0 or vapb_1
*/
- .parent_names = (const char *[]){ "vapb_0", "vapb_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vapb_0.hw,
+ &gxbb_vapb_1.hw
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -1568,7 +1720,7 @@ static struct clk_regmap gxbb_vapb = {
.hw.init = &(struct clk_init_data) {
.name = "vapb",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vapb_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vapb_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1592,13 +1744,33 @@ static struct clk_regmap gxbb_vid_pll_div = {
.hw.init = &(struct clk_init_data) {
.name = "vid_pll_div",
.ops = &meson_vid_pll_div_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll" },
+ .parent_data = &(const struct clk_parent_data) {
+ /*
+ * Note:
+ * GXL and GXBB have different hdmi_plls (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so vid_pll_div picks up the
+ * appropriate one.
+ */
+ .name = "hdmi_pll",
+ .index = -1,
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
-static const char * const gxbb_vid_pll_parent_names[] = { "vid_pll_div", "hdmi_pll" };
+static const struct clk_parent_data gxbb_vid_pll_parent_data[] = {
+ { .hw = &gxbb_vid_pll_div.hw },
+ /*
+ * Note:
+ * GXL and GXBB have different hdmi_plls (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so vid_pll_div picks up the
+ * appropriate one.
+ */
+ { .name = "hdmi_pll", .index = -1 },
+};
static struct clk_regmap gxbb_vid_pll_sel = {
.data = &(struct clk_regmap_mux_data){
@@ -1613,8 +1785,8 @@ static struct clk_regmap gxbb_vid_pll_sel = {
* bit 18 selects from 2 possible parents:
* vid_pll_div or hdmi_pll
*/
- .parent_names = gxbb_vid_pll_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_names),
+ .parent_data = gxbb_vid_pll_parent_data,
+ .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_data),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -1627,15 +1799,22 @@ static struct clk_regmap gxbb_vid_pll = {
.hw.init = &(struct clk_init_data) {
.name = "vid_pll",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vid_pll_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vid_pll_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-static const char * const gxbb_vclk_parent_names[] = {
- "vid_pll", "fclk_div4", "fclk_div3", "fclk_div5", "vid_pll",
- "fclk_div7", "mpll1",
+static const struct clk_hw *gxbb_vclk_parent_hws[] = {
+ &gxbb_vid_pll.hw,
+ &gxbb_fclk_div4.hw,
+ &gxbb_fclk_div3.hw,
+ &gxbb_fclk_div5.hw,
+ &gxbb_vid_pll.hw,
+ &gxbb_fclk_div7.hw,
+ &gxbb_mpll1.hw,
};
static struct clk_regmap gxbb_vclk_sel = {
@@ -1652,8 +1831,8 @@ static struct clk_regmap gxbb_vclk_sel = {
* vid_pll, fclk_div4, fclk_div3, fclk_div5,
* vid_pll, fclk_div7, mp1
*/
- .parent_names = gxbb_vclk_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
+ .parent_hws = gxbb_vclk_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -1672,8 +1851,8 @@ static struct clk_regmap gxbb_vclk2_sel = {
* vid_pll, fclk_div4, fclk_div3, fclk_div5,
* vid_pll, fclk_div7, mp1
*/
- .parent_names = gxbb_vclk_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
+ .parent_hws = gxbb_vclk_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -1686,7 +1865,7 @@ static struct clk_regmap gxbb_vclk_input = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_input",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1700,7 +1879,7 @@ static struct clk_regmap gxbb_vclk2_input = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_input",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1715,7 +1894,9 @@ static struct clk_regmap gxbb_vclk_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vclk_input" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk_input.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -1730,7 +1911,9 @@ static struct clk_regmap gxbb_vclk2_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vclk2_input" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk2_input.hw
+ },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -1744,7 +1927,7 @@ static struct clk_regmap gxbb_vclk = {
.hw.init = &(struct clk_init_data) {
.name = "vclk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1758,7 +1941,7 @@ static struct clk_regmap gxbb_vclk2 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1772,7 +1955,7 @@ static struct clk_regmap gxbb_vclk_div1 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1786,7 +1969,7 @@ static struct clk_regmap gxbb_vclk_div2_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div2_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1800,7 +1983,7 @@ static struct clk_regmap gxbb_vclk_div4_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div4_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1814,7 +1997,7 @@ static struct clk_regmap gxbb_vclk_div6_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div6_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1828,7 +2011,7 @@ static struct clk_regmap gxbb_vclk_div12_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk_div12_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1842,7 +2025,7 @@ static struct clk_regmap gxbb_vclk2_div1 = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1856,7 +2039,7 @@ static struct clk_regmap gxbb_vclk2_div2_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div2_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1870,7 +2053,7 @@ static struct clk_regmap gxbb_vclk2_div4_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div4_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1884,7 +2067,7 @@ static struct clk_regmap gxbb_vclk2_div6_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div6_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1898,7 +2081,7 @@ static struct clk_regmap gxbb_vclk2_div12_en = {
.hw.init = &(struct clk_init_data) {
.name = "vclk2_div12_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vclk2" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -1910,7 +2093,9 @@ static struct clk_fixed_factor gxbb_vclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div2_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk_div2_en.hw
+ },
.num_parents = 1,
},
};
@@ -1921,7 +2106,9 @@ static struct clk_fixed_factor gxbb_vclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div4_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk_div4_en.hw
+ },
.num_parents = 1,
},
};
@@ -1932,7 +2119,9 @@ static struct clk_fixed_factor gxbb_vclk_div6 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div6_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk_div6_en.hw
+ },
.num_parents = 1,
},
};
@@ -1943,7 +2132,9 @@ static struct clk_fixed_factor gxbb_vclk_div12 = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_div12_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk_div12_en.hw
+ },
.num_parents = 1,
},
};
@@ -1954,7 +2145,9 @@ static struct clk_fixed_factor gxbb_vclk2_div2 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div2_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk2_div2_en.hw
+ },
.num_parents = 1,
},
};
@@ -1965,7 +2158,9 @@ static struct clk_fixed_factor gxbb_vclk2_div4 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div4_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk2_div4_en.hw
+ },
.num_parents = 1,
},
};
@@ -1976,7 +2171,9 @@ static struct clk_fixed_factor gxbb_vclk2_div6 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div6_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk2_div6_en.hw
+ },
.num_parents = 1,
},
};
@@ -1987,16 +2184,25 @@ static struct clk_fixed_factor gxbb_vclk2_div12 = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_div12_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vclk2_div12_en.hw
+ },
.num_parents = 1,
},
};
static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
-static const char * const gxbb_cts_parent_names[] = {
- "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
- "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
- "vclk2_div6", "vclk2_div12"
+static const struct clk_hw *gxbb_cts_parent_hws[] = {
+ &gxbb_vclk_div1.hw,
+ &gxbb_vclk_div2.hw,
+ &gxbb_vclk_div4.hw,
+ &gxbb_vclk_div6.hw,
+ &gxbb_vclk_div12.hw,
+ &gxbb_vclk2_div1.hw,
+ &gxbb_vclk2_div2.hw,
+ &gxbb_vclk2_div4.hw,
+ &gxbb_vclk2_div6.hw,
+ &gxbb_vclk2_div12.hw,
};
static struct clk_regmap gxbb_cts_enci_sel = {
@@ -2009,8 +2215,8 @@ static struct clk_regmap gxbb_cts_enci_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_enci_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_cts_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+ .parent_hws = gxbb_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2025,8 +2231,8 @@ static struct clk_regmap gxbb_cts_encp_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_encp_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_cts_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+ .parent_hws = gxbb_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2041,18 +2247,25 @@ static struct clk_regmap gxbb_cts_vdac_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_vdac_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_cts_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+ .parent_hws = gxbb_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
/* TOFIX: add support for cts_tcon */
static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
-static const char * const gxbb_cts_hdmi_tx_parent_names[] = {
- "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
- "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
- "vclk2_div6", "vclk2_div12"
+static const struct clk_hw *gxbb_cts_hdmi_tx_parent_hws[] = {
+ &gxbb_vclk_div1.hw,
+ &gxbb_vclk_div2.hw,
+ &gxbb_vclk_div4.hw,
+ &gxbb_vclk_div6.hw,
+ &gxbb_vclk_div12.hw,
+ &gxbb_vclk2_div1.hw,
+ &gxbb_vclk2_div2.hw,
+ &gxbb_vclk2_div4.hw,
+ &gxbb_vclk2_div6.hw,
+ &gxbb_vclk2_div12.hw,
};
static struct clk_regmap gxbb_hdmi_tx_sel = {
@@ -2071,8 +2284,8 @@ static struct clk_regmap gxbb_hdmi_tx_sel = {
* vclk2_div1, vclk2_div2, vclk2_div4, vclk2_div6, vclk2_div12,
* cts_tcon
*/
- .parent_names = gxbb_cts_hdmi_tx_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_names),
+ .parent_hws = gxbb_cts_hdmi_tx_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_hws),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2085,7 +2298,9 @@ static struct clk_regmap gxbb_cts_enci = {
.hw.init = &(struct clk_init_data) {
.name = "cts_enci",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_enci_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_enci_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2099,7 +2314,9 @@ static struct clk_regmap gxbb_cts_encp = {
.hw.init = &(struct clk_init_data) {
.name = "cts_encp",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_encp_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_encp_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2113,7 +2330,9 @@ static struct clk_regmap gxbb_cts_vdac = {
.hw.init = &(struct clk_init_data) {
.name = "cts_vdac",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_vdac_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_cts_vdac_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2127,7 +2346,9 @@ static struct clk_regmap gxbb_hdmi_tx = {
.hw.init = &(struct clk_init_data) {
.name = "hdmi_tx",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "hdmi_tx_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_hdmi_tx_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2135,8 +2356,11 @@ static struct clk_regmap gxbb_hdmi_tx = {
/* HDMI Clocks */
-static const char * const gxbb_hdmi_parent_names[] = {
- IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
+static const struct clk_parent_data gxbb_hdmi_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_fclk_div4.hw },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
};
static struct clk_regmap gxbb_hdmi_sel = {
@@ -2149,8 +2373,8 @@ static struct clk_regmap gxbb_hdmi_sel = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_hdmi_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_names),
+ .parent_data = gxbb_hdmi_parent_data,
+ .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_data),
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
},
};
@@ -2164,7 +2388,7 @@ static struct clk_regmap gxbb_hdmi_div = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "hdmi_sel" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_hdmi_sel.hw },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
@@ -2178,7 +2402,7 @@ static struct clk_regmap gxbb_hdmi = {
.hw.init = &(struct clk_init_data) {
.name = "hdmi",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "hdmi_div" },
+ .parent_hws = (const struct clk_hw *[]) { &gxbb_hdmi_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
@@ -2186,8 +2410,11 @@ static struct clk_regmap gxbb_hdmi = {
/* VDEC clocks */
-static const char * const gxbb_vdec_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+static const struct clk_hw *gxbb_vdec_parent_hws[] = {
+ &gxbb_fclk_div4.hw,
+ &gxbb_fclk_div3.hw,
+ &gxbb_fclk_div5.hw,
+ &gxbb_fclk_div7.hw,
};
static struct clk_regmap gxbb_vdec_1_sel = {
@@ -2200,8 +2427,8 @@ static struct clk_regmap gxbb_vdec_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_vdec_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names),
+ .parent_hws = gxbb_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2216,7 +2443,9 @@ static struct clk_regmap gxbb_vdec_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vdec_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2230,7 +2459,9 @@ static struct clk_regmap gxbb_vdec_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vdec_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2246,8 +2477,8 @@ static struct clk_regmap gxbb_vdec_hevc_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = gxbb_vdec_parent_names,
- .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names),
+ .parent_hws = gxbb_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2262,7 +2493,9 @@ static struct clk_regmap gxbb_vdec_hevc_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_hevc_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vdec_hevc_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2276,7 +2509,9 @@ static struct clk_regmap gxbb_vdec_hevc = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_hevc",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_hevc_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_vdec_hevc_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2284,9 +2519,18 @@ static struct clk_regmap gxbb_vdec_hevc = {
static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
9, 10, 11, 13, 14, };
-static const char * const gen_clk_parent_names[] = {
- IN_PREFIX "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2",
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
+static const struct clk_parent_data gen_clk_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &gxbb_vdec_1.hw },
+ { .hw = &gxbb_vdec_hevc.hw },
+ { .hw = &gxbb_mpll0.hw },
+ { .hw = &gxbb_mpll1.hw },
+ { .hw = &gxbb_mpll2.hw },
+ { .hw = &gxbb_fclk_div4.hw },
+ { .hw = &gxbb_fclk_div3.hw },
+ { .hw = &gxbb_fclk_div5.hw },
+ { .hw = &gxbb_fclk_div7.hw },
+ { .hw = &gxbb_gp0_pll.hw },
};
static struct clk_regmap gxbb_gen_clk_sel = {
@@ -2305,8 +2549,8 @@ static struct clk_regmap gxbb_gen_clk_sel = {
* vid_pll, vid2_pll (hevc), mpll0, mpll1, mpll2, fdiv4,
* fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
*/
- .parent_names = gen_clk_parent_names,
- .num_parents = ARRAY_SIZE(gen_clk_parent_names),
+ .parent_data = gen_clk_parent_data,
+ .num_parents = ARRAY_SIZE(gen_clk_parent_data),
},
};
@@ -2319,7 +2563,9 @@ static struct clk_regmap gxbb_gen_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gen_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_gen_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2333,12 +2579,17 @@ static struct clk_regmap gxbb_gen_clk = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "gen_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &gxbb_gen_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &gxbb_clk81.hw)
+
/* Everything Else (EE) domain gates */
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c
index b67951909e04..bf8bea675d24 100644
--- a/drivers/clk/meson/meson-aoclk.c
+++ b/drivers/clk/meson/meson-aoclk.c
@@ -17,8 +17,6 @@
#include <linux/slab.h>
#include "meson-aoclk.h"
-#include "clk-input.h"
-
static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
@@ -33,37 +31,6 @@ static const struct reset_control_ops meson_aoclk_reset_ops = {
.reset = meson_aoclk_do_reset,
};
-static int meson_aoclkc_register_inputs(struct device *dev,
- struct meson_aoclk_data *data)
-{
- struct clk_hw *hw;
- char *str;
- int i;
-
- for (i = 0; i < data->num_inputs; i++) {
- const struct meson_aoclk_input *in = &data->inputs[i];
-
- str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix,
- in->name);
- if (!str)
- return -ENOMEM;
-
- hw = meson_clk_hw_register_input(dev, in->name, str, 0);
- kfree(str);
-
- if (IS_ERR(hw)) {
- if (!in->required && PTR_ERR(hw) == -ENOENT)
- continue;
- else if (PTR_ERR(hw) != -EPROBE_DEFER)
- dev_err(dev, "failed to register input %s\n",
- in->name);
- return PTR_ERR(hw);
- }
- }
-
- return 0;
-}
-
int meson_aoclkc_probe(struct platform_device *pdev)
{
struct meson_aoclk_reset_controller *rstc;
@@ -86,10 +53,6 @@ int meson_aoclkc_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
- ret = meson_aoclkc_register_inputs(dev, data);
- if (ret)
- return ret;
-
/* Reset Controller */
rstc->data = data;
rstc->regmap = regmap;
diff --git a/drivers/clk/meson/meson-aoclk.h b/drivers/clk/meson/meson-aoclk.h
index 999cde3868f7..605b43855a69 100644
--- a/drivers/clk/meson/meson-aoclk.h
+++ b/drivers/clk/meson/meson-aoclk.h
@@ -18,20 +18,12 @@
#include "clk-regmap.h"
-struct meson_aoclk_input {
- const char *name;
- bool required;
-};
-
struct meson_aoclk_data {
const unsigned int reset_reg;
const int num_reset;
const unsigned int *reset;
const int num_clks;
struct clk_regmap **clks;
- const int num_inputs;
- const struct meson_aoclk_input *inputs;
- const char *input_prefix;
const struct clk_hw_onecell_data *hw_data;
};
diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c
index 6ba2094be257..a7cb1e7aedc4 100644
--- a/drivers/clk/meson/meson-eeclk.c
+++ b/drivers/clk/meson/meson-eeclk.c
@@ -10,7 +10,6 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
-#include "clk-input.h"
#include "clk-regmap.h"
#include "meson-eeclk.h"
@@ -18,7 +17,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
{
const struct meson_eeclkc_data *data;
struct device *dev = &pdev->dev;
- struct clk_hw *input;
struct regmap *map;
int ret, i;
@@ -37,14 +35,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
if (data->init_count)
regmap_multi_reg_write(map, data->init_regs, data->init_count);
- input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0);
- if (IS_ERR(input)) {
- ret = PTR_ERR(input);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to get input clock");
- return ret;
- }
-
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < data->regmap_clk_num; i++)
data->regmap_clks[i]->map = map;
diff --git a/drivers/clk/meson/meson-eeclk.h b/drivers/clk/meson/meson-eeclk.h
index 9ab5d6fa7ccb..77316207bde1 100644
--- a/drivers/clk/meson/meson-eeclk.h
+++ b/drivers/clk/meson/meson-eeclk.h
@@ -10,8 +10,6 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
-#define IN_PREFIX "ee-in-"
-
struct platform_device;
struct meson_eeclkc_data {
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 537219fa573e..67e6691e080c 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -97,7 +97,9 @@ static struct clk_regmap meson8b_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw
+ },
.num_parents = 1,
},
};
@@ -112,7 +114,9 @@ static struct clk_regmap meson8b_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll_dco.hw
+ },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@@ -158,7 +162,9 @@ static struct clk_regmap meson8b_hdmi_pll_dco = {
/* sometimes also called "HPLL" or "HPLL PLL" */
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw
+ },
.num_parents = 1,
},
};
@@ -173,7 +179,9 @@ static struct clk_regmap meson8b_hdmi_pll_lvds_out = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_lvds_out",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -189,7 +197,9 @@ static struct clk_regmap meson8b_hdmi_pll_hdmi_out = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_hdmi_out",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -227,7 +237,9 @@ static struct clk_regmap meson8b_sys_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw
+ },
.num_parents = 1,
},
};
@@ -242,7 +254,9 @@ static struct clk_regmap meson8b_sys_pll = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "sys_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_sys_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -254,7 +268,9 @@ static struct clk_fixed_factor meson8b_fclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -267,7 +283,9 @@ static struct clk_regmap meson8b_fclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div2_div.hw
+ },
.num_parents = 1,
/*
* FIXME: Ethernet with a RGMII PHYs is not working if
@@ -285,7 +303,9 @@ static struct clk_fixed_factor meson8b_fclk_div3_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -298,7 +318,9 @@ static struct clk_regmap meson8b_fclk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div3_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div3_div.hw
+ },
.num_parents = 1,
},
};
@@ -309,7 +331,9 @@ static struct clk_fixed_factor meson8b_fclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -322,7 +346,9 @@ static struct clk_regmap meson8b_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div4_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div4_div.hw
+ },
.num_parents = 1,
},
};
@@ -333,7 +359,9 @@ static struct clk_fixed_factor meson8b_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -346,7 +374,9 @@ static struct clk_regmap meson8b_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div5_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div5_div.hw
+ },
.num_parents = 1,
},
};
@@ -357,7 +387,9 @@ static struct clk_fixed_factor meson8b_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -370,7 +402,9 @@ static struct clk_regmap meson8b_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "fclk_div7_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div7_div.hw
+ },
.num_parents = 1,
},
};
@@ -384,7 +418,9 @@ static struct clk_regmap meson8b_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fixed_pll.hw
+ },
.num_parents = 1,
},
};
@@ -416,7 +452,9 @@ static struct clk_regmap meson8b_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -429,7 +467,9 @@ static struct clk_regmap meson8b_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -457,7 +497,9 @@ static struct clk_regmap meson8b_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -470,7 +512,9 @@ static struct clk_regmap meson8b_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -498,7 +542,9 @@ static struct clk_regmap meson8b_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "mpll_prediv" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll_prediv.hw
+ },
.num_parents = 1,
},
};
@@ -511,7 +557,9 @@ static struct clk_regmap meson8b_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpll2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpll2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -533,8 +581,11 @@ static struct clk_regmap meson8b_mpeg_clk_sel = {
* xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
* fclk_div4, fclk_div3, fclk_div5
*/
- .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
- "fclk_div5" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div5.hw,
+ },
.num_parents = 3,
},
};
@@ -548,7 +599,9 @@ static struct clk_regmap meson8b_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "mpeg_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpeg_clk_sel.hw
+ },
.num_parents = 1,
},
};
@@ -561,7 +614,9 @@ static struct clk_regmap meson8b_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mpeg_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mpeg_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@@ -576,7 +631,10 @@ static struct clk_regmap meson8b_cpu_in_sel = {
.hw.init = &(struct clk_init_data){
.name = "cpu_in_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "xtal", "sys_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw,
+ &meson8b_sys_pll.hw,
+ },
.num_parents = 2,
.flags = (CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT),
@@ -589,7 +647,9 @@ static struct clk_fixed_factor meson8b_cpu_in_div2 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_in_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -601,7 +661,9 @@ static struct clk_fixed_factor meson8b_cpu_in_div3 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_in_div3",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -630,7 +692,9 @@ static struct clk_regmap meson8b_cpu_scale_div = {
.hw.init = &(struct clk_init_data){
.name = "cpu_scale_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "cpu_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -649,13 +713,15 @@ static struct clk_regmap meson8b_cpu_scale_out_sel = {
.ops = &clk_regmap_mux_ops,
/*
* NOTE: We are skipping the parent with value 0x2 (which is
- * "cpu_in_div3") because it results in a duty cycle of 33%
- * which makes the system unstable and can result in a lockup
- * of the whole system.
+ * meson8b_cpu_in_div3) because it results in a duty cycle of
+ * 33% which makes the system unstable and can result in a
+ * lockup of the whole system.
*/
- .parent_names = (const char *[]) { "cpu_in_sel",
- "cpu_in_div2",
- "cpu_scale_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_in_sel.hw,
+ &meson8b_cpu_in_div2.hw,
+ &meson8b_cpu_scale_div.hw,
+ },
.num_parents = 3,
.flags = CLK_SET_RATE_PARENT,
},
@@ -670,8 +736,10 @@ static struct clk_regmap meson8b_cpu_clk = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "xtal",
- "cpu_scale_out_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw,
+ &meson8b_cpu_scale_out_sel.hw,
+ },
.num_parents = 2,
.flags = (CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT |
@@ -690,8 +758,13 @@ static struct clk_regmap meson8b_nand_clk_sel = {
.name = "nand_clk_sel",
.ops = &clk_regmap_mux_ops,
/* FIXME all other parents are unknown: */
- .parent_names = (const char *[]){ "fclk_div4", "fclk_div3",
- "fclk_div5", "fclk_div7", "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
+ &meson8b_fclk_div7.hw,
+ &meson8b_xtal.hw,
+ },
.num_parents = 5,
.flags = CLK_SET_RATE_PARENT,
},
@@ -707,7 +780,9 @@ static struct clk_regmap meson8b_nand_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "nand_clk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "nand_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_nand_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -721,7 +796,9 @@ static struct clk_regmap meson8b_nand_clk_gate = {
.hw.init = &(struct clk_init_data){
.name = "nand_clk_gate",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "nand_clk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_nand_clk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -733,7 +810,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -744,7 +823,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div3",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -755,7 +836,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -766,7 +849,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div5",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -777,7 +862,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div6 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -788,7 +875,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div7",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -799,7 +888,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div8 = {
.hw.init = &(struct clk_init_data){
.name = "cpu_clk_div8",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "cpu_clk" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk.hw
+ },
.num_parents = 1,
},
};
@@ -815,13 +906,15 @@ static struct clk_regmap meson8b_apb_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "apb_clk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cpu_clk_div2",
- "cpu_clk_div3",
- "cpu_clk_div4",
- "cpu_clk_div5",
- "cpu_clk_div6",
- "cpu_clk_div7",
- "cpu_clk_div8", },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk_div2.hw,
+ &meson8b_cpu_clk_div3.hw,
+ &meson8b_cpu_clk_div4.hw,
+ &meson8b_cpu_clk_div5.hw,
+ &meson8b_cpu_clk_div6.hw,
+ &meson8b_cpu_clk_div7.hw,
+ &meson8b_cpu_clk_div8.hw,
+ },
.num_parents = 7,
},
};
@@ -835,7 +928,9 @@ static struct clk_regmap meson8b_apb_clk_gate = {
.hw.init = &(struct clk_init_data){
.name = "apb_clk_dis",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "apb_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_apb_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -850,13 +945,15 @@ static struct clk_regmap meson8b_periph_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "periph_clk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cpu_clk_div2",
- "cpu_clk_div3",
- "cpu_clk_div4",
- "cpu_clk_div5",
- "cpu_clk_div6",
- "cpu_clk_div7",
- "cpu_clk_div8", },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk_div2.hw,
+ &meson8b_cpu_clk_div3.hw,
+ &meson8b_cpu_clk_div4.hw,
+ &meson8b_cpu_clk_div5.hw,
+ &meson8b_cpu_clk_div6.hw,
+ &meson8b_cpu_clk_div7.hw,
+ &meson8b_cpu_clk_div8.hw,
+ },
.num_parents = 7,
},
};
@@ -870,7 +967,9 @@ static struct clk_regmap meson8b_periph_clk_gate = {
.hw.init = &(struct clk_init_data){
.name = "periph_clk_dis",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "periph_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_periph_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -887,13 +986,15 @@ static struct clk_regmap meson8b_axi_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "axi_clk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cpu_clk_div2",
- "cpu_clk_div3",
- "cpu_clk_div4",
- "cpu_clk_div5",
- "cpu_clk_div6",
- "cpu_clk_div7",
- "cpu_clk_div8", },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk_div2.hw,
+ &meson8b_cpu_clk_div3.hw,
+ &meson8b_cpu_clk_div4.hw,
+ &meson8b_cpu_clk_div5.hw,
+ &meson8b_cpu_clk_div6.hw,
+ &meson8b_cpu_clk_div7.hw,
+ &meson8b_cpu_clk_div8.hw,
+ },
.num_parents = 7,
},
};
@@ -907,7 +1008,9 @@ static struct clk_regmap meson8b_axi_clk_gate = {
.hw.init = &(struct clk_init_data){
.name = "axi_clk_dis",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "axi_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_axi_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -922,13 +1025,15 @@ static struct clk_regmap meson8b_l2_dram_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "l2_dram_clk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cpu_clk_div2",
- "cpu_clk_div3",
- "cpu_clk_div4",
- "cpu_clk_div5",
- "cpu_clk_div6",
- "cpu_clk_div7",
- "cpu_clk_div8", },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cpu_clk_div2.hw,
+ &meson8b_cpu_clk_div3.hw,
+ &meson8b_cpu_clk_div4.hw,
+ &meson8b_cpu_clk_div5.hw,
+ &meson8b_cpu_clk_div6.hw,
+ &meson8b_cpu_clk_div7.hw,
+ &meson8b_cpu_clk_div8.hw,
+ },
.num_parents = 7,
},
};
@@ -942,7 +1047,9 @@ static struct clk_regmap meson8b_l2_dram_clk_gate = {
.hw.init = &(struct clk_init_data){
.name = "l2_dram_clk_dis",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "l2_dram_clk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_l2_dram_clk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -963,7 +1070,9 @@ static struct clk_regmap meson8b_vid_pll_in_sel = {
* Meson8b: hdmi_pll_dco
* Meson8m2: vid2_pll
*/
- .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -977,7 +1086,9 @@ static struct clk_regmap meson8b_vid_pll_in_en = {
.hw.init = &(struct clk_init_data){
.name = "vid_pll_in_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vid_pll_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vid_pll_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -992,7 +1103,9 @@ static struct clk_regmap meson8b_vid_pll_pre_div = {
.hw.init = &(struct clk_init_data){
.name = "vid_pll_pre_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "vid_pll_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vid_pll_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1007,7 +1120,9 @@ static struct clk_regmap meson8b_vid_pll_post_div = {
.hw.init = &(struct clk_init_data){
.name = "vid_pll_post_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "vid_pll_pre_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vid_pll_pre_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1023,8 +1138,10 @@ static struct clk_regmap meson8b_vid_pll = {
.name = "vid_pll",
.ops = &clk_regmap_mux_ro_ops,
/* TODO: parent 0x2 is vid_pll_pre_div_mult7_div2 */
- .parent_names = (const char *[]){ "vid_pll_pre_div",
- "vid_pll_post_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vid_pll_pre_div.hw,
+ &meson8b_vid_pll_post_div.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1039,15 +1156,22 @@ static struct clk_regmap meson8b_vid_pll_final_div = {
.hw.init = &(struct clk_init_data){
.name = "vid_pll_final_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "vid_pll" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vid_pll.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const meson8b_vclk_mux_parents[] = {
- "vid_pll_final_div", "fclk_div4", "fclk_div3", "fclk_div5",
- "vid_pll_final_div", "fclk_div7", "mpll1"
+static const struct clk_hw *meson8b_vclk_mux_parent_hws[] = {
+ &meson8b_vid_pll_final_div.hw,
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
+ &meson8b_vid_pll_final_div.hw,
+ &meson8b_fclk_div7.hw,
+ &meson8b_mpll1.hw,
};
static struct clk_regmap meson8b_vclk_in_sel = {
@@ -1059,8 +1183,8 @@ static struct clk_regmap meson8b_vclk_in_sel = {
.hw.init = &(struct clk_init_data){
.name = "vclk_in_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents),
+ .parent_hws = meson8b_vclk_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1073,7 +1197,9 @@ static struct clk_regmap meson8b_vclk_in_en = {
.hw.init = &(struct clk_init_data){
.name = "vclk_in_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1087,7 +1213,9 @@ static struct clk_regmap meson8b_vclk_div1_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div1_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1099,7 +1227,9 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1113,7 +1243,9 @@ static struct clk_regmap meson8b_vclk_div2_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div2_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_div2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_div2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1125,7 +1257,9 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1139,7 +1273,9 @@ static struct clk_regmap meson8b_vclk_div4_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div4_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_div4" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_div4_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1151,7 +1287,9 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1165,7 +1303,9 @@ static struct clk_regmap meson8b_vclk_div6_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div6_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_div6" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_div6_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1177,7 +1317,9 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1191,7 +1333,9 @@ static struct clk_regmap meson8b_vclk_div12_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk_div12_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk_div12" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk_div12_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1206,8 +1350,8 @@ static struct clk_regmap meson8b_vclk2_in_sel = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_in_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents),
+ .parent_hws = meson8b_vclk_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1220,7 +1364,9 @@ static struct clk_regmap meson8b_vclk2_clk_in_en = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_in_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_in_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_in_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1234,7 +1380,9 @@ static struct clk_regmap meson8b_vclk2_div1_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div1_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_clk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1246,7 +1394,9 @@ static struct clk_fixed_factor meson8b_vclk2_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_clk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1260,7 +1410,9 @@ static struct clk_regmap meson8b_vclk2_div2_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_div2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_div2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1272,7 +1424,9 @@ static struct clk_fixed_factor meson8b_vclk2_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_clk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1286,7 +1440,9 @@ static struct clk_regmap meson8b_vclk2_div4_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_div4" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_div4_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1298,7 +1454,9 @@ static struct clk_fixed_factor meson8b_vclk2_div6_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_clk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1312,7 +1470,9 @@ static struct clk_regmap meson8b_vclk2_div6_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_div6" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_div6_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1324,7 +1484,9 @@ static struct clk_fixed_factor meson8b_vclk2_div12_div = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12",
.ops = &clk_fixed_factor_ops,
- .parent_names = (const char *[]){ "vclk2_in_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_clk_in_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
@@ -1338,15 +1500,20 @@ static struct clk_regmap meson8b_vclk2_div12_div_gate = {
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12_en",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "vclk2_div12" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vclk2_div12_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const meson8b_vclk_enc_mux_parents[] = {
- "vclk_div1_en", "vclk_div2_en", "vclk_div4_en", "vclk_div6_en",
- "vclk_div12_en",
+static const struct clk_hw *meson8b_vclk_enc_mux_parent_hws[] = {
+ &meson8b_vclk_div1_gate.hw,
+ &meson8b_vclk_div2_div_gate.hw,
+ &meson8b_vclk_div4_div_gate.hw,
+ &meson8b_vclk_div6_div_gate.hw,
+ &meson8b_vclk_div12_div_gate.hw,
};
static struct clk_regmap meson8b_cts_enct_sel = {
@@ -1358,8 +1525,8 @@ static struct clk_regmap meson8b_cts_enct_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_enct_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
+ .parent_hws = meson8b_vclk_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1372,7 +1539,9 @@ static struct clk_regmap meson8b_cts_enct = {
.hw.init = &(struct clk_init_data){
.name = "cts_enct",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cts_enct_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_enct_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1387,8 +1556,8 @@ static struct clk_regmap meson8b_cts_encp_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_encp_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
+ .parent_hws = meson8b_vclk_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1401,7 +1570,9 @@ static struct clk_regmap meson8b_cts_encp = {
.hw.init = &(struct clk_init_data){
.name = "cts_encp",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cts_encp_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_encp_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1416,8 +1587,8 @@ static struct clk_regmap meson8b_cts_enci_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_enci_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
+ .parent_hws = meson8b_vclk_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1430,7 +1601,9 @@ static struct clk_regmap meson8b_cts_enci = {
.hw.init = &(struct clk_init_data){
.name = "cts_enci",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cts_enci_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_enci_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1445,8 +1618,8 @@ static struct clk_regmap meson8b_hdmi_tx_pixel_sel = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_tx_pixel_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
+ .parent_hws = meson8b_vclk_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1459,15 +1632,20 @@ static struct clk_regmap meson8b_hdmi_tx_pixel = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_tx_pixel",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "hdmi_tx_pixel_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_tx_pixel_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const meson8b_vclk2_enc_mux_parents[] = {
- "vclk2_div1_en", "vclk2_div2_en", "vclk2_div4_en", "vclk2_div6_en",
- "vclk2_div12_en",
+static const struct clk_hw *meson8b_vclk2_enc_mux_parent_hws[] = {
+ &meson8b_vclk2_div1_gate.hw,
+ &meson8b_vclk2_div2_div_gate.hw,
+ &meson8b_vclk2_div4_div_gate.hw,
+ &meson8b_vclk2_div6_div_gate.hw,
+ &meson8b_vclk2_div12_div_gate.hw,
};
static struct clk_regmap meson8b_cts_encl_sel = {
@@ -1479,8 +1657,8 @@ static struct clk_regmap meson8b_cts_encl_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_encl_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk2_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents),
+ .parent_hws = meson8b_vclk2_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1493,7 +1671,9 @@ static struct clk_regmap meson8b_cts_encl = {
.hw.init = &(struct clk_init_data){
.name = "cts_encl",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cts_encl_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_encl_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1508,8 +1688,8 @@ static struct clk_regmap meson8b_cts_vdac0_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_vdac0_sel",
.ops = &clk_regmap_mux_ro_ops,
- .parent_names = meson8b_vclk2_enc_mux_parents,
- .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents),
+ .parent_hws = meson8b_vclk2_enc_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1522,7 +1702,9 @@ static struct clk_regmap meson8b_cts_vdac0 = {
.hw.init = &(struct clk_init_data){
.name = "cts_vdac0",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "cts_vdac0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_vdac0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1539,7 +1721,9 @@ static struct clk_regmap meson8b_hdmi_sys_sel = {
.name = "hdmi_sys_sel",
.ops = &clk_regmap_mux_ro_ops,
/* FIXME: all other parents are unknown */
- .parent_names = (const char *[]){ "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
@@ -1554,7 +1738,9 @@ static struct clk_regmap meson8b_hdmi_sys_div = {
.hw.init = &(struct clk_init_data){
.name = "hdmi_sys_div",
.ops = &clk_regmap_divider_ro_ops,
- .parent_names = (const char *[]){ "hdmi_sys_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_sys_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1568,7 +1754,9 @@ static struct clk_regmap meson8b_hdmi_sys = {
.hw.init = &(struct clk_init_data) {
.name = "hdmi_sys",
.ops = &clk_regmap_gate_ro_ops,
- .parent_names = (const char *[]){ "hdmi_sys_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_hdmi_sys_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1579,9 +1767,14 @@ static struct clk_regmap meson8b_hdmi_sys = {
* muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only
* has mali_0 and no glitch-free mux.
*/
-static const char * const meson8b_mali_0_1_parent_names[] = {
- "xtal", "mpll2", "mpll1", "fclk_div7", "fclk_div4", "fclk_div3",
- "fclk_div5"
+static const struct clk_hw *meson8b_mali_0_1_parent_hws[] = {
+ &meson8b_xtal.hw,
+ &meson8b_mpll2.hw,
+ &meson8b_mpll1.hw,
+ &meson8b_fclk_div7.hw,
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
};
static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 };
@@ -1596,8 +1789,8 @@ static struct clk_regmap meson8b_mali_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_mali_0_1_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
+ .parent_hws = meson8b_mali_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws),
/*
* Don't propagate rate changes up because the only changeable
* parents are mpll1 and mpll2 but we need those for audio and
@@ -1617,7 +1810,9 @@ static struct clk_regmap meson8b_mali_0_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_0_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mali_0_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1631,7 +1826,9 @@ static struct clk_regmap meson8b_mali_0 = {
.hw.init = &(struct clk_init_data){
.name = "mali_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mali_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1647,8 +1844,8 @@ static struct clk_regmap meson8b_mali_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_mali_0_1_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
+ .parent_hws = meson8b_mali_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws),
/*
* Don't propagate rate changes up because the only changeable
* parents are mpll1 and mpll2 but we need those for audio and
@@ -1668,7 +1865,9 @@ static struct clk_regmap meson8b_mali_1_div = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "mali_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mali_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1682,7 +1881,9 @@ static struct clk_regmap meson8b_mali_1 = {
.hw.init = &(struct clk_init_data){
.name = "mali_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "mali_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mali_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1697,7 +1898,10 @@ static struct clk_regmap meson8b_mali = {
.hw.init = &(struct clk_init_data){
.name = "mali",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "mali_0", "mali_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_mali_0.hw,
+ &meson8b_mali_1.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1740,7 +1944,9 @@ static struct clk_regmap meson8m2_gp_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp_pll_dco",
.ops = &meson_clk_pll_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_xtal.hw
+ },
.num_parents = 1,
},
};
@@ -1755,18 +1961,26 @@ static struct clk_regmap meson8m2_gp_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp_pll",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "gp_pll_dco" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8m2_gp_pll_dco.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static const char * const meson8b_vpu_0_1_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+static const struct clk_hw *meson8b_vpu_0_1_parent_hws[] = {
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
+ &meson8b_fclk_div7.hw,
};
-static const char * const mmeson8m2_vpu_0_1_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "gp_pll"
+static const struct clk_hw *mmeson8m2_vpu_0_1_parent_hws[] = {
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
+ &meson8m2_gp_pll.hw,
};
static struct clk_regmap meson8b_vpu_0_sel = {
@@ -1778,8 +1992,8 @@ static struct clk_regmap meson8b_vpu_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vpu_0_1_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_names),
+ .parent_hws = meson8b_vpu_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1793,8 +2007,8 @@ static struct clk_regmap meson8m2_vpu_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = mmeson8m2_vpu_0_1_parent_names,
- .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
+ .parent_hws = mmeson8m2_vpu_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1808,7 +2022,17 @@ static struct clk_regmap meson8b_vpu_0_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_0_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_0_sel" },
+ .parent_data = &(const struct clk_parent_data) {
+ /*
+ * Note:
+ * meson8b and meson8m2 have different vpu_0_sels (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so vpu_0_div picks up the
+ * appropriate one.
+ */
+ .name = "vpu_0_sel",
+ .index = -1,
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1822,7 +2046,9 @@ static struct clk_regmap meson8b_vpu_0 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_0",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_0_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vpu_0_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1837,8 +2063,8 @@ static struct clk_regmap meson8b_vpu_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vpu_0_1_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_names),
+ .parent_hws = meson8b_vpu_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1852,8 +2078,8 @@ static struct clk_regmap meson8m2_vpu_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = mmeson8m2_vpu_0_1_parent_names,
- .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
+ .parent_hws = mmeson8m2_vpu_0_1_parent_hws,
+ .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1867,7 +2093,17 @@ static struct clk_regmap meson8b_vpu_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vpu_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vpu_1_sel" },
+ .parent_data = &(const struct clk_parent_data) {
+ /*
+ * Note:
+ * meson8b and meson8m2 have different vpu_1_sels (with
+ * different struct clk_hw). We fallback to the global
+ * naming string mechanism so vpu_1_div picks up the
+ * appropriate one.
+ */
+ .name = "vpu_1_sel",
+ .index = -1,
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1881,7 +2117,9 @@ static struct clk_regmap meson8b_vpu_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vpu_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vpu_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vpu_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1896,14 +2134,22 @@ static struct clk_regmap meson8b_vpu = {
.hw.init = &(struct clk_init_data){
.name = "vpu",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "vpu_0", "vpu_1" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vpu_0.hw,
+ &meson8b_vpu_1.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
-static const char * const meson8b_vdec_parent_names[] = {
- "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll1"
+static const struct clk_hw *meson8b_vdec_parent_hws[] = {
+ &meson8b_fclk_div4.hw,
+ &meson8b_fclk_div3.hw,
+ &meson8b_fclk_div5.hw,
+ &meson8b_fclk_div7.hw,
+ &meson8b_mpll2.hw,
+ &meson8b_mpll1.hw,
};
static struct clk_regmap meson8b_vdec_1_sel = {
@@ -1916,8 +2162,8 @@ static struct clk_regmap meson8b_vdec_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vdec_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+ .parent_hws = meson8b_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1932,7 +2178,9 @@ static struct clk_regmap meson8b_vdec_1_1_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_1_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1946,7 +2194,9 @@ static struct clk_regmap meson8b_vdec_1_1 = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_1_1",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_1_1_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_1_1_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1962,7 +2212,9 @@ static struct clk_regmap meson8b_vdec_1_2_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1_2_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_1_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_1_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1976,7 +2228,9 @@ static struct clk_regmap meson8b_vdec_1_2 = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_1_2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_1_2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_1_2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1992,7 +2246,10 @@ static struct clk_regmap meson8b_vdec_1 = {
.hw.init = &(struct clk_init_data){
.name = "vdec_1",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "vdec_1_1", "vdec_1_2" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_1_1.hw,
+ &meson8b_vdec_1_2.hw,
+ },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2008,8 +2265,8 @@ static struct clk_regmap meson8b_vdec_hcodec_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hcodec_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vdec_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+ .parent_hws = meson8b_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2024,7 +2281,9 @@ static struct clk_regmap meson8b_vdec_hcodec_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hcodec_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_hcodec_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_hcodec_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2038,7 +2297,9 @@ static struct clk_regmap meson8b_vdec_hcodec = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_hcodec",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_hcodec_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_hcodec_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2054,8 +2315,8 @@ static struct clk_regmap meson8b_vdec_2_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_2_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vdec_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+ .parent_hws = meson8b_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2070,7 +2331,9 @@ static struct clk_regmap meson8b_vdec_2_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_2_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_2_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_2_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2084,7 +2347,9 @@ static struct clk_regmap meson8b_vdec_2 = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_2",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_2_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_2_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2100,8 +2365,8 @@ static struct clk_regmap meson8b_vdec_hevc_sel = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_vdec_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+ .parent_hws = meson8b_vdec_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2116,7 +2381,9 @@ static struct clk_regmap meson8b_vdec_hevc_div = {
.hw.init = &(struct clk_init_data){
.name = "vdec_hevc_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "vdec_hevc_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_hevc_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2130,7 +2397,9 @@ static struct clk_regmap meson8b_vdec_hevc_en = {
.hw.init = &(struct clk_init_data) {
.name = "vdec_hevc_en",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "vdec_hevc_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_hevc_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2147,15 +2416,19 @@ static struct clk_regmap meson8b_vdec_hevc = {
.name = "vdec_hevc",
.ops = &clk_regmap_mux_ops,
/* TODO: The second parent is currently unknown */
- .parent_names = (const char *[]){ "vdec_hevc_en" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_vdec_hevc_en.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
/* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */
-static const char * const meson8b_cts_amclk_parent_names[] = {
- "mpll0", "mpll1", "mpll2"
+static const struct clk_hw *meson8b_cts_amclk_parent_hws[] = {
+ &meson8b_mpll0.hw,
+ &meson8b_mpll1.hw,
+ &meson8b_mpll2.hw
};
static u32 meson8b_cts_amclk_mux_table[] = { 1, 2, 3 };
@@ -2171,8 +2444,8 @@ static struct clk_regmap meson8b_cts_amclk_sel = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_cts_amclk_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_cts_amclk_parent_names),
+ .parent_hws = meson8b_cts_amclk_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_cts_amclk_parent_hws),
},
};
@@ -2186,7 +2459,9 @@ static struct clk_regmap meson8b_cts_amclk_div = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "cts_amclk_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_amclk_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2200,15 +2475,19 @@ static struct clk_regmap meson8b_cts_amclk = {
.hw.init = &(struct clk_init_data){
.name = "cts_amclk",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_amclk_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_amclk_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
/* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */
-static const char * const meson8b_cts_mclk_i958_parent_names[] = {
- "mpll0", "mpll1", "mpll2"
+static const struct clk_hw *meson8b_cts_mclk_i958_parent_hws[] = {
+ &meson8b_mpll0.hw,
+ &meson8b_mpll1.hw,
+ &meson8b_mpll2.hw
};
static u32 meson8b_cts_mclk_i958_mux_table[] = { 1, 2, 3 };
@@ -2224,8 +2503,8 @@ static struct clk_regmap meson8b_cts_mclk_i958_sel = {
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_sel",
.ops = &clk_regmap_mux_ops,
- .parent_names = meson8b_cts_mclk_i958_parent_names,
- .num_parents = ARRAY_SIZE(meson8b_cts_mclk_i958_parent_names),
+ .parent_hws = meson8b_cts_mclk_i958_parent_hws,
+ .num_parents = ARRAY_SIZE(meson8b_cts_mclk_i958_parent_hws),
},
};
@@ -2239,7 +2518,9 @@ static struct clk_regmap meson8b_cts_mclk_i958_div = {
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_div",
.ops = &clk_regmap_divider_ops,
- .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_mclk_i958_sel.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2253,7 +2534,9 @@ static struct clk_regmap meson8b_cts_mclk_i958 = {
.hw.init = &(struct clk_init_data){
.name = "cts_mclk_i958",
.ops = &clk_regmap_gate_ops,
- .parent_names = (const char *[]){ "cts_mclk_i958_div" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_mclk_i958_div.hw
+ },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -2268,8 +2551,10 @@ static struct clk_regmap meson8b_cts_i958 = {
.hw.init = &(struct clk_init_data){
.name = "cts_i958",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "cts_amclk",
- "cts_mclk_i958" },
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8b_cts_amclk.hw,
+ &meson8b_cts_mclk_i958.hw
+ },
.num_parents = 2,
/*
* The parent is specific to origin of the audio data. Let the
@@ -2279,6 +2564,9 @@ static struct clk_regmap meson8b_cts_i958 = {
},
};
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &meson8b_clk81.hw)
+
/* Everything Else (EE) domain gates */
static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index 52bbb9ce3807..d4075b130674 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -572,17 +572,11 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
- unsigned long flags;
- u32 value;
dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
/* Reset module */
- spin_lock_irqsave(&priv->rmw_lock, flags);
- value = readl(priv->base + SRCR(reg));
- value |= bitmask;
- writel(value, priv->base + SRCR(reg));
- spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ writel(bitmask, priv->base + SRCR(reg));
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
@@ -599,16 +593,10 @@ static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
- unsigned long flags;
- u32 value;
dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
- spin_lock_irqsave(&priv->rmw_lock, flags);
- value = readl(priv->base + SRCR(reg));
- value |= bitmask;
- writel(value, priv->base + SRCR(reg));
- spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ writel(bitmask, priv->base + SRCR(reg));
return 0;
}
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c
index 91db7894125d..65c82d922b05 100644
--- a/drivers/clk/samsung/clk-exynos5-subcmu.c
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.c
@@ -14,7 +14,7 @@
#include "clk-exynos5-subcmu.h"
static struct samsung_clk_provider *ctx;
-static const struct exynos5_subcmu_info *cmu;
+static const struct exynos5_subcmu_info **cmu;
static int nr_cmus;
static void exynos5_subcmu_clk_save(void __iomem *base,
@@ -56,17 +56,17 @@ static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
* when OF-core populates all device-tree nodes.
*/
void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
- const struct exynos5_subcmu_info *_cmu)
+ const struct exynos5_subcmu_info **_cmu)
{
ctx = _ctx;
cmu = _cmu;
nr_cmus = _nr_cmus;
for (; _nr_cmus--; _cmu++) {
- exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
- _cmu->nr_gate_clks);
- exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
- _cmu->nr_suspend_regs);
+ exynos5_subcmu_defer_gate(ctx, (*_cmu)->gate_clks,
+ (*_cmu)->nr_gate_clks);
+ exynos5_subcmu_clk_save(ctx->reg_base, (*_cmu)->suspend_regs,
+ (*_cmu)->nr_suspend_regs);
}
}
@@ -163,9 +163,9 @@ static int __init exynos5_clk_probe(struct platform_device *pdev)
if (of_property_read_string(np, "label", &name) < 0)
continue;
for (i = 0; i < nr_cmus; i++)
- if (strcmp(cmu[i].pd_name, name) == 0)
+ if (strcmp(cmu[i]->pd_name, name) == 0)
exynos5_clk_register_subcmu(&pdev->dev,
- &cmu[i], np);
+ cmu[i], np);
}
return 0;
}
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.h b/drivers/clk/samsung/clk-exynos5-subcmu.h
index 755ee8aaa3de..9ae5356f25aa 100644
--- a/drivers/clk/samsung/clk-exynos5-subcmu.h
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.h
@@ -21,6 +21,6 @@ struct exynos5_subcmu_info {
};
void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
- const struct exynos5_subcmu_info *cmu);
+ const struct exynos5_subcmu_info **cmu);
#endif
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index f2b896881768..931c70a4da19 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -681,6 +681,10 @@ static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
.pd_name = "DISP1",
};
+static const struct exynos5_subcmu_info *exynos5250_subcmus[] = {
+ &exynos5250_disp_subcmu,
+};
+
static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
@@ -843,7 +847,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_sleep_init(reg_base, exynos5250_clk_regs,
ARRAY_SIZE(exynos5250_clk_regs));
- exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5250_subcmus),
+ exynos5250_subcmus);
samsung_clk_of_add_provider(np, ctx);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 01bca5a498b2..7670cc596c74 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -534,8 +534,6 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
GATE_BUS_TOP, 24, 0, 0),
GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
- GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
- SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -577,8 +575,13 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = {
GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
+ /* Maudio Block */
GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+ GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+ GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
@@ -890,9 +893,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
/* GSCL Block */
DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
- /* MSCL Block */
- DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
-
/* PSGEN */
DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1),
@@ -1017,12 +1017,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
- /* Maudio Block */
- GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
- GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
- GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
- GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
-
/* FSYS Block */
GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0),
@@ -1162,17 +1156,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
GATE_IP_GSCL1, 17, 0, 0),
- /* MSCL Block */
- GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
- GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
- GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
- GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
- GATE_IP_MSCL, 8, 0, 0),
- GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
- GATE_IP_MSCL, 9, 0, 0),
- GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
- GATE_IP_MSCL, 10, 0, 0),
-
/* ISP */
GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1281,32 +1264,103 @@ static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
{ DIV4_RATIO, 0, 0x3 }, /* DIV dout_mfc_blk */
};
-static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
- {
- .div_clks = exynos5x_disp_div_clks,
- .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks),
- .gate_clks = exynos5x_disp_gate_clks,
- .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks),
- .suspend_regs = exynos5x_disp_suspend_regs,
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
- .pd_name = "DISP",
- }, {
- .div_clks = exynos5x_gsc_div_clks,
- .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks),
- .gate_clks = exynos5x_gsc_gate_clks,
- .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks),
- .suspend_regs = exynos5x_gsc_suspend_regs,
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
- .pd_name = "GSC",
- }, {
- .div_clks = exynos5x_mfc_div_clks,
- .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks),
- .gate_clks = exynos5x_mfc_gate_clks,
- .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks),
- .suspend_regs = exynos5x_mfc_suspend_regs,
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
- .pd_name = "MFC",
- },
+static const struct samsung_gate_clock exynos5x_mscl_gate_clks[] __initconst = {
+ /* MSCL Block */
+ GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
+ GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
+ GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
+ GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
+ GATE_IP_MSCL, 8, 0, 0),
+ GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
+ GATE_IP_MSCL, 9, 0, 0),
+ GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
+ GATE_IP_MSCL, 10, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_mscl_div_clks[] __initconst = {
+ DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_mscl_suspend_regs[] = {
+ { GATE_IP_MSCL, 0xffffffff, 0xffffffff }, /* MSCL gates */
+ { SRC_TOP3, 0, BIT(4) }, /* MUX mout_user_aclk400_mscl */
+ { DIV2_RATIO0, 0, 0x30000000 }, /* DIV dout_mscl_blk */
+};
+
+static const struct samsung_gate_clock exynos5800_mau_gate_clks[] __initconst = {
+ GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
+ SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+ GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+ GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5800_mau_suspend_regs[] = {
+ { SRC_TOP9, 0, BIT(8) }, /* MUX mout_user_mau_epll */
+};
+
+static const struct exynos5_subcmu_info exynos5x_disp_subcmu = {
+ .div_clks = exynos5x_disp_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks),
+ .gate_clks = exynos5x_disp_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks),
+ .suspend_regs = exynos5x_disp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+ .pd_name = "DISP",
+};
+
+static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
+ .div_clks = exynos5x_gsc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks),
+ .gate_clks = exynos5x_gsc_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+ .suspend_regs = exynos5x_gsc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+ .pd_name = "GSC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
+ .div_clks = exynos5x_mfc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks),
+ .gate_clks = exynos5x_mfc_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+ .suspend_regs = exynos5x_mfc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+ .pd_name = "MFC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mscl_subcmu = {
+ .div_clks = exynos5x_mscl_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_mscl_div_clks),
+ .gate_clks = exynos5x_mscl_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_mscl_gate_clks),
+ .suspend_regs = exynos5x_mscl_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_mscl_suspend_regs),
+ .pd_name = "MSC",
+};
+
+static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
+ .gate_clks = exynos5800_mau_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5800_mau_gate_clks),
+ .suspend_regs = exynos5800_mau_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5800_mau_suspend_regs),
+ .pd_name = "MAU",
+};
+
+static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
+ &exynos5x_disp_subcmu,
+ &exynos5x_gsc_subcmu,
+ &exynos5x_mfc_subcmu,
+ &exynos5x_mscl_subcmu,
+};
+
+static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
+ &exynos5x_disp_subcmu,
+ &exynos5x_gsc_subcmu,
+ &exynos5x_mfc_subcmu,
+ &exynos5x_mscl_subcmu,
+ &exynos5800_mau_subcmu,
};
static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
@@ -1539,11 +1593,17 @@ static void __init exynos5x_clk_init(struct device_node *np,
samsung_clk_extended_sleep_init(reg_base,
exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
exynos5420_set_clksrc, ARRAY_SIZE(exynos5420_set_clksrc));
- if (soc == EXYNOS5800)
+
+ if (soc == EXYNOS5800) {
samsung_clk_sleep_init(reg_base, exynos5800_clk_regs,
ARRAY_SIZE(exynos5800_clk_regs));
- exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
- exynos5x_subcmus);
+
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5800_subcmus),
+ exynos5800_subcmus);
+ } else {
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+ exynos5x_subcmus);
+ }
samsung_clk_of_add_provider(np, ctx);
}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
index 5c50e723ecae..1a191eeeebba 100644
--- a/drivers/clk/socfpga/clk-periph-s10.c
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -38,7 +38,7 @@ static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
if (socfpgaclk->fixed_div) {
div = socfpgaclk->fixed_div;
} else {
- if (!socfpgaclk->bypass_reg)
+ if (socfpgaclk->hw.reg)
div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
}
diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
index 91d3d721c801..3c219af25100 100644
--- a/drivers/clk/sprd/Kconfig
+++ b/drivers/clk/sprd/Kconfig
@@ -3,6 +3,7 @@ config SPRD_COMMON_CLK
tristate "Clock support for Spreadtrum SoCs"
depends on ARCH_SPRD || COMPILE_TEST
default ARCH_SPRD
+ select REGMAP_MMIO
if SPRD_COMMON_CLK
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 5e6038fbf115..470c7ef02ea4 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -2,6 +2,10 @@
/*
* Copyright (C) 2012 Regents of the University of California
* Copyright (C) 2017 SiFive
+ *
+ * All RISC-V systems have a timer attached to every hart. These timers can be
+ * read from the "time" and "timeh" CSRs, and can use the SBI to setup
+ * events.
*/
#include <linux/clocksource.h>
#include <linux/clockchips.h>
@@ -12,19 +16,6 @@
#include <asm/smp.h>
#include <asm/sbi.h>
-/*
- * All RISC-V systems have a timer attached to every hart. These timers can be
- * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup
- * events. In order to abstract the architecture-specific timer reading and
- * setting functions away from the clock event insertion code, we provide
- * function pointers to the clockevent subsystem that perform two basic
- * operations: rdtime() reads the timer on the current CPU, and
- * next_event(delta) sets the next timer event to 'delta' cycles in the future.
- * As the timers are inherently a per-cpu resource, these callbacks perform
- * operations on the current hart. There is guaranteed to be exactly one timer
- * per hart on all RISC-V systems.
- */
-
static int riscv_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
@@ -55,7 +46,7 @@ static u64 riscv_sched_clock(void)
return get_cycles64();
}
-static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
+static struct clocksource riscv_clocksource = {
.name = "riscv_clocksource",
.rating = 300,
.mask = CLOCKSOURCE_MASK(64),
@@ -92,7 +83,6 @@ void riscv_timer_interrupt(void)
static int __init riscv_timer_init_dt(struct device_node *n)
{
int cpuid, hartid, error;
- struct clocksource *cs;
hartid = riscv_of_processor_hartid(n);
if (hartid < 0) {
@@ -112,8 +102,7 @@ static int __init riscv_timer_init_dt(struct device_node *n)
pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
__func__, cpuid, hartid);
- cs = per_cpu_ptr(&riscv_clocksource, cpuid);
- error = clocksource_register_hz(cs, riscv_timebase);
+ error = clocksource_register_hz(&riscv_clocksource, riscv_timebase);
if (error) {
pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
error, cpuid);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8dda62367816..c28ebf2810f1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2528,7 +2528,7 @@ static int cpufreq_boost_set_sw(int state)
}
ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
- if (ret)
+ if (ret < 0)
break;
}
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index cc27d4c59dca..886324041add 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1867,22 +1867,22 @@ static const struct pstate_funcs knl_funcs = {
(unsigned long)&policy }
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
- ICPU(INTEL_FAM6_SANDYBRIDGE, core_funcs),
+ ICPU(INTEL_FAM6_SANDYBRIDGE, core_funcs),
ICPU(INTEL_FAM6_SANDYBRIDGE_X, core_funcs),
ICPU(INTEL_FAM6_ATOM_SILVERMONT, silvermont_funcs),
ICPU(INTEL_FAM6_IVYBRIDGE, core_funcs),
- ICPU(INTEL_FAM6_HASWELL_CORE, core_funcs),
- ICPU(INTEL_FAM6_BROADWELL_CORE, core_funcs),
+ ICPU(INTEL_FAM6_HASWELL, core_funcs),
+ ICPU(INTEL_FAM6_BROADWELL, core_funcs),
ICPU(INTEL_FAM6_IVYBRIDGE_X, core_funcs),
ICPU(INTEL_FAM6_HASWELL_X, core_funcs),
- ICPU(INTEL_FAM6_HASWELL_ULT, core_funcs),
- ICPU(INTEL_FAM6_HASWELL_GT3E, core_funcs),
- ICPU(INTEL_FAM6_BROADWELL_GT3E, core_funcs),
+ ICPU(INTEL_FAM6_HASWELL_L, core_funcs),
+ ICPU(INTEL_FAM6_HASWELL_G, core_funcs),
+ ICPU(INTEL_FAM6_BROADWELL_G, core_funcs),
ICPU(INTEL_FAM6_ATOM_AIRMONT, airmont_funcs),
- ICPU(INTEL_FAM6_SKYLAKE_MOBILE, core_funcs),
+ ICPU(INTEL_FAM6_SKYLAKE_L, core_funcs),
ICPU(INTEL_FAM6_BROADWELL_X, core_funcs),
- ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs),
- ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_funcs),
+ ICPU(INTEL_FAM6_SKYLAKE, core_funcs),
+ ICPU(INTEL_FAM6_BROADWELL_D, core_funcs),
ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_funcs),
ICPU(INTEL_FAM6_XEON_PHI_KNM, knl_funcs),
ICPU(INTEL_FAM6_ATOM_GOLDMONT, core_funcs),
@@ -1893,20 +1893,20 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
- ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_funcs),
+ ICPU(INTEL_FAM6_BROADWELL_D, core_funcs),
ICPU(INTEL_FAM6_BROADWELL_X, core_funcs),
ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs),
{}
};
static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
- ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, core_funcs),
+ ICPU(INTEL_FAM6_KABYLAKE, core_funcs),
{}
};
static const struct x86_cpu_id intel_pstate_hwp_boost_ids[] = {
ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs),
- ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs),
+ ICPU(INTEL_FAM6_SKYLAKE, core_funcs),
{}
};
@@ -2624,7 +2624,7 @@ static inline void intel_pstate_request_control_from_smm(void) {}
static const struct x86_cpu_id hwp_support_ids[] __initconst = {
ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL),
- ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL),
+ ICPU_HWP(INTEL_FAM6_BROADWELL_D, INTEL_PSTATE_HWP_BROADWELL),
ICPU_HWP(X86_MODEL_ANY, 0),
{}
};
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
index 93f39a1d4c3d..c66f566a854c 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -131,10 +131,18 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
int err = -ENODEV;
cpu = of_get_cpu_node(policy->cpu, NULL);
+ if (!cpu)
+ goto out;
+ max_freqp = of_get_property(cpu, "clock-frequency", NULL);
of_node_put(cpu);
- if (!cpu)
+ if (!max_freqp) {
+ err = -EINVAL;
goto out;
+ }
+
+ /* we need the freq in kHz */
+ max_freq = *max_freqp / 1000;
dn = of_find_compatible_node(NULL, NULL, "1682m-sdc");
if (!dn)
@@ -171,16 +179,6 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
}
pr_debug("init cpufreq on CPU %d\n", policy->cpu);
-
- max_freqp = of_get_property(cpu, "clock-frequency", NULL);
- if (!max_freqp) {
- err = -EINVAL;
- goto out_unmap_sdcpwr;
- }
-
- /* we need the freq in kHz */
- max_freq = *max_freqp / 1000;
-
pr_debug("max clock-frequency is at %u kHz\n", max_freq);
pr_debug("initializing frequency table\n");
@@ -199,9 +197,6 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
return 0;
-out_unmap_sdcpwr:
- iounmap(sdcpwr_mapbase);
-
out_unmap_sdcasr:
iounmap(sdcasr_mapbase);
out:
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 48cb3d4bb7d1..d8530475493c 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -13,6 +13,16 @@ config ARM_CPUIDLE
initialized by calling the CPU operations init idle hook
provided by architecture code.
+config ARM_PSCI_CPUIDLE
+ bool "PSCI CPU idle Driver"
+ depends on ARM_PSCI_FW
+ select DT_IDLE_STATES
+ select CPU_IDLE_MULTIPLE_DRIVERS
+ help
+ Select this to enable PSCI firmware based CPUidle driver for ARM.
+ It provides an idle driver that is capable of detecting and
+ managing idle states through the PSCI firmware interface.
+
config ARM_BIG_LITTLE_CPUIDLE
bool "Support for ARM big.LITTLE processors"
depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 9d7176cee3d3..40d016339b29 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o
obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o
obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o
obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o
+obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o
###############################################################################
# MIPS drivers
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index 5bcd82c35dcf..9e5156d39627 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
-#include <linux/topology.h>
#include <asm/cpuidle.h>
@@ -106,11 +105,17 @@ static int __init arm_idle_init_cpu(int cpu)
ret = arm_cpuidle_init(cpu);
/*
- * Allow the initialization to continue for other CPUs, if the reported
- * failure is a HW misconfiguration/breakage (-ENXIO).
+ * Allow the initialization to continue for other CPUs, if the
+ * reported failure is a HW misconfiguration/breakage (-ENXIO).
+ *
+ * Some platforms do not support idle operations
+ * (arm_cpuidle_init() returning -EOPNOTSUPP), we should
+ * not flag this case as an error, it is a valid
+ * configuration.
*/
if (ret) {
- pr_err("CPU %d failed to init idle CPU ops\n", cpu);
+ if (ret != -EOPNOTSUPP)
+ pr_err("CPU %d failed to init idle CPU ops\n", cpu);
ret = ret == -ENXIO ? 0 : ret;
goto out_kfree_drv;
}
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
new file mode 100644
index 000000000000..f3c1a2396f98
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PSCI CPU idle driver.
+ *
+ * Copyright (C) 2019 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ */
+
+#define pr_fmt(fmt) "CPUidle PSCI: " fmt
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+
+#include <asm/cpuidle.h>
+
+#include "dt_idle_states.h"
+
+static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+
+static int psci_enter_idle_state(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int idx)
+{
+ u32 *state = __this_cpu_read(psci_power_state);
+
+ return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
+ idx, state[idx - 1]);
+}
+
+static struct cpuidle_driver psci_idle_driver __initdata = {
+ .name = "psci_idle",
+ .owner = THIS_MODULE,
+ /*
+ * PSCI idle states relies on architectural WFI to
+ * be represented as state index 0.
+ */
+ .states[0] = {
+ .enter = psci_enter_idle_state,
+ .exit_latency = 1,
+ .target_residency = 1,
+ .power_usage = UINT_MAX,
+ .name = "WFI",
+ .desc = "ARM WFI",
+ }
+};
+
+static const struct of_device_id psci_idle_state_match[] __initconst = {
+ { .compatible = "arm,idle-state",
+ .data = psci_enter_idle_state },
+ { },
+};
+
+static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
+{
+ int err = of_property_read_u32(np, "arm,psci-suspend-param", state);
+
+ if (err) {
+ pr_warn("%pOF missing arm,psci-suspend-param property\n", np);
+ return err;
+ }
+
+ if (!psci_power_state_is_valid(*state)) {
+ pr_warn("Invalid PSCI power state %#x\n", *state);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+{
+ int i, ret = 0, count = 0;
+ u32 *psci_states;
+ struct device_node *state_node;
+
+ /* Count idle states */
+ while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
+ count))) {
+ count++;
+ of_node_put(state_node);
+ }
+
+ if (!count)
+ return -ENODEV;
+
+ psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
+ if (!psci_states)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+ ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
+ of_node_put(state_node);
+
+ if (ret)
+ goto free_mem;
+
+ pr_debug("psci-power-state %#x index %d\n", psci_states[i], i);
+ }
+
+ /* Idle states parsed correctly, initialize per-cpu pointer */
+ per_cpu(psci_power_state, cpu) = psci_states;
+ return 0;
+
+free_mem:
+ kfree(psci_states);
+ return ret;
+}
+
+static __init int psci_cpu_init_idle(unsigned int cpu)
+{
+ struct device_node *cpu_node;
+ int ret;
+
+ /*
+ * If the PSCI cpu_suspend function hook has not been initialized
+ * idle states must not be enabled, so bail out
+ */
+ if (!psci_ops.cpu_suspend)
+ return -EOPNOTSUPP;
+
+ cpu_node = of_cpu_device_node_get(cpu);
+ if (!cpu_node)
+ return -ENODEV;
+
+ ret = psci_dt_cpu_init_idle(cpu_node, cpu);
+
+ of_node_put(cpu_node);
+
+ return ret;
+}
+
+static int __init psci_idle_init_cpu(int cpu)
+{
+ struct cpuidle_driver *drv;
+ struct device_node *cpu_node;
+ const char *enable_method;
+ int ret = 0;
+
+ cpu_node = of_cpu_device_node_get(cpu);
+ if (!cpu_node)
+ return -ENODEV;
+
+ /*
+ * Check whether the enable-method for the cpu is PSCI, fail
+ * if it is not.
+ */
+ enable_method = of_get_property(cpu_node, "enable-method", NULL);
+ if (!enable_method || (strcmp(enable_method, "psci")))
+ ret = -ENODEV;
+
+ of_node_put(cpu_node);
+ if (ret)
+ return ret;
+
+ drv = kmemdup(&psci_idle_driver, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
+ drv->cpumask = (struct cpumask *)cpumask_of(cpu);
+
+ /*
+ * Initialize idle states data, starting at index 1, since
+ * by default idle state 0 is the quiescent state reached
+ * by the cpu by executing the wfi instruction.
+ *
+ * If no DT idle states are detected (ret == 0) let the driver
+ * initialization fail accordingly since there is no reason to
+ * initialize the idle driver if only wfi is supported, the
+ * default archictectural back-end already executes wfi
+ * on idle entry.
+ */
+ ret = dt_init_idle_driver(drv, psci_idle_state_match, 1);
+ if (ret <= 0) {
+ ret = ret ? : -ENODEV;
+ goto out_kfree_drv;
+ }
+
+ /*
+ * Initialize PSCI idle states.
+ */
+ ret = psci_cpu_init_idle(cpu);
+ if (ret) {
+ pr_err("CPU %d failed to PSCI idle\n", cpu);
+ goto out_kfree_drv;
+ }
+
+ ret = cpuidle_register(drv, NULL);
+ if (ret)
+ goto out_kfree_drv;
+
+ return 0;
+
+out_kfree_drv:
+ kfree(drv);
+ return ret;
+}
+
+/*
+ * psci_idle_init - Initializes PSCI cpuidle driver
+ *
+ * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails
+ * to register cpuidle driver then rollback to cancel all CPUs
+ * registration.
+ */
+static int __init psci_idle_init(void)
+{
+ int cpu, ret;
+ struct cpuidle_driver *drv;
+ struct cpuidle_device *dev;
+
+ for_each_possible_cpu(cpu) {
+ ret = psci_idle_init_cpu(cpu);
+ if (ret)
+ goto out_fail;
+ }
+
+ return 0;
+
+out_fail:
+ while (--cpu >= 0) {
+ dev = per_cpu(cpuidle_devices, cpu);
+ drv = cpuidle_get_cpu_driver(dev);
+ cpuidle_unregister(drv);
+ kfree(drv);
+ }
+
+ return ret;
+}
+device_initcall(psci_idle_init);
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
index f9fec2ddf56a..94c1ad7eeddf 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes-galois.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
@@ -58,6 +58,19 @@ static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
unsigned int authsize)
{
+ switch (authsize) {
+ case 16:
+ case 15:
+ case 14:
+ case 13:
+ case 12:
+ case 8:
+ case 4:
+ break;
+ default:
+ return -EINVAL;
+ }
+
return 0;
}
@@ -104,6 +117,7 @@ static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
memset(&rctx->cmd, 0, sizeof(rctx->cmd));
INIT_LIST_HEAD(&rctx->cmd.entry);
rctx->cmd.engine = CCP_ENGINE_AES;
+ rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);
rctx->cmd.u.aes.type = ctx->u.aes.type;
rctx->cmd.u.aes.mode = ctx->u.aes.mode;
rctx->cmd.u.aes.action = encrypt;
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index f79eede71c62..edefa669153f 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -540,6 +540,10 @@ int ccp_dev_suspend(struct sp_device *sp, pm_message_t state)
unsigned long flags;
unsigned int i;
+ /* If there's no device there's nothing to do */
+ if (!ccp)
+ return 0;
+
spin_lock_irqsave(&ccp->cmd_lock, flags);
ccp->suspending = 1;
@@ -564,6 +568,10 @@ int ccp_dev_resume(struct sp_device *sp)
unsigned long flags;
unsigned int i;
+ /* If there's no device there's nothing to do */
+ if (!ccp)
+ return 0;
+
spin_lock_irqsave(&ccp->cmd_lock, flags);
ccp->suspending = 0;
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index c69ed4bae2eb..9bc3c62157d7 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -622,6 +622,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
unsigned long long *final;
unsigned int dm_offset;
+ unsigned int authsize;
unsigned int jobid;
unsigned int ilen;
bool in_place = true; /* Default value */
@@ -643,6 +644,21 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
if (!aes->key) /* Gotta have a key SGL */
return -EINVAL;
+ /* Zero defaults to 16 bytes, the maximum size */
+ authsize = aes->authsize ? aes->authsize : AES_BLOCK_SIZE;
+ switch (authsize) {
+ case 16:
+ case 15:
+ case 14:
+ case 13:
+ case 12:
+ case 8:
+ case 4:
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* First, decompose the source buffer into AAD & PT,
* and the destination buffer into AAD, CT & tag, or
* the input into CT & tag.
@@ -657,7 +673,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen);
} else {
/* Input length for decryption includes tag */
- ilen = aes->src_len - AES_BLOCK_SIZE;
+ ilen = aes->src_len - authsize;
p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen);
}
@@ -766,8 +782,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
while (src.sg_wa.bytes_left) {
ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true);
if (!src.sg_wa.bytes_left) {
- unsigned int nbytes = aes->src_len
- % AES_BLOCK_SIZE;
+ unsigned int nbytes = ilen % AES_BLOCK_SIZE;
if (nbytes) {
op.eom = 1;
@@ -839,19 +854,19 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
if (aes->action == CCP_AES_ACTION_ENCRYPT) {
/* Put the ciphered tag after the ciphertext. */
- ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE);
+ ccp_get_dm_area(&final_wa, 0, p_tag, 0, authsize);
} else {
/* Does this ciphered tag match the input? */
- ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE,
+ ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
DMA_BIDIRECTIONAL);
if (ret)
goto e_tag;
- ret = ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE);
+ ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
if (ret)
goto e_tag;
ret = crypto_memneq(tag.address, final_wa.address,
- AES_BLOCK_SIZE) ? -EBADMSG : 0;
+ authsize) ? -EBADMSG : 0;
ccp_dm_free(&tag);
}
@@ -859,11 +874,11 @@ e_tag:
ccp_dm_free(&final_wa);
e_dst:
- if (aes->src_len && !in_place)
+ if (ilen > 0 && !in_place)
ccp_free_data(&dst, cmd_q);
e_src:
- if (aes->src_len)
+ if (ilen > 0)
ccp_free_data(&src, cmd_q);
e_aad:
diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c
index ece83a363e11..f22f6fa612b3 100644
--- a/drivers/crypto/ux500/cryp/cryp.c
+++ b/drivers/crypto/ux500/cryp/cryp.c
@@ -314,14 +314,17 @@ void cryp_save_device_context(struct cryp_device_data *device_data,
case CRYP_KEY_SIZE_256:
ctx->key_4_l = readl_relaxed(&src_reg->key_4_l);
ctx->key_4_r = readl_relaxed(&src_reg->key_4_r);
+ /* Fall through */
case CRYP_KEY_SIZE_192:
ctx->key_3_l = readl_relaxed(&src_reg->key_3_l);
ctx->key_3_r = readl_relaxed(&src_reg->key_3_r);
+ /* Fall through */
case CRYP_KEY_SIZE_128:
ctx->key_2_l = readl_relaxed(&src_reg->key_2_l);
ctx->key_2_r = readl_relaxed(&src_reg->key_2_r);
+ /* Fall through */
default:
ctx->key_1_l = readl_relaxed(&src_reg->key_1_l);
@@ -361,14 +364,17 @@ void cryp_restore_device_context(struct cryp_device_data *device_data,
case CRYP_KEY_SIZE_256:
writel_relaxed(ctx->key_4_l, &reg->key_4_l);
writel_relaxed(ctx->key_4_r, &reg->key_4_r);
+ /* Fall through */
case CRYP_KEY_SIZE_192:
writel_relaxed(ctx->key_3_l, &reg->key_3_l);
writel_relaxed(ctx->key_3_r, &reg->key_3_r);
+ /* Fall through */
case CRYP_KEY_SIZE_128:
writel_relaxed(ctx->key_2_l, &reg->key_2_l);
writel_relaxed(ctx->key_2_r, &reg->key_2_r);
+ /* Fall through */
default:
writel_relaxed(ctx->key_1_l, &reg->key_1_l);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 03fa0c58cef3..413efef5fbb6 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -294,8 +294,8 @@ config INTEL_IOATDMA
If unsure, say N.
config INTEL_IOP_ADMA
- tristate "Intel IOP ADMA support"
- depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
+ tristate "Intel IOP32x ADMA support"
+ depends on ARCH_IOP32X
select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
help
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 8101ff2f05c1..67100e4e1083 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -37,10 +37,19 @@
#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
#define BCM2835_DMA_CHAN_NAME_SIZE 8
+/**
+ * struct bcm2835_dmadev - BCM2835 DMA controller
+ * @ddev: DMA device
+ * @base: base address of register map
+ * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients)
+ * @zero_page: bus address of zero page (to detect transactions copying from
+ * zero page and avoid accessing memory if so)
+ */
struct bcm2835_dmadev {
struct dma_device ddev;
void __iomem *base;
struct device_dma_parameters dma_parms;
+ dma_addr_t zero_page;
};
struct bcm2835_dma_cb {
@@ -687,11 +696,12 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
size_t period_len, enum dma_transfer_direction direction,
unsigned long flags)
{
+ struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device);
struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
struct bcm2835_desc *d;
dma_addr_t src, dst;
u32 info = BCM2835_DMA_WAIT_RESP;
- u32 extra = BCM2835_DMA_INT_EN;
+ u32 extra = 0;
size_t max_len = bcm2835_dma_max_frame_length(c);
size_t frames;
@@ -707,6 +717,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
return NULL;
}
+ if (flags & DMA_PREP_INTERRUPT)
+ extra |= BCM2835_DMA_INT_EN;
+ else
+ period_len = buf_len;
+
/*
* warn if buf_len is not a multiple of period_len - this may leed
* to unexpected latencies for interrupts and thus audiable clicks
@@ -732,6 +747,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
dst = c->cfg.dst_addr;
src = buf_addr;
info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+
+ /* non-lite channels can write zeroes w/o accessing memory */
+ if (buf_addr == od->zero_page && !c->is_lite_channel)
+ info |= BCM2835_DMA_S_IGNORE;
}
/* calculate number of frames */
@@ -778,7 +797,10 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
/* stop DMA activity */
if (c->desc) {
- vchan_terminate_vdesc(&c->desc->vd);
+ if (c->desc->vd.tx.flags & DMA_PREP_INTERRUPT)
+ vchan_terminate_vdesc(&c->desc->vd);
+ else
+ vchan_vdesc_fini(&c->desc->vd);
c->desc = NULL;
bcm2835_dma_abort(c);
}
@@ -831,6 +853,9 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
list_del(&c->vc.chan.device_node);
tasklet_kill(&c->vc.task);
}
+
+ dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE,
+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
}
static const struct of_device_id bcm2835_dma_of_match[] = {
@@ -907,11 +932,20 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) |
BIT(DMA_MEM_TO_MEM);
od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ od->ddev.descriptor_reuse = true;
od->ddev.dev = &pdev->dev;
INIT_LIST_HEAD(&od->ddev.channels);
platform_set_drvdata(pdev, od);
+ od->zero_page = dma_map_page_attrs(od->ddev.dev, ZERO_PAGE(0), 0,
+ PAGE_SIZE, DMA_TO_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(od->ddev.dev, od->zero_page)) {
+ dev_err(&pdev->dev, "Failed to map zero page\n");
+ return -ENOMEM;
+ }
+
/* Request DMA channel mask from device tree */
if (of_property_read_u32(pdev->dev.of_node,
"brcm,dma-channel-mask",
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index b6cc90cbc9dc..4e5f9f6e901b 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -50,7 +50,7 @@ struct dw_edma_burst {
struct dw_edma_region {
phys_addr_t paddr;
- dma_addr_t vaddr;
+ void __iomem *vaddr;
size_t sz;
};
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 4c96e1c948f2..dc85f55e1bb8 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -130,19 +130,19 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->id = pdev->devfn;
chip->irq = pdev->irq;
- dw->rg_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->rg_bar];
+ dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
dw->rg_region.vaddr += pdata->rg_off;
dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
dw->rg_region.paddr += pdata->rg_off;
dw->rg_region.sz = pdata->rg_sz;
- dw->ll_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->ll_bar];
+ dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
dw->ll_region.vaddr += pdata->ll_off;
dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
dw->ll_region.paddr += pdata->ll_off;
dw->ll_region.sz = pdata->ll_sz;
- dw->dt_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->dt_bar];
+ dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
dw->dt_region.vaddr += pdata->dt_off;
dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
dw->dt_region.paddr += pdata->dt_off;
@@ -158,17 +158,17 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
pci_dbg(pdev, "Mode:\t%s\n",
dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
- pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+ pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
- &dw->rg_region.vaddr, &dw->rg_region.paddr);
+ dw->rg_region.vaddr, &dw->rg_region.paddr);
- pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+ pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
- &dw->ll_region.vaddr, &dw->ll_region.paddr);
+ dw->ll_region.vaddr, &dw->ll_region.paddr);
- pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+ pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
- &dw->dt_region.vaddr, &dw->dt_region.paddr);
+ dw->dt_region.vaddr, &dw->dt_region.paddr);
pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 8a3180ed49a6..692de47b1670 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -25,7 +25,7 @@ enum dw_edma_control {
static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
{
- return (struct dw_edma_v0_regs __iomem *)dw->rg_region.vaddr;
+ return dw->rg_region.vaddr;
}
#define SET(dw, name, value) \
@@ -192,13 +192,12 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
{
struct dw_edma_burst *child;
- struct dw_edma_v0_lli *lli;
- struct dw_edma_v0_llp *llp;
+ struct dw_edma_v0_lli __iomem *lli;
+ struct dw_edma_v0_llp __iomem *llp;
u32 control = 0, i = 0;
- u64 sar, dar, addr;
int j;
- lli = (struct dw_edma_v0_lli *)chunk->ll_region.vaddr;
+ lli = chunk->ll_region.vaddr;
if (chunk->cb)
control = DW_EDMA_V0_CB;
@@ -214,17 +213,15 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
/* Transfer size */
SET_LL(&lli[i].transfer_size, child->sz);
/* SAR - low, high */
- sar = cpu_to_le64(child->sar);
- SET_LL(&lli[i].sar_low, lower_32_bits(sar));
- SET_LL(&lli[i].sar_high, upper_32_bits(sar));
+ SET_LL(&lli[i].sar_low, lower_32_bits(child->sar));
+ SET_LL(&lli[i].sar_high, upper_32_bits(child->sar));
/* DAR - low, high */
- dar = cpu_to_le64(child->dar);
- SET_LL(&lli[i].dar_low, lower_32_bits(dar));
- SET_LL(&lli[i].dar_high, upper_32_bits(dar));
+ SET_LL(&lli[i].dar_low, lower_32_bits(child->dar));
+ SET_LL(&lli[i].dar_high, upper_32_bits(child->dar));
i++;
}
- llp = (struct dw_edma_v0_llp *)&lli[i];
+ llp = (void __iomem *)&lli[i];
control = DW_EDMA_V0_LLP | DW_EDMA_V0_TCB;
if (!chunk->cb)
control |= DW_EDMA_V0_CB;
@@ -232,9 +229,8 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
/* Channel control */
SET_LL(&llp->control, control);
/* Linked list - low, high */
- addr = cpu_to_le64(chunk->ll_region.paddr);
- SET_LL(&llp->llp_low, lower_32_bits(addr));
- SET_LL(&llp->llp_high, upper_32_bits(addr));
+ SET_LL(&llp->llp_low, lower_32_bits(chunk->ll_region.paddr));
+ SET_LL(&llp->llp_high, upper_32_bits(chunk->ll_region.paddr));
}
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
@@ -242,7 +238,6 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
struct dw_edma_chan *chan = chunk->chan;
struct dw_edma *dw = chan->chip->dw;
u32 tmp;
- u64 llp;
dw_edma_v0_core_write_chunk(chunk);
@@ -262,9 +257,10 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
SET_CH(dw, chan->dir, chan->id, ch_control1,
(DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
/* Linked list - low, high */
- llp = cpu_to_le64(chunk->ll_region.paddr);
- SET_CH(dw, chan->dir, chan->id, llp_low, lower_32_bits(llp));
- SET_CH(dw, chan->dir, chan->id, llp_high, upper_32_bits(llp));
+ SET_CH(dw, chan->dir, chan->id, llp_low,
+ lower_32_bits(chunk->ll_region.paddr));
+ SET_CH(dw, chan->dir, chan->id, llp_high,
+ upper_32_bits(chunk->ll_region.paddr));
}
/* Doorbell */
SET_RW(dw, chan->dir, doorbell,
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 3226f528cc11..42739508c0d8 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -14,7 +14,7 @@
#include "dw-edma-core.h"
#define REGS_ADDR(name) \
- ((dma_addr_t *)&regs->name)
+ ((void __force *)&regs->name)
#define REGISTER(name) \
{ #name, REGS_ADDR(name) }
@@ -40,36 +40,37 @@
static struct dentry *base_dir;
static struct dw_edma *dw;
-static struct dw_edma_v0_regs *regs;
+static struct dw_edma_v0_regs __iomem *regs;
static struct {
- void *start;
- void *end;
+ void __iomem *start;
+ void __iomem *end;
} lim[2][EDMA_V0_MAX_NR_CH];
struct debugfs_entries {
- char name[24];
+ const char *name;
dma_addr_t *reg;
};
static int dw_edma_debugfs_u32_get(void *data, u64 *val)
{
+ void __iomem *reg = (void __force __iomem *)data;
if (dw->mode == EDMA_MODE_LEGACY &&
- data >= (void *)&regs->type.legacy.ch) {
- void *ptr = (void *)&regs->type.legacy.ch;
+ reg >= (void __iomem *)&regs->type.legacy.ch) {
+ void __iomem *ptr = &regs->type.legacy.ch;
u32 viewport_sel = 0;
unsigned long flags;
u16 ch;
for (ch = 0; ch < dw->wr_ch_cnt; ch++)
- if (lim[0][ch].start >= data && data < lim[0][ch].end) {
- ptr += (data - lim[0][ch].start);
+ if (lim[0][ch].start >= reg && reg < lim[0][ch].end) {
+ ptr += (reg - lim[0][ch].start);
goto legacy_sel_wr;
}
for (ch = 0; ch < dw->rd_ch_cnt; ch++)
- if (lim[1][ch].start >= data && data < lim[1][ch].end) {
- ptr += (data - lim[1][ch].start);
+ if (lim[1][ch].start >= reg && reg < lim[1][ch].end) {
+ ptr += (reg - lim[1][ch].start);
goto legacy_sel_rd;
}
@@ -86,7 +87,7 @@ legacy_sel_wr:
raw_spin_unlock_irqrestore(&dw->lock, flags);
} else {
- *val = readl(data);
+ *val = readl(reg);
}
return 0;
@@ -105,7 +106,7 @@ static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
}
}
-static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs *regs,
+static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
struct dentry *dir)
{
int nr_entries;
@@ -288,7 +289,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
if (!dw)
return;
- regs = (struct dw_edma_v0_regs *)dw->rg_region.vaddr;
+ regs = dw->rg_region.vaddr;
if (!regs)
return;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 23e0a356f167..ad72b3f42ffa 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1163,6 +1163,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
switch (chan->feature & FSL_DMA_IP_MASK) {
case FSL_DMA_IP_85XX:
chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+ /* Fall through */
case FSL_DMA_IP_83XX:
chan->toggle_ext_start = fsl_chan_toggle_ext_start;
chan->set_src_loop_size = fsl_chan_set_src_loop_size;
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index c6c0143670d9..03f4a588cf7f 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -16,13 +16,13 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/prefetch.h>
#include <linux/memory.h>
#include <linux/ioport.h>
#include <linux/raid/pq.h>
#include <linux/slab.h>
-#include <mach/adma.h>
-
+#include "iop-adma.h"
#include "dmaengine.h"
#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
@@ -116,9 +116,9 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
chain_node) {
pr_debug("\tcookie: %d slot: %d busy: %d "
- "this_desc: %#x next_desc: %#x ack: %d\n",
+ "this_desc: %#x next_desc: %#llx ack: %d\n",
iter->async_tx.cookie, iter->idx, busy,
- iter->async_tx.phys, iop_desc_get_next_desc(iter),
+ iter->async_tx.phys, (u64)iop_desc_get_next_desc(iter),
async_tx_test_ack(&iter->async_tx));
prefetch(_iter);
prefetch(&_iter->async_tx);
@@ -306,9 +306,9 @@ retry:
int i;
dev_dbg(iop_chan->device->common.dev,
"allocated slot: %d "
- "(desc %p phys: %#x) slots_per_op %d\n",
+ "(desc %p phys: %#llx) slots_per_op %d\n",
iter->idx, iter->hw_desc,
- iter->async_tx.phys, slots_per_op);
+ (u64)iter->async_tx.phys, slots_per_op);
/* pre-ack all but the last descriptor */
if (num_slots != slots_per_op)
@@ -516,7 +516,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
return NULL;
BUG_ON(len > IOP_ADMA_MAX_BYTE_COUNT);
- dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s len: %zu\n",
__func__, len);
spin_lock_bh(&iop_chan->lock);
@@ -549,7 +549,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
dev_dbg(iop_chan->device->common.dev,
- "%s src_cnt: %d len: %u flags: %lx\n",
+ "%s src_cnt: %d len: %zu flags: %lx\n",
__func__, src_cnt, len, flags);
spin_lock_bh(&iop_chan->lock);
@@ -582,7 +582,7 @@ iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src,
if (unlikely(!len))
return NULL;
- dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
__func__, src_cnt, len);
spin_lock_bh(&iop_chan->lock);
@@ -620,7 +620,7 @@ iop_adma_prep_dma_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
dev_dbg(iop_chan->device->common.dev,
- "%s src_cnt: %d len: %u flags: %lx\n",
+ "%s src_cnt: %d len: %zu flags: %lx\n",
__func__, src_cnt, len, flags);
if (dmaf_p_disabled_continue(flags))
@@ -683,7 +683,7 @@ iop_adma_prep_dma_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
return NULL;
BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
- dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
__func__, src_cnt, len);
spin_lock_bh(&iop_chan->lock);
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/drivers/dma/iop-adma.h
index 6d998df17efd..c499c9578f00 100644
--- a/arch/arm/include/asm/hardware/iop3xx-adma.h
+++ b/drivers/dma/iop-adma.h
@@ -6,8 +6,7 @@
#define _ADMA_H
#include <linux/types.h>
#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/hardware/iop_adma.h>
+#include <linux/platform_data/dma-iop32x.h>
/* Memory copy units */
#define DMA_CCR(chan) (chan->mmr_base + 0x0)
@@ -34,10 +33,6 @@
#define AAU_EDCR1_IDX 17
#define AAU_EDCR2_IDX 26
-#define DMA0_ID 0
-#define DMA1_ID 1
-#define AAU_ID 2
-
struct iop3xx_aau_desc_ctrl {
unsigned int int_en:1;
unsigned int blk1_cmd_ctrl:3;
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 9c41a4e42575..1072c450c37a 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -192,6 +192,7 @@ struct rcar_dmac_chan {
* @iomem: remapped I/O memory base
* @n_channels: number of available channels
* @channels: array of DMAC channels
+ * @channels_mask: bitfield of which DMA channels are managed by this driver
* @modules: bitmask of client modules in use
*/
struct rcar_dmac {
@@ -202,6 +203,7 @@ struct rcar_dmac {
unsigned int n_channels;
struct rcar_dmac_chan *channels;
+ unsigned int channels_mask;
DECLARE_BITMAP(modules, 256);
};
@@ -438,7 +440,7 @@ static int rcar_dmac_init(struct rcar_dmac *dmac)
u16 dmaor;
/* Clear all channels and enable the DMAC globally. */
- rcar_dmac_write(dmac, RCAR_DMACHCLR, GENMASK(dmac->n_channels - 1, 0));
+ rcar_dmac_write(dmac, RCAR_DMACHCLR, dmac->channels_mask);
rcar_dmac_write(dmac, RCAR_DMAOR,
RCAR_DMAOR_PRI_FIXED | RCAR_DMAOR_DME);
@@ -814,6 +816,9 @@ static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac)
for (i = 0; i < dmac->n_channels; ++i) {
struct rcar_dmac_chan *chan = &dmac->channels[i];
+ if (!(dmac->channels_mask & BIT(i)))
+ continue;
+
/* Stop and reinitialize the channel. */
spin_lock_irq(&chan->lock);
rcar_dmac_chan_halt(chan);
@@ -1776,6 +1781,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
return 0;
}
+#define RCAR_DMAC_MAX_CHANNELS 32
+
static int rcar_dmac_parse_of(struct device *dev, struct rcar_dmac *dmac)
{
struct device_node *np = dev->of_node;
@@ -1787,12 +1794,16 @@ static int rcar_dmac_parse_of(struct device *dev, struct rcar_dmac *dmac)
return ret;
}
- if (dmac->n_channels <= 0 || dmac->n_channels >= 100) {
+ /* The hardware and driver don't support more than 32 bits in CHCLR */
+ if (dmac->n_channels <= 0 ||
+ dmac->n_channels >= RCAR_DMAC_MAX_CHANNELS) {
dev_err(dev, "invalid number of channels %u\n",
dmac->n_channels);
return -EINVAL;
}
+ dmac->channels_mask = GENMASK(dmac->n_channels - 1, 0);
+
return 0;
}
@@ -1802,7 +1813,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
DMA_SLAVE_BUSWIDTH_2_BYTES | DMA_SLAVE_BUSWIDTH_4_BYTES |
DMA_SLAVE_BUSWIDTH_8_BYTES | DMA_SLAVE_BUSWIDTH_16_BYTES |
DMA_SLAVE_BUSWIDTH_32_BYTES | DMA_SLAVE_BUSWIDTH_64_BYTES;
- unsigned int channels_offset = 0;
struct dma_device *engine;
struct rcar_dmac *dmac;
struct resource *mem;
@@ -1831,10 +1841,8 @@ static int rcar_dmac_probe(struct platform_device *pdev)
* level we can't disable it selectively, so ignore channel 0 for now if
* the device is part of an IOMMU group.
*/
- if (device_iommu_mapped(&pdev->dev)) {
- dmac->n_channels--;
- channels_offset = 1;
- }
+ if (device_iommu_mapped(&pdev->dev))
+ dmac->channels_mask &= ~BIT(0);
dmac->channels = devm_kcalloc(&pdev->dev, dmac->n_channels,
sizeof(*dmac->channels), GFP_KERNEL);
@@ -1892,8 +1900,10 @@ static int rcar_dmac_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&engine->channels);
for (i = 0; i < dmac->n_channels; ++i) {
- ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i],
- i + channels_offset);
+ if (!(dmac->channels_mask & BIT(i)))
+ continue;
+
+ ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i], i);
if (ret < 0)
goto error;
}
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c
index baac476c8622..525dc7338fe3 100644
--- a/drivers/dma/sprd-dma.c
+++ b/drivers/dma/sprd-dma.c
@@ -908,6 +908,7 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
struct dma_slave_config *slave_cfg = &schan->slave_cfg;
dma_addr_t src = 0, dst = 0;
+ dma_addr_t start_src = 0, start_dst = 0;
struct sprd_dma_desc *sdesc;
struct scatterlist *sg;
u32 len = 0;
@@ -954,6 +955,11 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
dst = sg_dma_address(sg);
}
+ if (!i) {
+ start_src = src;
+ start_dst = dst;
+ }
+
/*
* The link-list mode needs at least 2 link-list
* configurations. If there is only one sg, it doesn't
@@ -970,8 +976,8 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
}
- ret = sprd_dma_fill_desc(chan, &sdesc->chn_hw, 0, 0, src, dst, len,
- dir, flags, slave_cfg);
+ ret = sprd_dma_fill_desc(chan, &sdesc->chn_hw, 0, 0, start_src,
+ start_dst, len, dir, flags, slave_cfg);
if (ret) {
kfree(sdesc);
return NULL;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 89d710899010..de8bfd9a76e9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -142,7 +142,7 @@ enum d40_events {
* when the DMA hw is powered off.
* TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
*/
-static u32 d40_backup_regs[] = {
+static __maybe_unused u32 d40_backup_regs[] = {
D40_DREG_LCPA,
D40_DREG_LCLA,
D40_DREG_PRMSE,
@@ -211,7 +211,7 @@ static u32 d40_backup_regs_v4b[] = {
#define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b)
-static u32 d40_backup_regs_chan[] = {
+static __maybe_unused u32 d40_backup_regs_chan[] = {
D40_CHAN_REG_SSCFG,
D40_CHAN_REG_SSELT,
D40_CHAN_REG_SSPTR,
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
index d6e919d3936a..1311de74bfdd 100644
--- a/drivers/dma/stm32-mdma.c
+++ b/drivers/dma/stm32-mdma.c
@@ -1366,7 +1366,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
chan = &dmadev->chan[id];
if (!chan) {
- dev_err(chan2dev(chan), "MDMA channel not initialized\n");
+ dev_dbg(mdma2dev(dmadev), "MDMA channel not initialized\n");
goto exit;
}
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 2805853e963f..b33cf6e8ab8e 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -712,7 +712,7 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
return chan;
}
-static int tegra_adma_runtime_suspend(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
{
struct tegra_adma *tdma = dev_get_drvdata(dev);
struct tegra_adma_chan_regs *ch_reg;
@@ -744,7 +744,7 @@ clk_disable:
return 0;
}
-static int tegra_adma_runtime_resume(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
{
struct tegra_adma *tdma = dev_get_drvdata(dev);
struct tegra_adma_chan_regs *ch_reg;
diff --git a/drivers/dma/ti/dma-crossbar.c b/drivers/dma/ti/dma-crossbar.c
index ad2f0a4cd6a4..f255056696ee 100644
--- a/drivers/dma/ti/dma-crossbar.c
+++ b/drivers/dma/ti/dma-crossbar.c
@@ -391,8 +391,10 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
ret = of_property_read_u32_array(node, pname, (u32 *)rsv_events,
nelm * 2);
- if (ret)
+ if (ret) {
+ kfree(rsv_events);
return ret;
+ }
for (i = 0; i < nelm; i++) {
ti_dra7_xbar_reserve(rsv_events[i][0], rsv_events[i][1],
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index ba2489d4ea24..d07c0d5de7a2 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1234,7 +1234,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
if (src_icg) {
d->ccr |= CCR_SRC_AMODE_DBLIDX;
d->ei = 1;
- d->fi = src_icg;
+ d->fi = src_icg + 1;
} else if (xt->src_inc) {
d->ccr |= CCR_SRC_AMODE_POSTINC;
d->fi = 0;
@@ -1249,7 +1249,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
if (dst_icg) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
sg->ei = 1;
- sg->fi = dst_icg;
+ sg->fi = dst_icg + 1;
} else if (xt->dst_inc) {
d->ccr |= CCR_DST_AMODE_POSTINC;
sg->fi = 0;
@@ -1540,8 +1540,10 @@ static int omap_dma_probe(struct platform_device *pdev)
rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
IRQF_SHARED, "omap-dma-engine", od);
- if (rc)
+ if (rc) {
+ omap_dma_free(od);
return rc;
+ }
}
if (omap_dma_glbl_read(od, CAPS_0) & CAPS_0_SUPPORT_LL123)
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 200c04ce5b0e..2a2603bfb918 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -510,4 +510,11 @@ config EDAC_ASPEED
First, ECC must be configured in the bootloader. Then, this driver
will expose error counters via the EDAC kernel framework.
+config EDAC_BLUEFIELD
+ tristate "Mellanox BlueField Memory ECC"
+ depends on ARM64 && ((MELLANOX_PLATFORM && ACPI) || COMPILE_TEST)
+ help
+ Support for error detection and correction on the
+ Mellanox BlueField SoCs.
+
endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 165ca65e1a3a..d265ff9311f0 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -85,3 +85,4 @@ obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o
obj-$(CONFIG_EDAC_TI) += ti_edac.o
obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o
+obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index c2e693e34d43..fbda4b876afd 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -222,7 +222,6 @@ static unsigned long get_total_mem(void)
static const struct of_device_id altr_sdram_ctrl_of_match[] = {
{ .compatible = "altr,sdram-edac", .data = &c5_data},
{ .compatible = "altr,sdram-edac-a10", .data = &a10_data},
- { .compatible = "altr,sdram-edac-s10", .data = &a10_data},
{},
};
MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);
@@ -1170,6 +1169,24 @@ static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat)
return 0;
}
+/*********************** SDRAM EDAC Device Functions *********************/
+
+#ifdef CONFIG_EDAC_ALTERA_SDRAM
+
+static const struct edac_device_prv_data s10_sdramecc_data = {
+ .setup = altr_check_ecc_deps,
+ .ce_clear_mask = ALTR_S10_ECC_SERRPENA,
+ .ue_clear_mask = ALTR_S10_ECC_DERRPENA,
+ .ecc_enable_mask = ALTR_S10_ECC_EN,
+ .ecc_en_ofst = ALTR_S10_ECC_CTRL_SDRAM_OFST,
+ .ce_set_mask = ALTR_S10_ECC_TSERRA,
+ .ue_set_mask = ALTR_S10_ECC_TDERRA,
+ .set_err_ofst = ALTR_S10_ECC_INTTEST_OFST,
+ .ecc_irq_handler = altr_edac_a10_ecc_irq,
+ .inject_fops = &altr_edac_a10_device_inject_fops,
+};
+#endif /* CONFIG_EDAC_ALTERA_SDRAM */
+
/*********************** OCRAM EDAC Device Functions *********************/
#ifdef CONFIG_EDAC_ALTERA_OCRAM
@@ -1759,6 +1776,9 @@ static const struct of_device_id altr_edac_a10_device_of_match[] = {
#ifdef CONFIG_EDAC_ALTERA_SDMMC
{ .compatible = "altr,socfpga-sdmmc-ecc", .data = &a10_sdmmcecca_data },
#endif
+#ifdef CONFIG_EDAC_ALTERA_SDRAM
+ { .compatible = "altr,sdram-edac-s10", .data = &s10_sdramecc_data },
+#endif
{},
};
MODULE_DEVICE_TABLE(of, altr_edac_a10_device_of_match);
@@ -1866,6 +1886,7 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc)
struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
int irq = irq_desc_get_irq(desc);
+ unsigned long bits;
dberr = (irq == edac->db_irq) ? 1 : 0;
sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST :
@@ -1875,7 +1896,8 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc)
regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
- for_each_set_bit(bit, (unsigned long *)&irq_status, 32) {
+ bits = irq_status;
+ for_each_set_bit(bit, &bits, 32) {
irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);
if (irq)
generic_handle_irq(irq);
@@ -1889,6 +1911,10 @@ static int validate_parent_available(struct device_node *np)
struct device_node *parent;
int ret = 0;
+ /* SDRAM must be present for Linux (implied parent) */
+ if (of_device_is_compatible(np, "altr,sdram-edac-s10"))
+ return 0;
+
/* Ensure parent device is enabled if parent node exists */
parent = of_parse_phandle(np, "altr,ecc-parent", 0);
if (parent && !of_device_is_available(parent))
@@ -1898,6 +1924,22 @@ static int validate_parent_available(struct device_node *np)
return ret;
}
+static int get_s10_sdram_edac_resource(struct device_node *np,
+ struct resource *res)
+{
+ struct device_node *parent;
+ int ret;
+
+ parent = of_parse_phandle(np, "altr,sdr-syscon", 0);
+ if (!parent)
+ return -ENODEV;
+
+ ret = of_address_to_resource(parent, 0, res);
+ of_node_put(parent);
+
+ return ret;
+}
+
static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
struct device_node *np)
{
@@ -1925,7 +1967,11 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))
return -ENOMEM;
- rc = of_address_to_resource(np, 0, &res);
+ if (of_device_is_compatible(np, "altr,sdram-edac-s10"))
+ rc = get_s10_sdram_edac_resource(np, &res);
+ else
+ rc = of_address_to_resource(np, 0, &res);
+
if (rc < 0) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s: no resource address\n", ecc_name);
@@ -2231,13 +2277,15 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
of_device_is_compatible(child, "altr,socfpga-dma-ecc") ||
of_device_is_compatible(child, "altr,socfpga-usb-ecc") ||
of_device_is_compatible(child, "altr,socfpga-qspi-ecc") ||
+#ifdef CONFIG_EDAC_ALTERA_SDRAM
+ of_device_is_compatible(child, "altr,sdram-edac-s10") ||
+#endif
of_device_is_compatible(child, "altr,socfpga-sdmmc-ecc"))
altr_edac_a10_device_add(edac, child);
#ifdef CONFIG_EDAC_ALTERA_SDRAM
- else if ((of_device_is_compatible(child, "altr,sdram-edac-a10")) ||
- (of_device_is_compatible(child, "altr,sdram-edac-s10")))
+ else if (of_device_is_compatible(child, "altr,sdram-edac-a10"))
of_platform_populate(pdev->dev.of_node,
altr_sdram_ctrl_of_match,
NULL, &pdev->dev);
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h
index 55654cc4bcdf..3727e72c8c2e 100644
--- a/drivers/edac/altera_edac.h
+++ b/drivers/edac/altera_edac.h
@@ -289,6 +289,29 @@ struct altr_sdram_mc_data {
#define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000
/************* Stratix10 Defines **************/
+#define ALTR_S10_ECC_CTRL_SDRAM_OFST 0x00
+#define ALTR_S10_ECC_EN BIT(0)
+
+#define ALTR_S10_ECC_ERRINTEN_OFST 0x10
+#define ALTR_S10_ECC_ERRINTENS_OFST 0x14
+#define ALTR_S10_ECC_ERRINTENR_OFST 0x18
+#define ALTR_S10_ECC_SERRINTEN BIT(0)
+
+#define ALTR_S10_ECC_INTMODE_OFST 0x1C
+#define ALTR_S10_ECC_INTMODE BIT(0)
+
+#define ALTR_S10_ECC_INTSTAT_OFST 0x20
+#define ALTR_S10_ECC_SERRPENA BIT(0)
+#define ALTR_S10_ECC_DERRPENA BIT(8)
+#define ALTR_S10_ECC_ERRPENA_MASK (ALTR_S10_ECC_SERRPENA | \
+ ALTR_S10_ECC_DERRPENA)
+
+#define ALTR_S10_ECC_INTTEST_OFST 0x24
+#define ALTR_S10_ECC_TSERRA BIT(0)
+#define ALTR_S10_ECC_TDERRA BIT(8)
+#define ALTR_S10_ECC_TSERRB BIT(16)
+#define ALTR_S10_ECC_TDERRB BIT(24)
+
#define ALTR_S10_DERR_ADDRA_OFST 0x2C
/* Stratix10 ECC Manager Defines */
@@ -300,7 +323,7 @@ struct altr_sdram_mc_data {
#define S10_SYSMGR_UE_ADDR_OFST 0x224
#define S10_DDR0_IRQ_MASK BIT(16)
-#define S10_DBE_IRQ_MASK 0x3FE
+#define S10_DBE_IRQ_MASK 0x3FFFE
/* Define ECC Block Offsets for peripherals */
#define ECC_BLK_ADDRESS_OFST 0x40
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 873437be86d9..c1d4536ae466 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -788,51 +788,45 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
(dclr & BIT(15)) ? "yes" : "no");
}
-/*
- * The Address Mask should be a contiguous set of bits in the non-interleaved
- * case. So to check for CS interleaving, find the most- and least-significant
- * bits of the mask, generate a contiguous bitmask, and compare the two.
- */
-static bool f17_cs_interleaved(struct amd64_pvt *pvt, u8 ctrl, int cs)
+#define CS_EVEN_PRIMARY BIT(0)
+#define CS_ODD_PRIMARY BIT(1)
+#define CS_EVEN_SECONDARY BIT(2)
+#define CS_ODD_SECONDARY BIT(3)
+
+#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
+#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
+
+static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
{
- u32 mask = pvt->csels[ctrl].csmasks[cs >> 1];
- u32 msb = fls(mask) - 1, lsb = ffs(mask) - 1;
- u32 test_mask = GENMASK(msb, lsb);
+ int cs_mode = 0;
- edac_dbg(1, "mask=0x%08x test_mask=0x%08x\n", mask, test_mask);
+ if (csrow_enabled(2 * dimm, ctrl, pvt))
+ cs_mode |= CS_EVEN_PRIMARY;
- return mask ^ test_mask;
+ if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
+ cs_mode |= CS_ODD_PRIMARY;
+
+ /* Asymmetric dual-rank DIMM support. */
+ if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
+ cs_mode |= CS_ODD_SECONDARY;
+
+ return cs_mode;
}
static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
{
- int dimm, size0, size1, cs0, cs1;
+ int dimm, size0, size1, cs0, cs1, cs_mode;
edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
- for (dimm = 0; dimm < 4; dimm++) {
- size0 = 0;
+ for (dimm = 0; dimm < 2; dimm++) {
cs0 = dimm * 2;
-
- if (csrow_enabled(cs0, ctrl, pvt))
- size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
-
- size1 = 0;
cs1 = dimm * 2 + 1;
- if (csrow_enabled(cs1, ctrl, pvt)) {
- /*
- * CS interleaving is only supported if both CSes have
- * the same amount of memory. Because they are
- * interleaved, it will look like both CSes have the
- * full amount of memory. Save the size for both as
- * half the amount we found on CS0, if interleaved.
- */
- if (f17_cs_interleaved(pvt, ctrl, cs1))
- size1 = size0 = (size0 >> 1);
- else
- size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
- }
+ cs_mode = f17_get_cs_mode(dimm, ctrl, pvt);
+
+ size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0);
+ size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1);
amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
cs0, size0,
@@ -942,89 +936,119 @@ static void prep_chip_selects(struct amd64_pvt *pvt)
} else if (pvt->fam == 0x15 && pvt->model == 0x30) {
pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
+ } else if (pvt->fam >= 0x17) {
+ int umc;
+
+ for_each_umc(umc) {
+ pvt->csels[umc].b_cnt = 4;
+ pvt->csels[umc].m_cnt = 2;
+ }
+
} else {
pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;
}
}
+static void read_umc_base_mask(struct amd64_pvt *pvt)
+{
+ u32 umc_base_reg, umc_base_reg_sec;
+ u32 umc_mask_reg, umc_mask_reg_sec;
+ u32 base_reg, base_reg_sec;
+ u32 mask_reg, mask_reg_sec;
+ u32 *base, *base_sec;
+ u32 *mask, *mask_sec;
+ int cs, umc;
+
+ for_each_umc(umc) {
+ umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR;
+ umc_base_reg_sec = get_umc_base(umc) + UMCCH_BASE_ADDR_SEC;
+
+ for_each_chip_select(cs, umc, pvt) {
+ base = &pvt->csels[umc].csbases[cs];
+ base_sec = &pvt->csels[umc].csbases_sec[cs];
+
+ base_reg = umc_base_reg + (cs * 4);
+ base_reg_sec = umc_base_reg_sec + (cs * 4);
+
+ if (!amd_smn_read(pvt->mc_node_id, base_reg, base))
+ edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *base, base_reg);
+
+ if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, base_sec))
+ edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *base_sec, base_reg_sec);
+ }
+
+ umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK;
+ umc_mask_reg_sec = get_umc_base(umc) + UMCCH_ADDR_MASK_SEC;
+
+ for_each_chip_select_mask(cs, umc, pvt) {
+ mask = &pvt->csels[umc].csmasks[cs];
+ mask_sec = &pvt->csels[umc].csmasks_sec[cs];
+
+ mask_reg = umc_mask_reg + (cs * 4);
+ mask_reg_sec = umc_mask_reg_sec + (cs * 4);
+
+ if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask))
+ edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *mask, mask_reg);
+
+ if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, mask_sec))
+ edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *mask_sec, mask_reg_sec);
+ }
+ }
+}
+
/*
* Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers
*/
static void read_dct_base_mask(struct amd64_pvt *pvt)
{
- int base_reg0, base_reg1, mask_reg0, mask_reg1, cs;
+ int cs;
prep_chip_selects(pvt);
- if (pvt->umc) {
- base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR;
- base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR;
- mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK;
- mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK;
- } else {
- base_reg0 = DCSB0;
- base_reg1 = DCSB1;
- mask_reg0 = DCSM0;
- mask_reg1 = DCSM1;
- }
+ if (pvt->umc)
+ return read_umc_base_mask(pvt);
for_each_chip_select(cs, 0, pvt) {
- int reg0 = base_reg0 + (cs * 4);
- int reg1 = base_reg1 + (cs * 4);
+ int reg0 = DCSB0 + (cs * 4);
+ int reg1 = DCSB1 + (cs * 4);
u32 *base0 = &pvt->csels[0].csbases[cs];
u32 *base1 = &pvt->csels[1].csbases[cs];
- if (pvt->umc) {
- if (!amd_smn_read(pvt->mc_node_id, reg0, base0))
- edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n",
- cs, *base0, reg0);
+ if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
+ edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
+ cs, *base0, reg0);
- if (!amd_smn_read(pvt->mc_node_id, reg1, base1))
- edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n",
- cs, *base1, reg1);
- } else {
- if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
- edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
- cs, *base0, reg0);
-
- if (pvt->fam == 0xf)
- continue;
+ if (pvt->fam == 0xf)
+ continue;
- if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
- edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",
- cs, *base1, (pvt->fam == 0x10) ? reg1
- : reg0);
- }
+ if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
+ edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",
+ cs, *base1, (pvt->fam == 0x10) ? reg1
+ : reg0);
}
for_each_chip_select_mask(cs, 0, pvt) {
- int reg0 = mask_reg0 + (cs * 4);
- int reg1 = mask_reg1 + (cs * 4);
+ int reg0 = DCSM0 + (cs * 4);
+ int reg1 = DCSM1 + (cs * 4);
u32 *mask0 = &pvt->csels[0].csmasks[cs];
u32 *mask1 = &pvt->csels[1].csmasks[cs];
- if (pvt->umc) {
- if (!amd_smn_read(pvt->mc_node_id, reg0, mask0))
- edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n",
- cs, *mask0, reg0);
-
- if (!amd_smn_read(pvt->mc_node_id, reg1, mask1))
- edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n",
- cs, *mask1, reg1);
- } else {
- if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
- edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
- cs, *mask0, reg0);
+ if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
+ edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
+ cs, *mask0, reg0);
- if (pvt->fam == 0xf)
- continue;
+ if (pvt->fam == 0xf)
+ continue;
- if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
- edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",
- cs, *mask1, (pvt->fam == 0x10) ? reg1
- : reg0);
- }
+ if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
+ edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",
+ cs, *mask1, (pvt->fam == 0x10) ? reg1
+ : reg0);
}
}
@@ -1556,18 +1580,58 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
return ddr3_cs_size(cs_mode, false);
}
-static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc,
+static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
unsigned int cs_mode, int csrow_nr)
{
- u32 base_addr = pvt->csels[umc].csbases[csrow_nr];
+ u32 addr_mask_orig, addr_mask_deinterleaved;
+ u32 msb, weight, num_zero_bits;
+ int dimm, size = 0;
- /* Each mask is used for every two base addresses. */
- u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1];
+ /* No Chip Selects are enabled. */
+ if (!cs_mode)
+ return size;
- /* Register [31:1] = Address [39:9]. Size is in kBs here. */
- u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1;
+ /* Requested size of an even CS but none are enabled. */
+ if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
+ return size;
- edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask);
+ /* Requested size of an odd CS but none are enabled. */
+ if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
+ return size;
+
+ /*
+ * There is one mask per DIMM, and two Chip Selects per DIMM.
+ * CS0 and CS1 -> DIMM0
+ * CS2 and CS3 -> DIMM1
+ */
+ dimm = csrow_nr >> 1;
+
+ /* Asymmetric dual-rank DIMM support. */
+ if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
+ addr_mask_orig = pvt->csels[umc].csmasks_sec[dimm];
+ else
+ addr_mask_orig = pvt->csels[umc].csmasks[dimm];
+
+ /*
+ * The number of zero bits in the mask is equal to the number of bits
+ * in a full mask minus the number of bits in the current mask.
+ *
+ * The MSB is the number of bits in the full mask because BIT[0] is
+ * always 0.
+ */
+ msb = fls(addr_mask_orig) - 1;
+ weight = hweight_long(addr_mask_orig);
+ num_zero_bits = msb - weight;
+
+ /* Take the number of zero bits off from the top of the mask. */
+ addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
+
+ edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
+ edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
+ edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
+
+ /* Register [31:1] = Address [39:9]. Size is in kBs here. */
+ size = (addr_mask_deinterleaved >> 2) + 1;
/* Return size in MBs. */
return size >> 10;
@@ -2232,7 +2296,7 @@ static struct amd64_family_type family_types[] = {
.f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6,
.ops = {
.early_channel_count = f17_early_channel_count,
- .dbam_to_cs = f17_base_addr_to_cs_size,
+ .dbam_to_cs = f17_addr_mask_to_cs_size,
}
},
[F17_M10H_CPUS] = {
@@ -2241,7 +2305,7 @@ static struct amd64_family_type family_types[] = {
.f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6,
.ops = {
.early_channel_count = f17_early_channel_count,
- .dbam_to_cs = f17_base_addr_to_cs_size,
+ .dbam_to_cs = f17_addr_mask_to_cs_size,
}
},
[F17_M30H_CPUS] = {
@@ -2250,7 +2314,16 @@ static struct amd64_family_type family_types[] = {
.f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6,
.ops = {
.early_channel_count = f17_early_channel_count,
- .dbam_to_cs = f17_base_addr_to_cs_size,
+ .dbam_to_cs = f17_addr_mask_to_cs_size,
+ }
+ },
+ [F17_M70H_CPUS] = {
+ .ctl_name = "F17h_M70h",
+ .f0_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F0,
+ .f6_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F6,
+ .ops = {
+ .early_channel_count = f17_early_channel_count,
+ .dbam_to_cs = f17_addr_mask_to_cs_size,
}
},
};
@@ -2537,13 +2610,6 @@ static void decode_umc_error(int node_id, struct mce *m)
err.channel = find_umc_channel(m);
- if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
- err.err_code = ERR_NORM_ADDR;
- goto log_error;
- }
-
- error_address_to_page_and_offset(sys_addr, &err);
-
if (!(m->status & MCI_STATUS_SYNDV)) {
err.err_code = ERR_SYND;
goto log_error;
@@ -2560,6 +2626,13 @@ static void decode_umc_error(int node_id, struct mce *m)
err.csrow = m->synd & 0x7;
+ if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
+ err.err_code = ERR_NORM_ADDR;
+ goto log_error;
+ }
+
+ error_address_to_page_and_offset(sys_addr, &err);
+
log_error:
__log_ecc_error(mci, &err, ecc_type);
}
@@ -2809,10 +2882,12 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
int csrow_nr = csrow_nr_orig;
u32 cs_mode, nr_pages;
- if (!pvt->umc)
+ if (!pvt->umc) {
csrow_nr >>= 1;
-
- cs_mode = DBAM_DIMM(csrow_nr, dbam);
+ cs_mode = DBAM_DIMM(csrow_nr, dbam);
+ } else {
+ cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt);
+ }
nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
nr_pages <<= 20 - PAGE_SHIFT;
@@ -2824,6 +2899,49 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
return nr_pages;
}
+static int init_csrows_df(struct mem_ctl_info *mci)
+{
+ struct amd64_pvt *pvt = mci->pvt_info;
+ enum edac_type edac_mode = EDAC_NONE;
+ enum dev_type dev_type = DEV_UNKNOWN;
+ struct dimm_info *dimm;
+ int empty = 1;
+ u8 umc, cs;
+
+ if (mci->edac_ctl_cap & EDAC_FLAG_S16ECD16ED) {
+ edac_mode = EDAC_S16ECD16ED;
+ dev_type = DEV_X16;
+ } else if (mci->edac_ctl_cap & EDAC_FLAG_S8ECD8ED) {
+ edac_mode = EDAC_S8ECD8ED;
+ dev_type = DEV_X8;
+ } else if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) {
+ edac_mode = EDAC_S4ECD4ED;
+ dev_type = DEV_X4;
+ } else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) {
+ edac_mode = EDAC_SECDED;
+ }
+
+ for_each_umc(umc) {
+ for_each_chip_select(cs, umc, pvt) {
+ if (!csrow_enabled(cs, umc, pvt))
+ continue;
+
+ empty = 0;
+ dimm = mci->csrows[cs]->channels[umc]->dimm;
+
+ edac_dbg(1, "MC node: %d, csrow: %d\n",
+ pvt->mc_node_id, cs);
+
+ dimm->nr_pages = get_csrow_nr_pages(pvt, umc, cs);
+ dimm->mtype = pvt->dram_type;
+ dimm->edac_mode = edac_mode;
+ dimm->dtype = dev_type;
+ }
+ }
+
+ return empty;
+}
+
/*
* Initialize the array of csrow attribute instances, based on the values
* from pci config hardware registers.
@@ -2838,15 +2956,16 @@ static int init_csrows(struct mem_ctl_info *mci)
int nr_pages = 0;
u32 val;
- if (!pvt->umc) {
- amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
+ if (pvt->umc)
+ return init_csrows_df(mci);
- pvt->nbcfg = val;
+ amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
- edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
- pvt->mc_node_id, val,
- !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
- }
+ pvt->nbcfg = val;
+
+ edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+ pvt->mc_node_id, val,
+ !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
/*
* We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
@@ -2883,13 +3002,7 @@ static int init_csrows(struct mem_ctl_info *mci)
edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
/* Determine DIMM ECC mode: */
- if (pvt->umc) {
- if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED)
- edac_mode = EDAC_S4ECD4ED;
- else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED)
- edac_mode = EDAC_SECDED;
-
- } else if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
+ if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL)
? EDAC_S4ECD4ED
: EDAC_SECDED;
@@ -3137,12 +3250,15 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
static inline void
f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
{
- u8 i, ecc_en = 1, cpk_en = 1;
+ u8 i, ecc_en = 1, cpk_en = 1, dev_x4 = 1, dev_x16 = 1;
for_each_umc(i) {
if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {
ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED);
cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP);
+
+ dev_x4 &= !!(pvt->umc[i].dimm_cfg & BIT(6));
+ dev_x16 &= !!(pvt->umc[i].dimm_cfg & BIT(7));
}
}
@@ -3150,8 +3266,15 @@ f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
if (ecc_en) {
mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
- if (cpk_en)
+ if (!cpk_en)
+ return;
+
+ if (dev_x4)
mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+ else if (dev_x16)
+ mci->edac_ctl_cap |= EDAC_FLAG_S16ECD16ED;
+ else
+ mci->edac_ctl_cap |= EDAC_FLAG_S8ECD8ED;
}
}
@@ -3241,6 +3364,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
fam_type = &family_types[F17_M30H_CPUS];
pvt->ops = &family_types[F17_M30H_CPUS].ops;
break;
+ } else if (pvt->model >= 0x70 && pvt->model <= 0x7f) {
+ fam_type = &family_types[F17_M70H_CPUS];
+ pvt->ops = &family_types[F17_M70H_CPUS].ops;
+ break;
}
/* fall through */
case 0x18:
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 8f66472f7adc..8c3cda81e619 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -96,6 +96,7 @@
/* Hardware limit on ChipSelect rows per MC and processors per system */
#define NUM_CHIPSELECTS 8
#define DRAM_RANGES 8
+#define NUM_CONTROLLERS 8
#define ON true
#define OFF false
@@ -119,6 +120,8 @@
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F0 0x1490
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F6 0x1496
+#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F0 0x1440
+#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F6 0x1446
/*
* Function 1 - Address Map
@@ -168,7 +171,8 @@
#define DCSM0 0x60
#define DCSM1 0x160
-#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
+#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
+#define csrow_sec_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases_sec[(i)] & DCSB_CS_ENABLE)
#define DRAM_CONTROL 0x78
@@ -258,7 +262,9 @@
/* UMC CH register offsets */
#define UMCCH_BASE_ADDR 0x0
+#define UMCCH_BASE_ADDR_SEC 0x10
#define UMCCH_ADDR_MASK 0x20
+#define UMCCH_ADDR_MASK_SEC 0x28
#define UMCCH_ADDR_CFG 0x30
#define UMCCH_DIMM_CFG 0x80
#define UMCCH_UMC_CFG 0x100
@@ -285,6 +291,7 @@ enum amd_families {
F17_CPUS,
F17_M10H_CPUS,
F17_M30H_CPUS,
+ F17_M70H_CPUS,
NUM_FAMILIES,
};
@@ -311,9 +318,11 @@ struct dram_range {
/* A DCT chip selects collection */
struct chip_select {
u32 csbases[NUM_CHIPSELECTS];
+ u32 csbases_sec[NUM_CHIPSELECTS];
u8 b_cnt;
u32 csmasks[NUM_CHIPSELECTS];
+ u32 csmasks_sec[NUM_CHIPSELECTS];
u8 m_cnt;
};
@@ -351,8 +360,8 @@ struct amd64_pvt {
u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */
u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */
- /* one for each DCT */
- struct chip_select csels[2];
+ /* one for each DCT/UMC */
+ struct chip_select csels[NUM_CONTROLLERS];
/* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */
struct dram_range ranges[DRAM_RANGES];
diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
new file mode 100644
index 000000000000..e4736eb37bfb
--- /dev/null
+++ b/drivers/edac/bluefield_edac.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Bluefield-specific EDAC driver.
+ *
+ * Copyright (c) 2019 Mellanox Technologies.
+ */
+
+#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
+#include <linux/edac.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "edac_module.h"
+
+#define DRIVER_NAME "bluefield-edac"
+
+/*
+ * Mellanox BlueField EMI (External Memory Interface) register definitions.
+ */
+
+#define MLXBF_ECC_CNT 0x340
+#define MLXBF_ECC_CNT__SERR_CNT GENMASK(15, 0)
+#define MLXBF_ECC_CNT__DERR_CNT GENMASK(31, 16)
+
+#define MLXBF_ECC_ERR 0x348
+#define MLXBF_ECC_ERR__SECC BIT(0)
+#define MLXBF_ECC_ERR__DECC BIT(16)
+
+#define MLXBF_ECC_LATCH_SEL 0x354
+#define MLXBF_ECC_LATCH_SEL__START BIT(24)
+
+#define MLXBF_ERR_ADDR_0 0x358
+
+#define MLXBF_ERR_ADDR_1 0x37c
+
+#define MLXBF_SYNDROM 0x35c
+#define MLXBF_SYNDROM__DERR BIT(0)
+#define MLXBF_SYNDROM__SERR BIT(1)
+#define MLXBF_SYNDROM__SYN GENMASK(25, 16)
+
+#define MLXBF_ADD_INFO 0x364
+#define MLXBF_ADD_INFO__ERR_PRANK GENMASK(9, 8)
+
+#define MLXBF_EDAC_MAX_DIMM_PER_MC 2
+#define MLXBF_EDAC_ERROR_GRAIN 8
+
+/*
+ * Request MLNX_SIP_GET_DIMM_INFO
+ *
+ * Retrieve information about DIMM on a certain slot.
+ *
+ * Call register usage:
+ * a0: MLNX_SIP_GET_DIMM_INFO
+ * a1: (Memory controller index) << 16 | (Dimm index in memory controller)
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: MLXBF_DIMM_INFO defined below describing the DIMM.
+ * a1-3: not used.
+ */
+#define MLNX_SIP_GET_DIMM_INFO 0x82000008
+
+/* Format for the SMC response about the memory information */
+#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0)
+#define MLXBF_DIMM_INFO__IS_RDIMM BIT(16)
+#define MLXBF_DIMM_INFO__IS_LRDIMM BIT(17)
+#define MLXBF_DIMM_INFO__IS_NVDIMM BIT(18)
+#define MLXBF_DIMM_INFO__RANKS GENMASK_ULL(23, 21)
+#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24)
+
+struct bluefield_edac_priv {
+ int dimm_ranks[MLXBF_EDAC_MAX_DIMM_PER_MC];
+ void __iomem *emi_base;
+ int dimm_per_mc;
+};
+
+static u64 smc_call1(u64 smc_op, u64 smc_arg)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res);
+
+ return res.a0;
+}
+
+/*
+ * Gather the ECC information from the External Memory Interface registers
+ * and report it to the edac handler.
+ */
+static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
+ int error_cnt,
+ int is_single_ecc)
+{
+ struct bluefield_edac_priv *priv = mci->pvt_info;
+ u32 dram_additional_info, err_prank, edea0, edea1;
+ u32 ecc_latch_select, dram_syndrom, serr, derr, syndrom;
+ enum hw_event_mc_err_type ecc_type;
+ u64 ecc_dimm_addr;
+ int ecc_dimm;
+
+ ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED :
+ HW_EVENT_ERR_UNCORRECTED;
+
+ /*
+ * Tell the External Memory Interface to populate the relevant
+ * registers with information about the last ECC error occurrence.
+ */
+ ecc_latch_select = MLXBF_ECC_LATCH_SEL__START;
+ writel(ecc_latch_select, priv->emi_base + MLXBF_ECC_LATCH_SEL);
+
+ /*
+ * Verify that the ECC reported info in the registers is of the
+ * same type as the one asked to report. If not, just report the
+ * error without the detailed information.
+ */
+ dram_syndrom = readl(priv->emi_base + MLXBF_SYNDROM);
+ serr = FIELD_GET(MLXBF_SYNDROM__SERR, dram_syndrom);
+ derr = FIELD_GET(MLXBF_SYNDROM__DERR, dram_syndrom);
+ syndrom = FIELD_GET(MLXBF_SYNDROM__SYN, dram_syndrom);
+
+ if ((is_single_ecc && !serr) || (!is_single_ecc && !derr)) {
+ edac_mc_handle_error(ecc_type, mci, error_cnt, 0, 0, 0,
+ 0, 0, -1, mci->ctl_name, "");
+ return;
+ }
+
+ dram_additional_info = readl(priv->emi_base + MLXBF_ADD_INFO);
+ err_prank = FIELD_GET(MLXBF_ADD_INFO__ERR_PRANK, dram_additional_info);
+
+ ecc_dimm = (err_prank >= 2 && priv->dimm_ranks[0] <= 2) ? 1 : 0;
+
+ edea0 = readl(priv->emi_base + MLXBF_ERR_ADDR_0);
+ edea1 = readl(priv->emi_base + MLXBF_ERR_ADDR_1);
+
+ ecc_dimm_addr = ((u64)edea1 << 32) | edea0;
+
+ edac_mc_handle_error(ecc_type, mci, error_cnt,
+ PFN_DOWN(ecc_dimm_addr),
+ offset_in_page(ecc_dimm_addr),
+ syndrom, ecc_dimm, 0, 0, mci->ctl_name, "");
+}
+
+static void bluefield_edac_check(struct mem_ctl_info *mci)
+{
+ struct bluefield_edac_priv *priv = mci->pvt_info;
+ u32 ecc_count, single_error_count, double_error_count, ecc_error = 0;
+
+ /*
+ * The memory controller might not be initialized by the firmware
+ * when there isn't memory, which may lead to bad register readings.
+ */
+ if (mci->edac_cap == EDAC_FLAG_NONE)
+ return;
+
+ ecc_count = readl(priv->emi_base + MLXBF_ECC_CNT);
+ single_error_count = FIELD_GET(MLXBF_ECC_CNT__SERR_CNT, ecc_count);
+ double_error_count = FIELD_GET(MLXBF_ECC_CNT__DERR_CNT, ecc_count);
+
+ if (single_error_count) {
+ ecc_error |= MLXBF_ECC_ERR__SECC;
+
+ bluefield_gather_report_ecc(mci, single_error_count, 1);
+ }
+
+ if (double_error_count) {
+ ecc_error |= MLXBF_ECC_ERR__DECC;
+
+ bluefield_gather_report_ecc(mci, double_error_count, 0);
+ }
+
+ /* Write to clear reported errors. */
+ if (ecc_count)
+ writel(ecc_error, priv->emi_base + MLXBF_ECC_ERR);
+}
+
+/* Initialize the DIMMs information for the given memory controller. */
+static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
+{
+ struct bluefield_edac_priv *priv = mci->pvt_info;
+ int mem_ctrl_idx = mci->mc_idx;
+ struct dimm_info *dimm;
+ u64 smc_info, smc_arg;
+ int is_empty = 1, i;
+
+ for (i = 0; i < priv->dimm_per_mc; i++) {
+ dimm = mci->dimms[i];
+
+ smc_arg = mem_ctrl_idx << 16 | i;
+ smc_info = smc_call1(MLNX_SIP_GET_DIMM_INFO, smc_arg);
+
+ if (!FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info)) {
+ dimm->mtype = MEM_EMPTY;
+ continue;
+ }
+
+ is_empty = 0;
+
+ dimm->edac_mode = EDAC_SECDED;
+
+ if (FIELD_GET(MLXBF_DIMM_INFO__IS_NVDIMM, smc_info))
+ dimm->mtype = MEM_NVDIMM;
+ else if (FIELD_GET(MLXBF_DIMM_INFO__IS_LRDIMM, smc_info))
+ dimm->mtype = MEM_LRDDR4;
+ else if (FIELD_GET(MLXBF_DIMM_INFO__IS_RDIMM, smc_info))
+ dimm->mtype = MEM_RDDR4;
+ else
+ dimm->mtype = MEM_DDR4;
+
+ dimm->nr_pages =
+ FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info) *
+ (SZ_1G / PAGE_SIZE);
+ dimm->grain = MLXBF_EDAC_ERROR_GRAIN;
+
+ /* Mem controller for BlueField only supports x4, x8 and x16 */
+ switch (FIELD_GET(MLXBF_DIMM_INFO__PACKAGE_X, smc_info)) {
+ case 4:
+ dimm->dtype = DEV_X4;
+ break;
+ case 8:
+ dimm->dtype = DEV_X8;
+ break;
+ case 16:
+ dimm->dtype = DEV_X16;
+ break;
+ default:
+ dimm->dtype = DEV_UNKNOWN;
+ }
+
+ priv->dimm_ranks[i] =
+ FIELD_GET(MLXBF_DIMM_INFO__RANKS, smc_info);
+ }
+
+ if (is_empty)
+ mci->edac_cap = EDAC_FLAG_NONE;
+ else
+ mci->edac_cap = EDAC_FLAG_SECDED;
+}
+
+static int bluefield_edac_mc_probe(struct platform_device *pdev)
+{
+ struct bluefield_edac_priv *priv;
+ struct device *dev = &pdev->dev;
+ struct edac_mc_layer layers[1];
+ struct mem_ctl_info *mci;
+ struct resource *emi_res;
+ unsigned int mc_idx, dimm_count;
+ int rc, ret;
+
+ /* Read the MSS (Memory SubSystem) index from ACPI table. */
+ if (device_property_read_u32(dev, "mss_number", &mc_idx)) {
+ dev_warn(dev, "bf_edac: MSS number unknown\n");
+ return -EINVAL;
+ }
+
+ /* Read the DIMMs per MC from ACPI table. */
+ if (device_property_read_u32(dev, "dimm_per_mc", &dimm_count)) {
+ dev_warn(dev, "bf_edac: DIMMs per MC unknown\n");
+ return -EINVAL;
+ }
+
+ if (dimm_count > MLXBF_EDAC_MAX_DIMM_PER_MC) {
+ dev_warn(dev, "bf_edac: DIMMs per MC not valid\n");
+ return -EINVAL;
+ }
+
+ emi_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!emi_res)
+ return -EINVAL;
+
+ layers[0].type = EDAC_MC_LAYER_SLOT;
+ layers[0].size = dimm_count;
+ layers[0].is_virt_csrow = true;
+
+ mci = edac_mc_alloc(mc_idx, ARRAY_SIZE(layers), layers, sizeof(*priv));
+ if (!mci)
+ return -ENOMEM;
+
+ priv = mci->pvt_info;
+
+ priv->dimm_per_mc = dimm_count;
+ priv->emi_base = devm_ioremap_resource(dev, emi_res);
+ if (IS_ERR(priv->emi_base)) {
+ dev_err(dev, "failed to map EMI IO resource\n");
+ ret = PTR_ERR(priv->emi_base);
+ goto err;
+ }
+
+ mci->pdev = dev;
+ mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_RDDR4 |
+ MEM_FLAG_LRDDR4 | MEM_FLAG_NVDIMM;
+ mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+
+ mci->mod_name = DRIVER_NAME;
+ mci->ctl_name = "BlueField_Memory_Controller";
+ mci->dev_name = dev_name(dev);
+ mci->edac_check = bluefield_edac_check;
+
+ /* Initialize mci with the actual populated DIMM information. */
+ bluefield_edac_init_dimms(mci);
+
+ platform_set_drvdata(pdev, mci);
+
+ /* Register with EDAC core */
+ rc = edac_mc_add_mc(mci);
+ if (rc) {
+ dev_err(dev, "failed to register with EDAC core\n");
+ ret = rc;
+ goto err;
+ }
+
+ /* Only POLL mode supported so far. */
+ edac_op_state = EDAC_OPSTATE_POLL;
+
+ return 0;
+
+err:
+ edac_mc_free(mci);
+
+ return ret;
+
+}
+
+static int bluefield_edac_mc_remove(struct platform_device *pdev)
+{
+ struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+ edac_mc_del_mc(&pdev->dev);
+ edac_mc_free(mci);
+
+ return 0;
+}
+
+static const struct acpi_device_id bluefield_mc_acpi_ids[] = {
+ {"MLNXBF08", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(acpi, bluefield_mc_acpi_ids);
+
+static struct platform_driver bluefield_edac_mc_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .acpi_match_table = bluefield_mc_acpi_ids,
+ },
+ .probe = bluefield_edac_mc_probe,
+ .remove = bluefield_edac_mc_remove,
+};
+
+module_platform_driver(bluefield_edac_mc_driver);
+
+MODULE_DESCRIPTION("Mellanox BlueField memory edac driver");
+MODULE_AUTHOR("Mellanox Technologies");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 64922c8fa7e3..e6fd079783bd 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -114,8 +114,8 @@ static const struct kernel_param_ops edac_report_ops = {
module_param_cb(edac_report, &edac_report_ops, &edac_report, 0644);
-unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
- unsigned len)
+unsigned int edac_dimm_info_location(struct dimm_info *dimm, char *buf,
+ unsigned int len)
{
struct mem_ctl_info *mci = dimm->mci;
int i, n, count = 0;
@@ -236,9 +236,9 @@ EXPORT_SYMBOL_GPL(edac_mem_types);
* At return, the pointer 'p' will be incremented to be used on a next call
* to this function.
*/
-void *edac_align_ptr(void **p, unsigned size, int n_elems)
+void *edac_align_ptr(void **p, unsigned int size, int n_elems)
{
- unsigned align, r;
+ unsigned int align, r;
void *ptr = *p;
*p += size * n_elems;
@@ -275,38 +275,37 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems)
static void _edac_mc_free(struct mem_ctl_info *mci)
{
- int i, chn, row;
struct csrow_info *csr;
- const unsigned int tot_dimms = mci->tot_dimms;
- const unsigned int tot_channels = mci->num_cschannel;
- const unsigned int tot_csrows = mci->nr_csrows;
+ int i, chn, row;
if (mci->dimms) {
- for (i = 0; i < tot_dimms; i++)
+ for (i = 0; i < mci->tot_dimms; i++)
kfree(mci->dimms[i]);
kfree(mci->dimms);
}
+
if (mci->csrows) {
- for (row = 0; row < tot_csrows; row++) {
+ for (row = 0; row < mci->nr_csrows; row++) {
csr = mci->csrows[row];
- if (csr) {
- if (csr->channels) {
- for (chn = 0; chn < tot_channels; chn++)
- kfree(csr->channels[chn]);
- kfree(csr->channels);
- }
- kfree(csr);
+ if (!csr)
+ continue;
+
+ if (csr->channels) {
+ for (chn = 0; chn < mci->num_cschannel; chn++)
+ kfree(csr->channels[chn]);
+ kfree(csr->channels);
}
+ kfree(csr);
}
kfree(mci->csrows);
}
kfree(mci);
}
-struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
- unsigned n_layers,
+struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
+ unsigned int n_layers,
struct edac_mc_layer *layers,
- unsigned sz_pvt)
+ unsigned int sz_pvt)
{
struct mem_ctl_info *mci;
struct edac_mc_layer *layer;
@@ -314,9 +313,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
struct rank_info *chan;
struct dimm_info *dimm;
u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS];
- unsigned pos[EDAC_MAX_LAYERS];
- unsigned size, tot_dimms = 1, count = 1;
- unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
+ unsigned int pos[EDAC_MAX_LAYERS];
+ unsigned int size, tot_dimms = 1, count = 1;
+ unsigned int tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
void *pvt, *p, *ptr = NULL;
int i, j, row, chn, n, len, off;
bool per_rank = false;
@@ -1235,9 +1234,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
if (p > e->location)
*(p - 1) = '\0';
- /* Report the error via the trace interface */
- grain_bits = fls_long(e->grain) + 1;
+ /* Sanity-check driver-supplied grain value. */
+ if (WARN_ON_ONCE(!e->grain))
+ e->grain = 1;
+ grain_bits = fls_long(e->grain - 1);
+
+ /* Report the error via the trace interface */
if (IS_ENABLED(CONFIG_RAS))
trace_mc_event(type, e->msg, e->label, e->error_count,
mci->mc_idx, e->top_layer, e->mid_layer,
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index 4165e15995ad..02aac5c61d00 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -122,10 +122,10 @@ do { \
* On success, return a pointer to struct mem_ctl_info pointer;
* %NULL otherwise
*/
-struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
- unsigned n_layers,
+struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
+ unsigned int n_layers,
struct edac_mc_layer *layers,
- unsigned sz_pvt);
+ unsigned int sz_pvt);
/**
* edac_get_owner - Return the owner's mod_name of EDAC MC
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 4386ea4b9b5a..32d016f1ecd1 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -131,7 +131,7 @@ static const char * const edac_caps[] = {
struct dev_ch_attribute {
struct device_attribute attr;
- int channel;
+ unsigned int channel;
};
#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \
@@ -200,7 +200,7 @@ static ssize_t channel_dimm_label_show(struct device *dev,
char *data)
{
struct csrow_info *csrow = to_csrow(dev);
- unsigned chan = to_channel(mattr);
+ unsigned int chan = to_channel(mattr);
struct rank_info *rank = csrow->channels[chan];
/* if field has not been initialized, there is nothing to send */
@@ -216,7 +216,7 @@ static ssize_t channel_dimm_label_store(struct device *dev,
const char *data, size_t count)
{
struct csrow_info *csrow = to_csrow(dev);
- unsigned chan = to_channel(mattr);
+ unsigned int chan = to_channel(mattr);
struct rank_info *rank = csrow->channels[chan];
size_t copy_count = count;
@@ -240,7 +240,7 @@ static ssize_t channel_ce_count_show(struct device *dev,
struct device_attribute *mattr, char *data)
{
struct csrow_info *csrow = to_csrow(dev);
- unsigned chan = to_channel(mattr);
+ unsigned int chan = to_channel(mattr);
struct rank_info *rank = csrow->channels[chan];
return sprintf(data, "%u\n", rank->ce_count);
@@ -278,7 +278,7 @@ static void csrow_attr_release(struct device *dev)
{
struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
- edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev));
+ edac_dbg(1, "device %s released\n", dev_name(dev));
kfree(csrow);
}
@@ -414,14 +414,16 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
dev_set_name(&csrow->dev, "csrow%d", index);
dev_set_drvdata(&csrow->dev, csrow);
- edac_dbg(0, "creating (virtual) csrow node %s\n",
- dev_name(&csrow->dev));
-
err = device_add(&csrow->dev);
- if (err)
+ if (err) {
+ edac_dbg(1, "failure: create device %s\n", dev_name(&csrow->dev));
put_device(&csrow->dev);
+ return err;
+ }
- return err;
+ edac_dbg(0, "device %s created\n", dev_name(&csrow->dev));
+
+ return 0;
}
/* Create a CSROW object under specifed edac_mc_device */
@@ -435,12 +437,8 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
if (!nr_pages_per_csrow(csrow))
continue;
err = edac_create_csrow_object(mci, mci->csrows[i], i);
- if (err < 0) {
- edac_dbg(1,
- "failure: create csrow objects for csrow %d\n",
- i);
+ if (err < 0)
goto error;
- }
}
return 0;
@@ -624,7 +622,7 @@ static void dimm_attr_release(struct device *dev)
{
struct dimm_info *dimm = container_of(dev, struct dimm_info, dev);
- edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev));
+ edac_dbg(1, "device %s released\n", dev_name(dev));
kfree(dimm);
}
@@ -653,12 +651,21 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,
pm_runtime_forbid(&mci->dev);
err = device_add(&dimm->dev);
- if (err)
+ if (err) {
+ edac_dbg(1, "failure: create device %s\n", dev_name(&dimm->dev));
put_device(&dimm->dev);
+ return err;
+ }
- edac_dbg(0, "created rank/dimm device %s\n", dev_name(&dimm->dev));
+ if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
+ char location[80];
- return err;
+ edac_dimm_info_location(dimm, location, sizeof(location));
+ edac_dbg(0, "device %s created at location %s\n",
+ dev_name(&dimm->dev), location);
+ }
+
+ return 0;
}
/*
@@ -901,7 +908,7 @@ static void mci_attr_release(struct device *dev)
{
struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);
- edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev));
+ edac_dbg(1, "device %s released\n", dev_name(dev));
kfree(mci);
}
@@ -933,14 +940,15 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
dev_set_drvdata(&mci->dev, mci);
pm_runtime_forbid(&mci->dev);
- edac_dbg(0, "creating device %s\n", dev_name(&mci->dev));
err = device_add(&mci->dev);
if (err < 0) {
edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
put_device(&mci->dev);
- goto out;
+ return err;
}
+ edac_dbg(0, "device %s created\n", dev_name(&mci->dev));
+
/*
* Create the dimm/rank devices
*/
@@ -950,22 +958,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
if (!dimm->nr_pages)
continue;
-#ifdef CONFIG_EDAC_DEBUG
- edac_dbg(1, "creating dimm%d, located at ", i);
- if (edac_debug_level >= 1) {
- int lay;
- for (lay = 0; lay < mci->n_layers; lay++)
- printk(KERN_CONT "%s %d ",
- edac_layer_name[mci->layers[lay].type],
- dimm->location[lay]);
- printk(KERN_CONT "\n");
- }
-#endif
err = edac_create_dimm_object(mci, dimm, i);
- if (err) {
- edac_dbg(1, "failure: create dimm %d obj\n", i);
+ if (err)
goto fail_unregister_dimm;
- }
}
#ifdef CONFIG_EDAC_LEGACY_SYSFS
@@ -987,7 +982,6 @@ fail_unregister_dimm:
}
device_unregister(&mci->dev);
-out:
return err;
}
@@ -1011,14 +1005,14 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
struct dimm_info *dimm = mci->dimms[i];
if (dimm->nr_pages == 0)
continue;
- edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev));
+ edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev));
device_unregister(&dimm->dev);
}
}
void edac_unregister_sysfs(struct mem_ctl_info *mci)
{
- edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
+ edac_dbg(1, "unregistering device %s\n", dev_name(&mci->dev));
device_unregister(&mci->dev);
}
@@ -1029,7 +1023,7 @@ static void mc_attr_release(struct device *dev)
* parent device, used to create the /sys/devices/mc sysfs node.
* So, there are no attributes on it.
*/
- edac_dbg(1, "Releasing device %s\n", dev_name(dev));
+ edac_dbg(1, "device %s released\n", dev_name(dev));
kfree(dev);
}
@@ -1044,10 +1038,8 @@ int __init edac_mc_sysfs_init(void)
int err;
mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
- if (!mci_pdev) {
- err = -ENOMEM;
- goto out;
- }
+ if (!mci_pdev)
+ return -ENOMEM;
mci_pdev->bus = edac_get_sysfs_subsys();
mci_pdev->type = &mc_attr_type;
@@ -1055,17 +1047,15 @@ int __init edac_mc_sysfs_init(void)
dev_set_name(mci_pdev, "mc");
err = device_add(mci_pdev);
- if (err < 0)
- goto out_put_device;
+ if (err < 0) {
+ edac_dbg(1, "failure: create device %s\n", dev_name(mci_pdev));
+ put_device(mci_pdev);
+ return err;
+ }
edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
return 0;
-
- out_put_device:
- put_device(mci_pdev);
- out:
- return err;
}
void edac_mc_sysfs_exit(void)
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index 7f19f1c672c3..d413a0bdc9ad 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -68,7 +68,7 @@ struct memdev_dmi_entry {
struct ghes_edac_dimm_fill {
struct mem_ctl_info *mci;
- unsigned count;
+ unsigned int count;
};
static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg)
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index 83392f2841de..c370d5457e6b 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -123,9 +123,9 @@ static int i10nm_get_all_munits(void)
}
static const struct x86_cpu_id i10nm_cpuids[] = {
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_TREMONT_X, 0, 0 },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_TREMONT_D, 0, 0 },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_X, 0, 0 },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_XEON_D, 0, 0 },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_D, 0, 0 },
{ }
};
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index b506eef6b146..251f2b692785 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -417,7 +417,8 @@ static const char *i5100_err_msg(unsigned err)
}
/* convert csrow index into a rank (per channel -- 0..5) */
-static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
+static unsigned int i5100_csrow_to_rank(const struct mem_ctl_info *mci,
+ unsigned int csrow)
{
const struct i5100_priv *priv = mci->pvt_info;
@@ -425,7 +426,8 @@ static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
}
/* convert csrow index into a channel (0..1) */
-static int i5100_csrow_to_chan(const struct mem_ctl_info *mci, int csrow)
+static unsigned int i5100_csrow_to_chan(const struct mem_ctl_info *mci,
+ unsigned int csrow)
{
const struct i5100_priv *priv = mci->pvt_info;
@@ -653,11 +655,11 @@ static struct pci_dev *pci_get_device_func(unsigned vendor,
return ret;
}
-static unsigned long i5100_npages(struct mem_ctl_info *mci, int csrow)
+static unsigned long i5100_npages(struct mem_ctl_info *mci, unsigned int csrow)
{
struct i5100_priv *priv = mci->pvt_info;
- const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow);
- const unsigned chan = i5100_csrow_to_chan(mci, csrow);
+ const unsigned int chan_rank = i5100_csrow_to_rank(mci, csrow);
+ const unsigned int chan = i5100_csrow_to_chan(mci, csrow);
unsigned addr_lines;
/* dimm present? */
@@ -852,8 +854,8 @@ static void i5100_init_csrows(struct mem_ctl_info *mci)
for (i = 0; i < mci->tot_dimms; i++) {
struct dimm_info *dimm;
const unsigned long npages = i5100_npages(mci, i);
- const unsigned chan = i5100_csrow_to_chan(mci, i);
- const unsigned rank = i5100_csrow_to_rank(mci, i);
+ const unsigned int chan = i5100_csrow_to_chan(mci, i);
+ const unsigned int rank = i5100_csrow_to_rank(mci, i);
if (!npages)
continue;
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
index ca25f8fe57ef..b1193be1ef1d 100644
--- a/drivers/edac/pnd2_edac.c
+++ b/drivers/edac/pnd2_edac.c
@@ -260,11 +260,14 @@ static u64 get_sideband_reg_base_addr(void)
}
}
+#define DNV_MCHBAR_SIZE 0x8000
+#define DNV_SB_PORT_SIZE 0x10000
static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *name)
{
struct pci_dev *pdev;
char *base;
u64 addr;
+ unsigned long size;
if (op == 4) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x1980, NULL);
@@ -279,15 +282,17 @@ static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *na
addr = get_mem_ctrl_hub_base_addr();
if (!addr)
return -ENODEV;
+ size = DNV_MCHBAR_SIZE;
} else {
/* MMIO via sideband register base address */
addr = get_sideband_reg_base_addr();
if (!addr)
return -ENODEV;
addr += (port << 16);
+ size = DNV_SB_PORT_SIZE;
}
- base = ioremap((resource_size_t)addr, 0x10000);
+ base = ioremap((resource_size_t)addr, size);
if (!base)
return -ENODEV;
@@ -1533,7 +1538,7 @@ static struct dunit_ops dnv_ops = {
static const struct x86_cpu_id pnd2_cpuids[] = {
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT, 0, (kernel_ulong_t)&apl_ops },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_X, 0, (kernel_ulong_t)&dnv_ops },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_D, 0, (kernel_ulong_t)&dnv_ops },
{ }
};
MODULE_DEVICE_TABLE(x86cpu, pnd2_cpuids);
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 37746b045e18..f743502ca9b7 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -3429,7 +3429,7 @@ static const struct x86_cpu_id sbridge_cpuids[] = {
INTEL_CPU_FAM6(IVYBRIDGE_X, pci_dev_descr_ibridge_table),
INTEL_CPU_FAM6(HASWELL_X, pci_dev_descr_haswell_table),
INTEL_CPU_FAM6(BROADWELL_X, pci_dev_descr_broadwell_table),
- INTEL_CPU_FAM6(BROADWELL_XEON_D, pci_dev_descr_broadwell_table),
+ INTEL_CPU_FAM6(BROADWELL_D, pci_dev_descr_broadwell_table),
INTEL_CPU_FAM6(XEON_PHI_KNL, pci_dev_descr_knl_table),
INTEL_CPU_FAM6(XEON_PHI_KNM, pci_dev_descr_knl_table),
{ }
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 3dc1cbf849db..b785e936244f 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -957,7 +957,7 @@ static void set_broadcast_channel(struct fw_device *device, int generation)
device->bc_implemented = BC_IMPLEMENTED;
break;
}
- /* else fall through to case address error */
+ /* else, fall through - to case address error */
case RCODE_ADDRESS_ERROR:
device->bc_implemented = BC_UNIMPLEMENTED;
}
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 42566b7be8f5..df8a56a979b9 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -284,7 +284,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
if ((data[0] & bit) == (data[1] & bit))
continue;
- /* 1394-1995 IRM, fall through to retry. */
+ /* fall through - It's a 1394-1995 IRM, retry. */
default:
if (retry) {
retry--;
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 46bd22dde535..94a13fca8267 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -54,6 +54,7 @@ static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count)
switch (port_type) {
case SELFID_PORT_CHILD:
(*child_port_count)++;
+ /* fall through */
case SELFID_PORT_PARENT:
case SELFID_PORT_NCONN:
(*total_port_count)++;
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 53446e39a32c..c9a827bffe1c 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -157,7 +157,7 @@ config DMI_SCAN_MACHINE_NON_EFI_FALLBACK
config ISCSI_IBFT_FIND
bool "iSCSI Boot Firmware Table Attributes"
- depends on X86 && ACPI
+ depends on X86 && ISCSI_IBFT
default n
help
This option enables the kernel to find the region of memory
@@ -168,7 +168,8 @@ config ISCSI_IBFT_FIND
config ISCSI_IBFT
tristate "iSCSI Boot Firmware Table Attributes module"
select ISCSI_BOOT_SYSFS
- depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL
+ select ISCSI_IBFT_FIND if X86
+ depends on ACPI && SCSI && SCSI_LOWLEVEL
default n
help
This option enables support for detection and exposing of iSCSI
@@ -270,6 +271,20 @@ config TRUSTED_FOUNDATIONS
Choose N if you don't know what this is about.
+config TURRIS_MOX_RWTM
+ tristate "Turris Mox rWTM secure firmware driver"
+ depends on ARCH_MVEBU || COMPILE_TEST
+ depends on HAS_DMA && OF
+ depends on MAILBOX
+ select HW_RANDOM
+ select ARMADA_37XX_RWTM_MBOX
+ help
+ This driver communicates with the firmware on the Cortex-M3 secure
+ processor of the Turris Mox router. Enable if you are building for
+ Turris Mox, and you will be able to read the device serial number and
+ other manufacturing data and also utilize the Entropy Bit Generator
+ for hardware random number generation.
+
config HAVE_ARM_SMCCC
bool
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 3fa0b34eb72f..2b6e3a0be595 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
+obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
obj-y += psci/
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index c47d28d556b6..5f298f00a82e 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -2,5 +2,5 @@
obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o
scmi-bus-y = bus.o
scmi-driver-y = driver.o
-scmi-protocols-y = base.o clock.o perf.o power.o sensors.o
+scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index 204390297f4b..f804e8af6521 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -204,7 +204,7 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(id);
+ put_unaligned_le32(id, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret)
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 0a194af92438..32526a793f3a 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -56,7 +56,7 @@ struct scmi_msg_resp_clock_describe_rates {
struct scmi_clock_set_rate {
__le32 flags;
#define CLOCK_SET_ASYNC BIT(0)
-#define CLOCK_SET_DELAYED BIT(1)
+#define CLOCK_SET_IGNORE_RESP BIT(1)
#define CLOCK_SET_ROUND_UP BIT(2)
#define CLOCK_SET_ROUND_AUTO BIT(3)
__le32 id;
@@ -67,6 +67,7 @@ struct scmi_clock_set_rate {
struct clock_info {
int num_clocks;
int max_async_req;
+ atomic_t cur_async_req;
struct scmi_clock_info *clk;
};
@@ -106,7 +107,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle,
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+ put_unaligned_le32(clk_id, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
@@ -203,39 +204,47 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+ put_unaligned_le32(clk_id, t->tx.buf);
ret = scmi_do_xfer(handle, t);
- if (!ret) {
- __le32 *pval = t->rx.buf;
-
- *value = le32_to_cpu(*pval);
- *value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
- }
+ if (!ret)
+ *value = get_unaligned_le64(t->rx.buf);
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
- u32 config, u64 rate)
+ u64 rate)
{
int ret;
+ u32 flags = 0;
struct scmi_xfer *t;
struct scmi_clock_set_rate *cfg;
+ struct clock_info *ci = handle->clk_priv;
ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
sizeof(*cfg), 0, &t);
if (ret)
return ret;
+ if (ci->max_async_req &&
+ atomic_inc_return(&ci->cur_async_req) < ci->max_async_req)
+ flags |= CLOCK_SET_ASYNC;
+
cfg = t->tx.buf;
- cfg->flags = cpu_to_le32(config);
+ cfg->flags = cpu_to_le32(flags);
cfg->id = cpu_to_le32(clk_id);
cfg->value_low = cpu_to_le32(rate & 0xffffffff);
cfg->value_high = cpu_to_le32(rate >> 32);
- ret = scmi_do_xfer(handle, t);
+ if (flags & CLOCK_SET_ASYNC)
+ ret = scmi_do_xfer_with_response(handle, t);
+ else
+ ret = scmi_do_xfer(handle, t);
+
+ if (ci->max_async_req)
+ atomic_dec(&ci->cur_async_req);
scmi_xfer_put(handle, t);
return ret;
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 44fd4f9404a9..5237c2ff79fe 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -15,6 +15,8 @@
#include <linux/scmi_protocol.h>
#include <linux/types.h>
+#include <asm/unaligned.h>
+
#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
#define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))
@@ -48,11 +50,11 @@ struct scmi_msg_resp_prot_version {
/**
* struct scmi_msg_hdr - Message(Tx/Rx) header
*
- * @id: The identifier of the command being sent
- * @protocol_id: The identifier of the protocol used to send @id command
- * @seq: The token to identify the message. when a message/command returns,
- * the platform returns the whole message header unmodified including
- * the token
+ * @id: The identifier of the message being sent
+ * @protocol_id: The identifier of the protocol used to send @id message
+ * @seq: The token to identify the message. When a message returns, the
+ * platform returns the whole message header unmodified including the
+ * token
* @status: Status of the transfer once it's complete
* @poll_completion: Indicate if the transfer needs to be polled for
* completion or interrupt mode is used
@@ -84,17 +86,21 @@ struct scmi_msg {
* @rx: Receive message, the buffer should be pre-allocated to store
* message. If request-ACK protocol is used, we can reuse the same
* buffer for the rx path as we use for the tx path.
- * @done: completion event
+ * @done: command message transmit completion event
+ * @async: pointer to delayed response message received event completion
*/
struct scmi_xfer {
struct scmi_msg_hdr hdr;
struct scmi_msg tx;
struct scmi_msg rx;
struct completion done;
+ struct completion *async_done;
};
void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_do_xfer_with_response(const struct scmi_handle *h,
+ struct scmi_xfer *xfer);
int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p);
int scmi_handle_put(const struct scmi_handle *handle);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index b5bc4c7a8fab..3eb0382491ce 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -30,8 +30,14 @@
#include "common.h"
#define MSG_ID_MASK GENMASK(7, 0)
+#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
#define MSG_TYPE_MASK GENMASK(9, 8)
+#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr))
+#define MSG_TYPE_COMMAND 0
+#define MSG_TYPE_DELAYED_RESP 2
+#define MSG_TYPE_NOTIFICATION 3
#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
+#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr))
#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
@@ -86,7 +92,7 @@ struct scmi_desc {
};
/**
- * struct scmi_chan_info - Structure representing a SCMI channel informfation
+ * struct scmi_chan_info - Structure representing a SCMI channel information
*
* @cl: Mailbox Client
* @chan: Transmit/Receive mailbox channel
@@ -111,8 +117,9 @@ struct scmi_chan_info {
* @handle: Instance of SCMI handle to send to clients
* @version: SCMI revision information containing protocol version,
* implementation version and (sub-)vendor identification.
- * @minfo: Message info
- * @tx_idr: IDR object to map protocol id to channel info pointer
+ * @tx_minfo: Universal Transmit Message management info
+ * @tx_idr: IDR object to map protocol id to Tx channel info pointer
+ * @rx_idr: IDR object to map protocol id to Rx channel info pointer
* @protocols_imp: List of protocols implemented, currently maximum of
* MAX_PROTOCOLS_IMP elements allocated by the base protocol
* @node: List head
@@ -123,8 +130,9 @@ struct scmi_info {
const struct scmi_desc *desc;
struct scmi_revision_info version;
struct scmi_handle handle;
- struct scmi_xfers_info minfo;
+ struct scmi_xfers_info tx_minfo;
struct idr tx_idr;
+ struct idr rx_idr;
u8 *protocols_imp;
struct list_head node;
int users;
@@ -182,7 +190,7 @@ static inline int scmi_to_linux_errno(int errno)
static inline void scmi_dump_header_dbg(struct device *dev,
struct scmi_msg_hdr *hdr)
{
- dev_dbg(dev, "Command ID: %x Sequence ID: %x Protocol: %x\n",
+ dev_dbg(dev, "Message ID: %x Sequence ID: %x Protocol: %x\n",
hdr->id, hdr->seq, hdr->protocol_id);
}
@@ -190,7 +198,7 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
struct scmi_shared_mem __iomem *mem)
{
xfer->hdr.status = ioread32(mem->msg_payload);
- /* Skip the length of header and statues in payload area i.e 8 bytes*/
+ /* Skip the length of header and status in payload area i.e 8 bytes */
xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8);
/* Take a copy to the rx buffer.. */
@@ -198,56 +206,12 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
}
/**
- * scmi_rx_callback() - mailbox client callback for receive messages
- *
- * @cl: client pointer
- * @m: mailbox message
- *
- * Processes one received message to appropriate transfer information and
- * signals completion of the transfer.
- *
- * NOTE: This function will be invoked in IRQ context, hence should be
- * as optimal as possible.
- */
-static void scmi_rx_callback(struct mbox_client *cl, void *m)
-{
- u16 xfer_id;
- struct scmi_xfer *xfer;
- struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
- struct device *dev = cinfo->dev;
- struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
- struct scmi_xfers_info *minfo = &info->minfo;
- struct scmi_shared_mem __iomem *mem = cinfo->payload;
-
- xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header));
-
- /* Are we even expecting this? */
- if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
- dev_err(dev, "message for %d is not expected!\n", xfer_id);
- return;
- }
-
- xfer = &minfo->xfer_block[xfer_id];
-
- scmi_dump_header_dbg(dev, &xfer->hdr);
- /* Is the message of valid length? */
- if (xfer->rx.len > info->desc->max_msg_size) {
- dev_err(dev, "unable to handle %zu xfer(max %d)\n",
- xfer->rx.len, info->desc->max_msg_size);
- return;
- }
-
- scmi_fetch_response(xfer, mem);
- complete(&xfer->done);
-}
-
-/**
* pack_scmi_header() - packs and returns 32-bit header
*
* @hdr: pointer to header containing all the information on message id,
* protocol id and sequence id.
*
- * Return: 32-bit packed command header to be sent to the platform.
+ * Return: 32-bit packed message header to be sent to the platform.
*/
static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
{
@@ -257,6 +221,18 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
}
/**
+ * unpack_scmi_header() - unpacks and records message and protocol id
+ *
+ * @msg_hdr: 32-bit packed message header sent from the platform
+ * @hdr: pointer to header to fetch message and protocol id.
+ */
+static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
+{
+ hdr->id = MSG_XTRACT_ID(msg_hdr);
+ hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
+}
+
+/**
* scmi_tx_prepare() - mailbox client callback to prepare for the transfer
*
* @cl: client pointer
@@ -271,6 +247,14 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m)
struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
struct scmi_shared_mem __iomem *mem = cinfo->payload;
+ /*
+ * Ideally channel must be free by now unless OS timeout last
+ * request and platform continued to process the same, wait
+ * until it releases the shared memory, otherwise we may endup
+ * overwriting its response with new message payload or vice-versa
+ */
+ spin_until_cond(ioread32(&mem->channel_status) &
+ SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
/* Mark channel busy + clear error */
iowrite32(0x0, &mem->channel_status);
iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
@@ -285,8 +269,9 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m)
* scmi_xfer_get() - Allocate one message
*
* @handle: Pointer to SCMI entity handle
+ * @minfo: Pointer to Tx/Rx Message management info based on channel type
*
- * Helper function which is used by various command functions that are
+ * Helper function which is used by various message functions that are
* exposed to clients of this driver for allocating a message traffic event.
*
* This function can sleep depending on pending requests already in the system
@@ -295,13 +280,13 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m)
*
* Return: 0 if all went fine, else corresponding error.
*/
-static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle)
+static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle,
+ struct scmi_xfers_info *minfo)
{
u16 xfer_id;
struct scmi_xfer *xfer;
unsigned long flags, bit_pos;
struct scmi_info *info = handle_to_scmi_info(handle);
- struct scmi_xfers_info *minfo = &info->minfo;
/* Keep the locked section as small as possible */
spin_lock_irqsave(&minfo->xfer_lock, flags);
@@ -324,18 +309,17 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle)
}
/**
- * scmi_xfer_put() - Release a message
+ * __scmi_xfer_put() - Release a message
*
- * @handle: Pointer to SCMI entity handle
+ * @minfo: Pointer to Tx/Rx Message management info based on channel type
* @xfer: message that was reserved by scmi_xfer_get
*
* This holds a spinlock to maintain integrity of internal data structures.
*/
-void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+static void
+__scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
{
unsigned long flags;
- struct scmi_info *info = handle_to_scmi_info(handle);
- struct scmi_xfers_info *minfo = &info->minfo;
/*
* Keep the locked section as small as possible
@@ -347,6 +331,68 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
}
+/**
+ * scmi_rx_callback() - mailbox client callback for receive messages
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+ u8 msg_type;
+ u32 msg_hdr;
+ u16 xfer_id;
+ struct scmi_xfer *xfer;
+ struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+ struct device *dev = cinfo->dev;
+ struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
+ struct scmi_xfers_info *minfo = &info->tx_minfo;
+ struct scmi_shared_mem __iomem *mem = cinfo->payload;
+
+ msg_hdr = ioread32(&mem->msg_header);
+ msg_type = MSG_XTRACT_TYPE(msg_hdr);
+ xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
+
+ if (msg_type == MSG_TYPE_NOTIFICATION)
+ return; /* Notifications not yet supported */
+
+ /* Are we even expecting this? */
+ if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
+ dev_err(dev, "message for %d is not expected!\n", xfer_id);
+ return;
+ }
+
+ xfer = &minfo->xfer_block[xfer_id];
+
+ scmi_dump_header_dbg(dev, &xfer->hdr);
+
+ scmi_fetch_response(xfer, mem);
+
+ if (msg_type == MSG_TYPE_DELAYED_RESP)
+ complete(xfer->async_done);
+ else
+ complete(&xfer->done);
+}
+
+/**
+ * scmi_xfer_put() - Release a transmit message
+ *
+ * @handle: Pointer to SCMI entity handle
+ * @xfer: message that was reserved by scmi_xfer_get
+ */
+void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+ struct scmi_info *info = handle_to_scmi_info(handle);
+
+ __scmi_xfer_put(&info->tx_minfo, xfer);
+}
+
static bool
scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
{
@@ -435,8 +481,36 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
return ret;
}
+#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)
+
+/**
+ * scmi_do_xfer_with_response() - Do one transfer and wait until the delayed
+ * response is received
+ *
+ * @handle: Pointer to SCMI entity handle
+ * @xfer: Transfer to initiate and wait for response
+ *
+ * Return: -ETIMEDOUT in case of no delayed response, if transmit error,
+ * return corresponding error, else if all goes well, return 0.
+ */
+int scmi_do_xfer_with_response(const struct scmi_handle *handle,
+ struct scmi_xfer *xfer)
+{
+ int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT);
+ DECLARE_COMPLETION_ONSTACK(async_response);
+
+ xfer->async_done = &async_response;
+
+ ret = scmi_do_xfer(handle, xfer);
+ if (!ret && !wait_for_completion_timeout(xfer->async_done, timeout))
+ ret = -ETIMEDOUT;
+
+ xfer->async_done = NULL;
+ return ret;
+}
+
/**
- * scmi_xfer_get_init() - Allocate and initialise one message
+ * scmi_xfer_get_init() - Allocate and initialise one message for transmit
*
* @handle: Pointer to SCMI entity handle
* @msg_id: Message identifier
@@ -457,6 +531,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
int ret;
struct scmi_xfer *xfer;
struct scmi_info *info = handle_to_scmi_info(handle);
+ struct scmi_xfers_info *minfo = &info->tx_minfo;
struct device *dev = info->dev;
/* Ensure we have sane transfer sizes */
@@ -464,7 +539,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
tx_size > info->desc->max_msg_size)
return -ERANGE;
- xfer = scmi_xfer_get(handle);
+ xfer = scmi_xfer_get(handle, minfo);
if (IS_ERR(xfer)) {
ret = PTR_ERR(xfer);
dev_err(dev, "failed to get free message slot(%d)\n", ret);
@@ -597,27 +672,13 @@ int scmi_handle_put(const struct scmi_handle *handle)
return 0;
}
-static const struct scmi_desc scmi_generic_desc = {
- .max_rx_timeout_ms = 30, /* We may increase this if required */
- .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
- .max_msg_size = 128,
-};
-
-/* Each compatible listed below must have descriptor associated with it */
-static const struct of_device_id scmi_of_match[] = {
- { .compatible = "arm,scmi", .data = &scmi_generic_desc },
- { /* Sentinel */ },
-};
-
-MODULE_DEVICE_TABLE(of, scmi_of_match);
-
static int scmi_xfer_info_init(struct scmi_info *sinfo)
{
int i;
struct scmi_xfer *xfer;
struct device *dev = sinfo->dev;
const struct scmi_desc *desc = sinfo->desc;
- struct scmi_xfers_info *info = &sinfo->minfo;
+ struct scmi_xfers_info *info = &sinfo->tx_minfo;
/* Pre-allocated messages, no more than what hdr.seq can support */
if (WARN_ON(desc->max_msg >= MSG_TOKEN_MAX)) {
@@ -652,61 +713,32 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
return 0;
}
-static int scmi_mailbox_check(struct device_node *np)
+static int scmi_mailbox_check(struct device_node *np, int idx)
{
- return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL);
+ return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells",
+ idx, NULL);
}
-static int scmi_mbox_free_channel(int id, void *p, void *data)
+static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev,
+ int prot_id, bool tx)
{
- struct scmi_chan_info *cinfo = p;
- struct idr *idr = data;
-
- if (!IS_ERR_OR_NULL(cinfo->chan)) {
- mbox_free_channel(cinfo->chan);
- cinfo->chan = NULL;
- }
-
- idr_remove(idr, id);
-
- return 0;
-}
-
-static int scmi_remove(struct platform_device *pdev)
-{
- int ret = 0;
- struct scmi_info *info = platform_get_drvdata(pdev);
- struct idr *idr = &info->tx_idr;
-
- mutex_lock(&scmi_list_mutex);
- if (info->users)
- ret = -EBUSY;
- else
- list_del(&info->node);
- mutex_unlock(&scmi_list_mutex);
-
- if (ret)
- return ret;
-
- /* Safe to free channels since no more users */
- ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
- idr_destroy(&info->tx_idr);
-
- return ret;
-}
-
-static inline int
-scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
-{
- int ret;
+ int ret, idx;
struct resource res;
resource_size_t size;
struct device_node *shmem, *np = dev->of_node;
struct scmi_chan_info *cinfo;
struct mbox_client *cl;
+ struct idr *idr;
+ const char *desc = tx ? "Tx" : "Rx";
- if (scmi_mailbox_check(np)) {
- cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE);
+ /* Transmit channel is first entry i.e. index 0 */
+ idx = tx ? 0 : 1;
+ idr = tx ? &info->tx_idr : &info->rx_idr;
+
+ if (scmi_mailbox_check(np, idx)) {
+ cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);
+ if (unlikely(!cinfo)) /* Possible only if platform has no Rx */
+ return -EINVAL;
goto idr_alloc;
}
@@ -719,36 +751,36 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
cl = &cinfo->cl;
cl->dev = dev;
cl->rx_callback = scmi_rx_callback;
- cl->tx_prepare = scmi_tx_prepare;
+ cl->tx_prepare = tx ? scmi_tx_prepare : NULL;
cl->tx_block = false;
- cl->knows_txdone = true;
+ cl->knows_txdone = tx;
- shmem = of_parse_phandle(np, "shmem", 0);
+ shmem = of_parse_phandle(np, "shmem", idx);
ret = of_address_to_resource(shmem, 0, &res);
of_node_put(shmem);
if (ret) {
- dev_err(dev, "failed to get SCMI Tx payload mem resource\n");
+ dev_err(dev, "failed to get SCMI %s payload memory\n", desc);
return ret;
}
size = resource_size(&res);
cinfo->payload = devm_ioremap(info->dev, res.start, size);
if (!cinfo->payload) {
- dev_err(dev, "failed to ioremap SCMI Tx payload\n");
+ dev_err(dev, "failed to ioremap SCMI %s payload\n", desc);
return -EADDRNOTAVAIL;
}
- /* Transmit channel is first entry i.e. index 0 */
- cinfo->chan = mbox_request_channel(cl, 0);
+ cinfo->chan = mbox_request_channel(cl, idx);
if (IS_ERR(cinfo->chan)) {
ret = PTR_ERR(cinfo->chan);
if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to request SCMI Tx mailbox\n");
+ dev_err(dev, "failed to request SCMI %s mailbox\n",
+ desc);
return ret;
}
idr_alloc:
- ret = idr_alloc(&info->tx_idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
+ ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
if (ret != prot_id) {
dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret);
return ret;
@@ -758,6 +790,17 @@ idr_alloc:
return 0;
}
+static inline int
+scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
+{
+ int ret = scmi_mbox_chan_setup(info, dev, prot_id, true);
+
+ if (!ret) /* Rx is optional, hence no error check */
+ scmi_mbox_chan_setup(info, dev, prot_id, false);
+
+ return ret;
+}
+
static inline void
scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
int prot_id)
@@ -771,7 +814,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
return;
}
- if (scmi_mbox_chan_setup(info, &sdev->dev, prot_id)) {
+ if (scmi_mbox_txrx_setup(info, &sdev->dev, prot_id)) {
dev_err(&sdev->dev, "failed to setup transport\n");
scmi_device_destroy(sdev);
return;
@@ -791,7 +834,7 @@ static int scmi_probe(struct platform_device *pdev)
struct device_node *child, *np = dev->of_node;
/* Only mailbox method supported, check for the presence of one */
- if (scmi_mailbox_check(np)) {
+ if (scmi_mailbox_check(np, 0)) {
dev_err(dev, "no mailbox found in %pOF\n", np);
return -EINVAL;
}
@@ -814,12 +857,13 @@ static int scmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, info);
idr_init(&info->tx_idr);
+ idr_init(&info->rx_idr);
handle = &info->handle;
handle->dev = info->dev;
handle->version = &info->version;
- ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE);
+ ret = scmi_mbox_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);
if (ret)
return ret;
@@ -854,6 +898,62 @@ static int scmi_probe(struct platform_device *pdev)
return 0;
}
+static int scmi_mbox_free_channel(int id, void *p, void *data)
+{
+ struct scmi_chan_info *cinfo = p;
+ struct idr *idr = data;
+
+ if (!IS_ERR_OR_NULL(cinfo->chan)) {
+ mbox_free_channel(cinfo->chan);
+ cinfo->chan = NULL;
+ }
+
+ idr_remove(idr, id);
+
+ return 0;
+}
+
+static int scmi_remove(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct scmi_info *info = platform_get_drvdata(pdev);
+ struct idr *idr = &info->tx_idr;
+
+ mutex_lock(&scmi_list_mutex);
+ if (info->users)
+ ret = -EBUSY;
+ else
+ list_del(&info->node);
+ mutex_unlock(&scmi_list_mutex);
+
+ if (ret)
+ return ret;
+
+ /* Safe to free channels since no more users */
+ ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+ idr_destroy(&info->tx_idr);
+
+ idr = &info->rx_idr;
+ ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+ idr_destroy(&info->rx_idr);
+
+ return ret;
+}
+
+static const struct scmi_desc scmi_generic_desc = {
+ .max_rx_timeout_ms = 30, /* We may increase this if required */
+ .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
+ .max_msg_size = 128,
+};
+
+/* Each compatible listed below must have descriptor associated with it */
+static const struct of_device_id scmi_of_match[] = {
+ { .compatible = "arm,scmi", .data = &scmi_generic_desc },
+ { /* Sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, scmi_of_match);
+
static struct platform_driver scmi_driver = {
.driver = {
.name = "arm-scmi",
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 3c8ae7cc35de..4a8012e3cb8c 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -5,7 +5,10 @@
* Copyright (C) 2018 ARM Ltd.
*/
+#include <linux/bits.h>
#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/sort.h>
@@ -21,6 +24,7 @@ enum scmi_performance_protocol_cmd {
PERF_LEVEL_GET = 0x8,
PERF_NOTIFY_LIMITS = 0x9,
PERF_NOTIFY_LEVEL = 0xa,
+ PERF_DESCRIBE_FASTCHANNEL = 0xb,
};
struct scmi_opp {
@@ -44,6 +48,7 @@ struct scmi_msg_resp_perf_domain_attributes {
#define SUPPORTS_SET_PERF_LVL(x) ((x) & BIT(30))
#define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29))
#define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28))
+#define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27))
__le32 rate_limit_us;
__le32 sustained_freq_khz;
__le32 sustained_perf_level;
@@ -87,17 +92,56 @@ struct scmi_msg_resp_perf_describe_levels {
} opp[0];
};
+struct scmi_perf_get_fc_info {
+ __le32 domain;
+ __le32 message_id;
+};
+
+struct scmi_msg_resp_perf_desc_fc {
+ __le32 attr;
+#define SUPPORTS_DOORBELL(x) ((x) & BIT(0))
+#define DOORBELL_REG_WIDTH(x) FIELD_GET(GENMASK(2, 1), (x))
+ __le32 rate_limit;
+ __le32 chan_addr_low;
+ __le32 chan_addr_high;
+ __le32 chan_size;
+ __le32 db_addr_low;
+ __le32 db_addr_high;
+ __le32 db_set_lmask;
+ __le32 db_set_hmask;
+ __le32 db_preserve_lmask;
+ __le32 db_preserve_hmask;
+};
+
+struct scmi_fc_db_info {
+ int width;
+ u64 set;
+ u64 mask;
+ void __iomem *addr;
+};
+
+struct scmi_fc_info {
+ void __iomem *level_set_addr;
+ void __iomem *limit_set_addr;
+ void __iomem *level_get_addr;
+ void __iomem *limit_get_addr;
+ struct scmi_fc_db_info *level_set_db;
+ struct scmi_fc_db_info *limit_set_db;
+};
+
struct perf_dom_info {
bool set_limits;
bool set_perf;
bool perf_limit_notify;
bool perf_level_notify;
+ bool perf_fastchannels;
u32 opp_count;
u32 sustained_freq_khz;
u32 sustained_perf_level;
u32 mult_factor;
char name[SCMI_MAX_STR_SIZE];
struct scmi_opp opp[MAX_OPPS];
+ struct scmi_fc_info *fc_info;
};
struct scmi_perf_info {
@@ -151,7 +195,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(domain);
+ put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
@@ -162,6 +206,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
dom_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);
dom_info->sustained_freq_khz =
le32_to_cpu(attr->sustained_freq_khz);
dom_info->sustained_perf_level =
@@ -249,8 +294,42 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
return ret;
}
-static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
- u32 max_perf, u32 min_perf)
+#define SCMI_PERF_FC_RING_DB(w) \
+do { \
+ u##w val = 0; \
+ \
+ if (db->mask) \
+ val = ioread##w(db->addr) & db->mask; \
+ iowrite##w((u##w)db->set | val, db->addr); \
+} while (0)
+
+static void scmi_perf_fc_ring_db(struct scmi_fc_db_info *db)
+{
+ if (!db || !db->addr)
+ return;
+
+ if (db->width == 1)
+ SCMI_PERF_FC_RING_DB(8);
+ else if (db->width == 2)
+ SCMI_PERF_FC_RING_DB(16);
+ else if (db->width == 4)
+ SCMI_PERF_FC_RING_DB(32);
+ else /* db->width == 8 */
+#ifdef CONFIG_64BIT
+ SCMI_PERF_FC_RING_DB(64);
+#else
+ {
+ u64 val = 0;
+
+ if (db->mask)
+ val = ioread64_hi_lo(db->addr) & db->mask;
+ iowrite64_hi_lo(db->set, db->addr);
+ }
+#endif
+}
+
+static int scmi_perf_mb_limits_set(const struct scmi_handle *handle, u32 domain,
+ u32 max_perf, u32 min_perf)
{
int ret;
struct scmi_xfer *t;
@@ -272,8 +351,24 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
return ret;
}
-static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
- u32 *max_perf, u32 *min_perf)
+static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
+ u32 max_perf, u32 min_perf)
+{
+ struct scmi_perf_info *pi = handle->perf_priv;
+ struct perf_dom_info *dom = pi->dom_info + domain;
+
+ if (dom->fc_info && dom->fc_info->limit_set_addr) {
+ iowrite32(max_perf, dom->fc_info->limit_set_addr);
+ iowrite32(min_perf, dom->fc_info->limit_set_addr + 4);
+ scmi_perf_fc_ring_db(dom->fc_info->limit_set_db);
+ return 0;
+ }
+
+ return scmi_perf_mb_limits_set(handle, domain, max_perf, min_perf);
+}
+
+static int scmi_perf_mb_limits_get(const struct scmi_handle *handle, u32 domain,
+ u32 *max_perf, u32 *min_perf)
{
int ret;
struct scmi_xfer *t;
@@ -284,7 +379,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(domain);
+ put_unaligned_le32(domain, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret) {
@@ -298,8 +393,23 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
return ret;
}
-static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
- u32 level, bool poll)
+static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
+ u32 *max_perf, u32 *min_perf)
+{
+ struct scmi_perf_info *pi = handle->perf_priv;
+ struct perf_dom_info *dom = pi->dom_info + domain;
+
+ if (dom->fc_info && dom->fc_info->limit_get_addr) {
+ *max_perf = ioread32(dom->fc_info->limit_get_addr);
+ *min_perf = ioread32(dom->fc_info->limit_get_addr + 4);
+ return 0;
+ }
+
+ return scmi_perf_mb_limits_get(handle, domain, max_perf, min_perf);
+}
+
+static int scmi_perf_mb_level_set(const struct scmi_handle *handle, u32 domain,
+ u32 level, bool poll)
{
int ret;
struct scmi_xfer *t;
@@ -321,8 +431,23 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
return ret;
}
-static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
- u32 *level, bool poll)
+static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
+ u32 level, bool poll)
+{
+ struct scmi_perf_info *pi = handle->perf_priv;
+ struct perf_dom_info *dom = pi->dom_info + domain;
+
+ if (dom->fc_info && dom->fc_info->level_set_addr) {
+ iowrite32(level, dom->fc_info->level_set_addr);
+ scmi_perf_fc_ring_db(dom->fc_info->level_set_db);
+ return 0;
+ }
+
+ return scmi_perf_mb_level_set(handle, domain, level, poll);
+}
+
+static int scmi_perf_mb_level_get(const struct scmi_handle *handle, u32 domain,
+ u32 *level, bool poll)
{
int ret;
struct scmi_xfer *t;
@@ -333,16 +458,128 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
return ret;
t->hdr.poll_completion = poll;
- *(__le32 *)t->tx.buf = cpu_to_le32(domain);
+ put_unaligned_le32(domain, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret)
- *level = le32_to_cpu(*(__le32 *)t->rx.buf);
+ *level = get_unaligned_le32(t->rx.buf);
scmi_xfer_put(handle, t);
return ret;
}
+static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
+ u32 *level, bool poll)
+{
+ struct scmi_perf_info *pi = handle->perf_priv;
+ struct perf_dom_info *dom = pi->dom_info + domain;
+
+ if (dom->fc_info && dom->fc_info->level_get_addr) {
+ *level = ioread32(dom->fc_info->level_get_addr);
+ return 0;
+ }
+
+ return scmi_perf_mb_level_get(handle, domain, level, poll);
+}
+
+static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size)
+{
+ if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4)
+ return true;
+ if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8)
+ return true;
+ return false;
+}
+
+static void
+scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain,
+ u32 message_id, void __iomem **p_addr,
+ struct scmi_fc_db_info **p_db)
+{
+ int ret;
+ u32 flags;
+ u64 phys_addr;
+ u8 size;
+ void __iomem *addr;
+ struct scmi_xfer *t;
+ struct scmi_fc_db_info *db;
+ struct scmi_perf_get_fc_info *info;
+ struct scmi_msg_resp_perf_desc_fc *resp;
+
+ if (!p_addr)
+ return;
+
+ ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_FASTCHANNEL,
+ SCMI_PROTOCOL_PERF,
+ sizeof(*info), sizeof(*resp), &t);
+ if (ret)
+ return;
+
+ info = t->tx.buf;
+ info->domain = cpu_to_le32(domain);
+ info->message_id = cpu_to_le32(message_id);
+
+ ret = scmi_do_xfer(handle, t);
+ if (ret)
+ goto err_xfer;
+
+ resp = t->rx.buf;
+ flags = le32_to_cpu(resp->attr);
+ size = le32_to_cpu(resp->chan_size);
+ if (!scmi_perf_fc_size_is_valid(message_id, size))
+ goto err_xfer;
+
+ phys_addr = le32_to_cpu(resp->chan_addr_low);
+ phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32;
+ addr = devm_ioremap(handle->dev, phys_addr, size);
+ if (!addr)
+ goto err_xfer;
+ *p_addr = addr;
+
+ if (p_db && SUPPORTS_DOORBELL(flags)) {
+ db = devm_kzalloc(handle->dev, sizeof(*db), GFP_KERNEL);
+ if (!db)
+ goto err_xfer;
+
+ size = 1 << DOORBELL_REG_WIDTH(flags);
+ phys_addr = le32_to_cpu(resp->db_addr_low);
+ phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32;
+ addr = devm_ioremap(handle->dev, phys_addr, size);
+ if (!addr)
+ goto err_xfer;
+
+ db->addr = addr;
+ db->width = size;
+ db->set = le32_to_cpu(resp->db_set_lmask);
+ db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32;
+ db->mask = le32_to_cpu(resp->db_preserve_lmask);
+ db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32;
+ *p_db = db;
+ }
+err_xfer:
+ scmi_xfer_put(handle, t);
+}
+
+static void scmi_perf_domain_init_fc(const struct scmi_handle *handle,
+ u32 domain, struct scmi_fc_info **p_fc)
+{
+ struct scmi_fc_info *fc;
+
+ fc = devm_kzalloc(handle->dev, sizeof(*fc), GFP_KERNEL);
+ if (!fc)
+ return;
+
+ scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_SET,
+ &fc->level_set_addr, &fc->level_set_db);
+ scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_GET,
+ &fc->level_get_addr, NULL);
+ scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_SET,
+ &fc->limit_set_addr, &fc->limit_set_db);
+ scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_GET,
+ &fc->limit_get_addr, NULL);
+ *p_fc = fc;
+}
+
/* Device specific ops */
static int scmi_dev_domain_id(struct device *dev)
{
@@ -494,6 +731,9 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle)
scmi_perf_domain_attributes_get(handle, domain, dom);
scmi_perf_describe_levels_get(handle, domain, dom);
+
+ if (dom->perf_fastchannels)
+ scmi_perf_domain_init_fc(handle, domain, &dom->fc_info);
}
handle->perf_ops = &perf_ops;
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 62f3401a1f01..5abef7079c0a 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -96,7 +96,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(domain);
+ put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
@@ -147,11 +147,11 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
if (ret)
return ret;
- *(__le32 *)t->tx.buf = cpu_to_le32(domain);
+ put_unaligned_le32(domain, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret)
- *state = le32_to_cpu(*(__le32 *)t->rx.buf);
+ *state = get_unaligned_le32(t->rx.buf);
scmi_xfer_put(handle, t);
return ret;
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
new file mode 100644
index 000000000000..64cc81915581
--- /dev/null
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * System Control and Management Interface (SCMI) Reset Protocol
+ *
+ * Copyright (C) 2019 ARM Ltd.
+ */
+
+#include "common.h"
+
+enum scmi_reset_protocol_cmd {
+ RESET_DOMAIN_ATTRIBUTES = 0x3,
+ RESET = 0x4,
+ RESET_NOTIFY = 0x5,
+};
+
+enum scmi_reset_protocol_notify {
+ RESET_ISSUED = 0x0,
+};
+
+#define NUM_RESET_DOMAIN_MASK 0xffff
+#define RESET_NOTIFY_ENABLE BIT(0)
+
+struct scmi_msg_resp_reset_domain_attributes {
+ __le32 attributes;
+#define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31))
+#define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30))
+ __le32 latency;
+ u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_msg_reset_domain_reset {
+ __le32 domain_id;
+ __le32 flags;
+#define AUTONOMOUS_RESET BIT(0)
+#define EXPLICIT_RESET_ASSERT BIT(1)
+#define ASYNCHRONOUS_RESET BIT(2)
+ __le32 reset_state;
+#define ARCH_RESET_TYPE BIT(31)
+#define COLD_RESET_STATE BIT(0)
+#define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE)
+};
+
+struct reset_dom_info {
+ bool async_reset;
+ bool reset_notify;
+ u32 latency_us;
+ char name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_reset_info {
+ int num_domains;
+ struct reset_dom_info *dom_info;
+};
+
+static int scmi_reset_attributes_get(const struct scmi_handle *handle,
+ struct scmi_reset_info *pi)
+{
+ int ret;
+ struct scmi_xfer *t;
+ u32 attr;
+
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
+ SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t);
+ if (ret)
+ return ret;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret) {
+ attr = get_unaligned_le32(t->rx.buf);
+ pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
+ }
+
+ scmi_xfer_put(handle, t);
+ return ret;
+}
+
+static int
+scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
+ struct reset_dom_info *dom_info)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_resp_reset_domain_attributes *attr;
+
+ ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES,
+ SCMI_PROTOCOL_RESET, sizeof(domain),
+ sizeof(*attr), &t);
+ if (ret)
+ return ret;
+
+ put_unaligned_le32(domain, t->tx.buf);
+ attr = t->rx.buf;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret) {
+ u32 attributes = le32_to_cpu(attr->attributes);
+
+ dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes);
+ dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes);
+ dom_info->latency_us = le32_to_cpu(attr->latency);
+ if (dom_info->latency_us == U32_MAX)
+ dom_info->latency_us = 0;
+ strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
+ }
+
+ scmi_xfer_put(handle, t);
+ return ret;
+}
+
+static int scmi_reset_num_domains_get(const struct scmi_handle *handle)
+{
+ struct scmi_reset_info *pi = handle->reset_priv;
+
+ return pi->num_domains;
+}
+
+static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain)
+{
+ struct scmi_reset_info *pi = handle->reset_priv;
+ struct reset_dom_info *dom = pi->dom_info + domain;
+
+ return dom->name;
+}
+
+static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain)
+{
+ struct scmi_reset_info *pi = handle->reset_priv;
+ struct reset_dom_info *dom = pi->dom_info + domain;
+
+ return dom->latency_us;
+}
+
+static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain,
+ u32 flags, u32 state)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_reset_domain_reset *dom;
+ struct scmi_reset_info *pi = handle->reset_priv;
+ struct reset_dom_info *rdom = pi->dom_info + domain;
+
+ if (rdom->async_reset)
+ flags |= ASYNCHRONOUS_RESET;
+
+ ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET,
+ sizeof(*dom), 0, &t);
+ if (ret)
+ return ret;
+
+ dom = t->tx.buf;
+ dom->domain_id = cpu_to_le32(domain);
+ dom->flags = cpu_to_le32(flags);
+ dom->domain_id = cpu_to_le32(state);
+
+ if (rdom->async_reset)
+ ret = scmi_do_xfer_with_response(handle, t);
+ else
+ ret = scmi_do_xfer(handle, t);
+
+ scmi_xfer_put(handle, t);
+ return ret;
+}
+
+static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain)
+{
+ return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET,
+ ARCH_COLD_RESET);
+}
+
+static int
+scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
+{
+ return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT,
+ ARCH_COLD_RESET);
+}
+
+static int
+scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
+{
+ return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET);
+}
+
+static struct scmi_reset_ops reset_ops = {
+ .num_domains_get = scmi_reset_num_domains_get,
+ .name_get = scmi_reset_name_get,
+ .latency_get = scmi_reset_latency_get,
+ .reset = scmi_reset_domain_reset,
+ .assert = scmi_reset_domain_assert,
+ .deassert = scmi_reset_domain_deassert,
+};
+
+static int scmi_reset_protocol_init(struct scmi_handle *handle)
+{
+ int domain;
+ u32 version;
+ struct scmi_reset_info *pinfo;
+
+ scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version);
+
+ dev_dbg(handle->dev, "Reset Version %d.%d\n",
+ PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+ pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
+ if (!pinfo)
+ return -ENOMEM;
+
+ scmi_reset_attributes_get(handle, pinfo);
+
+ pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains,
+ sizeof(*pinfo->dom_info), GFP_KERNEL);
+ if (!pinfo->dom_info)
+ return -ENOMEM;
+
+ for (domain = 0; domain < pinfo->num_domains; domain++) {
+ struct reset_dom_info *dom = pinfo->dom_info + domain;
+
+ scmi_reset_domain_attributes_get(handle, domain, dom);
+ }
+
+ handle->reset_ops = &reset_ops;
+ handle->reset_priv = pinfo;
+
+ return 0;
+}
+
+static int __init scmi_reset_init(void)
+{
+ return scmi_protocol_register(SCMI_PROTOCOL_RESET,
+ &scmi_reset_protocol_init);
+}
+subsys_initcall(scmi_reset_init);
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index 0e94ab56f679..a400ea805fc2 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -9,8 +9,8 @@
enum scmi_sensor_protocol_cmd {
SENSOR_DESCRIPTION_GET = 0x3,
- SENSOR_CONFIG_SET = 0x4,
- SENSOR_TRIP_POINT_SET = 0x5,
+ SENSOR_TRIP_POINT_NOTIFY = 0x4,
+ SENSOR_TRIP_POINT_CONFIG = 0x5,
SENSOR_READING_GET = 0x6,
};
@@ -42,9 +42,10 @@ struct scmi_msg_resp_sensor_description {
} desc[0];
};
-struct scmi_msg_set_sensor_config {
+struct scmi_msg_sensor_trip_point_notify {
__le32 id;
__le32 event_control;
+#define SENSOR_TP_NOTIFY_ALL BIT(0)
};
struct scmi_msg_set_sensor_trip_point {
@@ -119,7 +120,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
do {
/* Set the number of sensors to be skipped/already read */
- *(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
+ put_unaligned_le32(desc_index, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (ret)
@@ -135,9 +136,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
}
for (cnt = 0; cnt < num_returned; cnt++) {
- u32 attrh;
+ u32 attrh, attrl;
struct scmi_sensor_info *s;
+ attrl = le32_to_cpu(buf->desc[cnt].attributes_low);
attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
s = &si->sensors[desc_index + cnt];
s->id = le32_to_cpu(buf->desc[cnt].id);
@@ -146,6 +148,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
/* Sign extend to a full s8 */
if (s->scale & SENSOR_SCALE_SIGN)
s->scale |= SENSOR_SCALE_EXTEND;
+ s->async = SUPPORTS_ASYNC_READ(attrl);
+ s->num_trip_points = NUM_TRIP_POINTS(attrl);
strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
}
@@ -160,15 +164,15 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
return ret;
}
-static int
-scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
+static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
+ u32 sensor_id, bool enable)
{
int ret;
- u32 evt_cntl = BIT(0);
+ u32 evt_cntl = enable ? SENSOR_TP_NOTIFY_ALL : 0;
struct scmi_xfer *t;
- struct scmi_msg_set_sensor_config *cfg;
+ struct scmi_msg_sensor_trip_point_notify *cfg;
- ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
+ ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY,
SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
if (ret)
return ret;
@@ -183,15 +187,16 @@ scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
return ret;
}
-static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
- u32 sensor_id, u8 trip_id, u64 trip_value)
+static int
+scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
+ u8 trip_id, u64 trip_value)
{
int ret;
u32 evt_cntl = SENSOR_TP_BOTH;
struct scmi_xfer *t;
struct scmi_msg_set_sensor_trip_point *trip;
- ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
+ ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG,
SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
if (ret)
return ret;
@@ -209,11 +214,13 @@ static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
}
static int scmi_sensor_reading_get(const struct scmi_handle *handle,
- u32 sensor_id, bool async, u64 *value)
+ u32 sensor_id, u64 *value)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
+ struct sensors_info *si = handle->sensor_priv;
+ struct scmi_sensor_info *s = si->sensors + sensor_id;
ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
@@ -223,14 +230,18 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
sensor = t->tx.buf;
sensor->id = cpu_to_le32(sensor_id);
- sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
- ret = scmi_do_xfer(handle, t);
- if (!ret) {
- __le32 *pval = t->rx.buf;
-
- *value = le32_to_cpu(*pval);
- *value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
+ if (s->async) {
+ sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
+ ret = scmi_do_xfer_with_response(handle, t);
+ if (!ret)
+ *value = get_unaligned_le64((void *)
+ ((__le32 *)t->rx.buf + 1));
+ } else {
+ sensor->flags = cpu_to_le32(0);
+ ret = scmi_do_xfer(handle, t);
+ if (!ret)
+ *value = get_unaligned_le64(t->rx.buf);
}
scmi_xfer_put(handle, t);
@@ -255,8 +266,8 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle)
static struct scmi_sensor_ops sensor_ops = {
.count_get = scmi_sensor_count_get,
.info_get = scmi_sensor_info_get,
- .configuration_set = scmi_sensor_configuration_set,
- .trip_point_set = scmi_sensor_trip_point_set,
+ .trip_point_notify = scmi_sensor_trip_point_notify,
+ .trip_point_config = scmi_sensor_trip_point_config,
.reading_get = scmi_sensor_reading_get,
};
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index d4ea929e8b34..178ee8106828 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -180,6 +180,19 @@ config RESET_ATTACK_MITIGATION
have been evicted, since otherwise it will trigger even on clean
reboots.
+config EFI_RCI2_TABLE
+ bool "EFI Runtime Configuration Interface Table Version 2 Support"
+ help
+ Displays the content of the Runtime Configuration Interface
+ Table version 2 on Dell EMC PowerEdge systems as a binary
+ attribute 'rci2' under /sys/firmware/efi/tables directory.
+
+ RCI2 table contains BIOS HII in XML format and is used to populate
+ BIOS setup page in Dell EMC OpenManage Server Administrator tool.
+ The BIOS setup page contains BIOS tokens which can be configured.
+
+ Say Y here for Dell EMC PowerEdge systems.
+
endmenu
config UEFI_CPER
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index d2d0d2030620..4ac2de4dfa72 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
obj-$(CONFIG_EFI_TEST) += test/
obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
+obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
obj-$(CONFIG_ARM) += $(arm-obj-y)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 8fa977c7861f..addf0749dd8b 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -390,6 +390,21 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
printk(
"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
pfx, pcie->bridge.secondary_status, pcie->bridge.control);
+
+ /* Fatal errors call __ghes_panic() before AER handler prints this */
+ if ((pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) &&
+ (gdata->error_severity & CPER_SEV_FATAL)) {
+ struct aer_capability_regs *aer;
+
+ aer = (struct aer_capability_regs *)pcie->aer_info;
+ printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n",
+ pfx, aer->uncor_status, aer->uncor_mask);
+ printk("%saer_uncor_severity: 0x%08x\n",
+ pfx, aer->uncor_severity);
+ printk("%sTLP Header: %08x %08x %08x %08x\n", pfx,
+ aer->header_log.dw0, aer->header_log.dw1,
+ aer->header_log.dw2, aer->header_log.dw3);
+ }
}
static void cper_print_tstamp(const char *pfx,
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index ad3b1f4866b3..8f1ab04f6743 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -39,11 +39,9 @@ struct efi __read_mostly efi = {
.acpi20 = EFI_INVALID_TABLE_ADDR,
.smbios = EFI_INVALID_TABLE_ADDR,
.smbios3 = EFI_INVALID_TABLE_ADDR,
- .sal_systab = EFI_INVALID_TABLE_ADDR,
.boot_info = EFI_INVALID_TABLE_ADDR,
.hcdp = EFI_INVALID_TABLE_ADDR,
.uga = EFI_INVALID_TABLE_ADDR,
- .uv_systab = EFI_INVALID_TABLE_ADDR,
.fw_vendor = EFI_INVALID_TABLE_ADDR,
.runtime = EFI_INVALID_TABLE_ADDR,
.config_table = EFI_INVALID_TABLE_ADDR,
@@ -57,25 +55,6 @@ struct efi __read_mostly efi = {
};
EXPORT_SYMBOL(efi);
-static unsigned long *efi_tables[] = {
- &efi.mps,
- &efi.acpi,
- &efi.acpi20,
- &efi.smbios,
- &efi.smbios3,
- &efi.sal_systab,
- &efi.boot_info,
- &efi.hcdp,
- &efi.uga,
- &efi.uv_systab,
- &efi.fw_vendor,
- &efi.runtime,
- &efi.config_table,
- &efi.esrt,
- &efi.properties_table,
- &efi.mem_attr_table,
-};
-
struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
.mm_users = ATOMIC_INIT(2),
@@ -476,7 +455,6 @@ static __initdata efi_config_table_type_t common_tables[] = {
{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
{HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
{MPS_TABLE_GUID, "MPS", &efi.mps},
- {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
@@ -487,6 +465,9 @@ static __initdata efi_config_table_type_t common_tables[] = {
{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
{LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
{LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
+#ifdef CONFIG_EFI_RCI2_TABLE
+ {DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys},
+#endif
{NULL_GUID, NULL, NULL},
};
@@ -964,20 +945,6 @@ int efi_status_to_err(efi_status_t status)
return err;
}
-bool efi_is_table_address(unsigned long phys_addr)
-{
- unsigned int i;
-
- if (phys_addr == EFI_INVALID_TABLE_ADDR)
- return false;
-
- for (i = 0; i < ARRAY_SIZE(efi_tables); i++)
- if (*(efi_tables[i]) == phys_addr)
- return true;
-
- return false;
-}
-
static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 1db780c0f07b..3caae7f2cf56 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -927,17 +927,33 @@ fail:
return status;
}
+#define GET_EFI_CONFIG_TABLE(bits) \
+static void *get_efi_config_table##bits(efi_system_table_t *_sys_table, \
+ efi_guid_t guid) \
+{ \
+ efi_system_table_##bits##_t *sys_table; \
+ efi_config_table_##bits##_t *tables; \
+ int i; \
+ \
+ sys_table = (typeof(sys_table))_sys_table; \
+ tables = (typeof(tables))(unsigned long)sys_table->tables; \
+ \
+ for (i = 0; i < sys_table->nr_tables; i++) { \
+ if (efi_guidcmp(tables[i].guid, guid) != 0) \
+ continue; \
+ \
+ return (void *)(unsigned long)tables[i].table; \
+ } \
+ \
+ return NULL; \
+}
+GET_EFI_CONFIG_TABLE(32)
+GET_EFI_CONFIG_TABLE(64)
+
void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
{
- efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
- int i;
-
- for (i = 0; i < sys_table->nr_tables; i++) {
- if (efi_guidcmp(tables[i].guid, guid) != 0)
- continue;
-
- return (void *)tables[i].table;
- }
-
- return NULL;
+ if (efi_is_64bit())
+ return get_efi_config_table64(sys_table, guid);
+ else
+ return get_efi_config_table32(sys_table, guid);
}
diff --git a/drivers/firmware/efi/rci2-table.c b/drivers/firmware/efi/rci2-table.c
new file mode 100644
index 000000000000..3e290f96620a
--- /dev/null
+++ b/drivers/firmware/efi/rci2-table.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Export Runtime Configuration Interface Table Version 2 (RCI2)
+ * to sysfs
+ *
+ * Copyright (C) 2019 Dell Inc
+ * by Narendra K <Narendra.K@dell.com>
+ *
+ * System firmware advertises the address of the RCI2 Table via
+ * an EFI Configuration Table entry. This code retrieves the RCI2
+ * table from the address and exports it to sysfs as a binary
+ * attribute 'rci2' under /sys/firmware/efi/tables directory.
+ */
+
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/efi.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define RCI_SIGNATURE "_RC_"
+
+struct rci2_table_global_hdr {
+ u16 type;
+ u16 resvd0;
+ u16 hdr_len;
+ u8 rci2_sig[4];
+ u16 resvd1;
+ u32 resvd2;
+ u32 resvd3;
+ u8 major_rev;
+ u8 minor_rev;
+ u16 num_of_structs;
+ u32 rci2_len;
+ u16 rci2_chksum;
+} __packed;
+
+static u8 *rci2_base;
+static u32 rci2_table_len;
+unsigned long rci2_table_phys __ro_after_init = EFI_INVALID_TABLE_ADDR;
+
+static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t pos, size_t count)
+{
+ memcpy(buf, attr->private + pos, count);
+ return count;
+}
+
+static BIN_ATTR(rci2, S_IRUSR, raw_table_read, NULL, 0);
+
+static u16 checksum(void)
+{
+ u8 len_is_odd = rci2_table_len % 2;
+ u32 chksum_len = rci2_table_len;
+ u16 *base = (u16 *)rci2_base;
+ u8 buf[2] = {0};
+ u32 offset = 0;
+ u16 chksum = 0;
+
+ if (len_is_odd)
+ chksum_len -= 1;
+
+ while (offset < chksum_len) {
+ chksum += *base;
+ offset += 2;
+ base++;
+ }
+
+ if (len_is_odd) {
+ buf[0] = *(u8 *)base;
+ chksum += *(u16 *)(buf);
+ }
+
+ return chksum;
+}
+
+int __init efi_rci2_sysfs_init(void)
+{
+ struct kobject *tables_kobj;
+ int ret = -ENOMEM;
+
+ rci2_base = memremap(rci2_table_phys,
+ sizeof(struct rci2_table_global_hdr),
+ MEMREMAP_WB);
+ if (!rci2_base) {
+ pr_debug("RCI2 table init failed - could not map RCI2 table\n");
+ goto err;
+ }
+
+ if (strncmp(rci2_base +
+ offsetof(struct rci2_table_global_hdr, rci2_sig),
+ RCI_SIGNATURE, 4)) {
+ pr_debug("RCI2 table init failed - incorrect signature\n");
+ ret = -ENODEV;
+ goto err_unmap;
+ }
+
+ rci2_table_len = *(u32 *)(rci2_base +
+ offsetof(struct rci2_table_global_hdr,
+ rci2_len));
+
+ memunmap(rci2_base);
+
+ if (!rci2_table_len) {
+ pr_debug("RCI2 table init failed - incorrect table length\n");
+ goto err;
+ }
+
+ rci2_base = memremap(rci2_table_phys, rci2_table_len, MEMREMAP_WB);
+ if (!rci2_base) {
+ pr_debug("RCI2 table - could not map RCI2 table\n");
+ goto err;
+ }
+
+ if (checksum() != 0) {
+ pr_debug("RCI2 table - incorrect checksum\n");
+ ret = -ENODEV;
+ goto err_unmap;
+ }
+
+ tables_kobj = kobject_create_and_add("tables", efi_kobj);
+ if (!tables_kobj) {
+ pr_debug("RCI2 table - tables_kobj creation failed\n");
+ goto err_unmap;
+ }
+
+ bin_attr_rci2.size = rci2_table_len;
+ bin_attr_rci2.private = rci2_base;
+ ret = sysfs_create_bin_file(tables_kobj, &bin_attr_rci2);
+ if (ret != 0) {
+ pr_debug("RCI2 table - rci2 sysfs bin file creation failed\n");
+ kobject_del(tables_kobj);
+ kobject_put(tables_kobj);
+ goto err_unmap;
+ }
+
+ return 0;
+
+ err_unmap:
+ memunmap(rci2_base);
+ err:
+ pr_debug("RCI2 table - sysfs initialization failed\n");
+ return ret;
+}
+late_initcall(efi_rci2_sysfs_init);
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index 42b566f8903f..0dbee32da4c6 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -1,4 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only
+config IMX_DSP
+ bool "IMX DSP Protocol driver"
+ depends on IMX_MBOX
+ help
+ This enables DSP IPC protocol between host AP (Linux)
+ and the firmware running on DSP.
+ DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
+
+ It acts like a doorbell. Client might use shared memory to
+ exchange information with DSP side.
+
config IMX_SCU
bool "IMX SCU Protocol driver"
depends on IMX_MBOX
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 802c4ad8e8f9..08bc9ddfbdfb 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_IMX_DSP) += imx-dsp.o
obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o
obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
new file mode 100644
index 000000000000..a43d2db5cbdb
--- /dev/null
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ * Author: Daniel Baluta <daniel.baluta@nxp.com>
+ *
+ * Implementation of the DSP IPC interface (host side)
+ */
+
+#include <linux/firmware/imx/dsp.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/*
+ * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
+ *
+ * @dsp: DSP IPC handle
+ * @chan_idx: index of the channel where to trigger the interrupt
+ *
+ * Returns non-negative value for success, negative value for error
+ */
+int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
+{
+ int ret;
+ struct imx_dsp_chan *dsp_chan;
+
+ if (idx >= DSP_MU_CHAN_NUM)
+ return -EINVAL;
+
+ dsp_chan = &ipc->chans[idx];
+ ret = mbox_send_message(dsp_chan->ch, NULL);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(imx_dsp_ring_doorbell);
+
+/*
+ * imx_dsp_handle_rx - rx callback used by imx mailbox
+ *
+ * @c: mbox client
+ * @msg: message received
+ *
+ * Users of DSP IPC will need to privde handle_reply and handle_request
+ * callbacks.
+ */
+static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
+{
+ struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
+
+ if (chan->idx == 0) {
+ chan->ipc->ops->handle_reply(chan->ipc);
+ } else {
+ chan->ipc->ops->handle_request(chan->ipc);
+ imx_dsp_ring_doorbell(chan->ipc, 1);
+ }
+}
+
+static int imx_dsp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imx_dsp_ipc *dsp_ipc;
+ struct imx_dsp_chan *dsp_chan;
+ struct mbox_client *cl;
+ char *chan_name;
+ int ret;
+ int i, j;
+
+ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
+ dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
+ if (!dsp_ipc)
+ return -ENOMEM;
+
+ for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
+ if (i < 2)
+ chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
+ else
+ chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
+
+ if (!chan_name)
+ return -ENOMEM;
+
+ dsp_chan = &dsp_ipc->chans[i];
+ cl = &dsp_chan->cl;
+ cl->dev = dev;
+ cl->tx_block = false;
+ cl->knows_txdone = true;
+ cl->rx_callback = imx_dsp_handle_rx;
+
+ dsp_chan->ipc = dsp_ipc;
+ dsp_chan->idx = i % 2;
+ dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
+ if (IS_ERR(dsp_chan->ch)) {
+ 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);
+ goto out;
+ }
+
+ dev_dbg(dev, "request mbox chan %s\n", chan_name);
+ /* chan_name is not used anymore by framework */
+ kfree(chan_name);
+ }
+
+ dsp_ipc->dev = dev;
+
+ dev_set_drvdata(dev, dsp_ipc);
+
+ dev_info(dev, "NXP i.MX DSP IPC initialized\n");
+
+ return devm_of_platform_populate(dev);
+out:
+ kfree(chan_name);
+ for (j = 0; j < i; j++) {
+ dsp_chan = &dsp_ipc->chans[j];
+ mbox_free_channel(dsp_chan->ch);
+ }
+
+ return ret;
+}
+
+static int imx_dsp_remove(struct platform_device *pdev)
+{
+ struct imx_dsp_chan *dsp_chan;
+ struct imx_dsp_ipc *dsp_ipc;
+ int i;
+
+ dsp_ipc = dev_get_drvdata(&pdev->dev);
+
+ for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
+ dsp_chan = &dsp_ipc->chans[i];
+ mbox_free_channel(dsp_chan->ch);
+ }
+
+ return 0;
+}
+
+static struct platform_driver imx_dsp_driver = {
+ .driver = {
+ .name = "imx-dsp",
+ },
+ .probe = imx_dsp_probe,
+ .remove = imx_dsp_remove,
+};
+builtin_platform_driver(imx_dsp_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
+MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 480cec69e2c9..b556612207e5 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -92,7 +92,8 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
{ "kpp", IMX_SC_R_KPP, 1, false, 0 },
{ "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
- { "mu", IMX_SC_R_MU_0A, 14, true, 0 },
+ { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },
+ { "mu_b", IMX_SC_R_MU_13B, 1, true, 13 },
/* CONN SS */
{ "usb", IMX_SC_R_USB_0, 2, true, 0 },
@@ -130,6 +131,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
{ "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
{ "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
+ { "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 },
/* VPU SS */
{ "vpu", IMX_SC_R_VPU, 1, false, 0 },
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index ab3aa3983833..7e12cbdf957c 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -84,6 +84,10 @@ MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
MODULE_LICENSE("GPL");
MODULE_VERSION(IBFT_ISCSI_VERSION);
+#ifndef CONFIG_ISCSI_IBFT_FIND
+struct acpi_table_ibft *ibft_addr;
+#endif
+
struct ibft_hdr {
u8 id;
u8 version;
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index f82ccd39a913..84f4ff351c62 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -103,7 +103,7 @@ static inline bool psci_power_state_loses_context(u32 state)
return state & mask;
}
-static inline bool psci_power_state_is_valid(u32 state)
+bool psci_power_state_is_valid(u32 state)
{
const u32 valid_mask = psci_has_ext_power_state() ?
PSCI_1_0_EXT_POWER_STATE_MASK :
@@ -277,175 +277,24 @@ static int __init psci_features(u32 psci_func_id)
}
#ifdef CONFIG_CPU_IDLE
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
-
-static int psci_dt_parse_state_node(struct device_node *np, u32 *state)
-{
- int err = of_property_read_u32(np, "arm,psci-suspend-param", state);
-
- if (err) {
- pr_warn("%pOF missing arm,psci-suspend-param property\n", np);
- return err;
- }
-
- if (!psci_power_state_is_valid(*state)) {
- pr_warn("Invalid PSCI power state %#x\n", *state);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
-{
- int i, ret = 0, count = 0;
- u32 *psci_states;
- struct device_node *state_node;
-
- /* Count idle states */
- while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
- count))) {
- count++;
- of_node_put(state_node);
- }
-
- if (!count)
- return -ENODEV;
-
- psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
- if (!psci_states)
- return -ENOMEM;
-
- for (i = 0; i < count; i++) {
- state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
- ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
- of_node_put(state_node);
-
- if (ret)
- goto free_mem;
-
- pr_debug("psci-power-state %#x index %d\n", psci_states[i], i);
- }
-
- /* Idle states parsed correctly, initialize per-cpu pointer */
- per_cpu(psci_power_state, cpu) = psci_states;
- return 0;
-
-free_mem:
- kfree(psci_states);
- return ret;
-}
-
-#ifdef CONFIG_ACPI
-#include <acpi/processor.h>
-
-static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
-{
- int i, count;
- u32 *psci_states;
- struct acpi_lpi_state *lpi;
- struct acpi_processor *pr = per_cpu(processors, cpu);
-
- if (unlikely(!pr || !pr->flags.has_lpi))
- return -EINVAL;
-
- count = pr->power.count - 1;
- if (count <= 0)
- return -ENODEV;
-
- psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
- if (!psci_states)
- return -ENOMEM;
-
- for (i = 0; i < count; i++) {
- u32 state;
-
- lpi = &pr->power.lpi_states[i + 1];
- /*
- * Only bits[31:0] represent a PSCI power_state while
- * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
- */
- state = lpi->address;
- if (!psci_power_state_is_valid(state)) {
- pr_warn("Invalid PSCI power state %#x\n", state);
- kfree(psci_states);
- return -EINVAL;
- }
- psci_states[i] = state;
- }
- /* Idle states parsed correctly, initialize per-cpu pointer */
- per_cpu(psci_power_state, cpu) = psci_states;
- return 0;
-}
-#else
-static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
-{
- return -EINVAL;
-}
-#endif
-
-int psci_cpu_init_idle(unsigned int cpu)
-{
- struct device_node *cpu_node;
- int ret;
-
- /*
- * If the PSCI cpu_suspend function hook has not been initialized
- * idle states must not be enabled, so bail out
- */
- if (!psci_ops.cpu_suspend)
- return -EOPNOTSUPP;
-
- if (!acpi_disabled)
- return psci_acpi_cpu_init_idle(cpu);
-
- cpu_node = of_get_cpu_node(cpu, NULL);
- if (!cpu_node)
- return -ENODEV;
-
- ret = psci_dt_cpu_init_idle(cpu_node, cpu);
-
- of_node_put(cpu_node);
-
- return ret;
-}
-
-static int psci_suspend_finisher(unsigned long index)
+static int psci_suspend_finisher(unsigned long state)
{
- u32 *state = __this_cpu_read(psci_power_state);
+ u32 power_state = state;
- return psci_ops.cpu_suspend(state[index - 1],
- __pa_symbol(cpu_resume));
+ return psci_ops.cpu_suspend(power_state, __pa_symbol(cpu_resume));
}
-int psci_cpu_suspend_enter(unsigned long index)
+int psci_cpu_suspend_enter(u32 state)
{
int ret;
- u32 *state = __this_cpu_read(psci_power_state);
- /*
- * idle state index 0 corresponds to wfi, should never be called
- * from the cpu_suspend operations
- */
- if (WARN_ON_ONCE(!index))
- return -EINVAL;
- if (!psci_power_state_loses_context(state[index - 1]))
- ret = psci_ops.cpu_suspend(state[index - 1], 0);
+ if (!psci_power_state_loses_context(state))
+ ret = psci_ops.cpu_suspend(state, 0);
else
- ret = cpu_suspend(index, psci_suspend_finisher);
+ ret = cpu_suspend(state, psci_suspend_finisher);
return ret;
}
-
-/* ARM specific CPU idle operations */
-#ifdef CONFIG_ARM
-static const struct cpuidle_ops psci_cpuidle_ops __initconst = {
- .suspend = psci_cpu_suspend_enter,
- .init = psci_dt_cpu_init_idle,
-};
-
-CPUIDLE_METHOD_OF_DECLARE(psci, "psci", &psci_cpuidle_ops);
-#endif
#endif
static int psci_system_suspend(unsigned long unused)
diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c
index f3659443f8c2..6a445397771c 100644
--- a/drivers/firmware/psci/psci_checker.c
+++ b/drivers/firmware/psci/psci_checker.c
@@ -228,8 +228,11 @@ out_free_cpus:
static void dummy_callback(struct timer_list *unused) {}
-static int suspend_cpu(int index, bool broadcast)
+static int suspend_cpu(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
{
+ struct cpuidle_state *state = &drv->states[index];
+ bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP;
int ret;
arch_cpu_idle_enter();
@@ -254,11 +257,7 @@ static int suspend_cpu(int index, bool broadcast)
}
}
- /*
- * Replicate the common ARM cpuidle enter function
- * (arm_enter_idle_state).
- */
- ret = CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, index);
+ ret = state->enter(dev, drv, index);
if (broadcast)
tick_broadcast_exit();
@@ -301,9 +300,8 @@ static int suspend_test_thread(void *arg)
* doesn't use PSCI).
*/
for (index = 1; index < drv->state_count; ++index) {
- struct cpuidle_state *state = &drv->states[index];
- bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP;
int ret;
+ struct cpuidle_state *state = &drv->states[index];
/*
* Set the timer to wake this CPU up in some time (which
@@ -318,7 +316,7 @@ static int suspend_test_thread(void *arg)
/* IRQs must be disabled during suspend operations. */
local_irq_disable();
- ret = suspend_cpu(index, broadcast);
+ ret = suspend_cpu(dev, drv, index);
/*
* We have woken up. Re-enable IRQs to handle any
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 2ddc118dba1b..4802ab170fe5 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/cpumask.h>
#include <linux/export.h>
+#include <linux/dma-direct.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -425,21 +426,23 @@ EXPORT_SYMBOL(qcom_scm_set_remote_state);
* @mem_sz: size of the region.
* @srcvm: vmid for current set of owners, each set bit in
* flag indicate a unique owner
- * @newvm: array having new owners and corrsponding permission
+ * @newvm: array having new owners and corresponding permission
* flags
* @dest_cnt: number of owners in next set.
*
- * Return negative errno on failure, 0 on success, with @srcvm updated.
+ * Return negative errno on failure or 0 on success with @srcvm updated.
*/
int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
unsigned int *srcvm,
- struct qcom_scm_vmperm *newvm, int dest_cnt)
+ const struct qcom_scm_vmperm *newvm,
+ unsigned int dest_cnt)
{
struct qcom_scm_current_perm_info *destvm;
struct qcom_scm_mem_map_info *mem_to_map;
phys_addr_t mem_to_map_phys;
phys_addr_t dest_phys;
phys_addr_t ptr_phys;
+ dma_addr_t ptr_dma;
size_t mem_to_map_sz;
size_t dest_sz;
size_t src_sz;
@@ -447,52 +450,50 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
int next_vm;
__le32 *src;
void *ptr;
- int ret;
- int len;
- int i;
+ int ret, i, b;
+ unsigned long srcvm_bits = *srcvm;
- src_sz = hweight_long(*srcvm) * sizeof(*src);
+ src_sz = hweight_long(srcvm_bits) * sizeof(*src);
mem_to_map_sz = sizeof(*mem_to_map);
dest_sz = dest_cnt * sizeof(*destvm);
ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
ALIGN(dest_sz, SZ_64);
- ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL);
+ ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_dma, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
+ ptr_phys = dma_to_phys(__scm->dev, ptr_dma);
/* Fill source vmid detail */
src = ptr;
- len = hweight_long(*srcvm);
- for (i = 0; i < len; i++) {
- src[i] = cpu_to_le32(ffs(*srcvm) - 1);
- *srcvm ^= 1 << (ffs(*srcvm) - 1);
- }
+ i = 0;
+ for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
+ src[i++] = cpu_to_le32(b);
/* Fill details of mem buff to map */
mem_to_map = ptr + ALIGN(src_sz, SZ_64);
mem_to_map_phys = ptr_phys + ALIGN(src_sz, SZ_64);
- mem_to_map[0].mem_addr = cpu_to_le64(mem_addr);
- mem_to_map[0].mem_size = cpu_to_le64(mem_sz);
+ mem_to_map->mem_addr = cpu_to_le64(mem_addr);
+ mem_to_map->mem_size = cpu_to_le64(mem_sz);
next_vm = 0;
/* Fill details of next vmid detail */
destvm = ptr + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
dest_phys = ptr_phys + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
- for (i = 0; i < dest_cnt; i++) {
- destvm[i].vmid = cpu_to_le32(newvm[i].vmid);
- destvm[i].perm = cpu_to_le32(newvm[i].perm);
- destvm[i].ctx = 0;
- destvm[i].ctx_size = 0;
- next_vm |= BIT(newvm[i].vmid);
+ for (i = 0; i < dest_cnt; i++, destvm++, newvm++) {
+ destvm->vmid = cpu_to_le32(newvm->vmid);
+ destvm->perm = cpu_to_le32(newvm->perm);
+ destvm->ctx = 0;
+ destvm->ctx_size = 0;
+ next_vm |= BIT(newvm->vmid);
}
ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz,
ptr_phys, src_sz, dest_phys, dest_sz);
- dma_free_coherent(__scm->dev, ALIGN(ptr_sz, SZ_64), ptr, ptr_phys);
+ dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_dma);
if (ret) {
dev_err(__scm->dev,
- "Assign memory protection call failed %d.\n", ret);
+ "Assign memory protection call failed %d\n", ret);
return -EINVAL;
}
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index cdee0b45943d..4126be9e3216 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -635,6 +635,7 @@ fail:
/**
* ti_sci_cmd_get_device() - command to request for device managed by TISCI
+ * that can be shared with other hosts.
* @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
* @id: Device Identifier
*
@@ -642,12 +643,30 @@ fail:
* usage count by balancing get_device with put_device. No refcounting is
* managed by driver for that purpose.
*
- * NOTE: The request is for exclusive access for the processor.
- *
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
{
+ return ti_sci_set_device_state(handle, id, 0,
+ MSG_DEVICE_SW_STATE_ON);
+}
+
+/**
+ * ti_sci_cmd_get_device_exclusive() - command to request for device managed by
+ * TISCI that is exclusively owned by the
+ * requesting host.
+ * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
+ u32 id)
+{
return ti_sci_set_device_state(handle, id,
MSG_FLAG_DEVICE_EXCLUSIVE,
MSG_DEVICE_SW_STATE_ON);
@@ -666,6 +685,26 @@ static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
*/
static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
{
+ return ti_sci_set_device_state(handle, id, 0,
+ MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+/**
+ * ti_sci_cmd_idle_device_exclusive() - Command to idle a device managed by
+ * TISCI that is exclusively owned by
+ * requesting host.
+ * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
+ u32 id)
+{
return ti_sci_set_device_state(handle, id,
MSG_FLAG_DEVICE_EXCLUSIVE,
MSG_DEVICE_SW_STATE_RETENTION);
@@ -2894,7 +2933,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
core_ops->reboot_device = ti_sci_cmd_core_reboot;
dops->get_device = ti_sci_cmd_get_device;
+ dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
dops->idle_device = ti_sci_cmd_idle_device;
+ dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
dops->put_device = ti_sci_cmd_put_device;
dops->is_valid = ti_sci_cmd_dev_is_valid;
diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c
new file mode 100644
index 000000000000..72be58960e54
--- /dev/null
+++ b/drivers/firmware/turris-mox-rwtm.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Turris Mox rWTM firmware driver
+ *
+ * Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <linux/armada-37xx-rwtm-mailbox.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/hw_random.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "turris-mox-rwtm"
+
+/*
+ * The macros and constants below come from Turris Mox's rWTM firmware code.
+ * This firmware is open source and it's sources can be found at
+ * https://gitlab.labs.nic.cz/turris/mox-boot-builder/tree/master/wtmi.
+ */
+
+#define MBOX_STS_SUCCESS (0 << 30)
+#define MBOX_STS_FAIL (1 << 30)
+#define MBOX_STS_BADCMD (2 << 30)
+#define MBOX_STS_ERROR(s) ((s) & (3 << 30))
+#define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff)
+#define MBOX_STS_CMD(s) ((s) & 0x3ff)
+
+enum mbox_cmd {
+ MBOX_CMD_GET_RANDOM = 1,
+ MBOX_CMD_BOARD_INFO = 2,
+ MBOX_CMD_ECDSA_PUB_KEY = 3,
+ MBOX_CMD_HASH = 4,
+ MBOX_CMD_SIGN = 5,
+ MBOX_CMD_VERIFY = 6,
+
+ MBOX_CMD_OTP_READ = 7,
+ MBOX_CMD_OTP_WRITE = 8,
+};
+
+struct mox_kobject;
+
+struct mox_rwtm {
+ struct device *dev;
+ struct mbox_client mbox_client;
+ struct mbox_chan *mbox;
+ struct mox_kobject *kobj;
+ struct hwrng hwrng;
+
+ struct armada_37xx_rwtm_rx_msg reply;
+
+ void *buf;
+ dma_addr_t buf_phys;
+
+ struct mutex busy;
+ struct completion cmd_done;
+
+ /* board information */
+ int has_board_info;
+ u64 serial_number;
+ int board_version, ram_size;
+ u8 mac_address1[6], mac_address2[6];
+
+ /* public key burned in eFuse */
+ int has_pubkey;
+ u8 pubkey[135];
+};
+
+struct mox_kobject {
+ struct kobject kobj;
+ struct mox_rwtm *rwtm;
+};
+
+static inline struct kobject *rwtm_to_kobj(struct mox_rwtm *rwtm)
+{
+ return &rwtm->kobj->kobj;
+}
+
+static inline struct mox_rwtm *to_rwtm(struct kobject *kobj)
+{
+ return container_of(kobj, struct mox_kobject, kobj)->rwtm;
+}
+
+static void mox_kobj_release(struct kobject *kobj)
+{
+ kfree(to_rwtm(kobj)->kobj);
+}
+
+static struct kobj_type mox_kobj_ktype = {
+ .release = mox_kobj_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
+static int mox_kobj_create(struct mox_rwtm *rwtm)
+{
+ rwtm->kobj = kzalloc(sizeof(*rwtm->kobj), GFP_KERNEL);
+ if (!rwtm->kobj)
+ return -ENOMEM;
+
+ kobject_init(rwtm_to_kobj(rwtm), &mox_kobj_ktype);
+ if (kobject_add(rwtm_to_kobj(rwtm), firmware_kobj, "turris-mox-rwtm")) {
+ kobject_put(rwtm_to_kobj(rwtm));
+ return -ENXIO;
+ }
+
+ rwtm->kobj->rwtm = rwtm;
+
+ return 0;
+}
+
+#define MOX_ATTR_RO(name, format, cat) \
+static ssize_t \
+name##_show(struct kobject *kobj, struct kobj_attribute *a, \
+ char *buf) \
+{ \
+ struct mox_rwtm *rwtm = to_rwtm(kobj); \
+ if (!rwtm->has_##cat) \
+ return -ENODATA; \
+ return sprintf(buf, format, rwtm->name); \
+} \
+static struct kobj_attribute mox_attr_##name = __ATTR_RO(name)
+
+MOX_ATTR_RO(serial_number, "%016llX\n", board_info);
+MOX_ATTR_RO(board_version, "%i\n", board_info);
+MOX_ATTR_RO(ram_size, "%i\n", board_info);
+MOX_ATTR_RO(mac_address1, "%pM\n", board_info);
+MOX_ATTR_RO(mac_address2, "%pM\n", board_info);
+MOX_ATTR_RO(pubkey, "%s\n", pubkey);
+
+static int mox_get_status(enum mbox_cmd cmd, u32 retval)
+{
+ if (MBOX_STS_CMD(retval) != cmd ||
+ MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
+ return -EIO;
+ else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL)
+ return -(int)MBOX_STS_VALUE(retval);
+ else
+ return MBOX_STS_VALUE(retval);
+}
+
+static const struct attribute *mox_rwtm_attrs[] = {
+ &mox_attr_serial_number.attr,
+ &mox_attr_board_version.attr,
+ &mox_attr_ram_size.attr,
+ &mox_attr_mac_address1.attr,
+ &mox_attr_mac_address2.attr,
+ &mox_attr_pubkey.attr,
+ NULL
+};
+
+static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
+{
+ struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
+ struct armada_37xx_rwtm_rx_msg *msg = data;
+
+ rwtm->reply = *msg;
+ complete(&rwtm->cmd_done);
+}
+
+static void reply_to_mac_addr(u8 *mac, u32 t1, u32 t2)
+{
+ mac[0] = t1 >> 8;
+ mac[1] = t1;
+ mac[2] = t2 >> 24;
+ mac[3] = t2 >> 16;
+ mac[4] = t2 >> 8;
+ mac[5] = t2;
+}
+
+static int mox_get_board_info(struct mox_rwtm *rwtm)
+{
+ struct armada_37xx_rwtm_tx_msg msg;
+ struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
+ int ret;
+
+ msg.command = MBOX_CMD_BOARD_INFO;
+ ret = mbox_send_message(rwtm->mbox, &msg);
+ if (ret < 0)
+ return ret;
+
+ ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
+ if (ret < 0)
+ return ret;
+
+ ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
+ if (ret < 0 && ret != -ENODATA) {
+ return ret;
+ } else if (ret == -ENODATA) {
+ dev_warn(rwtm->dev,
+ "Board does not have manufacturing information burned!\n");
+ } else {
+ rwtm->serial_number = reply->status[1];
+ rwtm->serial_number <<= 32;
+ rwtm->serial_number |= reply->status[0];
+ rwtm->board_version = reply->status[2];
+ rwtm->ram_size = reply->status[3];
+ reply_to_mac_addr(rwtm->mac_address1, reply->status[4],
+ reply->status[5]);
+ reply_to_mac_addr(rwtm->mac_address2, reply->status[6],
+ reply->status[7]);
+ rwtm->has_board_info = 1;
+
+ pr_info("Turris Mox serial number %016llX\n",
+ rwtm->serial_number);
+ pr_info(" board version %i\n", rwtm->board_version);
+ pr_info(" burned RAM size %i MiB\n", rwtm->ram_size);
+ }
+
+ msg.command = MBOX_CMD_ECDSA_PUB_KEY;
+ ret = mbox_send_message(rwtm->mbox, &msg);
+ if (ret < 0)
+ return ret;
+
+ ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
+ if (ret < 0)
+ return ret;
+
+ ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
+ if (ret < 0 && ret != -ENODATA) {
+ return ret;
+ } else if (ret == -ENODATA) {
+ dev_warn(rwtm->dev, "Board has no public key burned!\n");
+ } else {
+ u32 *s = reply->status;
+
+ rwtm->has_pubkey = 1;
+ sprintf(rwtm->pubkey,
+ "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
+ ret, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
+ s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]);
+ }
+
+ return 0;
+}
+
+static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv;
+ struct armada_37xx_rwtm_tx_msg msg;
+ int ret;
+
+ if (max > 4096)
+ max = 4096;
+
+ msg.command = MBOX_CMD_GET_RANDOM;
+ msg.args[0] = 1;
+ msg.args[1] = rwtm->buf_phys;
+ msg.args[2] = (max + 3) & ~3;
+
+ if (!wait) {
+ if (!mutex_trylock(&rwtm->busy))
+ return -EBUSY;
+ } else {
+ mutex_lock(&rwtm->busy);
+ }
+
+ ret = mbox_send_message(rwtm->mbox, &msg);
+ if (ret < 0)
+ goto unlock_mutex;
+
+ ret = wait_for_completion_interruptible(&rwtm->cmd_done);
+ if (ret < 0)
+ goto unlock_mutex;
+
+ ret = mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
+ if (ret < 0)
+ goto unlock_mutex;
+
+ memcpy(data, rwtm->buf, max);
+ ret = max;
+
+unlock_mutex:
+ mutex_unlock(&rwtm->busy);
+ return ret;
+}
+
+static int turris_mox_rwtm_probe(struct platform_device *pdev)
+{
+ struct mox_rwtm *rwtm;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ rwtm = devm_kzalloc(dev, sizeof(*rwtm), GFP_KERNEL);
+ if (!rwtm)
+ return -ENOMEM;
+
+ rwtm->dev = dev;
+ rwtm->buf = dmam_alloc_coherent(dev, PAGE_SIZE, &rwtm->buf_phys,
+ GFP_KERNEL);
+ if (!rwtm->buf)
+ return -ENOMEM;
+
+ ret = mox_kobj_create(rwtm);
+ if (ret < 0) {
+ dev_err(dev, "Cannot create turris-mox-rwtm kobject!\n");
+ return ret;
+ }
+
+ ret = sysfs_create_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
+ if (ret < 0) {
+ dev_err(dev, "Cannot create sysfs files!\n");
+ goto put_kobj;
+ }
+
+ platform_set_drvdata(pdev, rwtm);
+
+ mutex_init(&rwtm->busy);
+
+ rwtm->mbox_client.dev = dev;
+ rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
+
+ rwtm->mbox = mbox_request_channel(&rwtm->mbox_client, 0);
+ if (IS_ERR(rwtm->mbox)) {
+ ret = PTR_ERR(rwtm->mbox);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Cannot request mailbox channel: %i\n",
+ ret);
+ goto remove_files;
+ }
+
+ init_completion(&rwtm->cmd_done);
+
+ ret = mox_get_board_info(rwtm);
+ if (ret < 0)
+ dev_warn(dev, "Cannot read board information: %i\n", ret);
+
+ rwtm->hwrng.name = DRIVER_NAME "_hwrng";
+ rwtm->hwrng.read = mox_hwrng_read;
+ rwtm->hwrng.priv = (unsigned long) rwtm;
+ rwtm->hwrng.quality = 1024;
+
+ ret = devm_hwrng_register(dev, &rwtm->hwrng);
+ if (ret < 0) {
+ dev_err(dev, "Cannot register HWRNG: %i\n", ret);
+ goto free_channel;
+ }
+
+ return 0;
+
+free_channel:
+ mbox_free_channel(rwtm->mbox);
+remove_files:
+ sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
+put_kobj:
+ kobject_put(rwtm_to_kobj(rwtm));
+ return ret;
+}
+
+static int turris_mox_rwtm_remove(struct platform_device *pdev)
+{
+ struct mox_rwtm *rwtm = platform_get_drvdata(pdev);
+
+ sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
+ kobject_put(rwtm_to_kobj(rwtm));
+ mbox_free_channel(rwtm->mbox);
+
+ return 0;
+}
+
+static const struct of_device_id turris_mox_rwtm_match[] = {
+ { .compatible = "cznic,turris-mox-rwtm", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, turris_mox_rwtm_match);
+
+static struct platform_driver turris_mox_rwtm_driver = {
+ .probe = turris_mox_rwtm_probe,
+ .remove = turris_mox_rwtm_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = turris_mox_rwtm_match,
+ },
+};
+module_platform_driver(turris_mox_rwtm_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Turris Mox rWTM firmware driver");
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 474f304ec109..cdd4f73b4869 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -40,6 +40,7 @@ config ALTERA_PR_IP_CORE_PLAT
config FPGA_MGR_ALTERA_PS_SPI
tristate "Altera FPGA Passive Serial over SPI"
depends on SPI
+ select BITREVERSE
help
FPGA manager driver support for Altera Arria/Cyclone/Stratix
using the passive serial interface over SPI.
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c
index a13f224303c6..0221dee8dd4c 100644
--- a/drivers/fpga/altera-ps-spi.c
+++ b/drivers/fpga/altera-ps-spi.c
@@ -210,7 +210,7 @@ static int altera_ps_write_complete(struct fpga_manager *mgr,
return -EIO;
}
- if (!IS_ERR(conf->confd)) {
+ if (conf->confd) {
if (!gpiod_get_raw_value_cansleep(conf->confd)) {
dev_err(&mgr->dev, "CONF_DONE is inactive!\n");
return -EIO;
@@ -289,10 +289,13 @@ static int altera_ps_probe(struct spi_device *spi)
return PTR_ERR(conf->status);
}
- conf->confd = devm_gpiod_get(&spi->dev, "confd", GPIOD_IN);
+ conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN);
if (IS_ERR(conf->confd)) {
- dev_warn(&spi->dev, "Not using confd gpio: %ld\n",
- PTR_ERR(conf->confd));
+ dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
+ PTR_ERR(conf->confd));
+ return PTR_ERR(conf->confd);
+ } else if (!conf->confd) {
+ dev_warn(&spi->dev, "Not using confd gpio");
}
/* Register manager with unique name */
diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index 343153d47e5b..004dc03ccf09 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -38,8 +38,7 @@
#define SCOM_STATUS_PIB_RESP_MASK 0x00007000
#define SCOM_STATUS_PIB_RESP_SHIFT 12
-#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_ERR_SUMMARY | \
- SCOM_STATUS_PROTECTION | \
+#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_PROTECTION | \
SCOM_STATUS_PARITY | \
SCOM_STATUS_PIB_ABORT | \
SCOM_STATUS_PIB_RESP_MASK)
@@ -251,11 +250,6 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
/* Return -EBUSY on PIB abort to force a retry */
if (status & SCOM_STATUS_PIB_ABORT)
return -EBUSY;
- if (status & SCOM_STATUS_ERR_SUMMARY) {
- fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
- sizeof(uint32_t));
- return -EIO;
- }
return 0;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index bb13c266c329..38e096e6925f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -275,7 +275,7 @@ config GPIO_ICH
config GPIO_IOP
tristate "Intel IOP GPIO"
- depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
+ depends on ARCH_IOP32X || COMPILE_TEST
select GPIO_GENERIC
help
Say yes here to support the GPIO functionality of a number of Intel
@@ -288,7 +288,7 @@ config GPIO_IXP4XX
depends on ARM # For <asm/mach-types.h>
depends on ARCH_IXP4XX
select GPIO_GENERIC
- select IRQ_DOMAIN
+ select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
help
Say yes here to support the GPIO functionality of a number of Intel
@@ -311,6 +311,13 @@ config GPIO_LPC18XX
Select this option to enable GPIO driver for
NXP LPC18XX/43XX devices.
+config GPIO_LPC32XX
+ tristate "NXP LPC32XX GPIO support"
+ depends on OF_GPIO && (ARCH_LPC32XX || COMPILE_TEST)
+ help
+ Select this option to enable GPIO driver for
+ NXP LPC32XX devices.
+
config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
@@ -539,6 +546,7 @@ config GPIO_THUNDERX
tristate "Cavium ThunderX/OCTEON-TX GPIO"
depends on ARCH_THUNDER || (64BIT && COMPILE_TEST)
depends on PCI_MSI
+ select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
select IRQ_FASTEOI_HIERARCHY_HANDLERS
help
@@ -1445,6 +1453,15 @@ config GPIO_XRA1403
help
GPIO driver for EXAR XRA1403 16-bit SPI-based GPIO expander.
+config GPIO_MOXTET
+ tristate "Turris Mox Moxtet bus GPIO expander"
+ depends on MOXTET
+ help
+ Say yes here if you are building for the Turris Mox router.
+ This is the driver needed for configuring the GPIOs via the Moxtet
+ bus. For example the Mox module with SFP cage needs this driver
+ so that phylink can use corresponding GPIOs.
+
endmenu
menu "USB GPIO expanders"
@@ -1465,7 +1482,6 @@ endmenu
config GPIO_MOCKUP
tristate "GPIO Testing Driver"
- depends on GPIOLIB
select IRQ_SIM
help
This enables GPIO Testing driver, which provides a way to test GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a4e91175c708..d2fd19c15bae 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -67,14 +67,13 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
-obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
-obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
+obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
@@ -93,6 +92,7 @@ obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
+obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index c07fad975049..5640efe5e750 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -142,7 +142,7 @@ static const struct gpio_chip template_chip = {
static int arizona_gpio_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
- struct arizona_pdata *pdata = dev_get_platdata(arizona->dev);
+ struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_gpio *arizona_gpio;
int ret;
@@ -177,7 +177,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (pdata && pdata->gpio_base)
+ if (pdata->gpio_base)
arizona_gpio->gpio_chip.base = pdata->gpio_base;
else
arizona_gpio->gpio_chip.base = -1;
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 13d80bfbc3b6..09e53c5f3b0a 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -52,6 +52,7 @@ struct aspeed_gpio_config {
*/
struct aspeed_gpio {
struct gpio_chip chip;
+ struct irq_chip irqc;
spinlock_t lock;
void __iomem *base;
int irq;
@@ -661,12 +662,14 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc);
struct aspeed_gpio *data = gpiochip_get_data(gc);
- unsigned int i, p, girq;
+ unsigned int i, p, girq, banks;
unsigned long reg;
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
chained_irq_enter(ic, desc);
- for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) {
+ banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
+ for (i = 0; i < banks; i++) {
const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
reg = ioread32(bank_reg(data, bank, reg_irq_status));
@@ -681,16 +684,11 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(ic, desc);
}
-static struct irq_chip aspeed_gpio_irqchip = {
- .name = "aspeed-gpio",
- .irq_ack = aspeed_gpio_irq_ack,
- .irq_mask = aspeed_gpio_irq_mask,
- .irq_unmask = aspeed_gpio_irq_unmask,
- .irq_set_type = aspeed_gpio_set_type,
-};
-
-static void set_irq_valid_mask(struct aspeed_gpio *gpio)
+static void aspeed_init_irq_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
const struct aspeed_bank_props *props = gpio->config->props;
while (!is_bank_props_sentinel(props)) {
@@ -701,42 +699,16 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio)
for_each_clear_bit(offset, &input, 32) {
unsigned int i = props->bank * 32 + offset;
- if (i >= gpio->config->nr_gpios)
+ if (i >= gpio->chip.ngpio)
break;
- clear_bit(i, gpio->chip.irq.valid_mask);
+ clear_bit(i, valid_mask);
}
props++;
}
}
-static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
- struct platform_device *pdev)
-{
- int rc;
-
- rc = platform_get_irq(pdev, 0);
- if (rc < 0)
- return rc;
-
- gpio->irq = rc;
-
- set_irq_valid_mask(gpio);
-
- rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
- 0, handle_bad_irq, IRQ_TYPE_NONE);
- if (rc) {
- dev_info(&pdev->dev, "Could not add irqchip\n");
- return rc;
- }
-
- gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip,
- gpio->irq, aspeed_gpio_irq_handler);
-
- return 0;
-}
-
static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
unsigned int offset, bool enable)
{
@@ -1040,10 +1012,10 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
unsigned long flags;
if (!gpio->cf_copro_bankmap)
- gpio->cf_copro_bankmap = kzalloc(gpio->config->nr_gpios >> 3, GFP_KERNEL);
+ gpio->cf_copro_bankmap = kzalloc(gpio->chip.ngpio >> 3, GFP_KERNEL);
if (!gpio->cf_copro_bankmap)
return -ENOMEM;
- if (offset < 0 || offset > gpio->config->nr_gpios)
+ if (offset < 0 || offset > gpio->chip.ngpio)
return -EINVAL;
bindex = offset >> 3;
@@ -1088,7 +1060,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
if (!gpio->cf_copro_bankmap)
return -ENXIO;
- if (offset < 0 || offset > gpio->config->nr_gpios)
+ if (offset < 0 || offset > gpio->chip.ngpio)
return -EINVAL;
bindex = offset >> 3;
@@ -1141,9 +1113,25 @@ static const struct aspeed_gpio_config ast2500_config =
/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
{ .nr_gpios = 232, .props = ast2500_bank_props, };
+static const struct aspeed_bank_props ast2600_bank_props[] = {
+ /* input output */
+ {5, 0xffffffff, 0x0000ffff}, /* U/V/W/X */
+ {6, 0xffff0000, 0x0fff0000}, /* Y/Z */
+ { },
+};
+
+static const struct aspeed_gpio_config ast2600_config =
+ /*
+ * ast2600 has two controllers one with 208 GPIOs and one with 36 GPIOs.
+ * We expect ngpio being set in the device tree and this is a fallback
+ * option.
+ */
+ { .nr_gpios = 208, .props = ast2600_bank_props, };
+
static const struct of_device_id aspeed_gpio_of_table[] = {
{ .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
{ .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
+ { .compatible = "aspeed,ast2600-gpio", .data = &ast2600_config, },
{}
};
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
@@ -1152,7 +1140,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio;
- int rc, i, banks;
+ int rc, i, banks, err;
+ u32 ngpio;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
@@ -1178,7 +1167,10 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->config = gpio_id->data;
gpio->chip.parent = &pdev->dev;
- gpio->chip.ngpio = gpio->config->nr_gpios;
+ err = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio);
+ gpio->chip.ngpio = (u16) ngpio;
+ if (err)
+ gpio->chip.ngpio = gpio->config->nr_gpios;
gpio->chip.direction_input = aspeed_gpio_dir_in;
gpio->chip.direction_output = aspeed_gpio_dir_out;
gpio->chip.get_direction = aspeed_gpio_get_direction;
@@ -1189,10 +1181,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.set_config = aspeed_gpio_set_config;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
- gpio->chip.irq.need_valid_mask = true;
/* Allocate a cache of the output registers */
- banks = gpio->config->nr_gpios >> 5;
+ banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
gpio->dcache = devm_kcalloc(&pdev->dev,
banks, sizeof(u32), GFP_KERNEL);
if (!gpio->dcache)
@@ -1212,16 +1203,42 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM);
}
- rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
- if (rc < 0)
- return rc;
+ /* Optionally set up an irqchip if there is an IRQ */
+ rc = platform_get_irq(pdev, 0);
+ if (rc > 0) {
+ struct gpio_irq_chip *girq;
+
+ gpio->irq = rc;
+ girq = &gpio->chip.irq;
+ girq->chip = &gpio->irqc;
+ girq->chip->name = dev_name(&pdev->dev);
+ girq->chip->irq_ack = aspeed_gpio_irq_ack;
+ girq->chip->irq_mask = aspeed_gpio_irq_mask;
+ girq->chip->irq_unmask = aspeed_gpio_irq_unmask;
+ girq->chip->irq_set_type = aspeed_gpio_set_type;
+ girq->parent_handler = aspeed_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = gpio->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+ girq->init_valid_mask = aspeed_init_irq_valid_mask;
+ }
gpio->offset_timer =
devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
if (!gpio->offset_timer)
return -ENOMEM;
- return aspeed_gpio_setup_irqs(gpio, pdev);
+ rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
+ if (rc < 0)
+ return rc;
+
+ return 0;
}
static struct platform_driver aspeed_gpio_driver = {
diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c
index fd85605d2dab..0c1ead12d883 100644
--- a/drivers/gpio/gpio-bd70528.c
+++ b/drivers/gpio/gpio-bd70528.c
@@ -36,7 +36,7 @@ static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
break;
default:
dev_err(bdgpio->chip.dev,
- "Invalid debouce value %u\n", debounce);
+ "Invalid debounce value %u\n", debounce);
return -EINVAL;
}
return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
@@ -153,7 +153,7 @@ static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
- int ret = -EINVAL;
+ int ret;
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
/*
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index af936dcca659..05e3f99ae59c 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -636,10 +636,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
if (of_property_read_bool(np, "interrupt-controller")) {
priv->parent_irq = platform_get_irq(pdev, 0);
- if (priv->parent_irq <= 0) {
- dev_err(dev, "Couldn't get IRQ");
+ if (priv->parent_irq <= 0)
return -ENOENT;
- }
} else {
priv->parent_irq = -ENOENT;
}
diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c
index 712ae212b0b4..a4d3239d2594 100644
--- a/drivers/gpio/gpio-cadence.c
+++ b/drivers/gpio/gpio-cadence.c
@@ -214,27 +214,33 @@ static int cdns_gpio_probe(struct platform_device *pdev)
goto err_revert_dir;
}
- ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio);
- if (ret < 0) {
- dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
- goto err_disable_clk;
- }
-
/*
- * irq_chip support
+ * Optional irq_chip support
*/
irq = platform_get_irq(pdev, 0);
if (irq >= 0) {
- ret = gpiochip_irqchip_add(&cgpio->gc, &cdns_gpio_irqchip,
- 0, handle_level_irq,
- IRQ_TYPE_NONE);
- if (ret) {
- dev_err(&pdev->dev, "Could not add irqchip, %d\n",
- ret);
+ struct gpio_irq_chip *girq;
+
+ girq = &cgpio->gc.irq;
+ girq->chip = &cdns_gpio_irqchip;
+ girq->parent_handler = cdns_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents) {
+ ret = -ENOMEM;
goto err_disable_clk;
}
- gpiochip_set_chained_irqchip(&cgpio->gc, &cdns_gpio_irqchip,
- irq, cdns_gpio_irq_handler);
+ girq->parents[0] = irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
+ }
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ goto err_disable_clk;
}
cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE);
diff --git a/drivers/gpio/gpio-creg-snps.c b/drivers/gpio/gpio-creg-snps.c
index 8cbc94d0d424..ff19a8ad5663 100644
--- a/drivers/gpio/gpio-creg-snps.c
+++ b/drivers/gpio/gpio-creg-snps.c
@@ -137,7 +137,6 @@ static int creg_gpio_probe(struct platform_device *pdev)
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct creg_gpio *hcg;
- struct resource *mem;
u32 ngpios;
int ret;
@@ -145,8 +144,7 @@ static int creg_gpio_probe(struct platform_device *pdev)
if (!hcg)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hcg->regs = devm_ioremap_resource(dev, mem);
+ hcg->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hcg->regs))
return PTR_ERR(hcg->regs);
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 3108be5e208c..92e127e74813 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include "gpiolib.h"
+#include "gpiolib-acpi.h"
#define GPIO_SWPORTA_DR 0x00
#define GPIO_SWPORTA_DDR 0x04
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
index 7b9ac4a12c20..fe7a73f52329 100644
--- a/drivers/gpio/gpio-eic-sprd.c
+++ b/drivers/gpio/gpio-eic-sprd.c
@@ -584,10 +584,8 @@ static int sprd_eic_probe(struct platform_device *pdev)
sprd_eic->type = pdata->type;
sprd_eic->irq = platform_get_irq(pdev, 0);
- if (sprd_eic->irq < 0) {
- dev_err(&pdev->dev, "Failed to get EIC interrupt.\n");
+ if (sprd_eic->irq < 0)
return sprd_eic->irq;
- }
for (i = 0; i < SPRD_EIC_MAX_BANK; i++) {
/*
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index a87951293aaa..620f25b7efb4 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev)
struct resource *io[2], *irq[2];
struct gpio_chip *gpio_chip;
struct irq_chip *irq_chip;
- const char *name = dev_name(&pdev->dev);
+ struct device *dev = &pdev->dev;
+ const char *name = dev_name(dev);
unsigned int ngpios;
int ret;
- p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+ p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
@@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev)
irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
- dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
+ dev_err(dev, "missing IRQ or IOMEM\n");
return -EINVAL;
}
- p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start,
+ p->base0 = devm_ioremap_nocache(dev, io[0]->start,
resource_size(io[0]));
if (!p->base0)
return -ENOMEM;
- p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start,
+ p->base1 = devm_ioremap_nocache(dev, io[1]->start,
resource_size(io[1]));
if (!p->base1)
return -ENOMEM;
- if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
- dev_err(&pdev->dev, "Missing ngpios OF property\n");
+ if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
+ dev_err(dev, "Missing ngpios OF property\n");
return -EINVAL;
}
gpio_chip = &p->gpio_chip;
- gpio_chip->of_node = pdev->dev.of_node;
+ gpio_chip->of_node = dev->of_node;
gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output;
@@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->request = em_gio_request;
gpio_chip->free = em_gio_free;
gpio_chip->label = name;
- gpio_chip->parent = &pdev->dev;
+ gpio_chip->parent = dev;
gpio_chip->owner = THIS_MODULE;
gpio_chip->base = -1;
gpio_chip->ngpio = ngpios;
@@ -333,33 +334,33 @@ static int em_gio_probe(struct platform_device *pdev)
irq_chip->irq_release_resources = em_gio_irq_relres;
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
- p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0,
+ p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0,
&em_gio_irq_domain_ops, p);
if (!p->irq_domain) {
- dev_err(&pdev->dev, "cannot initialize irq domain\n");
+ dev_err(dev, "cannot initialize irq domain\n");
return -ENXIO;
}
- ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove,
+ ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove,
p->irq_domain);
if (ret)
return ret;
- if (devm_request_irq(&pdev->dev, irq[0]->start,
+ if (devm_request_irq(dev, irq[0]->start,
em_gio_irq_handler, 0, name, p)) {
- dev_err(&pdev->dev, "failed to request low IRQ\n");
+ dev_err(dev, "failed to request low IRQ\n");
return -ENOENT;
}
- if (devm_request_irq(&pdev->dev, irq[1]->start,
+ if (devm_request_irq(dev, irq[1]->start,
em_gio_irq_handler, 0, name, p)) {
- dev_err(&pdev->dev, "failed to request high IRQ\n");
+ dev_err(dev, "failed to request high IRQ\n");
return -ENOENT;
}
- ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p);
+ ret = devm_gpiochip_add_data(dev, gpio_chip, p);
if (ret) {
- dev_err(&pdev->dev, "failed to add GPIO controller\n");
+ dev_err(dev, "failed to add GPIO controller\n");
return ret;
}
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index a90870a60c15..226da8df6f10 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -269,56 +269,6 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
.irq_set_type = ep93xx_gpio_irq_type,
};
-static int ep93xx_gpio_init_irq(struct platform_device *pdev,
- struct ep93xx_gpio *epg)
-{
- int ab_parent_irq = platform_get_irq(pdev, 0);
- struct device *dev = &pdev->dev;
- int gpio_irq;
- int ret;
- int i;
-
- /* The A bank */
- ret = gpiochip_irqchip_add(&epg->gc[0], &ep93xx_gpio_irq_chip,
- 64, handle_level_irq,
- IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "Could not add irqchip 0\n");
- return ret;
- }
- gpiochip_set_chained_irqchip(&epg->gc[0], &ep93xx_gpio_irq_chip,
- ab_parent_irq,
- ep93xx_gpio_ab_irq_handler);
-
- /* The B bank */
- ret = gpiochip_irqchip_add(&epg->gc[1], &ep93xx_gpio_irq_chip,
- 72, handle_level_irq,
- IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "Could not add irqchip 1\n");
- return ret;
- }
- gpiochip_set_chained_irqchip(&epg->gc[1], &ep93xx_gpio_irq_chip,
- ab_parent_irq,
- ep93xx_gpio_ab_irq_handler);
-
- /* The F bank */
- for (i = 0; i < 8; i++) {
- gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;
- irq_set_chip_data(gpio_irq, &epg->gc[5]);
- irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
- handle_level_irq);
- irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
- }
-
- for (i = 1; i <= 8; i++)
- irq_set_chained_handler_and_data(platform_get_irq(pdev, i),
- ep93xx_gpio_f_irq_handler,
- &epg->gc[i]);
- return 0;
-}
-
-
/*************************************************************************
* gpiolib interface for EP93xx on-chip GPIOs
*************************************************************************/
@@ -328,26 +278,33 @@ struct ep93xx_gpio_bank {
int dir;
int base;
bool has_irq;
+ bool has_hierarchical_irq;
+ unsigned int irq_base;
};
-#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq) \
+#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq, _has_hier, _irq_base) \
{ \
.label = _label, \
.data = _data, \
.dir = _dir, \
.base = _base, \
.has_irq = _has_irq, \
+ .has_hierarchical_irq = _has_hier, \
+ .irq_base = _irq_base, \
}
static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
- EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true), /* Bank A has 8 IRQs */
- EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true), /* Bank B has 8 IRQs */
- EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
- EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
- EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
- EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true), /* Bank F has 8 IRQs */
- EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
- EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
+ /* Bank A has 8 IRQs */
+ EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true, false, 64),
+ /* Bank B has 8 IRQs */
+ EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true, false, 72),
+ EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false, false, 0),
+ EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false, false, 0),
+ EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false, false, 0),
+ /* Bank F has 8 IRQs */
+ EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, false, true, 0),
+ EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false, false, 0),
+ EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false, false, 0),
};
static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset,
@@ -369,12 +326,15 @@ static int ep93xx_gpio_f_to_irq(struct gpio_chip *gc, unsigned offset)
return EP93XX_GPIO_F_IRQ_BASE + offset;
}
-static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
+static int ep93xx_gpio_add_bank(struct gpio_chip *gc,
+ struct platform_device *pdev,
struct ep93xx_gpio *epg,
struct ep93xx_gpio_bank *bank)
{
void __iomem *data = epg->base + bank->data;
void __iomem *dir = epg->base + bank->dir;
+ struct device *dev = &pdev->dev;
+ struct gpio_irq_chip *girq;
int err;
err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0);
@@ -384,8 +344,59 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
gc->label = bank->label;
gc->base = bank->base;
- if (bank->has_irq)
+ girq = &gc->irq;
+ if (bank->has_irq || bank->has_hierarchical_irq) {
gc->set_config = ep93xx_gpio_set_config;
+ girq->chip = &ep93xx_gpio_irq_chip;
+ }
+
+ if (bank->has_irq) {
+ int ab_parent_irq = platform_get_irq(pdev, 0);
+
+ girq->parent_handler = ep93xx_gpio_ab_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
+ girq->parents[0] = ab_parent_irq;
+ girq->first = bank->irq_base;
+ }
+
+ /* Only bank F has especially funky IRQ handling */
+ if (bank->has_hierarchical_irq) {
+ int gpio_irq;
+ int i;
+
+ /*
+ * FIXME: convert this to use hierarchical IRQ support!
+ * this requires fixing the root irqchip to be hierarchial.
+ */
+ girq->parent_handler = ep93xx_gpio_f_irq_handler;
+ girq->num_parents = 8;
+ girq->parents = devm_kcalloc(dev, 8,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ /* Pick resources 1..8 for these IRQs */
+ for (i = 1; i <= 8; i++)
+ girq->parents[i - 1] = platform_get_irq(pdev, i);
+ for (i = 0; i < 8; i++) {
+ gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;
+ irq_set_chip_data(gpio_irq, &epg->gc[5]);
+ irq_set_chip_and_handler(gpio_irq,
+ &ep93xx_gpio_irq_chip,
+ handle_level_irq);
+ irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
+ }
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
+ gc->to_irq = ep93xx_gpio_f_to_irq;
+ }
return devm_gpiochip_add_data(dev, gc, epg);
}
@@ -407,16 +418,11 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
struct gpio_chip *gc = &epg->gc[i];
struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
- if (ep93xx_gpio_add_bank(gc, &pdev->dev, epg, bank))
+ if (ep93xx_gpio_add_bank(gc, pdev, epg, bank))
dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
bank->label);
- /* Only bank F has especially funky IRQ handling */
- if (i == 5)
- gc->to_irq = ep93xx_gpio_f_to_irq;
}
- ep93xx_gpio_init_irq(pdev, epg);
-
return 0;
}
diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c
index 250e71f3e688..fbddb1662428 100644
--- a/drivers/gpio/gpio-ftgpio010.c
+++ b/drivers/gpio/gpio-ftgpio010.c
@@ -290,16 +290,14 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
GFP_KERNEL);
- if (!girq->parents)
- return -ENOMEM;
+ if (!girq->parents) {
+ ret = -ENOMEM;
+ goto dis_clk;
+ }
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->parents[0] = irq;
- ret = devm_gpiochip_add_data(dev, &g->gc, g);
- if (ret)
- goto dis_clk;
-
/* Disable, unmask and clear all interrupts */
writel(0x0, g->base + GPIO_INT_EN);
writel(0x0, g->base + GPIO_INT_MASK);
@@ -308,6 +306,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
/* Clear any use of debounce */
writel(0x0, g->base + GPIO_DEBOUNCE_EN);
+ ret = devm_gpiochip_add_data(dev, &g->gc, g);
+ if (ret)
+ goto dis_clk;
+
platform_set_drvdata(pdev, g);
dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 0937b605e134..08234e64993a 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -408,8 +408,6 @@ static int grgpio_probe(struct platform_device *ofdev)
* Continue without irq functionality for that
* gpio line
*/
- dev_err(priv->dev,
- "Failed to get irq for offset %d\n", i);
continue;
}
priv->uirqs[lirq->index].uirq = ret;
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c
index e5fa00f8145f..4a17599f6d44 100644
--- a/drivers/gpio/gpio-hlwd.c
+++ b/drivers/gpio/gpio-hlwd.c
@@ -244,43 +244,45 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
ngpios = 32;
hlwd->gpioc.ngpio = ngpios;
- res = devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
- if (res)
- return res;
-
/* Mask and ack all interrupts */
iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK);
iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG);
/*
* If this GPIO controller is not marked as an interrupt controller in
- * the DT, return.
+ * the DT, skip interrupt support.
*/
- if (!of_property_read_bool(pdev->dev.of_node, "interrupt-controller"))
- return 0;
-
- hlwd->irq = platform_get_irq(pdev, 0);
- if (hlwd->irq < 0) {
- dev_info(&pdev->dev, "platform_get_irq returned %d\n",
- hlwd->irq);
- return hlwd->irq;
+ if (of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) {
+ struct gpio_irq_chip *girq;
+
+ hlwd->irq = platform_get_irq(pdev, 0);
+ if (hlwd->irq < 0) {
+ dev_info(&pdev->dev, "platform_get_irq returned %d\n",
+ hlwd->irq);
+ return hlwd->irq;
+ }
+
+ hlwd->irqc.name = dev_name(&pdev->dev);
+ hlwd->irqc.irq_mask = hlwd_gpio_irq_mask;
+ hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask;
+ hlwd->irqc.irq_enable = hlwd_gpio_irq_enable;
+ hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type;
+
+ girq = &hlwd->gpioc.irq;
+ girq->chip = &hlwd->irqc;
+ girq->parent_handler = hlwd_gpio_irqhandler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = hlwd->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
}
- hlwd->irqc.name = dev_name(&pdev->dev);
- hlwd->irqc.irq_mask = hlwd_gpio_irq_mask;
- hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask;
- hlwd->irqc.irq_enable = hlwd_gpio_irq_enable;
- hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type;
-
- res = gpiochip_irqchip_add(&hlwd->gpioc, &hlwd->irqc, 0,
- handle_level_irq, IRQ_TYPE_NONE);
- if (res)
- return res;
-
- gpiochip_set_chained_irqchip(&hlwd->gpioc, &hlwd->irqc,
- hlwd->irq, hlwd_gpio_irqhandler);
-
- return 0;
+ return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
}
static const struct of_device_id hlwd_gpio_match[] = {
diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c
index 9d3ac51a765c..6eb56f7ab9c9 100644
--- a/drivers/gpio/gpio-htc-egpio.c
+++ b/drivers/gpio/gpio-htc-egpio.c
@@ -118,20 +118,6 @@ static void egpio_handler(struct irq_desc *desc)
}
}
-int htc_egpio_get_wakeup_irq(struct device *dev)
-{
- struct egpio_info *ei = dev_get_drvdata(dev);
-
- /* Read current pins. */
- u16 readval = egpio_readw(ei, ei->ack_register);
- /* Ack/unmask interrupts. */
- ack_irqs(ei);
- /* Return first set pin. */
- readval &= ei->irqs_enabled;
- return ei->irq_start + ffs(readval) - 1;
-}
-EXPORT_SYMBOL(htc_egpio_get_wakeup_irq);
-
static inline int egpio_pos(struct egpio_info *ei, int bit)
{
return bit >> ei->reg_shift;
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index 4e803baf980e..4d835f9089df 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -329,6 +329,7 @@ static int intel_gpio_probe(struct pci_dev *pdev,
u32 gpio_base;
u32 irq_base;
int retval;
+ struct gpio_irq_chip *girq;
struct intel_mid_gpio_ddata *ddata =
(struct intel_mid_gpio_ddata *)id->driver_data;
@@ -369,6 +370,22 @@ static int intel_gpio_probe(struct pci_dev *pdev,
spin_lock_init(&priv->lock);
+ girq = &priv->chip.irq;
+ girq->chip = &intel_mid_irqchip;
+ girq->parent_handler = intel_mid_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = pdev->irq;
+ girq->first = irq_base;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+
+ intel_mid_irq_init_hw(priv);
+
pci_set_drvdata(pdev, priv);
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
if (retval) {
@@ -376,24 +393,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
return retval;
}
- retval = gpiochip_irqchip_add(&priv->chip,
- &intel_mid_irqchip,
- irq_base,
- handle_simple_irq,
- IRQ_TYPE_NONE);
- if (retval) {
- dev_err(&pdev->dev,
- "could not connect irqchip to gpiochip\n");
- return retval;
- }
-
- intel_mid_irq_init_hw(priv);
-
- gpiochip_set_chained_irqchip(&priv->chip,
- &intel_mid_irqchip,
- pdev->irq,
- intel_mid_irq_handler);
-
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
index 670c2a85a35b..b3b050604e0b 100644
--- a/drivers/gpio/gpio-ixp4xx.c
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -47,7 +47,6 @@
* @dev: containing device for this instance
* @fwnode: the fwnode for this GPIO chip
* @gc: gpiochip for this instance
- * @domain: irqdomain for this chip instance
* @base: remapped I/O-memory base
* @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
* 0: level triggered
@@ -56,48 +55,22 @@ struct ixp4xx_gpio {
struct device *dev;
struct fwnode_handle *fwnode;
struct gpio_chip gc;
- struct irq_domain *domain;
void __iomem *base;
unsigned long long irq_edge;
};
-/**
- * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
- * @gpio_offset: offset of the IXP4 GPIO line
- * @parent_hwirq: hwirq on the parent IRQ controller
- */
-struct ixp4xx_gpio_map {
- int gpio_offset;
- int parent_hwirq;
-};
-
-/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
-const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
- { .gpio_offset = 0, .parent_hwirq = 6 },
- { .gpio_offset = 1, .parent_hwirq = 7 },
- { .gpio_offset = 2, .parent_hwirq = 19 },
- { .gpio_offset = 3, .parent_hwirq = 20 },
- { .gpio_offset = 4, .parent_hwirq = 21 },
- { .gpio_offset = 5, .parent_hwirq = 22 },
- { .gpio_offset = 6, .parent_hwirq = 23 },
- { .gpio_offset = 7, .parent_hwirq = 24 },
- { .gpio_offset = 8, .parent_hwirq = 25 },
- { .gpio_offset = 9, .parent_hwirq = 26 },
- { .gpio_offset = 10, .parent_hwirq = 27 },
- { .gpio_offset = 11, .parent_hwirq = 28 },
- { .gpio_offset = 12, .parent_hwirq = 29 },
-};
-
static void ixp4xx_gpio_irq_ack(struct irq_data *d)
{
- struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct ixp4xx_gpio *g = gpiochip_get_data(gc);
__raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
}
static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
{
- struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct ixp4xx_gpio *g = gpiochip_get_data(gc);
/* ACK when unmasking if not edge-triggered */
if (!(g->irq_edge & BIT(d->hwirq)))
@@ -108,7 +81,8 @@ static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
- struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct ixp4xx_gpio *g = gpiochip_get_data(gc);
int line = d->hwirq;
unsigned long flags;
u32 int_style;
@@ -187,122 +161,31 @@ static struct irq_chip ixp4xx_gpio_irqchip = {
.irq_set_type = ixp4xx_gpio_irq_set_type,
};
-static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+static int ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
+ unsigned int child,
+ unsigned int child_type,
+ unsigned int *parent,
+ unsigned int *parent_type)
{
- struct ixp4xx_gpio *g = gpiochip_get_data(gc);
- struct irq_fwspec fwspec;
-
- fwspec.fwnode = g->fwnode;
- fwspec.param_count = 2;
- fwspec.param[0] = offset;
- fwspec.param[1] = IRQ_TYPE_NONE;
-
- return irq_create_fwspec_mapping(&fwspec);
-}
+ /* All these interrupts are level high in the CPU */
+ *parent_type = IRQ_TYPE_LEVEL_HIGH;
-static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
- struct irq_fwspec *fwspec,
- unsigned long *hwirq,
- unsigned int *type)
-{
- int ret;
-
- /* We support standard DT translation */
- if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
- return irq_domain_translate_twocell(domain, fwspec,
- hwirq, type);
+ /* GPIO lines 0..12 have dedicated IRQs */
+ if (child == 0) {
+ *parent = 6;
+ return 0;
}
-
- /* This goes away when we transition to DT */
- if (is_fwnode_irqchip(fwspec->fwnode)) {
- ret = irq_domain_translate_twocell(domain, fwspec,
- hwirq, type);
- if (ret)
- return ret;
- WARN_ON(*type == IRQ_TYPE_NONE);
+ if (child == 1) {
+ *parent = 7;
return 0;
}
- return -EINVAL;
-}
-
-static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
- unsigned int irq, unsigned int nr_irqs,
- void *data)
-{
- struct ixp4xx_gpio *g = d->host_data;
- irq_hw_number_t hwirq;
- unsigned int type = IRQ_TYPE_NONE;
- struct irq_fwspec *fwspec = data;
- int ret;
- int i;
-
- ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
- if (ret)
- return ret;
-
- dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
- irq, irq + nr_irqs - 1,
- hwirq, hwirq + nr_irqs - 1);
-
- for (i = 0; i < nr_irqs; i++) {
- struct irq_fwspec parent_fwspec;
- const struct ixp4xx_gpio_map *map;
- int j;
-
- /* Not all lines support IRQs */
- for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
- map = &ixp4xx_gpiomap[j];
- if (map->gpio_offset == hwirq)
- break;
- }
- if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
- dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
- return -EINVAL;
- }
- dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
-
- /*
- * We set handle_bad_irq because the .set_type() should
- * always be invoked and set the right type of handler.
- */
- irq_domain_set_info(d,
- irq + i,
- hwirq + i,
- &ixp4xx_gpio_irqchip,
- g,
- handle_bad_irq,
- NULL, NULL);
- irq_set_probe(irq + i);
-
- /*
- * Create a IRQ fwspec to send up to the parent irqdomain:
- * specify the hwirq we address on the parent and tie it
- * all together up the chain.
- */
- parent_fwspec.fwnode = d->parent->fwnode;
- parent_fwspec.param_count = 2;
- parent_fwspec.param[0] = map->parent_hwirq;
- /* This parent only handles asserted level IRQs */
- parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
- dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
- irq + i, map->parent_hwirq);
- ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
- &parent_fwspec);
- if (ret)
- dev_err(g->dev,
- "failed to allocate parent hwirq %d for hwirq %lu\n",
- map->parent_hwirq, hwirq);
+ if (child >= 2 && child <= 12) {
+ *parent = child + 17;
+ return 0;
}
-
- return 0;
+ return -EINVAL;
}
-static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
- .translate = ixp4xx_gpio_irq_domain_translate,
- .alloc = ixp4xx_gpio_irq_domain_alloc,
- .free = irq_domain_free_irqs_common,
-};
-
static int ixp4xx_gpio_probe(struct platform_device *pdev)
{
unsigned long flags;
@@ -311,8 +194,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
struct irq_domain *parent;
struct resource *res;
struct ixp4xx_gpio *g;
+ struct gpio_irq_chip *girq;
int ret;
- int i;
g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
if (!g)
@@ -321,9 +204,36 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
g->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(g->base)) {
- dev_err(dev, "ioremap error\n");
+ if (IS_ERR(g->base))
return PTR_ERR(g->base);
+
+ /*
+ * When we convert to device tree we will simply look up the
+ * parent irqdomain using irq_find_host(parent) as parent comes
+ * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
+ * the fwnode. For now we need this boardfile style code.
+ */
+ if (np) {
+ struct device_node *irq_parent;
+
+ irq_parent = of_irq_find_parent(np);
+ if (!irq_parent) {
+ dev_err(dev, "no IRQ parent node\n");
+ return -ENODEV;
+ }
+ parent = irq_find_host(irq_parent);
+ if (!parent) {
+ dev_err(dev, "no IRQ parent domain\n");
+ return -ENODEV;
+ }
+ g->fwnode = of_node_to_fwnode(np);
+ } else {
+ parent = ixp4xx_get_irq_domain();
+ g->fwnode = irq_domain_alloc_fwnode(&res->start);
+ if (!g->fwnode) {
+ dev_err(dev, "no domain base\n");
+ return -ENODEV;
+ }
}
/*
@@ -360,7 +270,6 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
dev_err(dev, "unable to init generic GPIO\n");
return ret;
}
- g->gc.to_irq = ixp4xx_gpio_to_irq;
g->gc.ngpio = 16;
g->gc.label = "IXP4XX_GPIO_CHIP";
/*
@@ -372,86 +281,22 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
g->gc.parent = &pdev->dev;
g->gc.owner = THIS_MODULE;
+ girq = &g->gc.irq;
+ girq->chip = &ixp4xx_gpio_irqchip;
+ girq->fwnode = g->fwnode;
+ girq->parent_domain = parent;
+ girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq;
+ girq->handler = handle_bad_irq;
+ girq->default_type = IRQ_TYPE_NONE;
+
ret = devm_gpiochip_add_data(dev, &g->gc, g);
if (ret) {
dev_err(dev, "failed to add SoC gpiochip\n");
return ret;
}
- /*
- * When we convert to device tree we will simply look up the
- * parent irqdomain using irq_find_host(parent) as parent comes
- * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
- * the fwnode. For now we need this boardfile style code.
- */
- if (np) {
- struct device_node *irq_parent;
-
- irq_parent = of_irq_find_parent(np);
- if (!irq_parent) {
- dev_err(dev, "no IRQ parent node\n");
- return -ENODEV;
- }
- parent = irq_find_host(irq_parent);
- if (!parent) {
- dev_err(dev, "no IRQ parent domain\n");
- return -ENODEV;
- }
- g->fwnode = of_node_to_fwnode(np);
- } else {
- parent = ixp4xx_get_irq_domain();
- g->fwnode = irq_domain_alloc_fwnode(g->base);
- if (!g->fwnode) {
- dev_err(dev, "no domain base\n");
- return -ENODEV;
- }
- }
- g->domain = irq_domain_create_hierarchy(parent,
- IRQ_DOMAIN_FLAG_HIERARCHY,
- ARRAY_SIZE(ixp4xx_gpiomap),
- g->fwnode,
- &ixp4xx_gpio_irqdomain_ops,
- g);
- if (!g->domain) {
- irq_domain_free_fwnode(g->fwnode);
- dev_err(dev, "no hierarchical irq domain\n");
- return ret;
- }
-
- /*
- * After adding OF support, this is no longer needed: irqs
- * will be allocated for the respective fwnodes.
- */
- if (!np) {
- for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
- const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
- struct irq_fwspec fwspec;
-
- fwspec.fwnode = g->fwnode;
- /* This is the hwirq for the GPIO line side of things */
- fwspec.param[0] = map->gpio_offset;
- fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
- fwspec.param_count = 2;
- ret = __irq_domain_alloc_irqs(g->domain,
- -1, /* just pick something */
- 1,
- NUMA_NO_NODE,
- &fwspec,
- false,
- NULL);
- if (ret < 0) {
- irq_domain_free_fwnode(g->fwnode);
- dev_err(dev,
- "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
- map->gpio_offset, map->parent_hwirq,
- ret);
- return ret;
- }
- }
- }
-
platform_set_drvdata(pdev, g);
- dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
+ dev_info(dev, "IXP4 GPIO registered\n");
return 0;
}
diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c
deleted file mode 100644
index a0f87c124894..000000000000
--- a/drivers/gpio/gpio-ks8695.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ks8695/gpio.c
- *
- * Copyright (C) 2006 Andrew Victor
- * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- */
-#include <linux/gpio/driver.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/irq.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/gpio-ks8695.h>
-
-/*
- * Configure a GPIO line for either GPIO function, or its internal
- * function (Interrupt, Timer, etc).
- */
-static void ks8695_gpio_mode(unsigned int pin, short gpio)
-{
- unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
- unsigned long x, flags;
-
- if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */
- return;
-
- local_irq_save(flags);
-
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
- if (gpio) /* GPIO: set bit to 0 */
- x &= ~enable[pin];
- else /* Internal function: set bit to 1 */
- x |= enable[pin];
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
-
- local_irq_restore(flags);
-}
-
-
-static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
-{
- unsigned long x, flags;
-
- if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
- return -EINVAL;
-
- local_irq_save(flags);
-
- /* set pin as input */
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
- x &= ~IOPM(pin);
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
- local_irq_restore(flags);
-
- /* Set IRQ triggering type */
- irq_set_irq_type(gpio_irq[pin], type);
-
- /* enable interrupt mode */
- ks8695_gpio_mode(pin, 0);
-
- return 0;
-}
-EXPORT_SYMBOL(ks8695_gpio_interrupt);
-
-
-
-/* .... Generic GPIO interface .............................................. */
-
-/*
- * Configure the GPIO line as an input.
- */
-static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
-{
- unsigned long x, flags;
-
- if (pin > KS8695_GPIO_15)
- return -EINVAL;
-
- /* set pin to GPIO mode */
- ks8695_gpio_mode(pin, 1);
-
- local_irq_save(flags);
-
- /* set pin as input */
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
- x &= ~IOPM(pin);
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-
-/*
- * Configure the GPIO line as an output, with default state.
- */
-static int ks8695_gpio_direction_output(struct gpio_chip *gc,
- unsigned int pin, int state)
-{
- unsigned long x, flags;
-
- if (pin > KS8695_GPIO_15)
- return -EINVAL;
-
- /* set pin to GPIO mode */
- ks8695_gpio_mode(pin, 1);
-
- local_irq_save(flags);
-
- /* set line state */
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
- if (state)
- x |= IOPD(pin);
- else
- x &= ~IOPD(pin);
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
- /* set pin as output */
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
- x |= IOPM(pin);
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-
-/*
- * Set the state of an output GPIO line.
- */
-static void ks8695_gpio_set_value(struct gpio_chip *gc,
- unsigned int pin, int state)
-{
- unsigned long x, flags;
-
- if (pin > KS8695_GPIO_15)
- return;
-
- local_irq_save(flags);
-
- /* set output line state */
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
- if (state)
- x |= IOPD(pin);
- else
- x &= ~IOPD(pin);
- __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
- local_irq_restore(flags);
-}
-
-
-/*
- * Read the state of a GPIO line.
- */
-static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
-{
- unsigned long x;
-
- if (pin > KS8695_GPIO_15)
- return -EINVAL;
-
- x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
- return (x & IOPD(pin)) != 0;
-}
-
-
-/*
- * Map GPIO line to IRQ number.
- */
-static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
-{
- if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
- return -EINVAL;
-
- return gpio_irq[pin];
-}
-
-/* GPIOLIB interface */
-
-static struct gpio_chip ks8695_gpio_chip = {
- .label = "KS8695",
- .direction_input = ks8695_gpio_direction_input,
- .direction_output = ks8695_gpio_direction_output,
- .get = ks8695_gpio_get_value,
- .set = ks8695_gpio_set_value,
- .to_irq = ks8695_gpio_to_irq,
- .base = 0,
- .ngpio = 16,
- .can_sleep = false,
-};
-
-/* Register the GPIOs */
-void ks8695_register_gpios(void)
-{
- if (gpiochip_add_data(&ks8695_gpio_chip, NULL))
- printk(KERN_ERR "Unable to register core GPIOs\n");
-}
-
-/* .... Debug interface ..................................................... */
-
-#ifdef CONFIG_DEBUG_FS
-
-static int ks8695_gpio_show(struct seq_file *s, void *unused)
-{
- unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
- unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
- unsigned long mode, ctrl, data;
- int i;
-
- mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
- ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
- data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-
- seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
-
- for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
- seq_printf(s, "%i:\t", i);
-
- seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
-
- if (i <= KS8695_GPIO_3) {
- if (ctrl & enable[i]) {
- seq_printf(s, "EXT%i ", i);
-
- switch ((ctrl & intmask[i]) >> (4 * i)) {
- case IOPC_TM_LOW:
- seq_printf(s, "(Low)"); break;
- case IOPC_TM_HIGH:
- seq_printf(s, "(High)"); break;
- case IOPC_TM_RISING:
- seq_printf(s, "(Rising)"); break;
- case IOPC_TM_FALLING:
- seq_printf(s, "(Falling)"); break;
- case IOPC_TM_EDGE:
- seq_printf(s, "(Edges)"); break;
- }
- } else
- seq_printf(s, "GPIO\t");
- } else if (i <= KS8695_GPIO_5) {
- if (ctrl & enable[i])
- seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
- else
- seq_printf(s, "GPIO\t");
- } else {
- seq_printf(s, "GPIO\t");
- }
-
- seq_printf(s, "\t");
-
- seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
- }
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(ks8695_gpio);
-
-static int __init ks8695_gpio_debugfs_init(void)
-{
- /* /sys/kernel/debug/ks8695_gpio */
- debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL,
- &ks8695_gpio_fops);
- return 0;
-}
-postcore_initcall(ks8695_gpio_debugfs_init);
-
-#endif
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 24885b3db3d5..4e626c4235c2 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -16,36 +16,33 @@
#include <linux/platform_device.h>
#include <linux/module.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
-
-#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
-#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
-#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008)
-#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C)
-#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010)
-#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014)
-#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018)
-#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C)
-#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020)
-#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024)
-#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028)
-#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C)
-#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030)
-#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040)
-#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044)
-#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048)
-#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C)
-#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050)
-#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054)
-#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058)
-#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060)
-#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064)
-#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068)
-#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C)
-#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070)
-#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074)
-#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078)
+#define LPC32XX_GPIO_P3_INP_STATE (0x000)
+#define LPC32XX_GPIO_P3_OUTP_SET (0x004)
+#define LPC32XX_GPIO_P3_OUTP_CLR (0x008)
+#define LPC32XX_GPIO_P3_OUTP_STATE (0x00C)
+#define LPC32XX_GPIO_P2_DIR_SET (0x010)
+#define LPC32XX_GPIO_P2_DIR_CLR (0x014)
+#define LPC32XX_GPIO_P2_DIR_STATE (0x018)
+#define LPC32XX_GPIO_P2_INP_STATE (0x01C)
+#define LPC32XX_GPIO_P2_OUTP_SET (0x020)
+#define LPC32XX_GPIO_P2_OUTP_CLR (0x024)
+#define LPC32XX_GPIO_P2_MUX_SET (0x028)
+#define LPC32XX_GPIO_P2_MUX_CLR (0x02C)
+#define LPC32XX_GPIO_P2_MUX_STATE (0x030)
+#define LPC32XX_GPIO_P0_INP_STATE (0x040)
+#define LPC32XX_GPIO_P0_OUTP_SET (0x044)
+#define LPC32XX_GPIO_P0_OUTP_CLR (0x048)
+#define LPC32XX_GPIO_P0_OUTP_STATE (0x04C)
+#define LPC32XX_GPIO_P0_DIR_SET (0x050)
+#define LPC32XX_GPIO_P0_DIR_CLR (0x054)
+#define LPC32XX_GPIO_P0_DIR_STATE (0x058)
+#define LPC32XX_GPIO_P1_INP_STATE (0x060)
+#define LPC32XX_GPIO_P1_OUTP_SET (0x064)
+#define LPC32XX_GPIO_P1_OUTP_CLR (0x068)
+#define LPC32XX_GPIO_P1_OUTP_STATE (0x06C)
+#define LPC32XX_GPIO_P1_DIR_SET (0x070)
+#define LPC32XX_GPIO_P1_DIR_CLR (0x074)
+#define LPC32XX_GPIO_P1_DIR_STATE (0x078)
#define GPIO012_PIN_TO_BIT(x) (1 << (x))
#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25))
@@ -72,12 +69,12 @@
#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
struct gpio_regs {
- void __iomem *inp_state;
- void __iomem *outp_state;
- void __iomem *outp_set;
- void __iomem *outp_clr;
- void __iomem *dir_set;
- void __iomem *dir_clr;
+ unsigned long inp_state;
+ unsigned long outp_state;
+ unsigned long outp_set;
+ unsigned long outp_clr;
+ unsigned long dir_set;
+ unsigned long dir_clr;
};
/*
@@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = {
struct lpc32xx_gpio_chip {
struct gpio_chip chip;
struct gpio_regs *gpio_grp;
+ void __iomem *reg_base;
};
+static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)
+{
+ return __raw_readl(group->reg_base + offset);
+}
+
+static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)
+{
+ __raw_writel(val, group->reg_base + offset);
+}
+
static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int input)
{
if (input)
- __raw_writel(GPIO012_PIN_TO_BIT(pin),
+ gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_clr);
else
- __raw_writel(GPIO012_PIN_TO_BIT(pin),
+ gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_set);
}
@@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin);
if (input)
- __raw_writel(u, group->gpio_grp->dir_clr);
+ gpreg_write(group, u, group->gpio_grp->dir_clr);
else
- __raw_writel(u, group->gpio_grp->dir_set);
+ gpreg_write(group, u, group->gpio_grp->dir_set);
}
static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int high)
{
if (high)
- __raw_writel(GPIO012_PIN_TO_BIT(pin),
+ gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_set);
else
- __raw_writel(GPIO012_PIN_TO_BIT(pin),
+ gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_clr);
}
@@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin);
if (high)
- __raw_writel(u, group->gpio_grp->outp_set);
+ gpreg_write(group, u, group->gpio_grp->outp_set);
else
- __raw_writel(u, group->gpio_grp->outp_clr);
+ gpreg_write(group, u, group->gpio_grp->outp_clr);
}
static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
unsigned pin, int high)
{
if (high)
- __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
+ gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
else
- __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
+ gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
}
static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
- return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
+ return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),
pin);
}
static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
- int state = __raw_readl(group->gpio_grp->inp_state);
+ int state = gpreg_read(group, group->gpio_grp->inp_state);
/*
* P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
@@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
- return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
+ return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);
}
static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
- return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
+ return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);
}
/*
@@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
static int lpc32xx_gpio_probe(struct platform_device *pdev)
{
int i;
+ void __iomem *reg_base;
+
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg_base))
+ return PTR_ERR(reg_base);
for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
if (pdev->dev.of_node) {
lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
+ lpc32xx_gpiochip[i].reg_base = reg_base;
}
devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
&lpc32xx_gpiochip[i]);
@@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = {
};
module_platform_driver(lpc32xx_gpio_driver);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 31b4a091ab60..6bb9741ad036 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -358,25 +358,30 @@ static int lp_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false;
gc->parent = dev;
- ret = devm_gpiochip_add_data(dev, gc, lg);
- if (ret) {
- dev_err(dev, "failed adding lp-gpio chip\n");
- return ret;
- }
-
/* set up interrupts */
if (irq_rc && irq_rc->start) {
+ struct gpio_irq_chip *girq;
+
+ girq = &gc->irq;
+ girq->chip = &lp_irqchip;
+ girq->parent_handler = lp_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = (unsigned)irq_rc->start;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+
lp_gpio_irq_init_hw(lg);
- ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "failed to add irqchip\n");
- return ret;
- }
+ }
- gpiochip_set_chained_irqchip(gc, &lp_irqchip,
- (unsigned)irq_rc->start,
- lp_gpio_irq_handler);
+ ret = devm_gpiochip_add_data(dev, gc, lg);
+ if (ret) {
+ dev_err(dev, "failed adding lp-gpio chip\n");
+ return ret;
}
pm_runtime_enable(dev);
diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c
index 4dbc837d1215..7086f8b5388f 100644
--- a/drivers/gpio/gpio-madera.c
+++ b/drivers/gpio/gpio-madera.c
@@ -120,7 +120,7 @@ static const struct gpio_chip madera_gpio_chip = {
static int madera_gpio_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
- struct madera_pdata *pdata = dev_get_platdata(madera->dev);
+ struct madera_pdata *pdata = &madera->pdata;
struct madera_gpio *madera_gpio;
int ret;
@@ -136,6 +136,9 @@ static int madera_gpio_probe(struct platform_device *pdev)
madera_gpio->gpio_chip.parent = pdev->dev.parent;
switch (madera->type) {
+ case CS47L15:
+ madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS;
+ break;
case CS47L35:
madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
break;
@@ -147,13 +150,18 @@ static int madera_gpio_probe(struct platform_device *pdev)
case CS47L91:
madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
break;
+ case CS42L92:
+ case CS47L92:
+ case CS47L93:
+ madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS;
+ break;
default:
dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
return -EINVAL;
}
/* We want to be usable on systems that don't use devicetree or acpi */
- if (pdata && pdata->gpio_base)
+ if (pdata->gpio_base)
madera_gpio->gpio_chip.base = pdata->gpio_base;
else
madera_gpio->gpio_chip.base = -1;
diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c
index b7d89e30131e..47d05e357e61 100644
--- a/drivers/gpio/gpio-max77620.c
+++ b/drivers/gpio/gpio-max77620.c
@@ -270,10 +270,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
int ret;
gpio_irq = platform_get_irq(pdev, 0);
- if (gpio_irq <= 0) {
- dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq);
+ if (gpio_irq <= 0)
return -ENODEV;
- }
mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
if (!mgpio)
diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c
index 3f03f4e8956c..3075f2513c6f 100644
--- a/drivers/gpio/gpio-max77650.c
+++ b/drivers/gpio/gpio-max77650.c
@@ -188,3 +188,4 @@ module_platform_driver(max77650_gpio_driver);
MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver");
MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:max77650-gpio");
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index 8f466993cd24..501e89548f53 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include "gpiolib.h"
+#include "gpiolib-acpi.h"
/*
* Only first 8bits of a register correspond to each pin,
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index 3302125e5265..4f27ddfe1e2f 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -397,6 +397,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
{
const struct mrfld_gpio_pinrange *range;
const char *pinctrl_dev_name;
+ struct gpio_irq_chip *girq;
struct mrfld_gpio *priv;
u32 gpio_base, irq_base;
void __iomem *base;
@@ -444,6 +445,21 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
raw_spin_lock_init(&priv->lock);
+ girq = &priv->chip.irq;
+ girq->chip = &mrfld_irqchip;
+ girq->parent_handler = mrfld_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = pdev->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+ mrfld_irq_init_hw(priv);
+
pci_set_drvdata(pdev, priv);
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
if (retval) {
@@ -465,18 +481,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
}
}
- retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
- handle_bad_irq, IRQ_TYPE_NONE);
- if (retval) {
- dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
- return retval;
- }
-
- mrfld_irq_init_hw(priv);
-
- gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
- mrfld_irq_handler);
-
return 0;
}
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index f1a9c0544e3f..213aedc97dc2 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -309,6 +309,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = {
.read = gpio_mockup_debugfs_read,
.write = gpio_mockup_debugfs_write,
.llseek = no_llseek,
+ .release = single_release,
};
static void gpio_mockup_debugfs_setup(struct device *dev,
diff --git a/drivers/gpio/gpio-moxtet.c b/drivers/gpio/gpio-moxtet.c
new file mode 100644
index 000000000000..3fd729994a38
--- /dev/null
+++ b/drivers/gpio/gpio-moxtet.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Turris Mox Moxtet GPIO expander
+ *
+ * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/moxtet.h>
+#include <linux/module.h>
+
+#define MOXTET_GPIO_NGPIOS 12
+#define MOXTET_GPIO_INPUTS 4
+
+struct moxtet_gpio_desc {
+ u16 in_mask;
+ u16 out_mask;
+};
+
+static const struct moxtet_gpio_desc descs[] = {
+ [TURRIS_MOX_MODULE_SFP] = {
+ .in_mask = GENMASK(2, 0),
+ .out_mask = GENMASK(5, 4),
+ },
+};
+
+struct moxtet_gpio_chip {
+ struct device *dev;
+ struct gpio_chip gpio_chip;
+ const struct moxtet_gpio_desc *desc;
+};
+
+static int moxtet_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
+{
+ struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
+ int ret;
+
+ if (chip->desc->in_mask & BIT(offset)) {
+ ret = moxtet_device_read(chip->dev);
+ } else if (chip->desc->out_mask & BIT(offset)) {
+ ret = moxtet_device_written(chip->dev);
+ if (ret >= 0)
+ ret <<= MOXTET_GPIO_INPUTS;
+ } else {
+ return -EINVAL;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return !!(ret & BIT(offset));
+}
+
+static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
+ int val)
+{
+ struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
+ int state;
+
+ state = moxtet_device_written(chip->dev);
+ if (state < 0)
+ return;
+
+ offset -= MOXTET_GPIO_INPUTS;
+
+ if (val)
+ state |= BIT(offset);
+ else
+ state &= ~BIT(offset);
+
+ moxtet_device_write(chip->dev, state);
+}
+
+static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
+
+ /* All lines are hard wired to be either input or output, not both. */
+ if (chip->desc->in_mask & BIT(offset))
+ return 1;
+ else if (chip->desc->out_mask & BIT(offset))
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static int moxtet_gpio_direction_input(struct gpio_chip *gc,
+ unsigned int offset)
+{
+ struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
+
+ if (chip->desc->in_mask & BIT(offset))
+ return 0;
+ else if (chip->desc->out_mask & BIT(offset))
+ return -ENOTSUPP;
+ else
+ return -EINVAL;
+}
+
+static int moxtet_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int offset, int val)
+{
+ struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
+
+ if (chip->desc->out_mask & BIT(offset))
+ moxtet_gpio_set_value(gc, offset, val);
+ else if (chip->desc->in_mask & BIT(offset))
+ return -ENOTSUPP;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int moxtet_gpio_probe(struct device *dev)
+{
+ struct moxtet_gpio_chip *chip;
+ struct device_node *nc = dev->of_node;
+ int id;
+
+ id = to_moxtet_device(dev)->id;
+
+ if (id >= ARRAY_SIZE(descs)) {
+ dev_err(dev, "%pOF Moxtet device id 0x%x is not supported by gpio-moxtet driver\n",
+ nc, id);
+ return -ENOTSUPP;
+ }
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = dev;
+ chip->gpio_chip.parent = dev;
+ chip->desc = &descs[id];
+
+ dev_set_drvdata(dev, chip);
+
+ chip->gpio_chip.label = dev_name(dev);
+ chip->gpio_chip.get_direction = moxtet_gpio_get_direction;
+ chip->gpio_chip.direction_input = moxtet_gpio_direction_input;
+ chip->gpio_chip.direction_output = moxtet_gpio_direction_output;
+ chip->gpio_chip.get = moxtet_gpio_get_value;
+ chip->gpio_chip.set = moxtet_gpio_set_value;
+ chip->gpio_chip.base = -1;
+
+ chip->gpio_chip.ngpio = MOXTET_GPIO_NGPIOS;
+
+ chip->gpio_chip.can_sleep = true;
+ chip->gpio_chip.owner = THIS_MODULE;
+
+ return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip);
+}
+
+static const struct of_device_id moxtet_gpio_dt_ids[] = {
+ { .compatible = "cznic,moxtet-gpio", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, moxtet_gpio_dt_ids);
+
+static const enum turris_mox_module_id moxtet_gpio_module_table[] = {
+ TURRIS_MOX_MODULE_SFP,
+ 0,
+};
+
+static struct moxtet_driver moxtet_gpio_driver = {
+ .driver = {
+ .name = "moxtet-gpio",
+ .of_match_table = moxtet_gpio_dt_ids,
+ .probe = moxtet_gpio_probe,
+ },
+ .id_table = moxtet_gpio_module_table,
+};
+module_moxtet_driver(moxtet_gpio_driver);
+
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
+MODULE_DESCRIPTION("Turris Mox Moxtet GPIO expander");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index c8673a5d9412..16a47de29c94 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -32,6 +32,7 @@
#define GPIO_IMR 0x10
#define GPIO_ICR 0x14
#define GPIO_ICR2 0x18
+#define GPIO_IBE 0x18
struct mpc8xxx_gpio_chip {
struct gpio_chip gc;
@@ -45,6 +46,27 @@ struct mpc8xxx_gpio_chip {
unsigned int irqn;
};
+/* The GPIO Input Buffer Enable register(GPIO_IBE) is used to
+ * control the input enable of each individual GPIO port.
+ * When an individual GPIO port’s direction is set to
+ * input (GPIO_GPDIR[DRn=0]), the associated input enable must be
+ * set (GPIOxGPIE[IEn]=1) to propagate the port value to the GPIO
+ * Data Register.
+ */
+static int ls1028a_gpio_dir_in_init(struct gpio_chip *gc)
+{
+ unsigned long flags;
+ struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc);
+
+ spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+ gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
+
+ spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+ return 0;
+}
+
/*
* This hardware has a big endian bit assignment such that GPIO line 0 is
* connected to bit 31, line 1 to bit 30 ... line 31 to bit 0.
@@ -261,6 +283,7 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
};
struct mpc8xxx_gpio_devtype {
+ int (*gpio_dir_in_init)(struct gpio_chip *chip);
int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int);
int (*gpio_get)(struct gpio_chip *, unsigned int);
int (*irq_set_type)(struct irq_data *, unsigned int);
@@ -271,6 +294,10 @@ static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = {
.irq_set_type = mpc512x_irq_set_type,
};
+static const struct mpc8xxx_gpio_devtype ls1028a_gpio_devtype = {
+ .gpio_dir_in_init = ls1028a_gpio_dir_in_init,
+};
+
static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = {
.gpio_dir_out = mpc5125_gpio_dir_out,
.irq_set_type = mpc512x_irq_set_type,
@@ -291,6 +318,8 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
{ .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, },
{ .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, },
{ .compatible = "fsl,pq3-gpio", },
+ { .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, },
+ { .compatible = "fsl,ls1088a-gpio", .data = &ls1028a_gpio_devtype, },
{ .compatible = "fsl,qoriq-gpio", },
{}
};
@@ -376,6 +405,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
/* ack and mask all irqs */
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0);
+ /* enable input buffer */
+ if (devtype->gpio_dir_in_init)
+ devtype->gpio_dir_in_init(gc);
irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index 79654fb2e50f..d1d785f983a7 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -241,13 +241,6 @@ mediatek_gpio_bank_probe(struct device *dev,
if (!rg->chip.label)
return -ENOMEM;
- ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
- if (ret < 0) {
- dev_err(dev, "Could not register gpio %d, ret=%d\n",
- rg->chip.ngpio, ret);
- return ret;
- }
-
rg->irq_chip.name = dev_name(dev);
rg->irq_chip.parent_device = dev;
rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
@@ -256,8 +249,10 @@ mediatek_gpio_bank_probe(struct device *dev,
rg->irq_chip.irq_set_type = mediatek_gpio_irq_type;
if (mtk->gpio_irq) {
+ struct gpio_irq_chip *girq;
+
/*
- * Manually request the irq here instead of passing
+ * Directly request the irq here instead of passing
* a flow-handler to gpiochip_set_chained_irqchip,
* because the irq is shared.
*/
@@ -271,15 +266,21 @@ mediatek_gpio_bank_probe(struct device *dev,
return ret;
}
- ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip,
- 0, handle_simple_irq, IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "failed to add gpiochip_irqchip\n");
- return ret;
- }
+ girq = &rg->chip.irq;
+ girq->chip = &rg->irq_chip;
+ /* This will let us handle the parent IRQ in the driver */
+ girq->parent_handler = NULL;
+ girq->num_parents = 0;
+ girq->parents = NULL;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+ }
- gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip,
- mtk->gpio_irq, NULL);
+ ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
+ if (ret < 0) {
+ dev_err(dev, "Could not register gpio %d, ret=%d\n",
+ rg->chip.ngpio, ret);
+ return ret;
}
/* set polarity to low for all gpios */
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index b2813580c582..7907a8755866 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -435,12 +435,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return port->irq;
/* the controller clock is optional */
- port->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(port->clk)) {
- if (PTR_ERR(port->clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- port->clk = NULL;
- }
+ port->clk = devm_clk_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(port->clk))
+ return PTR_ERR(port->clk);
err = clk_prepare_enable(port->clk);
if (err) {
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 378b206d2dc9..de5d1383f28d 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -9,6 +9,7 @@
*/
#include <linux/acpi.h>
+#include <linux/bits.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
@@ -28,9 +29,9 @@
#define PCA953X_INVERT 0x02
#define PCA953X_DIRECTION 0x03
-#define REG_ADDR_MASK 0x3f
-#define REG_ADDR_EXT 0x40
-#define REG_ADDR_AI 0x80
+#define REG_ADDR_MASK GENMASK(5, 0)
+#define REG_ADDR_EXT BIT(6)
+#define REG_ADDR_AI BIT(7)
#define PCA957X_IN 0x00
#define PCA957X_INVRT 0x01
@@ -55,17 +56,17 @@
#define PCAL6524_OUT_INDCONF 0x2c
#define PCAL6524_DEBOUNCE 0x2d
-#define PCA_GPIO_MASK 0x00FF
+#define PCA_GPIO_MASK GENMASK(7, 0)
-#define PCAL_GPIO_MASK 0x1f
-#define PCAL_PINCTRL_MASK 0x60
+#define PCAL_GPIO_MASK GENMASK(4, 0)
+#define PCAL_PINCTRL_MASK GENMASK(6, 5)
-#define PCA_INT 0x0100
-#define PCA_PCAL 0x0200
+#define PCA_INT BIT(8)
+#define PCA_PCAL BIT(9)
#define PCA_LATCH_INT (PCA_PCAL | PCA_INT)
-#define PCA953X_TYPE 0x1000
-#define PCA957X_TYPE 0x2000
-#define PCA_TYPE_MASK 0xF000
+#define PCA953X_TYPE BIT(12)
+#define PCA957X_TYPE BIT(13)
+#define PCA_TYPE_MASK GENMASK(15, 12)
#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK)
@@ -565,7 +566,7 @@ static void pca953x_irq_mask(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pca953x_chip *chip = gpiochip_get_data(gc);
- chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
+ chip->irq_mask[d->hwirq / BANK_SZ] &= ~BIT(d->hwirq % BANK_SZ);
}
static void pca953x_irq_unmask(struct irq_data *d)
@@ -573,7 +574,7 @@ static void pca953x_irq_unmask(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pca953x_chip *chip = gpiochip_get_data(gc);
- chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
+ chip->irq_mask[d->hwirq / BANK_SZ] |= BIT(d->hwirq % BANK_SZ);
}
static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -604,10 +605,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
u8 new_irqs;
int level, i;
u8 invert_irq_mask[MAX_BANK];
- int reg_direction[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
- regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
- NBANK(chip));
+ pca953x_read_regs(chip, chip->regs->direction, reg_direction);
if (chip->driver_data & PCA_PCAL) {
/* Enable latch on interrupt-enabled inputs */
@@ -641,7 +641,7 @@ 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);
int bank_nb = d->hwirq / BANK_SZ;
- u8 mask = 1 << (d->hwirq % BANK_SZ);
+ u8 mask = BIT(d->hwirq % BANK_SZ);
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -666,7 +666,7 @@ static void pca953x_irq_shutdown(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pca953x_chip *chip = gpiochip_get_data(gc);
- u8 mask = 1 << (d->hwirq % BANK_SZ);
+ u8 mask = BIT(d->hwirq % BANK_SZ);
chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask;
chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask;
@@ -679,7 +679,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
bool pending_seen = false;
bool trigger_seen = false;
u8 trigger[MAX_BANK];
- int reg_direction[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
int ret, i;
if (chip->driver_data & PCA_PCAL) {
@@ -710,8 +710,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
return false;
/* Remove output pins from the equation */
- regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
- NBANK(chip));
+ pca953x_read_regs(chip, chip->regs->direction, reg_direction);
for (i = 0; i < NBANK(chip); i++)
cur_stat[i] &= reg_direction[i];
@@ -768,7 +767,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
{
struct i2c_client *client = chip->client;
struct irq_chip *irq_chip = &chip->irq_chip;
- int reg_direction[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
int ret, i;
if (!client->irq)
@@ -789,8 +788,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
* interrupt. We have to rely on the previous read for
* this purpose.
*/
- regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
- NBANK(chip));
+ pca953x_read_regs(chip, chip->regs->direction, reg_direction);
for (i = 0; i < NBANK(chip); i++)
chip->irq_stat[i] &= reg_direction[i];
mutex_init(&chip->irq_lock);
@@ -849,12 +847,12 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert)
ret = regcache_sync_region(chip->regmap, chip->regs->output,
chip->regs->output + NBANK(chip));
- if (ret != 0)
+ if (ret)
goto out;
ret = regcache_sync_region(chip->regmap, chip->regs->direction,
chip->regs->direction + NBANK(chip));
- if (ret != 0)
+ if (ret)
goto out;
/* set platform specific polarity inversion */
@@ -949,19 +947,15 @@ static int pca953x_probe(struct i2c_client *client,
if (i2c_id) {
chip->driver_data = i2c_id->driver_data;
} else {
- const struct acpi_device_id *acpi_id;
- struct device *dev = &client->dev;
-
- chip->driver_data = (uintptr_t)of_device_get_match_data(dev);
- if (!chip->driver_data) {
- acpi_id = acpi_match_device(pca953x_acpi_ids, dev);
- if (!acpi_id) {
- ret = -ENODEV;
- goto err_exit;
- }
-
- chip->driver_data = acpi_id->driver_data;
+ const void *match;
+
+ match = device_get_match_data(&client->dev);
+ if (!match) {
+ ret = -ENODEV;
+ goto err_exit;
}
+
+ chip->driver_data = (uintptr_t)match;
}
i2c_set_clientdata(client, chip);
@@ -1041,8 +1035,7 @@ static int pca953x_remove(struct i2c_client *client)
ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)
- dev_err(&client->dev, "%s failed, %d\n",
- "teardown", ret);
+ dev_err(&client->dev, "teardown failed, %d\n", ret);
} else {
ret = 0;
}
@@ -1064,14 +1057,14 @@ static int pca953x_regcache_sync(struct device *dev)
*/
ret = regcache_sync_region(chip->regmap, chip->regs->direction,
chip->regs->direction + NBANK(chip));
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret);
return ret;
}
ret = regcache_sync_region(chip->regmap, chip->regs->output,
chip->regs->output + NBANK(chip));
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret);
return ret;
}
@@ -1080,7 +1073,7 @@ static int pca953x_regcache_sync(struct device *dev)
if (chip->driver_data & PCA_PCAL) {
ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH,
PCAL953X_IN_LATCH + NBANK(chip));
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to sync INT latch registers: %d\n",
ret);
return ret;
@@ -1088,7 +1081,7 @@ static int pca953x_regcache_sync(struct device *dev)
ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK,
PCAL953X_INT_MASK + NBANK(chip));
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to sync INT mask registers: %d\n",
ret);
return ret;
@@ -1120,7 +1113,7 @@ static int pca953x_resume(struct device *dev)
if (!atomic_read(&chip->wakeup_path)) {
ret = regulator_enable(chip->regulator);
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return 0;
}
@@ -1133,7 +1126,7 @@ static int pca953x_resume(struct device *dev)
return ret;
ret = regcache_sync(chip->regmap);
- if (ret != 0) {
+ if (ret) {
dev_err(dev, "Failed to restore register map: %d\n", ret);
return ret;
}
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 1d99293096f2..3f3d9a94b709 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -409,8 +409,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
static int __maybe_unused pch_gpio_suspend(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct pch_gpio *chip = pci_get_drvdata(pdev);
+ struct pch_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
@@ -422,8 +421,7 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev)
static int __maybe_unused pch_gpio_resume(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct pch_gpio *chip = pci_get_drvdata(pdev);
+ struct pch_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c
index 24228cf79afc..05000cace9b2 100644
--- a/drivers/gpio/gpio-pmic-eic-sprd.c
+++ b/drivers/gpio/gpio-pmic-eic-sprd.c
@@ -305,10 +305,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev)
mutex_init(&pmic_eic->buslock);
pmic_eic->irq = platform_get_irq(pdev, 0);
- if (pmic_eic->irq < 0) {
- dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n");
+ if (pmic_eic->irq < 0)
return pmic_eic->irq;
- }
pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL);
if (!pmic_eic->map)
diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c
index f5c8b3a351d5..d7314d39ab65 100644
--- a/drivers/gpio/gpio-sprd.c
+++ b/drivers/gpio/gpio-sprd.c
@@ -226,10 +226,8 @@ static int sprd_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
sprd_gpio->irq = platform_get_irq(pdev, 0);
- if (sprd_gpio->irq < 0) {
- dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n");
+ if (sprd_gpio->irq < 0)
return sprd_gpio->irq;
- }
sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sprd_gpio->base))
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index dbf9cbe36b2b..994d542daf53 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
+static void stmpe_init_irq_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
+ int i;
+
+ if (!stmpe_gpio->norequest_mask)
+ return;
+
+ /* Forbid unused lines to be mapped as IRQs */
+ for (i = 0; i < sizeof(u32); i++) {
+ if (stmpe_gpio->norequest_mask & BIT(i))
+ clear_bit(i, valid_mask);
+ }
+}
+
static int stmpe_gpio_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
@@ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
stmpe_gpio->chip.parent = &pdev->dev;
stmpe_gpio->chip.of_node = np;
stmpe_gpio->chip.base = -1;
+ /*
+ * REVISIT: this makes sure the valid mask gets allocated and
+ * filled in when adding the gpio_chip, but the rest of the
+ * gpio_irqchip is still filled in using the old method
+ * in gpiochip_irqchip_add_nested() so clean this up once we
+ * get the gpio_irqchip to initialize while adding the
+ * gpio_chip also for threaded irqchips.
+ */
+ stmpe_gpio->chip.irq.init_valid_mask = stmpe_init_irq_valid_mask;
if (IS_ENABLED(CONFIG_DEBUG_FS))
stmpe_gpio->chip.dbg_show = stmpe_dbg_show;
of_property_read_u32(np, "st,norequest-mask",
&stmpe_gpio->norequest_mask);
- if (stmpe_gpio->norequest_mask)
- stmpe_gpio->chip.irq.need_valid_mask = true;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_disable;
}
- if (stmpe_gpio->norequest_mask) {
- int i;
-
- /* Forbid unused lines to be mapped as IRQs */
- for (i = 0; i < sizeof(u32); i++)
- if (stmpe_gpio->norequest_mask & BIT(i))
- clear_bit(i, stmpe_gpio->chip.irq.valid_mask);
- }
ret = gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
&stmpe_gpio_irq_chip,
0,
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
index bd1f3f775ce9..5e375186f90e 100644
--- a/drivers/gpio/gpio-tb10x.c
+++ b/drivers/gpio/gpio-tb10x.c
@@ -171,10 +171,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
struct irq_chip_generic *gc;
ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "No interrupt specified.\n");
+ if (ret < 0)
return ret;
- }
tb10x_gpio->gc.to_irq = tb10x_gpio_to_irq;
tb10x_gpio->irq = ret;
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 0f59161a4701..8a01d3694b28 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -624,10 +624,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
for (i = 0; i < tgi->bank_count; i++) {
ret = platform_get_irq(pdev, i);
- if (ret < 0) {
- dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret);
+ if (ret < 0)
return ret;
- }
bank = &tgi->bank_info[i];
bank->bank = i;
diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c
index 715371b5102a..ddad5c7ea617 100644
--- a/drivers/gpio/gpio-thunderx.c
+++ b/drivers/gpio/gpio-thunderx.c
@@ -53,7 +53,6 @@ struct thunderx_line {
struct thunderx_gpio {
struct gpio_chip chip;
u8 __iomem *register_base;
- struct irq_domain *irqd;
struct msix_entry *msix_entries; /* per line MSI-X */
struct thunderx_line *line_entries; /* per line irq info */
raw_spinlock_t lock;
@@ -283,54 +282,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
}
}
-static void thunderx_gpio_irq_ack(struct irq_data *data)
+static void thunderx_gpio_irq_ack(struct irq_data *d)
{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_INTR,
- txline->txgpio->register_base + intr_reg(txline->line));
+ txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
}
-static void thunderx_gpio_irq_mask(struct irq_data *data)
+static void thunderx_gpio_irq_mask(struct irq_data *d)
{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1C,
- txline->txgpio->register_base + intr_reg(txline->line));
+ txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
}
-static void thunderx_gpio_irq_mask_ack(struct irq_data *data)
+static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
- txline->txgpio->register_base + intr_reg(txline->line));
+ txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
}
-static void thunderx_gpio_irq_unmask(struct irq_data *data)
+static void thunderx_gpio_irq_unmask(struct irq_data *d)
{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1S,
- txline->txgpio->register_base + intr_reg(txline->line));
+ txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
}
-static int thunderx_gpio_irq_set_type(struct irq_data *data,
+static int thunderx_gpio_irq_set_type(struct irq_data *d,
unsigned int flow_type)
{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
- struct thunderx_gpio *txgpio = txline->txgpio;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+ struct thunderx_line *txline =
+ &txgpio->line_entries[irqd_to_hwirq(d)];
u64 bit_cfg;
- irqd_set_trigger_type(data, flow_type);
+ irqd_set_trigger_type(d, flow_type);
bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
if (flow_type & IRQ_TYPE_EDGE_BOTH) {
- irq_set_handler_locked(data, handle_fasteoi_ack_irq);
+ irq_set_handler_locked(d, handle_fasteoi_ack_irq);
bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
} else {
- irq_set_handler_locked(data, handle_fasteoi_mask_irq);
+ irq_set_handler_locked(d, handle_fasteoi_mask_irq);
}
raw_spin_lock(&txgpio->lock);
@@ -359,33 +364,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
irq_chip_disable_parent(data);
}
-static int thunderx_gpio_irq_request_resources(struct irq_data *data)
-{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
- struct thunderx_gpio *txgpio = txline->txgpio;
- int r;
-
- r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
- if (r)
- return r;
-
- r = irq_chip_request_resources_parent(data);
- if (r)
- gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
-
- return r;
-}
-
-static void thunderx_gpio_irq_release_resources(struct irq_data *data)
-{
- struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
- struct thunderx_gpio *txgpio = txline->txgpio;
-
- irq_chip_release_resources_parent(data);
-
- gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
-}
-
/*
* Interrupts are chained from underlying MSI-X vectors. We have
* these irq_chip functions to be able to handle level triggering
@@ -402,48 +380,22 @@ static struct irq_chip thunderx_gpio_irq_chip = {
.irq_unmask = thunderx_gpio_irq_unmask,
.irq_eoi = irq_chip_eoi_parent,
.irq_set_affinity = irq_chip_set_affinity_parent,
- .irq_request_resources = thunderx_gpio_irq_request_resources,
- .irq_release_resources = thunderx_gpio_irq_release_resources,
.irq_set_type = thunderx_gpio_irq_set_type,
.flags = IRQCHIP_SET_TYPE_MASKED
};
-static int thunderx_gpio_irq_translate(struct irq_domain *d,
- struct irq_fwspec *fwspec,
- irq_hw_number_t *hwirq,
- unsigned int *type)
+static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
+ unsigned int child,
+ unsigned int child_type,
+ unsigned int *parent,
+ unsigned int *parent_type)
{
- struct thunderx_gpio *txgpio = d->host_data;
-
- if (WARN_ON(fwspec->param_count < 2))
- return -EINVAL;
- if (fwspec->param[0] >= txgpio->chip.ngpio)
- return -EINVAL;
- *hwirq = fwspec->param[0];
- *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
- return 0;
-}
-
-static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq,
- unsigned int nr_irqs, void *arg)
-{
- struct thunderx_line *txline = arg;
+ struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
- return irq_domain_set_hwirq_and_chip(d, virq, txline->line,
- &thunderx_gpio_irq_chip, txline);
-}
-
-static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
- .alloc = thunderx_gpio_irq_alloc,
- .translate = thunderx_gpio_irq_translate
-};
-
-static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
- struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
-
- return irq_find_mapping(txgpio->irqd, offset);
+ *parent = txgpio->base_msi + (2 * child);
+ *parent_type = IRQ_TYPE_LEVEL_HIGH;
+ return 0;
}
static int thunderx_gpio_probe(struct pci_dev *pdev,
@@ -453,6 +405,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
struct device *dev = &pdev->dev;
struct thunderx_gpio *txgpio;
struct gpio_chip *chip;
+ struct gpio_irq_chip *girq;
int ngpio, i;
int err = 0;
@@ -497,8 +450,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
}
txgpio->msix_entries = devm_kcalloc(dev,
- ngpio, sizeof(struct msix_entry),
- GFP_KERNEL);
+ ngpio, sizeof(struct msix_entry),
+ GFP_KERNEL);
if (!txgpio->msix_entries) {
err = -ENOMEM;
goto out;
@@ -539,27 +492,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
if (err < 0)
goto out;
- /*
- * Push GPIO specific irqdomain on hierarchy created as a side
- * effect of the pci_enable_msix()
- */
- txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
- 0, 0, of_node_to_fwnode(dev->of_node),
- &thunderx_gpio_irqd_ops, txgpio);
- if (!txgpio->irqd) {
- err = -ENOMEM;
- goto out;
- }
-
- /* Push on irq_data and the domain for each line. */
- for (i = 0; i < ngpio; i++) {
- err = irq_domain_push_irq(txgpio->irqd,
- txgpio->msix_entries[i].vector,
- &txgpio->line_entries[i]);
- if (err < 0)
- dev_err(dev, "irq_domain_push_irq: %d\n", err);
- }
-
chip->label = KBUILD_MODNAME;
chip->parent = dev;
chip->owner = THIS_MODULE;
@@ -574,11 +506,28 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
chip->set = thunderx_gpio_set;
chip->set_multiple = thunderx_gpio_set_multiple;
chip->set_config = thunderx_gpio_set_config;
- chip->to_irq = thunderx_gpio_to_irq;
+ girq = &chip->irq;
+ girq->chip = &thunderx_gpio_irq_chip;
+ girq->fwnode = of_node_to_fwnode(dev->of_node);
+ girq->parent_domain =
+ irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
+ girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
+ girq->handler = handle_bad_irq;
+ girq->default_type = IRQ_TYPE_NONE;
+
err = devm_gpiochip_add_data(dev, chip, txgpio);
if (err)
goto out;
+ /* Push on irq_data and the domain for each line. */
+ for (i = 0; i < ngpio; i++) {
+ err = irq_domain_push_irq(chip->irq.domain,
+ txgpio->msix_entries[i].vector,
+ chip);
+ if (err < 0)
+ dev_err(dev, "irq_domain_push_irq: %d\n", err);
+ }
+
dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
ngpio, chip->base);
return 0;
@@ -593,10 +542,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
for (i = 0; i < txgpio->chip.ngpio; i++)
- irq_domain_pop_irq(txgpio->irqd,
+ irq_domain_pop_irq(txgpio->chip.irq.domain,
txgpio->msix_entries[i].vector);
- irq_domain_remove(txgpio->irqd);
+ irq_domain_remove(txgpio->chip.irq.domain);
pci_set_drvdata(pdev, NULL);
}
diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c
index d5880db7f9d4..a3109bcaa0ac 100644
--- a/drivers/gpio/gpio-tqmx86.c
+++ b/drivers/gpio/gpio-tqmx86.c
@@ -214,11 +214,23 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = {
tqmx86_gpio_runtime_resume, NULL)
};
+static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ /* Only GPIOs 4-7 are valid for interrupts. Clear the others */
+ clear_bit(0, valid_mask);
+ clear_bit(1, valid_mask);
+ clear_bit(2, valid_mask);
+ clear_bit(3, valid_mask);
+}
+
static int tqmx86_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tqmx86_gpio_data *gpio;
struct gpio_chip *chip;
+ struct gpio_irq_chip *girq;
void __iomem *io_base;
struct resource *res;
int ret, irq;
@@ -259,17 +271,10 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
chip->get = tqmx86_gpio_get;
chip->set = tqmx86_gpio_set;
chip->ngpio = TQMX86_NGPIO;
- chip->irq.need_valid_mask = true;
chip->parent = pdev->dev.parent;
pm_runtime_enable(&pdev->dev);
- ret = devm_gpiochip_add_data(dev, chip, gpio);
- if (ret) {
- dev_err(dev, "Could not register GPIO chip\n");
- goto out_pm_dis;
- }
-
if (irq) {
struct irq_chip *irq_chip = &gpio->irq_chip;
u8 irq_status;
@@ -287,23 +292,28 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
- ret = gpiochip_irqchip_add(chip, irq_chip,
- 0, handle_simple_irq,
- IRQ_TYPE_EDGE_BOTH);
- if (ret) {
- dev_err(dev, "Could not add irq chip\n");
+ girq = &chip->irq;
+ girq->chip = irq_chip;
+ girq->parent_handler = tqmx86_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents) {
+ ret = -ENOMEM;
goto out_pm_dis;
}
-
- gpiochip_set_chained_irqchip(chip, irq_chip,
- irq, tqmx86_gpio_irq_handler);
+ girq->parents[0] = irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+ girq->init_valid_mask = tqmx86_init_irq_valid_mask;
}
- /* Only GPIOs 4-7 are valid for interrupts. Clear the others */
- clear_bit(0, chip->irq.valid_mask);
- clear_bit(1, chip->irq.valid_mask);
- clear_bit(2, chip->irq.valid_mask);
- clear_bit(3, chip->irq.valid_mask);
+ ret = devm_gpiochip_add_data(dev, chip, gpio);
+ if (ret) {
+ dev_err(dev, "Could not register GPIO chip\n");
+ goto out_pm_dis;
+ }
dev_info(dev, "GPIO functionality initialized with %d pins\n",
chip->ngpio);
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 7ba668db171b..58776f2d69ff 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -243,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct vf610_gpio_port *port;
struct gpio_chip *gc;
+ struct gpio_irq_chip *girq;
struct irq_chip *ic;
int i;
int ret;
@@ -318,10 +319,6 @@ static int vf610_gpio_probe(struct platform_device *pdev)
ic->irq_set_type = vf610_gpio_irq_set_type;
ic->irq_set_wake = vf610_gpio_irq_set_wake;
- ret = devm_gpiochip_add_data(dev, gc, port);
- if (ret < 0)
- return ret;
-
/* Mask all GPIO interrupts */
for (i = 0; i < gc->ngpio; i++)
vf610_gpio_writel(0, port->base + PORT_PCR(i));
@@ -329,15 +326,20 @@ static int vf610_gpio_probe(struct platform_device *pdev)
/* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR);
- ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "failed to add irqchip\n");
- return ret;
- }
- gpiochip_set_chained_irqchip(gc, ic, port->irq,
- vf610_gpio_irq_handler);
+ girq = &gc->irq;
+ girq->chip = ic;
+ girq->parent_handler = vf610_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = port->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_edge_irq;
- return 0;
+ return devm_gpiochip_add_data(dev, gc, port);
}
static struct platform_driver vf610_gpio_driver = {
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c
index 9b604f13e302..c301c1d56dd2 100644
--- a/drivers/gpio/gpio-viperboard.c
+++ b/drivers/gpio/gpio-viperboard.c
@@ -79,7 +79,7 @@ MODULE_PARM_DESC(gpioa_freq,
/* ----- begin of gipo a chip -------------------------------------------- */
static int vprbrd_gpioa_get(struct gpio_chip *chip,
- unsigned offset)
+ unsigned int offset)
{
int ret, answer, error = 0;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -129,7 +129,7 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip,
}
static void vprbrd_gpioa_set(struct gpio_chip *chip,
- unsigned offset, int value)
+ unsigned int offset, int value)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -170,7 +170,7 @@ static void vprbrd_gpioa_set(struct gpio_chip *chip,
}
static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
- unsigned offset)
+ unsigned int offset)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -207,7 +207,7 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
}
static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
+ unsigned int offset, int value)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -251,8 +251,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
/* ----- begin of gipo b chip -------------------------------------------- */
-static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset,
- unsigned dir)
+static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset,
+ unsigned int dir)
{
struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
int ret;
@@ -273,7 +273,7 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset,
}
static int vprbrd_gpiob_get(struct gpio_chip *chip,
- unsigned offset)
+ unsigned int offset)
{
int ret;
u16 val;
@@ -305,7 +305,7 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip,
}
static void vprbrd_gpiob_set(struct gpio_chip *chip,
- unsigned offset, int value)
+ unsigned int offset, int value)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -338,7 +338,7 @@ static void vprbrd_gpiob_set(struct gpio_chip *chip,
}
static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
- unsigned offset)
+ unsigned int offset)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
@@ -359,7 +359,7 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
}
static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
+ unsigned int offset, int value)
{
int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index 38c01912c7b2..25d86441666e 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -16,6 +16,7 @@
#include <linux/acpi.h>
#include "gpiolib.h"
+#include "gpiolib-acpi.h"
/* Common property names */
#define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c
index 54d3359444f3..d7b16bb9e4e4 100644
--- a/drivers/gpio/gpio-xlp.c
+++ b/drivers/gpio/gpio-xlp.c
@@ -290,6 +290,7 @@ MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids);
static int xlp_gpio_probe(struct platform_device *pdev)
{
struct gpio_chip *gc;
+ struct gpio_irq_chip *girq;
struct xlp_gpio_priv *priv;
void __iomem *gpio_base;
int irq_base, irq, err;
@@ -395,27 +396,27 @@ static int xlp_gpio_probe(struct platform_device *pdev)
irq_base = 0;
}
+ girq = &gc->irq;
+ girq->chip = &xlp_gpio_irq_chip;
+ girq->parent_handler = xlp_gpio_generic_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = irq;
+ girq->first = irq_base;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
+
err = gpiochip_add_data(gc, priv);
if (err < 0)
return err;
- err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
- handle_level_irq, IRQ_TYPE_NONE);
- if (err) {
- dev_err(&pdev->dev, "Could not connect irqchip to gpiochip!\n");
- goto out_gpio_remove;
- }
-
- gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq,
- xlp_gpio_generic_handler);
-
dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio);
return 0;
-
-out_gpio_remove:
- gpiochip_remove(gc);
- return err;
}
#ifdef CONFIG_ACPI
diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c
index 8637adb6bc20..98cbaf0e415e 100644
--- a/drivers/gpio/gpio-zx.c
+++ b/drivers/gpio/gpio-zx.c
@@ -215,6 +215,7 @@ static int zx_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct zx_gpio *chip;
+ struct gpio_irq_chip *girq;
int irq, id, ret;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
@@ -242,32 +243,30 @@ static int zx_gpio_probe(struct platform_device *pdev)
chip->gc.parent = dev;
chip->gc.owner = THIS_MODULE;
- ret = gpiochip_add_data(&chip->gc, chip);
- if (ret)
- return ret;
-
/*
* irq_chip support
*/
writew_relaxed(0xffff, chip->base + ZX_GPIO_IM);
writew_relaxed(0, chip->base + ZX_GPIO_IE);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "invalid IRQ\n");
- gpiochip_remove(&chip->gc);
- return -ENODEV;
- }
+ if (irq < 0)
+ return irq;
+ girq = &chip->gc.irq;
+ girq->chip = &zx_irqchip;
+ girq->parent_handler = zx_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
- ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip,
- 0, handle_simple_irq,
- IRQ_TYPE_NONE);
- if (ret) {
- dev_err(dev, "could not add irqchip\n");
- gpiochip_remove(&chip->gc);
+ ret = gpiochip_add_data(&chip->gc, chip);
+ if (ret)
return ret;
- }
- gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip,
- irq, zx_irq_handler);
platform_set_drvdata(pdev, chip);
dev_info(dev, "ZX GPIO chip registered\n");
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index f241b6c13dbe..cd475ff4bcad 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -830,6 +830,7 @@ static int zynq_gpio_probe(struct platform_device *pdev)
int ret, bank_num;
struct zynq_gpio *gpio;
struct gpio_chip *chip;
+ struct gpio_irq_chip *girq;
const struct of_device_id *match;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
@@ -849,10 +850,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
return PTR_ERR(gpio->base_addr);
gpio->irq = platform_get_irq(pdev, 0);
- if (gpio->irq < 0) {
- dev_err(&pdev->dev, "invalid IRQ\n");
+ if (gpio->irq < 0)
return gpio->irq;
- }
/* configure the gpio chip */
chip = &gpio->chip;
@@ -887,34 +886,38 @@ static int zynq_gpio_probe(struct platform_device *pdev)
if (ret < 0)
goto err_pm_dis;
- /* report a bug if gpio chip registration fails */
- ret = gpiochip_add_data(chip, gpio);
- if (ret) {
- dev_err(&pdev->dev, "Failed to add gpio chip\n");
- goto err_pm_put;
- }
-
/* disable interrupts for all banks */
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
- ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0,
- handle_level_irq, IRQ_TYPE_NONE);
- if (ret) {
- dev_err(&pdev->dev, "Failed to add irq chip\n");
- goto err_rm_gpiochip;
+ /* Set up the GPIO irqchip */
+ girq = &chip->irq;
+ girq->chip = &zynq_gpio_edge_irqchip;
+ girq->parent_handler = zynq_gpio_irqhandler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents) {
+ ret = -ENOMEM;
+ goto err_pm_put;
}
+ girq->parents[0] = gpio->irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
- gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq,
- zynq_gpio_irqhandler);
+ /* report a bug if gpio chip registration fails */
+ ret = gpiochip_add_data(chip, gpio);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add gpio chip\n");
+ goto err_pm_put;
+ }
pm_runtime_put(&pdev->dev);
return 0;
-err_rm_gpiochip:
- gpiochip_remove(chip);
err_pm_put:
pm_runtime_put(&pdev->dev);
err_pm_dis:
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 39f2f9035c11..609ed16ae933 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -7,6 +7,7 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
+#include <linux/dmi.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
@@ -18,6 +19,12 @@
#include <linux/pinctrl/pinctrl.h>
#include "gpiolib.h"
+#include "gpiolib-acpi.h"
+
+static int run_edge_events_on_boot = -1;
+module_param(run_edge_events_on_boot, int, 0444);
+MODULE_PARM_DESC(run_edge_events_on_boot,
+ "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
/**
* struct acpi_gpio_event - ACPI GPIO event handler data
@@ -170,10 +177,13 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
event->irq_requested = true;
/* Make sure we trigger the initial state of edge-triggered IRQs */
- value = gpiod_get_raw_value_cansleep(event->desc);
- if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
- ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
- event->handler(event->irq, event);
+ if (run_edge_events_on_boot &&
+ (event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
+ value = gpiod_get_raw_value_cansleep(event->desc);
+ if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
+ ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+ event->handler(event->irq, event);
+ }
}
static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
@@ -382,6 +392,13 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev,
}
EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
+void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
+{
+ if (adev)
+ adev->driver_gpios = NULL;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios);
+
static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res)
{
acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev));
@@ -720,6 +737,16 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ret ? ERR_PTR(ret) : lookup.desc;
}
+static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
+ const char *con_id)
+{
+ /* Never allow fallback if the device has properties */
+ if (acpi_dev_has_props(adev) || adev->driver_gpios)
+ return false;
+
+ return con_id == NULL;
+}
+
struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
@@ -1256,15 +1283,6 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
return count ? count : -ENOENT;
}
-bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id)
-{
- /* Never allow fallback if the device has properties */
- if (acpi_dev_has_props(adev) || adev->driver_gpios)
- return false;
-
- return con_id == NULL;
-}
-
/* Run deferred acpi_gpiochip_request_irqs() */
static int acpi_gpio_handle_deferred_request_irqs(void)
{
@@ -1283,3 +1301,28 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
}
/* We must use _sync so that this runs after the first deferred_probe run */
late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
+
+static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
+ }
+ },
+ {} /* Terminating entry */
+};
+
+static int acpi_gpio_setup_params(void)
+{
+ if (run_edge_events_on_boot < 0) {
+ if (dmi_check_system(run_edge_events_on_boot_blacklist))
+ run_edge_events_on_boot = 0;
+ else
+ run_edge_events_on_boot = 1;
+ }
+
+ return 0;
+}
+
+/* Directly after dmi_setup() which runs as core_initcall() */
+postcore_initcall(acpi_gpio_setup_params);
diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h
new file mode 100644
index 000000000000..1c6d65cf0629
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012,2019 Intel Corporation
+ */
+
+#ifndef GPIOLIB_ACPI_H
+#define GPIOLIB_ACPI_H
+
+struct acpi_device;
+
+/**
+ * struct acpi_gpio_info - ACPI GPIO specific information
+ * @adev: reference to ACPI device which consumes GPIO resource
+ * @flags: GPIO initialization flags
+ * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
+ * @pin_config: pin bias as provided by ACPI
+ * @polarity: interrupt polarity as provided by ACPI
+ * @triggering: triggering type as provided by ACPI
+ * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
+ */
+struct acpi_gpio_info {
+ struct acpi_device *adev;
+ enum gpiod_flags flags;
+ bool gpioint;
+ int pin_config;
+ int polarity;
+ int triggering;
+ unsigned int quirks;
+};
+
+#ifdef CONFIG_ACPI
+void acpi_gpiochip_add(struct gpio_chip *chip);
+void acpi_gpiochip_remove(struct gpio_chip *chip);
+
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
+
+int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
+ struct acpi_gpio_info *info);
+int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
+ struct acpi_gpio_info *info);
+
+struct gpio_desc *acpi_find_gpio(struct device *dev,
+ const char *con_id,
+ unsigned int idx,
+ enum gpiod_flags *dflags,
+ unsigned long *lookupflags);
+struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
+ const char *propname, int index,
+ struct acpi_gpio_info *info);
+
+int acpi_gpio_count(struct device *dev, const char *con_id);
+#else
+static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
+static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
+
+static inline void
+acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
+
+static inline void
+acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
+
+static inline int
+acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
+{
+ return 0;
+}
+static inline int
+acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
+ struct acpi_gpio_info *info)
+{
+ return 0;
+}
+
+static inline struct gpio_desc *
+acpi_find_gpio(struct device *dev, const char *con_id,
+ unsigned int idx, enum gpiod_flags *dflags,
+ unsigned long *lookupflags)
+{
+ return ERR_PTR(-ENOENT);
+}
+static inline struct gpio_desc *
+acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
+ int index, struct acpi_gpio_info *info)
+{
+ return ERR_PTR(-ENXIO);
+}
+static inline int acpi_gpio_count(struct device *dev, const char *con_id)
+{
+ return -ENODEV;
+}
+#endif
+
+#endif /* GPIOLIB_ACPI_H */
diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c
index 0acc2cc6e868..98e3c20d9730 100644
--- a/drivers/gpio/gpiolib-devres.c
+++ b/drivers/gpio/gpiolib-devres.c
@@ -59,7 +59,7 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
{
return devm_gpiod_get_index(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL(devm_gpiod_get);
+EXPORT_SYMBOL_GPL(devm_gpiod_get);
/**
* devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
@@ -77,7 +77,7 @@ struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
{
return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL(devm_gpiod_get_optional);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_optional);
/**
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
@@ -127,7 +127,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_gpiod_get_index);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_index);
/**
* devm_gpiod_get_from_of_node() - obtain a GPIO from an OF node
@@ -182,7 +182,7 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_gpiod_get_from_of_node);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
/**
* devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
@@ -239,7 +239,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_fwnode_get_index_gpiod_from_child);
+EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child);
/**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
@@ -268,7 +268,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_gpiod_get_index_optional);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional);
/**
* devm_gpiod_get_array - Resource-managed gpiod_get_array()
@@ -303,7 +303,7 @@ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
return descs;
}
-EXPORT_SYMBOL(devm_gpiod_get_array);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_array);
/**
* devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
@@ -328,7 +328,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
return descs;
}
-EXPORT_SYMBOL(devm_gpiod_get_array_optional);
+EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional);
/**
* devm_gpiod_put - Resource-managed gpiod_put()
@@ -344,7 +344,7 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
&desc));
}
-EXPORT_SYMBOL(devm_gpiod_put);
+EXPORT_SYMBOL_GPL(devm_gpiod_put);
/**
* devm_gpiod_unhinge - Remove resource management from a gpio descriptor
@@ -374,7 +374,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
/* Anything else we should warn about */
WARN_ON(ret);
}
-EXPORT_SYMBOL(devm_gpiod_unhinge);
+EXPORT_SYMBOL_GPL(devm_gpiod_unhinge);
/**
* devm_gpiod_put_array - Resource-managed gpiod_put_array()
@@ -390,7 +390,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
WARN_ON(devres_release(dev, devm_gpiod_release_array,
devm_gpiod_match_array, &descs));
}
-EXPORT_SYMBOL(devm_gpiod_put_array);
+EXPORT_SYMBOL_GPL(devm_gpiod_put_array);
@@ -444,7 +444,7 @@ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
return 0;
}
-EXPORT_SYMBOL(devm_gpio_request);
+EXPORT_SYMBOL_GPL(devm_gpio_request);
/**
* devm_gpio_request_one - request a single GPIO with initial setup
@@ -474,7 +474,7 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
return 0;
}
-EXPORT_SYMBOL(devm_gpio_request_one);
+EXPORT_SYMBOL_GPL(devm_gpio_request_one);
/**
* devm_gpio_free - free a GPIO
@@ -492,4 +492,4 @@ void devm_gpio_free(struct device *dev, unsigned int gpio)
WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
&gpio));
}
-EXPORT_SYMBOL(devm_gpio_free);
+EXPORT_SYMBOL_GPL(devm_gpio_free);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 567fb98c0892..1eea2c6c2e1d 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -21,6 +21,34 @@
#include <linux/gpio/machine.h>
#include "gpiolib.h"
+#include "gpiolib-of.h"
+
+/*
+ * This is used by external users of of_gpio_count() from <linux/of_gpio.h>
+ *
+ * FIXME: get rid of those external users by converting them to GPIO
+ * descriptors and let them all use gpiod_get_count()
+ */
+int of_gpio_get_count(struct device *dev, const char *con_id)
+{
+ int ret;
+ char propname[32];
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+ if (con_id)
+ snprintf(propname, sizeof(propname), "%s-%s",
+ con_id, gpio_suffixes[i]);
+ else
+ snprintf(propname, sizeof(propname), "%s",
+ gpio_suffixes[i]);
+
+ ret = of_gpio_named_count(dev->of_node, propname);
+ if (ret > 0)
+ break;
+ }
+ return ret ? ret : -ENOENT;
+}
static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data)
{
@@ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
return gpiochip_get_desc(chip, ret);
}
+/**
+ * of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs
+ * to set the .valid_mask
+ * @dev: the device for the GPIO provider
+ * @return: true if the valid mask needs to be set
+ */
+bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
+{
+ int size;
+ struct device_node *np = gc->of_node;
+
+ size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
+ if (size > 0 && size % 2 == 0)
+ return true;
+ return false;
+}
+
static void of_gpio_flags_quirks(struct device_node *np,
const char *propname,
enum of_gpio_flags *flags,
@@ -178,7 +223,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
-struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags)
{
struct of_phandle_args gpiospec;
@@ -229,7 +274,76 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
else
return desc_to_gpio(desc);
}
-EXPORT_SYMBOL(of_get_named_gpio_flags);
+EXPORT_SYMBOL_GPL(of_get_named_gpio_flags);
+
+/**
+ * gpiod_get_from_of_node() - obtain a GPIO from an OF node
+ * @node: handle of the OF node
+ * @propname: name of the DT property representing the GPIO
+ * @index: index of the GPIO to obtain for the consumer
+ * @dflags: GPIO initialization flags
+ * @label: label to attach to the requested GPIO
+ *
+ * Returns:
+ * On successful request the GPIO pin is configured in accordance with
+ * provided @dflags.
+ *
+ * In case of error an ERR_PTR() is returned.
+ */
+struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label)
+{
+ unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ struct gpio_desc *desc;
+ enum of_gpio_flags flags;
+ bool active_low = false;
+ bool single_ended = false;
+ bool open_drain = false;
+ bool transitory = false;
+ int ret;
+
+ desc = of_get_named_gpiod_flags(node, propname,
+ index, &flags);
+
+ if (!desc || IS_ERR(desc)) {
+ return desc;
+ }
+
+ active_low = flags & OF_GPIO_ACTIVE_LOW;
+ single_ended = flags & OF_GPIO_SINGLE_ENDED;
+ open_drain = flags & OF_GPIO_OPEN_DRAIN;
+ transitory = flags & OF_GPIO_TRANSITORY;
+
+ ret = gpiod_request(desc, label);
+ if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
+ return desc;
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (active_low)
+ lflags |= GPIO_ACTIVE_LOW;
+
+ if (single_ended) {
+ if (open_drain)
+ lflags |= GPIO_OPEN_DRAIN;
+ else
+ lflags |= GPIO_OPEN_SOURCE;
+ }
+
+ if (transitory)
+ lflags |= GPIO_TRANSITORY;
+
+ ret = gpiod_configure_flags(desc, propname, lflags, dflags);
+ if (ret < 0) {
+ gpiod_put(desc);
+ return ERR_PTR(ret);
+ }
+
+ return desc;
+}
+EXPORT_SYMBOL_GPL(gpiod_get_from_of_node);
/*
* The SPI GPIO bindings happened before we managed to establish that GPIO
@@ -324,6 +438,19 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
return desc;
}
+static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
+ const char *con_id,
+ enum of_gpio_flags *of_flags)
+{
+ if (!IS_ENABLED(CONFIG_MFD_ARIZONA))
+ return ERR_PTR(-ENOENT);
+
+ if (!con_id || strcmp(con_id, "wlf,reset"))
+ return ERR_PTR(-ENOENT);
+
+ return of_get_named_gpiod_flags(dev->of_node, con_id, 0, of_flags);
+}
+
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, unsigned long *flags)
{
@@ -343,36 +470,30 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags);
- /*
- * -EPROBE_DEFER in our case means that we found a
- * valid GPIO property, but no controller has been
- * registered so far.
- *
- * This means we don't need to look any further for
- * alternate name conventions, and we should really
- * preserve the return code for our user to be able to
- * retry probing later.
- */
- if (IS_ERR(desc) && PTR_ERR(desc) == -EPROBE_DEFER)
- return desc;
- if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
+ if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
break;
}
- /* Special handling for SPI GPIOs if used */
- if (IS_ERR(desc))
+ if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+ /* Special handling for SPI GPIOs if used */
desc = of_find_spi_gpio(dev, con_id, &of_flags);
- if (IS_ERR(desc)) {
+ }
+
+ if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
/* This quirk looks up flags and all */
desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
if (!IS_ERR(desc))
return desc;
}
- /* Special handling for regulator GPIOs if used */
- if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
+ if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+ /* Special handling for regulator GPIOs if used */
desc = of_find_regulator_gpio(dev, con_id, &of_flags);
+ }
+
+ if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
+ desc = of_find_arizona_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc))
return desc;
@@ -523,8 +644,9 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
* GPIO chips. This function performs only one sanity check: whether GPIO
* is less than ngpios (that is specified in the gpio_chip).
*/
-int of_gpio_simple_xlate(struct gpio_chip *gc,
- const struct of_phandle_args *gpiospec, u32 *flags)
+static int of_gpio_simple_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
{
/*
* We're discouraging gpio_cells < 2, since that way you'll have to
@@ -548,7 +670,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc,
return gpiospec->args[0];
}
-EXPORT_SYMBOL(of_gpio_simple_xlate);
/**
* of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank)
@@ -605,7 +726,7 @@ err0:
pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret);
return ret;
}
-EXPORT_SYMBOL(of_mm_gpiochip_add_data);
+EXPORT_SYMBOL_GPL(of_mm_gpiochip_add_data);
/**
* of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank)
@@ -622,7 +743,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
iounmap(mm_gc->regs);
kfree(gc->label);
}
-EXPORT_SYMBOL(of_mm_gpiochip_remove);
+EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove);
static void of_gpiochip_init_valid_mask(struct gpio_chip *chip)
{
@@ -734,7 +855,7 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; }
int of_gpiochip_add(struct gpio_chip *chip)
{
- int status;
+ int ret;
if (!chip->of_node)
return 0;
@@ -749,9 +870,9 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_gpiochip_init_valid_mask(chip);
- status = of_gpiochip_add_pin_range(chip);
- if (status)
- return status;
+ ret = of_gpiochip_add_pin_range(chip);
+ if (ret)
+ return ret;
/* If the chip defines names itself, these take precedence */
if (!chip->names)
@@ -760,13 +881,13 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_node_get(chip->of_node);
- status = of_gpiochip_scan_gpios(chip);
- if (status) {
+ ret = of_gpiochip_scan_gpios(chip);
+ if (ret) {
of_node_put(chip->of_node);
gpiochip_remove_pin_ranges(chip);
}
- return status;
+ return ret;
}
void of_gpiochip_remove(struct gpio_chip *chip)
diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h
new file mode 100644
index 000000000000..9768831b1fe2
--- /dev/null
+++ b/drivers/gpio/gpiolib-of.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef GPIOLIB_OF_H
+#define GPIOLIB_OF_H
+
+struct gpio_chip;
+enum of_gpio_flags;
+
+#ifdef CONFIG_OF_GPIO
+struct gpio_desc *of_find_gpio(struct device *dev,
+ const char *con_id,
+ unsigned int idx,
+ unsigned long *lookupflags);
+int of_gpiochip_add(struct gpio_chip *gc);
+void of_gpiochip_remove(struct gpio_chip *gc);
+int of_gpio_get_count(struct device *dev, const char *con_id);
+bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
+#else
+static inline struct gpio_desc *of_find_gpio(struct device *dev,
+ const char *con_id,
+ unsigned int idx,
+ unsigned long *lookupflags)
+{
+ return ERR_PTR(-ENOENT);
+}
+static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
+static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
+static inline int of_gpio_get_count(struct device *dev, const char *con_id)
+{
+ return 0;
+}
+static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
+{
+ return false;
+}
+#endif /* CONFIG_OF_GPIO */
+
+#endif /* GPIOLIB_OF_H */
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 3ee99d070608..822988818efc 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -11,7 +11,6 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/gpio.h>
-#include <linux/of_gpio.h>
#include <linux/idr.h>
#include <linux/slab.h>
#include <linux/acpi.h>
@@ -30,6 +29,8 @@
#include <uapi/linux/gpio.h>
#include "gpiolib.h"
+#include "gpiolib-of.h"
+#include "gpiolib-acpi.h"
#define CREATE_TRACE_POINTS
#include <trace/events/gpio.h>
@@ -213,7 +214,7 @@ int gpiod_get_direction(struct gpio_desc *desc)
{
struct gpio_chip *chip;
unsigned offset;
- int status;
+ int ret;
chip = gpiod_to_chip(desc);
offset = gpio_chip_hwgpio(desc);
@@ -221,17 +222,17 @@ int gpiod_get_direction(struct gpio_desc *desc)
if (!chip->get_direction)
return -ENOTSUPP;
- status = chip->get_direction(chip, offset);
- if (status > 0) {
+ ret = chip->get_direction(chip, offset);
+ if (ret > 0) {
/* GPIOF_DIR_IN, or other positive */
- status = 1;
+ ret = 1;
clear_bit(FLAG_IS_OUT, &desc->flags);
}
- if (status == 0) {
+ if (ret == 0) {
/* GPIOF_DIR_OUT */
set_bit(FLAG_IS_OUT, &desc->flags);
}
- return status;
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiod_get_direction);
@@ -350,7 +351,7 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip)
{
unsigned long *p;
- p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL);
+ p = bitmap_alloc(chip->ngpio, GFP_KERNEL);
if (!p)
return NULL;
@@ -360,38 +361,31 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip)
return p;
}
-static int gpiochip_alloc_valid_mask(struct gpio_chip *gpiochip)
+static int gpiochip_alloc_valid_mask(struct gpio_chip *gc)
{
-#ifdef CONFIG_OF_GPIO
- int size;
- struct device_node *np = gpiochip->of_node;
-
- size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
- if (size > 0 && size % 2 == 0)
- gpiochip->need_valid_mask = true;
-#endif
-
- if (!gpiochip->need_valid_mask)
+ if (!(of_gpio_need_valid_mask(gc) || gc->init_valid_mask))
return 0;
- gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip);
- if (!gpiochip->valid_mask)
+ gc->valid_mask = gpiochip_allocate_mask(gc);
+ if (!gc->valid_mask)
return -ENOMEM;
return 0;
}
-static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip)
+static int gpiochip_init_valid_mask(struct gpio_chip *gc)
{
- if (gpiochip->init_valid_mask)
- return gpiochip->init_valid_mask(gpiochip);
+ if (gc->init_valid_mask)
+ return gc->init_valid_mask(gc,
+ gc->valid_mask,
+ gc->ngpio);
return 0;
}
static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip)
{
- kfree(gpiochip->valid_mask);
+ bitmap_free(gpiochip->valid_mask);
gpiochip->valid_mask = NULL;
}
@@ -536,6 +530,14 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
return -EINVAL;
/*
+ * Do not allow both INPUT & OUTPUT flags to be set as they are
+ * contradictory.
+ */
+ if ((lflags & GPIOHANDLE_REQUEST_INPUT) &&
+ (lflags & GPIOHANDLE_REQUEST_OUTPUT))
+ return -EINVAL;
+
+ /*
* Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If
* the hardware actually supports enabling both at the same time the
* electrical result would be disastrous.
@@ -857,7 +859,7 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
}
ret = kfifo_put(&le->events, ge);
- if (ret != 0)
+ if (ret)
wake_up_poll(&le->wait, EPOLLIN);
return IRQ_HANDLED;
@@ -926,7 +928,9 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
}
/* This is just wrong: we don't look for events on output lines */
- if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
+ if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
+ (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
+ (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) {
ret = -EINVAL;
goto out_free_label;
}
@@ -940,10 +944,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
- if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
ret = gpiod_direction_input(desc);
if (ret)
@@ -956,9 +956,11 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
}
if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
- irqflags |= IRQF_TRIGGER_RISING;
+ irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+ IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
- irqflags |= IRQF_TRIGGER_FALLING;
+ irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+ IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
irqflags |= IRQF_ONESHOT;
INIT_KFIFO(le->events);
@@ -1089,9 +1091,11 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW;
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_OPEN_DRAIN;
+ lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
+ GPIOLINE_FLAG_IS_OUT);
if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_OPEN_SOURCE;
+ lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
+ GPIOLINE_FLAG_IS_OUT);
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
return -EFAULT;
@@ -1172,21 +1176,21 @@ static void gpiodevice_release(struct device *dev)
static int gpiochip_setup_dev(struct gpio_device *gdev)
{
- int status;
+ int ret;
cdev_init(&gdev->chrdev, &gpio_fileops);
gdev->chrdev.owner = THIS_MODULE;
gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
- status = cdev_device_add(&gdev->chrdev, &gdev->dev);
- if (status)
- return status;
+ ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
+ if (ret)
+ return ret;
chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
MAJOR(gpio_devt), gdev->id);
- status = gpiochip_sysfs_register(gdev);
- if (status)
+ ret = gpiochip_sysfs_register(gdev);
+ if (ret)
goto err_remove_device;
/* From this point, the .release() function cleans up gpio_device */
@@ -1199,7 +1203,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
err_remove_device:
cdev_device_del(&gdev->chrdev, &gdev->dev);
- return status;
+ return ret;
}
static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
@@ -1240,13 +1244,13 @@ static void machine_gpiochip_add(struct gpio_chip *chip)
static void gpiochip_setup_devs(void)
{
struct gpio_device *gdev;
- int err;
+ int ret;
list_for_each_entry(gdev, &gpio_devices, list) {
- err = gpiochip_setup_dev(gdev);
- if (err)
+ ret = gpiochip_setup_dev(gdev);
+ if (ret)
pr_err("%s: Failed to initialize gpio device (%d)\n",
- dev_name(&gdev->dev), err);
+ dev_name(&gdev->dev), ret);
}
}
@@ -1255,7 +1259,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
struct lock_class_key *request_key)
{
unsigned long flags;
- int status = 0;
+ int ret = 0;
unsigned i;
int base = chip->base;
struct gpio_device *gdev;
@@ -1285,7 +1289,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL);
if (gdev->id < 0) {
- status = gdev->id;
+ ret = gdev->id;
goto err_free_gdev;
}
dev_set_name(&gdev->dev, "gpiochip%d", gdev->id);
@@ -1301,13 +1305,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
if (!gdev->descs) {
- status = -ENOMEM;
+ ret = -ENOMEM;
goto err_free_ida;
}
if (chip->ngpio == 0) {
chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
- status = -EINVAL;
+ ret = -EINVAL;
goto err_free_descs;
}
@@ -1317,7 +1321,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL);
if (!gdev->label) {
- status = -ENOMEM;
+ ret = -ENOMEM;
goto err_free_descs;
}
@@ -1336,7 +1340,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (base < 0) {
base = gpiochip_find_base(chip->ngpio);
if (base < 0) {
- status = base;
+ ret = base;
spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_label;
}
@@ -1350,8 +1354,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
}
gdev->base = base;
- status = gpiodev_add_to_list(gdev);
- if (status) {
+ ret = gpiodev_add_to_list(gdev);
+ if (ret) {
spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_label;
}
@@ -1365,45 +1369,50 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
- status = gpiochip_set_desc_names(chip);
- if (status)
+ ret = gpiochip_set_desc_names(chip);
+ if (ret)
goto err_remove_from_list;
- status = gpiochip_irqchip_init_valid_mask(chip);
- if (status)
+ ret = gpiochip_alloc_valid_mask(chip);
+ if (ret)
goto err_remove_from_list;
- status = gpiochip_alloc_valid_mask(chip);
- if (status)
- goto err_remove_irqchip_mask;
-
- status = gpiochip_add_irqchip(chip, lock_key, request_key);
- if (status)
+ ret = of_gpiochip_add(chip);
+ if (ret)
goto err_free_gpiochip_mask;
- status = of_gpiochip_add(chip);
- if (status)
- goto err_remove_chip;
-
- status = gpiochip_init_valid_mask(chip);
- if (status)
+ ret = gpiochip_init_valid_mask(chip);
+ if (ret)
goto err_remove_of_chip;
for (i = 0; i < chip->ngpio; i++) {
struct gpio_desc *desc = &gdev->descs[i];
- if (chip->get_direction && gpiochip_line_is_valid(chip, i))
- desc->flags = !chip->get_direction(chip, i) ?
- (1 << FLAG_IS_OUT) : 0;
- else
- desc->flags = !chip->direction_input ?
- (1 << FLAG_IS_OUT) : 0;
+ if (chip->get_direction && gpiochip_line_is_valid(chip, i)) {
+ if (!chip->get_direction(chip, i))
+ set_bit(FLAG_IS_OUT, &desc->flags);
+ else
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+ } else {
+ if (!chip->direction_input)
+ set_bit(FLAG_IS_OUT, &desc->flags);
+ else
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+ }
}
acpi_gpiochip_add(chip);
machine_gpiochip_add(chip);
+ ret = gpiochip_irqchip_init_valid_mask(chip);
+ if (ret)
+ goto err_remove_acpi_chip;
+
+ ret = gpiochip_add_irqchip(chip, lock_key, request_key);
+ if (ret)
+ goto err_remove_irqchip_mask;
+
/*
* By first adding the chardev, and then adding the device,
* we get a device node entry in sysfs under
@@ -1413,23 +1422,23 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
* Otherwise, defer until later.
*/
if (gpiolib_initialized) {
- status = gpiochip_setup_dev(gdev);
- if (status)
- goto err_remove_acpi_chip;
+ ret = gpiochip_setup_dev(gdev);
+ if (ret)
+ goto err_remove_irqchip;
}
return 0;
+err_remove_irqchip:
+ gpiochip_irqchip_remove(chip);
+err_remove_irqchip_mask:
+ gpiochip_irqchip_free_valid_mask(chip);
err_remove_acpi_chip:
acpi_gpiochip_remove(chip);
err_remove_of_chip:
gpiochip_free_hogs(chip);
of_gpiochip_remove(chip);
-err_remove_chip:
- gpiochip_irqchip_remove(chip);
err_free_gpiochip_mask:
gpiochip_free_valid_mask(chip);
-err_remove_irqchip_mask:
- gpiochip_irqchip_free_valid_mask(chip);
err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list);
@@ -1444,9 +1453,9 @@ err_free_gdev:
/* failures here can mean systems won't boot... */
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
gdev->base, gdev->base + gdev->ngpio - 1,
- chip->label ? : "generic", status);
+ chip->label ? : "generic", ret);
kfree(gdev);
- return status;
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key);
@@ -1612,21 +1621,25 @@ static struct gpio_chip *find_chip_by_name(const char *name)
* The following is irqchip helper code for gpiochips.
*/
-static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
+static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
{
- if (!gpiochip->irq.need_valid_mask)
+ struct gpio_irq_chip *girq = &gc->irq;
+
+ if (!girq->init_valid_mask)
return 0;
- gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip);
- if (!gpiochip->irq.valid_mask)
+ girq->valid_mask = gpiochip_allocate_mask(gc);
+ if (!girq->valid_mask)
return -ENOMEM;
+ girq->init_valid_mask(gc, girq->valid_mask, gc->ngpio);
+
return 0;
}
static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
{
- kfree(gpiochip->irq.valid_mask);
+ bitmap_free(gpiochip->irq.valid_mask);
gpiochip->irq.valid_mask = NULL;
}
@@ -1726,6 +1739,273 @@ void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
}
EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+
+/**
+ * gpiochip_set_hierarchical_irqchip() - connects a hierarchical irqchip
+ * to a gpiochip
+ * @gc: the gpiochip to set the irqchip hierarchical handler to
+ * @irqchip: the irqchip to handle this level of the hierarchy, the interrupt
+ * will then percolate up to the parent
+ */
+static void gpiochip_set_hierarchical_irqchip(struct gpio_chip *gc,
+ struct irq_chip *irqchip)
+{
+ /* DT will deal with mapping each IRQ as we go along */
+ if (is_of_node(gc->irq.fwnode))
+ return;
+
+ /*
+ * This is for legacy and boardfile "irqchip" fwnodes: allocate
+ * irqs upfront instead of dynamically since we don't have the
+ * dynamic type of allocation that hardware description languages
+ * provide. Once all GPIO drivers using board files are gone from
+ * the kernel we can delete this code, but for a transitional period
+ * it is necessary to keep this around.
+ */
+ if (is_fwnode_irqchip(gc->irq.fwnode)) {
+ int i;
+ int ret;
+
+ for (i = 0; i < gc->ngpio; i++) {
+ struct irq_fwspec fwspec;
+ unsigned int parent_hwirq;
+ unsigned int parent_type;
+ struct gpio_irq_chip *girq = &gc->irq;
+
+ /*
+ * We call the child to parent translation function
+ * only to check if the child IRQ is valid or not.
+ * Just pick the rising edge type here as that is what
+ * we likely need to support.
+ */
+ ret = girq->child_to_parent_hwirq(gc, i,
+ IRQ_TYPE_EDGE_RISING,
+ &parent_hwirq,
+ &parent_type);
+ if (ret) {
+ chip_err(gc, "skip set-up on hwirq %d\n",
+ i);
+ continue;
+ }
+
+ fwspec.fwnode = gc->irq.fwnode;
+ /* This is the hwirq for the GPIO line side of things */
+ fwspec.param[0] = girq->child_offset_to_irq(gc, i);
+ /* Just pick something */
+ fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+ fwspec.param_count = 2;
+ ret = __irq_domain_alloc_irqs(gc->irq.domain,
+ /* just pick something */
+ -1,
+ 1,
+ NUMA_NO_NODE,
+ &fwspec,
+ false,
+ NULL);
+ if (ret < 0) {
+ chip_err(gc,
+ "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
+ i, parent_hwirq,
+ ret);
+ }
+ }
+ }
+
+ chip_err(gc, "%s unknown fwnode type proceed anyway\n", __func__);
+
+ return;
+}
+
+static int gpiochip_hierarchy_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ /* We support standard DT translation */
+ if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
+ return irq_domain_translate_twocell(d, fwspec, hwirq, type);
+ }
+
+ /* This is for board files and others not using DT */
+ if (is_fwnode_irqchip(fwspec->fwnode)) {
+ int ret;
+
+ ret = irq_domain_translate_twocell(d, fwspec, hwirq, type);
+ if (ret)
+ return ret;
+ WARN_ON(*type == IRQ_TYPE_NONE);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,
+ unsigned int irq,
+ unsigned int nr_irqs,
+ void *data)
+{
+ struct gpio_chip *gc = d->host_data;
+ irq_hw_number_t hwirq;
+ unsigned int type = IRQ_TYPE_NONE;
+ struct irq_fwspec *fwspec = data;
+ struct irq_fwspec parent_fwspec;
+ unsigned int parent_hwirq;
+ unsigned int parent_type;
+ struct gpio_irq_chip *girq = &gc->irq;
+ int ret;
+
+ /*
+ * The nr_irqs parameter is always one except for PCI multi-MSI
+ * so this should not happen.
+ */
+ WARN_ON(nr_irqs != 1);
+
+ ret = gc->irq.child_irq_domain_ops.translate(d, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ chip_info(gc, "allocate IRQ %d, hwirq %lu\n", irq, hwirq);
+
+ ret = girq->child_to_parent_hwirq(gc, hwirq, type,
+ &parent_hwirq, &parent_type);
+ if (ret) {
+ chip_err(gc, "can't look up hwirq %lu\n", hwirq);
+ return ret;
+ }
+ chip_info(gc, "found parent hwirq %u\n", parent_hwirq);
+
+ /*
+ * We set handle_bad_irq because the .set_type() should
+ * always be invoked and set the right type of handler.
+ */
+ irq_domain_set_info(d,
+ irq,
+ hwirq,
+ gc->irq.chip,
+ gc,
+ girq->handler,
+ NULL, NULL);
+ irq_set_probe(irq);
+
+ /*
+ * Create a IRQ fwspec to send up to the parent irqdomain:
+ * specify the hwirq we address on the parent and tie it
+ * all together up the chain.
+ */
+ parent_fwspec.fwnode = d->parent->fwnode;
+ /* This parent only handles asserted level IRQs */
+ girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq,
+ parent_type);
+ chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n",
+ irq, parent_hwirq);
+ ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec);
+ if (ret)
+ chip_err(gc,
+ "failed to allocate parent hwirq %d for hwirq %lu\n",
+ parent_hwirq, hwirq);
+
+ return ret;
+}
+
+static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ return offset;
+}
+
+static void gpiochip_hierarchy_setup_domain_ops(struct irq_domain_ops *ops)
+{
+ ops->activate = gpiochip_irq_domain_activate;
+ ops->deactivate = gpiochip_irq_domain_deactivate;
+ ops->alloc = gpiochip_hierarchy_irq_domain_alloc;
+ ops->free = irq_domain_free_irqs_common;
+
+ /*
+ * We only allow overriding the translate() function for
+ * hierarchical chips, and this should only be done if the user
+ * really need something other than 1:1 translation.
+ */
+ if (!ops->translate)
+ ops->translate = gpiochip_hierarchy_irq_domain_translate;
+}
+
+static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc)
+{
+ if (!gc->irq.child_to_parent_hwirq ||
+ !gc->irq.fwnode) {
+ chip_err(gc, "missing irqdomain vital data\n");
+ return -EINVAL;
+ }
+
+ if (!gc->irq.child_offset_to_irq)
+ gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop;
+
+ if (!gc->irq.populate_parent_fwspec)
+ gc->irq.populate_parent_fwspec =
+ gpiochip_populate_parent_fwspec_twocell;
+
+ gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops);
+
+ gc->irq.domain = irq_domain_create_hierarchy(
+ gc->irq.parent_domain,
+ 0,
+ gc->ngpio,
+ gc->irq.fwnode,
+ &gc->irq.child_irq_domain_ops,
+ gc);
+
+ if (!gc->irq.domain)
+ return -ENOMEM;
+
+ gpiochip_set_hierarchical_irqchip(gc, gc->irq.chip);
+
+ return 0;
+}
+
+static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)
+{
+ return !!gc->irq.parent_domain;
+}
+
+void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type)
+{
+ fwspec->param_count = 2;
+ fwspec->param[0] = parent_hwirq;
+ fwspec->param[1] = parent_type;
+}
+EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell);
+
+void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type)
+{
+ fwspec->param_count = 4;
+ fwspec->param[0] = 0;
+ fwspec->param[1] = parent_hwirq;
+ fwspec->param[2] = 0;
+ fwspec->param[3] = parent_type;
+}
+EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell);
+
+#else
+
+static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc)
+{
+ return -EINVAL;
+}
+
+static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)
+{
+ return false;
+}
+
+#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
+
/**
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
* @d: the irqdomain used by this irqchip
@@ -1740,7 +2020,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct gpio_chip *chip = d->host_data;
- int err = 0;
+ int ret = 0;
if (!gpiochip_irqchip_irq_valid(chip, hwirq))
return -ENXIO;
@@ -1758,12 +2038,12 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
irq_set_noprobe(irq);
if (chip->irq.num_parents == 1)
- err = irq_set_parent(irq, chip->irq.parents[0]);
+ ret = irq_set_parent(irq, chip->irq.parents[0]);
else if (chip->irq.map)
- err = irq_set_parent(irq, chip->irq.map[hwirq]);
+ ret = irq_set_parent(irq, chip->irq.map[hwirq]);
- if (err < 0)
- return err;
+ if (ret < 0)
+ return ret;
/*
* No set-up of the hardware will happen if IRQ_TYPE_NONE
@@ -1794,6 +2074,11 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
.xlate = irq_domain_xlate_twocell,
};
+/*
+ * TODO: move these activate/deactivate in under the hierarchicial
+ * irqchip implementation as static once SPMI and SSBI (all external
+ * users) are phased over.
+ */
/**
* gpiochip_irq_domain_activate() - Lock a GPIO to be used as an IRQ
* @domain: The IRQ domain used by this IRQ chip
@@ -1833,10 +2118,25 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate);
static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
{
+ struct irq_domain *domain = chip->irq.domain;
+
if (!gpiochip_irqchip_irq_valid(chip, offset))
return -ENXIO;
- return irq_create_mapping(chip->irq.domain, offset);
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+ if (irq_domain_is_hierarchy(domain)) {
+ struct irq_fwspec spec;
+
+ spec.fwnode = domain->fwnode;
+ spec.param_count = 2;
+ spec.param[0] = chip->irq.child_offset_to_irq(chip, offset);
+ spec.param[1] = IRQ_TYPE_NONE;
+
+ return irq_create_fwspec_mapping(&spec);
+ }
+#endif
+
+ return irq_create_mapping(domain, offset);
}
static int gpiochip_irq_reqres(struct irq_data *d)
@@ -1913,7 +2213,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
struct lock_class_key *request_key)
{
struct irq_chip *irqchip = gpiochip->irq.chip;
- const struct irq_domain_ops *ops;
+ const struct irq_domain_ops *ops = NULL;
struct device_node *np;
unsigned int type;
unsigned int i;
@@ -1949,16 +2249,25 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
gpiochip->irq.lock_key = lock_key;
gpiochip->irq.request_key = request_key;
- if (gpiochip->irq.domain_ops)
- ops = gpiochip->irq.domain_ops;
- else
- ops = &gpiochip_domain_ops;
-
- gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio,
- gpiochip->irq.first,
- ops, gpiochip);
- if (!gpiochip->irq.domain)
- return -EINVAL;
+ /* If a parent irqdomain is provided, let's build a hierarchy */
+ if (gpiochip_hierarchy_is_hierarchical(gpiochip)) {
+ int ret = gpiochip_hierarchy_add_domain(gpiochip);
+ if (ret)
+ return ret;
+ } else {
+ /* Some drivers provide custom irqdomain ops */
+ if (gpiochip->irq.domain_ops)
+ ops = gpiochip->irq.domain_ops;
+
+ if (!ops)
+ ops = &gpiochip_domain_ops;
+ gpiochip->irq.domain = irq_domain_add_simple(np,
+ gpiochip->ngpio,
+ gpiochip->irq.first,
+ ops, gpiochip);
+ if (!gpiochip->irq.domain)
+ return -EINVAL;
+ }
if (gpiochip->irq.parent_handler) {
void *data = gpiochip->irq.parent_handler_data ?: gpiochip;
@@ -2321,7 +2630,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
{
struct gpio_chip *chip = desc->gdev->chip;
- int status;
+ int ret;
unsigned long flags;
unsigned offset;
@@ -2339,10 +2648,10 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
desc_set_label(desc, label ? : "?");
- status = 0;
+ ret = 0;
} else {
kfree_const(label);
- status = -EBUSY;
+ ret = -EBUSY;
goto done;
}
@@ -2351,12 +2660,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
spin_unlock_irqrestore(&gpio_lock, flags);
offset = gpio_chip_hwgpio(desc);
if (gpiochip_line_is_valid(chip, offset))
- status = chip->request(chip, offset);
+ ret = chip->request(chip, offset);
else
- status = -EINVAL;
+ ret = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
- if (status < 0) {
+ if (ret < 0) {
desc_set_label(desc, NULL);
kfree_const(label);
clear_bit(FLAG_REQUESTED, &desc->flags);
@@ -2371,7 +2680,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
}
done:
spin_unlock_irqrestore(&gpio_lock, flags);
- return status;
+ return ret;
}
/*
@@ -2414,24 +2723,24 @@ static int validate_desc(const struct gpio_desc *desc, const char *func)
int gpiod_request(struct gpio_desc *desc, const char *label)
{
- int status = -EPROBE_DEFER;
+ int ret = -EPROBE_DEFER;
struct gpio_device *gdev;
VALIDATE_DESC(desc);
gdev = desc->gdev;
if (try_module_get(gdev->owner)) {
- status = gpiod_request_commit(desc, label);
- if (status < 0)
+ ret = gpiod_request_commit(desc, label);
+ if (ret < 0)
module_put(gdev->owner);
else
get_device(&gdev->dev);
}
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+ if (ret)
+ gpiod_dbg(desc, "%s: status %d\n", __func__, ret);
- return status;
+ return ret;
}
static bool gpiod_free_commit(struct gpio_desc *desc)
@@ -2533,22 +2842,22 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum,
enum gpiod_flags dflags)
{
struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum);
- int err;
+ int ret;
if (IS_ERR(desc)) {
chip_err(chip, "failed to get GPIO descriptor\n");
return desc;
}
- err = gpiod_request_commit(desc, label);
- if (err < 0)
- return ERR_PTR(err);
+ ret = gpiod_request_commit(desc, label);
+ if (ret < 0)
+ return ERR_PTR(ret);
- err = gpiod_configure_flags(desc, label, lflags, dflags);
- if (err) {
+ ret = gpiod_configure_flags(desc, label, lflags, dflags);
+ if (ret) {
chip_err(chip, "setup of own GPIO %s failed\n", label);
gpiod_free_commit(desc);
- return ERR_PTR(err);
+ return ERR_PTR(ret);
}
return desc;
@@ -2611,7 +2920,7 @@ static int gpio_set_config(struct gpio_chip *gc, unsigned offset,
int gpiod_direction_input(struct gpio_desc *desc)
{
struct gpio_chip *chip;
- int status = 0;
+ int ret = 0;
VALIDATE_DESC(desc);
chip = desc->gdev->chip;
@@ -2635,7 +2944,7 @@ int gpiod_direction_input(struct gpio_desc *desc)
* assume we are in input mode after this.
*/
if (chip->direction_input) {
- status = chip->direction_input(chip, gpio_chip_hwgpio(desc));
+ ret = chip->direction_input(chip, gpio_chip_hwgpio(desc));
} else if (chip->get_direction &&
(chip->get_direction(chip, gpio_chip_hwgpio(desc)) != 1)) {
gpiod_warn(desc,
@@ -2643,7 +2952,7 @@ int gpiod_direction_input(struct gpio_desc *desc)
__func__);
return -EIO;
}
- if (status == 0)
+ if (ret == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
if (test_bit(FLAG_PULL_UP, &desc->flags))
@@ -2653,9 +2962,9 @@ int gpiod_direction_input(struct gpio_desc *desc)
gpio_set_config(chip, gpio_chip_hwgpio(desc),
PIN_CONFIG_BIAS_PULL_DOWN);
- trace_gpio_direction(desc_to_gpio(desc), 1, status);
+ trace_gpio_direction(desc_to_gpio(desc), 1, ret);
- return status;
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiod_direction_input);
@@ -2927,7 +3236,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
- int err, i = 0;
+ int ret, i = 0;
/*
* Validate array_info against desc_array and its size.
@@ -2940,11 +3249,11 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
if (!can_sleep)
WARN_ON(array_info->chip->can_sleep);
- err = gpio_chip_get_multiple(array_info->chip,
+ ret = gpio_chip_get_multiple(array_info->chip,
array_info->get_mask,
value_bitmap);
- if (err)
- return err;
+ if (ret)
+ return ret;
if (!raw && !bitmap_empty(array_info->invert_mask, array_size))
bitmap_xor(value_bitmap, value_bitmap,
@@ -3132,24 +3441,24 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value);
*/
static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)
{
- int err = 0;
+ int ret = 0;
struct gpio_chip *chip = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
- err = chip->direction_input(chip, offset);
- if (!err)
+ ret = chip->direction_input(chip, offset);
+ if (!ret)
clear_bit(FLAG_IS_OUT, &desc->flags);
} else {
- err = chip->direction_output(chip, offset, 0);
- if (!err)
+ ret = chip->direction_output(chip, offset, 0);
+ if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
}
- trace_gpio_direction(desc_to_gpio(desc), value, err);
- if (err < 0)
+ trace_gpio_direction(desc_to_gpio(desc), value, ret);
+ if (ret < 0)
gpiod_err(desc,
"%s: Error in set_value for open drain err %d\n",
- __func__, err);
+ __func__, ret);
}
/*
@@ -3159,24 +3468,24 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)
*/
static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value)
{
- int err = 0;
+ int ret = 0;
struct gpio_chip *chip = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
- err = chip->direction_output(chip, offset, 1);
- if (!err)
+ ret = chip->direction_output(chip, offset, 1);
+ if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
} else {
- err = chip->direction_input(chip, offset);
- if (!err)
+ ret = chip->direction_input(chip, offset);
+ if (!ret)
clear_bit(FLAG_IS_OUT, &desc->flags);
}
- trace_gpio_direction(desc_to_gpio(desc), !value, err);
- if (err < 0)
+ trace_gpio_direction(desc_to_gpio(desc), !value, ret);
+ if (ret < 0)
gpiod_err(desc,
"%s: Error in set_value for open source err %d\n",
- __func__, err);
+ __func__, ret);
}
static void gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value)
@@ -3993,27 +4302,6 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return desc;
}
-static int dt_gpio_count(struct device *dev, const char *con_id)
-{
- int ret;
- char propname[32];
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
- if (con_id)
- snprintf(propname, sizeof(propname), "%s-%s",
- con_id, gpio_suffixes[i]);
- else
- snprintf(propname, sizeof(propname), "%s",
- gpio_suffixes[i]);
-
- ret = of_gpio_named_count(dev->of_node, propname);
- if (ret > 0)
- break;
- }
- return ret ? ret : -ENOENT;
-}
-
static int platform_gpio_count(struct device *dev, const char *con_id)
{
struct gpiod_lookup_table *table;
@@ -4046,7 +4334,7 @@ int gpiod_count(struct device *dev, const char *con_id)
int count = -ENOENT;
if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
- count = dt_gpio_count(dev, con_id);
+ count = of_gpio_get_count(dev, con_id);
else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev))
count = acpi_gpio_count(dev, con_id);
@@ -4108,7 +4396,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags)
{
- int status;
+ int ret;
if (lflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -4141,9 +4429,9 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
else if (lflags & GPIO_PULL_DOWN)
set_bit(FLAG_PULL_DOWN, &desc->flags);
- status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY));
- if (status < 0)
- return status;
+ ret = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY));
+ if (ret < 0)
+ return ret;
/* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
@@ -4153,12 +4441,12 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
/* Process flags */
if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
- status = gpiod_direction_output(desc,
+ ret = gpiod_direction_output(desc,
!!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
else
- status = gpiod_direction_input(desc);
+ ret = gpiod_direction_input(desc);
- return status;
+ return ret;
}
/**
@@ -4182,7 +4470,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
{
unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT;
struct gpio_desc *desc = NULL;
- int status;
+ int ret;
/* Maybe we have a device name, maybe not */
const char *devname = dev ? dev_name(dev) : "?";
@@ -4217,9 +4505,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
* If a connection label was passed use that, else attempt to use
* the device name as label
*/
- status = gpiod_request(desc, con_id ? con_id : devname);
- if (status < 0) {
- if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
+ ret = gpiod_request(desc, con_id ? con_id : devname);
+ if (ret < 0) {
+ if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
/*
* This happens when there are several consumers for
* the same GPIO line: we just return here without
@@ -4232,89 +4520,20 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
con_id ? con_id : devname);
return desc;
} else {
- return ERR_PTR(status);
+ return ERR_PTR(ret);
}
}
- status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
- if (status < 0) {
- dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
- gpiod_put(desc);
- return ERR_PTR(status);
- }
-
- return desc;
-}
-EXPORT_SYMBOL_GPL(gpiod_get_index);
-
-/**
- * gpiod_get_from_of_node() - obtain a GPIO from an OF node
- * @node: handle of the OF node
- * @propname: name of the DT property representing the GPIO
- * @index: index of the GPIO to obtain for the consumer
- * @dflags: GPIO initialization flags
- * @label: label to attach to the requested GPIO
- *
- * Returns:
- * On successful request the GPIO pin is configured in accordance with
- * provided @dflags.
- *
- * In case of error an ERR_PTR() is returned.
- */
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
- const char *propname, int index,
- enum gpiod_flags dflags,
- const char *label)
-{
- unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
- struct gpio_desc *desc;
- enum of_gpio_flags flags;
- bool active_low = false;
- bool single_ended = false;
- bool open_drain = false;
- bool transitory = false;
- int ret;
-
- desc = of_get_named_gpiod_flags(node, propname,
- index, &flags);
-
- if (!desc || IS_ERR(desc)) {
- return desc;
- }
-
- active_low = flags & OF_GPIO_ACTIVE_LOW;
- single_ended = flags & OF_GPIO_SINGLE_ENDED;
- open_drain = flags & OF_GPIO_OPEN_DRAIN;
- transitory = flags & OF_GPIO_TRANSITORY;
-
- ret = gpiod_request(desc, label);
- if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
- return desc;
- if (ret)
- return ERR_PTR(ret);
-
- if (active_low)
- lflags |= GPIO_ACTIVE_LOW;
-
- if (single_ended) {
- if (open_drain)
- lflags |= GPIO_OPEN_DRAIN;
- else
- lflags |= GPIO_OPEN_SOURCE;
- }
-
- if (transitory)
- lflags |= GPIO_TRANSITORY;
-
- ret = gpiod_configure_flags(desc, propname, lflags, dflags);
+ ret = gpiod_configure_flags(desc, con_id, lookupflags, flags);
if (ret < 0) {
+ dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
gpiod_put(desc);
return ERR_PTR(ret);
}
return desc;
}
-EXPORT_SYMBOL(gpiod_get_from_of_node);
+EXPORT_SYMBOL_GPL(gpiod_get_index);
/**
* fwnode_get_named_gpiod - obtain a GPIO from firmware node
@@ -4424,7 +4643,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
struct gpio_chip *chip;
struct gpio_desc *local_desc;
int hwnum;
- int status;
+ int ret;
chip = gpiod_to_chip(desc);
hwnum = gpio_chip_hwgpio(desc);
@@ -4432,10 +4651,10 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
local_desc = gpiochip_request_own_desc(chip, hwnum, name,
lflags, dflags);
if (IS_ERR(local_desc)) {
- status = PTR_ERR(local_desc);
+ ret = PTR_ERR(local_desc);
pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n",
- name, chip->label, hwnum, status);
- return status;
+ name, chip->label, hwnum, ret);
+ return ret;
}
/* Mark GPIO as hogged so it can be identified and removed later */
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 7c52c2442173..b8b10a409c7b 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -16,9 +16,6 @@
#include <linux/module.h>
#include <linux/cdev.h>
-enum of_gpio_flags;
-struct acpi_device;
-
/**
* struct gpio_device - internal state container for GPIO devices
* @id: numerical ID number for the GPIO chip
@@ -69,126 +66,9 @@ struct gpio_device {
#endif
};
-/**
- * struct acpi_gpio_info - ACPI GPIO specific information
- * @adev: reference to ACPI device which consumes GPIO resource
- * @flags: GPIO initialization flags
- * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
- * @pin_config: pin bias as provided by ACPI
- * @polarity: interrupt polarity as provided by ACPI
- * @triggering: triggering type as provided by ACPI
- * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
- */
-struct acpi_gpio_info {
- struct acpi_device *adev;
- enum gpiod_flags flags;
- bool gpioint;
- int pin_config;
- int polarity;
- int triggering;
- unsigned int quirks;
-};
-
/* gpio suffixes used for ACPI and device tree lookup */
static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
-#ifdef CONFIG_OF_GPIO
-struct gpio_desc *of_find_gpio(struct device *dev,
- const char *con_id,
- unsigned int idx,
- unsigned long *lookupflags);
-struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
- const char *list_name, int index, enum of_gpio_flags *flags);
-int of_gpiochip_add(struct gpio_chip *gc);
-void of_gpiochip_remove(struct gpio_chip *gc);
-#else
-static inline struct gpio_desc *of_find_gpio(struct device *dev,
- const char *con_id,
- unsigned int idx,
- unsigned long *lookupflags)
-{
- return ERR_PTR(-ENOENT);
-}
-static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
- const char *list_name, int index, enum of_gpio_flags *flags)
-{
- return ERR_PTR(-ENOENT);
-}
-static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
-static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
-#endif /* CONFIG_OF_GPIO */
-
-#ifdef CONFIG_ACPI
-void acpi_gpiochip_add(struct gpio_chip *chip);
-void acpi_gpiochip_remove(struct gpio_chip *chip);
-
-void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
-void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
-
-int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
- struct acpi_gpio_info *info);
-int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
- struct acpi_gpio_info *info);
-
-struct gpio_desc *acpi_find_gpio(struct device *dev,
- const char *con_id,
- unsigned int idx,
- enum gpiod_flags *dflags,
- unsigned long *lookupflags);
-struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
- const char *propname, int index,
- struct acpi_gpio_info *info);
-
-int acpi_gpio_count(struct device *dev, const char *con_id);
-
-bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id);
-#else
-static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
-static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
-
-static inline void
-acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
-
-static inline void
-acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
-
-static inline int
-acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
-{
- return 0;
-}
-static inline int
-acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
- struct acpi_gpio_info *info)
-{
- return 0;
-}
-
-static inline struct gpio_desc *
-acpi_find_gpio(struct device *dev, const char *con_id,
- unsigned int idx, enum gpiod_flags *dflags,
- unsigned long *lookupflags)
-{
- return ERR_PTR(-ENOENT);
-}
-static inline struct gpio_desc *
-acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
- int index, struct acpi_gpio_info *info)
-{
- return ERR_PTR(-ENXIO);
-}
-static inline int acpi_gpio_count(struct device *dev, const char *con_id)
-{
- return -ENODEV;
-}
-
-static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
- const char *con_id)
-{
- return false;
-}
-#endif
-
struct gpio_array {
struct gpio_desc **desc;
unsigned int size;
diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c
new file mode 100644
index 000000000000..7e99860ca447
--- /dev/null
+++ b/drivers/gpio/sgpio-aspeed.c
@@ -0,0 +1,533 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2019 American Megatrends International LLC.
+ *
+ * Author: Karthikeyan Mani <karthikeyanm@amiindia.co.in>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/hashtable.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#define MAX_NR_SGPIO 80
+
+#define ASPEED_SGPIO_CTRL 0x54
+
+#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6)
+#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
+#define ASPEED_SGPIO_ENABLE BIT(0)
+
+struct aspeed_sgpio {
+ struct gpio_chip chip;
+ struct clk *pclk;
+ spinlock_t lock;
+ void __iomem *base;
+ uint32_t dir_in[3];
+ int irq;
+};
+
+struct aspeed_sgpio_bank {
+ uint16_t val_regs;
+ uint16_t rdata_reg;
+ uint16_t irq_regs;
+ const char names[4][3];
+};
+
+/*
+ * Note: The "value" register returns the input value when the GPIO is
+ * configured as an input.
+ *
+ * The "rdata" register returns the output value when the GPIO is
+ * configured as an output.
+ */
+static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
+ {
+ .val_regs = 0x0000,
+ .rdata_reg = 0x0070,
+ .irq_regs = 0x0004,
+ .names = { "A", "B", "C", "D" },
+ },
+ {
+ .val_regs = 0x001C,
+ .rdata_reg = 0x0074,
+ .irq_regs = 0x0020,
+ .names = { "E", "F", "G", "H" },
+ },
+ {
+ .val_regs = 0x0038,
+ .rdata_reg = 0x0078,
+ .irq_regs = 0x003C,
+ .names = { "I", "J" },
+ },
+};
+
+enum aspeed_sgpio_reg {
+ reg_val,
+ reg_rdata,
+ reg_irq_enable,
+ reg_irq_type0,
+ reg_irq_type1,
+ reg_irq_type2,
+ reg_irq_status,
+};
+
+#define GPIO_VAL_VALUE 0x00
+#define GPIO_IRQ_ENABLE 0x00
+#define GPIO_IRQ_TYPE0 0x04
+#define GPIO_IRQ_TYPE1 0x08
+#define GPIO_IRQ_TYPE2 0x0C
+#define GPIO_IRQ_STATUS 0x10
+
+static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
+ const struct aspeed_sgpio_bank *bank,
+ const enum aspeed_sgpio_reg reg)
+{
+ switch (reg) {
+ case reg_val:
+ return gpio->base + bank->val_regs + GPIO_VAL_VALUE;
+ case reg_rdata:
+ return gpio->base + bank->rdata_reg;
+ case reg_irq_enable:
+ return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE;
+ case reg_irq_type0:
+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0;
+ case reg_irq_type1:
+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1;
+ case reg_irq_type2:
+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
+ case reg_irq_status:
+ return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
+ default:
+ /* acturally if code runs to here, it's an error case */
+ BUG_ON(1);
+ }
+}
+
+#define GPIO_BANK(x) ((x) >> 5)
+#define GPIO_OFFSET(x) ((x) & 0x1f)
+#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
+
+static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
+{
+ unsigned int bank = GPIO_BANK(offset);
+
+ WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
+ return &aspeed_sgpio_banks[bank];
+}
+
+static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_sgpio_bank *bank = to_bank(offset);
+ unsigned long flags;
+ enum aspeed_sgpio_reg reg;
+ bool is_input;
+ int rc = 0;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
+ reg = is_input ? reg_val : reg_rdata;
+ rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return rc;
+}
+
+static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_sgpio_bank *bank = to_bank(offset);
+ void __iomem *addr;
+ u32 reg = 0;
+
+ addr = bank_reg(gpio, bank, reg_val);
+ reg = ioread32(addr);
+
+ if (val)
+ reg |= GPIO_BIT(offset);
+ else
+ reg &= ~GPIO_BIT(offset);
+
+ iowrite32(reg, addr);
+}
+
+static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ sgpio_set_value(gc, offset, val);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset);
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
+ sgpio_set_value(gc, offset, val);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ int dir_status;
+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return dir_status;
+
+}
+
+static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
+ struct aspeed_sgpio **gpio,
+ const struct aspeed_sgpio_bank **bank,
+ u32 *bit, int *offset)
+{
+ struct aspeed_sgpio *internal;
+
+ *offset = irqd_to_hwirq(d);
+ internal = irq_data_get_irq_chip_data(d);
+ WARN_ON(!internal);
+
+ *gpio = internal;
+ *bank = to_bank(*offset);
+ *bit = GPIO_BIT(*offset);
+}
+
+static void aspeed_sgpio_irq_ack(struct irq_data *d)
+{
+ const struct aspeed_sgpio_bank *bank;
+ struct aspeed_sgpio *gpio;
+ unsigned long flags;
+ void __iomem *status_addr;
+ int offset;
+ u32 bit;
+
+ irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
+
+ status_addr = bank_reg(gpio, bank, reg_irq_status);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ iowrite32(bit, status_addr);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
+{
+ const struct aspeed_sgpio_bank *bank;
+ struct aspeed_sgpio *gpio;
+ unsigned long flags;
+ u32 reg, bit;
+ void __iomem *addr;
+ int offset;
+
+ irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
+ addr = bank_reg(gpio, bank, reg_irq_enable);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ reg = ioread32(addr);
+ if (set)
+ reg |= bit;
+ else
+ reg &= ~bit;
+
+ iowrite32(reg, addr);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static void aspeed_sgpio_irq_mask(struct irq_data *d)
+{
+ aspeed_sgpio_irq_set_mask(d, false);
+}
+
+static void aspeed_sgpio_irq_unmask(struct irq_data *d)
+{
+ aspeed_sgpio_irq_set_mask(d, true);
+}
+
+static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
+{
+ u32 type0 = 0;
+ u32 type1 = 0;
+ u32 type2 = 0;
+ u32 bit, reg;
+ const struct aspeed_sgpio_bank *bank;
+ irq_flow_handler_t handler;
+ struct aspeed_sgpio *gpio;
+ unsigned long flags;
+ void __iomem *addr;
+ int offset;
+
+ irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_BOTH:
+ type2 |= bit;
+ /* fall through */
+ case IRQ_TYPE_EDGE_RISING:
+ type0 |= bit;
+ /* fall through */
+ case IRQ_TYPE_EDGE_FALLING:
+ handler = handle_edge_irq;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ type0 |= bit;
+ /* fall through */
+ case IRQ_TYPE_LEVEL_LOW:
+ type1 |= bit;
+ handler = handle_level_irq;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ addr = bank_reg(gpio, bank, reg_irq_type0);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type0;
+ iowrite32(reg, addr);
+
+ addr = bank_reg(gpio, bank, reg_irq_type1);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type1;
+ iowrite32(reg, addr);
+
+ addr = bank_reg(gpio, bank, reg_irq_type2);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type2;
+ iowrite32(reg, addr);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ irq_set_handler_locked(d, handler);
+
+ return 0;
+}
+
+static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
+{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct irq_chip *ic = irq_desc_get_chip(desc);
+ struct aspeed_sgpio *data = gpiochip_get_data(gc);
+ unsigned int i, p, girq;
+ unsigned long reg;
+
+ chained_irq_enter(ic, desc);
+
+ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
+ const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i];
+
+ reg = ioread32(bank_reg(data, bank, reg_irq_status));
+
+ for_each_set_bit(p, &reg, 32) {
+ girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
+ generic_handle_irq(girq);
+ }
+
+ }
+
+ chained_irq_exit(ic, desc);
+}
+
+static struct irq_chip aspeed_sgpio_irqchip = {
+ .name = "aspeed-sgpio",
+ .irq_ack = aspeed_sgpio_irq_ack,
+ .irq_mask = aspeed_sgpio_irq_mask,
+ .irq_unmask = aspeed_sgpio_irq_unmask,
+ .irq_set_type = aspeed_sgpio_set_type,
+};
+
+static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
+ struct platform_device *pdev)
+{
+ int rc, i;
+ const struct aspeed_sgpio_bank *bank;
+ struct gpio_irq_chip *irq;
+
+ rc = platform_get_irq(pdev, 0);
+ if (rc < 0)
+ return rc;
+
+ gpio->irq = rc;
+
+ /* Disable IRQ and clear Interrupt status registers for all SPGIO Pins. */
+ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
+ bank = &aspeed_sgpio_banks[i];
+ /* disable irq enable bits */
+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable));
+ /* clear status bits */
+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
+ }
+
+ irq = &gpio->chip.irq;
+ irq->chip = &aspeed_sgpio_irqchip;
+ irq->handler = handle_bad_irq;
+ irq->default_type = IRQ_TYPE_NONE;
+ irq->parent_handler = aspeed_sgpio_irq_handler;
+ irq->parent_handler_data = gpio;
+ irq->parents = &gpio->irq;
+ irq->num_parents = 1;
+
+ /* set IRQ settings and Enable Interrupt */
+ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
+ bank = &aspeed_sgpio_banks[i];
+ /* set falling or level-low irq */
+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
+ /* trigger type is edge */
+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
+ /* dual edge trigger mode. */
+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
+ /* enable irq */
+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));
+ }
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_sgpio_of_table[] = {
+ { .compatible = "aspeed,ast2400-sgpio" },
+ { .compatible = "aspeed,ast2500-sgpio" },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
+
+static int __init aspeed_sgpio_probe(struct platform_device *pdev)
+{
+ struct aspeed_sgpio *gpio;
+ u32 nr_gpios, sgpio_freq, sgpio_clk_div;
+ int rc;
+ unsigned long apb_freq;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ gpio->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(gpio->base))
+ return PTR_ERR(gpio->base);
+
+ rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not read ngpios property\n");
+ return -EINVAL;
+ } else if (nr_gpios > MAX_NR_SGPIO) {
+ dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
+ MAX_NR_SGPIO, nr_gpios);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not read bus-frequency property\n");
+ return -EINVAL;
+ }
+
+ gpio->pclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(gpio->pclk)) {
+ dev_err(&pdev->dev, "devm_clk_get failed\n");
+ return PTR_ERR(gpio->pclk);
+ }
+
+ apb_freq = clk_get_rate(gpio->pclk);
+
+ /*
+ * From the datasheet,
+ * SGPIO period = 1/PCLK * 2 * (GPIO254[31:16] + 1)
+ * period = 2 * (GPIO254[31:16] + 1) / PCLK
+ * frequency = 1 / (2 * (GPIO254[31:16] + 1) / PCLK)
+ * frequency = PCLK / (2 * (GPIO254[31:16] + 1))
+ * frequency * 2 * (GPIO254[31:16] + 1) = PCLK
+ * GPIO254[31:16] = PCLK / (frequency * 2) - 1
+ */
+ if (sgpio_freq == 0)
+ return -EINVAL;
+
+ sgpio_clk_div = (apb_freq / (sgpio_freq * 2)) - 1;
+
+ if (sgpio_clk_div > (1 << 16) - 1)
+ return -EINVAL;
+
+ iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) |
+ FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) |
+ ASPEED_SGPIO_ENABLE,
+ gpio->base + ASPEED_SGPIO_CTRL);
+
+ spin_lock_init(&gpio->lock);
+
+ gpio->chip.parent = &pdev->dev;
+ gpio->chip.ngpio = nr_gpios;
+ gpio->chip.direction_input = aspeed_sgpio_dir_in;
+ gpio->chip.direction_output = aspeed_sgpio_dir_out;
+ gpio->chip.get_direction = aspeed_sgpio_get_direction;
+ gpio->chip.request = NULL;
+ gpio->chip.free = NULL;
+ gpio->chip.get = aspeed_sgpio_get;
+ gpio->chip.set = aspeed_sgpio_set;
+ gpio->chip.set_config = NULL;
+ gpio->chip.label = dev_name(&pdev->dev);
+ gpio->chip.base = -1;
+
+ /* set all SGPIO pins as input (1). */
+ memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in));
+
+ aspeed_sgpio_setup_irqs(gpio, pdev);
+
+ rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static struct platform_driver aspeed_sgpio_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = aspeed_sgpio_of_table,
+ },
+};
+
+module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe);
+MODULE_DESCRIPTION("Aspeed Serial GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1d80222587ad..3c88420e3497 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -394,7 +394,7 @@ config DRM_R128
config DRM_I810
tristate "Intel I810"
# !PREEMPT because of missing ioctl locking
- depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
+ depends on DRM && AGP && AGP_INTEL && (!PREEMPTION || BROKEN)
help
Choose this option if you have an Intel I810 graphics card. If M is
selected, the module will be called i810. AGP support is required
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 1d3ee9c42f7e..6a5c96e519b1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1140,7 +1140,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
adev->asic_type != CHIP_FIJI &&
adev->asic_type != CHIP_POLARIS10 &&
adev->asic_type != CHIP_POLARIS11 &&
- adev->asic_type != CHIP_POLARIS12) ?
+ adev->asic_type != CHIP_POLARIS12 &&
+ adev->asic_type != CHIP_VEGAM) ?
VI_BO_SIZE_ALIGN : 1;
mapping_flags = AMDGPU_VM_PAGE_READABLE;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 9b384a94d2f3..3e35a8f2c5e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -574,6 +574,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
+ { 0x1002, 0x699f, 0x1028, 0x0814, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0, 0, 0, 0, 0 },
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index e069de8b54e6..8b26c970a3cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1044,29 +1044,27 @@ static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
return r;
}
- fence = amdgpu_ctx_get_fence(ctx, entity,
- deps[i].handle);
+ fence = amdgpu_ctx_get_fence(ctx, entity, deps[i].handle);
+ amdgpu_ctx_put(ctx);
+
+ if (IS_ERR(fence))
+ return PTR_ERR(fence);
+ else if (!fence)
+ continue;
if (chunk->chunk_id == AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES) {
- struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
+ struct drm_sched_fence *s_fence;
struct dma_fence *old = fence;
+ s_fence = to_drm_sched_fence(fence);
fence = dma_fence_get(&s_fence->scheduled);
dma_fence_put(old);
}
- if (IS_ERR(fence)) {
- r = PTR_ERR(fence);
- amdgpu_ctx_put(ctx);
+ r = amdgpu_sync_fence(p->adev, &p->job->sync, fence, true);
+ dma_fence_put(fence);
+ if (r)
return r;
- } else if (fence) {
- r = amdgpu_sync_fence(p->adev, &p->job->sync, fence,
- true);
- dma_fence_put(fence);
- amdgpu_ctx_put(ctx);
- if (r)
- return r;
- }
}
return 0;
}
@@ -1145,6 +1143,9 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
num_deps = chunk->length_dw * 4 /
sizeof(struct drm_amdgpu_cs_chunk_sem);
+ if (p->post_deps)
+ return -EINVAL;
+
p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
GFP_KERNEL);
p->num_post_deps = 0;
@@ -1168,8 +1169,7 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p,
- struct amdgpu_cs_chunk
- *chunk)
+ struct amdgpu_cs_chunk *chunk)
{
struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps;
unsigned num_deps;
@@ -1179,6 +1179,9 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p
num_deps = chunk->length_dw * 4 /
sizeof(struct drm_amdgpu_cs_chunk_syncobj);
+ if (p->post_deps)
+ return -EINVAL;
+
p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
GFP_KERNEL);
p->num_post_deps = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index f539a2a92774..7398b4850649 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -534,21 +534,24 @@ int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
struct drm_sched_entity *entity)
{
struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
- unsigned idx = centity->sequence & (amdgpu_sched_jobs - 1);
- struct dma_fence *other = centity->fences[idx];
+ struct dma_fence *other;
+ unsigned idx;
+ long r;
- if (other) {
- signed long r;
- r = dma_fence_wait(other, true);
- if (r < 0) {
- if (r != -ERESTARTSYS)
- DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+ spin_lock(&ctx->ring_lock);
+ idx = centity->sequence & (amdgpu_sched_jobs - 1);
+ other = dma_fence_get(centity->fences[idx]);
+ spin_unlock(&ctx->ring_lock);
- return r;
- }
- }
+ if (!other)
+ return 0;
- return 0;
+ r = dma_fence_wait(other, true);
+ if (r < 0 && r != -ERESTARTSYS)
+ DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+
+ dma_fence_put(other);
+ return r;
}
void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 6d54decef7f8..5652cc72ed3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -707,7 +707,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
thread = (*pos & GENMASK_ULL(59, 52)) >> 52;
bank = (*pos & GENMASK_ULL(61, 60)) >> 60;
- data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);
+ data = kcalloc(1024, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index f2e8b4238efd..5376328d3fd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -148,7 +148,7 @@ struct amdgpu_mgpu_info mgpu_info = {
.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
};
int amdgpu_ras_enable = -1;
-uint amdgpu_ras_mask = 0xffffffff;
+uint amdgpu_ras_mask = 0xfffffffb;
/**
* DOC: vramlimit (int)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
index df8a23554831..f6ac1e9548f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
@@ -32,7 +32,6 @@ struct amdgpu_gds {
uint32_t gws_size;
uint32_t oa_size;
uint32_t gds_compute_max_wave_id;
- uint32_t vgt_gs_max_wave_id;
};
struct amdgpu_gds_reg_offset {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 8b7efd0a7028..2b546567853b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -159,12 +159,16 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev,
struct amdgpu_device *adev = ddev->dev_private;
enum amd_pm_state_type pm;
- if (is_support_sw_smu(adev) && adev->smu.ppt_funcs->get_current_power_state)
- pm = amdgpu_smu_get_current_power_state(adev);
- else if (adev->powerplay.pp_funcs->get_current_power_state)
+ if (is_support_sw_smu(adev)) {
+ if (adev->smu.ppt_funcs->get_current_power_state)
+ pm = amdgpu_smu_get_current_power_state(adev);
+ else
+ pm = adev->pm.dpm.user_state;
+ } else if (adev->powerplay.pp_funcs->get_current_power_state) {
pm = amdgpu_dpm_get_current_power_state(adev);
- else
+ } else {
pm = adev->pm.dpm.user_state;
+ }
return snprintf(buf, PAGE_SIZE, "%s\n",
(pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
@@ -191,7 +195,11 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev,
goto fail;
}
- if (adev->powerplay.pp_funcs->dispatch_tasks) {
+ if (is_support_sw_smu(adev)) {
+ mutex_lock(&adev->pm.mutex);
+ adev->pm.dpm.user_state = state;
+ mutex_unlock(&adev->pm.mutex);
+ } else if (adev->powerplay.pp_funcs->dispatch_tasks) {
amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state);
} else {
mutex_lock(&adev->pm.mutex);
@@ -1734,7 +1742,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
return -EINVAL;
if (is_support_sw_smu(adev)) {
- err = smu_get_current_rpm(&adev->smu, &speed);
+ err = smu_get_fan_speed_rpm(&adev->smu, &speed);
if (err)
return err;
} else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) {
@@ -1794,7 +1802,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev,
return -EINVAL;
if (is_support_sw_smu(adev)) {
- err = smu_get_current_rpm(&adev->smu, &rpm);
+ err = smu_get_fan_speed_rpm(&adev->smu, &rpm);
if (err)
return err;
} else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) {
@@ -3067,28 +3075,44 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size))
seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64);
- /* UVD clocks */
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) {
- if (!value) {
- seq_printf(m, "UVD: Disabled\n");
- } else {
- seq_printf(m, "UVD: Enabled\n");
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
- seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
- seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+ if (adev->asic_type > CHIP_VEGA20) {
+ /* VCN clocks */
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) {
+ if (!value) {
+ seq_printf(m, "VCN: Disabled\n");
+ } else {
+ seq_printf(m, "VCN: Enabled\n");
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
+ seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
+ seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+ }
}
- }
- seq_printf(m, "\n");
+ seq_printf(m, "\n");
+ } else {
+ /* UVD clocks */
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) {
+ if (!value) {
+ seq_printf(m, "UVD: Disabled\n");
+ } else {
+ seq_printf(m, "UVD: Enabled\n");
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
+ seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
+ seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+ }
+ }
+ seq_printf(m, "\n");
- /* VCE clocks */
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) {
- if (!value) {
- seq_printf(m, "VCE: Disabled\n");
- } else {
- seq_printf(m, "VCE: Enabled\n");
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size))
- seq_printf(m, "\t%u MHz (ECCLK)\n", value/100);
+ /* VCE clocks */
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) {
+ if (!value) {
+ seq_printf(m, "VCE: Disabled\n");
+ } else {
+ seq_printf(m, "VCE: Enabled\n");
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size))
+ seq_printf(m, "\t%u MHz (ECCLK)\n", value/100);
+ }
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 1a4412e47810..fac7aa2c244f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -136,11 +136,6 @@ static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
struct amdgpu_bo **bo_ptr);
-static void amdgpu_ras_self_test(struct amdgpu_device *adev)
-{
- /* TODO */
-}
-
static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
{
@@ -689,6 +684,12 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
if (!obj)
return -EINVAL;
+ if (block_info.block_id != TA_RAS_BLOCK__UMC) {
+ DRM_INFO("%s error injection is not supported yet\n",
+ ras_block_str(info->head.block));
+ return -EINVAL;
+ }
+
ret = psp_ras_trigger_error(&adev->psp, &block_info);
if (ret)
DRM_ERROR("RAS ERROR: inject %s error failed ret %d\n",
@@ -1557,6 +1558,12 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
amdgpu_ras_check_supported(adev, &con->hw_supported,
&con->supported);
+ if (!con->hw_supported) {
+ amdgpu_ras_set_context(adev, NULL);
+ kfree(con);
+ return 0;
+ }
+
con->features = 0;
INIT_LIST_HEAD(&con->head);
/* Might need get this flag from vbios. */
@@ -1570,8 +1577,6 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
if (amdgpu_ras_fs_init(adev))
goto fs_out;
- amdgpu_ras_self_test(adev);
-
DRM_INFO("RAS INFO: ras initialized successfully, "
"hardware ability[%x] ras_mask[%x]\n",
con->hw_supported, con->supported);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 99f14fcc1460..19661c645703 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -30,6 +30,7 @@
#define AMDGPU_VCN_FIRMWARE_OFFSET 256
#define AMDGPU_VCN_MAX_ENC_RINGS 3
+#define VCN_DEC_KMD_CMD 0x80000000
#define VCN_DEC_CMD_FENCE 0x00000000
#define VCN_DEC_CMD_TRAP 0x00000001
#define VCN_DEC_CMD_WRITE_REG 0x00000004
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 1675d5837c3c..f41287f9000d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -1441,6 +1441,15 @@ static void gfx_v10_0_init_compute_vmid(struct amdgpu_device *adev)
}
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+ acccess. These should be enabled by FW for target VMIDs. */
+ for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_BASE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_SIZE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_GWS_VMID0, i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_OA_VMID0, i, 0);
+ }
}
static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
@@ -4197,15 +4206,6 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
u32 header, control = 0;
- /* Prevent a hw deadlock due to a wave ID mismatch between ME and GDS.
- * This resets the wave ID counters. (needed by transform feedback)
- * TODO: This might only be needed on a VMID switch when we change
- * the GDS OA mapping, not sure.
- */
- amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
- amdgpu_ring_write(ring, mmVGT_GS_MAX_WAVE_ID);
- amdgpu_ring_write(ring, ring->adev->gds.vgt_gs_max_wave_id);
-
if (ib->flags & AMDGPU_IB_FLAG_CE)
header = PACKET3(PACKET3_INDIRECT_BUFFER_CNST, 2);
else
@@ -4611,6 +4611,7 @@ gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
TIME_STAMP_INT_ENABLE, 0);
WREG32(cp_int_cntl_reg, cp_int_cntl);
+ break;
case AMDGPU_IRQ_STATE_ENABLE:
cp_int_cntl = RREG32(cp_int_cntl_reg);
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
@@ -4951,7 +4952,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
5 + /* HDP_INVL */
8 + 8 + /* FENCE x2 */
2, /* SWITCH_BUFFER */
- .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_gfx */
+ .emit_ib_size = 4, /* gfx_v10_0_ring_emit_ib_gfx */
.emit_ib = gfx_v10_0_ring_emit_ib_gfx,
.emit_fence = gfx_v10_0_ring_emit_fence,
.emit_pipeline_sync = gfx_v10_0_ring_emit_pipeline_sync,
@@ -5102,7 +5103,6 @@ static void gfx_v10_0_set_gds_init(struct amdgpu_device *adev)
default:
adev->gds.gds_size = 0x10000;
adev->gds.gds_compute_max_wave_id = 0x4ff;
- adev->gds.vgt_gs_max_wave_id = 0x3ff;
break;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 0db9f488da7e..21187275dfd3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -1879,6 +1879,15 @@ static void gfx_v7_0_init_compute_vmid(struct amdgpu_device *adev)
}
cik_srbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+ acccess. These should be enabled by FW for target VMIDs. */
+ for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+ WREG32(amdgpu_gds_reg_offset[i].mem_base, 0);
+ WREG32(amdgpu_gds_reg_offset[i].mem_size, 0);
+ WREG32(amdgpu_gds_reg_offset[i].gws, 0);
+ WREG32(amdgpu_gds_reg_offset[i].oa, 0);
+ }
}
static void gfx_v7_0_config_init(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 5f401b41ef7c..ee1ccdcf2d30 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -1321,6 +1321,39 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
return 0;
}
+static int gfx_v8_0_csb_vram_pin(struct amdgpu_device *adev)
+{
+ int r;
+
+ r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+ if (unlikely(r != 0))
+ return r;
+
+ r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
+ AMDGPU_GEM_DOMAIN_VRAM);
+ if (!r)
+ adev->gfx.rlc.clear_state_gpu_addr =
+ amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
+
+ amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+
+ return r;
+}
+
+static void gfx_v8_0_csb_vram_unpin(struct amdgpu_device *adev)
+{
+ int r;
+
+ if (!adev->gfx.rlc.clear_state_obj)
+ return;
+
+ r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
+ if (likely(r == 0)) {
+ amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
+ amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+ }
+}
+
static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
{
amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -3706,6 +3739,15 @@ static void gfx_v8_0_init_compute_vmid(struct amdgpu_device *adev)
}
vi_srbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+ acccess. These should be enabled by FW for target VMIDs. */
+ for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+ WREG32(amdgpu_gds_reg_offset[i].mem_base, 0);
+ WREG32(amdgpu_gds_reg_offset[i].mem_size, 0);
+ WREG32(amdgpu_gds_reg_offset[i].gws, 0);
+ WREG32(amdgpu_gds_reg_offset[i].oa, 0);
+ }
}
static void gfx_v8_0_config_init(struct amdgpu_device *adev)
@@ -4776,6 +4818,10 @@ static int gfx_v8_0_hw_init(void *handle)
gfx_v8_0_init_golden_registers(adev);
gfx_v8_0_constants_init(adev);
+ r = gfx_v8_0_csb_vram_pin(adev);
+ if (r)
+ return r;
+
r = adev->gfx.rlc.funcs->resume(adev);
if (r)
return r;
@@ -4892,6 +4938,9 @@ static int gfx_v8_0_hw_fini(void *handle)
else
pr_err("rlc is busy, skip halt rlc\n");
amdgpu_gfx_rlc_exit_safe_mode(adev);
+
+ gfx_v8_0_csb_vram_unpin(adev);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index f4c4eea62526..c066e1d3f981 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -596,14 +596,18 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
case CHIP_VEGA20:
break;
case CHIP_RAVEN:
- if (adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
- break;
- if ((adev->gfx.rlc_fw_version != 106 &&
- adev->gfx.rlc_fw_version < 531) ||
- (adev->gfx.rlc_fw_version == 53815) ||
- (adev->gfx.rlc_feature_version < 1) ||
- !adev->gfx.rlc.is_rlc_v2_1)
+ if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
+ &&((adev->gfx.rlc_fw_version != 106 &&
+ adev->gfx.rlc_fw_version < 531) ||
+ (adev->gfx.rlc_fw_version == 53815) ||
+ (adev->gfx.rlc_feature_version < 1) ||
+ !adev->gfx.rlc.is_rlc_v2_1))
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+
+ if (adev->pm.pp_feature & PP_GFXOFF_MASK)
+ adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+ AMD_PG_SUPPORT_CP |
+ AMD_PG_SUPPORT_RLC_SMU_HS;
break;
default:
break;
@@ -1918,6 +1922,15 @@ static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev)
}
soc15_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+ acccess. These should be enabled by FW for target VMIDs. */
+ for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_BASE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_SIZE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_GWS_VMID0, i, 0);
+ WREG32_SOC15_OFFSET(GC, 0, mmGDS_OA_VMID0, i, 0);
+ }
}
static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
@@ -4860,7 +4873,7 @@ static void gfx_v9_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
- WREG32(mmSQ_CMD, value);
+ WREG32_SOC15(GC, 0, mmSQ_CMD, value);
}
static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 662612f89c70..9922bce3fd89 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -552,7 +552,6 @@ static int nv_common_early_init(void *handle)
AMD_CG_SUPPORT_BIF_LS;
adev->pg_flags = AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_VCN_DPG |
- AMD_PG_SUPPORT_MMHUB |
AMD_PG_SUPPORT_ATHUB;
adev->external_rev_id = adev->rev_id + 0x1;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index 23265414d448..04fbf05d7176 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -992,11 +992,6 @@ static int soc15_common_early_init(void *handle)
adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
}
-
- if (adev->pm.pp_feature & PP_GFXOFF_MASK)
- adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
- AMD_PG_SUPPORT_CP |
- AMD_PG_SUPPORT_RLC_SMU_HS;
break;
default:
/* FIXME: not supported yet */
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 988c0adaca91..dfde886cc6bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -372,11 +372,8 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
upper_32_bits(adev->vcn.gpu_addr));
offset = size;
- /* No signed header for now from firmware
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0,
AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
- */
- WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, 0);
}
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size);
@@ -1488,7 +1485,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_START << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
}
/**
@@ -1501,7 +1498,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
static void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
{
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_END << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
}
/**
@@ -1546,7 +1543,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_FENCE << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
amdgpu_ring_write(ring, 0);
@@ -1556,7 +1553,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_TRAP << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
}
/**
@@ -1600,7 +1597,7 @@ static void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_REG_READ_COND_WAIT << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
}
static void vcn_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
@@ -1629,7 +1626,7 @@ static void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
- amdgpu_ring_write(ring, VCN_DEC_CMD_WRITE_REG << 1);
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
}
/**
@@ -2082,6 +2079,36 @@ static int vcn_v2_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
+static int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t tmp = 0;
+ unsigned i;
+ int r;
+
+ WREG32(adev->vcn.external.scratch9, 0xCAFEDEAD);
+ r = amdgpu_ring_alloc(ring, 4);
+ if (r)
+ return r;
+ amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
+ amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
+ amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
+ amdgpu_ring_write(ring, 0xDEADBEEF);
+ amdgpu_ring_commit(ring);
+ for (i = 0; i < adev->usec_timeout; i++) {
+ tmp = RREG32(adev->vcn.external.scratch9);
+ if (tmp == 0xDEADBEEF)
+ break;
+ DRM_UDELAY(1);
+ }
+
+ if (i >= adev->usec_timeout)
+ r = -ETIMEDOUT;
+
+ return r;
+}
+
+
static int vcn_v2_0_set_powergating_state(void *handle,
enum amd_powergating_state state)
{
@@ -2145,7 +2172,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
.emit_ib = vcn_v2_0_dec_ring_emit_ib,
.emit_fence = vcn_v2_0_dec_ring_emit_fence,
.emit_vm_flush = vcn_v2_0_dec_ring_emit_vm_flush,
- .test_ring = amdgpu_vcn_dec_ring_test_ring,
+ .test_ring = vcn_v2_0_dec_ring_test_ring,
.test_ib = amdgpu_vcn_dec_ring_test_ib,
.insert_nop = vcn_v2_0_dec_ring_insert_nop,
.insert_start = vcn_v2_0_dec_ring_insert_start,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 26b15cc56c31..1d3cd5c50d5f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1567,32 +1567,6 @@ copy_from_user_failed:
return err;
}
-static int kfd_ioctl_alloc_queue_gws(struct file *filep,
- struct kfd_process *p, void *data)
-{
- int retval;
- struct kfd_ioctl_alloc_queue_gws_args *args = data;
- struct kfd_dev *dev;
-
- if (!hws_gws_support)
- return -ENODEV;
-
- dev = kfd_device_by_id(args->gpu_id);
- if (!dev) {
- pr_debug("Could not find gpu id 0x%x\n", args->gpu_id);
- return -ENODEV;
- }
- if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
- return -ENODEV;
-
- mutex_lock(&p->mutex);
- retval = pqm_set_gws(&p->pqm, args->queue_id, args->num_gws ? dev->gws : NULL);
- mutex_unlock(&p->mutex);
-
- args->first_gws = 0;
- return retval;
-}
-
static int kfd_ioctl_get_dmabuf_info(struct file *filep,
struct kfd_process *p, void *data)
{
@@ -1795,8 +1769,6 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
AMDKFD_IOCTL_DEF(AMDKFD_IOC_IMPORT_DMABUF,
kfd_ioctl_import_dmabuf, 0),
- AMDKFD_IOCTL_DEF(AMDKFD_IOC_ALLOC_QUEUE_GWS,
- kfd_ioctl_alloc_queue_gws, 0),
};
#define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 792371442195..4e3fc284f6ac 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -668,6 +668,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
case CHIP_RAVEN:
pcache_info = raven_cache_info;
num_of_cache_types = ARRAY_SIZE(raven_cache_info);
+ break;
case CHIP_NAVI10:
pcache_info = navi10_cache_info;
num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
index 4f8a6ffc5775..9cd3eb2d90bd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
@@ -429,7 +429,6 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
switch (type) {
case KFD_MQD_TYPE_CP:
- pr_debug("%s@%i\n", __func__, __LINE__);
case KFD_MQD_TYPE_COMPUTE:
pr_debug("%s@%i\n", __func__, __LINE__);
mqd->allocate_mqd = allocate_mqd;
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 4a29f72334d0..45be7a2132bb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3131,13 +3131,25 @@ static enum dc_color_depth
convert_color_depth_from_display_info(const struct drm_connector *connector,
const struct drm_connector_state *state)
{
- uint32_t bpc = connector->display_info.bpc;
+ uint8_t bpc = (uint8_t)connector->display_info.bpc;
+
+ /* Assume 8 bpc by default if no bpc is specified. */
+ bpc = bpc ? bpc : 8;
if (!state)
state = connector->state;
if (state) {
- bpc = state->max_bpc;
+ /*
+ * Cap display bpc based on the user requested value.
+ *
+ * The value for state->max_bpc may not correctly updated
+ * depending on when the connector gets added to the state
+ * or if this was called outside of atomic check, so it
+ * can't be used directly.
+ */
+ bpc = min(bpc, state->max_requested_bpc);
+
/* Round down to the nearest even number. */
bpc = bpc - (bpc & 1);
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
index c1a92c16535c..5cc3acccda2a 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
@@ -262,12 +262,12 @@ void dce110_clk_mgr_construct(
struct dc_context *ctx,
struct clk_mgr_internal *clk_mgr)
{
+ dce_clk_mgr_construct(ctx, clk_mgr);
+
memcpy(clk_mgr->max_clks_by_state,
dce110_max_clks_by_state,
sizeof(dce110_max_clks_by_state));
- dce_clk_mgr_construct(ctx, clk_mgr);
-
clk_mgr->regs = &disp_clk_regs;
clk_mgr->clk_mgr_shift = &disp_clk_shift;
clk_mgr->clk_mgr_mask = &disp_clk_mask;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
index 778392c73187..7c746ef1e32e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
@@ -226,12 +226,12 @@ void dce112_clk_mgr_construct(
struct dc_context *ctx,
struct clk_mgr_internal *clk_mgr)
{
+ dce_clk_mgr_construct(ctx, clk_mgr);
+
memcpy(clk_mgr->max_clks_by_state,
dce112_max_clks_by_state,
sizeof(dce112_max_clks_by_state));
- dce_clk_mgr_construct(ctx, clk_mgr);
-
clk_mgr->regs = &disp_clk_regs;
clk_mgr->clk_mgr_shift = &disp_clk_shift;
clk_mgr->clk_mgr_mask = &disp_clk_mask;
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 906310c3e2eb..5399b8cf6b75 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
@@ -127,12 +127,12 @@ static struct clk_mgr_funcs dce120_funcs = {
void dce120_clk_mgr_construct(struct dc_context *ctx, struct clk_mgr_internal *clk_mgr)
{
+ dce_clk_mgr_construct(ctx, clk_mgr);
+
memcpy(clk_mgr->max_clks_by_state,
dce120_max_clks_by_state,
sizeof(dce120_max_clks_by_state));
- dce_clk_mgr_construct(ctx, clk_mgr);
-
clk_mgr->base.dprefclk_khz = 600000;
clk_mgr->base.funcs = &dce120_funcs;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
index 08a774fc7b67..50bfb5921de0 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
@@ -301,6 +301,8 @@ void dcn2_update_clocks_fpga(struct clk_mgr *clk_mgr,
void dcn2_init_clocks(struct clk_mgr *clk_mgr)
{
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+ // Assumption is that boot state always supports pstate
+ clk_mgr->clks.p_state_change_support = true;
}
void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base)
@@ -331,6 +333,7 @@ void dcn20_clk_mgr_construct(
struct dccg *dccg)
{
clk_mgr->base.ctx = ctx;
+ clk_mgr->pp_smu = pp_smu;
clk_mgr->base.funcs = &dcn2_funcs;
clk_mgr->regs = &clk_mgr_regs;
clk_mgr->clk_mgr_shift = &clk_mgr_shift;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 4ef4dc63e221..cbc480a33376 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -23,6 +23,7 @@
*/
#include <linux/slab.h>
+#include <linux/mm.h>
#include "dm_services.h"
@@ -502,8 +503,10 @@ void dc_stream_set_static_screen_events(struct dc *dc,
static void destruct(struct dc *dc)
{
- dc_release_state(dc->current_state);
- dc->current_state = NULL;
+ if (dc->current_state) {
+ dc_release_state(dc->current_state);
+ dc->current_state = NULL;
+ }
destroy_links(dc);
@@ -1169,8 +1172,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
struct dc_state *dc_create_state(struct dc *dc)
{
- struct dc_state *context = kzalloc(sizeof(struct dc_state),
- GFP_KERNEL);
+ struct dc_state *context = kvzalloc(sizeof(struct dc_state),
+ GFP_KERNEL);
if (!context)
return NULL;
@@ -1190,11 +1193,11 @@ struct dc_state *dc_create_state(struct dc *dc)
struct dc_state *dc_copy_state(struct dc_state *src_ctx)
{
int i, j;
- struct dc_state *new_ctx = kmemdup(src_ctx,
- sizeof(struct dc_state), GFP_KERNEL);
+ struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
if (!new_ctx)
return NULL;
+ memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
@@ -1228,7 +1231,7 @@ static void dc_state_free(struct kref *kref)
{
struct dc_state *context = container_of(kref, struct dc_state, refcount);
dc_resource_state_destruct(context);
- kfree(context);
+ kvfree(context);
}
void dc_release_state(struct dc_state *context)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 8dbf759eba45..355b4ba12796 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -532,6 +532,7 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
uint32_t read_dpcd_retry_cnt = 10;
enum dc_status status = DC_ERROR_UNEXPECTED;
int i;
+ union max_down_spread max_down_spread = { {0} };
// Read DPCD 00101h to find out the number of lanes currently set
for (i = 0; i < read_dpcd_retry_cnt; i++) {
@@ -553,8 +554,6 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
msleep(8);
}
- ASSERT(status == DC_OK);
-
// Read DPCD 00100h to find if standard link rates are set
core_link_read_dpcd(link, DP_LINK_BW_SET,
&link_bw_set, sizeof(link_bw_set));
@@ -576,6 +575,12 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
link->cur_link_settings.link_rate = link_bw_set;
link->cur_link_settings.use_link_rate_set = false;
}
+ // Read DPCD 00003h to find the max down spread.
+ core_link_read_dpcd(link, DP_MAX_DOWNSPREAD,
+ &max_down_spread.raw, sizeof(max_down_spread));
+ link->cur_link_settings.link_spread =
+ max_down_spread.bits.MAX_DOWN_SPREAD ?
+ LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
}
static bool detect_dp(
@@ -717,13 +722,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
return false;
}
- if (link->connector_signal == SIGNAL_TYPE_EDP) {
- /* On detect, we want to make sure current link settings are
- * up to date, especially if link was powered on by GOP.
- */
- read_edp_current_link_settings_on_detect(link);
- }
-
prev_sink = link->local_sink;
if (prev_sink != NULL) {
dc_sink_retain(prev_sink);
@@ -765,6 +763,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
}
case SIGNAL_TYPE_EDP: {
+ read_edp_current_link_settings_on_detect(link);
detect_edp_sink_caps(link);
sink_caps.transaction_type =
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
@@ -2329,7 +2328,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
if (core_dc->current_state->res_ctx.
pipe_ctx[i].stream->link
- == link)
+ == link) {
/* DMCU -1 for all controller id values,
* therefore +1 here
*/
@@ -2337,6 +2336,13 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
core_dc->current_state->
res_ctx.pipe_ctx[i].stream_res.tg->inst +
1;
+
+ /* Disable brightness ramping when the display is blanked
+ * as it can hang the DMCU
+ */
+ if (core_dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL)
+ frame_ramp = 0;
+ }
}
}
abm->funcs->set_backlight_level_pwm(
@@ -2984,8 +2990,10 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
/* Retrain with preferred link settings only relevant for
* DP signal type
+ * Check for non-DP signal or if passive dongle present
*/
- if (!dc_is_dp_signal(link->connector_signal))
+ if (!dc_is_dp_signal(link->connector_signal) ||
+ link->dongle_max_pix_clk > 0)
return;
for (i = 0; i < MAX_PIPES; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 056be4c34a98..2c7aaed907b9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -2230,18 +2230,25 @@ static void get_active_converter_info(
link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
ddc_service_set_dongle_type(link->ddc,
link->dpcd_caps.dongle_type);
+ link->dpcd_caps.is_branch_dev = false;
return;
}
/* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
- link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
+ if (ds_port.fields.PORT_TYPE == DOWNSTREAM_DP) {
+ link->dpcd_caps.is_branch_dev = false;
+ }
+
+ else {
+ link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
+ }
switch (ds_port.fields.PORT_TYPE) {
case DOWNSTREAM_VGA:
link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
break;
- case DOWNSTREAM_DVI_HDMI:
- /* At this point we don't know is it DVI or HDMI,
+ case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
+ /* At this point we don't know is it DVI or HDMI or DP++,
* assume DVI.*/
link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
break;
@@ -2258,6 +2265,10 @@ static void get_active_converter_info(
det_caps, sizeof(det_caps));
switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
+ /*Handle DP case as DONGLE_NONE*/
+ case DOWN_STREAM_DETAILED_DP:
+ link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+ break;
case DOWN_STREAM_DETAILED_VGA:
link->dpcd_caps.dongle_type =
DISPLAY_DONGLE_DP_VGA_CONVERTER;
@@ -2267,6 +2278,8 @@ static void get_active_converter_info(
DISPLAY_DONGLE_DP_DVI_CONVERTER;
break;
case DOWN_STREAM_DETAILED_HDMI:
+ case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
+ /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
link->dpcd_caps.dongle_type =
DISPLAY_DONGLE_DP_HDMI_CONVERTER;
@@ -2282,14 +2295,18 @@ static void get_active_converter_info(
link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
- hdmi_caps.bits.YCrCr422_PASS_THROUGH;
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
- hdmi_caps.bits.YCrCr420_PASS_THROUGH;
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
- hdmi_caps.bits.YCrCr422_CONVERSION;
- link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
- hdmi_caps.bits.YCrCr420_CONVERSION;
+ /*YCBCR capability only for HDMI case*/
+ if (port_caps->bits.DWN_STRM_PORTX_TYPE
+ == DOWN_STREAM_DETAILED_HDMI) {
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
+ hdmi_caps.bits.YCrCr422_PASS_THROUGH;
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
+ hdmi_caps.bits.YCrCr420_PASS_THROUGH;
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
+ hdmi_caps.bits.YCrCr422_CONVERSION;
+ link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
+ hdmi_caps.bits.YCrCr420_CONVERSION;
+ }
link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
translate_dpcd_max_bpc(
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 51a78283a86d..2ceaab4fb5de 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -258,7 +258,7 @@ bool resource_construct(
* PORT_CONNECTIVITY == 1 (as instructed by HW team).
*/
update_num_audio(&straps, &num_audio, &pool->audio_support);
- for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
+ for (i = 0; i < caps->num_audio; i++) {
struct audio *aud = create_funcs->create_audio(ctx, i);
if (aud == NULL) {
@@ -1669,6 +1669,12 @@ static struct audio *find_first_free_audio(
return pool->audios[i];
}
}
+
+ /* use engine id to find free audio */
+ if ((id < pool->audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
+ return pool->audios[id];
+ }
+
/*not found the matching one, first come first serve*/
for (i = 0; i < pool->audio_count; i++) {
if (res_ctx->is_audio_acquired[i] == false) {
@@ -1833,6 +1839,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
pix_clk /= 2;
if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
switch (timing->display_color_depth) {
+ case COLOR_DEPTH_666:
case COLOR_DEPTH_888:
normalized_pix_clk = pix_clk;
break;
@@ -1979,7 +1986,7 @@ enum dc_status resource_map_pool_resources(
/* TODO: Add check if ASIC support and EDID audio */
if (!stream->converter_disable_audio &&
dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
- stream->audio_info.mode_count) {
+ stream->audio_info.mode_count && stream->audio_info.flags.all) {
pipe_ctx->stream_res.audio = find_first_free_audio(
&context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id);
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 af7f8be230f7..352862370390 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -612,7 +612,8 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
pipe_ctx->stream->dmdata_address = attr->address;
- if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
+ if (pipe_ctx->stream_res.stream_enc &&
+ pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
/* if using dynamic meta, don't set up generic infopackets */
pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index f8903bcabe49..58bd131d5b48 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -239,6 +239,10 @@ static void dmcu_set_backlight_level(
s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
REG_WRITE(BIOS_SCRATCH_2, s2);
+
+ /* waitDMCUReadyForCmd */
+ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
+ 0, 1, 80000);
}
static void dce_abm_init(struct abm *abm)
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 858a58856ebd..fafb4b470140 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -965,11 +965,17 @@ void hwss_edp_backlight_control(
void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
{
/* notify audio driver for audio modes of monitor */
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *core_dc;
struct pp_smu_funcs *pp_smu = NULL;
- struct clk_mgr *clk_mgr = core_dc->clk_mgr;
+ struct clk_mgr *clk_mgr;
unsigned int i, num_audio = 1;
+ if (!pipe_ctx->stream)
+ return;
+
+ core_dc = pipe_ctx->stream->ctx->dc;
+ clk_mgr = core_dc->clk_mgr;
+
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
return;
@@ -999,9 +1005,15 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
{
- struct dc *dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc;
struct pp_smu_funcs *pp_smu = NULL;
- struct clk_mgr *clk_mgr = dc->clk_mgr;
+ struct clk_mgr *clk_mgr;
+
+ if (!pipe_ctx || !pipe_ctx->stream)
+ return;
+
+ dc = pipe_ctx->stream->ctx->dc;
+ clk_mgr = dc->clk_mgr;
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
return;
@@ -1009,6 +1021,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, true);
if (pipe_ctx->stream_res.audio) {
+ pipe_ctx->stream_res.audio->enabled = false;
+
if (dc->res_pool->pp_smu)
pp_smu = dc->res_pool->pp_smu;
@@ -1039,8 +1053,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
/* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
* stream->stream_engine_id);
*/
- if (pipe_ctx->stream_res.audio)
- pipe_ctx->stream_res.audio->enabled = false;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index e50a696fcb5d..2118ea21d7e9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1195,16 +1195,7 @@ static void dcn10_init_hw(struct dc *dc)
* everything down.
*/
if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct hubp *hubp = dc->res_pool->hubps[i];
- struct dpp *dpp = dc->res_pool->dpps[i];
-
- hubp->funcs->hubp_init(hubp);
- dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
- plane_atomic_power_down(dc, dpp, hubp);
- }
-
- apply_DEGVIDCN10_253_wa(dc);
+ dc->hwss.init_pipes(dc, dc->current_state);
}
for (i = 0; i < dc->res_pool->audio_count; i++) {
@@ -1375,10 +1366,6 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
return result;
}
-
-
-
-
static bool
dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
@@ -2516,6 +2503,12 @@ static void dcn10_apply_ctx_for_surface(
if (removed_pipe[i])
dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+ for (i = 0; i < dc->res_pool->pipe_count; i++)
+ if (removed_pipe[i]) {
+ dc->hwss.optimize_bandwidth(dc, context);
+ break;
+ }
+
if (dc->hwseq->wa.DEGVIDCN10_254)
hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
}
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 1a20461c2937..a12530a3ab9c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -508,7 +508,7 @@ static const struct resource_caps rv2_res_cap = {
.num_audio = 3,
.num_stream_encoder = 3,
.num_pll = 3,
- .num_ddc = 3,
+ .num_ddc = 4,
};
static const struct dc_plane_cap plane_cap = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
index 51a3dfe97f0e..31aa6ee5cd5b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
@@ -102,14 +102,19 @@ void dccg2_init(struct dccg *dccg)
switch (dccg_dcn->base.ctx->dc->res_pool->pipe_count) {
case 6:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[5], 1);
+ /* Fall through */
case 5:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[4], 1);
+ /* Fall through */
case 4:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[3], 1);
+ /* Fall through */
case 3:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[2], 1);
+ /* Fall through */
case 2:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[1], 1);
+ /* Fall through */
case 1:
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[0], 1);
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
index ece6e136437b..6e2dbd03f9bf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
@@ -337,6 +337,7 @@ static enum dcn_hubbub_page_table_block_size page_table_block_size_to_hw(unsigne
break;
default:
ASSERT(false);
+ block_size = page_table_block_size;
break;
}
@@ -366,25 +367,24 @@ int hubbub2_init_dchub_sys_ctx(struct hubbub *hubbub,
struct dcn_vmid_page_table_config phys_config;
REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
- FB_BASE, pa_config->system_aperture.fb_base);
+ FB_BASE, pa_config->system_aperture.fb_base >> 24);
REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
- FB_TOP, pa_config->system_aperture.fb_top);
+ FB_TOP, pa_config->system_aperture.fb_top >> 24);
REG_SET(DCN_VM_FB_OFFSET, 0,
- FB_OFFSET, pa_config->system_aperture.fb_offset);
+ FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
REG_SET(DCN_VM_AGP_BOT, 0,
- AGP_BOT, pa_config->system_aperture.agp_bot);
+ AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
REG_SET(DCN_VM_AGP_TOP, 0,
- AGP_TOP, pa_config->system_aperture.agp_top);
+ AGP_TOP, pa_config->system_aperture.agp_top >> 24);
REG_SET(DCN_VM_AGP_BASE, 0,
- AGP_BASE, pa_config->system_aperture.agp_base);
+ AGP_BASE, pa_config->system_aperture.agp_base >> 24);
if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
- phys_config.depth = 1;
- phys_config.block_size = 4096;
phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
-
+ phys_config.depth = 0;
+ phys_config.block_size = 0;
// Init VMID 0 based on PA config
dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 0b84a322b8a2..d810c8940129 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1153,8 +1153,8 @@ void dcn20_enable_plane(
apt.sys_default.quad_part = 0;
- apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.start_addr;
- apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.end_addr;
+ apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
+ apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
// Program system aperture settings
pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
@@ -1242,6 +1242,8 @@ void dcn20_pipe_control_lock_global(
CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
CRTC_STATE_VBLANK);
+ pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
+ CRTC_STATE_VACTIVE);
pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
pipe->stream_res.tg);
}
@@ -1263,6 +1265,17 @@ void dcn20_pipe_control_lock(
if (pipe->plane_state != NULL)
flip_immediate = pipe->plane_state->flip_immediate;
+ if (flip_immediate && lock) {
+ while (pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp)) {
+ udelay(1);
+ }
+
+ if (pipe->bottom_pipe != NULL)
+ while (pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp)) {
+ udelay(1);
+ }
+ }
+
/* In flip immediate and pipe splitting case, we need to use GSL
* for synchronization. Only do setup on locking and on flip type change.
*/
@@ -1740,8 +1753,11 @@ static void dcn20_reset_back_end_for_pipe(
else if (pipe_ctx->stream_res.audio) {
dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
}
-
}
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+ else if (pipe_ctx->stream_res.dsc)
+ dp_set_dsc_enable(pipe_ctx, false);
+#endif
/* by upper caller loop, parent pipe: pipe0, will be reset last.
* back end share by all pipes and will be disable only when disable
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 26a66ccf6e72..1ae973962d53 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -535,7 +535,7 @@ void dcn20_timing_generator_init(struct optc *optc1)
optc1->min_h_blank = 32;
optc1->min_v_blank = 3;
optc1->min_v_blank_interlace = 5;
- optc1->min_h_sync_width = 8;
+ optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue.
optc1->min_v_sync_width = 1;
optc1->comb_opp_id = 0xf;
}
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 d200bc3cec71..b949e202d6cb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -2643,6 +2643,10 @@ static void update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_
if (dc->bb_overrides.min_dcfclk_mhz > 0)
min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
+ else
+ // Accounting for SOC/DCF relationship, we can go as high as
+ // 506Mhz in Vmin. We need to code 507 since SMU will round down to 506.
+ min_dcfclk = 507;
for (i = 0; i < num_states; i++) {
int min_fclk_required_by_uclk;
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 27679ef6ebe8..96c263223315 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
@@ -23,6 +23,8 @@
*
*/
+#include <linux/delay.h>
+
#include "dcn20_vmid.h"
#include "reg_helper.h"
@@ -36,6 +38,38 @@
#define FN(reg_name, field_name) \
vmid->shifts->field_name, vmid->masks->field_name
+static void dcn20_wait_for_vmid_ready(struct dcn20_vmid *vmid)
+{
+ /* According the hardware spec, we need to poll for the lowest
+ * bit of PAGE_TABLE_BASE_ADDR_LO32 = 1 any time a GPUVM
+ * context is updated. We can't use REG_WAIT here since we
+ * don't have a seperate field to wait on.
+ *
+ * TODO: Confirm timeout / poll interval with hardware team
+ */
+
+ int max_times = 10000;
+ int delay_us = 5;
+ int i;
+
+ for (i = 0; i < max_times; ++i) {
+ uint32_t entry_lo32;
+
+ REG_GET(PAGE_TABLE_BASE_ADDR_LO32,
+ VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_LO32,
+ &entry_lo32);
+
+ if (entry_lo32 & 0x1)
+ return;
+
+ udelay(delay_us);
+ }
+
+ /* VM setup timed out */
+ DC_LOG_WARNING("Timeout while waiting for GPUVM context update\n");
+ ASSERT(0);
+}
+
void dcn20_vmid_setup(struct dcn20_vmid *vmid, const struct dcn_vmid_page_table_config *config)
{
REG_SET(PAGE_TABLE_START_ADDR_HI32, 0,
@@ -54,6 +88,9 @@ void dcn20_vmid_setup(struct dcn20_vmid *vmid, const struct dcn_vmid_page_table_
REG_SET(PAGE_TABLE_BASE_ADDR_HI32, 0,
VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_HI32, (config->page_table_base_addr >> 32) & 0xFFFFFFFF);
+ /* Note: per hardware spec PAGE_TABLE_BASE_ADDR_LO32 must be programmed last in sequence */
REG_SET(PAGE_TABLE_BASE_ADDR_LO32, 0,
VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_LO32, config->page_table_base_addr & 0xFFFFFFFF);
+
+ dcn20_wait_for_vmid_ready(vmid);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c b/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
index 67089765780b..340ef4d41ebd 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
@@ -377,6 +377,12 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16;
vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay;
+ /* As per DSC spec v1.2a recommendation: */
+ if (vdsc_cfg->native_420)
+ vdsc_cfg->second_line_offset_adj = 512;
+ else
+ vdsc_cfg->second_line_offset_adj = 0;
+
return 0;
}
EXPORT_SYMBOL(drm_dsc_compute_rc_parameters);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index c89393c19232..a148ffde8b12 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -212,7 +212,7 @@ struct resource_pool {
struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
unsigned int clk_src_count;
- struct audio *audios[MAX_PIPES];
+ struct audio *audios[MAX_AUDIOS];
unsigned int audio_count;
struct audio_support audio_support;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 959f5b654611..9502478c4a1b 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -61,8 +61,8 @@ enum dcn_hubbub_page_table_depth {
};
enum dcn_hubbub_page_table_block_size {
- DCN_PAGE_TABLE_BLOCK_SIZE_4KB,
- DCN_PAGE_TABLE_BLOCK_SIZE_64KB
+ DCN_PAGE_TABLE_BLOCK_SIZE_4KB = 0,
+ DCN_PAGE_TABLE_BLOCK_SIZE_64KB = 4,
};
struct dcn_hubbub_phys_addr_config {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
index 8759ec03aede..f82365e2d03c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
@@ -34,6 +34,7 @@
* Data types shared between different Virtual HW blocks
******************************************************************************/
+#define MAX_AUDIOS 7
#define MAX_PIPES 6
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#define MAX_DWB_PIPES 1
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 1c66166d0a94..2c90d1b46c8b 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -43,7 +43,7 @@ enum dpcd_revision {
enum dpcd_downstream_port_type {
DOWNSTREAM_DP = 0,
DOWNSTREAM_VGA,
- DOWNSTREAM_DVI_HDMI,
+ DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS,/* DVI, HDMI, DP++ */
DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */
};
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 9f661bf96ed0..5b1ebb7f995a 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -123,6 +123,7 @@ enum amd_pp_sensors {
AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK,
AMDGPU_PP_SENSOR_MIN_FAN_RPM,
AMDGPU_PP_SENSOR_MAX_FAN_RPM,
+ AMDGPU_PP_SENSOR_VCN_POWER_STATE,
};
enum amd_pp_task {
diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index f1565c448de5..8a3eadeebdcb 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -137,12 +137,37 @@ int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
{
int ret = 0, clk_id = 0;
uint32_t param = 0;
+ uint32_t clock_limit;
if (!min && !max)
return -EINVAL;
- if (!smu_clk_dpm_is_enabled(smu, clk_type))
+ if (!smu_clk_dpm_is_enabled(smu, clk_type)) {
+ switch (clk_type) {
+ case SMU_MCLK:
+ case SMU_UCLK:
+ clock_limit = smu->smu_table.boot_values.uclk;
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ clock_limit = smu->smu_table.boot_values.gfxclk;
+ break;
+ case SMU_SOCCLK:
+ clock_limit = smu->smu_table.boot_values.socclk;
+ break;
+ default:
+ clock_limit = 0;
+ break;
+ }
+
+ /* clock in Mhz unit */
+ if (min)
+ *min = clock_limit / 100;
+ if (max)
+ *max = clock_limit / 100;
+
return 0;
+ }
mutex_lock(&smu->mutex);
clk_id = smu_clk_get_index(smu, clk_type);
@@ -281,7 +306,8 @@ int smu_get_power_num_states(struct smu_context *smu,
/* not support power state */
memset(state_info, 0, sizeof(struct pp_states_info));
- state_info->nums = 0;
+ state_info->nums = 1;
+ state_info->states[0] = POWER_STATE_TYPE_DEFAULT;
return 0;
}
@@ -289,6 +315,8 @@ int smu_get_power_num_states(struct smu_context *smu,
int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
void *data, uint32_t *size)
{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
int ret = 0;
switch (sensor) {
@@ -312,6 +340,10 @@ int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
*(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT) ? 1 : 0;
*size = 4;
break;
+ case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
+ *(uint32_t *)data = power_gate->vcn_gated ? 0 : 1;
+ *size = 4;
+ break;
default:
ret = -EINVAL;
break;
@@ -698,6 +730,12 @@ static int smu_sw_init(void *handle)
return ret;
}
+ ret = smu_register_irq_handler(smu);
+ if (ret) {
+ pr_err("Failed to register smc irq handler!\n");
+ return ret;
+ }
+
return 0;
}
@@ -707,6 +745,9 @@ static int smu_sw_fini(void *handle)
struct smu_context *smu = &adev->smu;
int ret;
+ kfree(smu->irq_source);
+ smu->irq_source = NULL;
+
ret = smu_smc_table_sw_fini(smu);
if (ret) {
pr_err("Failed to sw fini smc table!\n");
@@ -1063,10 +1104,6 @@ static int smu_hw_init(void *handle)
if (ret)
goto failed;
- ret = smu_register_irq_handler(smu);
- if (ret)
- goto failed;
-
if (!smu->pm_enabled)
adev->pm.dpm_enabled = false;
else
@@ -1096,9 +1133,6 @@ static int smu_hw_fini(void *handle)
kfree(table_context->overdrive_table);
table_context->overdrive_table = NULL;
- kfree(smu->irq_source);
- smu->irq_source = NULL;
-
ret = smu_fini_fb_allocations(smu);
if (ret)
return ret;
@@ -1349,13 +1383,49 @@ static int smu_enable_umd_pstate(void *handle,
return 0;
}
+static int smu_default_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
+{
+ int ret = 0;
+ uint32_t sclk_mask, mclk_mask, soc_mask;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_HIGH:
+ ret = smu_force_dpm_limit_value(smu, true);
+ break;
+ case AMD_DPM_FORCED_LEVEL_LOW:
+ ret = smu_force_dpm_limit_value(smu, false);
+ break;
+ case AMD_DPM_FORCED_LEVEL_AUTO:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
+ ret = smu_unforce_dpm_levels(smu);
+ break;
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+ ret = smu_get_profiling_clk_mask(smu, level,
+ &sclk_mask,
+ &mclk_mask,
+ &soc_mask);
+ if (ret)
+ return ret;
+ smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
+ smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
+ smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
+ break;
+ case AMD_DPM_FORCED_LEVEL_MANUAL:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
+ default:
+ break;
+ }
+ return ret;
+}
+
int smu_adjust_power_state_dynamic(struct smu_context *smu,
enum amd_dpm_forced_level level,
bool skip_display_settings)
{
int ret = 0;
int index = 0;
- uint32_t sclk_mask, mclk_mask, soc_mask;
long workload;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
@@ -1386,39 +1456,10 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu,
}
if (smu_dpm_ctx->dpm_level != level) {
- switch (level) {
- case AMD_DPM_FORCED_LEVEL_HIGH:
- ret = smu_force_dpm_limit_value(smu, true);
- break;
- case AMD_DPM_FORCED_LEVEL_LOW:
- ret = smu_force_dpm_limit_value(smu, false);
- break;
-
- case AMD_DPM_FORCED_LEVEL_AUTO:
- case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
- ret = smu_unforce_dpm_levels(smu);
- break;
-
- case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
- case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
- case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- ret = smu_get_profiling_clk_mask(smu, level,
- &sclk_mask,
- &mclk_mask,
- &soc_mask);
- if (ret)
- return ret;
- smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
- smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
- smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
- break;
-
- case AMD_DPM_FORCED_LEVEL_MANUAL:
- case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
- default:
- break;
+ ret = smu_asic_set_performance_level(smu, level);
+ if (ret) {
+ ret = smu_default_set_performance_level(smu, level);
}
-
if (!ret)
smu_dpm_ctx->dpm_level = level;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index e32ae9d3373c..18e780f566fa 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -1111,6 +1111,7 @@ static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
void *value, int *size)
{
+ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
uint32_t sclk, mclk;
int ret = 0;
@@ -1132,6 +1133,10 @@ static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
case AMDGPU_PP_SENSOR_GPU_TEMP:
*((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr);
break;
+ case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
+ *(uint32_t *)value = smu10_data->vcn_power_gated ? 0 : 1;
+ *size = 4;
+ break;
default:
ret = -EINVAL;
break;
@@ -1175,18 +1180,22 @@ static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate)
static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate)
{
+ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
+
if (bgate) {
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCN,
AMD_PG_STATE_GATE);
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_PowerDownVcn, 0);
+ smu10_data->vcn_power_gated = true;
} else {
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_PowerUpVcn, 0);
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCN,
AMD_PG_STATE_UNGATE);
+ smu10_data->vcn_power_gated = false;
}
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index f27c6fbb192e..90c4e87ac5ad 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -2101,7 +2101,11 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
if (ret)
return ret;
- *query = metrics_table.CurrSocketPower << 8;
+ /* For the 40.46 release, they changed the value name */
+ if (hwmgr->smu_version == 0x282e00)
+ *query = metrics_table.AverageSocketPower << 8;
+ else
+ *query = metrics_table.CurrSocketPower << 8;
return ret;
}
@@ -2349,12 +2353,16 @@ static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
data->dpm_table.soc_table.dpm_state.soft_max_level =
data->dpm_table.soc_table.dpm_levels[soft_level].value;
- ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload boot level to highest!",
return ret);
- ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload dpm max level to highest!",
return ret);
@@ -2387,12 +2395,16 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
data->dpm_table.soc_table.dpm_state.soft_max_level =
data->dpm_table.soc_table.dpm_levels[soft_level].value;
- ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload boot level to highest!",
return ret);
- ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload dpm max level to highest!",
return ret);
@@ -2403,14 +2415,54 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
{
+ struct vega20_hwmgr *data =
+ (struct vega20_hwmgr *)(hwmgr->backend);
+ uint32_t soft_min_level, soft_max_level;
int ret = 0;
- ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+ /* gfxclk soft min/max settings */
+ soft_min_level =
+ vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
+ soft_max_level =
+ vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
+
+ data->dpm_table.gfx_table.dpm_state.soft_min_level =
+ data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
+ data->dpm_table.gfx_table.dpm_state.soft_max_level =
+ data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
+
+ /* uclk soft min/max settings */
+ soft_min_level =
+ vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
+ soft_max_level =
+ vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
+
+ data->dpm_table.mem_table.dpm_state.soft_min_level =
+ data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
+ data->dpm_table.mem_table.dpm_state.soft_max_level =
+ data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
+
+ /* socclk soft min/max settings */
+ soft_min_level =
+ vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
+ soft_max_level =
+ vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
+
+ data->dpm_table.soc_table.dpm_state.soft_min_level =
+ data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+ data->dpm_table.soc_table.dpm_state.soft_max_level =
+ data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+ ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload DPM Bootup Levels!",
return ret);
- ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+ FEATURE_DPM_UCLK_MASK |
+ FEATURE_DPM_SOCCLK_MASK);
PP_ASSERT_WITH_CODE(!ret,
"Failed to upload DPM Max Levels!",
return ret);
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index 1af992fb0bde..a78b2e295895 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -429,7 +429,6 @@ struct smu_table_context
struct smu_table *tables;
uint32_t table_count;
struct smu_table memory_pool;
- uint16_t software_shutdown_temp;
uint8_t thermal_controller_type;
uint16_t TDPODLimit;
@@ -452,6 +451,7 @@ struct smu_dpm_context {
struct smu_power_gate {
bool uvd_gated;
bool vce_gated;
+ bool vcn_gated;
};
struct smu_power_context {
@@ -613,6 +613,7 @@ struct pptable_funcs {
int (*tables_init)(struct smu_context *smu, struct smu_table *tables);
int (*set_thermal_fan_table)(struct smu_context *smu);
int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
+ int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
int (*set_watermarks_table)(struct smu_context *smu, void *watermarks,
struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
int (*get_current_clk_freq_by_table)(struct smu_context *smu,
@@ -621,6 +622,7 @@ struct pptable_funcs {
int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range);
int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states);
int (*set_default_od_settings)(struct smu_context *smu, bool initialize);
+ int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
};
struct smu_funcs
@@ -685,7 +687,6 @@ struct smu_funcs
int (*set_watermarks_for_clock_ranges)(struct smu_context *smu,
struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
int (*conv_power_profile_to_pplib_workload)(int power_profile);
- int (*get_current_rpm)(struct smu_context *smu, uint32_t *speed);
uint32_t (*get_fan_control_mode)(struct smu_context *smu);
int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
@@ -751,8 +752,6 @@ struct smu_funcs
((smu)->funcs->init_max_sustainable_clocks ? (smu)->funcs->init_max_sustainable_clocks((smu)) : 0)
#define smu_set_default_od_settings(smu, initialize) \
((smu)->ppt_funcs->set_default_od_settings ? (smu)->ppt_funcs->set_default_od_settings((smu), (initialize)) : 0)
-#define smu_get_current_rpm(smu, speed) \
- ((smu)->funcs->get_current_rpm ? (smu)->funcs->get_current_rpm((smu), (speed)) : 0)
#define smu_set_fan_speed_rpm(smu, speed) \
((smu)->funcs->set_fan_speed_rpm ? (smu)->funcs->set_fan_speed_rpm((smu), (speed)) : 0)
#define smu_send_smc_msg(smu, msg) \
@@ -841,6 +840,8 @@ struct smu_funcs
((smu)->ppt_funcs->get_fan_speed_percent ? (smu)->ppt_funcs->get_fan_speed_percent((smu), (speed)) : 0)
#define smu_set_fan_speed_percent(smu, speed) \
((smu)->funcs->set_fan_speed_percent ? (smu)->funcs->set_fan_speed_percent((smu), (speed)) : 0)
+#define smu_get_fan_speed_rpm(smu, speed) \
+ ((smu)->ppt_funcs->get_fan_speed_rpm ? (smu)->ppt_funcs->get_fan_speed_rpm((smu), (speed)) : 0)
#define smu_msg_get_index(smu, msg) \
((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_msg_index? (smu)->ppt_funcs->get_smu_msg_index((smu), (msg)) : -EINVAL) : -EINVAL)
@@ -906,8 +907,6 @@ struct smu_funcs
((smu)->funcs->register_irq_handler ? (smu)->funcs->register_irq_handler(smu) : 0)
#define smu_set_azalia_d3_pme(smu) \
((smu)->funcs->set_azalia_d3_pme ? (smu)->funcs->set_azalia_d3_pme((smu)) : 0)
-#define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
- ((smu)->ppt_funcs->get_uclk_dpm_states ? (smu)->ppt_funcs->get_uclk_dpm_states((smu), (clocks_in_khz), (num_states)) : 0)
#define smu_get_max_sustainable_clocks_by_dc(smu, max_clocks) \
((smu)->funcs->get_max_sustainable_clocks_by_dc ? (smu)->funcs->get_max_sustainable_clocks_by_dc((smu), (max_clocks)) : 0)
#define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
@@ -918,6 +917,9 @@ struct smu_funcs
((smu)->funcs->baco_get_state? (smu)->funcs->baco_get_state((smu), (state)) : 0)
#define smu_baco_reset(smu) \
((smu)->funcs->baco_reset? (smu)->funcs->baco_reset((smu)) : 0)
+#define smu_asic_set_performance_level(smu, level) \
+ ((smu)->ppt_funcs->set_performance_level? (smu)->ppt_funcs->set_performance_level((smu), (level)) : -EINVAL);
+
extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
uint16_t *size, uint8_t *frev, uint8_t *crev,
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index 2dae0ae0829e..b81c7e715dc9 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -23,6 +23,7 @@
#include "pp_debug.h"
#include <linux/firmware.h>
+#include <linux/pci.h>
#include "amdgpu.h"
#include "amdgpu_smu.h"
#include "atomfirmware.h"
@@ -501,6 +502,8 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
@@ -515,9 +518,35 @@ static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM);
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+ if (!smu_table->metrics_table)
+ return -ENOMEM;
+ smu_table->metrics_time = 0;
+
return 0;
}
+static int navi10_get_metrics_table(struct smu_context *smu,
+ SmuMetrics_t *metrics_table)
+{
+ struct smu_table_context *smu_table= &smu->smu_table;
+ int ret = 0;
+
+ if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
+ ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
+ (void *)smu_table->metrics_table, false);
+ if (ret) {
+ pr_info("Failed to export SMU metrics table!\n");
+ return ret;
+ }
+ smu_table->metrics_time = jiffies;
+ }
+
+ memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+
+ return ret;
+}
+
static int navi10_allocate_dpm_context(struct smu_context *smu)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
@@ -576,44 +605,38 @@ static int navi10_set_default_dpm_table(struct smu_context *smu)
static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
{
- int ret = 0;
struct smu_power_context *smu_power = &smu->smu_power;
struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int ret = 0;
- if (enable && power_gate->uvd_gated) {
- if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
+ if (enable) {
+ /* vcn dpm on is a prerequisite for vcn power gate messages */
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
if (ret)
return ret;
}
- power_gate->uvd_gated = false;
+ power_gate->vcn_gated = false;
} else {
- if (!enable && !power_gate->uvd_gated) {
- if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
- ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
- if (ret)
- return ret;
- }
- power_gate->uvd_gated = true;
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+ ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
+ if (ret)
+ return ret;
}
+ power_gate->vcn_gated = true;
}
- return 0;
+ return ret;
}
static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *value)
{
- static SmuMetrics_t metrics;
int ret = 0, clk_id = 0;
+ SmuMetrics_t metrics;
- if (!value)
- return -EINVAL;
-
- memset(&metrics, 0, sizeof(metrics));
-
- ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+ ret = navi10_get_metrics_table(smu, &metrics);
if (ret)
return ret;
@@ -626,11 +649,26 @@ static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
return ret;
}
+static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ DpmDescriptor_t *dpm_desc = NULL;
+ uint32_t clk_index = 0;
+
+ clk_index = smu_clk_get_index(smu, clk_type);
+ dpm_desc = &pptable->DpmDescriptor[clk_index];
+
+ /* 0 - Fine grained DPM, 1 - Discrete DPM */
+ return dpm_desc->SnapToDiscrete == 0 ? true : false;
+}
+
static int navi10_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
int i, size = 0, ret = 0;
uint32_t cur_value = 0, value = 0, count = 0;
+ uint32_t freq_values[3] = {0};
+ uint32_t mark_index = 0;
switch (clk_type) {
case SMU_GFXCLK:
@@ -643,22 +681,42 @@ static int navi10_print_clk_levels(struct smu_context *smu,
ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
if (ret)
return size;
+
/* 10KHz -> MHz */
cur_value = cur_value / 100;
- size += sprintf(buf, "current clk: %uMhz\n", cur_value);
-
ret = smu_get_dpm_level_count(smu, clk_type, &count);
if (ret)
return size;
- for (i = 0; i < count; i++) {
- ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
+ if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
+ for (i = 0; i < count; i++) {
+ ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
+ if (ret)
+ return size;
+
+ size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ cur_value == value ? "*" : "");
+ }
+ } else {
+ ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
if (ret)
return size;
+ ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
+ if (ret)
+ return size;
+
+ freq_values[1] = cur_value;
+ mark_index = cur_value == freq_values[0] ? 0 :
+ cur_value == freq_values[2] ? 2 : 1;
+ if (mark_index != 1)
+ freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
+
+ for (i = 0; i < 3; i++) {
+ size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
+ i == mark_index ? "*" : "");
+ }
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
- cur_value == value ? "*" : "");
}
break;
default:
@@ -866,8 +924,9 @@ static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
if (!value)
return -EINVAL;
- ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics,
- false);
+ ret = navi10_get_metrics_table(smu, &metrics);
+ if (ret)
+ return ret;
if (ret)
return ret;
@@ -886,10 +945,7 @@ static int navi10_get_current_activity_percent(struct smu_context *smu,
if (!value)
return -EINVAL;
- msleep(1);
-
- ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
- (void *)&metrics, false);
+ ret = navi10_get_metrics_table(smu, &metrics);
if (ret)
return ret;
@@ -919,22 +975,22 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static int navi10_get_fan_speed(struct smu_context *smu, uint16_t *value)
+static int navi10_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
{
SmuMetrics_t metrics;
int ret = 0;
- if (!value)
+ if (!speed)
return -EINVAL;
- memset(&metrics, 0, sizeof(metrics));
-
- ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
- (void *)&metrics, false);
+ ret = navi10_get_metrics_table(smu, &metrics);
+ if (ret)
+ return ret;
if (ret)
return ret;
- *value = metrics.CurrFanSpeed;
+ *speed = metrics.CurrFanSpeed;
return ret;
}
@@ -944,10 +1000,10 @@ static int navi10_get_fan_speed_percent(struct smu_context *smu,
{
int ret = 0;
uint32_t percent = 0;
- uint16_t current_rpm;
+ uint32_t current_rpm;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- ret = navi10_get_fan_speed(smu, &current_rpm);
+ ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
if (ret)
return ret;
@@ -1278,7 +1334,7 @@ static int navi10_thermal_get_temperature(struct smu_context *smu,
if (!value)
return -EINVAL;
- ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+ ret = navi10_get_metrics_table(smu, &metrics);
if (ret)
return ret;
@@ -1530,6 +1586,76 @@ static int navi10_set_ppfeature_status(struct smu_context *smu,
return 0;
}
+static int navi10_set_peak_clock_by_device(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+ uint32_t sclk_freq = 0, uclk_freq = 0;
+ uint32_t uclk_level = 0;
+
+ switch (adev->pdev->revision) {
+ case 0xf0: /* XTX */
+ case 0xc0:
+ sclk_freq = NAVI10_PEAK_SCLK_XTX;
+ break;
+ case 0xf1: /* XT */
+ case 0xc1:
+ sclk_freq = NAVI10_PEAK_SCLK_XT;
+ break;
+ default: /* XL */
+ sclk_freq = NAVI10_PEAK_SCLK_XL;
+ break;
+ }
+
+ ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
+ if (ret)
+ return ret;
+ ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
+ if (ret)
+ return ret;
+
+ ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
+ if (ret)
+ return ret;
+ ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
+{
+ int ret = 0;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+ ret = navi10_set_peak_clock_by_device(smu);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int navi10_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
+
+ if (!range || !powerplay_table)
+ return -EINVAL;
+
+ /* The unit is temperature */
+ range->min = 0;
+ range->max = powerplay_table->software_shutdown_temp;
+
+ return 0;
+}
+
static const struct pptable_funcs navi10_ppt_funcs = {
.tables_init = navi10_tables_init,
.alloc_dpm_context = navi10_allocate_dpm_context,
@@ -1557,6 +1683,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.unforce_dpm_levels = navi10_unforce_dpm_levels,
.is_dpm_running = navi10_is_dpm_running,
.get_fan_speed_percent = navi10_get_fan_speed_percent,
+ .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
.get_power_profile_mode = navi10_get_power_profile_mode,
.set_power_profile_mode = navi10_set_power_profile_mode,
.get_profiling_clk_mask = navi10_get_profiling_clk_mask,
@@ -1565,6 +1692,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.get_uclk_dpm_states = navi10_get_uclk_dpm_states,
.get_ppfeature_status = navi10_get_ppfeature_status,
.set_ppfeature_status = navi10_set_ppfeature_status,
+ .set_performance_level = navi10_set_performance_level,
+ .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
};
void navi10_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h
index 957288e22f47..620ff17c2fef 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h
@@ -23,6 +23,10 @@
#ifndef __NAVI10_PPT_H__
#define __NAVI10_PPT_H__
+#define NAVI10_PEAK_SCLK_XTX (1830)
+#define NAVI10_PEAK_SCLK_XT (1755)
+#define NAVI10_PEAK_SCLK_XL (1625)
+
extern void navi10_set_ppt_funcs(struct smu_context *smu);
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 95c7c4dae523..53097961bf2b 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -326,7 +326,8 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
const struct smc_firmware_header_v1_0 *hdr;
int ret, index;
- uint32_t size;
+ uint32_t size = 0;
+ uint16_t atom_table_size;
uint8_t frev, crev;
void *table;
uint16_t version_major, version_minor;
@@ -354,10 +355,11 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
powerplayinfo);
- ret = smu_get_atom_data_table(smu, index, (uint16_t *)&size, &frev, &crev,
+ ret = smu_get_atom_data_table(smu, index, &atom_table_size, &frev, &crev,
(uint8_t **)&table);
if (ret)
return ret;
+ size = atom_table_size;
}
if (!smu->smu_table.power_play_table)
@@ -1124,10 +1126,8 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
struct smu_temperature_range *range)
{
struct amdgpu_device *adev = smu->adev;
- int low = SMU_THERMAL_MINIMUM_ALERT_TEMP *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
+ int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
uint32_t val;
if (!range)
@@ -1138,6 +1138,9 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
if (high > range->max)
high = range->max;
+ low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, range->min);
+ high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, range->max);
+
if (low > high)
return -EINVAL;
@@ -1146,8 +1149,8 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0);
- val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES));
- val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES));
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff));
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
@@ -1186,7 +1189,10 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
if (!smu->pm_enabled)
return ret;
+
ret = smu_get_thermal_temperature_range(smu, &range);
+ if (ret)
+ return ret;
if (smu->smu_table.thermal_controller_type) {
ret = smu_v11_0_set_thermal_range(smu, &range);
@@ -1202,15 +1208,17 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
return ret;
}
- adev->pm.dpm.thermal.min_temp = range.min;
- adev->pm.dpm.thermal.max_temp = range.max;
- adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max;
- adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min;
- adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max;
- adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max;
- adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
- adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
- adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
+ adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.min_mem_temp = range.mem_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
return ret;
}
@@ -1371,23 +1379,6 @@ static int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
return ret;
}
-static int smu_v11_0_get_current_rpm(struct smu_context *smu,
- uint32_t *current_rpm)
-{
- int ret;
-
- ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
-
- if (ret) {
- pr_err("Attempt to get current RPM from SMC Failed!\n");
- return ret;
- }
-
- smu_read_smc_arg(smu, current_rpm);
-
- return 0;
-}
-
static uint32_t
smu_v11_0_get_fan_control_mode(struct smu_context *smu)
{
@@ -1402,7 +1393,7 @@ smu_v11_0_smc_fan_control(struct smu_context *smu, bool start)
{
int ret = 0;
- if (smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
+ if (!smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
return 0;
ret = smu_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, start);
@@ -1773,7 +1764,6 @@ static const struct smu_funcs smu_v11_0_funcs = {
.set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
.set_watermarks_for_clock_ranges = smu_v11_0_set_watermarks_for_clock_ranges,
- .get_current_rpm = smu_v11_0_get_current_rpm,
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
.set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
index bb9bb09cfc7a..6a14497257e4 100644
--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
@@ -450,7 +450,6 @@ static int vega20_store_powerplay_table(struct smu_context *smu)
memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
sizeof(PPTable_t));
- table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
@@ -3015,6 +3014,23 @@ static int vega20_set_thermal_fan_table(struct smu_context *smu)
return ret;
}
+static int vega20_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ int ret;
+
+ ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
+
+ if (ret) {
+ pr_err("Attempt to get current RPM from SMC Failed!\n");
+ return ret;
+ }
+
+ smu_read_smc_arg(smu, speed);
+
+ return 0;
+}
+
static int vega20_get_fan_speed_percent(struct smu_context *smu,
uint32_t *speed)
{
@@ -3022,7 +3038,7 @@ static int vega20_get_fan_speed_percent(struct smu_context *smu,
uint32_t current_rpm = 0, percent = 0;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- ret = smu_get_current_rpm(smu, &current_rpm);
+ ret = vega20_get_fan_speed_rpm(smu, &current_rpm);
if (ret)
return ret;
@@ -3034,6 +3050,7 @@ static int vega20_get_fan_speed_percent(struct smu_context *smu,
static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
{
+ uint32_t smu_version;
int ret = 0;
SmuMetrics_t metrics;
@@ -3044,7 +3061,15 @@ static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
if (ret)
return ret;
- *value = metrics.CurrSocketPower << 8;
+ ret = smu_get_smc_version(smu, NULL, &smu_version);
+ if (ret)
+ return ret;
+
+ /* For the 40.46 release, they changed the value name */
+ if (smu_version == 0x282e00)
+ *value = metrics.AverageSocketPower << 8;
+ else
+ *value = metrics.CurrSocketPower << 8;
return 0;
}
@@ -3217,35 +3242,24 @@ static int vega20_set_watermarks_table(struct smu_context *smu,
return 0;
}
-static const struct smu_temperature_range vega20_thermal_policy[] =
-{
- {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
- { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
-};
-
static int vega20_get_thermal_temperature_range(struct smu_context *smu,
struct smu_temperature_range *range)
{
-
+ struct smu_table_context *table_context = &smu->smu_table;
+ ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- if (!range)
+ if (!range || !powerplay_table)
return -EINVAL;
- memcpy(range, &vega20_thermal_policy[0], sizeof(struct smu_temperature_range));
-
- range->max = pptable->TedgeLimit *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- range->hotspot_crit_max = pptable->ThotspotLimit *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- range->mem_crit_max = pptable->ThbmLimit *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM)*
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ /* The unit is temperature */
+ range->min = 0;
+ range->max = powerplay_table->usSoftwareShutdownTemp;
+ range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE);
+ range->hotspot_crit_max = pptable->ThotspotLimit;
+ range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT);
+ range->mem_crit_max = pptable->ThbmLimit;
+ range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM);
return 0;
@@ -3293,6 +3307,7 @@ static const struct pptable_funcs vega20_ppt_funcs = {
.is_dpm_running = vega20_is_dpm_running,
.set_thermal_fan_table = vega20_set_thermal_fan_table,
.get_fan_speed_percent = vega20_get_fan_speed_percent,
+ .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
.set_watermarks_table = vega20_set_watermarks_table,
.get_thermal_temperature_range = vega20_get_thermal_temperature_range
};
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index 5a118984de33..9d4d5075cc64 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -8,6 +8,7 @@
#include <linux/iommu.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#ifdef CONFIG_DEBUG_FS
@@ -126,7 +127,7 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np)
pipe->of_output_port =
of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
- pipe->of_node = np;
+ pipe->of_node = of_node_get(np);
return 0;
}
@@ -143,6 +144,12 @@ static int komeda_parse_dt(struct device *dev, struct komeda_dev *mdev)
return mdev->irq;
}
+ /* Get the optional framebuffer memory resource */
+ ret = of_reserved_mem_device_init(dev);
+ if (ret && ret != -ENODEV)
+ return ret;
+ ret = 0;
+
for_each_available_child_of_node(np, child) {
if (of_node_cmp(child->name, "pipeline") == 0) {
ret = komeda_parse_pipe_dt(mdev, child);
@@ -289,6 +296,8 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
mdev->n_pipelines = 0;
+ of_reserved_mem_device_release(dev);
+
if (funcs && funcs->cleanup)
funcs->cleanup(mdev);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c
index cd4d9f53ddef..c9a1edb9a000 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c
@@ -35,6 +35,25 @@ komeda_get_format_caps(struct komeda_format_caps_table *table,
return NULL;
}
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info, u64 modifier)
+{
+ u32 bpp;
+
+ switch (info->format) {
+ case DRM_FORMAT_YUV420_8BIT:
+ bpp = 12;
+ break;
+ case DRM_FORMAT_YUV420_10BIT:
+ bpp = 15;
+ break;
+ default:
+ bpp = info->cpp[0] * 8;
+ break;
+ }
+
+ return bpp;
+}
+
/* Two assumptions
* 1. RGB always has YTR
* 2. Tiled RGB always has SC
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
index 3631910d33b5..32273cf18f7c 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
@@ -97,6 +97,9 @@ const struct komeda_format_caps *
komeda_get_format_caps(struct komeda_format_caps_table *table,
u32 fourcc, u64 modifier);
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info,
+ u64 modifier);
+
u32 *komeda_get_layer_fourcc_list(struct komeda_format_caps_table *table,
u32 layer_type, u32 *n_fmts);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
index 3b0a70ed6aa0..1b01a625f40e 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
@@ -43,7 +43,7 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
struct drm_framebuffer *fb = &kfb->base;
const struct drm_format_info *info = fb->format;
struct drm_gem_object *obj;
- u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks;
+ u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks, bpp;
u64 min_size;
obj = drm_gem_object_lookup(file, mode_cmd->handles[0]);
@@ -88,8 +88,9 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE,
alignment_header);
+ bpp = komeda_get_afbc_format_bpp(info, fb->modifier);
kfb->afbc_size = kfb->offset_payload + n_blocks *
- ALIGN(info->cpp[0] * AFBC_SUPERBLK_PIXELS,
+ ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8,
AFBC_SUPERBLK_ALIGNMENT);
min_size = kfb->afbc_size + fb->offsets[0];
if (min_size > obj->size) {
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 419a8b0e5de8..69d9e26c60c8 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -14,6 +14,7 @@
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_irq.h>
+#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
#include "komeda_dev.h"
@@ -146,7 +147,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc_st);
struct komeda_plane_state *kplane_st;
struct drm_plane_state *plane_st;
- struct drm_framebuffer *fb;
struct drm_plane *plane;
struct list_head zorder_list;
int order = 0, err;
@@ -172,7 +172,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
list_for_each_entry(kplane_st, &zorder_list, zlist_node) {
plane_st = &kplane_st->base;
- fb = plane_st->fb;
plane = plane_st->plane;
plane_st->normalized_zpos = order++;
@@ -205,7 +204,7 @@ static int komeda_kms_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct drm_crtc *crtc;
- struct drm_crtc_state *old_crtc_st, *new_crtc_st;
+ struct drm_crtc_state *new_crtc_st;
int i, err;
err = drm_atomic_helper_check_modeset(dev, state);
@@ -216,7 +215,7 @@ static int komeda_kms_check(struct drm_device *dev,
* so need to add all affected_planes (even unchanged) to
* drm_atomic_state.
*/
- for_each_oldnew_crtc_in_state(state, crtc, old_crtc_st, new_crtc_st, i) {
+ for_each_new_crtc_in_state(state, crtc, new_crtc_st, i) {
err = drm_atomic_add_affected_planes(state, crtc);
if (err)
return err;
@@ -307,24 +306,33 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
komeda_kms_irq_handler, IRQF_SHARED,
drm->driver->name, drm);
if (err)
- goto cleanup_mode_config;
+ goto free_component_binding;
err = mdev->funcs->enable_irq(mdev);
if (err)
- goto cleanup_mode_config;
+ goto free_component_binding;
drm->irq_enabled = true;
+ drm_kms_helper_poll_init(drm);
+
err = drm_dev_register(drm, 0);
if (err)
- goto cleanup_mode_config;
+ goto free_interrupts;
return kms;
-cleanup_mode_config:
+free_interrupts:
+ drm_kms_helper_poll_fini(drm);
drm->irq_enabled = false;
+ mdev->funcs->disable_irq(mdev);
+free_component_binding:
+ component_unbind_all(mdev->dev, drm);
+cleanup_mode_config:
drm_mode_config_cleanup(drm);
komeda_kms_cleanup_private_objs(kms);
+ drm->dev_private = NULL;
+ drm_dev_put(drm);
free_kms:
kfree(kms);
return ERR_PTR(err);
@@ -335,12 +343,14 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
struct drm_device *drm = &kms->base;
struct komeda_dev *mdev = drm->dev_private;
+ drm_dev_unregister(drm);
+ drm_kms_helper_poll_fini(drm);
+ drm_atomic_helper_shutdown(drm);
drm->irq_enabled = false;
mdev->funcs->disable_irq(mdev);
- drm_dev_unregister(drm);
component_unbind_all(mdev->dev, drm);
- komeda_kms_cleanup_private_objs(kms);
drm_mode_config_cleanup(drm);
+ komeda_kms_cleanup_private_objs(kms);
drm->dev_private = NULL;
drm_dev_put(drm);
}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index a90bcbb3cb23..14b683164544 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -480,6 +480,7 @@ void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
struct seq_file *sf);
/* component APIs */
+extern __printf(10, 11)
struct komeda_component *
komeda_component_add(struct komeda_pipeline *pipe,
size_t comp_sz, u32 id, u32 hw_id,
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
index 617e1f7b8472..2851cac94d86 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -148,7 +148,7 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms,
if (!kcrtc->master->wb_layer)
return 0;
- kwb_conn = kzalloc(sizeof(*wb_conn), GFP_KERNEL);
+ kwb_conn = kzalloc(sizeof(*kwb_conn), GFP_KERNEL);
if (!kwb_conn)
return -ENOMEM;
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 4c7e31cb45ff..a5d1494a3dc4 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -131,8 +131,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
/* Enable extended register access */
- ast_enable_mmio(dev);
ast_open_key(ast);
+ ast_enable_mmio(dev);
/* Find out whether P2A works or whether to use device-tree */
ast_detect_config_mode(dev, &scu_rev);
@@ -576,6 +576,9 @@ void ast_driver_unload(struct drm_device *dev)
{
struct ast_private *ast = dev->dev_private;
+ /* enable standard VGA decode */
+ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
+
ast_release_firmware(dev);
kfree(ast->dp501_fw_addr);
ast_mode_fini(dev);
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index ffccbef962a4..a1cb020e07e5 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -604,7 +604,7 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc,
return -EINVAL;
ast_open_key(ast);
- ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
ast_set_std_reg(crtc, adjusted_mode, &vbios_mode);
ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode);
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index f7d421359d56..c1d1ac51d1c2 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -46,7 +46,7 @@ void ast_enable_mmio(struct drm_device *dev)
{
struct ast_private *ast = dev->dev_private;
- ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index bc19dbd531ef..359030d5d818 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -191,6 +191,7 @@ int bochs_kms_init(struct bochs_device *bochs)
bochs->dev->mode_config.fb_base = bochs->fb_base;
bochs->dev->mode_config.preferred_depth = 24;
bochs->dev->mode_config.prefer_shadow = 0;
+ bochs->dev->mode_config.prefer_shadow_fbdev = 1;
bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
bochs->dev->mode_config.funcs = &bochs_mode_funcs;
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index ee777469293a..e4e22bbae2a7 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -48,6 +48,7 @@ config DRM_DUMB_VGA_DAC
config DRM_LVDS_ENCODER
tristate "Transparent parallel to LVDS encoder support"
depends on OF
+ select DRM_KMS_HELPER
select DRM_PANEL_BRIDGE
help
Support for transparent parallel to LVDS encoders that don't require
@@ -116,9 +117,10 @@ config DRM_THINE_THC63LVD1024
config DRM_TOSHIBA_TC358764
tristate "TC358764 DSI/LVDS bridge"
- depends on DRM && DRM_PANEL
depends on OF
select DRM_MIPI_DSI
+ select DRM_KMS_HELPER
+ select DRM_PANEL
help
Toshiba TC358764 DSI/LVDS bridge driver.
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 410572f14257..e1dafb0cc5e2 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -254,7 +254,6 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
struct drm_device *dev = client->dev;
struct drm_client_buffer *buffer;
struct drm_gem_object *obj;
- void *vaddr;
int ret;
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
@@ -281,6 +280,36 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
buffer->gem = obj;
+ return buffer;
+
+err_delete:
+ drm_client_buffer_delete(buffer);
+
+ return ERR_PTR(ret);
+}
+
+/**
+ * drm_client_buffer_vmap - Map DRM client buffer into address space
+ * @buffer: DRM client buffer
+ *
+ * This function maps a client buffer into kernel address space. If the
+ * buffer is already mapped, it returns the mapping's address.
+ *
+ * Client buffer mappings are not ref'counted. Each call to
+ * drm_client_buffer_vmap() should be followed by a call to
+ * drm_client_buffer_vunmap(); or the client buffer should be mapped
+ * throughout its lifetime.
+ *
+ * Returns:
+ * The mapped memory's address
+ */
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer)
+{
+ void *vaddr;
+
+ if (buffer->vaddr)
+ return buffer->vaddr;
+
/*
* FIXME: The dependency on GEM here isn't required, we could
* convert the driver handle to a dma-buf instead and use the
@@ -289,21 +318,30 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
* fd_install step out of the driver backend hooks, to make that
* final step optional for internal users.
*/
- vaddr = drm_gem_vmap(obj);
- if (IS_ERR(vaddr)) {
- ret = PTR_ERR(vaddr);
- goto err_delete;
- }
+ vaddr = drm_gem_vmap(buffer->gem);
+ if (IS_ERR(vaddr))
+ return vaddr;
buffer->vaddr = vaddr;
- return buffer;
-
-err_delete:
- drm_client_buffer_delete(buffer);
+ return vaddr;
+}
+EXPORT_SYMBOL(drm_client_buffer_vmap);
- return ERR_PTR(ret);
+/**
+ * drm_client_buffer_vunmap - Unmap DRM client buffer
+ * @buffer: DRM client buffer
+ *
+ * This function removes a client buffer's memory mapping. Calling this
+ * function is only required by clients that manage their buffer mappings
+ * by themselves.
+ */
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
+{
+ drm_gem_vunmap(buffer->gem, buffer->vaddr);
+ buffer->vaddr = NULL;
}
+EXPORT_SYMBOL(drm_client_buffer_vunmap);
static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
{
diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 56d36779d213..c8922b7cac09 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -859,7 +859,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
* simple XOR between the two handle the addition nicely.
*/
cmdline = &connector->cmdline_mode;
- if (cmdline->specified) {
+ if (cmdline->specified && cmdline->rotation_reflection) {
unsigned int cmdline_rest, panel_rest;
unsigned int cmdline_rot, panel_rot;
unsigned int sum_rot, sum_rest;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 1984e5c54d58..a7ba5b4902d6 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -403,6 +403,7 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
struct drm_clip_rect *clip = &helper->dirty_clip;
struct drm_clip_rect clip_copy;
unsigned long flags;
+ void *vaddr;
spin_lock_irqsave(&helper->dirty_lock, flags);
clip_copy = *clip;
@@ -412,10 +413,20 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
/* call dirty callback only when it has been really touched */
if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) {
+
/* Generic fbdev uses a shadow buffer */
- if (helper->buffer)
+ if (helper->buffer) {
+ vaddr = drm_client_buffer_vmap(helper->buffer);
+ if (IS_ERR(vaddr))
+ return;
drm_fb_helper_dirty_blit_real(helper, &clip_copy);
- helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+ }
+ if (helper->fb->funcs->dirty)
+ helper->fb->funcs->dirty(helper->fb, NULL, 0, 0,
+ &clip_copy, 1);
+
+ if (helper->buffer)
+ drm_client_buffer_vunmap(helper->buffer);
}
}
@@ -604,6 +615,16 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
}
EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
+static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
+{
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_framebuffer *fb = fb_helper->fb;
+
+ return dev->mode_config.prefer_shadow_fbdev ||
+ dev->mode_config.prefer_shadow ||
+ fb->funcs->dirty;
+}
+
static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
u32 width, u32 height)
{
@@ -611,7 +632,7 @@ static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
struct drm_clip_rect *clip = &helper->dirty_clip;
unsigned long flags;
- if (!helper->fb->funcs->dirty)
+ if (!drm_fbdev_use_shadow_fb(helper))
return;
spin_lock_irqsave(&helper->dirty_lock, flags);
@@ -2178,6 +2199,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
struct drm_framebuffer *fb;
struct fb_info *fbi;
u32 format;
+ void *vaddr;
DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
sizes->surface_width, sizes->surface_height,
@@ -2200,16 +2222,10 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
fbi->fbops = &drm_fbdev_fb_ops;
fbi->screen_size = fb->height * fb->pitches[0];
fbi->fix.smem_len = fbi->screen_size;
- fbi->screen_buffer = buffer->vaddr;
- /* Shamelessly leak the physical address to user-space */
-#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
- if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
- fbi->fix.smem_start =
- page_to_phys(virt_to_page(fbi->screen_buffer));
-#endif
+
drm_fb_helper_fill_info(fbi, fb_helper, sizes);
- if (fb->funcs->dirty) {
+ if (drm_fbdev_use_shadow_fb(fb_helper)) {
struct fb_ops *fbops;
void *shadow;
@@ -2231,6 +2247,19 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
fbi->fbdefio = &drm_fbdev_defio;
fb_deferred_io_init(fbi);
+ } else {
+ /* buffer is mapped for HW framebuffer */
+ vaddr = drm_client_buffer_vmap(fb_helper->buffer);
+ if (IS_ERR(vaddr))
+ return PTR_ERR(vaddr);
+
+ fbi->screen_buffer = vaddr;
+ /* Shamelessly leak the physical address to user-space */
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
+ if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
+ fbi->fix.smem_start =
+ page_to_phys(virt_to_page(fbi->screen_buffer));
+#endif
}
return 0;
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 0b72468e8131..57564318ceea 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -835,7 +835,7 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
struct drm_device *dev = fb->dev;
struct drm_atomic_state *state;
struct drm_plane *plane;
- struct drm_connector *conn;
+ struct drm_connector *conn __maybe_unused;
struct drm_connector_state *conn_state;
int i, ret;
unsigned plane_mask;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 74a5739df506..c814bcef18a4 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1454,6 +1454,7 @@ static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
}
static int drm_mode_parse_cmdline_extra(const char *str, int length,
+ bool freestanding,
const struct drm_connector *connector,
struct drm_cmdline_mode *mode)
{
@@ -1462,9 +1463,15 @@ static int drm_mode_parse_cmdline_extra(const char *str, int length,
for (i = 0; i < length; i++) {
switch (str[i]) {
case 'i':
+ if (freestanding)
+ return -EINVAL;
+
mode->interlace = true;
break;
case 'm':
+ if (freestanding)
+ return -EINVAL;
+
mode->margins = true;
break;
case 'D':
@@ -1542,6 +1549,7 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
if (extras) {
int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
1,
+ false,
connector,
mode);
if (ret)
@@ -1669,6 +1677,22 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
return 0;
}
+static const char * const drm_named_modes_whitelist[] = {
+ "NTSC",
+ "PAL",
+};
+
+static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
+ if (!strncmp(mode, drm_named_modes_whitelist[i], size))
+ return true;
+
+ return false;
+}
+
/**
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
* @mode_option: optional per connector mode option
@@ -1686,7 +1710,7 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
*
* Additionals options can be provided following the mode, using a comma to
* separate each option. Valid options can be found in
- * Documentation/fb/modedb.txt.
+ * Documentation/fb/modedb.rst.
*
* The intermediate drm_cmdline_mode structure is required to store additional
* options from the command line modline like the force-enable/disable flag.
@@ -1725,16 +1749,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
* bunch of things:
* - We need to make sure that the first character (which
* would be our resolution in X) is a digit.
- * - However, if the X resolution is missing, then we end up
- * with something like x<yres>, with our first character
- * being an alpha-numerical character, which would be
- * considered a named mode.
+ * - If not, then it's either a named mode or a force on/off.
+ * To distinguish between the two, we need to run the
+ * extra parsing function, and if not, then we consider it
+ * a named mode.
*
* If this isn't enough, we should add more heuristics here,
* and matching unit-tests.
*/
- if (!isdigit(name[0]) && name[0] != 'x')
+ if (!isdigit(name[0]) && name[0] != 'x') {
+ unsigned int namelen = strlen(name);
+
+ /*
+ * Only the force on/off options can be in that case,
+ * and they all take a single character.
+ */
+ if (namelen == 1) {
+ ret = drm_mode_parse_cmdline_extra(name, namelen, true,
+ connector, mode);
+ if (!ret)
+ return true;
+ }
+
named_mode = true;
+ }
/* Try to locate the bpp and refresh specifiers, if any */
bpp_ptr = strchr(name, '-');
@@ -1770,7 +1808,13 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
}
if (named_mode) {
- strncpy(mode->name, name, mode_end);
+ if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
+ return false;
+
+ if (!drm_named_mode_is_in_whitelist(name, mode_end))
+ return false;
+
+ strscpy(mode->name, name, mode_end + 1);
} else {
ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
parse_extras,
@@ -1809,7 +1853,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
extra_ptr != options_ptr) {
int len = strlen(name) - (extra_ptr - name);
- ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
+ ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
connector, mode);
if (ret)
return false;
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 60ce4a8ad9e1..6f7d3b3b3628 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -2,6 +2,7 @@
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST)
+ depends on MMU
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
select SND_SOC_HDMI_CODEC if SND_SOC
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index a594ab7be2c0..164d914cbe9a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -44,7 +44,7 @@ static unsigned int fimc_mask = 0xc;
module_param_named(fimc_devs, fimc_mask, uint, 0644);
MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM");
-#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
+#define get_fimc_context(dev) dev_get_drvdata(dev)
enum {
FIMC_CLK_LCLK,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 50904eee96f7..2a3382d43bc9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -267,7 +267,7 @@ static inline void g2d_hw_reset(struct g2d_data *g2d)
static int g2d_init_cmdlist(struct g2d_data *g2d)
{
struct device *dev = g2d->dev;
- struct g2d_cmdlist_node *node = g2d->cmdlist_node;
+ struct g2d_cmdlist_node *node;
int nr;
int ret;
struct g2d_buf_info *buf_info;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 1e4b21c49a06..1c524db9570f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -58,7 +58,7 @@
#define GSC_COEF_DEPTH 3
#define GSC_AUTOSUSPEND_DELAY 2000
-#define get_gsc_context(dev) platform_get_drvdata(to_platform_device(dev))
+#define get_gsc_context(dev) dev_get_drvdata(dev)
#define gsc_read(offset) readl(ctx->regs + (offset))
#define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index 9af096479e1c..b24ba948b725 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -94,12 +94,12 @@ static inline int scaler_reset(struct scaler_context *scaler)
scaler_write(SCALER_CFG_SOFT_RESET, SCALER_CFG);
do {
cpu_relax();
- } while (retry > 1 &&
+ } while (--retry > 1 &&
scaler_read(SCALER_CFG) & SCALER_CFG_SOFT_RESET);
do {
cpu_relax();
scaler_write(1, SCALER_INT_EN);
- } while (retry > 0 && scaler_read(SCALER_INT_EN) != 1);
+ } while (--retry > 0 && scaler_read(SCALER_INT_EN) != 1);
return retry ? 0 : -EIO;
}
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 91355c2ea8a5..8cace65f50ce 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -16,7 +16,6 @@ subdir-ccflags-y := -Wall -Wextra
subdir-ccflags-y += $(call cc-disable-warning, unused-parameter)
subdir-ccflags-y += $(call cc-disable-warning, type-limits)
subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers)
-subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough)
subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
# clang warnings
subdir-ccflags-y += $(call cc-disable-warning, sign-compare)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index c4710889cb32..3ef4e9f573cf 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -765,7 +765,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
}
if (bdb->version >= 226) {
- u32 wakeup_time = psr_table->psr2_tp2_tp3_wakeup_time;
+ u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
switch (wakeup_time) {
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index 753ac3165061..7b908e10d32e 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -178,6 +178,8 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv)
clpchgroup = (sa->deburst * deinterleave / num_channels) << i;
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
+ bi->num_qgv_points = qi.num_points;
+
for (j = 0; j < qi.num_points; j++) {
const struct intel_qgv_point *sp = &qi.points[j];
int ct, bw;
@@ -195,7 +197,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv)
bi->deratedbw[j] = min(maxdebw,
bw * 9 / 10); /* 90% */
- DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%d\n",
+ DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
i, j, bi->num_planes, bi->deratedbw[j]);
}
@@ -211,14 +213,17 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
{
int i;
- /* Did we initialize the bw limits successfully? */
- if (dev_priv->max_bw[0].num_planes == 0)
- return UINT_MAX;
-
for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
const struct intel_bw_info *bi =
&dev_priv->max_bw[i];
+ /*
+ * Pcode will not expose all QGV points when
+ * SAGV is forced to off/min/med/max.
+ */
+ if (qgv_point >= bi->num_qgv_points)
+ return UINT_MAX;
+
if (num_planes >= bi->num_planes)
return bi->deratedbw[qgv_point];
}
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 8993ab283562..0d19bbd08122 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2240,6 +2240,17 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
min_cdclk = max(2 * 96000, min_cdclk);
/*
+ * "For DP audio configuration, cdclk frequency shall be set to
+ * meet the following requirements:
+ * DP Link Frequency(MHz) | Cdclk frequency(MHz)
+ * 270 | 320 or higher
+ * 162 | 200 or higher"
+ */
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio)
+ min_cdclk = max(crtc_state->port_clock, min_cdclk);
+
+ /*
* On Valleyview some DSI panels lose (v|h)sync when the clock is lower
* than 320000KHz.
*/
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 7925a176f900..1cb1fa74cfbc 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -1465,8 +1465,8 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
else if (intel_crtc_has_dp_encoder(pipe_config))
dotclock = intel_dotclock_calculate(pipe_config->port_clock,
&pipe_config->dp_m_n);
- else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp == 36)
- dotclock = pipe_config->port_clock * 2 / 3;
+ else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp > 24)
+ dotclock = pipe_config->port_clock * 24 / pipe_config->pipe_bpp;
else
dotclock = pipe_config->port_clock;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 8592a7d422de..592b92782fab 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1839,7 +1839,7 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
/* FIXME: assert CPU port conditions for SNB+ */
}
- trace_intel_pipe_enable(dev_priv, pipe);
+ trace_intel_pipe_enable(crtc);
reg = PIPECONF(cpu_transcoder);
val = I915_READ(reg);
@@ -1880,7 +1880,7 @@ static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
*/
assert_planes_disabled(crtc);
- trace_intel_pipe_disable(dev_priv, pipe);
+ trace_intel_pipe_disable(crtc);
reg = PIPECONF(cpu_transcoder);
val = I915_READ(reg);
@@ -12042,7 +12042,7 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)
case INTEL_OUTPUT_DDI:
if (WARN_ON(!HAS_DDI(to_i915(dev))))
break;
- /* else: fall through */
+ /* else, fall through */
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_HDMI:
case INTEL_OUTPUT_EDP:
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index c93ad512014c..2d1939db108f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -438,16 +438,23 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
#define ICL_AUX_PW_TO_CH(pw_idx) \
((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
+#define ICL_TBT_AUX_PW_TO_CH(pw_idx) \
+ ((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
+
static void
icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum aux_ch aux_ch = ICL_AUX_PW_TO_CH(power_well->desc->hsw.idx);
+ int pw_idx = power_well->desc->hsw.idx;
+ bool is_tbt = power_well->desc->hsw.is_tc_tbt;
+ enum aux_ch aux_ch;
u32 val;
+ aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
+ ICL_AUX_PW_TO_CH(pw_idx);
val = I915_READ(DP_AUX_CH_CTL(aux_ch));
val &= ~DP_AUX_CH_CTL_TBT_IO;
- if (power_well->desc->hsw.is_tc_tbt)
+ if (is_tbt)
val |= DP_AUX_CH_CTL_TBT_IO;
I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 4336df46fe78..d0fc34826771 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -231,6 +231,7 @@ static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
switch (lane_info) {
default:
MISSING_CASE(lane_info);
+ /* fall through */
case 1:
case 2:
case 4:
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 60652ebbdf61..8aa6a31e8ad0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -128,7 +128,15 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
limits.min_bpp = intel_dp_min_bpp(pipe_config);
- limits.max_bpp = pipe_config->pipe_bpp;
+ /*
+ * FIXME: If all the streams can't fit into the link with
+ * their current pipe_bpp we should reduce pipe_bpp across
+ * the board until things start to fit. Until then we
+ * limit to <= 8bpc since that's what was hardcoded for all
+ * MST streams previously. This hack should be removed once
+ * we have the proper retry logic in place.
+ */
+ limits.max_bpp = min(pipe_config->pipe_bpp, 24);
intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
@@ -539,7 +547,15 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
- drm_connector_attach_max_bpc_property(connector, 6, 12);
+
+ /*
+ * Reuse the prop from the SST connector because we're
+ * not allowed to create new props after device registration.
+ */
+ connector->max_bpc_property =
+ intel_dp->attached_connector->base.max_bpc_property;
+ if (connector->max_bpc_property)
+ drm_connector_attach_max_bpc_property(connector, 6, 12);
return connector;
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index bc3a94d491c4..27bd7276a82d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -536,7 +536,8 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (drm_hdcp_check_ksvs_revoked(dev, ksv_fifo, num_downstream)) {
DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
- return -EPERM;
+ ret = -EPERM;
+ goto err;
}
/*
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index 2f4894e9a03d..5ddbe71ab423 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -478,13 +478,13 @@ struct psr_table {
/* TP wake up time in multiple of 100 */
u16 tp1_wakeup_time;
u16 tp2_tp3_wakeup_time;
-
- /* PSR2 TP2/TP3 wakeup time for 16 panels */
- u32 psr2_tp2_tp3_wakeup_time;
} __packed;
struct bdb_psr {
struct psr_table psr_table[16];
+
+ /* PSR2 TP2/TP3 wakeup time for 16 panels */
+ u32 psr2_tp2_tp3_wakeup_time;
} __packed;
/*
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index ffec807b8960..f413904a3e96 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -541,7 +541,7 @@ static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder,
pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) |
DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
DRM_INFO("PPS2 = 0x%08x\n", pps_val);
- if (encoder->type == INTEL_OUTPUT_EDP) {
+ if (cpu_transcoder == TRANSCODER_EDP) {
I915_WRITE(DSCA_PICTURE_PARAMETER_SET_2, pps_val);
/*
* If 2 VDSC instances are needed, configure PPS for second
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
index 99cc3e2e9c2c..f016a776a39e 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
@@ -396,8 +396,8 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev,
else
txesc2_div = 10;
- I915_WRITE(MIPIO_TXESC_CLK_DIV1, txesc1_div & GLK_TX_ESC_CLK_DIV1_MASK);
- I915_WRITE(MIPIO_TXESC_CLK_DIV2, txesc2_div & GLK_TX_ESC_CLK_DIV2_MASK);
+ I915_WRITE(MIPIO_TXESC_CLK_DIV1, (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
+ I915_WRITE(MIPIO_TXESC_CLK_DIV2, (1 << (txesc2_div - 1)) & GLK_TX_ESC_CLK_DIV2_MASK);
}
/* Program BXT Mipi clocks and dividers */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 5fae0e50aad0..41dab9ea33cd 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -1628,6 +1628,7 @@ static int check_relocations(const struct drm_i915_gem_exec_object2 *entry)
static int eb_copy_relocations(const struct i915_execbuffer *eb)
{
+ struct drm_i915_gem_relocation_entry *relocs;
const unsigned int count = eb->buffer_count;
unsigned int i;
int err;
@@ -1635,7 +1636,6 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
for (i = 0; i < count; i++) {
const unsigned int nreloc = eb->exec[i].relocation_count;
struct drm_i915_gem_relocation_entry __user *urelocs;
- struct drm_i915_gem_relocation_entry *relocs;
unsigned long size;
unsigned long copied;
@@ -1663,14 +1663,8 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
if (__copy_from_user((char *)relocs + copied,
(char __user *)urelocs + copied,
- len)) {
-end_user:
- user_access_end();
-end:
- kvfree(relocs);
- err = -EFAULT;
- goto err;
- }
+ len))
+ goto end;
copied += len;
} while (copied < size);
@@ -1699,10 +1693,14 @@ end:
return 0;
+end_user:
+ user_access_end();
+end:
+ kvfree(relocs);
+ err = -EFAULT;
err:
while (i--) {
- struct drm_i915_gem_relocation_entry *relocs =
- u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
+ relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
if (eb->exec[i].relocation_count)
kvfree(relocs);
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 391621ee3cbb..39a661927d8e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -341,7 +341,7 @@ err:
*/
if (!i915_terminally_wedged(i915))
return VM_FAULT_SIGBUS;
- /* else: fall through */
+ /* else, fall through */
case -EAGAIN:
/*
* EAGAIN means the gpu is hung and we'll wait for the error
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index b36ad269f4ea..65eb430cedba 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -268,7 +268,7 @@ static void *i915_gem_object_map(const struct drm_i915_gem_object *obj,
switch (type) {
default:
MISSING_CASE(type);
- /* fallthrough to use PAGE_KERNEL anyway */
+ /* fallthrough - to use PAGE_KERNEL anyway */
case I915_MAP_WB:
pgprot = PAGE_KERNEL;
break;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
index 05011d4a3b88..914b5d4112bb 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
@@ -253,14 +253,15 @@ void i915_gem_resume(struct drm_i915_private *i915)
i915_gem_restore_gtt_mappings(i915);
i915_gem_restore_fences(i915);
+ if (i915_gem_init_hw(i915))
+ goto err_wedged;
+
/*
* As we didn't flush the kernel context before suspend, we cannot
* guarantee that the context image is complete. So let's just reset
* it and start again.
*/
- intel_gt_resume(i915);
-
- if (i915_gem_init_hw(i915))
+ if (intel_gt_resume(i915))
goto err_wedged;
intel_uc_resume(i915);
diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index 2c454f227c2e..23120901c55f 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -126,6 +126,7 @@ static void intel_context_retire(struct i915_active *active)
if (ce->state)
__context_unpin_state(ce->state);
+ intel_ring_unpin(ce->ring);
intel_context_put(ce);
}
@@ -160,27 +161,35 @@ int intel_context_active_acquire(struct intel_context *ce, unsigned long flags)
intel_context_get(ce);
+ err = intel_ring_pin(ce->ring);
+ if (err)
+ goto err_put;
+
if (!ce->state)
return 0;
err = __context_pin_state(ce->state, flags);
- if (err) {
- i915_active_cancel(&ce->active);
- intel_context_put(ce);
- return err;
- }
+ if (err)
+ goto err_ring;
/* Preallocate tracking nodes */
if (!i915_gem_context_is_kernel(ce->gem_context)) {
err = i915_active_acquire_preallocate_barrier(&ce->active,
ce->engine);
- if (err) {
- i915_active_release(&ce->active);
- return err;
- }
+ if (err)
+ goto err_state;
}
return 0;
+
+err_state:
+ __context_unpin_state(ce->state);
+err_ring:
+ intel_ring_unpin(ce->ring);
+err_put:
+ intel_context_put(ce);
+ i915_active_cancel(&ce->active);
+ return err;
}
void intel_context_active_release(struct intel_context *ce)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 7fd33e81c2d9..f25632c9b292 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -969,9 +969,14 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
{
const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
+ unsigned int slice = fls(sseu->slice_mask) - 1;
+ unsigned int subslice;
u32 mcr_s_ss_select;
- u32 slice = fls(sseu->slice_mask);
- u32 subslice = fls(sseu->subslice_mask[slice]);
+
+ GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
+ subslice = fls(sseu->subslice_mask[slice]);
+ GEM_BUG_ON(!subslice);
+ subslice--;
if (IS_GEN(dev_priv, 10))
mcr_s_ss_select = GEN8_MCR_SLICE(slice) |
@@ -1471,6 +1476,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
struct i915_gpu_error * const error = &engine->i915->gpu_error;
struct i915_request *rq;
intel_wakeref_t wakeref;
+ unsigned long flags;
if (header) {
va_list ap;
@@ -1490,10 +1496,9 @@ void intel_engine_dump(struct intel_engine_cs *engine,
i915_reset_engine_count(error, engine),
i915_reset_count(error));
- rcu_read_lock();
-
drm_printf(m, "\tRequests:\n");
+ spin_lock_irqsave(&engine->active.lock, flags);
rq = intel_engine_find_active_request(engine);
if (rq) {
print_request(m, rq, "\t\tactive ");
@@ -1513,8 +1518,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
print_request_ring(m, rq);
}
-
- rcu_read_unlock();
+ spin_unlock_irqrestore(&engine->active.lock, flags);
wakeref = intel_runtime_pm_get_if_in_use(&engine->i915->runtime_pm);
if (wakeref) {
@@ -1672,7 +1676,6 @@ struct i915_request *
intel_engine_find_active_request(struct intel_engine_cs *engine)
{
struct i915_request *request, *active = NULL;
- unsigned long flags;
/*
* We are called by the error capture, reset and to dump engine
@@ -1685,7 +1688,7 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
* At all other times, we must assume the GPU is still running, but
* we only care about the snapshot of this moment.
*/
- spin_lock_irqsave(&engine->active.lock, flags);
+ lockdep_assert_held(&engine->active.lock);
list_for_each_entry(request, &engine->active.requests, sched.link) {
if (i915_request_completed(request))
continue;
@@ -1700,7 +1703,6 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
active = request;
break;
}
- spin_unlock_irqrestore(&engine->active.lock, flags);
return active;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
index 2ce00d3dc42a..ae5b6baf6dff 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
@@ -142,27 +142,3 @@ void intel_engine_init__pm(struct intel_engine_cs *engine)
{
intel_wakeref_init(&engine->wakeref);
}
-
-int intel_engines_resume(struct drm_i915_private *i915)
-{
- struct intel_engine_cs *engine;
- enum intel_engine_id id;
- int err = 0;
-
- intel_gt_pm_get(i915);
- for_each_engine(engine, i915, id) {
- intel_engine_pm_get(engine);
- engine->serial++; /* kernel context lost */
- err = engine->resume(engine);
- intel_engine_pm_put(engine);
- if (err) {
- dev_err(i915->drm.dev,
- "Failed to restart %s (%d)\n",
- engine->name, err);
- break;
- }
- }
- intel_gt_pm_put(i915);
-
- return err;
-}
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h
index b326cd993d60..a11c893f64c6 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h
@@ -7,16 +7,22 @@
#ifndef INTEL_ENGINE_PM_H
#define INTEL_ENGINE_PM_H
+#include "intel_engine_types.h"
+#include "intel_wakeref.h"
+
struct drm_i915_private;
-struct intel_engine_cs;
void intel_engine_pm_get(struct intel_engine_cs *engine);
void intel_engine_pm_put(struct intel_engine_cs *engine);
+static inline bool
+intel_engine_pm_get_if_awake(struct intel_engine_cs *engine)
+{
+ return intel_wakeref_get_if_active(&engine->wakeref);
+}
+
void intel_engine_park(struct intel_engine_cs *engine);
void intel_engine_init__pm(struct intel_engine_cs *engine);
-int intel_engines_resume(struct drm_i915_private *i915);
-
#endif /* INTEL_ENGINE_PM_H */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 868b220214f8..43e975a26016 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -70,6 +70,18 @@ struct intel_ring {
struct list_head request_list;
struct list_head active_link;
+ /*
+ * As we have two types of rings, one global to the engine used
+ * by ringbuffer submission and those that are exclusive to a
+ * context used by execlists, we have to play safe and allow
+ * atomic updates to the pin_count. However, the actual pinning
+ * of the context is either done during initialisation for
+ * ringbuffer submission or serialised as part of the context
+ * pinning for execlists, and so we do not need a mutex ourselves
+ * to serialise intel_ring_pin/intel_ring_unpin.
+ */
+ atomic_t pin_count;
+
u32 head;
u32 tail;
u32 emit;
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index 7b5967751762..9f8f7f54191f 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -5,6 +5,7 @@
*/
#include "i915_drv.h"
+#include "intel_engine_pm.h"
#include "intel_gt_pm.h"
#include "intel_pm.h"
#include "intel_wakeref.h"
@@ -118,10 +119,11 @@ void intel_gt_sanitize(struct drm_i915_private *i915, bool force)
intel_engine_reset(engine, false);
}
-void intel_gt_resume(struct drm_i915_private *i915)
+int intel_gt_resume(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ int err = 0;
/*
* After resume, we may need to poke into the pinned kernel
@@ -129,9 +131,12 @@ void intel_gt_resume(struct drm_i915_private *i915)
* Only the kernel contexts should remain pinned over suspend,
* allowing us to fixup the user contexts on their first pin.
*/
+ intel_gt_pm_get(i915);
for_each_engine(engine, i915, id) {
struct intel_context *ce;
+ intel_engine_pm_get(engine);
+
ce = engine->kernel_context;
if (ce)
ce->ops->reset(ce);
@@ -139,5 +144,19 @@ void intel_gt_resume(struct drm_i915_private *i915)
ce = engine->preempt_context;
if (ce)
ce->ops->reset(ce);
+
+ engine->serial++; /* kernel context lost */
+ err = engine->resume(engine);
+
+ intel_engine_pm_put(engine);
+ if (err) {
+ dev_err(i915->drm.dev,
+ "Failed to restart %s (%d)\n",
+ engine->name, err);
+ break;
+ }
}
+ intel_gt_pm_put(i915);
+
+ return err;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h
index 7dd1130a19a4..53f342b20181 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h
@@ -22,6 +22,6 @@ void intel_gt_pm_put(struct drm_i915_private *i915);
void intel_gt_pm_init(struct drm_i915_private *i915);
void intel_gt_sanitize(struct drm_i915_private *i915, bool force);
-void intel_gt_resume(struct drm_i915_private *i915);
+int intel_gt_resume(struct drm_i915_private *i915);
#endif /* INTEL_GT_PM_H */
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index b42b5f158295..82b7ace62d97 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1414,6 +1414,7 @@ static void execlists_context_destroy(struct kref *kref)
{
struct intel_context *ce = container_of(kref, typeof(*ce), ref);
+ GEM_BUG_ON(!i915_active_is_idle(&ce->active));
GEM_BUG_ON(intel_context_is_pinned(ce));
if (ce->state)
@@ -1426,7 +1427,6 @@ static void execlists_context_unpin(struct intel_context *ce)
{
i915_gem_context_unpin_hw_id(ce->gem_context);
i915_gem_object_unpin_map(ce->state->obj);
- intel_ring_unpin(ce->ring);
}
static void
@@ -1478,13 +1478,9 @@ __execlists_context_pin(struct intel_context *ce,
goto unpin_active;
}
- ret = intel_ring_pin(ce->ring);
- if (ret)
- goto unpin_map;
-
ret = i915_gem_context_pin_hw_id(ce->gem_context);
if (ret)
- goto unpin_ring;
+ goto unpin_map;
ce->lrc_desc = lrc_descriptor(ce, engine);
ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
@@ -1492,8 +1488,6 @@ __execlists_context_pin(struct intel_context *ce,
return 0;
-unpin_ring:
- intel_ring_unpin(ce->ring);
unpin_map:
i915_gem_object_unpin_map(ce->state->obj);
unpin_active:
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 4c478b38e420..3f907701ef4d 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -687,7 +687,6 @@ static void reset_prepare_engine(struct intel_engine_cs *engine)
* written to the powercontext is undefined and so we may lose
* GPU state upon resume, i.e. fail to restart after a reset.
*/
- intel_engine_pm_get(engine);
intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL);
engine->reset.prepare(engine);
}
@@ -718,16 +717,21 @@ static void revoke_mmaps(struct drm_i915_private *i915)
}
}
-static void reset_prepare(struct drm_i915_private *i915)
+static intel_engine_mask_t reset_prepare(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
+ intel_engine_mask_t awake = 0;
enum intel_engine_id id;
- intel_gt_pm_get(i915);
- for_each_engine(engine, i915, id)
+ for_each_engine(engine, i915, id) {
+ if (intel_engine_pm_get_if_awake(engine))
+ awake |= engine->mask;
reset_prepare_engine(engine);
+ }
intel_uc_reset_prepare(i915);
+
+ return awake;
}
static void gt_revoke(struct drm_i915_private *i915)
@@ -761,20 +765,22 @@ static int gt_reset(struct drm_i915_private *i915,
static void reset_finish_engine(struct intel_engine_cs *engine)
{
engine->reset.finish(engine);
- intel_engine_pm_put(engine);
intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL);
+
+ intel_engine_signal_breadcrumbs(engine);
}
-static void reset_finish(struct drm_i915_private *i915)
+static void reset_finish(struct drm_i915_private *i915,
+ intel_engine_mask_t awake)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
for_each_engine(engine, i915, id) {
reset_finish_engine(engine);
- intel_engine_signal_breadcrumbs(engine);
+ if (awake & engine->mask)
+ intel_engine_pm_put(engine);
}
- intel_gt_pm_put(i915);
}
static void nop_submit_request(struct i915_request *request)
@@ -798,6 +804,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
{
struct i915_gpu_error *error = &i915->gpu_error;
struct intel_engine_cs *engine;
+ intel_engine_mask_t awake;
enum intel_engine_id id;
if (test_bit(I915_WEDGED, &error->flags))
@@ -817,7 +824,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
* rolling the global seqno forward (since this would complete requests
* for which we haven't set the fence error to EIO yet).
*/
- reset_prepare(i915);
+ awake = reset_prepare(i915);
/* Even if the GPU reset fails, it should still stop the engines */
if (!INTEL_INFO(i915)->gpu_reset_clobbers_display)
@@ -841,7 +848,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
for_each_engine(engine, i915, id)
engine->cancel_requests(engine);
- reset_finish(i915);
+ reset_finish(i915, awake);
GEM_TRACE("end\n");
}
@@ -951,6 +958,21 @@ static int do_reset(struct drm_i915_private *i915,
return gt_reset(i915, stalled_mask);
}
+static int resume(struct drm_i915_private *i915)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ int ret;
+
+ for_each_engine(engine, i915, id) {
+ ret = engine->resume(engine);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* i915_reset - reset chip after a hang
* @i915: #drm_i915_private to reset
@@ -973,6 +995,7 @@ void i915_reset(struct drm_i915_private *i915,
const char *reason)
{
struct i915_gpu_error *error = &i915->gpu_error;
+ intel_engine_mask_t awake;
int ret;
GEM_TRACE("flags=%lx\n", error->flags);
@@ -989,7 +1012,7 @@ void i915_reset(struct drm_i915_private *i915,
dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason);
error->reset_count++;
- reset_prepare(i915);
+ awake = reset_prepare(i915);
if (!intel_has_gpu_reset(i915)) {
if (i915_modparams.reset)
@@ -1024,13 +1047,17 @@ void i915_reset(struct drm_i915_private *i915,
if (ret) {
DRM_ERROR("Failed to initialise HW following reset (%d)\n",
ret);
- goto error;
+ goto taint;
}
+ ret = resume(i915);
+ if (ret)
+ goto taint;
+
i915_queue_hangcheck(i915);
finish:
- reset_finish(i915);
+ reset_finish(i915, awake);
unlock:
mutex_unlock(&error->wedge_mutex);
return;
@@ -1081,7 +1108,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
GEM_TRACE("%s flags=%lx\n", engine->name, error->flags);
GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags));
- if (!intel_wakeref_active(&engine->wakeref))
+ if (!intel_engine_pm_get_if_awake(engine))
return 0;
reset_prepare_engine(engine);
@@ -1116,12 +1143,11 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
* process to program RING_MODE, HWSP and re-enable submission.
*/
ret = engine->resume(engine);
- if (ret)
- goto out;
out:
intel_engine_cancel_stop_cs(engine);
reset_finish_engine(engine);
+ intel_engine_pm_put(engine);
return ret;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
index c6023bc9452d..12010e798868 100644
--- a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
@@ -1149,16 +1149,16 @@ i915_emit_bb_start(struct i915_request *rq,
int intel_ring_pin(struct intel_ring *ring)
{
struct i915_vma *vma = ring->vma;
- enum i915_map_type map = i915_coherent_map_type(vma->vm->i915);
unsigned int flags;
void *addr;
int ret;
- GEM_BUG_ON(ring->vaddr);
+ if (atomic_fetch_inc(&ring->pin_count))
+ return 0;
ret = i915_timeline_pin(ring->timeline);
if (ret)
- return ret;
+ goto err_unpin;
flags = PIN_GLOBAL;
@@ -1172,26 +1172,31 @@ int intel_ring_pin(struct intel_ring *ring)
ret = i915_vma_pin(vma, 0, 0, flags);
if (unlikely(ret))
- goto unpin_timeline;
+ goto err_timeline;
if (i915_vma_is_map_and_fenceable(vma))
addr = (void __force *)i915_vma_pin_iomap(vma);
else
- addr = i915_gem_object_pin_map(vma->obj, map);
+ addr = i915_gem_object_pin_map(vma->obj,
+ i915_coherent_map_type(vma->vm->i915));
if (IS_ERR(addr)) {
ret = PTR_ERR(addr);
- goto unpin_ring;
+ goto err_ring;
}
vma->obj->pin_global++;
+ GEM_BUG_ON(ring->vaddr);
ring->vaddr = addr;
+
return 0;
-unpin_ring:
+err_ring:
i915_vma_unpin(vma);
-unpin_timeline:
+err_timeline:
i915_timeline_unpin(ring->timeline);
+err_unpin:
+ atomic_dec(&ring->pin_count);
return ret;
}
@@ -1207,16 +1212,19 @@ void intel_ring_reset(struct intel_ring *ring, u32 tail)
void intel_ring_unpin(struct intel_ring *ring)
{
- GEM_BUG_ON(!ring->vma);
- GEM_BUG_ON(!ring->vaddr);
+ if (!atomic_dec_and_test(&ring->pin_count))
+ return;
/* Discard any unused bytes beyond that submitted to hw. */
intel_ring_reset(ring, ring->tail);
+ GEM_BUG_ON(!ring->vma);
if (i915_vma_is_map_and_fenceable(ring->vma))
i915_vma_unpin_iomap(ring->vma);
else
i915_gem_object_unpin_map(ring->vma->obj);
+
+ GEM_BUG_ON(!ring->vaddr);
ring->vaddr = NULL;
ring->vma->obj->pin_global--;
@@ -2081,10 +2089,11 @@ static void ring_destroy(struct intel_engine_cs *engine)
WARN_ON(INTEL_GEN(dev_priv) > 2 &&
(ENGINE_READ(engine, RING_MI_MODE) & MODE_IDLE) == 0);
+ intel_engine_cleanup_common(engine);
+
intel_ring_unpin(engine->buffer);
intel_ring_put(engine->buffer);
- intel_engine_cleanup_common(engine);
kfree(engine);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 15e90fd2cfdc..99e8242194c0 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -308,11 +308,6 @@ static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine,
FLOW_CONTROL_ENABLE |
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
- /* Syncing dependencies between camera and graphics:skl,bxt,kbl */
- if (!IS_COFFEELAKE(i915))
- WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
- GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
-
/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */
/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */
WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
@@ -1098,10 +1093,25 @@ static void glk_whitelist_build(struct intel_engine_cs *engine)
static void cfl_whitelist_build(struct intel_engine_cs *engine)
{
+ struct i915_wa_list *w = &engine->whitelist;
+
if (engine->class != RENDER_CLASS)
return;
- gen9_whitelist_build(&engine->whitelist);
+ gen9_whitelist_build(w);
+
+ /*
+ * WaAllowPMDepthAndInvocationCountAccessFromUMD:cfl,whl,cml,aml
+ *
+ * This covers 4 register which are next to one another :
+ * - PS_INVOCATION_COUNT
+ * - PS_INVOCATION_COUNT_UDW
+ * - PS_DEPTH_COUNT
+ * - PS_DEPTH_COUNT_UDW
+ */
+ whitelist_reg_ext(w, PS_INVOCATION_COUNT,
+ RING_FORCE_TO_NONPRIV_RD |
+ RING_FORCE_TO_NONPRIV_RANGE_4);
}
static void cnl_whitelist_build(struct intel_engine_cs *engine)
@@ -1129,6 +1139,19 @@ static void icl_whitelist_build(struct intel_engine_cs *engine)
/* WaEnableStateCacheRedirectToCS:icl */
whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1);
+
+ /*
+ * WaAllowPMDepthAndInvocationCountAccessFromUMD:icl
+ *
+ * This covers 4 register which are next to one another :
+ * - PS_INVOCATION_COUNT
+ * - PS_INVOCATION_COUNT_UDW
+ * - PS_DEPTH_COUNT
+ * - PS_DEPTH_COUNT_UDW
+ */
+ whitelist_reg_ext(w, PS_INVOCATION_COUNT,
+ RING_FORCE_TO_NONPRIV_RD |
+ RING_FORCE_TO_NONPRIV_RANGE_4);
break;
case VIDEO_DECODE_CLASS:
@@ -1258,8 +1281,12 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
wa_write_or(wal,
GEN7_SARCHKMD,
- GEN7_DISABLE_DEMAND_PREFETCH |
- GEN7_DISABLE_SAMPLER_PREFETCH);
+ GEN7_DISABLE_DEMAND_PREFETCH);
+
+ /* Wa_1606682166:icl */
+ wa_write_or(wal,
+ GEN7_SARCHKMD,
+ GEN7_DISABLE_SAMPLER_PREFETCH);
}
if (IS_GEN_RANGE(i915, 9, 11)) {
diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c
index 086801b51441..486c6953dcb1 100644
--- a/drivers/gpu/drm/i915/gt/mock_engine.c
+++ b/drivers/gpu/drm/i915/gt/mock_engine.c
@@ -66,6 +66,7 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
ring->base.effective_size = sz;
ring->base.vaddr = (void *)(ring + 1);
ring->base.timeline = &ring->timeline;
+ atomic_set(&ring->base.pin_count, 1);
INIT_LIST_HEAD(&ring->base.request_list);
intel_ring_update_space(&ring->base);
diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c
index 89da9e7cc1ba..b5c590c9ccba 100644
--- a/drivers/gpu/drm/i915/gt/selftest_reset.c
+++ b/drivers/gpu/drm/i915/gt/selftest_reset.c
@@ -71,13 +71,16 @@ static int igt_atomic_reset(void *arg)
goto unlock;
for (p = igt_atomic_phases; p->name; p++) {
+ intel_engine_mask_t awake;
+
GEM_TRACE("intel_gpu_reset under %s\n", p->name);
+ awake = reset_prepare(i915);
p->critical_section_begin();
reset_prepare(i915);
err = intel_gpu_reset(i915, ALL_ENGINES);
- reset_finish(i915);
p->critical_section_end();
+ reset_finish(i915, awake);
if (err) {
pr_err("intel_gpu_reset failed under %s\n", p->name);
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 9eaf030affd0..44becd9538be 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -925,7 +925,12 @@ check_whitelisted_registers(struct intel_engine_cs *engine,
err = 0;
for (i = 0; i < engine->whitelist.count; i++) {
- if (!fn(engine, a[i], b[i], engine->whitelist.list[i].reg))
+ const struct i915_wa *wa = &engine->whitelist.list[i];
+
+ if (i915_mmio_reg_offset(wa->reg) & RING_FORCE_TO_NONPRIV_RD)
+ continue;
+
+ if (!fn(engine, a[i], b[i], wa->reg))
err = -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index 6ea88270c818..b09dc315e2da 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -2674,11 +2674,6 @@ static int scan_workload(struct intel_vgpu_workload *workload)
gma_head == gma_tail)
return 0;
- if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) {
- ret = -EINVAL;
- goto out;
- }
-
ret = ip_gma_set(&s, gma_head);
if (ret)
goto out;
@@ -2724,11 +2719,6 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
s.workload = workload;
s.is_ctx_wa = true;
- if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) {
- ret = -EINVAL;
- goto out;
- }
-
ret = ip_gma_set(&s, gma_head);
if (ret)
goto out;
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
index 65e847392aea..8bb292b01271 100644
--- a/drivers/gpu/drm/i915/gvt/fb_decoder.c
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
@@ -245,7 +245,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
plane->hw_format = fmt;
plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK;
- if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+ if (!vgpu_gmadr_is_valid(vgpu, plane->base))
return -EINVAL;
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
@@ -368,7 +368,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu,
alpha_plane, alpha_force);
plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK;
- if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+ if (!vgpu_gmadr_is_valid(vgpu, plane->base))
return -EINVAL;
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
@@ -472,7 +472,7 @@ int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu,
plane->drm_format = drm_format;
plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK;
- if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+ if (!vgpu_gmadr_is_valid(vgpu, plane->base))
return -EINVAL;
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 53115bdae12b..4b04af569c05 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -2141,11 +2141,20 @@ static int emulate_ggtt_mmio_read(struct intel_vgpu *vgpu,
struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
unsigned long index = off >> info->gtt_entry_size_shift;
+ unsigned long gma;
struct intel_gvt_gtt_entry e;
if (bytes != 4 && bytes != 8)
return -EINVAL;
+ gma = index << I915_GTT_PAGE_SHIFT;
+ if (!intel_gvt_ggtt_validate_range(vgpu,
+ gma, 1 << I915_GTT_PAGE_SHIFT)) {
+ gvt_dbg_mm("read invalid ggtt at 0x%lx\n", gma);
+ memset(p_data, 0, bytes);
+ return 0;
+ }
+
ggtt_get_guest_entry(ggtt_mm, &e, index);
memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)),
bytes);
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 144301b778df..23aa3e50cbf8 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1911,6 +1911,18 @@ static int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr, size);
if (ret)
goto err_unmap;
+ } else if (entry->size != size) {
+ /* the same gfn with different size: unmap and re-map */
+ gvt_dma_unmap_page(vgpu, gfn, entry->dma_addr, entry->size);
+ __gvt_cache_remove_entry(vgpu, entry);
+
+ ret = gvt_dma_map_page(vgpu, gfn, dma_addr, size);
+ if (ret)
+ goto err_unlock;
+
+ ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr, size);
+ if (ret)
+ goto err_unmap;
} else {
kref_get(&entry->ref);
*dma_addr = entry->dma_addr;
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 2144fb46d0e1..75baff657e43 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -364,16 +364,13 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
wa_ctx->indirect_ctx.shadow_va = NULL;
}
-static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
- struct i915_gem_context *ctx)
+static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
+ struct i915_gem_context *ctx)
{
struct intel_vgpu_mm *mm = workload->shadow_mm;
struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(ctx->vm);
int i = 0;
- if (mm->type != INTEL_GVT_MM_PPGTT || !mm->ppgtt_mm.shadowed)
- return -EINVAL;
-
if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
px_dma(ppgtt->pd) = mm->ppgtt_mm.shadow_pdps[0];
} else {
@@ -384,8 +381,6 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i];
}
}
-
- return 0;
}
static int
@@ -614,6 +609,8 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload)
static int prepare_workload(struct intel_vgpu_workload *workload)
{
struct intel_vgpu *vgpu = workload->vgpu;
+ struct intel_vgpu_submission *s = &vgpu->submission;
+ int ring = workload->ring_id;
int ret = 0;
ret = intel_vgpu_pin_mm(workload->shadow_mm);
@@ -622,8 +619,16 @@ static int prepare_workload(struct intel_vgpu_workload *workload)
return ret;
}
+ if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT ||
+ !workload->shadow_mm->ppgtt_mm.shadowed) {
+ gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
+ return -EINVAL;
+ }
+
update_shadow_pdps(workload);
+ set_context_ppgtt_from_shadow(workload, s->shadow[ring]->gem_context);
+
ret = intel_vgpu_sync_oos_pages(workload->vgpu);
if (ret) {
gvt_vgpu_err("fail to vgpu sync oos pages\n");
@@ -674,7 +679,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
{
struct intel_vgpu *vgpu = workload->vgpu;
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
- struct intel_vgpu_submission *s = &vgpu->submission;
struct i915_request *rq;
int ring_id = workload->ring_id;
int ret;
@@ -685,13 +689,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
mutex_lock(&vgpu->vgpu_lock);
mutex_lock(&dev_priv->drm.struct_mutex);
- ret = set_context_ppgtt_from_shadow(workload,
- s->shadow[ring_id]->gem_context);
- if (ret < 0) {
- gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
- goto err_req;
- }
-
ret = intel_gvt_workload_req_alloc(workload);
if (ret)
goto err_req;
@@ -990,6 +987,7 @@ static int workload_thread(void *priv)
int ret;
bool need_force_wake = (INTEL_GEN(gvt->dev_priv) >= 9);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
+ struct intel_runtime_pm *rpm = &gvt->dev_priv->runtime_pm;
kfree(p);
@@ -1013,6 +1011,8 @@ static int workload_thread(void *priv)
workload->ring_id, workload,
workload->vgpu->id);
+ intel_runtime_pm_get(rpm);
+
gvt_dbg_sched("ring id %d will dispatch workload %p\n",
workload->ring_id, workload);
@@ -1042,6 +1042,7 @@ complete:
intel_uncore_forcewake_put(&gvt->dev_priv->uncore,
FORCEWAKE_ALL);
+ intel_runtime_pm_put_unchecked(rpm);
if (ret && (vgpu_is_vm_unhealthy(ret)))
enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
}
@@ -1492,6 +1493,12 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4);
+ if (!intel_gvt_ggtt_validate_range(vgpu, start,
+ _RING_CTL_BUF_SIZE(ctl))) {
+ gvt_vgpu_err("context contain invalid rb at: 0x%x\n", start);
+ return ERR_PTR(-EINVAL);
+ }
+
workload = alloc_workload(vgpu);
if (IS_ERR(workload))
return workload;
@@ -1516,9 +1523,31 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
workload->wa_ctx.indirect_ctx.size =
(indirect_ctx & INDIRECT_CTX_SIZE_MASK) *
CACHELINE_BYTES;
+
+ if (workload->wa_ctx.indirect_ctx.size != 0) {
+ if (!intel_gvt_ggtt_validate_range(vgpu,
+ workload->wa_ctx.indirect_ctx.guest_gma,
+ workload->wa_ctx.indirect_ctx.size)) {
+ gvt_vgpu_err("invalid wa_ctx at: 0x%lx\n",
+ workload->wa_ctx.indirect_ctx.guest_gma);
+ kmem_cache_free(s->workloads, workload);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
workload->wa_ctx.per_ctx.guest_gma =
per_ctx & PER_CTX_ADDR_MASK;
workload->wa_ctx.per_ctx.valid = per_ctx & 1;
+ if (workload->wa_ctx.per_ctx.valid) {
+ if (!intel_gvt_ggtt_validate_range(vgpu,
+ workload->wa_ctx.per_ctx.guest_gma,
+ CACHELINE_BYTES)) {
+ gvt_vgpu_err("invalid per_ctx at: 0x%lx\n",
+ workload->wa_ctx.per_ctx.guest_gma);
+ kmem_cache_free(s->workloads, workload);
+ return ERR_PTR(-EINVAL);
+ }
+ }
}
gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n",
diff --git a/drivers/gpu/drm/i915/gvt/trace_points.c b/drivers/gpu/drm/i915/gvt/trace_points.c
index a3deed692b9c..fe552e877e09 100644
--- a/drivers/gpu/drm/i915/gvt/trace_points.c
+++ b/drivers/gpu/drm/i915/gvt/trace_points.c
@@ -28,8 +28,6 @@
*
*/
-#include "trace.h"
-
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "trace.h"
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f62e3397d936..bac1ee94f63f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1598,6 +1598,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
pci_set_master(pdev);
+ /*
+ * We don't have a max segment size, so set it to the max so sg's
+ * debugging layer doesn't complain
+ */
+ dma_set_max_seg_size(&pdev->dev, UINT_MAX);
+
/* overlay on gen2 is broken and can't address above 1G */
if (IS_GEN(dev_priv, 2)) {
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bc909ec5d9c3..fe7a6ec2c199 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1674,8 +1674,9 @@ struct drm_i915_private {
} dram_info;
struct intel_bw_info {
- int num_planes;
- int deratedbw[3];
+ unsigned int deratedbw[3]; /* for each QGV point */
+ u8 num_qgv_points;
+ u8 num_planes;
} max_bw[6];
struct drm_private_obj bw_obj;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 190ad54fb072..8a659d3d7435 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -46,7 +46,6 @@
#include "gem/i915_gem_ioctls.h"
#include "gem/i915_gem_pm.h"
#include "gem/i915_gemfs.h"
-#include "gt/intel_engine_pm.h"
#include "gt/intel_gt_pm.h"
#include "gt/intel_mocs.h"
#include "gt/intel_reset.h"
@@ -1307,21 +1306,13 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
intel_mocs_init_l3cc_table(dev_priv);
- /* Only when the HW is re-initialised, can we replay the requests */
- ret = intel_engines_resume(dev_priv);
- if (ret)
- goto cleanup_uc;
-
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
intel_engines_set_scheduler_caps(dev_priv);
return 0;
-cleanup_uc:
- intel_uc_fini_hw(dev_priv);
out:
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
-
return ret;
}
@@ -1580,6 +1571,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (ret)
goto err_uc_init;
+ /* Only when the HW is re-initialised, can we replay the requests */
+ ret = intel_gt_resume(dev_priv);
+ if (ret)
+ goto err_init_hw;
+
/*
* Despite its name intel_init_clock_gating applies both display
* clock gating workarounds; GT mmio workarounds and the occasional
@@ -1593,20 +1589,20 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
ret = intel_engines_verify_workarounds(dev_priv);
if (ret)
- goto err_init_hw;
+ goto err_gt;
ret = __intel_engines_record_defaults(dev_priv);
if (ret)
- goto err_init_hw;
+ goto err_gt;
if (i915_inject_load_failure()) {
ret = -ENODEV;
- goto err_init_hw;
+ goto err_gt;
}
if (i915_inject_load_failure()) {
ret = -EIO;
- goto err_init_hw;
+ goto err_gt;
}
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
@@ -1620,7 +1616,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
* HW as irrevisibly wedged, but keep enough state around that the
* driver doesn't explode during runtime.
*/
-err_init_hw:
+err_gt:
mutex_unlock(&dev_priv->drm.struct_mutex);
i915_gem_set_wedged(dev_priv);
@@ -1630,6 +1626,7 @@ err_init_hw:
i915_gem_drain_workqueue(dev_priv);
mutex_lock(&dev_priv->drm.struct_mutex);
+err_init_hw:
intel_uc_fini_hw(dev_priv);
err_uc_init:
intel_uc_fini(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 8ab820145ea6..7015a97b1097 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1444,9 +1444,11 @@ unwind_pd:
spin_lock(&pdp->lock);
if (atomic_dec_and_test(&pd->used)) {
gen8_ppgtt_set_pdpe(pdp, vm->scratch_pd, pdpe);
+ pdp->entry[pdpe] = vm->scratch_pd;
GEM_BUG_ON(!atomic_read(&pdp->used));
atomic_dec(&pdp->used);
- free_pd(vm, pd);
+ GEM_BUG_ON(alloc);
+ alloc = pd; /* defer the free to after the lock */
}
spin_unlock(&pdp->lock);
unwind:
@@ -1515,7 +1517,9 @@ unwind_pdp:
spin_lock(&pml4->lock);
if (atomic_dec_and_test(&pdp->used)) {
gen8_ppgtt_set_pml4e(pml4, vm->scratch_pdp, pml4e);
- free_pd(vm, pdp);
+ pml4->entry[pml4e] = vm->scratch_pdp;
+ GEM_BUG_ON(alloc);
+ alloc = pdp; /* defer the free until after the lock */
}
spin_unlock(&pml4->lock);
unwind:
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index b7e9fddef270..8bc76fcff70d 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1194,6 +1194,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
switch (engine->id) {
default:
MISSING_CASE(engine->id);
+ /* fall through */
case RCS0:
mmio = RENDER_HWS_PGA_GEN7;
break;
@@ -1417,6 +1418,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
struct intel_engine_cs *engine = i915->engine[i];
struct drm_i915_error_engine *ee = &error->engine[i];
struct i915_request *request;
+ unsigned long flags;
ee->engine_id = -1;
@@ -1428,10 +1430,11 @@ static void gem_record_rings(struct i915_gpu_state *error)
error_record_engine_registers(error, engine, ee);
error_record_engine_execlists(engine, ee);
+ spin_lock_irqsave(&engine->active.lock, flags);
request = intel_engine_find_active_request(engine);
if (request) {
struct i915_gem_context *ctx = request->gem_context;
- struct intel_ring *ring;
+ struct intel_ring *ring = request->ring;
ee->vm = ctx->vm ?: &ggtt->vm;
@@ -1461,7 +1464,6 @@ static void gem_record_rings(struct i915_gpu_state *error)
ee->rq_post = request->postfix;
ee->rq_tail = request->tail;
- ring = request->ring;
ee->cpu_ring_head = ring->head;
ee->cpu_ring_tail = ring->tail;
ee->ringbuffer =
@@ -1469,6 +1471,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
engine_record_requests(engine, request, ee);
}
+ spin_unlock_irqrestore(&engine->active.lock, flags);
ee->hws_page =
i915_error_object_create(i915,
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index a700c5c3d167..5140017f9a39 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1567,28 +1567,10 @@ static void config_oa_regs(struct drm_i915_private *dev_priv,
}
}
-static int hsw_enable_metric_set(struct i915_perf_stream *stream)
+static void delay_after_mux(void)
{
- struct drm_i915_private *dev_priv = stream->dev_priv;
- const struct i915_oa_config *oa_config = stream->oa_config;
-
- /* PRM:
- *
- * OA unit is using “crclk†for its functionality. When trunk
- * level clock gating takes place, OA clock would be gated,
- * unable to count the events from non-render clock domain.
- * Render clock gating must be disabled when OA is enabled to
- * count the events from non-render domain. Unit level clock
- * gating for RCS should also be disabled.
- */
- I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
- ~GEN7_DOP_CLOCK_GATE_ENABLE));
- I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) |
- GEN6_CSUNIT_CLOCK_GATE_DISABLE));
-
- config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
-
- /* It apparently takes a fairly long time for a new MUX
+ /*
+ * It apparently takes a fairly long time for a new MUX
* configuration to be be applied after these register writes.
* This delay duration was derived empirically based on the
* render_basic config but hopefully it covers the maximum
@@ -1610,6 +1592,30 @@ static int hsw_enable_metric_set(struct i915_perf_stream *stream)
* a delay at this location would mitigate any invalid reports.
*/
usleep_range(15000, 20000);
+}
+
+static int hsw_enable_metric_set(struct i915_perf_stream *stream)
+{
+ struct drm_i915_private *dev_priv = stream->dev_priv;
+ const struct i915_oa_config *oa_config = stream->oa_config;
+
+ /*
+ * PRM:
+ *
+ * OA unit is using “crclk†for its functionality. When trunk
+ * level clock gating takes place, OA clock would be gated,
+ * unable to count the events from non-render clock domain.
+ * Render clock gating must be disabled when OA is enabled to
+ * count the events from non-render domain. Unit level clock
+ * gating for RCS should also be disabled.
+ */
+ I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
+ ~GEN7_DOP_CLOCK_GATE_ENABLE));
+ I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) |
+ GEN6_CSUNIT_CLOCK_GATE_DISABLE));
+
+ config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
+ delay_after_mux();
config_oa_regs(dev_priv, oa_config->b_counter_regs,
oa_config->b_counter_regs_len);
@@ -1835,6 +1841,7 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
return ret;
config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
+ delay_after_mux();
config_oa_regs(dev_priv, oa_config->b_counter_regs,
oa_config->b_counter_regs_len);
@@ -2515,6 +2522,9 @@ static int i915_perf_release(struct inode *inode, struct file *file)
i915_perf_destroy_locked(stream);
mutex_unlock(&dev_priv->perf.lock);
+ /* Release the reference the perf stream kept on the driver. */
+ drm_dev_put(&dev_priv->drm);
+
return 0;
}
@@ -2650,6 +2660,11 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,
if (!(param->flags & I915_PERF_FLAG_DISABLED))
i915_perf_enable_locked(stream);
+ /* Take a reference on the driver that will be kept with stream_fd
+ * until its release.
+ */
+ drm_dev_get(&dev_priv->drm);
+
return stream_fd;
err_open:
@@ -3477,9 +3492,13 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
dev_priv->perf.oa.ops.disable_metric_set = gen10_disable_metric_set;
- dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
- dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
-
+ if (IS_GEN(dev_priv, 10)) {
+ dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
+ dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
+ } else {
+ dev_priv->perf.oa.ctx_oactxctrl_offset = 0x124;
+ dev_priv->perf.oa.ctx_flexeu0_offset = 0x78e;
+ }
dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
}
}
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index f4ce643b3bc3..cce426b23a24 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -21,24 +21,22 @@
/* watermark/fifo updates */
TRACE_EVENT(intel_pipe_enable,
- TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pipe),
- TP_ARGS(dev_priv, pipe),
+ TP_PROTO(struct intel_crtc *crtc),
+ TP_ARGS(crtc),
TP_STRUCT__entry(
__array(u32, frame, 3)
__array(u32, scanline, 3)
__field(enum pipe, pipe)
),
-
TP_fast_assign(
- enum pipe _pipe;
- for_each_pipe(dev_priv, _pipe) {
- __entry->frame[_pipe] =
- dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, _pipe);
- __entry->scanline[_pipe] =
- intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, _pipe));
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc *it__;
+ for_each_intel_crtc(&dev_priv->drm, it__) {
+ __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
+ __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
- __entry->pipe = pipe;
+ __entry->pipe = crtc->pipe;
),
TP_printk("pipe %c enable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
@@ -49,8 +47,8 @@ TRACE_EVENT(intel_pipe_enable,
);
TRACE_EVENT(intel_pipe_disable,
- TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pipe),
- TP_ARGS(dev_priv, pipe),
+ TP_PROTO(struct intel_crtc *crtc),
+ TP_ARGS(crtc),
TP_STRUCT__entry(
__array(u32, frame, 3)
@@ -59,14 +57,13 @@ TRACE_EVENT(intel_pipe_disable,
),
TP_fast_assign(
- enum pipe _pipe;
- for_each_pipe(dev_priv, _pipe) {
- __entry->frame[_pipe] =
- dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, _pipe);
- __entry->scanline[_pipe] =
- intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, _pipe));
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc *it__;
+ for_each_intel_crtc(&dev_priv->drm, it__) {
+ __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
+ __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
- __entry->pipe = pipe;
+ __entry->pipe = crtc->pipe;
),
TP_printk("pipe %c disable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
@@ -89,8 +86,7 @@ TRACE_EVENT(intel_pipe_crc,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->crcs, crcs, sizeof(__entry->crcs));
),
@@ -112,9 +108,10 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
),
TP_fast_assign(
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
__entry->pipe = pipe;
- __entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
- __entry->scanline = intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("pipe %c, frame=%u, scanline=%u",
@@ -134,9 +131,10 @@ TRACE_EVENT(intel_pch_fifo_underrun,
TP_fast_assign(
enum pipe pipe = pch_transcoder;
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
__entry->pipe = pipe;
- __entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
- __entry->scanline = intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("pch transcoder %c, frame=%u, scanline=%u",
@@ -156,12 +154,10 @@ TRACE_EVENT(intel_memory_cxsr,
),
TP_fast_assign(
- enum pipe pipe;
- for_each_pipe(dev_priv, pipe) {
- __entry->frame[pipe] =
- dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
- __entry->scanline[pipe] =
- intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+ struct intel_crtc *crtc;
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ __entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
}
__entry->old = old;
__entry->new = new;
@@ -198,8 +194,7 @@ TRACE_EVENT(g4x_wm,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->primary = wm->pipe[crtc->pipe].plane[PLANE_PRIMARY];
__entry->sprite = wm->pipe[crtc->pipe].plane[PLANE_SPRITE0];
@@ -243,8 +238,7 @@ TRACE_EVENT(vlv_wm,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->level = wm->level;
__entry->cxsr = wm->cxsr;
@@ -278,8 +272,7 @@ TRACE_EVENT(vlv_fifo_size,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->sprite0_start = sprite0_start;
__entry->sprite1_start = sprite1_start;
@@ -310,8 +303,7 @@ TRACE_EVENT(intel_update_plane,
TP_fast_assign(
__entry->pipe = crtc->pipe;
__entry->name = plane->name;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->src, &plane->state->src, sizeof(__entry->src));
memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst));
@@ -338,8 +330,7 @@ TRACE_EVENT(intel_disable_plane,
TP_fast_assign(
__entry->pipe = crtc->pipe;
__entry->name = plane->name;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
@@ -364,8 +355,7 @@ TRACE_EVENT(i915_pipe_update_start,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->min = crtc->debug.min_vbl;
__entry->max = crtc->debug.max_vbl;
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index 94d3992b599d..724627afdedc 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -101,6 +101,9 @@ static struct _balloon_info_ bl_info;
static void vgt_deballoon_space(struct i915_ggtt *ggtt,
struct drm_mm_node *node)
{
+ if (!drm_mm_node_allocated(node))
+ return;
+
DRM_DEBUG_DRIVER("deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
node->start,
node->start + node->size,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1d58f7ec5d84..f11979879e7b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -829,7 +829,7 @@ struct intel_crtc_state {
/*
* Frequence the dpll for the port should run at. Differs from the
- * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
+ * adjusted dotclock e.g. for DP or 10/12bpc hdmi mode. This is also
* already multiplied by pixel_multiplier.
*/
int port_clock;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 502c54428570..8d1aebc3e857 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -221,13 +221,11 @@ __untrack_all_wakerefs(struct intel_runtime_pm_debug *debug,
static void
dump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug)
{
- struct drm_printer p;
+ if (debug->count) {
+ struct drm_printer p = drm_debug_printer("i915");
- if (!debug->count)
- return;
-
- p = drm_debug_printer("i915");
- __print_intel_runtime_pm_wakeref(&p, debug);
+ __print_intel_runtime_pm_wakeref(&p, debug);
+ }
kfree(debug->owners);
}
diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h
index 9cbb2ebf575b..38275310b196 100644
--- a/drivers/gpu/drm/i915/intel_wakeref.h
+++ b/drivers/gpu/drm/i915/intel_wakeref.h
@@ -66,6 +66,21 @@ intel_wakeref_get(struct intel_runtime_pm *rpm,
}
/**
+ * intel_wakeref_get_if_in_use: Acquire the wakeref
+ * @wf: the wakeref
+ *
+ * Acquire a hold on the wakeref, but only if the wakeref is already
+ * active.
+ *
+ * Returns: true if the wakeref was acquired, false otherwise.
+ */
+static inline bool
+intel_wakeref_get_if_active(struct intel_wakeref *wf)
+{
+ return atomic_inc_not_zero(&wf->count);
+}
+
+/**
* intel_wakeref_put: Release the wakeref
* @i915: the drm_i915_private device
* @wf: the wakeref
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c
index e9f9e9fb9b17..6381652a8829 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm.c
@@ -656,10 +656,9 @@ static int ingenic_drm_probe(struct platform_device *pdev)
return ret;
}
- if (panel) {
+ if (panel)
bridge = devm_drm_panel_bridge_add(dev, panel,
- DRM_MODE_CONNECTOR_Unknown);
- }
+ DRM_MODE_CONNECTOR_DPI);
priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc),
&priv->dma_hwdesc_phys,
diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
index 477c0f766663..b609dc030d6c 100644
--- a/drivers/gpu/drm/lima/lima_gem.c
+++ b/drivers/gpu/drm/lima/lima_gem.c
@@ -342,7 +342,7 @@ int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, s64 timeout_ns)
timeout = drm_timeout_abs_to_jiffies(timeout_ns);
ret = drm_gem_reservation_object_wait(file, handle, write, timeout);
- if (ret == 0)
+ if (ret == -ETIME)
ret = timeout ? -ETIMEDOUT : -EBUSY;
return ret;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 95fdbd0fbcac..945bc20f1d33 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
#include "mtk_drm_crtc.h"
#include "mtk_drm_ddp.h"
@@ -213,6 +214,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
struct mtk_drm_private *private = drm->dev_private;
struct platform_device *pdev;
struct device_node *np;
+ struct device *dma_dev;
int ret;
if (!iommu_present(&platform_bus_type))
@@ -275,7 +277,29 @@ static int mtk_drm_kms_init(struct drm_device *drm)
goto err_component_unbind;
}
- private->dma_dev = &pdev->dev;
+ dma_dev = &pdev->dev;
+ private->dma_dev = dma_dev;
+
+ /*
+ * Configure the DMA segment size to make sure we get contiguous IOVA
+ * when importing PRIME buffers.
+ */
+ if (!dma_dev->dma_parms) {
+ private->dma_parms_allocated = true;
+ dma_dev->dma_parms =
+ devm_kzalloc(drm->dev, sizeof(*dma_dev->dma_parms),
+ GFP_KERNEL);
+ }
+ if (!dma_dev->dma_parms) {
+ ret = -ENOMEM;
+ goto err_component_unbind;
+ }
+
+ ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(dma_dev, "Failed to set DMA segment size\n");
+ goto err_unset_dma_parms;
+ }
/*
* We don't use the drm_irq_install() helpers provided by the DRM
@@ -285,13 +309,16 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm->irq_enabled = true;
ret = drm_vblank_init(drm, MAX_CRTC);
if (ret < 0)
- goto err_component_unbind;
+ goto err_unset_dma_parms;
drm_kms_helper_poll_init(drm);
drm_mode_config_reset(drm);
return 0;
+err_unset_dma_parms:
+ if (private->dma_parms_allocated)
+ dma_dev->dma_parms = NULL;
err_component_unbind:
component_unbind_all(drm->dev, drm);
err_config_cleanup:
@@ -302,9 +329,14 @@ err_config_cleanup:
static void mtk_drm_kms_deinit(struct drm_device *drm)
{
+ struct mtk_drm_private *private = drm->dev_private;
+
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
+ if (private->dma_parms_allocated)
+ private->dma_dev->dma_parms = NULL;
+
component_unbind_all(drm->dev, drm);
drm_mode_config_cleanup(drm);
}
@@ -320,6 +352,18 @@ static const struct file_operations mtk_drm_fops = {
.compat_ioctl = drm_compat_ioctl,
};
+/*
+ * We need to override this because the device used to import the memory is
+ * not dev->dev, as drm_gem_prime_import() expects.
+ */
+struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *dma_buf)
+{
+ struct mtk_drm_private *private = dev->dev_private;
+
+ return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
+}
+
static struct drm_driver mtk_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
DRIVER_ATOMIC,
@@ -331,7 +375,7 @@ static struct drm_driver mtk_drm_driver = {
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = drm_gem_prime_export,
- .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_import = mtk_drm_gem_prime_import,
.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
.gem_prime_mmap = mtk_drm_gem_mmap_buf,
@@ -524,12 +568,15 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
if (!comp) {
ret = -ENOMEM;
+ of_node_put(node);
goto err_node;
}
ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
- if (ret)
+ if (ret) {
+ of_node_put(node);
goto err_node;
+ }
private->ddp_comp[comp_id] = comp;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 598ff3e70446..e03fea12ff59 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -51,6 +51,8 @@ struct mtk_drm_private {
} commit;
struct drm_atomic_state *suspend_state;
+
+ bool dma_parms_allocated;
};
extern struct platform_driver mtk_ddp_driver;
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 1671db47aa57..e9c55d1d6c04 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -59,6 +59,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
if (priv->lastctx == ctx)
break;
+ /* fall-thru */
case MSM_SUBMIT_CMD_BUF:
/* copy commands into RB: */
obj = submit->bos[submit->cmd[i].idx].obj;
@@ -149,6 +150,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
if (priv->lastctx == ctx)
break;
+ /* fall-thru */
case MSM_SUBMIT_CMD_BUF:
OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index be39cf01e51e..dc8ec2c94301 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -115,6 +115,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
if (priv->lastctx == ctx)
break;
+ /* fall-thru */
case MSM_SUBMIT_CMD_BUF:
OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9acbbc0f3232..048c8be426f3 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -428,6 +428,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
/* ignore if there has not been a ctx switch: */
if (priv->lastctx == ctx)
break;
+ /* fall-thru */
case MSM_SUBMIT_CMD_BUF:
OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ?
CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0e2f74163a16..0aa8a12c9952 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2221,8 +2221,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
if (ret)
goto fail;
- spin_lock_init(&dpu_enc->enc_spinlock);
-
atomic_set(&dpu_enc->frame_done_timeout_ms, 0);
timer_setup(&dpu_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
@@ -2276,6 +2274,7 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs);
+ spin_lock_init(&dpu_enc->enc_spinlock);
dpu_enc->enabled = false;
return &dpu_enc->base;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index ff14555372d0..78d5fa230c16 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -439,6 +439,18 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
mdp5_crtc->enabled = false;
}
+static void mdp5_crtc_vblank_on(struct drm_crtc *crtc)
+{
+ struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+ struct mdp5_interface *intf = mdp5_cstate->pipeline.intf;
+ u32 count;
+
+ count = intf->mode == MDP5_INTF_DSI_MODE_COMMAND ? 0 : 0xffffffff;
+ drm_crtc_set_max_vblank_count(crtc, count);
+
+ drm_crtc_vblank_on(crtc);
+}
+
static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -475,7 +487,7 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
}
/* Restore vblank irq handling after power is enabled */
- drm_crtc_vblank_on(crtc);
+ mdp5_crtc_vblank_on(crtc);
mdp5_crtc_mode_set_nofb(crtc);
@@ -1028,6 +1040,8 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
mdp5_crtc_destroy_state(crtc, crtc->state);
__drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
+
+ drm_crtc_vblank_reset(crtc);
}
static const struct drm_crtc_funcs mdp5_crtc_funcs = {
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 4a60f5fca6b0..fec6ef1ae3b9 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -740,7 +740,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
dev->driver->get_scanout_position = mdp5_get_scanoutpos;
dev->driver->get_vblank_counter = mdp5_get_vblank_counter;
- dev->max_vblank_count = 0xffffffff;
+ dev->max_vblank_count = 0; /* max_vblank_count is set on each CRTC */
dev->vblank_disable_immediate = true;
return kms;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index ab64ab470de7..c356f5ccf253 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -619,7 +619,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file)
msm_submitqueue_init(dev, ctx);
- ctx->aspace = priv->gpu->aspace;
+ ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL;
file->driver_priv = ctx;
return 0;
@@ -1279,7 +1279,8 @@ static int add_gpu_components(struct device *dev,
if (!np)
return 0;
- drm_of_component_match_add(dev, matchptr, compare_of, np);
+ if (of_device_is_available(np))
+ drm_of_component_match_add(dev, matchptr, compare_of, np);
of_node_put(np);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 8b78554cfde3..8cf6362e64bf 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -32,6 +32,46 @@ static bool use_pages(struct drm_gem_object *obj)
return !msm_obj->vram_node;
}
+/*
+ * Cache sync.. this is a bit over-complicated, to fit dma-mapping
+ * API. Really GPU cache is out of scope here (handled on cmdstream)
+ * and all we need to do is invalidate newly allocated pages before
+ * mapping to CPU as uncached/writecombine.
+ *
+ * On top of this, we have the added headache, that depending on
+ * display generation, the display's iommu may be wired up to either
+ * the toplevel drm device (mdss), or to the mdp sub-node, meaning
+ * that here we either have dma-direct or iommu ops.
+ *
+ * Let this be a cautionary tail of abstraction gone wrong.
+ */
+
+static void sync_for_device(struct msm_gem_object *msm_obj)
+{
+ struct device *dev = msm_obj->base.dev->dev;
+
+ if (get_dma_ops(dev)) {
+ dma_sync_sg_for_device(dev, msm_obj->sgt->sgl,
+ msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+ } else {
+ dma_map_sg(dev, msm_obj->sgt->sgl,
+ msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+ }
+}
+
+static void sync_for_cpu(struct msm_gem_object *msm_obj)
+{
+ struct device *dev = msm_obj->base.dev->dev;
+
+ if (get_dma_ops(dev)) {
+ dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl,
+ msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+ } else {
+ dma_unmap_sg(dev, msm_obj->sgt->sgl,
+ msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+ }
+}
+
/* allocate pages from VRAM carveout, used when no IOMMU: */
static struct page **get_pages_vram(struct drm_gem_object *obj, int npages)
{
@@ -97,8 +137,7 @@ static struct page **get_pages(struct drm_gem_object *obj)
* because display controller, GPU, etc. are not coherent:
*/
if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
- dma_map_sg(dev->dev, msm_obj->sgt->sgl,
- msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+ sync_for_device(msm_obj);
}
return msm_obj->pages;
@@ -127,9 +166,7 @@ static void put_pages(struct drm_gem_object *obj)
* GPU, etc. are not coherent:
*/
if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
- dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl,
- msm_obj->sgt->nents,
- DMA_BIDIRECTIONAL);
+ sync_for_cpu(msm_obj);
sg_free_table(msm_obj->sgt);
kfree(msm_obj->sgt);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 8497768f1b41..5c36c75232e6 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -771,16 +771,20 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
int slots;
- /* When restoring duplicated states, we need to make sure that the
- * bw remains the same and avoid recalculating it, as the connector's
- * bpc may have changed after the state was duplicated
- */
- if (!state->duplicated)
- asyh->dp.pbn =
- drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
- connector->display_info.bpc * 3);
+ if (crtc_state->mode_changed || crtc_state->connectors_changed) {
+ /*
+ * When restoring duplicated states, we need to make sure that
+ * the bw remains the same and avoid recalculating it, as the
+ * connector's bpc may have changed after the state was
+ * duplicated
+ */
+ if (!state->duplicated) {
+ const int bpp = connector->display_info.bpc * 3;
+ const int clock = crtc_state->adjusted_mode.clock;
+
+ asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
+ }
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
mstc->port,
asyh->dp.pbn);
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 8c92374afcf2..a835cebb6d90 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -475,6 +475,47 @@ nouveau_svm_fault_cache(struct nouveau_svm *svm,
fault->inst, fault->addr, fault->access);
}
+static inline bool
+nouveau_range_done(struct hmm_range *range)
+{
+ bool ret = hmm_range_valid(range);
+
+ hmm_range_unregister(range);
+ return ret;
+}
+
+static int
+nouveau_range_fault(struct hmm_mirror *mirror, struct hmm_range *range)
+{
+ long ret;
+
+ range->default_flags = 0;
+ range->pfn_flags_mask = -1UL;
+
+ ret = hmm_range_register(range, mirror,
+ range->start, range->end,
+ PAGE_SHIFT);
+ if (ret) {
+ up_read(&range->vma->vm_mm->mmap_sem);
+ return (int)ret;
+ }
+
+ if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
+ up_read(&range->vma->vm_mm->mmap_sem);
+ return -EAGAIN;
+ }
+
+ ret = hmm_range_fault(range, true);
+ if (ret <= 0) {
+ if (ret == 0)
+ ret = -EBUSY;
+ up_read(&range->vma->vm_mm->mmap_sem);
+ hmm_range_unregister(range);
+ return ret;
+ }
+ return 0;
+}
+
static int
nouveau_svm_fault(struct nvif_notify *notify)
{
@@ -649,10 +690,10 @@ nouveau_svm_fault(struct nvif_notify *notify)
range.values = nouveau_svm_pfn_values;
range.pfn_shift = NVIF_VMM_PFNMAP_V0_ADDR_SHIFT;
again:
- ret = hmm_vma_fault(&svmm->mirror, &range, true);
+ ret = nouveau_range_fault(&svmm->mirror, &range);
if (ret == 0) {
mutex_lock(&svmm->mutex);
- if (!hmm_vma_range_done(&range)) {
+ if (!nouveau_range_done(&range)) {
mutex_unlock(&svmm->mutex);
goto again;
}
@@ -666,8 +707,8 @@ again:
NULL);
svmm->vmm->vmm.object.client->super = false;
mutex_unlock(&svmm->mutex);
+ up_read(&svmm->mm->mmap_sem);
}
- up_read(&svmm->mm->mmap_sem);
/* Cancel any faults in the window whose pages didn't manage
* to keep their valid bit, or stay writeable when required.
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
index b4e7404fe660..a11637b0f6cc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
@@ -40,8 +40,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
u8 *ptr = msg->buf;
while (remaining) {
- u8 cnt = (remaining > 16) ? 16 : remaining;
- u8 cmd;
+ u8 cnt, retries, cmd;
if (msg->flags & I2C_M_RD)
cmd = 1;
@@ -51,10 +50,19 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (mcnt || remaining > 16)
cmd |= 4; /* MOT */
- ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt);
- if (ret < 0) {
- nvkm_i2c_aux_release(aux);
- return ret;
+ for (retries = 0, cnt = 0;
+ retries < 32 && !cnt;
+ retries++) {
+ cnt = min_t(u8, remaining, 16);
+ ret = aux->func->xfer(aux, true, cmd,
+ msg->addr, ptr, &cnt);
+ if (ret < 0)
+ goto out;
+ }
+ if (!cnt) {
+ AUX_TRACE(aux, "no data after 32 retries");
+ ret = -EIO;
+ goto out;
}
ptr += cnt;
@@ -64,8 +72,10 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
msg++;
}
+ ret = num;
+out:
nvkm_i2c_aux_release(aux);
- return num;
+ return ret;
}
static u32
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
index 84a2f243ed9b..4695f1c8e33f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
@@ -190,6 +190,9 @@ MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/ucode_load.bin");
@@ -210,6 +213,9 @@ MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin");
@@ -230,6 +236,9 @@ MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin");
@@ -250,3 +259,6 @@ MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin");
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index de0f882f0f7b..14b41de44ebc 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -4,6 +4,7 @@
* Author: Archit Taneja <archit@ti.com>
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -20,7 +21,8 @@ int omapdss_device_init_output(struct omap_dss_device *out)
{
struct device_node *remote_node;
- remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
+ remote_node = of_graph_get_remote_node(out->dev->of_node,
+ ffs(out->of_ports) - 1, 0);
if (!remote_node) {
dev_dbg(out->dev, "failed to find video sink\n");
return 0;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 288c59dae56a..1bad0a2cc5c6 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -669,7 +669,7 @@ static int pdev_probe(struct platform_device *pdev)
if (omapdss_is_initialized() == false)
return -EPROBE_DEFER;
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "Failed to set the DMA mask\n");
return ret;
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 92ac995dd9c6..6e8145c36e93 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -222,7 +222,7 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo)
size_t unmapped_page;
size_t pgsize = get_pgsize(iova, len - unmapped_len);
- unmapped_page = ops->unmap(ops, iova, pgsize);
+ unmapped_page = ops->unmap(ops, iova, pgsize, NULL);
if (!unmapped_page)
break;
@@ -247,20 +247,28 @@ static void mmu_tlb_inv_context_s1(void *cookie)
mmu_hw_do_operation(pfdev, 0, 0, ~0UL, AS_COMMAND_FLUSH_MEM);
}
-static void mmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
-{}
-
static void mmu_tlb_sync_context(void *cookie)
{
//struct panfrost_device *pfdev = cookie;
// TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X
}
-static const struct iommu_gather_ops mmu_tlb_ops = {
+static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule,
+ void *cookie)
+{
+ mmu_tlb_sync_context(cookie);
+}
+
+static void mmu_tlb_flush_leaf(unsigned long iova, size_t size, size_t granule,
+ void *cookie)
+{
+ mmu_tlb_sync_context(cookie);
+}
+
+static const struct iommu_flush_ops mmu_tlb_ops = {
.tlb_flush_all = mmu_tlb_inv_context_s1,
- .tlb_add_flush = mmu_tlb_inv_range_nosync,
- .tlb_sync = mmu_tlb_sync_context,
+ .tlb_flush_walk = mmu_tlb_flush_walk,
+ .tlb_flush_leaf = mmu_tlb_flush_leaf,
};
static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index f33e349c4ec5..952201c6d821 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -59,6 +59,11 @@ module_param_named(num_heads, qxl_num_crtc, int, 0400);
static struct drm_driver qxl_driver;
static struct pci_driver qxl_pci_driver;
+static bool is_vga(struct pci_dev *pdev)
+{
+ return pdev->class == PCI_CLASS_DISPLAY_VGA << 8;
+}
+
static int
qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -83,9 +88,17 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto disable_pci;
+ if (is_vga(pdev)) {
+ ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO);
+ if (ret) {
+ DRM_ERROR("can't get legacy vga ioports\n");
+ goto disable_pci;
+ }
+ }
+
ret = qxl_device_init(qdev, &qxl_driver, pdev);
if (ret)
- goto disable_pci;
+ goto put_vga;
ret = qxl_modeset_init(qdev);
if (ret)
@@ -105,6 +118,9 @@ modeset_cleanup:
qxl_modeset_fini(qdev);
unload:
qxl_device_fini(qdev);
+put_vga:
+ if (is_vga(pdev))
+ vga_put(pdev, VGA_RSRC_LEGACY_IO);
disable_pci:
pci_disable_device(pdev);
free_dev:
@@ -122,6 +138,8 @@ qxl_pci_remove(struct pci_dev *pdev)
qxl_modeset_fini(qdev);
qxl_device_fini(qdev);
+ if (is_vga(pdev))
+ vga_put(pdev, VGA_RSRC_LEGACY_IO);
dev->dev_private = NULL;
kfree(qdev);
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 1c62578590f4..082d02c84024 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -673,10 +673,8 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
/* Locate the companion LVDS encoder for dual-link operation, if any. */
companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
- if (!companion) {
- dev_err(dev, "Companion LVDS encoder not found\n");
- return -ENXIO;
- }
+ if (!companion)
+ return 0;
/*
* Sanity check: the companion encoder must have the same compatible
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 95e5c517a15f..9aae3d8e99ef 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -432,7 +432,7 @@ static int rockchip_dp_resume(struct device *dev)
static const struct dev_pm_ops rockchip_dp_pm_ops = {
#ifdef CONFIG_PM_SLEEP
- .suspend = rockchip_dp_suspend,
+ .suspend_late = rockchip_dp_suspend,
.resume_early = rockchip_dp_resume,
#endif
};
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 35ddbec1375a..671c90f34ede 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -95,7 +95,7 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity)
rmb(); /* for list_empty to work without lock */
if (list_empty(&entity->list) ||
- spsc_queue_peek(&entity->job_queue) == NULL)
+ spsc_queue_count(&entity->job_queue) == 0)
return true;
return false;
@@ -281,7 +281,7 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity)
/* Consumption of existing IBs wasn't completed. Forcefully
* remove them here.
*/
- if (spsc_queue_peek(&entity->job_queue)) {
+ if (spsc_queue_count(&entity->job_queue)) {
if (sched) {
/* Park the kernel for a moment to make sure it isn't processing
* our enity.
diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
index b45824ec7c8f..6d61a0eb5d64 100644
--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
@@ -9,6 +9,13 @@
#define cmdline_test(test) selftest(test, test)
+cmdline_test(drm_cmdline_test_force_d_only)
+cmdline_test(drm_cmdline_test_force_D_only_dvi)
+cmdline_test(drm_cmdline_test_force_D_only_hdmi)
+cmdline_test(drm_cmdline_test_force_D_only_not_digital)
+cmdline_test(drm_cmdline_test_force_e_only)
+cmdline_test(drm_cmdline_test_margin_only)
+cmdline_test(drm_cmdline_test_interlace_only)
cmdline_test(drm_cmdline_test_res)
cmdline_test(drm_cmdline_test_res_missing_x)
cmdline_test(drm_cmdline_test_res_missing_y)
diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
index 14c96edb13df..013de9d27c35 100644
--- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
@@ -17,6 +17,136 @@
static const struct drm_connector no_connector = {};
+static int drm_cmdline_test_force_e_only(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(!drm_mode_parse_command_line_for_connector("e",
+ &no_connector,
+ &mode));
+ FAIL_ON(mode.specified);
+ FAIL_ON(mode.refresh_specified);
+ FAIL_ON(mode.bpp_specified);
+
+ FAIL_ON(mode.rb);
+ FAIL_ON(mode.cvt);
+ FAIL_ON(mode.interlace);
+ FAIL_ON(mode.margins);
+ FAIL_ON(mode.force != DRM_FORCE_ON);
+
+ return 0;
+}
+
+static int drm_cmdline_test_force_D_only_not_digital(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+ &no_connector,
+ &mode));
+ FAIL_ON(mode.specified);
+ FAIL_ON(mode.refresh_specified);
+ FAIL_ON(mode.bpp_specified);
+
+ FAIL_ON(mode.rb);
+ FAIL_ON(mode.cvt);
+ FAIL_ON(mode.interlace);
+ FAIL_ON(mode.margins);
+ FAIL_ON(mode.force != DRM_FORCE_ON);
+
+ return 0;
+}
+
+static const struct drm_connector connector_hdmi = {
+ .connector_type = DRM_MODE_CONNECTOR_HDMIB,
+};
+
+static int drm_cmdline_test_force_D_only_hdmi(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+ &connector_hdmi,
+ &mode));
+ FAIL_ON(mode.specified);
+ FAIL_ON(mode.refresh_specified);
+ FAIL_ON(mode.bpp_specified);
+
+ FAIL_ON(mode.rb);
+ FAIL_ON(mode.cvt);
+ FAIL_ON(mode.interlace);
+ FAIL_ON(mode.margins);
+ FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
+
+ return 0;
+}
+
+static const struct drm_connector connector_dvi = {
+ .connector_type = DRM_MODE_CONNECTOR_DVII,
+};
+
+static int drm_cmdline_test_force_D_only_dvi(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+ &connector_dvi,
+ &mode));
+ FAIL_ON(mode.specified);
+ FAIL_ON(mode.refresh_specified);
+ FAIL_ON(mode.bpp_specified);
+
+ FAIL_ON(mode.rb);
+ FAIL_ON(mode.cvt);
+ FAIL_ON(mode.interlace);
+ FAIL_ON(mode.margins);
+ FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
+
+ return 0;
+}
+
+static int drm_cmdline_test_force_d_only(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(!drm_mode_parse_command_line_for_connector("d",
+ &no_connector,
+ &mode));
+ FAIL_ON(mode.specified);
+ FAIL_ON(mode.refresh_specified);
+ FAIL_ON(mode.bpp_specified);
+
+ FAIL_ON(mode.rb);
+ FAIL_ON(mode.cvt);
+ FAIL_ON(mode.interlace);
+ FAIL_ON(mode.margins);
+ FAIL_ON(mode.force != DRM_FORCE_OFF);
+
+ return 0;
+}
+
+static int drm_cmdline_test_margin_only(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(drm_mode_parse_command_line_for_connector("m",
+ &no_connector,
+ &mode));
+
+ return 0;
+}
+
+static int drm_cmdline_test_interlace_only(void *ignored)
+{
+ struct drm_cmdline_mode mode = { };
+
+ FAIL_ON(drm_mode_parse_command_line_for_connector("i",
+ &no_connector,
+ &mode));
+
+ return 0;
+}
+
static int drm_cmdline_test_res(void *ignored)
{
struct drm_cmdline_mode mode = { };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64c43ee6bd92..df0cc8f46d7b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -314,6 +314,7 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
/* R and B components are only 5 bits deep */
val |= SUN4I_TCON0_FRM_CTL_MODE_R;
val |= SUN4I_TCON0_FRM_CTL_MODE_B;
+ /* Fall through */
case MEDIA_BUS_FMT_RGB666_1X18:
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
/* Fall through: enable dithering */
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a1fc8b520985..b889ad3e86e1 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -993,6 +993,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
ret = sun6i_dsi_dcs_read(dsi, msg);
break;
}
+ /* Else, fall through */
default:
ret = -EINVAL;
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 274cb955e2e1..bdcaa4c7168c 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -126,8 +126,12 @@ int tegra_output_probe(struct tegra_output *output)
"nvidia,hpd-gpio", 0,
GPIOD_IN,
"HDMI hotplug detect");
- if (IS_ERR(output->hpd_gpio))
- return PTR_ERR(output->hpd_gpio);
+ if (IS_ERR(output->hpd_gpio)) {
+ if (PTR_ERR(output->hpd_gpio) != -ENOENT)
+ return PTR_ERR(output->hpd_gpio);
+
+ output->hpd_gpio = NULL;
+ }
if (output->hpd_gpio) {
err = gpiod_to_irq(output->hpd_gpio);
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index d594f7520b7b..7d78e6deac89 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -285,9 +285,13 @@ static int ttm_set_pages_caching(struct dma_pool *pool,
static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page)
{
+ unsigned long attrs = 0;
dma_addr_t dma = d_page->dma;
d_page->vaddr &= ~VADDR_FLAG_HUGE_POOL;
- dma_free_coherent(pool->dev, pool->size, (void *)d_page->vaddr, dma);
+ if (pool->type & IS_HUGE)
+ attrs = DMA_ATTR_NO_WARN;
+
+ dma_free_attrs(pool->dev, pool->size, (void *)d_page->vaddr, dma, attrs);
kfree(d_page);
d_page = NULL;
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index b2da31310d24..09b526518f5a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -204,6 +204,7 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
.interruptible = false,
.no_wait_gpu = false
};
+ size_t max_segment;
/* wtf swapping */
if (bo->pages)
@@ -215,8 +216,13 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
if (!bo->pages)
goto out;
- ret = sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
- nr_pages << PAGE_SHIFT, GFP_KERNEL);
+ max_segment = virtio_max_dma_size(qdev->vdev);
+ max_segment &= PAGE_MASK;
+ if (max_segment > SCATTERLIST_MAX_SEGMENT)
+ max_segment = SCATTERLIST_MAX_SEGMENT;
+ ret = __sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
+ nr_pages << PAGE_SHIFT,
+ max_segment, GFP_KERNEL);
if (ret)
goto out;
return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index e4e09d47c5c0..0c647be81ab0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -46,8 +46,6 @@
#define RETRIES 3
#define VMW_HYPERVISOR_MAGIC 0x564D5868
-#define VMW_HYPERVISOR_PORT 0x5658
-#define VMW_HYPERVISOR_HB_PORT 0x5659
#define VMW_PORT_CMD_MSG 30
#define VMW_PORT_CMD_HB_MSG 0
@@ -93,7 +91,7 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
(protocol | GUESTMSG_FLAG_COOKIE), si, di,
- VMW_HYPERVISOR_PORT,
+ 0,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
@@ -126,7 +124,7 @@ static int vmw_close_channel(struct rpc_channel *channel)
VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
0, si, di,
- (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
@@ -160,7 +158,8 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
VMW_PORT_HB_OUT(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
msg_len, si, di,
- VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16),
+ VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) |
+ VMWARE_HYPERVISOR_OUT,
VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di);
@@ -181,7 +180,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16),
word, si, di,
- VMW_HYPERVISOR_PORT | (channel->channel_id << 16),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
}
@@ -213,7 +212,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
VMW_PORT_HB_IN(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
reply_len, si, di,
- VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16),
+ VMWARE_HYPERVISOR_HB | (channel->channel_id << 16),
VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di);
@@ -230,7 +229,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16),
MESSAGE_STATUS_SUCCESS, si, di,
- VMW_HYPERVISOR_PORT | (channel->channel_id << 16),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
@@ -269,7 +268,7 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
VMW_PORT(VMW_PORT_CMD_SENDSIZE,
msg_len, si, di,
- VMW_HYPERVISOR_PORT | (channel->channel_id << 16),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
@@ -327,7 +326,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
VMW_PORT(VMW_PORT_CMD_RECVSIZE,
0, si, di,
- (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
@@ -353,7 +352,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
!!(HIGH_WORD(ecx) & MESSAGE_STATUS_HB));
if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) {
kfree(reply);
-
+ reply = NULL;
if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry. */
continue;
@@ -371,13 +370,13 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
MESSAGE_STATUS_SUCCESS, si, di,
- (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+ channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
kfree(reply);
-
+ reply = NULL;
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry. */
continue;
@@ -389,7 +388,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
break;
}
- if (retries == RETRIES)
+ if (!reply)
return -EINVAL;
*msg_len = reply_len;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h
index 4907e50fb20a..f685c7071dec 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h
@@ -32,6 +32,7 @@
#ifndef _VMWGFX_MSG_H
#define _VMWGFX_MSG_H
+#include <asm/vmware.h>
/**
* Hypervisor-specific bi-directional communication channel. Should never
@@ -44,7 +45,7 @@
* @in_ebx: [IN] Message Len, through EBX
* @in_si: [IN] Input argument through SI, set to 0 if not used
* @in_di: [IN] Input argument through DI, set ot 0 if not used
- * @port_num: [IN] port number + [channel id]
+ * @flags: [IN] hypercall flags + [channel id]
* @magic: [IN] hypervisor magic value
* @eax: [OUT] value of EAX register
* @ebx: [OUT] e.g. status from an HB message status command
@@ -54,10 +55,10 @@
* @di: [OUT]
*/
#define VMW_PORT(cmd, in_ebx, in_si, in_di, \
- port_num, magic, \
+ flags, magic, \
eax, ebx, ecx, edx, si, di) \
({ \
- asm volatile ("inl %%dx, %%eax;" : \
+ asm volatile (VMWARE_HYPERCALL : \
"=a"(eax), \
"=b"(ebx), \
"=c"(ecx), \
@@ -67,7 +68,7 @@
"a"(magic), \
"b"(in_ebx), \
"c"(cmd), \
- "d"(port_num), \
+ "d"(flags), \
"S"(in_si), \
"D"(in_di) : \
"memory"); \
@@ -85,7 +86,7 @@
* @in_ecx: [IN] Message Len, through ECX
* @in_si: [IN] Input argument through SI, set to 0 if not used
* @in_di: [IN] Input argument through DI, set to 0 if not used
- * @port_num: [IN] port number + [channel id]
+ * @flags: [IN] hypercall flags + [channel id]
* @magic: [IN] hypervisor magic value
* @bp: [IN]
* @eax: [OUT] value of EAX register
@@ -98,12 +99,12 @@
#ifdef __x86_64__
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- port_num, magic, bp, \
+ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
asm volatile ("push %%rbp;" \
"mov %12, %%rbp;" \
- "rep outsb;" \
+ VMWARE_HYPERCALL_HB_OUT \
"pop %%rbp;" : \
"=a"(eax), \
"=b"(ebx), \
@@ -114,7 +115,7 @@
"a"(magic), \
"b"(cmd), \
"c"(in_ecx), \
- "d"(port_num), \
+ "d"(flags), \
"S"(in_si), \
"D"(in_di), \
"r"(bp) : \
@@ -123,12 +124,12 @@
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- port_num, magic, bp, \
+ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
asm volatile ("push %%rbp;" \
"mov %12, %%rbp;" \
- "rep insb;" \
+ VMWARE_HYPERCALL_HB_IN \
"pop %%rbp" : \
"=a"(eax), \
"=b"(ebx), \
@@ -139,7 +140,7 @@
"a"(magic), \
"b"(cmd), \
"c"(in_ecx), \
- "d"(port_num), \
+ "d"(flags), \
"S"(in_si), \
"D"(in_di), \
"r"(bp) : \
@@ -157,13 +158,13 @@
* just pushed it.
*/
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- port_num, magic, bp, \
+ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
asm volatile ("push %12;" \
"push %%ebp;" \
"mov 0x04(%%esp), %%ebp;" \
- "rep outsb;" \
+ VMWARE_HYPERCALL_HB_OUT \
"pop %%ebp;" \
"add $0x04, %%esp;" : \
"=a"(eax), \
@@ -175,7 +176,7 @@
"a"(magic), \
"b"(cmd), \
"c"(in_ecx), \
- "d"(port_num), \
+ "d"(flags), \
"S"(in_si), \
"D"(in_di), \
"m"(bp) : \
@@ -184,13 +185,13 @@
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- port_num, magic, bp, \
+ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
asm volatile ("push %12;" \
"push %%ebp;" \
"mov 0x04(%%esp), %%ebp;" \
- "rep insb;" \
+ VMWARE_HYPERCALL_HB_IN \
"pop %%ebp;" \
"add $0x04, %%esp;" : \
"=a"(eax), \
@@ -202,7 +203,7 @@
"a"(magic), \
"b"(cmd), \
"c"(in_ecx), \
- "d"(port_num), \
+ "d"(flags), \
"S"(in_si), \
"D"(in_di), \
"m"(bp) : \
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
index 98bf694626f7..3a8c4a5971f7 100644
--- a/drivers/hid/hid-a4tech.c
+++ b/drivers/hid/hid-a4tech.c
@@ -23,12 +23,36 @@
#define A4_2WHEEL_MOUSE_HACK_7 0x01
#define A4_2WHEEL_MOUSE_HACK_B8 0x02
+#define A4_WHEEL_ORIENTATION (HID_UP_GENDESK | 0x000000b8)
+
struct a4tech_sc {
unsigned long quirks;
unsigned int hw_wheel;
__s32 delayed_value;
};
+static int a4_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+ if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8 &&
+ usage->hid == A4_WHEEL_ORIENTATION) {
+ /*
+ * We do not want to have this usage mapped to anything as it's
+ * nonstandard and doesn't really behave like an HID report.
+ * It's only selecting the orientation (vertical/horizontal) of
+ * the previous mouse wheel report. The input_events will be
+ * generated once both reports are recorded in a4_event().
+ */
+ return -1;
+ }
+
+ return 0;
+
+}
+
static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
@@ -52,8 +76,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
struct input_dev *input;
- if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
- !usage->type)
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
return 0;
input = field->hidinput->input;
@@ -64,7 +87,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
return 1;
}
- if (usage->hid == 0x000100b8) {
+ if (usage->hid == A4_WHEEL_ORIENTATION) {
input_event(input, EV_REL, value ? REL_HWHEEL :
REL_WHEEL, a4->delayed_value);
input_event(input, EV_REL, value ? REL_HWHEEL_HI_RES :
@@ -131,6 +154,7 @@ MODULE_DEVICE_TABLE(hid, a4_devices);
static struct hid_driver a4_driver = {
.name = "a4tech",
.id_table = a4_devices,
+ .input_mapping = a4_input_mapping,
.input_mapped = a4_input_mapped,
.event = a4_event,
.probe = a4_probe,
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 2310c96ccf4a..db1b55df0d13 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -1153,8 +1153,6 @@ static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
- cp2112_gpio_direction_input(gc, d->hwirq);
-
if (!dev->gpio_poll) {
dev->gpio_poll = true;
schedule_delayed_work(&dev->gpio_poll_worker, 0);
@@ -1204,6 +1202,12 @@ static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
return PTR_ERR(dev->desc[pin]);
}
+ ret = cp2112_gpio_direction_input(&dev->gc, pin);
+ if (ret < 0) {
+ dev_err(dev->gc.parent, "Failed to set GPIO to input dir\n");
+ goto err_desc;
+ }
+
ret = gpiochip_lock_as_irq(&dev->gc, pin);
if (ret) {
dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n");
diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c
index b3d502421b79..0a38e8e9bc78 100644
--- a/drivers/hid/hid-holtek-kbd.c
+++ b/drivers/hid/hid-holtek-kbd.c
@@ -123,9 +123,14 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
/* Locate the boot interface, to receive the LED change events */
struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
+ struct hid_device *boot_hid;
+ struct hid_input *boot_hid_input;
- struct hid_device *boot_hid = usb_get_intfdata(boot_interface);
- struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs,
+ if (unlikely(boot_interface == NULL))
+ return -ENODEV;
+
+ boot_hid = usb_get_intfdata(boot_interface);
+ boot_hid_input = list_first_entry(&boot_hid->inputs,
struct hid_input, list);
return boot_hid_input->input->event(boot_hid_input->input, type, code,
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0d695f8e1b2c..0a00be19f7a0 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -568,6 +568,7 @@
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A 0x094a
+#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641 0x0641
#define USB_VENDOR_ID_HUION 0x256c
#define USB_DEVICE_ID_HUION_TABLET 0x006e
@@ -768,7 +769,8 @@
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f
#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534
-#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING 0xc539
+#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED 0xc539
+#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
@@ -989,6 +991,7 @@
#define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
+#define USB_DEVICE_ID_SAITEK_X52 0x075c
#define USB_VENDOR_ID_SAMSUNG 0x0419
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 6196217a7d93..cc47f948c1d0 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1125,7 +1125,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
HID_REQ_SET_REPORT);
kfree(hidpp_report);
- return retval;
+ return (retval < 0) ? retval : 0;
}
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
@@ -1832,13 +1832,17 @@ static const struct hid_device_id logi_dj_receivers[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2),
.driver_data = recvr_type_hidpp},
- { /* Logitech gaming receiver (0xc539) */
+ { /* Logitech lightspeed receiver (0xc539) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
- USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING),
+ USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED),
.driver_data = recvr_type_gaming_hidpp},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
.driver_data = recvr_type_27mhz},
+ { /* Logitech powerplay receiver (0xc53a) */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY),
+ .driver_data = recvr_type_gaming_hidpp},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_S510_RECEIVER_2),
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index e3b6245bf4b2..0179f7ed77e5 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -3749,15 +3749,23 @@ static const struct hid_device_id hidpp_devices[] = {
{ L27MHZ_DEVICE(HID_ANY_ID) },
- { /* Logitech G403 Gaming Mouse over USB */
+ { /* Logitech G403 Wireless Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
- { /* Logitech G700 Gaming Mouse over USB */
- HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
+ { /* Logitech G703 Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
+ { /* Logitech G703 Hero Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC090) },
{ /* Logitech G900 Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC081) },
+ { /* Logitech G903 Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC086) },
+ { /* Logitech G903 Hero Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC091) },
{ /* Logitech G920 Wheel over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
+ { /* Logitech G Pro Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
{ /* MX5000 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 185a577c46f6..166f41f3173b 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -92,6 +92,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
@@ -141,6 +142,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 93942063b51b..49dd2d905c7f 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -585,10 +585,14 @@ static void sony_set_leds(struct sony_sc *sc);
static inline void sony_schedule_work(struct sony_sc *sc,
enum sony_worker which)
{
+ unsigned long flags;
+
switch (which) {
case SONY_WORKER_STATE:
- if (!sc->defer_initialization)
+ spin_lock_irqsave(&sc->lock, flags);
+ if (!sc->defer_initialization && sc->state_worker_initialized)
schedule_work(&sc->state_worker);
+ spin_unlock_irqrestore(&sc->lock, flags);
break;
case SONY_WORKER_HOTPLUG:
if (sc->hotplug_worker_initialized)
@@ -2558,13 +2562,18 @@ static inline void sony_init_output_report(struct sony_sc *sc,
static inline void sony_cancel_work_sync(struct sony_sc *sc)
{
+ unsigned long flags;
+
if (sc->hotplug_worker_initialized)
cancel_work_sync(&sc->hotplug_worker);
- if (sc->state_worker_initialized)
+ if (sc->state_worker_initialized) {
+ spin_lock_irqsave(&sc->lock, flags);
+ sc->state_worker_initialized = 0;
+ spin_unlock_irqrestore(&sc->lock, flags);
cancel_work_sync(&sc->state_worker);
+ }
}
-
static int sony_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index e12f2588ddeb..bdfc5ff3b2c5 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -22,6 +22,8 @@
#include "hid-ids.h"
+#define THRUSTMASTER_DEVICE_ID_2_IN_1_DT 0xb320
+
static const signed short ff_rumble[] = {
FF_RUMBLE,
-1
@@ -76,6 +78,7 @@ static int tmff_play(struct input_dev *dev, void *data,
struct hid_field *ff_field = tmff->ff_field;
int x, y;
int left, right; /* Rumbling */
+ int motor_swap;
switch (effect->type) {
case FF_CONSTANT:
@@ -100,6 +103,13 @@ static int tmff_play(struct input_dev *dev, void *data,
ff_field->logical_minimum,
ff_field->logical_maximum);
+ /* 2-in-1 strong motor is left */
+ if (hid->product == THRUSTMASTER_DEVICE_ID_2_IN_1_DT) {
+ motor_swap = left;
+ left = right;
+ right = motor_swap;
+ }
+
dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
ff_field->value[0] = left;
ff_field->value[1] = right;
@@ -226,6 +236,8 @@ static const struct hid_device_id tm_devices[] = {
.driver_data = (unsigned long)ff_rumble },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), /* FireStorm Dual Power 2 (and 3) */
.driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, THRUSTMASTER_DEVICE_ID_2_IN_1_DT), /* Dual Trigger 2-in-1 */
+ .driver_data = (unsigned long)ff_rumble },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323), /* Dual Trigger 3-in-1 (PC Mode) */
.driver_data = (unsigned long)ff_rumble },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324), /* Dual Trigger 3-in-1 (PS3 Mode) */
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index 1065692f90e2..5792a104000a 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -24,6 +24,7 @@
#define ICL_MOBILE_DEVICE_ID 0x34FC
#define SPT_H_DEVICE_ID 0xA135
#define CML_LP_DEVICE_ID 0x02FC
+#define EHL_Ax_DEVICE_ID 0x4BB3
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index aa80b4d3b740..279567baca3d 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -33,6 +33,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
{0, }
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 55b72573066b..4e11cc6fc34b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -284,6 +284,14 @@ static int hiddev_open(struct inode *inode, struct file *file)
spin_unlock_irq(&list->hiddev->list_lock);
mutex_lock(&hiddev->existancelock);
+ /*
+ * recheck exist with existance lock held to
+ * avoid opening a disconnected device
+ */
+ if (!list->hiddev->exist) {
+ res = -ENODEV;
+ goto bail_unlock;
+ }
if (!list->hiddev->open++)
if (list->hiddev->exist) {
struct hid_device *hid = hiddev->hid;
@@ -300,6 +308,10 @@ bail_normal_power:
hid_hw_power(hid, PM_HINT_NORMAL);
bail_unlock:
mutex_unlock(&hiddev->existancelock);
+
+ spin_lock_irq(&list->hiddev->list_lock);
+ list_del(&list->node);
+ spin_unlock_irq(&list->hiddev->list_lock);
bail:
file->private_data = NULL;
vfree(list);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 8fc36a28081b..1713235d28cb 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -533,14 +533,14 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
*/
buttons = (data[4] << 1) | (data[3] & 0x01);
} else if (features->type == CINTIQ_COMPANION_2) {
- /* d-pad right -> data[4] & 0x10
- * d-pad up -> data[4] & 0x20
- * d-pad left -> data[4] & 0x40
- * d-pad down -> data[4] & 0x80
- * d-pad center -> data[3] & 0x01
+ /* d-pad right -> data[2] & 0x10
+ * d-pad up -> data[2] & 0x20
+ * d-pad left -> data[2] & 0x40
+ * d-pad down -> data[2] & 0x80
+ * d-pad center -> data[1] & 0x01
*/
buttons = ((data[2] >> 4) << 7) |
- ((data[1] & 0x04) << 6) |
+ ((data[1] & 0x04) << 4) |
((data[2] & 0x0F) << 2) |
(data[1] & 0x03);
} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
@@ -846,6 +846,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
y >>= 1;
distance >>= 1;
}
+ if (features->type == INTUOSHT2)
+ distance = features->distance_max - distance;
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_DISTANCE, distance);
@@ -1059,7 +1061,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
input_report_key(input, BTN_BASE2, (data[11] & 0x02));
if (data[12] & 0x80)
- input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
+ input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f) - 1);
else
input_report_abs(input, ABS_WHEEL, 0);
@@ -1290,7 +1292,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
}
if (wacom->tool[0]) {
input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
- if (wacom->features.type == INTUOSP2_BT) {
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
input_report_abs(pen_input, ABS_DISTANCE,
range ? frame[13] : wacom->features.distance_max);
} else {
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 5f9505a087f6..23f358cb7f49 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -26,7 +26,7 @@
static unsigned long virt_to_hvpfn(void *addr)
{
- unsigned long paddr;
+ phys_addr_t paddr;
if (is_vmalloc_addr(addr))
paddr = page_to_phys(vmalloc_to_page(addr)) +
diff --git a/drivers/hv/hv_trace.h b/drivers/hv/hv_trace.h
index 999f80a63bff..e70783e33680 100644
--- a/drivers/hv/hv_trace.h
+++ b/drivers/hv/hv_trace.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM hyperv
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 362e70e9d145..50eaa1fd6e45 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -146,8 +146,6 @@ struct hv_context {
*/
u64 guestid;
- void *tsc_page;
-
struct hv_per_cpu_context __percpu *cpu_context;
/*
@@ -192,11 +190,11 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
u64 *requestid, bool raw);
/*
- * Maximum channels is determined by the size of the interrupt page
- * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
- * and the other is receive endpoint interrupt
+ * The Maximum number of channels (16348) is determined by the size of the
+ * interrupt page, which is HV_HYP_PAGE_SIZE. 1/2 of HV_HYP_PAGE_SIZE is to
+ * send endpoint interrupts, and the other is to receive endpoint interrupts.
*/
-#define MAX_NUM_CHANNELS ((PAGE_SIZE >> 1) << 3) /* 16348 channels */
+#define MAX_NUM_CHANNELS ((HV_HYP_PAGE_SIZE >> 1) << 3)
/* The value here must be in multiple of 32 */
/* TODO: Need to make this configurable */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 650dd71f9724..2ca5668bdb62 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -246,6 +246,16 @@ config SENSORS_ADT7475
This driver can also be built as a module. If so, the module
will be called adt7475.
+config SENSORS_AS370
+ tristate "Synaptics AS370 SoC hardware monitoring driver"
+ help
+ If you say yes here you get support for the PVT sensors of
+ the Synaptics AS370 SoC
+
+ This driver can also be built as a module. If so, the module
+ will be called as370-hwmon.
+
+
config SENSORS_ASC7621
tristate "Andigilog aSC7621"
depends on I2C
@@ -1382,8 +1392,8 @@ config SENSORS_SHTC1
tristate "Sensiron humidity and temperature sensors. SHTC1 and compat."
depends on I2C
help
- If you say yes here you get support for the Sensiron SHTC1 and SHTW1
- humidity and temperature sensors.
+ If you say yes here you get support for the Sensiron SHTC1, SHTW1,
+ and SHTC3 humidity and temperature sensors.
This driver can also be built as a module. If so, the module
will be called shtc1.
@@ -1570,16 +1580,6 @@ config SENSORS_ADC128D818
This driver can also be built as a module. If so, the module
will be called adc128d818.
-config SENSORS_ADS1015
- tristate "Texas Instruments ADS1015"
- depends on I2C
- help
- If you say yes here you get support for Texas Instruments
- ADS1015/ADS1115 12/16-bit 4-input ADC device.
-
- This driver can also be built as a module. If so, the module
- will be called ads1015.
-
config SENSORS_ADS7828
tristate "Texas Instruments ADS7828 and compatibles"
depends on I2C
@@ -1834,17 +1834,12 @@ config SENSORS_W83795
will be called w83795.
config SENSORS_W83795_FANCTRL
- bool "Include automatic fan control support (DANGEROUS)"
+ bool "Include automatic fan control support"
depends on SENSORS_W83795
help
If you say yes here, support for automatic fan speed control
will be included in the driver.
- This part of the code wasn't carefully reviewed and tested yet,
- so enabling this option is strongly discouraged on production
- servers. Only developers and testers should enable it for the
- time being.
-
Please also note that this option will create sysfs attribute
files which may change in the future, so you shouldn't rely
on them being stable.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 8db472ea04f0..c86ce4d3d36b 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
-obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o
obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o
obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o
@@ -48,6 +47,7 @@ obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
obj-$(CONFIG_SENSORS_ARM_SCMI) += scmi-hwmon.o
obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
+obj-$(CONFIG_SENSORS_AS370) += as370-hwmon.o
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 6ba1a08253f0..4cf25458f0b9 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -681,8 +681,8 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
if (resource->caps.flags & POWER_METER_CAN_CAP) {
if (!can_cap_in_hardware()) {
- dev_err(&resource->acpi_dev->dev,
- "Ignoring unsafe software power cap!\n");
+ dev_warn(&resource->acpi_dev->dev,
+ "Ignoring unsafe software power cap!\n");
goto skip_unsafe_cap;
}
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
deleted file mode 100644
index 3727a3762eb8..000000000000
--- a/drivers/hwmon/ads1015.c
+++ /dev/null
@@ -1,324 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC
- * (C) Copyright 2010
- * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
- *
- * Based on the ads7828 driver by Steve Hardy.
- *
- * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/of_device.h>
-#include <linux/of.h>
-
-#include <linux/platform_data/ads1015.h>
-
-/* ADS1015 registers */
-enum {
- ADS1015_CONVERSION = 0,
- ADS1015_CONFIG = 1,
-};
-
-/* PGA fullscale voltages in mV */
-static const unsigned int fullscale_table[8] = {
- 6144, 4096, 2048, 1024, 512, 256, 256, 256 };
-
-/* Data rates in samples per second */
-static const unsigned int data_rate_table_1015[8] = {
- 128, 250, 490, 920, 1600, 2400, 3300, 3300
-};
-
-static const unsigned int data_rate_table_1115[8] = {
- 8, 16, 32, 64, 128, 250, 475, 860
-};
-
-#define ADS1015_DEFAULT_CHANNELS 0xff
-#define ADS1015_DEFAULT_PGA 2
-#define ADS1015_DEFAULT_DATA_RATE 4
-
-enum ads1015_chips {
- ads1015,
- ads1115,
-};
-
-struct ads1015_data {
- struct device *hwmon_dev;
- struct mutex update_lock; /* mutex protect updates */
- struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
- enum ads1015_chips id;
-};
-
-static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
-{
- u16 config;
- struct ads1015_data *data = i2c_get_clientdata(client);
- unsigned int pga = data->channel_data[channel].pga;
- unsigned int data_rate = data->channel_data[channel].data_rate;
- unsigned int conversion_time_ms;
- const unsigned int * const rate_table = data->id == ads1115 ?
- data_rate_table_1115 : data_rate_table_1015;
- int res;
-
- mutex_lock(&data->update_lock);
-
- /* get channel parameters */
- res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
- if (res < 0)
- goto err_unlock;
- config = res;
- conversion_time_ms = DIV_ROUND_UP(1000, rate_table[data_rate]);
-
- /* setup and start single conversion */
- config &= 0x001f;
- config |= (1 << 15) | (1 << 8);
- config |= (channel & 0x0007) << 12;
- config |= (pga & 0x0007) << 9;
- config |= (data_rate & 0x0007) << 5;
-
- res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config);
- if (res < 0)
- goto err_unlock;
-
- /* wait until conversion finished */
- msleep(conversion_time_ms);
- res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
- if (res < 0)
- goto err_unlock;
- config = res;
- if (!(config & (1 << 15))) {
- /* conversion not finished in time */
- res = -EIO;
- goto err_unlock;
- }
-
- res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
-
-err_unlock:
- mutex_unlock(&data->update_lock);
- return res;
-}
-
-static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
- s16 reg)
-{
- struct ads1015_data *data = i2c_get_clientdata(client);
- unsigned int pga = data->channel_data[channel].pga;
- int fullscale = fullscale_table[pga];
- const int mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
-
- return DIV_ROUND_CLOSEST(reg * fullscale, mask);
-}
-
-/* sysfs callback function */
-static ssize_t in_show(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
- int res;
- int index = attr->index;
-
- res = ads1015_read_adc(client, index);
- if (res < 0)
- return res;
-
- return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res));
-}
-
-static const struct sensor_device_attribute ads1015_in[] = {
- SENSOR_ATTR_RO(in0_input, in, 0),
- SENSOR_ATTR_RO(in1_input, in, 1),
- SENSOR_ATTR_RO(in2_input, in, 2),
- SENSOR_ATTR_RO(in3_input, in, 3),
- SENSOR_ATTR_RO(in4_input, in, 4),
- SENSOR_ATTR_RO(in5_input, in, 5),
- SENSOR_ATTR_RO(in6_input, in, 6),
- SENSOR_ATTR_RO(in7_input, in, 7),
-};
-
-/*
- * Driver interface
- */
-
-static int ads1015_remove(struct i2c_client *client)
-{
- struct ads1015_data *data = i2c_get_clientdata(client);
- int k;
-
- hwmon_device_unregister(data->hwmon_dev);
- for (k = 0; k < ADS1015_CHANNELS; ++k)
- device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
- return 0;
-}
-
-#ifdef CONFIG_OF
-static int ads1015_get_channels_config_of(struct i2c_client *client)
-{
- struct ads1015_data *data = i2c_get_clientdata(client);
- struct device_node *node;
-
- if (!client->dev.of_node
- || !of_get_next_child(client->dev.of_node, NULL))
- return -EINVAL;
-
- for_each_child_of_node(client->dev.of_node, node) {
- u32 pval;
- unsigned int channel;
- unsigned int pga = ADS1015_DEFAULT_PGA;
- unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
-
- if (of_property_read_u32(node, "reg", &pval)) {
- dev_err(&client->dev, "invalid reg on %pOF\n", node);
- continue;
- }
-
- channel = pval;
- if (channel >= ADS1015_CHANNELS) {
- dev_err(&client->dev,
- "invalid channel index %d on %pOF\n",
- channel, node);
- continue;
- }
-
- if (!of_property_read_u32(node, "ti,gain", &pval)) {
- pga = pval;
- if (pga > 6) {
- dev_err(&client->dev, "invalid gain on %pOF\n",
- node);
- return -EINVAL;
- }
- }
-
- if (!of_property_read_u32(node, "ti,datarate", &pval)) {
- data_rate = pval;
- if (data_rate > 7) {
- dev_err(&client->dev,
- "invalid data_rate on %pOF\n", node);
- return -EINVAL;
- }
- }
-
- data->channel_data[channel].enabled = true;
- data->channel_data[channel].pga = pga;
- data->channel_data[channel].data_rate = data_rate;
- }
-
- return 0;
-}
-#endif
-
-static void ads1015_get_channels_config(struct i2c_client *client)
-{
- unsigned int k;
- struct ads1015_data *data = i2c_get_clientdata(client);
- struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
-
- /* prefer platform data */
- if (pdata) {
- memcpy(data->channel_data, pdata->channel_data,
- sizeof(data->channel_data));
- return;
- }
-
-#ifdef CONFIG_OF
- if (!ads1015_get_channels_config_of(client))
- return;
-#endif
-
- /* fallback on default configuration */
- for (k = 0; k < ADS1015_CHANNELS; ++k) {
- data->channel_data[k].enabled = true;
- data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
- data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE;
- }
-}
-
-static int ads1015_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct ads1015_data *data;
- int err;
- unsigned int k;
-
- data = devm_kzalloc(&client->dev, sizeof(struct ads1015_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- if (client->dev.of_node)
- data->id = (enum ads1015_chips)
- of_device_get_match_data(&client->dev);
- else
- data->id = id->driver_data;
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- /* build sysfs attribute group */
- ads1015_get_channels_config(client);
- for (k = 0; k < ADS1015_CHANNELS; ++k) {
- if (!data->channel_data[k].enabled)
- continue;
- err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
- if (err)
- goto exit_remove;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- for (k = 0; k < ADS1015_CHANNELS; ++k)
- device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
- return err;
-}
-
-static const struct i2c_device_id ads1015_id[] = {
- { "ads1015", ads1015},
- { "ads1115", ads1115},
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ads1015_id);
-
-static const struct of_device_id __maybe_unused ads1015_of_match[] = {
- {
- .compatible = "ti,ads1015",
- .data = (void *)ads1015
- },
- {
- .compatible = "ti,ads1115",
- .data = (void *)ads1115
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, ads1015_of_match);
-
-static struct i2c_driver ads1015_driver = {
- .driver = {
- .name = "ads1015",
- .of_match_table = of_match_ptr(ads1015_of_match),
- },
- .probe = ads1015_probe,
- .remove = ads1015_remove,
- .id_table = ads1015_id,
-};
-
-module_i2c_driver(ads1015_driver);
-
-MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
-MODULE_DESCRIPTION("ADS1015 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index c3c6031a7285..6c64d50c9aae 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -187,7 +187,7 @@ static const struct of_device_id __maybe_unused adt7475_of_match[] = {
MODULE_DEVICE_TABLE(of, adt7475_of_match);
struct adt7475_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock;
unsigned long measure_updated;
@@ -212,6 +212,7 @@ struct adt7475_data {
u8 vid;
u8 vrm;
+ const struct attribute_group *groups[9];
};
static struct i2c_driver adt7475_driver;
@@ -346,8 +347,8 @@ static ssize_t voltage_store(struct device *dev,
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned char reg;
long val;
@@ -440,8 +441,8 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned char reg = 0;
u8 out;
int temp;
@@ -542,8 +543,7 @@ static ssize_t temp_st_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
long val;
switch (sattr->index) {
@@ -570,8 +570,8 @@ static ssize_t temp_st_store(struct device *dev,
size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned char reg;
int shift, idx;
ulong val;
@@ -647,8 +647,8 @@ static ssize_t point2_show(struct device *dev, struct device_attribute *attr,
static ssize_t point2_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
int temp;
long val;
@@ -710,8 +710,8 @@ static ssize_t tach_store(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
if (kstrtoul(buf, 10, &val))
@@ -769,8 +769,8 @@ static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned char reg = 0;
long val;
@@ -818,8 +818,8 @@ static ssize_t stall_disable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+
u8 mask = BIT(5 + sattr->index);
return sprintf(buf, "%d\n", !!(data->enh_acoustics[0] & mask));
@@ -830,8 +830,8 @@ static ssize_t stall_disable_store(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
u8 mask = BIT(5 + sattr->index);
@@ -914,8 +914,8 @@ static ssize_t pwmchan_store(struct device *dev,
size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int r;
long val;
@@ -938,8 +938,8 @@ static ssize_t pwmctrl_store(struct device *dev,
size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int r;
long val;
@@ -982,8 +982,8 @@ static ssize_t pwmfreq_store(struct device *dev,
size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int out;
long val;
@@ -1022,8 +1022,8 @@ static ssize_t pwm_use_point2_pwm_at_crit_store(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
if (kstrtol(buf, 10, &val))
@@ -1342,26 +1342,6 @@ static int adt7475_detect(struct i2c_client *client,
return 0;
}
-static void adt7475_remove_files(struct i2c_client *client,
- struct adt7475_data *data)
-{
- sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
- if (data->has_fan4)
- sysfs_remove_group(&client->dev.kobj, &fan4_attr_group);
- if (data->has_pwm2)
- sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group);
- if (data->has_voltage & (1 << 0))
- sysfs_remove_group(&client->dev.kobj, &in0_attr_group);
- if (data->has_voltage & (1 << 3))
- sysfs_remove_group(&client->dev.kobj, &in3_attr_group);
- if (data->has_voltage & (1 << 4))
- sysfs_remove_group(&client->dev.kobj, &in4_attr_group);
- if (data->has_voltage & (1 << 5))
- sysfs_remove_group(&client->dev.kobj, &in5_attr_group);
- if (data->has_vid)
- sysfs_remove_group(&client->dev.kobj, &vid_attr_group);
-}
-
static int adt7475_update_limits(struct i2c_client *client)
{
struct adt7475_data *data = i2c_get_clientdata(client);
@@ -1489,7 +1469,8 @@ static int adt7475_probe(struct i2c_client *client,
};
struct adt7475_data *data;
- int i, ret = 0, revision;
+ struct device *hwmon_dev;
+ int i, ret = 0, revision, group_num = 0;
u8 config2, config3;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
@@ -1497,6 +1478,7 @@ static int adt7475_probe(struct i2c_client *client,
return -ENOMEM;
mutex_init(&data->lock);
+ data->client = client;
i2c_set_clientdata(client, data);
if (client->dev.of_node)
@@ -1590,52 +1572,40 @@ static int adt7475_probe(struct i2c_client *client,
break;
}
- ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group);
- if (ret)
- return ret;
+ data->groups[group_num++] = &adt7475_attr_group;
/* Features that can be disabled individually */
if (data->has_fan4) {
- ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &fan4_attr_group;
}
if (data->has_pwm2) {
- ret = sysfs_create_group(&client->dev.kobj, &pwm2_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &pwm2_attr_group;
}
if (data->has_voltage & (1 << 0)) {
- ret = sysfs_create_group(&client->dev.kobj, &in0_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &in0_attr_group;
}
if (data->has_voltage & (1 << 3)) {
- ret = sysfs_create_group(&client->dev.kobj, &in3_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &in3_attr_group;
}
if (data->has_voltage & (1 << 4)) {
- ret = sysfs_create_group(&client->dev.kobj, &in4_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &in4_attr_group;
}
if (data->has_voltage & (1 << 5)) {
- ret = sysfs_create_group(&client->dev.kobj, &in5_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num++] = &in5_attr_group;
}
if (data->has_vid) {
data->vrm = vid_which_vrm();
- ret = sysfs_create_group(&client->dev.kobj, &vid_attr_group);
- if (ret)
- goto eremove;
+ data->groups[group_num] = &vid_attr_group;
}
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto eremove;
+ /* register device with all the acquired attributes */
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ data->groups);
+
+ if (IS_ERR(hwmon_dev)) {
+ ret = PTR_ERR(hwmon_dev);
+ return ret;
}
dev_info(&client->dev, "%s device, revision %d\n",
@@ -1657,21 +1627,7 @@ static int adt7475_probe(struct i2c_client *client,
/* Limits and settings, should never change update more than once */
ret = adt7475_update_limits(client);
if (ret)
- goto eremove;
-
- return 0;
-
-eremove:
- adt7475_remove_files(client, data);
- return ret;
-}
-
-static int adt7475_remove(struct i2c_client *client)
-{
- struct adt7475_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- adt7475_remove_files(client, data);
+ return ret;
return 0;
}
@@ -1683,7 +1639,6 @@ static struct i2c_driver adt7475_driver = {
.of_match_table = of_match_ptr(adt7475_of_match),
},
.probe = adt7475_probe,
- .remove = adt7475_remove,
.id_table = adt7475_id,
.detect = adt7475_detect,
.address_list = normal_i2c,
@@ -1757,8 +1712,8 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
static int adt7475_update_measure(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u16 ext;
int i;
int ret;
@@ -1854,8 +1809,7 @@ static int adt7475_update_measure(struct device *dev)
static struct adt7475_data *adt7475_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7475_data *data = i2c_get_clientdata(client);
+ struct adt7475_data *data = dev_get_drvdata(dev);
int ret;
mutex_lock(&data->lock);
diff --git a/drivers/hwmon/as370-hwmon.c b/drivers/hwmon/as370-hwmon.c
new file mode 100644
index 000000000000..464244ba8d58
--- /dev/null
+++ b/drivers/hwmon/as370-hwmon.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Synaptics AS370 SoC Hardware Monitoring Driver
+ *
+ * Copyright (C) 2018 Synaptics Incorporated
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <linux/bitops.h>
+#include <linux/hwmon.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#define CTRL 0x0
+#define PD BIT(0)
+#define EN BIT(1)
+#define T_SEL BIT(2)
+#define V_SEL BIT(3)
+#define NMOS_SEL BIT(8)
+#define PMOS_SEL BIT(9)
+#define STS 0x4
+#define BN_MASK GENMASK(11, 0)
+#define EOC BIT(12)
+
+struct as370_hwmon {
+ void __iomem *base;
+};
+
+static void init_pvt(struct as370_hwmon *hwmon)
+{
+ u32 val;
+ void __iomem *addr = hwmon->base + CTRL;
+
+ val = PD;
+ writel_relaxed(val, addr);
+ val |= T_SEL;
+ writel_relaxed(val, addr);
+ val |= EN;
+ writel_relaxed(val, addr);
+ val &= ~PD;
+ writel_relaxed(val, addr);
+}
+
+static int as370_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *temp)
+{
+ int val;
+ struct as370_hwmon *hwmon = dev_get_drvdata(dev);
+
+ switch (attr) {
+ case hwmon_temp_input:
+ val = readl_relaxed(hwmon->base + STS) & BN_MASK;
+ *temp = DIV_ROUND_CLOSEST(val * 251802, 4096) - 85525;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static umode_t
+as370_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static const u32 as370_hwmon_temp_config[] = {
+ HWMON_T_INPUT,
+ 0
+};
+
+static const struct hwmon_channel_info as370_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = as370_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *as370_hwmon_info[] = {
+ &as370_hwmon_temp,
+ NULL
+};
+
+static const struct hwmon_ops as370_hwmon_ops = {
+ .is_visible = as370_hwmon_is_visible,
+ .read = as370_hwmon_read,
+};
+
+static const struct hwmon_chip_info as370_chip_info = {
+ .ops = &as370_hwmon_ops,
+ .info = as370_hwmon_info,
+};
+
+static int as370_hwmon_probe(struct platform_device *pdev)
+{
+ struct device *hwmon_dev;
+ struct as370_hwmon *hwmon;
+ struct device *dev = &pdev->dev;
+
+ hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ hwmon->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hwmon->base))
+ return PTR_ERR(hwmon->base);
+
+ init_pvt(hwmon);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev,
+ "as370",
+ hwmon,
+ &as370_chip_info,
+ NULL);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct of_device_id as370_hwmon_match[] = {
+ { .compatible = "syna,as370-hwmon" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, as370_hwmon_match);
+
+static struct platform_driver as370_hwmon_driver = {
+ .probe = as370_hwmon_probe,
+ .driver = {
+ .name = "as370-hwmon",
+ .of_match_table = as370_hwmon_match,
+ },
+};
+module_platform_driver(as370_hwmon_driver);
+
+MODULE_AUTHOR("Jisheng Zhang<jszhang@kernel.org>");
+MODULE_DESCRIPTION("Synaptics AS370 SoC hardware monitor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index c9fa84b25678..4c609e23a4ef 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -706,21 +706,21 @@ static int asb100_detect_subclients(struct i2c_client *client)
goto ERROR_SC_2;
}
- data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
- if (!data->lm75[0]) {
+ data->lm75[0] = i2c_new_dummy_device(adapter, sc_addr[0]);
+ if (IS_ERR(data->lm75[0])) {
dev_err(&client->dev,
"subclient %d registration at address 0x%x failed.\n",
1, sc_addr[0]);
- err = -ENOMEM;
+ err = PTR_ERR(data->lm75[0]);
goto ERROR_SC_2;
}
- data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
- if (!data->lm75[1]) {
+ data->lm75[1] = i2c_new_dummy_device(adapter, sc_addr[1]);
+ if (IS_ERR(data->lm75[1])) {
dev_err(&client->dev,
"subclient %d registration at address 0x%x failed.\n",
2, sc_addr[1]);
- err = -ENOMEM;
+ err = PTR_ERR(data->lm75[1]);
goto ERROR_SC_3;
}
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index fe6618e49dc4..d855c78fb8be 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -736,7 +736,7 @@ static int __init coretemp_init(void)
err = platform_driver_register(&coretemp_driver);
if (err)
- return err;
+ goto outzone;
err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online",
coretemp_cpu_online, coretemp_cpu_offline);
@@ -747,6 +747,7 @@ static int __init coretemp_init(void)
outdrv:
platform_driver_unregister(&coretemp_driver);
+outzone:
kfree(zone_devices);
return err;
}
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index f1c2d5faedf0..b85a125dd86f 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -44,12 +44,20 @@ static ssize_t iio_hwmon_read_val(struct device *dev,
int ret;
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
struct iio_hwmon_state *state = dev_get_drvdata(dev);
+ struct iio_channel *chan = &state->channels[sattr->index];
+ enum iio_chan_type type;
+
+ ret = iio_read_channel_processed(chan, &result);
+ if (ret < 0)
+ return ret;
- ret = iio_read_channel_processed(&state->channels[sattr->index],
- &result);
+ ret = iio_get_channel_type(chan, &type);
if (ret < 0)
return ret;
+ if (type == IIO_POWER)
+ result *= 1000; /* mili-Watts to micro-Watts conversion */
+
return sprintf(buf, "%d\n", result);
}
@@ -59,7 +67,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
struct iio_hwmon_state *st;
struct sensor_device_attribute *a;
int ret, i;
- int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1;
+ int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1, power_i = 1;
enum iio_chan_type type;
struct iio_channel *channels;
struct device *hwmon_dev;
@@ -114,6 +122,10 @@ static int iio_hwmon_probe(struct platform_device *pdev)
n = curr_i++;
prefix = "curr";
break;
+ case IIO_POWER:
+ n = power_i++;
+ prefix = "power";
+ break;
case IIO_HUMIDITYRELATIVE:
n = humidity_i++;
prefix = "humidity";
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index c77e89239dcd..5c1dddde193c 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -349,6 +349,7 @@ static const struct pci_device_id k10temp_id_table[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{}
};
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 4994c90c8929..f73bd4eceb28 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -10,10 +10,8 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/jiffies.h>
#include <linux/pci.h>
#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <asm/processor.h>
@@ -24,108 +22,18 @@
#define SEL_CORE 0x04
struct k8temp_data {
- struct device *hwmon_dev;
struct mutex update_lock;
- const char *name;
- char valid; /* zero until following fields are valid */
- unsigned long last_updated; /* in jiffies */
/* registers values */
u8 sensorsp; /* sensor presence bits - SEL_CORE, SEL_PLACE */
- u32 temp[2][2]; /* core, place */
u8 swap_core_select; /* meaning of SEL_CORE is inverted */
u32 temp_offset;
};
-static struct k8temp_data *k8temp_update_device(struct device *dev)
-{
- struct k8temp_data *data = dev_get_drvdata(dev);
- struct pci_dev *pdev = to_pci_dev(dev);
- u8 tmp;
-
- mutex_lock(&data->update_lock);
-
- if (!data->valid
- || time_after(jiffies, data->last_updated + HZ)) {
- pci_read_config_byte(pdev, REG_TEMP, &tmp);
- tmp &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]);
-
- if (data->sensorsp & SEL_PLACE) {
- tmp |= SEL_PLACE; /* Select sensor 1, core0 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[0][1]);
- }
-
- if (data->sensorsp & SEL_CORE) {
- tmp &= ~SEL_PLACE; /* Select sensor 0, core1 */
- tmp |= SEL_CORE;
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[1][0]);
-
- if (data->sensorsp & SEL_PLACE) {
- tmp |= SEL_PLACE; /* Select sensor 1, core1 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[1][1]);
- }
- }
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- mutex_unlock(&data->update_lock);
- return data;
-}
-
-/*
- * Sysfs stuff
- */
-
-static ssize_t name_show(struct device *dev, struct device_attribute
- *devattr, char *buf)
-{
- struct k8temp_data *data = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", data->name);
-}
-
-
-static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute_2 *attr =
- to_sensor_dev_attr_2(devattr);
- int core = attr->nr;
- int place = attr->index;
- int temp;
- struct k8temp_data *data = k8temp_update_device(dev);
-
- if (data->swap_core_select && (data->sensorsp & SEL_CORE))
- core = core ? 0 : 1;
-
- temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
-
- return sprintf(buf, "%d\n", temp);
-}
-
-/* core, place */
-
-static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, 0, 0);
-static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, 0, 1);
-static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, 1, 0);
-static SENSOR_DEVICE_ATTR_2_RO(temp4_input, temp, 1, 1);
-static DEVICE_ATTR_RO(name);
-
static const struct pci_device_id k8temp_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
{ 0 },
};
-
MODULE_DEVICE_TABLE(pci, k8temp_ids);
static int is_rev_g_desktop(u8 model)
@@ -159,14 +67,76 @@ static int is_rev_g_desktop(u8 model)
return 1;
}
+static umode_t
+k8temp_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct k8temp_data *data = drvdata;
+
+ if ((channel & 1) && !(data->sensorsp & SEL_PLACE))
+ return 0;
+
+ if ((channel & 2) && !(data->sensorsp & SEL_CORE))
+ return 0;
+
+ return 0444;
+}
+
+static int
+k8temp_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct k8temp_data *data = dev_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->parent);
+ int core, place;
+ u32 temp;
+ u8 tmp;
+
+ core = (channel >> 1) & 1;
+ place = channel & 1;
+
+ core ^= data->swap_core_select;
+
+ mutex_lock(&data->update_lock);
+ pci_read_config_byte(pdev, REG_TEMP, &tmp);
+ tmp &= ~(SEL_PLACE | SEL_CORE);
+ if (core)
+ tmp |= SEL_CORE;
+ if (place)
+ tmp |= SEL_PLACE;
+ pci_write_config_byte(pdev, REG_TEMP, tmp);
+ pci_read_config_dword(pdev, REG_TEMP, &temp);
+ mutex_unlock(&data->update_lock);
+
+ *val = TEMP_FROM_REG(temp) + data->temp_offset;
+
+ return 0;
+}
+
+static const struct hwmon_ops k8temp_ops = {
+ .is_visible = k8temp_is_visible,
+ .read = k8temp_read,
+};
+
+static const struct hwmon_channel_info *k8temp_info[] = {
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT, HWMON_T_INPUT, HWMON_T_INPUT, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info k8temp_chip_info = {
+ .ops = &k8temp_ops,
+ .info = k8temp_info,
+};
+
static int k8temp_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- int err;
u8 scfg;
u32 temp;
u8 model, stepping;
struct k8temp_data *data;
+ struct device *hwmon_dev;
data = devm_kzalloc(&pdev->dev, sizeof(struct k8temp_data), GFP_KERNEL);
if (!data)
@@ -231,86 +201,21 @@ static int k8temp_probe(struct pci_dev *pdev,
data->sensorsp &= ~SEL_CORE;
}
- data->name = "k8temp";
mutex_init(&data->update_lock);
- pci_set_drvdata(pdev, data);
-
- /* Register sysfs hooks */
- err = device_create_file(&pdev->dev,
- &sensor_dev_attr_temp1_input.dev_attr);
- if (err)
- goto exit_remove;
-
- /* sensor can be changed and reports something */
- if (data->sensorsp & SEL_PLACE) {
- err = device_create_file(&pdev->dev,
- &sensor_dev_attr_temp2_input.dev_attr);
- if (err)
- goto exit_remove;
- }
-
- /* core can be changed and reports something */
- if (data->sensorsp & SEL_CORE) {
- err = device_create_file(&pdev->dev,
- &sensor_dev_attr_temp3_input.dev_attr);
- if (err)
- goto exit_remove;
- if (data->sensorsp & SEL_PLACE) {
- err = device_create_file(&pdev->dev,
- &sensor_dev_attr_temp4_input.
- dev_attr);
- if (err)
- goto exit_remove;
- }
- }
-
- err = device_create_file(&pdev->dev, &dev_attr_name);
- if (err)
- goto exit_remove;
- data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
+ "k8temp",
+ data,
+ &k8temp_chip_info,
+ NULL);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp1_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp2_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp3_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp4_input.dev_attr);
- device_remove_file(&pdev->dev, &dev_attr_name);
- return err;
-}
-
-static void k8temp_remove(struct pci_dev *pdev)
-{
- struct k8temp_data *data = pci_get_drvdata(pdev);
-
- hwmon_device_unregister(data->hwmon_dev);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp1_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp2_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp3_input.dev_attr);
- device_remove_file(&pdev->dev,
- &sensor_dev_attr_temp4_input.dev_attr);
- device_remove_file(&pdev->dev, &dev_attr_name);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static struct pci_driver k8temp_driver = {
.name = "k8temp",
.id_table = k8temp_ids,
.probe = k8temp_probe,
- .remove = k8temp_remove,
};
module_pci_driver(k8temp_driver);
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 3fb9c0a2d6d0..5e6392294c03 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -16,9 +16,9 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
+#include <linux/util_macros.h>
#include "lm75.h"
-
/*
* This driver handles the LM75 and compatible digital temperature sensors.
*/
@@ -36,6 +36,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
max6626,
max31725,
mcp980x,
+ pct2075,
stds75,
stlm75,
tcn75,
@@ -50,6 +51,41 @@ enum lm75_type { /* keep sorted in alphabetical order */
tmp75c,
};
+/**
+ * struct lm75_params - lm75 configuration parameters.
+ * @set_mask: Bits to set in configuration register when configuring
+ * the chip.
+ * @clr_mask: Bits to clear in configuration register when configuring
+ * the chip.
+ * @default_resolution: Default number of bits to represent the temperature
+ * value.
+ * @resolution_limits: Limit register resolution. Optional. Should be set if
+ * the resolution of limit registers does not match the
+ * resolution of the temperature register.
+ * @resolutions: List of resolutions associated with sample times.
+ * Optional. Should be set if num_sample_times is larger
+ * than 1, and if the resolution changes with sample times.
+ * If set, number of entries must match num_sample_times.
+ * @default_sample_time:Sample time to be set by default.
+ * @num_sample_times: Number of possible sample times to be set. Optional.
+ * Should be set if the number of sample times is larger
+ * than one.
+ * @sample_times: All the possible sample times to be set. Mandatory if
+ * num_sample_times is larger than 1. If set, number of
+ * entries must match num_sample_times.
+ */
+
+struct lm75_params {
+ u8 set_mask;
+ u8 clr_mask;
+ u8 default_resolution;
+ u8 resolution_limits;
+ const u8 *resolutions;
+ unsigned int default_sample_time;
+ u8 num_sample_times;
+ const unsigned int *sample_times;
+};
+
/* Addresses scanned */
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
@@ -59,24 +95,231 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
#define LM75_REG_CONF 0x01
#define LM75_REG_HYST 0x02
#define LM75_REG_MAX 0x03
+#define PCT2075_REG_IDLE 0x04
/* Each client has this additional data */
struct lm75_data {
- struct i2c_client *client;
- struct regmap *regmap;
- u8 orig_conf;
- u8 resolution; /* In bits, between 9 and 16 */
- u8 resolution_limits;
- unsigned int sample_time; /* In ms */
+ struct i2c_client *client;
+ struct regmap *regmap;
+ u8 orig_conf;
+ u8 current_conf;
+ u8 resolution; /* In bits, 9 to 16 */
+ unsigned int sample_time; /* In ms */
+ enum lm75_type kind;
+ const struct lm75_params *params;
};
/*-----------------------------------------------------------------------*/
+static const u8 lm75_sample_set_masks[] = { 0 << 5, 1 << 5, 2 << 5, 3 << 5 };
+
+#define LM75_SAMPLE_CLEAR_MASK (3 << 5)
+
+/* The structure below stores the configuration values of the supported devices.
+ * In case of being supported multiple configurations, the default one must
+ * always be the first element of the array
+ */
+static const struct lm75_params device_params[] = {
+ [adt75] = {
+ .clr_mask = 1 << 5, /* not one-shot mode */
+ .default_resolution = 12,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ },
+ [ds1775] = {
+ .clr_mask = 3 << 5,
+ .set_mask = 2 << 5, /* 11-bit mode */
+ .default_resolution = 11,
+ .default_sample_time = 500,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 125, 250, 500, 1000 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [ds75] = {
+ .clr_mask = 3 << 5,
+ .set_mask = 2 << 5, /* 11-bit mode */
+ .default_resolution = 11,
+ .default_sample_time = 600,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 150, 300, 600, 1200 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [stds75] = {
+ .clr_mask = 3 << 5,
+ .set_mask = 2 << 5, /* 11-bit mode */
+ .default_resolution = 11,
+ .default_sample_time = 600,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 150, 300, 600, 1200 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [stlm75] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 6,
+ },
+ [ds7505] = {
+ .set_mask = 3 << 5, /* 12-bit mode*/
+ .default_resolution = 12,
+ .default_sample_time = 200,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 25, 50, 100, 200 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [g751] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ },
+ [lm75] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ },
+ [lm75a] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ },
+ [lm75b] = {
+ .default_resolution = 11,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ },
+ [max6625] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 7,
+ },
+ [max6626] = {
+ .default_resolution = 12,
+ .default_sample_time = MSEC_PER_SEC / 7,
+ .resolution_limits = 9,
+ },
+ [max31725] = {
+ .default_resolution = 16,
+ .default_sample_time = MSEC_PER_SEC / 20,
+ },
+ [tcn75] = {
+ .default_resolution = 9,
+ .default_sample_time = MSEC_PER_SEC / 18,
+ },
+ [pct2075] = {
+ .default_resolution = 11,
+ .default_sample_time = MSEC_PER_SEC / 10,
+ .num_sample_times = 31,
+ .sample_times = (unsigned int []){ 100, 200, 300, 400, 500, 600,
+ 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700,
+ 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700,
+ 2800, 2900, 3000, 3100 },
+ },
+ [mcp980x] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode */
+ .default_resolution = 12,
+ .resolution_limits = 9,
+ .default_sample_time = 240,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 30, 60, 120, 240 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp100] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode */
+ .default_resolution = 12,
+ .default_sample_time = 320,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 40, 80, 160, 320 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp101] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode */
+ .default_resolution = 12,
+ .default_sample_time = 320,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 40, 80, 160, 320 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp105] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = 220,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 28, 55, 110, 220 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp112] = {
+ .set_mask = 3 << 5, /* 8 samples / second */
+ .clr_mask = 1 << 7, /* no one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = 125,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 125, 250, 1000, 4000 },
+ },
+ [tmp175] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = 220,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 28, 55, 110, 220 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp275] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = 220,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 28, 55, 110, 220 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp75] = {
+ .set_mask = 3 << 5, /* 12-bit mode */
+ .clr_mask = 1 << 7, /* not one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = 220,
+ .num_sample_times = 4,
+ .sample_times = (unsigned int []){ 28, 55, 110, 220 },
+ .resolutions = (u8 []) {9, 10, 11, 12 },
+ },
+ [tmp75b] = { /* not one-shot mode, Conversion rate 37Hz */
+ .clr_mask = 1 << 7 | 3 << 5,
+ .default_resolution = 12,
+ .default_sample_time = MSEC_PER_SEC / 37,
+ .sample_times = (unsigned int []){ MSEC_PER_SEC / 37,
+ MSEC_PER_SEC / 18,
+ MSEC_PER_SEC / 9, MSEC_PER_SEC / 4 },
+ .num_sample_times = 4,
+ },
+ [tmp75c] = {
+ .clr_mask = 1 << 5, /*not one-shot mode*/
+ .default_resolution = 12,
+ .default_sample_time = MSEC_PER_SEC / 12,
+ }
+};
+
static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
{
return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8);
}
+static int lm75_write_config(struct lm75_data *data, u8 set_mask,
+ u8 clr_mask)
+{
+ u8 value;
+
+ clr_mask |= LM75_SHUTDOWN;
+ value = data->current_conf & ~clr_mask;
+ value |= set_mask;
+
+ if (data->current_conf != value) {
+ s32 err;
+
+ err = i2c_smbus_write_byte_data(data->client, LM75_REG_CONF,
+ value);
+ if (err)
+ return err;
+ data->current_conf = value;
+ }
+ return 0;
+}
+
static int lm75_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
@@ -120,16 +363,12 @@ static int lm75_read(struct device *dev, enum hwmon_sensor_types type,
return 0;
}
-static int lm75_write(struct device *dev, enum hwmon_sensor_types type,
- u32 attr, int channel, long temp)
+static int lm75_write_temp(struct device *dev, u32 attr, long temp)
{
struct lm75_data *data = dev_get_drvdata(dev);
u8 resolution;
int reg;
- if (type != hwmon_temp)
- return -EINVAL;
-
switch (attr) {
case hwmon_temp_max:
reg = LM75_REG_MAX;
@@ -145,8 +384,8 @@ static int lm75_write(struct device *dev, enum hwmon_sensor_types type,
* Resolution of limit registers is assumed to be the same as the
* temperature input register resolution unless given explicitly.
*/
- if (data->resolution_limits)
- resolution = data->resolution_limits;
+ if (data->params->resolution_limits)
+ resolution = data->params->resolution_limits;
else
resolution = data->resolution;
@@ -154,16 +393,88 @@ static int lm75_write(struct device *dev, enum hwmon_sensor_types type,
temp = DIV_ROUND_CLOSEST(temp << (resolution - 8),
1000) << (16 - resolution);
- return regmap_write(data->regmap, reg, temp);
+ return regmap_write(data->regmap, reg, (u16)temp);
+}
+
+static int lm75_update_interval(struct device *dev, long val)
+{
+ struct lm75_data *data = dev_get_drvdata(dev);
+ unsigned int reg;
+ u8 index;
+ s32 err;
+
+ index = find_closest(val, data->params->sample_times,
+ (int)data->params->num_sample_times);
+
+ switch (data->kind) {
+ default:
+ err = lm75_write_config(data, lm75_sample_set_masks[index],
+ LM75_SAMPLE_CLEAR_MASK);
+ if (err)
+ return err;
+
+ data->sample_time = data->params->sample_times[index];
+ if (data->params->resolutions)
+ data->resolution = data->params->resolutions[index];
+ break;
+ case tmp112:
+ err = regmap_read(data->regmap, LM75_REG_CONF, &reg);
+ if (err < 0)
+ return err;
+ reg &= ~0x00c0;
+ reg |= (3 - index) << 6;
+ err = regmap_write(data->regmap, LM75_REG_CONF, reg);
+ if (err < 0)
+ return err;
+ data->sample_time = data->params->sample_times[index];
+ break;
+ case pct2075:
+ err = i2c_smbus_write_byte_data(data->client, PCT2075_REG_IDLE,
+ index + 1);
+ if (err)
+ return err;
+ data->sample_time = data->params->sample_times[index];
+ break;
+ }
+ return 0;
+}
+
+static int lm75_write_chip(struct device *dev, u32 attr, long val)
+{
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return lm75_update_interval(dev, val);
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int lm75_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_chip:
+ return lm75_write_chip(dev, attr, val);
+ case hwmon_temp:
+ return lm75_write_temp(dev, attr, val);
+ default:
+ return -EINVAL;
+ }
+ return 0;
}
static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
+ const struct lm75_data *config_data = data;
+
switch (type) {
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
+ if (config_data->params->num_sample_times > 1)
+ return 0644;
return 0444;
}
break;
@@ -208,13 +519,13 @@ static bool lm75_is_writeable_reg(struct device *dev, unsigned int reg)
static bool lm75_is_volatile_reg(struct device *dev, unsigned int reg)
{
- return reg == LM75_REG_TEMP;
+ return reg == LM75_REG_TEMP || reg == LM75_REG_CONF;
}
static const struct regmap_config lm75_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
- .max_register = LM75_REG_MAX,
+ .max_register = PCT2075_REG_IDLE,
.writeable_reg = lm75_is_writeable_reg,
.volatile_reg = lm75_is_volatile_reg,
.val_format_endian = REGMAP_ENDIAN_BIG,
@@ -238,8 +549,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct device *hwmon_dev;
struct lm75_data *data;
int status, err;
- u8 set_mask, clr_mask;
- int new;
enum lm75_type kind;
if (client->dev.of_node)
@@ -256,6 +565,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -ENOMEM;
data->client = client;
+ data->kind = kind;
data->regmap = devm_regmap_init_i2c(client, &lm75_regmap_config);
if (IS_ERR(data->regmap))
@@ -264,113 +574,30 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* Set to LM75 resolution (9 bits, 1/2 degree C) and range.
* Then tweak to be more precise when appropriate.
*/
- set_mask = 0;
- clr_mask = LM75_SHUTDOWN; /* continuous conversions */
-
- switch (kind) {
- case adt75:
- clr_mask |= 1 << 5; /* not one-shot mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 8;
- break;
- case ds1775:
- case ds75:
- case stds75:
- clr_mask |= 3 << 5;
- set_mask |= 2 << 5; /* 11-bit mode */
- data->resolution = 11;
- data->sample_time = MSEC_PER_SEC;
- break;
- case stlm75:
- data->resolution = 9;
- data->sample_time = MSEC_PER_SEC / 5;
- break;
- case ds7505:
- set_mask |= 3 << 5; /* 12-bit mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- case g751:
- case lm75:
- case lm75a:
- data->resolution = 9;
- data->sample_time = MSEC_PER_SEC / 2;
- break;
- case lm75b:
- data->resolution = 11;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- case max6625:
- data->resolution = 9;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- case max6626:
- data->resolution = 12;
- data->resolution_limits = 9;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- case max31725:
- data->resolution = 16;
- data->sample_time = MSEC_PER_SEC / 8;
- break;
- case tcn75:
- data->resolution = 9;
- data->sample_time = MSEC_PER_SEC / 8;
- break;
- case mcp980x:
- data->resolution_limits = 9;
- /* fall through */
- case tmp100:
- case tmp101:
- set_mask |= 3 << 5; /* 12-bit mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC;
- clr_mask |= 1 << 7; /* not one-shot mode */
- break;
- case tmp112:
- set_mask |= 3 << 5; /* 12-bit mode */
- clr_mask |= 1 << 7; /* not one-shot mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- case tmp105:
- case tmp175:
- case tmp275:
- case tmp75:
- set_mask |= 3 << 5; /* 12-bit mode */
- clr_mask |= 1 << 7; /* not one-shot mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 2;
- break;
- case tmp75b: /* not one-shot mode, Conversion rate 37Hz */
- clr_mask |= 1 << 15 | 0x3 << 13;
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 37;
- break;
- case tmp75c:
- clr_mask |= 1 << 5; /* not one-shot mode */
- data->resolution = 12;
- data->sample_time = MSEC_PER_SEC / 4;
- break;
- }
- /* configure as specified */
+ data->params = &device_params[data->kind];
+
+ /* Save default sample time and resolution*/
+ data->sample_time = data->params->default_sample_time;
+ data->resolution = data->params->default_resolution;
+
+ /* Cache original configuration */
status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
if (status < 0) {
dev_dbg(dev, "Can't read config? %d\n", status);
return status;
}
data->orig_conf = status;
- new = status & ~clr_mask;
- new |= set_mask;
- if (status != new)
- i2c_smbus_write_byte_data(client, LM75_REG_CONF, new);
+ data->current_conf = status;
- err = devm_add_action_or_reset(dev, lm75_remove, data);
+ err = lm75_write_config(data, data->params->set_mask,
+ data->params->clr_mask);
if (err)
return err;
- dev_dbg(dev, "Config %02x\n", new);
+ err = devm_add_action_or_reset(dev, lm75_remove, data);
+ if (err)
+ return err;
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &lm75_chip_info,
@@ -397,6 +624,7 @@ static const struct i2c_device_id lm75_ids[] = {
{ "max31725", max31725, },
{ "max31726", max31725, },
{ "mcp980x", mcp980x, },
+ { "pct2075", pct2075, },
{ "stds75", stds75, },
{ "stlm75", stlm75, },
{ "tcn75", tcn75, },
@@ -467,6 +695,10 @@ static const struct of_device_id __maybe_unused lm75_of_match[] = {
.data = (void *)mcp980x
},
{
+ .compatible = "nxp,pct2075",
+ .data = (void *)pct2075
+ },
+ {
.compatible = "st,stds75",
.data = (void *)stds75
},
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
index f9431ad43ad3..53ff5051774c 100644
--- a/drivers/hwmon/ltc2990.c
+++ b/drivers/hwmon/ltc2990.c
@@ -13,7 +13,7 @@
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
#define LTC2990_STATUS 0x00
#define LTC2990_CONTROL 0x01
@@ -206,7 +206,6 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c,
int ret;
struct device *hwmon_dev;
struct ltc2990_data *data;
- struct device_node *of_node = i2c->dev.of_node;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
@@ -218,9 +217,10 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c,
data->i2c = i2c;
- if (of_node) {
- ret = of_property_read_u32_array(of_node, "lltc,meas-mode",
- data->mode, 2);
+ if (dev_fwnode(&i2c->dev)) {
+ ret = device_property_read_u32_array(&i2c->dev,
+ "lltc,meas-mode",
+ data->mode, 2);
if (ret < 0)
return ret;
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index e7dff5febe16..7efa6bfef060 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -20,6 +20,7 @@
*
* Chip #vin #fan #pwm #temp chip IDs man ID
* nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
+ * nct6116d 9 5 5 3+3 0xd280 0xc1 0x5ca3
* nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
* nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
* nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
@@ -58,12 +59,13 @@
#define USE_ALTERNATE
-enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
- nct6795, nct6796, nct6797, nct6798 };
+enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
+ nct6793, nct6795, nct6796, nct6797, nct6798 };
/* used to set data->name = nct6775_device_names[data->sio_kind] */
static const char * const nct6775_device_names[] = {
"nct6106",
+ "nct6116",
"nct6775",
"nct6776",
"nct6779",
@@ -78,6 +80,7 @@ static const char * const nct6775_device_names[] = {
static const char * const nct6775_sio_names[] __initconst = {
"NCT6106D",
+ "NCT6116D",
"NCT6775F",
"NCT6776D/F",
"NCT6779D",
@@ -115,6 +118,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
#define SIO_NCT6106_ID 0xc450
+#define SIO_NCT6116_ID 0xd280
#define SIO_NCT6775_ID 0xb470
#define SIO_NCT6776_ID 0xc330
#define SIO_NCT6779_ID 0xc560
@@ -825,10 +829,8 @@ static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4 };
static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
-static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
-static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
static const u16 NCT6106_REG_TEMP_SOURCE[] = {
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
@@ -852,7 +854,7 @@ static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
-static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
+static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b };
static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
@@ -896,6 +898,70 @@ static const u16 NCT6106_REG_TEMP_CRIT[32] = {
[12] = 0x205,
};
+/* NCT6112D/NCT6114D/NCT6116D specific data */
+
+static const u16 NCT6116_REG_FAN[] = { 0x20, 0x22, 0x24, 0x26, 0x28 };
+static const u16 NCT6116_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4, 0xe6, 0xe8 };
+static const u16 NCT6116_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0xf6, 0xf5 };
+static const u16 NCT6116_FAN_PULSE_SHIFT[] = { 0, 2, 4, 6, 6 };
+
+static const u16 NCT6116_REG_PWM[] = { 0x119, 0x129, 0x139, 0x199, 0x1a9 };
+static const u16 NCT6116_REG_FAN_MODE[] = { 0x113, 0x123, 0x133, 0x193, 0x1a3 };
+static const u16 NCT6116_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130, 0x190, 0x1a0 };
+static const u16 NCT6116_REG_TEMP_SOURCE[] = {
+ 0xb0, 0xb1, 0xb2 };
+
+static const u16 NCT6116_REG_CRITICAL_TEMP[] = {
+ 0x11a, 0x12a, 0x13a, 0x19a, 0x1aa };
+static const u16 NCT6116_REG_CRITICAL_TEMP_TOLERANCE[] = {
+ 0x11b, 0x12b, 0x13b, 0x19b, 0x1ab };
+
+static const u16 NCT6116_REG_CRITICAL_PWM_ENABLE[] = {
+ 0x11c, 0x12c, 0x13c, 0x19c, 0x1ac };
+static const u16 NCT6116_REG_CRITICAL_PWM[] = {
+ 0x11d, 0x12d, 0x13d, 0x19d, 0x1ad };
+
+static const u16 NCT6116_REG_FAN_STEP_UP_TIME[] = {
+ 0x114, 0x124, 0x134, 0x194, 0x1a4 };
+static const u16 NCT6116_REG_FAN_STEP_DOWN_TIME[] = {
+ 0x115, 0x125, 0x135, 0x195, 0x1a5 };
+static const u16 NCT6116_REG_FAN_STOP_OUTPUT[] = {
+ 0x116, 0x126, 0x136, 0x196, 0x1a6 };
+static const u16 NCT6116_REG_FAN_START_OUTPUT[] = {
+ 0x117, 0x127, 0x137, 0x197, 0x1a7 };
+static const u16 NCT6116_REG_FAN_STOP_TIME[] = {
+ 0x118, 0x128, 0x138, 0x198, 0x1a8 };
+static const u16 NCT6116_REG_TOLERANCE_H[] = {
+ 0x112, 0x122, 0x132, 0x192, 0x1a2 };
+
+static const u16 NCT6116_REG_TARGET[] = {
+ 0x111, 0x121, 0x131, 0x191, 0x1a1 };
+
+static const u16 NCT6116_REG_AUTO_TEMP[] = {
+ 0x160, 0x170, 0x180, 0x1d0, 0x1e0 };
+static const u16 NCT6116_REG_AUTO_PWM[] = {
+ 0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
+
+static const s8 NCT6116_ALARM_BITS[] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
+ 9, -1, -1, -1, -1, -1, -1, /* in8..in9 */
+ -1, /* unused */
+ 32, 33, 34, 35, 36, /* fan1..fan5 */
+ -1, -1, -1, /* unused */
+ 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
+ 48, -1 /* intrusion0, intrusion1 */
+};
+
+static const s8 NCT6116_BEEP_BITS[] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
+ 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
+ 32, /* global beep enable */
+ 24, 25, 26, 27, 28, /* fan1..fan5 */
+ -1, -1, -1, /* unused */
+ 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
+ 34, -1 /* intrusion0, intrusion1 */
+};
+
static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
{
if (mode == 0 && pwm == 255)
@@ -1294,6 +1360,11 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
reg == 0x111 || reg == 0x121 || reg == 0x131;
+ case nct6116:
+ return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
+ reg == 0x26 || reg == 0x28 || reg == 0xe0 || reg == 0xe2 ||
+ reg == 0xe4 || reg == 0xe6 || reg == 0xe8 || reg == 0x111 ||
+ reg == 0x121 || reg == 0x131 || reg == 0x191 || reg == 0x1a1;
case nct6775:
return (((reg & 0xff00) == 0x100 ||
(reg & 0xff00) == 0x200) &&
@@ -1673,6 +1744,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
data->auto_pwm[i][data->auto_pwm_num] = 0xff;
break;
case nct6106:
+ case nct6116:
case nct6779:
case nct6791:
case nct6792:
@@ -3109,6 +3181,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
case nct6776:
break; /* always enabled, nothing to do */
case nct6106:
+ case nct6116:
case nct6779:
case nct6791:
case nct6792:
@@ -3535,6 +3608,23 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
fan3pin = !(cr24 & 0x80);
pwm3pin = cr24 & 0x08;
+ } else if (data->kind == nct6116) {
+ int cr1a = superio_inb(sioreg, 0x1a);
+ int cr1b = superio_inb(sioreg, 0x1b);
+ int cr24 = superio_inb(sioreg, 0x24);
+ int cr2a = superio_inb(sioreg, 0x2a);
+ int cr2b = superio_inb(sioreg, 0x2b);
+ int cr2f = superio_inb(sioreg, 0x2f);
+
+ fan3pin = !(cr2b & 0x10);
+ fan4pin = (cr2b & 0x80) || // pin 1(2)
+ (!(cr2f & 0x10) && (cr1a & 0x04)); // pin 65(66)
+ fan5pin = (cr2b & 0x80) || // pin 126(127)
+ (!(cr1b & 0x03) && (cr2a & 0x02)); // pin 94(96)
+
+ pwm3pin = fan3pin && (cr24 & 0x08);
+ pwm4pin = fan4pin;
+ pwm5pin = fan5pin;
} else {
/*
* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,
@@ -3764,7 +3854,8 @@ static int nct6775_probe(struct platform_device *pdev)
data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
- data->REG_PWM[0] = NCT6106_REG_PWM;
+ data->REG_TOLERANCE_H = NCT6106_REG_TOLERANCE_H;
+ data->REG_PWM[0] = NCT6116_REG_PWM;
data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
@@ -3783,7 +3874,7 @@ static int nct6775_probe(struct platform_device *pdev)
data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
- data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
+ data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
@@ -3806,6 +3897,79 @@ static int nct6775_probe(struct platform_device *pdev)
reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
break;
+ case nct6116:
+ data->in_num = 9;
+ data->pwm_num = 3;
+ data->auto_pwm_num = 4;
+ data->temp_fixed_num = 3;
+ data->num_temp_alarms = 3;
+ data->num_temp_beeps = 3;
+
+ data->fan_from_reg = fan_from_reg13;
+ data->fan_from_reg_min = fan_from_reg13;
+
+ data->temp_label = nct6776_temp_label;
+ data->temp_mask = NCT6776_TEMP_MASK;
+ data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
+
+ data->REG_VBAT = NCT6106_REG_VBAT;
+ data->REG_DIODE = NCT6106_REG_DIODE;
+ data->DIODE_MASK = NCT6106_DIODE_MASK;
+ data->REG_VIN = NCT6106_REG_IN;
+ data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
+ data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
+ data->REG_TARGET = NCT6116_REG_TARGET;
+ data->REG_FAN = NCT6116_REG_FAN;
+ data->REG_FAN_MODE = NCT6116_REG_FAN_MODE;
+ data->REG_FAN_MIN = NCT6116_REG_FAN_MIN;
+ data->REG_FAN_PULSES = NCT6116_REG_FAN_PULSES;
+ data->FAN_PULSE_SHIFT = NCT6116_FAN_PULSE_SHIFT;
+ data->REG_FAN_TIME[0] = NCT6116_REG_FAN_STOP_TIME;
+ data->REG_FAN_TIME[1] = NCT6116_REG_FAN_STEP_UP_TIME;
+ data->REG_FAN_TIME[2] = NCT6116_REG_FAN_STEP_DOWN_TIME;
+ data->REG_TOLERANCE_H = NCT6116_REG_TOLERANCE_H;
+ data->REG_PWM[0] = NCT6116_REG_PWM;
+ data->REG_PWM[1] = NCT6116_REG_FAN_START_OUTPUT;
+ data->REG_PWM[2] = NCT6116_REG_FAN_STOP_OUTPUT;
+ data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
+ data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
+ data->REG_PWM_READ = NCT6106_REG_PWM_READ;
+ data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
+ data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
+ data->REG_AUTO_TEMP = NCT6116_REG_AUTO_TEMP;
+ data->REG_AUTO_PWM = NCT6116_REG_AUTO_PWM;
+ data->REG_CRITICAL_TEMP = NCT6116_REG_CRITICAL_TEMP;
+ data->REG_CRITICAL_TEMP_TOLERANCE
+ = NCT6116_REG_CRITICAL_TEMP_TOLERANCE;
+ data->REG_CRITICAL_PWM_ENABLE = NCT6116_REG_CRITICAL_PWM_ENABLE;
+ data->CRITICAL_PWM_ENABLE_MASK
+ = NCT6106_CRITICAL_PWM_ENABLE_MASK;
+ data->REG_CRITICAL_PWM = NCT6116_REG_CRITICAL_PWM;
+ data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
+ data->REG_TEMP_SOURCE = NCT6116_REG_TEMP_SOURCE;
+ data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
+ data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
+ data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
+ data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
+ data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
+ data->REG_ALARM = NCT6106_REG_ALARM;
+ data->ALARM_BITS = NCT6116_ALARM_BITS;
+ data->REG_BEEP = NCT6106_REG_BEEP;
+ data->BEEP_BITS = NCT6116_BEEP_BITS;
+
+ reg_temp = NCT6106_REG_TEMP;
+ reg_temp_mon = NCT6106_REG_TEMP_MON;
+ num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
+ num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
+ reg_temp_over = NCT6106_REG_TEMP_OVER;
+ reg_temp_hyst = NCT6106_REG_TEMP_HYST;
+ reg_temp_config = NCT6106_REG_TEMP_CONFIG;
+ reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
+ reg_temp_crit = NCT6106_REG_TEMP_CRIT;
+ reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
+ reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
+
+ break;
case nct6775:
data->in_num = 9;
data->pwm_num = 3;
@@ -4351,6 +4515,7 @@ static int nct6775_probe(struct platform_device *pdev)
data->have_vid = (cr2a & 0x60) == 0x40;
break;
case nct6106:
+ case nct6116:
case nct6779:
case nct6791:
case nct6792:
@@ -4380,6 +4545,7 @@ static int nct6775_probe(struct platform_device *pdev)
NCT6775_REG_CR_FAN_DEBOUNCE);
switch (data->kind) {
case nct6106:
+ case nct6116:
tmp |= 0xe0;
break;
case nct6775:
@@ -4575,6 +4741,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
case SIO_NCT6106_ID:
sio_data->kind = nct6106;
break;
+ case SIO_NCT6116_ID:
+ sio_data->kind = nct6116;
+ break;
case SIO_NCT6775_ID:
sio_data->kind = nct6775;
break;
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index ec7bcf8d7cd6..f3dd2a17bd42 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -704,7 +704,7 @@ static struct attribute *nct7802_in_attrs[] = {
&sensor_dev_attr_in3_alarm.dev_attr.attr,
&sensor_dev_attr_in3_beep.dev_attr.attr,
- &sensor_dev_attr_in4_input.dev_attr.attr, /* 17 */
+ &sensor_dev_attr_in4_input.dev_attr.attr, /* 16 */
&sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in4_max.dev_attr.attr,
&sensor_dev_attr_in4_alarm.dev_attr.attr,
@@ -730,9 +730,9 @@ static umode_t nct7802_in_is_visible(struct kobject *kobj,
if (index >= 6 && index < 11 && (reg & 0x03) != 0x03) /* VSEN1 */
return 0;
- if (index >= 11 && index < 17 && (reg & 0x0c) != 0x0c) /* VSEN2 */
+ if (index >= 11 && index < 16 && (reg & 0x0c) != 0x0c) /* VSEN2 */
return 0;
- if (index >= 17 && (reg & 0x30) != 0x30) /* VSEN3 */
+ if (index >= 16 && (reg & 0x30) != 0x30) /* VSEN3 */
return 0;
return attr->mode;
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
index 710c30562fc1..95b447cfa24c 100644
--- a/drivers/hwmon/nct7904.c
+++ b/drivers/hwmon/nct7904.c
@@ -46,10 +46,34 @@
#define DTS_T_CTRL1_REG 0x27
#define VT_ADC_MD_REG 0x2E
+#define VSEN1_HV_LL_REG 0x02 /* Bank 1; 2 regs (HV/LV) per sensor */
+#define VSEN1_LV_LL_REG 0x03 /* Bank 1; 2 regs (HV/LV) per sensor */
+#define VSEN1_HV_HL_REG 0x00 /* Bank 1; 2 regs (HV/LV) per sensor */
+#define VSEN1_LV_HL_REG 0x01 /* Bank 1; 2 regs (HV/LV) per sensor */
+#define SMI_STS1_REG 0xC1 /* Bank 0; SMI Status Register */
+#define SMI_STS3_REG 0xC3 /* Bank 0; SMI Status Register */
+#define SMI_STS5_REG 0xC5 /* Bank 0; SMI Status Register */
+#define SMI_STS7_REG 0xC7 /* Bank 0; SMI Status Register */
+#define SMI_STS8_REG 0xC8 /* Bank 0; SMI Status Register */
+
#define VSEN1_HV_REG 0x40 /* Bank 0; 2 regs (HV/LV) per sensor */
#define TEMP_CH1_HV_REG 0x42 /* Bank 0; same as VSEN2_HV */
#define LTD_HV_REG 0x62 /* Bank 0; 2 regs in VSEN range */
+#define LTD_HV_HL_REG 0x44 /* Bank 1; 1 reg for LTD */
+#define LTD_LV_HL_REG 0x45 /* Bank 1; 1 reg for LTD */
+#define LTD_HV_LL_REG 0x46 /* Bank 1; 1 reg for LTD */
+#define LTD_LV_LL_REG 0x47 /* Bank 1; 1 reg for LTD */
+#define TEMP_CH1_CH_REG 0x05 /* Bank 1; 1 reg for LTD */
+#define TEMP_CH1_W_REG 0x06 /* Bank 1; 1 reg for LTD */
+#define TEMP_CH1_WH_REG 0x07 /* Bank 1; 1 reg for LTD */
+#define TEMP_CH1_C_REG 0x04 /* Bank 1; 1 reg per sensor */
+#define DTS_T_CPU1_C_REG 0x90 /* Bank 1; 1 reg per sensor */
+#define DTS_T_CPU1_CH_REG 0x91 /* Bank 1; 1 reg per sensor */
+#define DTS_T_CPU1_W_REG 0x92 /* Bank 1; 1 reg per sensor */
+#define DTS_T_CPU1_WH_REG 0x93 /* Bank 1; 1 reg per sensor */
#define FANIN1_HV_REG 0x80 /* Bank 0; 2 regs (HV/LV) per sensor */
+#define FANIN1_HV_HL_REG 0x60 /* Bank 1; 2 regs (HV/LV) per sensor */
+#define FANIN1_LV_HL_REG 0x61 /* Bank 1; 2 regs (HV/LV) per sensor */
#define T_CPU1_HV_REG 0xA0 /* Bank 0; 2 regs (HV/LV) per sensor */
#define PRTS_REG 0x03 /* Bank 2 */
@@ -58,6 +82,8 @@
#define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */
#define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */
+#define ENABLE_TSI BIT(1)
+
static const unsigned short normal_i2c[] = {
0x2d, 0x2e, I2C_CLIENT_END
};
@@ -72,6 +98,7 @@ struct nct7904_data {
u8 fan_mode[FANCTL_MAX];
u8 enable_dts;
u8 has_dts;
+ u8 temp_mode; /* 0: TR mode, 1: TD mode */
};
/* Access functions */
@@ -170,6 +197,25 @@ static int nct7904_read_fan(struct device *dev, u32 attr, int channel,
rpm = 1350000 / cnt;
*val = rpm;
return 0;
+ case hwmon_fan_min:
+ ret = nct7904_read_reg16(data, BANK_1,
+ FANIN1_HV_HL_REG + channel * 2);
+ if (ret < 0)
+ return ret;
+ cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
+ if (cnt == 0x1fff)
+ rpm = 0;
+ else
+ rpm = 1350000 / cnt;
+ *val = rpm;
+ return 0;
+ case hwmon_fan_alarm:
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS5_REG + (channel >> 3));
+ if (ret < 0)
+ return ret;
+ *val = (ret >> (channel & 0x07)) & 1;
+ return 0;
default:
return -EOPNOTSUPP;
}
@@ -179,8 +225,20 @@ static umode_t nct7904_fan_is_visible(const void *_data, u32 attr, int channel)
{
const struct nct7904_data *data = _data;
- if (attr == hwmon_fan_input && data->fanin_mask & (1 << channel))
- return 0444;
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_alarm:
+ if (data->fanin_mask & (1 << channel))
+ return 0444;
+ break;
+ case hwmon_fan_min:
+ if (data->fanin_mask & (1 << channel))
+ return 0644;
+ break;
+ default:
+ break;
+ }
+
return 0;
}
@@ -211,6 +269,37 @@ static int nct7904_read_in(struct device *dev, u32 attr, int channel,
volt *= 6; /* 0.006V scale */
*val = volt;
return 0;
+ case hwmon_in_min:
+ ret = nct7904_read_reg16(data, BANK_1,
+ VSEN1_HV_LL_REG + index * 4);
+ if (ret < 0)
+ return ret;
+ volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
+ if (index < 14)
+ volt *= 2; /* 0.002V scale */
+ else
+ volt *= 6; /* 0.006V scale */
+ *val = volt;
+ return 0;
+ case hwmon_in_max:
+ ret = nct7904_read_reg16(data, BANK_1,
+ VSEN1_HV_HL_REG + index * 4);
+ if (ret < 0)
+ return ret;
+ volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
+ if (index < 14)
+ volt *= 2; /* 0.002V scale */
+ else
+ volt *= 6; /* 0.006V scale */
+ *val = volt;
+ return 0;
+ case hwmon_in_alarm:
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS1_REG + (index >> 3));
+ if (ret < 0)
+ return ret;
+ *val = (ret >> (index & 0x07)) & 1;
+ return 0;
default:
return -EOPNOTSUPP;
}
@@ -221,9 +310,20 @@ static umode_t nct7904_in_is_visible(const void *_data, u32 attr, int channel)
const struct nct7904_data *data = _data;
int index = nct7904_chan_to_index[channel];
- if (channel > 0 && attr == hwmon_in_input &&
- (data->vsen_mask & BIT(index)))
- return 0444;
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_alarm:
+ if (channel > 0 && (data->vsen_mask & BIT(index)))
+ return 0444;
+ break;
+ case hwmon_in_min:
+ case hwmon_in_max:
+ if (channel > 0 && (data->vsen_mask & BIT(index)))
+ return 0644;
+ break;
+ default:
+ break;
+ }
return 0;
}
@@ -233,6 +333,7 @@ static int nct7904_read_temp(struct device *dev, u32 attr, int channel,
{
struct nct7904_data *data = dev_get_drvdata(dev);
int ret, temp;
+ unsigned int reg1, reg2, reg3;
switch (attr) {
case hwmon_temp_input:
@@ -250,16 +351,106 @@ static int nct7904_read_temp(struct device *dev, u32 attr, int channel,
temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
*val = sign_extend32(temp, 10) * 125;
return 0;
+ case hwmon_temp_alarm:
+ if (channel == 4) {
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS3_REG);
+ if (ret < 0)
+ return ret;
+ *val = (ret >> 1) & 1;
+ } else if (channel < 4) {
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS1_REG);
+ if (ret < 0)
+ return ret;
+ *val = (ret >> (((channel * 2) + 1) & 0x07)) & 1;
+ } else {
+ if ((channel - 5) < 4) {
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS7_REG +
+ ((channel - 5) >> 3));
+ if (ret < 0)
+ return ret;
+ *val = (ret >> ((channel - 5) & 0x07)) & 1;
+ } else {
+ ret = nct7904_read_reg(data, BANK_0,
+ SMI_STS8_REG +
+ ((channel - 5) >> 3));
+ if (ret < 0)
+ return ret;
+ *val = (ret >> (((channel - 5) & 0x07) - 4))
+ & 1;
+ }
+ }
+ return 0;
+ case hwmon_temp_type:
+ if (channel < 5) {
+ if ((data->tcpu_mask >> channel) & 0x01) {
+ if ((data->temp_mode >> channel) & 0x01)
+ *val = 3; /* TD */
+ else
+ *val = 4; /* TR */
+ } else {
+ *val = 0;
+ }
+ } else {
+ if ((data->has_dts >> (channel - 5)) & 0x01) {
+ if (data->enable_dts & ENABLE_TSI)
+ *val = 5; /* TSI */
+ else
+ *val = 6; /* PECI */
+ } else {
+ *val = 0;
+ }
+ }
+ return 0;
+ case hwmon_temp_max:
+ reg1 = LTD_HV_LL_REG;
+ reg2 = TEMP_CH1_W_REG;
+ reg3 = DTS_T_CPU1_W_REG;
+ break;
+ case hwmon_temp_max_hyst:
+ reg1 = LTD_LV_LL_REG;
+ reg2 = TEMP_CH1_WH_REG;
+ reg3 = DTS_T_CPU1_WH_REG;
+ break;
+ case hwmon_temp_crit:
+ reg1 = LTD_HV_HL_REG;
+ reg2 = TEMP_CH1_C_REG;
+ reg3 = DTS_T_CPU1_C_REG;
+ break;
+ case hwmon_temp_crit_hyst:
+ reg1 = LTD_LV_HL_REG;
+ reg2 = TEMP_CH1_CH_REG;
+ reg3 = DTS_T_CPU1_CH_REG;
+ break;
default:
return -EOPNOTSUPP;
}
+
+ if (channel == 4)
+ ret = nct7904_read_reg(data, BANK_1, reg1);
+ else if (channel < 5)
+ ret = nct7904_read_reg(data, BANK_1,
+ reg2 + channel * 8);
+ else
+ ret = nct7904_read_reg(data, BANK_1,
+ reg3 + (channel - 5) * 4);
+
+ if (ret < 0)
+ return ret;
+ *val = ret * 1000;
+ return 0;
}
static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel)
{
const struct nct7904_data *data = _data;
- if (attr == hwmon_temp_input) {
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_alarm:
+ case hwmon_temp_type:
if (channel < 5) {
if (data->tcpu_mask & BIT(channel))
return 0444;
@@ -267,6 +458,21 @@ static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel)
if (data->has_dts & BIT(channel - 5))
return 0444;
}
+ break;
+ case hwmon_temp_max:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_crit:
+ case hwmon_temp_crit_hyst:
+ if (channel < 5) {
+ if (data->tcpu_mask & BIT(channel))
+ return 0644;
+ } else {
+ if (data->has_dts & BIT(channel - 5))
+ return 0644;
+ }
+ break;
+ default:
+ break;
}
return 0;
@@ -297,6 +503,137 @@ static int nct7904_read_pwm(struct device *dev, u32 attr, int channel,
}
}
+static int nct7904_write_temp(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct nct7904_data *data = dev_get_drvdata(dev);
+ int ret;
+ unsigned int reg1, reg2, reg3;
+
+ val = clamp_val(val / 1000, -128, 127);
+
+ switch (attr) {
+ case hwmon_temp_max:
+ reg1 = LTD_HV_LL_REG;
+ reg2 = TEMP_CH1_W_REG;
+ reg3 = DTS_T_CPU1_W_REG;
+ break;
+ case hwmon_temp_max_hyst:
+ reg1 = LTD_LV_LL_REG;
+ reg2 = TEMP_CH1_WH_REG;
+ reg3 = DTS_T_CPU1_WH_REG;
+ break;
+ case hwmon_temp_crit:
+ reg1 = LTD_HV_HL_REG;
+ reg2 = TEMP_CH1_C_REG;
+ reg3 = DTS_T_CPU1_C_REG;
+ break;
+ case hwmon_temp_crit_hyst:
+ reg1 = LTD_LV_HL_REG;
+ reg2 = TEMP_CH1_CH_REG;
+ reg3 = DTS_T_CPU1_CH_REG;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ if (channel == 4)
+ ret = nct7904_write_reg(data, BANK_1, reg1, val);
+ else if (channel < 5)
+ ret = nct7904_write_reg(data, BANK_1,
+ reg2 + channel * 8, val);
+ else
+ ret = nct7904_write_reg(data, BANK_1,
+ reg3 + (channel - 5) * 4, val);
+
+ return ret;
+}
+
+static int nct7904_write_fan(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct nct7904_data *data = dev_get_drvdata(dev);
+ int ret;
+ u8 tmp;
+
+ switch (attr) {
+ case hwmon_fan_min:
+ if (val <= 0)
+ return -EINVAL;
+
+ val = clamp_val(DIV_ROUND_CLOSEST(1350000, val), 1, 0x1fff);
+ tmp = (val >> 5) & 0xff;
+ ret = nct7904_write_reg(data, BANK_1,
+ FANIN1_HV_HL_REG + channel * 2, tmp);
+ if (ret < 0)
+ return ret;
+ tmp = val & 0x1f;
+ ret = nct7904_write_reg(data, BANK_1,
+ FANIN1_LV_HL_REG + channel * 2, tmp);
+ return ret;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nct7904_write_in(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct nct7904_data *data = dev_get_drvdata(dev);
+ int ret, index, tmp;
+
+ index = nct7904_chan_to_index[channel];
+
+ if (index < 14)
+ val = val / 2; /* 0.002V scale */
+ else
+ val = val / 6; /* 0.006V scale */
+
+ val = clamp_val(val, 0, 0x7ff);
+
+ switch (attr) {
+ case hwmon_in_min:
+ tmp = nct7904_read_reg(data, BANK_1,
+ VSEN1_LV_LL_REG + index * 4);
+ if (tmp < 0)
+ return tmp;
+ tmp &= ~0x7;
+ tmp |= val & 0x7;
+ ret = nct7904_write_reg(data, BANK_1,
+ VSEN1_LV_LL_REG + index * 4, tmp);
+ if (ret < 0)
+ return ret;
+ tmp = nct7904_read_reg(data, BANK_1,
+ VSEN1_HV_LL_REG + index * 4);
+ if (tmp < 0)
+ return tmp;
+ tmp = (val >> 3) & 0xff;
+ ret = nct7904_write_reg(data, BANK_1,
+ VSEN1_HV_LL_REG + index * 4, tmp);
+ return ret;
+ case hwmon_in_max:
+ tmp = nct7904_read_reg(data, BANK_1,
+ VSEN1_LV_HL_REG + index * 4);
+ if (tmp < 0)
+ return tmp;
+ tmp &= ~0x7;
+ tmp |= val & 0x7;
+ ret = nct7904_write_reg(data, BANK_1,
+ VSEN1_LV_HL_REG + index * 4, tmp);
+ if (ret < 0)
+ return ret;
+ tmp = nct7904_read_reg(data, BANK_1,
+ VSEN1_HV_HL_REG + index * 4);
+ if (tmp < 0)
+ return tmp;
+ tmp = (val >> 3) & 0xff;
+ ret = nct7904_write_reg(data, BANK_1,
+ VSEN1_HV_HL_REG + index * 4, tmp);
+ return ret;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int nct7904_write_pwm(struct device *dev, u32 attr, int channel,
long val)
{
@@ -354,8 +691,14 @@ static int nct7904_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
switch (type) {
+ case hwmon_in:
+ return nct7904_write_in(dev, attr, channel, val);
+ case hwmon_fan:
+ return nct7904_write_fan(dev, attr, channel, val);
case hwmon_pwm:
return nct7904_write_pwm(dev, attr, channel, val);
+ case hwmon_temp:
+ return nct7904_write_temp(dev, attr, channel, val);
default:
return -EOPNOTSUPP;
}
@@ -404,51 +747,91 @@ static int nct7904_detect(struct i2c_client *client,
static const struct hwmon_channel_info *nct7904_info[] = {
HWMON_CHANNEL_INFO(in,
- HWMON_I_INPUT, /* dummy, skipped in is_visible */
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT,
- HWMON_I_INPUT),
+ /* dummy, skipped in is_visible */
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM,
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
+ HWMON_I_ALARM),
HWMON_CHANNEL_INFO(fan,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT,
- HWMON_F_INPUT),
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM),
HWMON_CHANNEL_INFO(pwm,
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
HWMON_CHANNEL_INFO(temp,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT,
- HWMON_T_INPUT),
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST),
NULL
};
@@ -530,11 +913,14 @@ static int nct7904_probe(struct i2c_client *client,
if (ret < 0)
return ret;
+ data->temp_mode = 0;
for (i = 0; i < 4; i++) {
val = (ret & (0x03 << i)) >> (i * 2);
bit = (1 << i);
if (val == 0)
data->tcpu_mask &= ~bit;
+ else if (val == 0x1 || val == 0x2)
+ data->temp_mode |= bit;
}
/* PECI */
@@ -557,7 +943,7 @@ static int nct7904_probe(struct i2c_client *client,
if (ret < 0)
return ret;
data->has_dts = ret & 0xF;
- if (data->enable_dts & 0x2) {
+ if (data->enable_dts & ENABLE_TSI) {
ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL1_REG);
if (ret < 0)
return ret;
diff --git a/drivers/hwmon/npcm750-pwm-fan.c b/drivers/hwmon/npcm750-pwm-fan.c
index 09aaefa6fdb8..11a28609da3c 100644
--- a/drivers/hwmon/npcm750-pwm-fan.c
+++ b/drivers/hwmon/npcm750-pwm-fan.c
@@ -967,10 +967,8 @@ static int npcm7xx_pwm_fan_probe(struct platform_device *pdev)
spin_lock_init(&data->fan_lock[i]);
data->fan_irq[i] = platform_get_irq(pdev, i);
- if (data->fan_irq[i] < 0) {
- dev_err(dev, "get IRQ fan%d failed\n", i);
+ if (data->fan_irq[i] < 0)
return data->fan_irq[i];
- }
sprintf(name, "NPCM7XX-FAN-MD%d", i);
ret = devm_request_irq(dev, data->fan_irq[i], npcm7xx_fan_isr,
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index a7d2b16dd702..30e18eb60da7 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -408,8 +408,10 @@ static ssize_t occ_show_power_1(struct device *dev,
static u64 occ_get_powr_avg(u64 *accum, u32 *samples)
{
- return div64_u64(get_unaligned_be64(accum) * 1000000ULL,
- get_unaligned_be32(samples));
+ u64 divisor = get_unaligned_be32(samples);
+
+ return (divisor == 0) ? 0 :
+ div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor);
}
static ssize_t occ_show_power_2(struct device *dev,
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index b6588483fae1..d62d69bb7e49 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -46,6 +46,15 @@ config SENSORS_IBM_CFFPS
This driver can also be built as a module. If so, the module will
be called ibm-cffps.
+config SENSORS_INSPUR_IPSPS
+ tristate "INSPUR Power System Power Supply"
+ help
+ If you say yes here you get hardware monitoring support for the INSPUR
+ Power System power supply.
+
+ This driver can also be built as a module. If so, the module will
+ be called inspur-ipsps.
+
config SENSORS_IR35221
tristate "Infineon IR35221"
help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index c950ea9a5d00..03bacfcfd660 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PMBUS) += pmbus_core.o
obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_IBM_CFFPS) += ibm-cffps.o
+obj-$(CONFIG_SENSORS_INSPUR_IPSPS) += inspur-ipsps.o
obj-$(CONFIG_SENSORS_IR35221) += ir35221.o
obj-$(CONFIG_SENSORS_IR38064) += ir38064.o
obj-$(CONFIG_SENSORS_IRPS5401) += irps5401.o
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index ee2ee9e3ffd7..d44745e498e7 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -12,6 +12,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of_device.h>
#include <linux/pmbus.h>
#include "pmbus.h"
@@ -20,8 +21,9 @@
#define CFFPS_PN_CMD 0x9B
#define CFFPS_SN_CMD 0x9E
#define CFFPS_CCIN_CMD 0xBD
-#define CFFPS_FW_CMD_START 0xFA
-#define CFFPS_FW_NUM_BYTES 4
+#define CFFPS_FW_CMD 0xFA
+#define CFFPS1_FW_NUM_BYTES 4
+#define CFFPS2_FW_NUM_WORDS 3
#define CFFPS_SYS_CONFIG_CMD 0xDA
#define CFFPS_INPUT_HISTORY_CMD 0xD6
@@ -52,6 +54,8 @@ enum {
CFFPS_DEBUGFS_NUM_ENTRIES
};
+enum versions { cffps1, cffps2 };
+
struct ibm_cffps_input_history {
struct mutex update_lock;
unsigned long last_update;
@@ -61,6 +65,7 @@ struct ibm_cffps_input_history {
};
struct ibm_cffps {
+ enum versions version;
struct i2c_client *client;
struct ibm_cffps_input_history input_history;
@@ -132,6 +137,8 @@ static ssize_t ibm_cffps_debugfs_op(struct file *file, char __user *buf,
struct ibm_cffps *psu = to_psu(idxp, idx);
char data[I2C_SMBUS_BLOCK_MAX] = { 0 };
+ pmbus_set_page(psu->client, 0);
+
switch (idx) {
case CFFPS_DEBUGFS_INPUT_HISTORY:
return ibm_cffps_read_input_history(psu, buf, count, ppos);
@@ -152,16 +159,36 @@ static ssize_t ibm_cffps_debugfs_op(struct file *file, char __user *buf,
rc = snprintf(data, 5, "%04X", rc);
goto done;
case CFFPS_DEBUGFS_FW:
- for (i = 0; i < CFFPS_FW_NUM_BYTES; ++i) {
- rc = i2c_smbus_read_byte_data(psu->client,
- CFFPS_FW_CMD_START + i);
- if (rc < 0)
- return rc;
+ switch (psu->version) {
+ case cffps1:
+ for (i = 0; i < CFFPS1_FW_NUM_BYTES; ++i) {
+ rc = i2c_smbus_read_byte_data(psu->client,
+ CFFPS_FW_CMD +
+ i);
+ if (rc < 0)
+ return rc;
+
+ snprintf(&data[i * 2], 3, "%02X", rc);
+ }
- snprintf(&data[i * 2], 3, "%02X", rc);
- }
+ rc = i * 2;
+ break;
+ case cffps2:
+ for (i = 0; i < CFFPS2_FW_NUM_WORDS; ++i) {
+ rc = i2c_smbus_read_word_data(psu->client,
+ CFFPS_FW_CMD +
+ i);
+ if (rc < 0)
+ return rc;
+
+ snprintf(&data[i * 4], 5, "%04X", rc);
+ }
- rc = i * 2;
+ rc = i * 4;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
goto done;
default:
return -EINVAL;
@@ -279,6 +306,8 @@ static void ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
psu->led_state = CFFPS_LED_ON;
}
+ pmbus_set_page(psu->client, 0);
+
rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
psu->led_state);
if (rc < 0)
@@ -299,6 +328,8 @@ static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev,
if (led_cdev->brightness == LED_OFF)
return 0;
+ pmbus_set_page(psu->client, 0);
+
rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
CFFPS_LED_BLINK);
if (rc < 0)
@@ -328,15 +359,32 @@ static void ibm_cffps_create_led_class(struct ibm_cffps *psu)
dev_warn(dev, "failed to register led class: %d\n", rc);
}
-static struct pmbus_driver_info ibm_cffps_info = {
- .pages = 1,
- .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
- PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP |
- PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_VOUT |
- PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT |
- PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_FAN12,
- .read_byte_data = ibm_cffps_read_byte_data,
- .read_word_data = ibm_cffps_read_word_data,
+static struct pmbus_driver_info ibm_cffps_info[] = {
+ [cffps1] = {
+ .pages = 1,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+ PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP |
+ PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_FAN12,
+ .read_byte_data = ibm_cffps_read_byte_data,
+ .read_word_data = ibm_cffps_read_word_data,
+ },
+ [cffps2] = {
+ .pages = 2,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+ PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP |
+ PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_FAN12,
+ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT,
+ .read_byte_data = ibm_cffps_read_byte_data,
+ .read_word_data = ibm_cffps_read_word_data,
+ },
};
static struct pmbus_platform_data ibm_cffps_pdata = {
@@ -347,12 +395,21 @@ static int ibm_cffps_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int i, rc;
+ enum versions vs;
struct dentry *debugfs;
struct dentry *ibm_cffps_dir;
struct ibm_cffps *psu;
+ const void *md = of_device_get_match_data(&client->dev);
+
+ if (md)
+ vs = (enum versions)md;
+ else if (id)
+ vs = (enum versions)id->driver_data;
+ else
+ vs = cffps1;
client->dev.platform_data = &ibm_cffps_pdata;
- rc = pmbus_do_probe(client, id, &ibm_cffps_info);
+ rc = pmbus_do_probe(client, id, &ibm_cffps_info[vs]);
if (rc)
return rc;
@@ -364,6 +421,7 @@ static int ibm_cffps_probe(struct i2c_client *client,
if (!psu)
return 0;
+ psu->version = vs;
psu->client = client;
mutex_init(&psu->input_history.update_lock);
psu->input_history.last_update = jiffies - HZ;
@@ -405,13 +463,21 @@ static int ibm_cffps_probe(struct i2c_client *client,
}
static const struct i2c_device_id ibm_cffps_id[] = {
- { "ibm_cffps1", 1 },
+ { "ibm_cffps1", cffps1 },
+ { "ibm_cffps2", cffps2 },
{}
};
MODULE_DEVICE_TABLE(i2c, ibm_cffps_id);
static const struct of_device_id ibm_cffps_of_match[] = {
- { .compatible = "ibm,cffps1" },
+ {
+ .compatible = "ibm,cffps1",
+ .data = (void *)cffps1
+ },
+ {
+ .compatible = "ibm,cffps2",
+ .data = (void *)cffps2
+ },
{}
};
MODULE_DEVICE_TABLE(of, ibm_cffps_of_match);
diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c
new file mode 100644
index 000000000000..42e01549184a
--- /dev/null
+++ b/drivers/hwmon/pmbus/inspur-ipsps.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2019 Inspur Corp.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pmbus.h>
+#include <linux/hwmon-sysfs.h>
+
+#include "pmbus.h"
+
+#define IPSPS_REG_VENDOR_ID 0x99
+#define IPSPS_REG_MODEL 0x9A
+#define IPSPS_REG_FW_VERSION 0x9B
+#define IPSPS_REG_PN 0x9C
+#define IPSPS_REG_SN 0x9E
+#define IPSPS_REG_HW_VERSION 0xB0
+#define IPSPS_REG_MODE 0xFC
+
+#define MODE_ACTIVE 0x55
+#define MODE_STANDBY 0x0E
+#define MODE_REDUNDANCY 0x00
+
+#define MODE_ACTIVE_STRING "active"
+#define MODE_STANDBY_STRING "standby"
+#define MODE_REDUNDANCY_STRING "redundancy"
+
+enum ipsps_index {
+ vendor,
+ model,
+ fw_version,
+ part_number,
+ serial_number,
+ hw_version,
+ mode,
+ num_regs,
+};
+
+static const u8 ipsps_regs[num_regs] = {
+ [vendor] = IPSPS_REG_VENDOR_ID,
+ [model] = IPSPS_REG_MODEL,
+ [fw_version] = IPSPS_REG_FW_VERSION,
+ [part_number] = IPSPS_REG_PN,
+ [serial_number] = IPSPS_REG_SN,
+ [hw_version] = IPSPS_REG_HW_VERSION,
+ [mode] = IPSPS_REG_MODE,
+};
+
+static ssize_t ipsps_string_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ u8 reg;
+ int rc;
+ char *p;
+ char data[I2C_SMBUS_BLOCK_MAX + 1];
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ reg = ipsps_regs[attr->index];
+ rc = i2c_smbus_read_block_data(client, reg, data);
+ if (rc < 0)
+ return rc;
+
+ /* filled with printable characters, ending with # */
+ p = memscan(data, '#', rc);
+ *p = '\0';
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", data);
+}
+
+static ssize_t ipsps_fw_version_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ u8 reg;
+ int rc;
+ u8 data[I2C_SMBUS_BLOCK_MAX] = { 0 };
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ reg = ipsps_regs[attr->index];
+ rc = i2c_smbus_read_block_data(client, reg, data);
+ if (rc < 0)
+ return rc;
+
+ if (rc != 6)
+ return -EPROTO;
+
+ return snprintf(buf, PAGE_SIZE, "%u.%02u%u-%u.%02u\n",
+ data[1], data[2]/* < 100 */, data[3]/*< 10*/,
+ data[4], data[5]/* < 100 */);
+}
+
+static ssize_t ipsps_mode_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ u8 reg;
+ int rc;
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ reg = ipsps_regs[attr->index];
+ rc = i2c_smbus_read_byte_data(client, reg);
+ if (rc < 0)
+ return rc;
+
+ switch (rc) {
+ case MODE_ACTIVE:
+ return snprintf(buf, PAGE_SIZE, "[%s] %s %s\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ case MODE_STANDBY:
+ return snprintf(buf, PAGE_SIZE, "%s [%s] %s\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ case MODE_REDUNDANCY:
+ return snprintf(buf, PAGE_SIZE, "%s %s [%s]\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ default:
+ return snprintf(buf, PAGE_SIZE, "unspecified\n");
+ }
+}
+
+static ssize_t ipsps_mode_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ u8 reg;
+ int rc;
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ reg = ipsps_regs[attr->index];
+ if (sysfs_streq(MODE_STANDBY_STRING, buf)) {
+ rc = i2c_smbus_write_byte_data(client, reg,
+ MODE_STANDBY);
+ if (rc < 0)
+ return rc;
+ return count;
+ } else if (sysfs_streq(MODE_ACTIVE_STRING, buf)) {
+ rc = i2c_smbus_write_byte_data(client, reg,
+ MODE_ACTIVE);
+ if (rc < 0)
+ return rc;
+ return count;
+ }
+
+ return -EINVAL;
+}
+
+static SENSOR_DEVICE_ATTR_RO(vendor, ipsps_string, vendor);
+static SENSOR_DEVICE_ATTR_RO(model, ipsps_string, model);
+static SENSOR_DEVICE_ATTR_RO(part_number, ipsps_string, part_number);
+static SENSOR_DEVICE_ATTR_RO(serial_number, ipsps_string, serial_number);
+static SENSOR_DEVICE_ATTR_RO(hw_version, ipsps_string, hw_version);
+static SENSOR_DEVICE_ATTR_RO(fw_version, ipsps_fw_version, fw_version);
+static SENSOR_DEVICE_ATTR_RW(mode, ipsps_mode, mode);
+
+static struct attribute *ipsps_attrs[] = {
+ &sensor_dev_attr_vendor.dev_attr.attr,
+ &sensor_dev_attr_model.dev_attr.attr,
+ &sensor_dev_attr_part_number.dev_attr.attr,
+ &sensor_dev_attr_serial_number.dev_attr.attr,
+ &sensor_dev_attr_hw_version.dev_attr.attr,
+ &sensor_dev_attr_fw_version.dev_attr.attr,
+ &sensor_dev_attr_mode.dev_attr.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(ipsps);
+
+static struct pmbus_driver_info ipsps_info = {
+ .pages = 1,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN |
+ PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
+ PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT |
+ PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_FAN12,
+ .groups = ipsps_groups,
+};
+
+static struct pmbus_platform_data ipsps_pdata = {
+ .flags = PMBUS_SKIP_STATUS_CHECK,
+};
+
+static int ipsps_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ client->dev.platform_data = &ipsps_pdata;
+ return pmbus_do_probe(client, id, &ipsps_info);
+}
+
+static const struct i2c_device_id ipsps_id[] = {
+ { "ipsps1", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ipsps_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id ipsps_of_match[] = {
+ { .compatible = "inspur,ipsps1" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ipsps_of_match);
+#endif
+
+static struct i2c_driver ipsps_driver = {
+ .driver = {
+ .name = "inspur-ipsps",
+ .of_match_table = of_match_ptr(ipsps_of_match),
+ },
+ .probe = ipsps_probe,
+ .remove = pmbus_do_remove,
+ .id_table = ipsps_id,
+};
+
+module_i2c_driver(ipsps_driver);
+
+MODULE_AUTHOR("John Wang");
+MODULE_DESCRIPTION("PMBus driver for Inspur Power System power supplies");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c
index 69d9029ea410..254b0f98c755 100644
--- a/drivers/hwmon/pmbus/max31785.c
+++ b/drivers/hwmon/pmbus/max31785.c
@@ -244,8 +244,6 @@ static int max31785_write_word_data(struct i2c_client *client, int page,
#define MAX31785_VOUT_FUNCS \
(PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT)
-#define MAX37185_NUM_FAN_PAGES 6
-
static const struct pmbus_driver_info max31785_info = {
.pages = MAX31785_NR_PAGES,
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index c846759bc1c0..a9229c6b0e84 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/pmbus.h>
-#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include "pmbus.h"
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
index efe4bb1ff221..d3a64a35f7a9 100644
--- a/drivers/hwmon/raspberrypi-hwmon.c
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -146,7 +146,7 @@ static struct platform_driver rpi_hwmon_driver = {
};
module_platform_driver(rpi_hwmon_driver);
-MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>");
MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:raspberrypi-hwmon");
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
index 0c93fc5ca762..8a7732c0bef3 100644
--- a/drivers/hwmon/scmi-hwmon.c
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -72,7 +72,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
const struct scmi_handle *h = scmi_sensors->handle;
sensor = *(scmi_sensors->info[type] + channel);
- ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
+ ret = h->sensor_ops->reading_get(h, sensor->id, &value);
if (ret)
return ret;
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
index 83fe08185ac7..a0078ccede03 100644
--- a/drivers/hwmon/shtc1.c
+++ b/drivers/hwmon/shtc1.c
@@ -24,19 +24,33 @@ static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 };
static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c };
/* command for reading the ID register */
-static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 };
+static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 };
-/* constants for reading the ID register */
-#define SHTC1_ID 0x07
-#define SHTC1_ID_REG_MASK 0x1f
+/*
+ * constants for reading the ID register
+ * SHTC1: 0x0007 with mask 0x003f
+ * SHTW1: 0x0007 with mask 0x003f
+ * SHTC3: 0x0807 with mask 0x083f
+ */
+#define SHTC3_ID 0x0807
+#define SHTC3_ID_MASK 0x083f
+#define SHTC1_ID 0x0007
+#define SHTC1_ID_MASK 0x003f
/* delays for non-blocking i2c commands, both in us */
#define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400
#define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000
+#define SHTC3_NONBLOCKING_WAIT_TIME_HPM 12100
+#define SHTC3_NONBLOCKING_WAIT_TIME_LPM 800
#define SHTC1_CMD_LENGTH 2
#define SHTC1_RESPONSE_LENGTH 6
+enum shtcx_chips {
+ shtc1,
+ shtc3,
+};
+
struct shtc1_data {
struct i2c_client *client;
struct mutex update_lock;
@@ -47,6 +61,7 @@ struct shtc1_data {
unsigned int nonblocking_wait_time; /* in us */
struct shtc1_platform_data setup;
+ enum shtcx_chips chip;
int temperature; /* 1000 * temperature in dgr C */
int humidity; /* 1000 * relative humidity in %RH */
@@ -157,13 +172,16 @@ static void shtc1_select_command(struct shtc1_data *data)
data->command = data->setup.blocking_io ?
shtc1_cmd_measure_blocking_hpm :
shtc1_cmd_measure_nonblocking_hpm;
- data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM;
-
+ data->nonblocking_wait_time = (data->chip == shtc1) ?
+ SHTC1_NONBLOCKING_WAIT_TIME_HPM :
+ SHTC3_NONBLOCKING_WAIT_TIME_HPM;
} else {
data->command = data->setup.blocking_io ?
shtc1_cmd_measure_blocking_lpm :
shtc1_cmd_measure_nonblocking_lpm;
- data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM;
+ data->nonblocking_wait_time = (data->chip == shtc1) ?
+ SHTC1_NONBLOCKING_WAIT_TIME_LPM :
+ SHTC3_NONBLOCKING_WAIT_TIME_LPM;
}
}
@@ -171,9 +189,11 @@ static int shtc1_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
- char id_reg[2];
+ u16 id_reg;
+ char id_reg_buf[2];
struct shtc1_data *data;
struct device *hwmon_dev;
+ enum shtcx_chips chip = id->driver_data;
struct i2c_adapter *adap = client->adapter;
struct device *dev = &client->dev;
@@ -187,13 +207,20 @@ static int shtc1_probe(struct i2c_client *client,
dev_err(dev, "could not send read_id_reg command: %d\n", ret);
return ret < 0 ? ret : -ENODEV;
}
- ret = i2c_master_recv(client, id_reg, sizeof(id_reg));
- if (ret != sizeof(id_reg)) {
+ ret = i2c_master_recv(client, id_reg_buf, sizeof(id_reg_buf));
+ if (ret != sizeof(id_reg_buf)) {
dev_err(dev, "could not read ID register: %d\n", ret);
return -ENODEV;
}
- if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) {
- dev_err(dev, "ID register doesn't match\n");
+
+ id_reg = be16_to_cpup((__be16 *)id_reg_buf);
+ if (chip == shtc3) {
+ if ((id_reg & SHTC3_ID_MASK) != SHTC3_ID) {
+ dev_err(dev, "SHTC3 ID register does not match\n");
+ return -ENODEV;
+ }
+ } else if ((id_reg & SHTC1_ID_MASK) != SHTC1_ID) {
+ dev_err(dev, "SHTC1 ID register does not match\n");
return -ENODEV;
}
@@ -204,6 +231,7 @@ static int shtc1_probe(struct i2c_client *client,
data->setup.blocking_io = false;
data->setup.high_precision = true;
data->client = client;
+ data->chip = chip;
if (client->dev.platform_data)
data->setup = *(struct shtc1_platform_data *)dev->platform_data;
@@ -222,8 +250,9 @@ static int shtc1_probe(struct i2c_client *client,
/* device ID table */
static const struct i2c_device_id shtc1_id[] = {
- { "shtc1", 0 },
- { "shtw1", 0 },
+ { "shtc1", shtc1 },
+ { "shtw1", shtc1 },
+ { "shtc3", shtc3 },
{ }
};
MODULE_DEVICE_TABLE(i2c, shtc1_id);
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index d8c91c2cb8cf..6eff14fe395d 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -586,10 +586,10 @@ static int smm665_probe(struct i2c_client *client,
data->client = client;
data->type = id->driver_data;
- data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK)
+ data->cmdreg = i2c_new_dummy_device(adapter, (client->addr & ~SMM665_REGMASK)
| SMM665_CMDREG_BASE);
- if (!data->cmdreg)
- return -ENOMEM;
+ if (IS_ERR(data->cmdreg))
+ return PTR_ERR(data->cmdreg);
switch (data->type) {
case smm465:
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index d2c04b6a3f2b..015f1ea31966 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -894,12 +894,12 @@ w83781d_detect_subclients(struct i2c_client *new_client)
}
for (i = 0; i < num_sc; i++) {
- data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]);
- if (!data->lm75[i]) {
+ data->lm75[i] = i2c_new_dummy_device(adapter, sc_addr[i]);
+ if (IS_ERR(data->lm75[i])) {
dev_err(&new_client->dev,
"Subclient %d registration at address 0x%x failed.\n",
i, sc_addr[i]);
- err = -ENOMEM;
+ err = PTR_ERR(data->lm75[i]);
if (i == 1)
goto ERROR_SC_3;
goto ERROR_SC_2;
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 050ad4201691..aad8d4da5802 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -1260,7 +1260,7 @@ static int w83791d_detect_subclients(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
struct w83791d_data *data = i2c_get_clientdata(client);
int address = client->addr;
- int i, id, err;
+ int i, id;
u8 val;
id = i2c_adapter_id(adapter);
@@ -1272,8 +1272,7 @@ static int w83791d_detect_subclients(struct i2c_client *client)
"invalid subclient "
"address %d; must be 0x48-0x4f\n",
force_subclients[i]);
- err = -ENODEV;
- goto error_sc_0;
+ return -ENODEV;
}
}
w83791d_write(client, W83791D_REG_I2C_SUBADDR,
@@ -1283,29 +1282,22 @@ static int w83791d_detect_subclients(struct i2c_client *client)
val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
if (!(val & 0x08))
- data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
+ data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
+ 0x48 + (val & 0x7));
if (!(val & 0x80)) {
- if ((data->lm75[0] != NULL) &&
+ if (!IS_ERR(data->lm75[0]) &&
((val & 0x7) == ((val >> 4) & 0x7))) {
dev_err(&client->dev,
"duplicate addresses 0x%x, "
"use force_subclient\n",
data->lm75[0]->addr);
- err = -ENODEV;
- goto error_sc_1;
+ return -ENODEV;
}
- data->lm75[1] = i2c_new_dummy(adapter,
- 0x48 + ((val >> 4) & 0x7));
+ data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
+ 0x48 + ((val >> 4) & 0x7));
}
return 0;
-
-/* Undo inits in case of errors */
-
-error_sc_1:
- i2c_unregister_device(data->lm75[0]);
-error_sc_0:
- return err;
}
@@ -1394,7 +1386,7 @@ static int w83791d_probe(struct i2c_client *client,
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &w83791d_group);
if (err)
- goto error3;
+ return err;
/* Check if pins of fan/pwm 4-5 are in use as GPIO */
has_fanpwm45 = w83791d_read(client, W83791D_REG_GPIO) & 0x10;
@@ -1419,9 +1411,6 @@ error5:
sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45);
error4:
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
-error3:
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
return err;
}
@@ -1432,9 +1421,6 @@ static int w83791d_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
-
return 0;
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index da8a6d62aa23..7fc8a1160c8f 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -924,7 +924,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr,
static int
w83792d_detect_subclients(struct i2c_client *new_client)
{
- int i, id, err;
+ int i, id;
int address = new_client->addr;
u8 val;
struct i2c_adapter *adapter = new_client->adapter;
@@ -938,8 +938,7 @@ w83792d_detect_subclients(struct i2c_client *new_client)
dev_err(&new_client->dev,
"invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
- err = -ENODEV;
- goto ERROR_SC_0;
+ return -ENODEV;
}
}
w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR,
@@ -949,28 +948,21 @@ w83792d_detect_subclients(struct i2c_client *new_client)
val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
if (!(val & 0x08))
- data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
+ data->lm75[0] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
+ 0x48 + (val & 0x7));
if (!(val & 0x80)) {
- if ((data->lm75[0] != NULL) &&
+ if (!IS_ERR(data->lm75[0]) &&
((val & 0x7) == ((val >> 4) & 0x7))) {
dev_err(&new_client->dev,
"duplicate addresses 0x%x, use force_subclient\n",
data->lm75[0]->addr);
- err = -ENODEV;
- goto ERROR_SC_1;
+ return -ENODEV;
}
- data->lm75[1] = i2c_new_dummy(adapter,
- 0x48 + ((val >> 4) & 0x7));
+ data->lm75[1] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
+ 0x48 + ((val >> 4) & 0x7));
}
return 0;
-
-/* Undo inits in case of errors */
-
-ERROR_SC_1:
- i2c_unregister_device(data->lm75[0]);
-ERROR_SC_0:
- return err;
}
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
@@ -1396,7 +1388,7 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* Register sysfs hooks */
err = sysfs_create_group(&dev->kobj, &w83792d_group);
if (err)
- goto exit_i2c_unregister;
+ return err;
/*
* Read GPIO enable register to check if pins for fan 4,5 are used as
@@ -1441,9 +1433,6 @@ exit_remove_files:
sysfs_remove_group(&dev->kobj, &w83792d_group);
for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]);
-exit_i2c_unregister:
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
return err;
}
@@ -1459,9 +1448,6 @@ w83792d_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj,
&w83792d_group_fan[i]);
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
-
return 0;
}
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 46f5dfec8d0a..9df48b70c70c 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -1551,9 +1551,6 @@ static int w83793_remove(struct i2c_client *client)
for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
device_remove_file(dev, &w83793_temp[i].dev_attr);
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
-
/* Decrease data reference counter */
mutex_lock(&watchdog_data_mutex);
kref_put(&data->kref, w83793_release_resources);
@@ -1565,7 +1562,7 @@ static int w83793_remove(struct i2c_client *client)
static int
w83793_detect_subclients(struct i2c_client *client)
{
- int i, id, err;
+ int i, id;
int address = client->addr;
u8 tmp;
struct i2c_adapter *adapter = client->adapter;
@@ -1580,8 +1577,7 @@ w83793_detect_subclients(struct i2c_client *client)
"invalid subclient "
"address %d; must be 0x48-0x4f\n",
force_subclients[i]);
- err = -EINVAL;
- goto ERROR_SC_0;
+ return -EINVAL;
}
}
w83793_write_value(client, W83793_REG_I2C_SUBADDR,
@@ -1591,28 +1587,21 @@ w83793_detect_subclients(struct i2c_client *client)
tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
if (!(tmp & 0x08))
- data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7));
+ data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
+ 0x48 + (tmp & 0x7));
if (!(tmp & 0x80)) {
- if ((data->lm75[0] != NULL)
+ if (!IS_ERR(data->lm75[0])
&& ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
dev_err(&client->dev,
"duplicate addresses 0x%x, "
"use force_subclients\n", data->lm75[0]->addr);
- err = -ENODEV;
- goto ERROR_SC_1;
+ return -ENODEV;
}
- data->lm75[1] = i2c_new_dummy(adapter,
- 0x48 + ((tmp >> 4) & 0x7));
+ data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
+ 0x48 + ((tmp >> 4) & 0x7));
}
return 0;
-
- /* Undo inits in case of errors */
-
-ERROR_SC_1:
- i2c_unregister_device(data->lm75[0]);
-ERROR_SC_0:
- return err;
}
/* Return 0 if detection is successful, -ENODEV otherwise */
@@ -1945,9 +1934,6 @@ exit_remove:
for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
device_remove_file(dev, &w83793_temp[i].dev_attr);
-
- i2c_unregister_device(data->lm75[0]);
- i2c_unregister_device(data->lm75[1]);
free_mem:
kfree(data);
exit:
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 5c1ca0df5cb0..84f1dcb69827 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -544,6 +544,7 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
/* See function coresight_get_sink_by_id() to know where this is used */
hash = hashlen_hash(hashlen_string(NULL, name));
+ sysfs_attr_init(&ea->attr.attr);
ea->attr.attr.name = devm_kstrdup(dev, name, GFP_KERNEL);
if (!ea->attr.attr.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/intel_th/msu.h b/drivers/hwtracing/intel_th/msu.h
index 574c16004cb2..13d9b141daaa 100644
--- a/drivers/hwtracing/intel_th/msu.h
+++ b/drivers/hwtracing/intel_th/msu.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Intel(R) Trace Hub Memory Storage Unit (MSU) data structures
*
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index c0378c3de9a4..91dfeba62485 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -165,6 +165,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
.driver_data = (kernel_ulong_t)0,
},
{
+ /* Lewisburg PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa226),
+ .driver_data = (kernel_ulong_t)0,
+ },
+ {
/* Gemini Lake */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e),
.driver_data = (kernel_ulong_t)&intel_th_2x,
@@ -199,6 +204,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
+ {
+ /* Tiger Lake PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
{ 0 },
};
diff --git a/drivers/hwtracing/intel_th/pti.h b/drivers/hwtracing/intel_th/pti.h
index e9381babc84c..7dfc0431333b 100644
--- a/drivers/hwtracing/intel_th/pti.h
+++ b/drivers/hwtracing/intel_th/pti.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Intel(R) Trace Hub PTI output data structures
*
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index e55b902560de..181e7ff1ec4f 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -1276,7 +1276,6 @@ int stm_source_register_device(struct device *parent,
err:
put_device(&src->dev);
- kfree(src);
return err;
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 09367fc014c3..f8c77edf70d0 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -684,7 +684,7 @@ config I2C_IMX_LPI2C
config I2C_IOP3XX
tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
- depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
+ depends on ARCH_IOP32X || ARCH_IXP4XX
help
Say Y here if you want to use the IIC bus controller on
the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c
index 8d55cdd69ff4..435c7d7377a3 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -142,7 +142,7 @@ static struct at91_twi_pdata sama5d4_config = {
static struct at91_twi_pdata sama5d2_config = {
.clk_max_div = 7,
- .clk_offset = 4,
+ .clk_offset = 3,
.has_unre_flag = true,
.has_alt_cmd = true,
.has_hold_field = true,
diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c
index e87232f2e708..a3fcc35ffd3b 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -122,9 +122,11 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
writeb_relaxed(*dev->buf, dev->base + AT91_TWI_THR);
/* send stop when last byte has been written */
- if (--dev->buf_len == 0)
+ if (--dev->buf_len == 0) {
if (!dev->use_alt_cmd)
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+ at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_TXRDY);
+ }
dev_dbg(dev->dev, "wrote 0x%x, to go %zu\n", *dev->buf, dev->buf_len);
@@ -542,9 +544,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
} else {
at91_twi_write_next_byte(dev);
at91_twi_write(dev, AT91_TWI_IER,
- AT91_TWI_TXCOMP |
- AT91_TWI_NACK |
- AT91_TWI_TXRDY);
+ AT91_TWI_TXCOMP | AT91_TWI_NACK |
+ (dev->buf_len ? AT91_TWI_TXRDY : 0));
}
}
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index 2c7f145a036e..19ef2b0c682a 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -392,16 +392,18 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
static void bcm_iproc_i2c_read_valid_bytes(struct bcm_iproc_i2c_dev *iproc_i2c)
{
struct i2c_msg *msg = iproc_i2c->msg;
+ uint32_t val;
/* Read valid data from RX FIFO */
while (iproc_i2c->rx_bytes < msg->len) {
- if (!((iproc_i2c_rd_reg(iproc_i2c, M_FIFO_CTRL_OFFSET) >> M_FIFO_RX_CNT_SHIFT)
- & M_FIFO_RX_CNT_MASK))
+ val = iproc_i2c_rd_reg(iproc_i2c, M_RX_OFFSET);
+
+ /* rx fifo empty */
+ if (!((val >> M_RX_STATUS_SHIFT) & M_RX_STATUS_MASK))
break;
msg->buf[iproc_i2c->rx_bytes] =
- (iproc_i2c_rd_reg(iproc_i2c, M_RX_OFFSET) >>
- M_RX_DATA_SHIFT) & M_RX_DATA_MASK;
+ (val >> M_RX_DATA_SHIFT) & M_RX_DATA_MASK;
iproc_i2c->rx_bytes++;
}
}
@@ -788,7 +790,10 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter,
static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap)
{
- u32 val = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ u32 val;
+
+ /* We do not support the SMBUS Quick command */
+ val = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
if (adap->algo->reg_slave)
val |= I2C_FUNC_SLAVE;
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index e7f9305b2dd9..f5f001738df5 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -94,6 +94,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
dev->disable_int(dev);
dev->disable(dev);
+ synchronize_irq(dev->irq);
dev->slave = NULL;
pm_runtime_put(dev->dev);
diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index 35b302d983e0..959d4912ec0d 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -69,6 +69,7 @@ struct em_i2c_device {
struct completion msg_done;
struct clk *sclk;
struct i2c_client *slave;
+ int irq;
};
static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -339,6 +340,12 @@ static int em_i2c_unreg_slave(struct i2c_client *slave)
writeb(0, priv->base + I2C_OFS_SVA0);
+ /*
+ * Wait for interrupt to finish. New slave irqs cannot happen because we
+ * cleared the slave address and, thus, only extension codes will be
+ * detected which do not use the slave ptr.
+ */
+ synchronize_irq(priv->irq);
priv->slave = NULL;
return 0;
@@ -355,7 +362,7 @@ static int em_i2c_probe(struct platform_device *pdev)
{
struct em_i2c_device *priv;
struct resource *r;
- int irq, ret;
+ int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -390,8 +397,8 @@ static int em_i2c_probe(struct platform_device *pdev)
em_i2c_reset(&priv->adap);
- irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, irq, em_i2c_irq_handler, 0,
+ priv->irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
"em_i2c", priv);
if (ret)
goto err_clk;
@@ -401,7 +408,8 @@ static int em_i2c_probe(struct platform_device *pdev)
if (ret)
goto err_clk;
- dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, irq);
+ dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
+ priv->irq);
return 0;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index f2956936c3f2..2e08b4722dc4 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -1194,19 +1194,28 @@ static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle,
int i;
status = acpi_get_object_info(obj_handle, &info);
- if (!ACPI_SUCCESS(status) || !(info->valid & ACPI_VALID_HID))
+ if (ACPI_FAILURE(status))
return AE_OK;
+ if (!(info->valid & ACPI_VALID_HID))
+ goto smo88xx_not_found;
+
hid = info->hardware_id.string;
if (!hid)
- return AE_OK;
+ goto smo88xx_not_found;
i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid);
if (i < 0)
- return AE_OK;
+ goto smo88xx_not_found;
+
+ kfree(info);
*((bool *)return_value) = true;
return AE_CTRL_TERMINATE;
+
+smo88xx_not_found:
+ kfree(info);
+ return AE_OK;
}
static bool is_dell_system_with_lis3lv02d(void)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index b1b8b938d7f4..15f6cde6452f 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
}
/* Functions for DMA support */
-static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
- dma_addr_t phy_addr)
+static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
+ dma_addr_t phy_addr)
{
struct imx_i2c_dma *dma;
struct dma_slave_config dma_sconfig;
@@ -283,7 +283,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
- return -ENOMEM;
+ return;
dma->chan_tx = dma_request_chan(dev, "tx");
if (IS_ERR(dma->chan_tx)) {
@@ -328,7 +328,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
- return 0;
+ return;
fail_rx:
dma_release_channel(dma->chan_rx);
@@ -336,8 +336,6 @@ fail_tx:
dma_release_channel(dma->chan_tx);
fail_al:
devm_kfree(dev, dma);
- /* return successfully if there is no dma support */
- return ret == -ENODEV ? 0 : ret;
}
static void i2c_imx_dma_callback(void *arg)
@@ -1165,17 +1163,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
i2c_imx->adapter.name);
+ dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
/* Init DMA config if supported */
- ret = i2c_imx_dma_request(i2c_imx, phy_addr);
- if (ret < 0)
- goto del_adapter;
+ i2c_imx_dma_request(i2c_imx, phy_addr);
- dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
return 0; /* Return OK */
-del_adapter:
- i2c_del_adapter(&i2c_imx->adapter);
clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
rpm_disable:
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 252edb433fdf..29eae1bf4f86 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -234,6 +234,10 @@ static const struct i2c_adapter_quirks mt7622_i2c_quirks = {
.max_num_msgs = 255,
};
+static const struct i2c_adapter_quirks mt8183_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static const struct mtk_i2c_compatible mt2712_compat = {
.regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
@@ -298,6 +302,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
};
static const struct mtk_i2c_compatible mt8183_compat = {
+ .quirks = &mt8183_i2c_quirks,
.regs = mt_i2c_regs_v2,
.pmic_i2c = 0,
.dcm = 0,
@@ -870,7 +875,11 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN)
+ return I2C_FUNC_I2C |
+ (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+ else
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm mtk_i2c_algorithm = {
diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c
index cfc76b5de726..5a1235fd86bb 100644
--- a/drivers/i2c/busses/i2c-nvidia-gpu.c
+++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
@@ -364,7 +364,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev)
/*
* We need gpu_i2c_suspend() even if it is stub, for runtime pm to work
* correctly. Without it, lspci shows runtime pm status as "D0" for the card.
- * Documentation/power/pci.txt also insists for driver to provide this.
+ * Documentation/power/pci.rst also insists for driver to provide this.
*/
static __maybe_unused int gpu_i2c_suspend(struct device *dev)
{
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index c46c4bddc7ca..cba325eb852f 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -91,7 +91,7 @@
#define SB800_PIIX4_PORT_IDX_MASK 0x06
#define SB800_PIIX4_PORT_IDX_SHIFT 1
-/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
+/* On kerncz and Hudson2, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
#define SB800_PIIX4_PORT_IDX_KERNCZ 0x02
#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
@@ -358,18 +358,16 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
/* Find which register is used for port selection */
if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD ||
PIIX4_dev->vendor == PCI_VENDOR_ID_HYGON) {
- switch (PIIX4_dev->device) {
- case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS:
+ if (PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS ||
+ (PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
+ PIIX4_dev->revision >= 0x1F)) {
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ;
- break;
- case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS:
- default:
+ } else {
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
- break;
}
} else {
if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d39a4606f72d..531c01100b56 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -139,6 +139,7 @@ struct rcar_i2c_priv {
enum dma_data_direction dma_direction;
struct reset_control *rstc;
+ int irq;
};
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -861,9 +862,11 @@ static int rcar_unreg_slave(struct i2c_client *slave)
WARN_ON(!priv->slave);
+ /* disable irqs and ensure none is running before clearing ptr */
rcar_i2c_write(priv, ICSIER, 0);
rcar_i2c_write(priv, ICSCR, 0);
+ synchronize_irq(priv->irq);
priv->slave = NULL;
pm_runtime_put(rcar_i2c_priv_to_dev(priv));
@@ -918,7 +921,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct device *dev = &pdev->dev;
struct i2c_timings i2c_t;
- int irq, ret;
+ int ret;
/* Otherwise logic will break because some bytes must always use PIO */
BUILD_BUG_ON_MSG(RCAR_MIN_DMA_LEN < 3, "Invalid min DMA length");
@@ -984,10 +987,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
pm_runtime_put(dev);
- irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
+ priv->irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv);
if (ret < 0) {
- dev_err(dev, "cannot get irq %d\n", irq);
+ dev_err(dev, "cannot get irq %d\n", priv->irq);
goto out_pm_disable;
}
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index d97fb857b0ea..c98ef4c4a0c9 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -435,6 +435,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
* fall through to the write state, as we will need to
* send a byte as well
*/
+ /* Fall through */
case STATE_WRITE:
/*
diff --git a/drivers/i2c/busses/i2c-stm32.h b/drivers/i2c/busses/i2c-stm32.h
index 868755f82f88..2c21893905a3 100644
--- a/drivers/i2c/busses/i2c-stm32.h
+++ b/drivers/i2c/busses/i2c-stm32.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* i2c-stm32.h
*
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index f26ed495d384..9c440fa6a3dd 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -832,7 +832,7 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/
void i2c_unregister_device(struct i2c_client *client)
{
- if (!client)
+ if (IS_ERR_OR_NULL(client))
return;
if (client->dev.of_node) {
diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index 69cc040c3a1c..9e2e1406f85e 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -201,6 +201,59 @@ struct i3c_device *dev_to_i3cdev(struct device *dev)
EXPORT_SYMBOL_GPL(dev_to_i3cdev);
/**
+ * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev
+ * @i3cdev: I3C device
+ * @id_table: I3C device match table
+ *
+ * Return: a pointer to an i3c_device_id object or NULL if there's no match.
+ */
+const struct i3c_device_id *
+i3c_device_match_id(struct i3c_device *i3cdev,
+ const struct i3c_device_id *id_table)
+{
+ struct i3c_device_info devinfo;
+ const struct i3c_device_id *id;
+
+ i3c_device_get_info(i3cdev, &devinfo);
+
+ /*
+ * The lower 32bits of the provisional ID is just filled with a random
+ * value, try to match using DCR info.
+ */
+ if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
+ u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
+ u16 part = I3C_PID_PART_ID(devinfo.pid);
+ u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
+
+ /* First try to match by manufacturer/part ID. */
+ for (id = id_table; id->match_flags != 0; id++) {
+ if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
+ I3C_MATCH_MANUF_AND_PART)
+ continue;
+
+ if (manuf != id->manuf_id || part != id->part_id)
+ continue;
+
+ if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
+ ext_info != id->extra_info)
+ continue;
+
+ return id;
+ }
+ }
+
+ /* Fallback to DCR match. */
+ for (id = id_table; id->match_flags != 0; id++) {
+ if ((id->match_flags & I3C_MATCH_DCR) &&
+ id->dcr == devinfo.dcr)
+ return id;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(i3c_device_match_id);
+
+/**
* i3c_driver_register_with_owner() - register an I3C device driver
*
* @drv: driver to register
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d6f8b038a896..5c051dba32a5 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -123,7 +123,7 @@ static struct i3c_dev_desc *dev_to_i3cdesc(struct device *dev)
if (dev->type == &i3c_device_type)
return dev_to_i3cdev(dev)->desc;
- master = container_of(dev, struct i3c_master_controller, dev);
+ master = dev_to_i3cmaster(dev);
return master->this;
}
@@ -276,51 +276,6 @@ static const struct device_type i3c_device_type = {
.uevent = i3c_device_uevent,
};
-static const struct i3c_device_id *
-i3c_device_match_id(struct i3c_device *i3cdev,
- const struct i3c_device_id *id_table)
-{
- struct i3c_device_info devinfo;
- const struct i3c_device_id *id;
-
- i3c_device_get_info(i3cdev, &devinfo);
-
- /*
- * The lower 32bits of the provisional ID is just filled with a random
- * value, try to match using DCR info.
- */
- if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
- u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
- u16 part = I3C_PID_PART_ID(devinfo.pid);
- u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
-
- /* First try to match by manufacturer/part ID. */
- for (id = id_table; id->match_flags != 0; id++) {
- if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
- I3C_MATCH_MANUF_AND_PART)
- continue;
-
- if (manuf != id->manuf_id || part != id->part_id)
- continue;
-
- if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
- ext_info != id->extra_info)
- continue;
-
- return id;
- }
- }
-
- /* Fallback to DCR match. */
- for (id = id_table; id->match_flags != 0; id++) {
- if ((id->match_flags & I3C_MATCH_DCR) &&
- id->dcr == devinfo.dcr)
- return id;
- }
-
- return NULL;
-}
-
static int i3c_device_match(struct device *dev, struct device_driver *drv)
{
struct i3c_device *i3cdev;
@@ -645,6 +600,8 @@ i3c_master_alloc_i2c_dev(struct i3c_master_controller *master,
dev->common.master = master;
dev->boardinfo = boardinfo;
+ dev->addr = boardinfo->base.addr;
+ dev->lvr = boardinfo->lvr;
return dev;
}
@@ -963,8 +920,8 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
desc = defslvs->slaves;
i3c_bus_for_each_i2cdev(bus, i2cdev) {
- desc->lvr = i2cdev->boardinfo->lvr;
- desc->static_addr = i2cdev->boardinfo->base.addr << 1;
+ desc->lvr = i2cdev->lvr;
+ desc->static_addr = i2cdev->addr << 1;
desc++;
}
@@ -1084,8 +1041,10 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
if (ret)
goto out;
- if (dest.payload.len != sizeof(*mwl))
- return -EIO;
+ if (dest.payload.len != sizeof(*mwl)) {
+ ret = -EIO;
+ goto out;
+ }
info->max_write_len = be16_to_cpu(mwl->len);
@@ -1631,8 +1590,8 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
common.node) {
i3c_master_detach_i2c_dev(i2cdev);
i3c_bus_set_addr_slot_status(&master->bus,
- i2cdev->boardinfo->base.addr,
- I3C_ADDR_SLOT_FREE);
+ i2cdev->addr,
+ I3C_ADDR_SLOT_FREE);
i3c_master_free_i2c_dev(i2cdev);
}
}
@@ -2093,8 +2052,10 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master)
for_each_available_child_of_node(i3cbus_np, node) {
ret = of_i3c_master_add_dev(master, node);
- if (ret)
+ if (ret) {
+ of_node_put(node);
return ret;
+ }
}
/*
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 09912d75c6d5..b0ff0e12d84c 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -1033,12 +1033,12 @@ static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
return -ENOMEM;
data->index = pos;
- master->addrs[pos] = dev->boardinfo->base.addr;
+ master->addrs[pos] = dev->addr;
master->free_pos &= ~BIT(pos);
i2c_dev_set_master_data(dev, data);
writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV |
- DEV_ADDR_TABLE_STATIC_ADDR(dev->boardinfo->base.addr),
+ DEV_ADDR_TABLE_STATIC_ADDR(dev->addr),
master->regs +
DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index 237f24adddc6..10db0bf0655a 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -903,7 +903,8 @@ static void cdns_i3c_master_upd_i3c_addr(struct i3c_dev_desc *dev)
static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master,
u8 dyn_addr)
{
- u32 activedevs, rr;
+ unsigned long activedevs;
+ u32 rr;
int i;
if (!dyn_addr) {
@@ -913,13 +914,10 @@ static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master,
return ffs(master->free_rr_slots) - 1;
}
- activedevs = readl(master->regs + DEVS_CTRL) &
- DEVS_CTRL_DEVS_ACTIVE_MASK;
-
- for (i = 1; i <= master->maxdevs; i++) {
- if (!(BIT(i) & activedevs))
- continue;
+ activedevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
+ activedevs &= ~BIT(0);
+ for_each_set_bit(i, &activedevs, master->maxdevs + 1) {
rr = readl(master->regs + DEV_ID_RR0(i));
if (!(rr & DEV_ID_RR0_IS_I3C) ||
DEV_ID_RR0_GET_DEV_ADDR(rr) != dyn_addr)
@@ -1005,9 +1003,9 @@ static int cdns_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
master->free_rr_slots &= ~BIT(slot);
i2c_dev_set_master_data(dev, data);
- writel(prepare_rr0_dev_address(dev->boardinfo->base.addr),
+ writel(prepare_rr0_dev_address(dev->addr),
master->regs + DEV_ID_RR0(data->id));
- writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id));
+ writel(dev->lvr, master->regs + DEV_ID_RR2(data->id));
writel(readl(master->regs + DEVS_CTRL) |
DEVS_CTRL_DEV_ACTIVE(data->id),
master->regs + DEVS_CTRL);
@@ -1126,18 +1124,16 @@ static void cdns_i3c_master_upd_i3c_scl_lim(struct cdns_i3c_master *master)
static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)
{
struct cdns_i3c_master *master = to_cdns_i3c_master(m);
- u32 olddevs, newdevs;
+ unsigned long olddevs, newdevs;
int ret, slot;
u8 addrs[MAX_DEVS] = { };
u8 last_addr = 0;
olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
+ olddevs |= BIT(0);
/* Prepare RR slots before launching DAA. */
- for (slot = 1; slot <= master->maxdevs; slot++) {
- if (olddevs & BIT(slot))
- continue;
-
+ for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) {
ret = i3c_master_get_free_addr(m, last_addr + 1);
if (ret < 0)
return -ENOSPC;
@@ -1161,10 +1157,8 @@ static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)
* Clear all retaining registers filled during DAA. We already
* have the addressed assigned to them in the addrs array.
*/
- for (slot = 1; slot <= master->maxdevs; slot++) {
- if (newdevs & BIT(slot))
- i3c_master_add_i3c_dev_locked(m, addrs[slot]);
- }
+ for_each_set_bit(slot, &newdevs, master->maxdevs + 1)
+ i3c_master_add_i3c_dev_locked(m, addrs[slot]);
/*
* Clear slots that ended up not being used. Can be caused by I3C
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 9eada392df15..1c227ea8ecd3 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -567,15 +567,6 @@ config BLK_DEV_SVWKS
This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5
chipsets.
-config BLK_DEV_SGIIOC4
- tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
- depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
- select BLK_DEV_IDEDMA_PCI
- help
- This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
- chipset, which has one channel and can support two devices.
- Please say Y here if you have an Altix System from SGI.
-
config BLK_DEV_SIIMAGE
tristate "Silicon Image chipset support"
select BLK_DEV_IDEDMA_PCI
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 9f617a77970f..cac02db4098d 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -59,7 +59,6 @@ obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o
obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += sgiioc4.o
obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
deleted file mode 100644
index 2d35e9f7516f..000000000000
--- a/drivers/ide/sgiioc4.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
- * Copyright (C) 2008-2009 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/scatterlist.h>
-#include <linux/ioc4.h>
-#include <linux/io.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "SGIIOC4"
-
-/* IOC4 Specific Definitions */
-#define IOC4_CMD_OFFSET 0x100
-#define IOC4_CTRL_OFFSET 0x120
-#define IOC4_DMA_OFFSET 0x140
-#define IOC4_INTR_OFFSET 0x0
-
-#define IOC4_TIMING 0x00
-#define IOC4_DMA_PTR_L 0x01
-#define IOC4_DMA_PTR_H 0x02
-#define IOC4_DMA_ADDR_L 0x03
-#define IOC4_DMA_ADDR_H 0x04
-#define IOC4_BC_DEV 0x05
-#define IOC4_BC_MEM 0x06
-#define IOC4_DMA_CTRL 0x07
-#define IOC4_DMA_END_ADDR 0x08
-
-/* Bits in the IOC4 Control/Status Register */
-#define IOC4_S_DMA_START 0x01
-#define IOC4_S_DMA_STOP 0x02
-#define IOC4_S_DMA_DIR 0x04
-#define IOC4_S_DMA_ACTIVE 0x08
-#define IOC4_S_DMA_ERROR 0x10
-#define IOC4_ATA_MEMERR 0x02
-
-/* Read/Write Directions */
-#define IOC4_DMA_WRITE 0x04
-#define IOC4_DMA_READ 0x00
-
-/* Interrupt Register Offsets */
-#define IOC4_INTR_REG 0x03
-#define IOC4_INTR_SET 0x05
-#define IOC4_INTR_CLEAR 0x07
-
-#define IOC4_IDE_CACHELINE_SIZE 128
-#define IOC4_CMD_CTL_BLK_SIZE 0x20
-#define IOC4_SUPPORTED_FIRMWARE_REV 46
-
-struct ioc4_dma_regs {
- u32 timing_reg0;
- u32 timing_reg1;
- u32 low_mem_ptr;
- u32 high_mem_ptr;
- u32 low_mem_addr;
- u32 high_mem_addr;
- u32 dev_byte_count;
- u32 mem_byte_count;
- u32 status;
-};
-
-/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
-/* IOC4 has only 1 IDE channel */
-#define IOC4_PRD_BYTES 16
-#define IOC4_PRD_ENTRIES (PAGE_SIZE / (4 * IOC4_PRD_BYTES))
-
-
-static void sgiioc4_init_hwif_ports(struct ide_hw *hw,
- unsigned long data_port,
- unsigned long ctrl_port,
- unsigned long irq_port)
-{
- unsigned long reg = data_port;
- int i;
-
- /* Registers are word (32 bit) aligned */
- for (i = 0; i <= 7; i++)
- hw->io_ports_array[i] = reg + i * 4;
-
- hw->io_ports.ctl_addr = ctrl_port;
- hw->io_ports.irq_addr = irq_port;
-}
-
-static int sgiioc4_checkirq(ide_hwif_t *hwif)
-{
- unsigned long intr_addr = hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
-
- if (readl((void __iomem *)intr_addr) & 0x03)
- return 1;
-
- return 0;
-}
-
-static u8 sgiioc4_read_status(ide_hwif_t *);
-
-static int sgiioc4_clearirq(ide_drive_t *drive)
-{
- u32 intr_reg;
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
-
- /* Code to check for PCI error conditions */
- intr_reg = readl((void __iomem *)other_ir);
- if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
- /*
- * Using sgiioc4_read_status to read the Status register has a
- * side effect of clearing the interrupt. The first read should
- * clear it if it is set. The second read should return
- * a "clear" status if it got cleared. If not, then spin
- * for a bit trying to clear it.
- */
- u8 stat = sgiioc4_read_status(hwif);
- int count = 0;
-
- stat = sgiioc4_read_status(hwif);
- while ((stat & ATA_BUSY) && (count++ < 100)) {
- udelay(1);
- stat = sgiioc4_read_status(hwif);
- }
-
- if (intr_reg & 0x02) {
- struct pci_dev *dev = to_pci_dev(hwif->dev);
- /* Error when transferring DMA data on PCI bus */
- u32 pci_err_addr_low, pci_err_addr_high,
- pci_stat_cmd_reg;
-
- pci_err_addr_low =
- readl((void __iomem *)io_ports->irq_addr);
- pci_err_addr_high =
- readl((void __iomem *)(io_ports->irq_addr + 4));
- pci_read_config_dword(dev, PCI_COMMAND,
- &pci_stat_cmd_reg);
- printk(KERN_ERR "%s(%s): PCI Bus Error when doing DMA: "
- "status-cmd reg is 0x%x\n",
- __func__, drive->name, pci_stat_cmd_reg);
- printk(KERN_ERR "%s(%s): PCI Error Address is 0x%x%x\n",
- __func__, drive->name,
- pci_err_addr_high, pci_err_addr_low);
- /* Clear the PCI Error indicator */
- pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
- }
-
- /* Clear the Interrupt, Error bits on the IOC4 */
- writel(0x03, (void __iomem *)other_ir);
-
- intr_reg = readl((void __iomem *)other_ir);
- }
-
- return intr_reg & 3;
-}
-
-static void sgiioc4_dma_start(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
- unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
- unsigned int temp_reg = reg | IOC4_S_DMA_START;
-
- writel(temp_reg, (void __iomem *)ioc4_dma_addr);
-}
-
-static u32 sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
-{
- unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
- u32 ioc4_dma;
- int count;
-
- count = 0;
- ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
- while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
- udelay(1);
- ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
- }
- return ioc4_dma;
-}
-
-/* Stops the IOC4 DMA Engine */
-static int sgiioc4_dma_end(ide_drive_t *drive)
-{
- u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
- ide_hwif_t *hwif = drive->hwif;
- unsigned long dma_base = hwif->dma_base;
- int dma_stat = 0;
- unsigned long *ending_dma = ide_get_hwifdata(hwif);
-
- writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
-
- ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
- if (ioc4_dma & IOC4_S_DMA_STOP) {
- printk(KERN_ERR
- "%s(%s): IOC4 DMA STOP bit is still 1 :"
- "ioc4_dma_reg 0x%x\n",
- __func__, drive->name, ioc4_dma);
- dma_stat = 1;
- }
-
- /*
- * The IOC4 will DMA 1's to the ending DMA area to indicate that
- * previous data DMA is complete. This is necessary because of relaxed
- * ordering between register reads and DMA writes on the Altix.
- */
- while ((cnt++ < 200) && (!valid)) {
- for (num = 0; num < 16; num++) {
- if (ending_dma[num]) {
- valid = 1;
- break;
- }
- }
- udelay(1);
- }
- if (!valid) {
- printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__,
- drive->name);
- dma_stat = 1;
- }
-
- bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
- bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
-
- if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
- if (bc_dev > bc_mem + 8) {
- printk(KERN_ERR
- "%s(%s): WARNING!! byte_count_dev %d "
- "!= byte_count_mem %d\n",
- __func__, drive->name, bc_dev, bc_mem);
- }
- }
-
- return dma_stat;
-}
-
-static void sgiioc4_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
-{
-}
-
-/* Returns 1 if DMA IRQ issued, 0 otherwise */
-static int sgiioc4_dma_test_irq(ide_drive_t *drive)
-{
- return sgiioc4_checkirq(drive->hwif);
-}
-
-static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
-{
- if (!on)
- sgiioc4_clearirq(drive);
-}
-
-static void sgiioc4_resetproc(ide_drive_t *drive)
-{
- struct ide_cmd *cmd = &drive->hwif->cmd;
-
- sgiioc4_dma_end(drive);
- ide_dma_unmap_sg(drive, cmd);
- sgiioc4_clearirq(drive);
-}
-
-static void sgiioc4_dma_lost_irq(ide_drive_t *drive)
-{
- sgiioc4_resetproc(drive);
-
- ide_dma_lost_irq(drive);
-}
-
-static u8 sgiioc4_read_status(ide_hwif_t *hwif)
-{
- unsigned long port = hwif->io_ports.status_addr;
- u8 reg = (u8) readb((void __iomem *) port);
-
- if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
- unsigned long other_ir = port - 0x110;
- unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
-
- /* Clear the Interrupt, Error bits on the IOC4 */
- if (intr_reg & 0x03) {
- writel(0x03, (void __iomem *) other_ir);
- intr_reg = (u32) readl((void __iomem *) other_ir);
- }
- }
-
- return reg;
-}
-
-/* Creates a DMA map for the scatter-gather list entries */
-static int ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
- unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
- int num_ports = sizeof(struct ioc4_dma_regs);
- void *pad;
-
- printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
-
- if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
- printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
- "already in use\n", __func__, hwif->name,
- dma_base, dma_base + num_ports - 1);
- return -1;
- }
-
- hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr +
- IOC4_DMA_OFFSET;
-
- hwif->sg_max_nents = IOC4_PRD_ENTRIES;
-
- hwif->prd_max_nents = IOC4_PRD_ENTRIES;
- hwif->prd_ent_size = IOC4_PRD_BYTES;
-
- if (ide_allocate_dma_engine(hwif))
- goto dma_pci_alloc_failure;
-
- pad = dma_alloc_coherent(&dev->dev, IOC4_IDE_CACHELINE_SIZE,
- (dma_addr_t *)&hwif->extra_base, GFP_KERNEL);
- if (pad) {
- ide_set_hwifdata(hwif, pad);
- return 0;
- }
-
- ide_release_dma_engine(hwif);
-
- printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
- __func__, hwif->name);
- printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
-
-dma_pci_alloc_failure:
- release_mem_region(dma_base, num_ports);
-
- return -1;
-}
-
-/* Initializes the IOC4 DMA Engine */
-static void sgiioc4_configure_for_dma(int dma_direction, ide_drive_t *drive)
-{
- u32 ioc4_dma;
- ide_hwif_t *hwif = drive->hwif;
- unsigned long dma_base = hwif->dma_base;
- unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
- u32 dma_addr, ending_dma_addr;
-
- ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
-
- if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
- printk(KERN_WARNING "%s(%s): Warning!! DMA from previous "
- "transfer was still active\n", __func__, drive->name);
- writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
- ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
- if (ioc4_dma & IOC4_S_DMA_STOP)
- printk(KERN_ERR "%s(%s): IOC4 DMA STOP bit is "
- "still 1\n", __func__, drive->name);
- }
-
- ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
- if (ioc4_dma & IOC4_S_DMA_ERROR) {
- printk(KERN_WARNING "%s(%s): Warning!! DMA Error during "
- "previous transfer, status 0x%x\n",
- __func__, drive->name, ioc4_dma);
- writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
- ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
- if (ioc4_dma & IOC4_S_DMA_STOP)
- printk(KERN_ERR "%s(%s): IOC4 DMA STOP bit is "
- "still 1\n", __func__, drive->name);
- }
-
- /* Address of the Scatter Gather List */
- dma_addr = cpu_to_le32(hwif->dmatable_dma);
- writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
-
- /* Address of the Ending DMA */
- memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
- ending_dma_addr = cpu_to_le32(hwif->extra_base);
- writel(ending_dma_addr, (void __iomem *)(dma_base +
- IOC4_DMA_END_ADDR * 4));
-
- writel(dma_direction, (void __iomem *)ioc4_dma_addr);
-}
-
-/* IOC4 Scatter Gather list Format */
-/* 128 Bit entries to support 64 bit addresses in the future */
-/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format */
-/* --------------------------------------------------------------------- */
-/* | Upper 32 bits - Zero | Lower 32 bits- address | */
-/* --------------------------------------------------------------------- */
-/* | Upper 32 bits - Zero |EOL| 15 unused | 16 Bit Length| */
-/* --------------------------------------------------------------------- */
-/* Creates the scatter gather list, DMA Table */
-
-static int sgiioc4_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
-{
- ide_hwif_t *hwif = drive->hwif;
- unsigned int *table = hwif->dmatable_cpu;
- unsigned int count = 0, i = cmd->sg_nents;
- struct scatterlist *sg = hwif->sg_table;
-
- while (i && sg_dma_len(sg)) {
- dma_addr_t cur_addr;
- int cur_len;
- cur_addr = sg_dma_address(sg);
- cur_len = sg_dma_len(sg);
-
- while (cur_len) {
- if (count++ >= IOC4_PRD_ENTRIES) {
- printk(KERN_WARNING
- "%s: DMA table too small\n",
- drive->name);
- return 0;
- } else {
- u32 bcount =
- 0x10000 - (cur_addr & 0xffff);
-
- if (bcount > cur_len)
- bcount = cur_len;
-
- /*
- * Put the address, length in
- * the IOC4 dma-table format
- */
- *table = 0x0;
- table++;
- *table = cpu_to_be32(cur_addr);
- table++;
- *table = 0x0;
- table++;
-
- *table = cpu_to_be32(bcount);
- table++;
-
- cur_addr += bcount;
- cur_len -= bcount;
- }
- }
-
- sg = sg_next(sg);
- i--;
- }
-
- if (count) {
- table--;
- *table |= cpu_to_be32(0x80000000);
- return count;
- }
-
- return 0; /* revert to PIO for this request */
-}
-
-static int sgiioc4_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
-{
- int ddir;
- u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
-
- if (sgiioc4_build_dmatable(drive, cmd) == 0)
- /* try PIO instead of DMA */
- return 1;
-
- if (write)
- /* Writes TO the IOC4 FROM Main Memory */
- ddir = IOC4_DMA_READ;
- else
- /* Writes FROM the IOC4 TO Main Memory */
- ddir = IOC4_DMA_WRITE;
-
- sgiioc4_configure_for_dma(ddir, drive);
-
- return 0;
-}
-
-static const struct ide_tp_ops sgiioc4_tp_ops = {
- .exec_command = ide_exec_command,
- .read_status = sgiioc4_read_status,
- .read_altstatus = ide_read_altstatus,
- .write_devctl = ide_write_devctl,
-
- .dev_select = ide_dev_select,
- .tf_load = ide_tf_load,
- .tf_read = ide_tf_read,
-
- .input_data = ide_input_data,
- .output_data = ide_output_data,
-};
-
-static const struct ide_port_ops sgiioc4_port_ops = {
- .set_dma_mode = sgiioc4_set_dma_mode,
- /* reset DMA engine, clear IRQs */
- .resetproc = sgiioc4_resetproc,
-};
-
-static const struct ide_dma_ops sgiioc4_dma_ops = {
- .dma_host_set = sgiioc4_dma_host_set,
- .dma_setup = sgiioc4_dma_setup,
- .dma_start = sgiioc4_dma_start,
- .dma_end = sgiioc4_dma_end,
- .dma_test_irq = sgiioc4_dma_test_irq,
- .dma_lost_irq = sgiioc4_dma_lost_irq,
-};
-
-static const struct ide_port_info sgiioc4_port_info = {
- .name = DRV_NAME,
- .chipset = ide_pci,
- .init_dma = ide_dma_sgiioc4,
- .tp_ops = &sgiioc4_tp_ops,
- .port_ops = &sgiioc4_port_ops,
- .dma_ops = &sgiioc4_dma_ops,
- .host_flags = IDE_HFLAG_MMIO,
- .irq_flags = IRQF_SHARED,
- .mwdma_mask = ATA_MWDMA2_ONLY,
-};
-
-static int sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
-{
- unsigned long cmd_base, irqport;
- unsigned long bar0, cmd_phys_base, ctl;
- void __iomem *virt_base;
- struct ide_hw hw, *hws[] = { &hw };
- int rc;
-
- /* Get the CmdBlk and CtrlBlk base registers */
- bar0 = pci_resource_start(dev, 0);
- virt_base = pci_ioremap_bar(dev, 0);
- if (virt_base == NULL) {
- printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
- DRV_NAME, bar0);
- return -ENOMEM;
- }
- cmd_base = (unsigned long)virt_base + IOC4_CMD_OFFSET;
- ctl = (unsigned long)virt_base + IOC4_CTRL_OFFSET;
- irqport = (unsigned long)virt_base + IOC4_INTR_OFFSET;
-
- cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
- if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
- DRV_NAME) == NULL) {
- printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
- "already in use\n", DRV_NAME, pci_name(dev),
- cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
- rc = -EBUSY;
- goto req_mem_rgn_err;
- }
-
- /* Initialize the IO registers */
- memset(&hw, 0, sizeof(hw));
- sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
- hw.irq = dev->irq;
- hw.dev = &dev->dev;
-
- /* Initialize chipset IRQ registers */
- writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
-
- rc = ide_host_add(&sgiioc4_port_info, hws, 1, NULL);
- if (!rc)
- return 0;
-
- release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
-req_mem_rgn_err:
- iounmap(virt_base);
- return rc;
-}
-
-static unsigned int pci_init_sgiioc4(struct pci_dev *dev)
-{
- int ret;
-
- printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
- DRV_NAME, pci_name(dev), dev->revision);
-
- if (dev->revision < IOC4_SUPPORTED_FIRMWARE_REV) {
- printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
- "firmware is obsolete - please upgrade to "
- "revision46 or higher\n",
- DRV_NAME, pci_name(dev));
- ret = -EAGAIN;
- goto out;
- }
- ret = sgiioc4_ide_setup_pci_device(dev);
-out:
- return ret;
-}
-
-static int ioc4_ide_attach_one(struct ioc4_driver_data *idd)
-{
- /*
- * PCI-RT does not bring out IDE connection.
- * Do not attach to this particular IOC4.
- */
- if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
- return 0;
-
- return pci_init_sgiioc4(idd->idd_pdev);
-}
-
-static struct ioc4_submodule ioc4_ide_submodule = {
- .is_name = "IOC4_ide",
- .is_owner = THIS_MODULE,
- .is_probe = ioc4_ide_attach_one,
-};
-
-static int __init ioc4_ide_init(void)
-{
- return ioc4_register_submodule(&ioc4_ide_submodule);
-}
-
-late_initcall(ioc4_ide_init); /* Call only after IDE init is done */
-
-MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
-MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index fa5ff77b8fe4..347b08b56042 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1072,26 +1072,26 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
INTEL_CPU_FAM6(ATOM_AIRMONT, idle_cpu_cht),
INTEL_CPU_FAM6(IVYBRIDGE, idle_cpu_ivb),
INTEL_CPU_FAM6(IVYBRIDGE_X, idle_cpu_ivt),
- INTEL_CPU_FAM6(HASWELL_CORE, idle_cpu_hsw),
+ INTEL_CPU_FAM6(HASWELL, idle_cpu_hsw),
INTEL_CPU_FAM6(HASWELL_X, idle_cpu_hsw),
- INTEL_CPU_FAM6(HASWELL_ULT, idle_cpu_hsw),
- INTEL_CPU_FAM6(HASWELL_GT3E, idle_cpu_hsw),
- INTEL_CPU_FAM6(ATOM_SILVERMONT_X, idle_cpu_avn),
- INTEL_CPU_FAM6(BROADWELL_CORE, idle_cpu_bdw),
- INTEL_CPU_FAM6(BROADWELL_GT3E, idle_cpu_bdw),
+ INTEL_CPU_FAM6(HASWELL_L, idle_cpu_hsw),
+ INTEL_CPU_FAM6(HASWELL_G, idle_cpu_hsw),
+ INTEL_CPU_FAM6(ATOM_SILVERMONT_D, idle_cpu_avn),
+ INTEL_CPU_FAM6(BROADWELL, idle_cpu_bdw),
+ INTEL_CPU_FAM6(BROADWELL_G, idle_cpu_bdw),
INTEL_CPU_FAM6(BROADWELL_X, idle_cpu_bdw),
- INTEL_CPU_FAM6(BROADWELL_XEON_D, idle_cpu_bdw),
- INTEL_CPU_FAM6(SKYLAKE_MOBILE, idle_cpu_skl),
- INTEL_CPU_FAM6(SKYLAKE_DESKTOP, idle_cpu_skl),
- INTEL_CPU_FAM6(KABYLAKE_MOBILE, idle_cpu_skl),
- INTEL_CPU_FAM6(KABYLAKE_DESKTOP, idle_cpu_skl),
+ INTEL_CPU_FAM6(BROADWELL_D, idle_cpu_bdw),
+ INTEL_CPU_FAM6(SKYLAKE_L, idle_cpu_skl),
+ INTEL_CPU_FAM6(SKYLAKE, idle_cpu_skl),
+ INTEL_CPU_FAM6(KABYLAKE_L, idle_cpu_skl),
+ INTEL_CPU_FAM6(KABYLAKE, idle_cpu_skl),
INTEL_CPU_FAM6(SKYLAKE_X, idle_cpu_skx),
INTEL_CPU_FAM6(XEON_PHI_KNL, idle_cpu_knl),
INTEL_CPU_FAM6(XEON_PHI_KNM, idle_cpu_knl),
INTEL_CPU_FAM6(ATOM_GOLDMONT, idle_cpu_bxt),
INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, idle_cpu_bxt),
- INTEL_CPU_FAM6(ATOM_GOLDMONT_X, idle_cpu_dnv),
- INTEL_CPU_FAM6(ATOM_TREMONT_X, idle_cpu_dnv),
+ INTEL_CPU_FAM6(ATOM_GOLDMONT_D, idle_cpu_dnv),
+ INTEL_CPU_FAM6(ATOM_TREMONT_D, idle_cpu_dnv),
{}
};
@@ -1311,7 +1311,7 @@ static void intel_idle_state_table_update(void)
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
bxt_idle_state_table_update();
break;
- case INTEL_FAM6_SKYLAKE_DESKTOP:
+ case INTEL_FAM6_SKYLAKE:
sklh_idle_state_table_update();
break;
}
diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c
index 46bb2e421bb9..ad19d9c716f4 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = {
.modified = 1, \
.info_mask_separate = \
BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
.ext_info = cros_ec_accel_legacy_ext_info, \
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7e3286265a38..f0af3a42f53c 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -958,7 +958,7 @@ config TI_ADC161S626
config TI_ADS1015
tristate "Texas Instruments ADS1015 ADC"
- depends on I2C && !SENSORS_ADS1015
+ depends on I2C
select REGMAP_I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index 92b1d5037ac9..e234970b7150 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -11,6 +11,7 @@
#include <linux/iio/iio.h>
#include <linux/io.h>
#include <linux/iopoll.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
@@ -22,8 +23,11 @@
#define JZ_ADC_REG_ADTCH 0x18
#define JZ_ADC_REG_ADBDAT 0x1c
#define JZ_ADC_REG_ADSDAT 0x20
+#define JZ_ADC_REG_ADCLK 0x28
#define JZ_ADC_REG_CFG_BAT_MD BIT(4)
+#define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
+#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB 16
#define JZ_ADC_AUX_VREF 3300
#define JZ_ADC_AUX_VREF_BITS 12
@@ -34,6 +38,8 @@
#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
+struct ingenic_adc;
+
struct ingenic_adc_soc_data {
unsigned int battery_high_vref;
unsigned int battery_high_vref_bits;
@@ -41,6 +47,7 @@ struct ingenic_adc_soc_data {
size_t battery_raw_avail_size;
const int *battery_scale_avail;
size_t battery_scale_avail_size;
+ int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
};
struct ingenic_adc {
@@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = {
JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
};
+static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+ struct clk *parent_clk;
+ unsigned long parent_rate, rate;
+ unsigned int div_main, div_10us;
+
+ parent_clk = clk_get_parent(adc->clk);
+ if (!parent_clk) {
+ dev_err(dev, "ADC clock has no parent\n");
+ return -ENODEV;
+ }
+ parent_rate = clk_get_rate(parent_clk);
+
+ /*
+ * The JZ4725B ADC works at 500 kHz to 8 MHz.
+ * We pick the highest rate possible.
+ * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
+ */
+ div_main = DIV_ROUND_UP(parent_rate, 8000000);
+ div_main = clamp(div_main, 1u, 64u);
+ rate = parent_rate / div_main;
+ if (rate < 500000 || rate > 8000000) {
+ dev_err(dev, "No valid divider for ADC main clock\n");
+ return -EINVAL;
+ }
+
+ /* We also need a divider that produces a 10us clock. */
+ div_10us = DIV_ROUND_UP(rate, 100000);
+
+ writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+ (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+ adc->base + JZ_ADC_REG_ADCLK);
+
+ return 0;
+}
+
static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
.battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
.battery_scale_avail = jz4725b_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+ .init_clk_div = jz4725b_adc_init_clk_div,
};
static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
@@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
.battery_scale_avail = jz4740_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+ .init_clk_div = NULL, /* no ADCLK register on JZ4740 */
};
static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
@@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev)
return ret;
}
+ /* Set clock dividers. */
+ if (soc_data->init_clk_div) {
+ ret = soc_data->init_clk_div(dev, adc);
+ if (ret) {
+ clk_disable_unprepare(adc->clk);
+ return ret;
+ }
+ }
+
/* Put hardware in a known passive state. */
writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c
index 917223d5ff5b..da073d72f649 100644
--- a/drivers/iio/adc/max9611.c
+++ b/drivers/iio/adc/max9611.c
@@ -83,7 +83,7 @@
#define MAX9611_TEMP_MAX_POS 0x7f80
#define MAX9611_TEMP_MAX_NEG 0xff80
#define MAX9611_TEMP_MIN_NEG 0xd980
-#define MAX9611_TEMP_MASK GENMASK(7, 15)
+#define MAX9611_TEMP_MASK GENMASK(15, 7)
#define MAX9611_TEMP_SHIFT 0x07
#define MAX9611_TEMP_RAW(_r) ((_r) >> MAX9611_TEMP_SHIFT)
#define MAX9611_TEMP_SCALE_NUM 1000000
@@ -480,7 +480,7 @@ static int max9611_init(struct max9611_dev *max9611)
if (ret)
return ret;
- regval = ret & MAX9611_TEMP_MASK;
+ regval &= MAX9611_TEMP_MASK;
if ((regval > MAX9611_TEMP_MAX_POS &&
regval < MAX9611_TEMP_MIN_NEG) ||
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 2d685730f867..c37f201294b2 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
dev_err(dev,
"Only %i channels supported with %pOFn, but reg = <%i>.\n",
num_channels, child, reg);
- return ret;
+ return -EINVAL;
}
}
@@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
dev_err(dev,
"Channel %i uses different ADC mode than the rest.\n",
reg);
- return ret;
+ return -EINVAL;
}
/* Channel is valid, grab the regulator. */
diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c
index e48f15cc9ab5..ff82863cbf42 100644
--- a/drivers/iio/frequency/adf4371.c
+++ b/drivers/iio/frequency/adf4371.c
@@ -276,11 +276,11 @@ static int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq,
st->buf[0] = st->integer >> 8;
st->buf[1] = 0x40; /* REG12 default */
st->buf[2] = 0x00;
- st->buf[3] = st->fract2 & 0xFF;
- st->buf[4] = st->fract2 >> 7;
- st->buf[5] = st->fract2 >> 15;
+ st->buf[3] = st->fract1 & 0xFF;
+ st->buf[4] = st->fract1 >> 8;
+ st->buf[5] = st->fract1 >> 16;
st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) |
- ADF4371_FRAC1WORD(st->fract1 >> 23);
+ ADF4371_FRAC1WORD(st->fract1 >> 24);
st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7);
st->buf[8] = st->mod2 & 0xFF;
st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 53a59957cc54..8a704cd5bddb 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -845,6 +845,25 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
};
+static const unsigned long inv_mpu_scan_masks[] = {
+ /* 3-axis accel */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z),
+ /* 3-axis gyro */
+ BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z),
+ /* 6-axis accel + gyro */
+ BIT(INV_MPU6050_SCAN_ACCL_X)
+ | BIT(INV_MPU6050_SCAN_ACCL_Y)
+ | BIT(INV_MPU6050_SCAN_ACCL_Z)
+ | BIT(INV_MPU6050_SCAN_GYRO_X)
+ | BIT(INV_MPU6050_SCAN_GYRO_Y)
+ | BIT(INV_MPU6050_SCAN_GYRO_Z),
+ 0,
+};
+
static const struct iio_chan_spec inv_icm20602_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
{
@@ -871,6 +890,28 @@ static const struct iio_chan_spec inv_icm20602_channels[] = {
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z),
};
+static const unsigned long inv_icm20602_scan_masks[] = {
+ /* 3-axis accel + temp (mandatory) */
+ BIT(INV_ICM20602_SCAN_ACCL_X)
+ | BIT(INV_ICM20602_SCAN_ACCL_Y)
+ | BIT(INV_ICM20602_SCAN_ACCL_Z)
+ | BIT(INV_ICM20602_SCAN_TEMP),
+ /* 3-axis gyro + temp (mandatory) */
+ BIT(INV_ICM20602_SCAN_GYRO_X)
+ | BIT(INV_ICM20602_SCAN_GYRO_Y)
+ | BIT(INV_ICM20602_SCAN_GYRO_Z)
+ | BIT(INV_ICM20602_SCAN_TEMP),
+ /* 6-axis accel + gyro + temp (mandatory) */
+ BIT(INV_ICM20602_SCAN_ACCL_X)
+ | BIT(INV_ICM20602_SCAN_ACCL_Y)
+ | BIT(INV_ICM20602_SCAN_ACCL_Z)
+ | BIT(INV_ICM20602_SCAN_GYRO_X)
+ | BIT(INV_ICM20602_SCAN_GYRO_Y)
+ | BIT(INV_ICM20602_SCAN_GYRO_Z)
+ | BIT(INV_ICM20602_SCAN_TEMP),
+ 0,
+};
+
/*
* The user can choose any frequency between INV_MPU6050_MIN_FIFO_RATE and
* INV_MPU6050_MAX_FIFO_RATE, but only these frequencies are matched by the
@@ -1130,9 +1171,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
if (chip_type == INV_ICM20602) {
indio_dev->channels = inv_icm20602_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels);
+ indio_dev->available_scan_masks = inv_icm20602_scan_masks;
} else {
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+ indio_dev->available_scan_masks = inv_mpu_scan_masks;
}
indio_dev->info = &mpu_info;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 19f1730a4f24..a68d0ccf67a4 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -4724,10 +4724,14 @@ static int __init cma_init(void)
if (ret)
goto err;
- cma_configfs_init();
+ ret = cma_configfs_init();
+ if (ret)
+ goto err_ib;
return 0;
+err_ib:
+ ib_unregister_client(&cma_client);
err:
unregister_netdevice_notifier(&cma_nb);
ib_sa_unregister_client(&sa_client);
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 888d89ce81df..beee7b7e0d9a 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -302,7 +302,9 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
struct ib_udata *udata,
struct ib_uobject *uobj)
{
+ enum ib_qp_type qp_type = attr->qp_type;
struct ib_qp *qp;
+ bool is_xrc;
if (!dev->ops.create_qp)
return ERR_PTR(-EOPNOTSUPP);
@@ -320,7 +322,8 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
* and more importantly they are created internaly by driver,
* see mlx5 create_dev_resources() as an example.
*/
- if (attr->qp_type < IB_QPT_XRC_INI) {
+ is_xrc = qp_type == IB_QPT_XRC_INI || qp_type == IB_QPT_XRC_TGT;
+ if ((qp_type < IB_QPT_MAX && !is_xrc) || qp_type == IB_QPT_DRIVER) {
qp->res.type = RDMA_RESTRACK_QP;
if (uobj)
rdma_restrack_uadd(&qp->res);
diff --git a/drivers/infiniband/core/counters.c b/drivers/infiniband/core/counters.c
index 01faef7bc061..af8c85d18e62 100644
--- a/drivers/infiniband/core/counters.c
+++ b/drivers/infiniband/core/counters.c
@@ -38,6 +38,9 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,
int ret;
port_counter = &dev->port_data[port].port_counter;
+ if (!port_counter->hstats)
+ return -EOPNOTSUPP;
+
mutex_lock(&port_counter->lock);
if (on) {
ret = __counter_set_mode(&port_counter->mode,
@@ -146,13 +149,11 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
struct auto_mode_param *param = &counter->mode.param;
bool match = true;
- if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res))
+ if (!rdma_is_visible_in_pid_ns(&qp->res))
return false;
- /* Ensure that counter belong to right PID */
- if (!rdma_is_kernel_res(&counter->res) &&
- !rdma_is_kernel_res(&qp->res) &&
- (task_pid_vnr(counter->res.task) != current->pid))
+ /* Ensure that counter belongs to the right PID */
+ if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task))
return false;
if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
@@ -393,6 +394,9 @@ u64 rdma_counter_get_hwstat_value(struct ib_device *dev, u8 port, u32 index)
u64 sum;
port_counter = &dev->port_data[port].port_counter;
+ if (!port_counter->hstats)
+ return 0;
+
sum = get_running_counters_hwstat_sum(dev, port, index);
sum += port_counter->hstats->value[index];
@@ -418,7 +422,7 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
return qp;
err:
- rdma_restrack_put(&qp->res);
+ rdma_restrack_put(res);
return NULL;
}
@@ -506,6 +510,9 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
if (!rdma_is_port_valid(dev, port))
return -EINVAL;
+ if (!dev->port_data[port].port_counter.hstats)
+ return -EOPNOTSUPP;
+
qp = rdma_counter_get_qp(dev, qp_num);
if (!qp)
return -ENOENT;
@@ -594,7 +601,7 @@ void rdma_counter_init(struct ib_device *dev)
struct rdma_port_counter *port_counter;
u32 port;
- if (!dev->ops.alloc_hw_stats || !dev->port_data)
+ if (!dev->port_data)
return;
rdma_for_each_port(dev, port) {
@@ -602,6 +609,9 @@ void rdma_counter_init(struct ib_device *dev)
port_counter->mode.mode = RDMA_COUNTER_MODE_NONE;
mutex_init(&port_counter->lock);
+ if (!dev->ops.alloc_hw_stats)
+ continue;
+
port_counter->hstats = dev->ops.alloc_hw_stats(dev, port);
if (!port_counter->hstats)
goto fail;
@@ -624,9 +634,6 @@ void rdma_counter_release(struct ib_device *dev)
struct rdma_port_counter *port_counter;
u32 port;
- if (!dev->ops.alloc_hw_stats)
- return;
-
rdma_for_each_port(dev, port) {
port_counter = &dev->port_data[port].port_counter;
kfree(port_counter->hstats);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 9773145dee09..ea8661a00651 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -94,11 +94,17 @@ static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC);
static DECLARE_RWSEM(devices_rwsem);
#define DEVICE_REGISTERED XA_MARK_1
-static LIST_HEAD(client_list);
+static u32 highest_client_id;
#define CLIENT_REGISTERED XA_MARK_1
static DEFINE_XARRAY_FLAGS(clients, XA_FLAGS_ALLOC);
static DECLARE_RWSEM(clients_rwsem);
+static void ib_client_put(struct ib_client *client)
+{
+ if (refcount_dec_and_test(&client->uses))
+ complete(&client->uses_zero);
+}
+
/*
* If client_data is registered then the corresponding client must also still
* be registered.
@@ -661,6 +667,14 @@ static int add_client_context(struct ib_device *device,
down_write(&device->client_data_rwsem);
/*
+ * So long as the client is registered hold both the client and device
+ * unregistration locks.
+ */
+ if (!refcount_inc_not_zero(&client->uses))
+ goto out_unlock;
+ refcount_inc(&device->refcount);
+
+ /*
* Another caller to add_client_context got here first and has already
* completely initialized context.
*/
@@ -683,6 +697,9 @@ static int add_client_context(struct ib_device *device,
return 0;
out:
+ ib_device_put(device);
+ ib_client_put(client);
+out_unlock:
up_write(&device->client_data_rwsem);
return ret;
}
@@ -702,7 +719,7 @@ static void remove_client_context(struct ib_device *device,
client_data = xa_load(&device->client_data, client_id);
xa_clear_mark(&device->client_data, client_id, CLIENT_DATA_REGISTERED);
client = xa_load(&clients, client_id);
- downgrade_write(&device->client_data_rwsem);
+ up_write(&device->client_data_rwsem);
/*
* Notice we cannot be holding any exclusive locks when calling the
@@ -712,17 +729,13 @@ static void remove_client_context(struct ib_device *device,
*
* For this reason clients and drivers should not call the
* unregistration functions will holdling any locks.
- *
- * It tempting to drop the client_data_rwsem too, but this is required
- * to ensure that unregister_client does not return until all clients
- * are completely unregistered, which is required to avoid module
- * unloading races.
*/
if (client->remove)
client->remove(device, client_data);
xa_erase(&device->client_data, client_id);
- up_read(&device->client_data_rwsem);
+ ib_device_put(device);
+ ib_client_put(client);
}
static int alloc_port_data(struct ib_device *device)
@@ -1224,7 +1237,7 @@ static int setup_device(struct ib_device *device)
static void disable_device(struct ib_device *device)
{
- struct ib_client *client;
+ u32 cid;
WARN_ON(!refcount_read(&device->refcount));
@@ -1232,10 +1245,19 @@ static void disable_device(struct ib_device *device)
xa_clear_mark(&devices, device->index, DEVICE_REGISTERED);
up_write(&devices_rwsem);
+ /*
+ * Remove clients in LIFO order, see assign_client_id. This could be
+ * more efficient if xarray learns to reverse iterate. Since no new
+ * clients can be added to this ib_device past this point we only need
+ * the maximum possible client_id value here.
+ */
down_read(&clients_rwsem);
- list_for_each_entry_reverse(client, &client_list, list)
- remove_client_context(device, client->client_id);
+ cid = highest_client_id;
up_read(&clients_rwsem);
+ while (cid) {
+ cid--;
+ remove_client_context(device, cid);
+ }
/* Pairs with refcount_set in enable_device */
ib_device_put(device);
@@ -1662,30 +1684,31 @@ static int assign_client_id(struct ib_client *client)
/*
* The add/remove callbacks must be called in FIFO/LIFO order. To
* achieve this we assign client_ids so they are sorted in
- * registration order, and retain a linked list we can reverse iterate
- * to get the LIFO order. The extra linked list can go away if xarray
- * learns to reverse iterate.
+ * registration order.
*/
- if (list_empty(&client_list)) {
- client->client_id = 0;
- } else {
- struct ib_client *last;
-
- last = list_last_entry(&client_list, struct ib_client, list);
- client->client_id = last->client_id + 1;
- }
+ client->client_id = highest_client_id;
ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
if (ret)
goto out;
+ highest_client_id++;
xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);
- list_add_tail(&client->list, &client_list);
out:
up_write(&clients_rwsem);
return ret;
}
+static void remove_client_id(struct ib_client *client)
+{
+ down_write(&clients_rwsem);
+ xa_erase(&clients, client->client_id);
+ for (; highest_client_id; highest_client_id--)
+ if (xa_load(&clients, highest_client_id - 1))
+ break;
+ up_write(&clients_rwsem);
+}
+
/**
* ib_register_client - Register an IB client
* @client:Client to register
@@ -1705,6 +1728,8 @@ int ib_register_client(struct ib_client *client)
unsigned long index;
int ret;
+ refcount_set(&client->uses, 1);
+ init_completion(&client->uses_zero);
ret = assign_client_id(client);
if (ret)
return ret;
@@ -1740,21 +1765,30 @@ void ib_unregister_client(struct ib_client *client)
unsigned long index;
down_write(&clients_rwsem);
+ ib_client_put(client);
xa_clear_mark(&clients, client->client_id, CLIENT_REGISTERED);
up_write(&clients_rwsem);
- /*
- * Every device still known must be serialized to make sure we are
- * done with the client callbacks before we return.
- */
- down_read(&devices_rwsem);
- xa_for_each (&devices, index, device)
+
+ /* We do not want to have locks while calling client->remove() */
+ rcu_read_lock();
+ xa_for_each (&devices, index, device) {
+ if (!ib_device_try_get(device))
+ continue;
+ rcu_read_unlock();
+
remove_client_context(device, client->client_id);
- up_read(&devices_rwsem);
- down_write(&clients_rwsem);
- list_del(&client->list);
- xa_erase(&clients, client->client_id);
- up_write(&clients_rwsem);
+ ib_device_put(device);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+
+ /*
+ * remove_client_context() is not a fence, it can return even though a
+ * removal is ongoing. Wait until all removals are completed.
+ */
+ wait_for_completion(&client->uses_zero);
+ remove_client_id(client);
}
EXPORT_SYMBOL(ib_unregister_client);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index cc99479b2c09..9947d16edef2 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -3224,18 +3224,18 @@ static int ib_mad_port_open(struct ib_device *device,
if (has_smi)
cq_size *= 2;
+ port_priv->pd = ib_alloc_pd(device, 0);
+ if (IS_ERR(port_priv->pd)) {
+ dev_err(&device->dev, "Couldn't create ib_mad PD\n");
+ ret = PTR_ERR(port_priv->pd);
+ goto error3;
+ }
+
port_priv->cq = ib_alloc_cq(port_priv->device, port_priv, cq_size, 0,
IB_POLL_UNBOUND_WORKQUEUE);
if (IS_ERR(port_priv->cq)) {
dev_err(&device->dev, "Couldn't create ib_mad CQ\n");
ret = PTR_ERR(port_priv->cq);
- goto error3;
- }
-
- port_priv->pd = ib_alloc_pd(device, 0);
- if (IS_ERR(port_priv->pd)) {
- dev_err(&device->dev, "Couldn't create ib_mad PD\n");
- ret = PTR_ERR(port_priv->pd);
goto error4;
}
@@ -3278,11 +3278,11 @@ error8:
error7:
destroy_mad_qp(&port_priv->qp_info[0]);
error6:
- ib_dealloc_pd(port_priv->pd);
-error4:
ib_free_cq(port_priv->cq);
cleanup_recv_queue(&port_priv->qp_info[1]);
cleanup_recv_queue(&port_priv->qp_info[0]);
+error4:
+ ib_dealloc_pd(port_priv->pd);
error3:
kfree(port_priv);
@@ -3312,8 +3312,8 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
destroy_workqueue(port_priv->wq);
destroy_mad_qp(&port_priv->qp_info[1]);
destroy_mad_qp(&port_priv->qp_info[0]);
- ib_dealloc_pd(port_priv->pd);
ib_free_cq(port_priv->cq);
+ ib_dealloc_pd(port_priv->pd);
cleanup_recv_queue(&port_priv->qp_info[1]);
cleanup_recv_queue(&port_priv->qp_info[0]);
/* XXX: Handle deallocation of MAD registration tables */
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 783e465e7c41..020c26976558 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -382,8 +382,7 @@ static int fill_res_info(struct sk_buff *msg, struct ib_device *device)
for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
if (!names[i])
continue;
- curr = rdma_restrack_count(device, i,
- task_active_pid_ns(current));
+ curr = rdma_restrack_count(device, i);
ret = fill_res_info_entry(msg, names[i], curr);
if (ret)
goto err;
@@ -1952,12 +1951,16 @@ static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,
if (fill_nldev_handle(msg, device) ||
nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
- nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode))
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {
+ ret = -EMSGSIZE;
goto err_msg;
+ }
if ((mode == RDMA_COUNTER_MODE_AUTO) &&
- nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask))
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {
+ ret = -EMSGSIZE;
goto err_msg;
+ }
nlmsg_end(msg, nlh);
ib_device_put(device);
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index bddff426ee0f..a07665f7ef8c 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -107,10 +107,8 @@ void rdma_restrack_clean(struct ib_device *dev)
* rdma_restrack_count() - the current usage of specific object
* @dev: IB device
* @type: actual type of object to operate
- * @ns: PID namespace
*/
-int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
- struct pid_namespace *ns)
+int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type)
{
struct rdma_restrack_root *rt = &dev->res[type];
struct rdma_restrack_entry *e;
@@ -119,10 +117,9 @@ int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
xa_lock(&rt->xa);
xas_for_each(&xas, e, U32_MAX) {
- if (ns == &init_pid_ns ||
- (!rdma_is_kernel_res(e) &&
- ns == task_active_pid_ns(e->task)))
- cnt++;
+ if (!rdma_is_visible_in_pid_ns(e))
+ continue;
+ cnt++;
}
xa_unlock(&rt->xa);
return cnt;
@@ -360,5 +357,7 @@ bool rdma_is_visible_in_pid_ns(struct rdma_restrack_entry *res)
*/
if (rdma_is_kernel_res(res))
return task_active_pid_ns(current) == &init_pid_ns;
- return task_active_pid_ns(current) == task_active_pid_ns(res->task);
+
+ /* PID 0 means that resource is not found in current namespace */
+ return task_pid_vnr(res->task);
}
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 08da840ed7ee..56553668256f 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -379,14 +379,9 @@ EXPORT_SYMBOL(ib_umem_release);
int ib_umem_page_count(struct ib_umem *umem)
{
- int i;
- int n;
+ int i, n = 0;
struct scatterlist *sg;
- if (umem->is_odp)
- return ib_umem_num_pages(umem);
-
- n = 0;
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i)
n += sg_dma_len(sg) >> PAGE_SHIFT;
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index 2a75c6f8d827..c0e15db34680 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -112,10 +112,6 @@ static int ib_umem_notifier_release_trampoline(struct ib_umem_odp *umem_odp,
* prevent any further fault handling on this MR.
*/
ib_umem_notifier_start_account(umem_odp);
- umem_odp->dying = 1;
- /* Make sure that the fact the umem is dying is out before we release
- * all pending page faults. */
- smp_wmb();
complete_all(&umem_odp->notifier_completion);
umem_odp->umem.context->invalidate_range(
umem_odp, ib_umem_start(umem_odp), ib_umem_end(umem_odp));
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 9f8a48016b41..ffdeaf6e0b68 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -49,6 +49,7 @@
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
+#include <linux/nospec.h>
#include <linux/uaccess.h>
@@ -884,11 +885,14 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
if (get_user(id, arg))
return -EFAULT;
+ if (id >= IB_UMAD_MAX_AGENTS)
+ return -EINVAL;
mutex_lock(&file->port->file_mutex);
mutex_lock(&file->mutex);
- if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+ id = array_index_nospec(id, IB_UMAD_MAX_AGENTS);
+ if (!__get_agent(file, id)) {
ret = -EINVAL;
goto out;
}
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index a91653aabf38..098ab883733e 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -308,6 +308,7 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
struct bnxt_qplib_gid *gid_to_del;
+ u16 vlan_id = 0xFFFF;
/* Delete the entry from the hardware */
ctx = *context;
@@ -317,7 +318,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
if (sgid_tbl && sgid_tbl->active) {
if (ctx->idx >= sgid_tbl->max)
return -EINVAL;
- gid_to_del = &sgid_tbl->tbl[ctx->idx];
+ gid_to_del = &sgid_tbl->tbl[ctx->idx].gid;
+ vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id;
/* DEL_GID is called in WQ context(netdevice_event_work_handler)
* or via the ib_unregister_device path. In the former case QP1
* may not be destroyed yet, in which case just return as FW
@@ -335,7 +337,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
}
ctx->refcnt--;
if (!ctx->refcnt) {
- rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del, true);
+ rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
+ vlan_id, true);
if (rc) {
dev_err(rdev_to_dev(rdev),
"Failed to remove GID: %#x", rc);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 48b04d2f175f..60c8f76aab33 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -136,6 +136,13 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
spin_unlock_irqrestore(&cmdq->lock, flags);
return -EBUSY;
}
+
+ size = req->cmd_size;
+ /* change the cmd_size to the number of 16byte cmdq unit.
+ * req->cmd_size is modified here
+ */
+ bnxt_qplib_set_cmd_slots(req);
+
memset(resp, 0, sizeof(*resp));
crsqe->resp = (struct creq_qp_event *)resp;
crsqe->resp->cookie = req->cookie;
@@ -150,7 +157,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
preq = (u8 *)req;
- size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
do {
/* Locate the next cmdq slot */
sw_prod = HWQ_CMP(cmdq->prod, cmdq);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
index 2138533bb642..dfeadc192e17 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
@@ -55,9 +55,7 @@
do { \
memset(&(req), 0, sizeof((req))); \
(req).opcode = CMDQ_BASE_OPCODE_##CMD; \
- (req).cmd_size = (sizeof((req)) + \
- BNXT_QPLIB_CMDQE_UNITS - 1) / \
- BNXT_QPLIB_CMDQE_UNITS; \
+ (req).cmd_size = sizeof((req)); \
(req).flags = cpu_to_le16(cmd_flags); \
} while (0)
@@ -95,6 +93,13 @@ static inline u32 bnxt_qplib_cmdqe_cnt_per_pg(u32 depth)
BNXT_QPLIB_CMDQE_UNITS);
}
+/* Set the cmd_size to a factor of CMDQE unit */
+static inline void bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
+{
+ req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+ BNXT_QPLIB_CMDQE_UNITS;
+}
+
#define MAX_CMDQ_IDX(depth) ((depth) - 1)
static inline u32 bnxt_qplib_max_cmdq_idx_per_pg(u32 depth)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 37928b1111df..bdbde8e22420 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -488,7 +488,7 @@ static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res,
struct bnxt_qplib_sgid_tbl *sgid_tbl,
u16 max)
{
- sgid_tbl->tbl = kcalloc(max, sizeof(struct bnxt_qplib_gid), GFP_KERNEL);
+ sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL);
if (!sgid_tbl->tbl)
return -ENOMEM;
@@ -526,9 +526,10 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
for (i = 0; i < sgid_tbl->max; i++) {
if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero)))
- bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i], true);
+ bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid,
+ sgid_tbl->tbl[i].vlan_id, true);
}
- memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max);
+ memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max);
memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max);
sgid_tbl->active = 0;
@@ -537,7 +538,11 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct net_device *netdev)
{
- memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max);
+ u32 i;
+
+ for (i = 0; i < sgid_tbl->max; i++)
+ sgid_tbl->tbl[i].vlan_id = 0xffff;
+
memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
}
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index 30c42c92fac7..fbda11a7ab1a 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -111,7 +111,7 @@ struct bnxt_qplib_pd_tbl {
};
struct bnxt_qplib_sgid_tbl {
- struct bnxt_qplib_gid *tbl;
+ struct bnxt_qplib_gid_info *tbl;
u16 *hw_id;
u16 max;
u16 active;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index 48793d3512ac..40296b97d21e 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -213,12 +213,12 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
index, sgid_tbl->max);
return -EINVAL;
}
- memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid));
+ memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid));
return 0;
}
int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
- struct bnxt_qplib_gid *gid, bool update)
+ struct bnxt_qplib_gid *gid, u16 vlan_id, bool update)
{
struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
struct bnxt_qplib_res,
@@ -236,7 +236,8 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
return -ENOMEM;
}
for (index = 0; index < sgid_tbl->max; index++) {
- if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid)))
+ if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) &&
+ vlan_id == sgid_tbl->tbl[index].vlan_id)
break;
}
if (index == sgid_tbl->max) {
@@ -262,8 +263,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
if (rc)
return rc;
}
- memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
+ memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero));
+ sgid_tbl->tbl[index].vlan_id = 0xFFFF;
sgid_tbl->vlan[index] = 0;
sgid_tbl->active--;
dev_dbg(&res->pdev->dev,
@@ -296,7 +298,8 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
}
free_idx = sgid_tbl->max;
for (i = 0; i < sgid_tbl->max; i++) {
- if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) {
+ if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) &&
+ sgid_tbl->tbl[i].vlan_id == vlan_id) {
dev_dbg(&res->pdev->dev,
"SGID entry already exist in entry %d!\n", i);
*index = i;
@@ -351,6 +354,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
}
/* Add GID to the sgid_tbl */
memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
+ sgid_tbl->tbl[free_idx].vlan_id = vlan_id;
sgid_tbl->active++;
if (vlan_id != 0xFFFF)
sgid_tbl->vlan[free_idx] = 1;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
index 0ec3b12b0bcd..13d9432d5ce2 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -84,6 +84,11 @@ struct bnxt_qplib_gid {
u8 data[16];
};
+struct bnxt_qplib_gid_info {
+ struct bnxt_qplib_gid gid;
+ u16 vlan_id;
+};
+
struct bnxt_qplib_ah {
struct bnxt_qplib_gid dgid;
struct bnxt_qplib_pd *pd;
@@ -221,7 +226,7 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
struct bnxt_qplib_gid *gid);
int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
- struct bnxt_qplib_gid *gid, bool update);
+ struct bnxt_qplib_gid *gid, u16 vlan_id, bool update);
int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, u8 *mac, u16 vlan_id,
bool update, u32 *index);
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index d5b643a1d9fd..67052dc3100c 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -14452,7 +14452,7 @@ void hfi1_deinit_vnic_rsm(struct hfi1_devdata *dd)
clear_rcvctrl(dd, RCV_CTRL_RCV_RSM_ENABLE_SMASK);
}
-static void init_rxe(struct hfi1_devdata *dd)
+static int init_rxe(struct hfi1_devdata *dd)
{
struct rsm_map_table *rmt;
u64 val;
@@ -14461,6 +14461,9 @@ static void init_rxe(struct hfi1_devdata *dd)
write_csr(dd, RCV_ERR_MASK, ~0ull);
rmt = alloc_rsm_map_table(dd);
+ if (!rmt)
+ return -ENOMEM;
+
/* set up QOS, including the QPN map table */
init_qos(dd, rmt);
init_fecn_handling(dd, rmt);
@@ -14487,6 +14490,7 @@ static void init_rxe(struct hfi1_devdata *dd)
val |= ((4ull & RCV_BYPASS_HDR_SIZE_MASK) <<
RCV_BYPASS_HDR_SIZE_SHIFT);
write_csr(dd, RCV_BYPASS, val);
+ return 0;
}
static void init_other(struct hfi1_devdata *dd)
@@ -15024,7 +15028,10 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
goto bail_cleanup;
/* set initial RXE CSRs */
- init_rxe(dd);
+ ret = init_rxe(dd);
+ if (ret)
+ goto bail_cleanup;
+
/* set initial TXE CSRs */
init_txe(dd);
/* set initial non-RXE, non-TXE CSRs */
diff --git a/drivers/infiniband/hw/hfi1/fault.c b/drivers/infiniband/hw/hfi1/fault.c
index 93613e5def9b..986c12153e62 100644
--- a/drivers/infiniband/hw/hfi1/fault.c
+++ b/drivers/infiniband/hw/hfi1/fault.c
@@ -141,12 +141,14 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
if (!data)
return -ENOMEM;
copy = min(len, datalen - 1);
- if (copy_from_user(data, buf, copy))
- return -EFAULT;
+ if (copy_from_user(data, buf, copy)) {
+ ret = -EFAULT;
+ goto free_data;
+ }
ret = debugfs_file_get(file->f_path.dentry);
if (unlikely(ret))
- return ret;
+ goto free_data;
ptr = data;
token = ptr;
for (ptr = data; *ptr; ptr = end + 1, token = ptr) {
@@ -195,6 +197,7 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
ret = len;
debugfs_file_put(file->f_path.dentry);
+free_data:
kfree(data);
return ret;
}
@@ -214,7 +217,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
return -ENOMEM;
ret = debugfs_file_get(file->f_path.dentry);
if (unlikely(ret))
- return ret;
+ goto free_data;
bit = find_first_bit(fault->opcodes, bitsize);
while (bit < bitsize) {
zero = find_next_zero_bit(fault->opcodes, bitsize, bit);
@@ -232,6 +235,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
data[size - 1] = '\n';
data[size] = '\0';
ret = simple_read_from_buffer(buf, len, pos, data, size);
+free_data:
kfree(data);
return ret;
}
diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c
index 0477c14633ab..024a7c2b6124 100644
--- a/drivers/infiniband/hw/hfi1/rc.c
+++ b/drivers/infiniband/hw/hfi1/rc.c
@@ -1835,7 +1835,6 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah)
cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)
break;
trdma_clean_swqe(qp, wqe);
- rvt_qp_wqe_unreserve(qp, wqe);
trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
rvt_qp_complete_swqe(qp,
wqe,
@@ -1882,7 +1881,6 @@ struct rvt_swqe *do_rc_completion(struct rvt_qp *qp,
if (cmp_psn(wqe->lpsn, qp->s_sending_psn) < 0 ||
cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
trdma_clean_swqe(qp, wqe);
- rvt_qp_wqe_unreserve(qp, wqe);
trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
rvt_qp_complete_swqe(qp,
wqe,
diff --git a/drivers/infiniband/hw/hfi1/tid_rdma.c b/drivers/infiniband/hw/hfi1/tid_rdma.c
index 92acccaaaa86..6141f4edc6bf 100644
--- a/drivers/infiniband/hw/hfi1/tid_rdma.c
+++ b/drivers/infiniband/hw/hfi1/tid_rdma.c
@@ -1620,6 +1620,7 @@ static int hfi1_kern_exp_rcv_alloc_flows(struct tid_rdma_request *req,
flows[i].req = req;
flows[i].npagesets = 0;
flows[i].pagesets[0].mapped = 0;
+ flows[i].resync_npkts = 0;
}
req->flows = flows;
return 0;
@@ -1673,34 +1674,6 @@ static struct tid_rdma_flow *find_flow_ib(struct tid_rdma_request *req,
return NULL;
}
-static struct tid_rdma_flow *
-__find_flow_ranged(struct tid_rdma_request *req, u16 head, u16 tail,
- u32 psn, u16 *fidx)
-{
- for ( ; CIRC_CNT(head, tail, MAX_FLOWS);
- tail = CIRC_NEXT(tail, MAX_FLOWS)) {
- struct tid_rdma_flow *flow = &req->flows[tail];
- u32 spsn, lpsn;
-
- spsn = full_flow_psn(flow, flow->flow_state.spsn);
- lpsn = full_flow_psn(flow, flow->flow_state.lpsn);
-
- if (cmp_psn(psn, spsn) >= 0 && cmp_psn(psn, lpsn) <= 0) {
- if (fidx)
- *fidx = tail;
- return flow;
- }
- }
- return NULL;
-}
-
-static struct tid_rdma_flow *find_flow(struct tid_rdma_request *req,
- u32 psn, u16 *fidx)
-{
- return __find_flow_ranged(req, req->setup_head, req->clear_tail, psn,
- fidx);
-}
-
/* TID RDMA READ functions */
u32 hfi1_build_tid_rdma_read_packet(struct rvt_swqe *wqe,
struct ib_other_headers *ohdr, u32 *bth1,
@@ -2601,18 +2574,9 @@ void hfi1_kern_read_tid_flow_free(struct rvt_qp *qp)
hfi1_kern_clear_hw_flow(priv->rcd, qp);
}
-static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
- struct hfi1_packet *packet, u8 rcv_type,
- u8 opcode)
+static bool tid_rdma_tid_err(struct hfi1_packet *packet, u8 rcv_type)
{
struct rvt_qp *qp = packet->qp;
- struct hfi1_qp_priv *qpriv = qp->priv;
- u32 ipsn;
- struct ib_other_headers *ohdr = packet->ohdr;
- struct rvt_ack_entry *e;
- struct tid_rdma_request *req;
- struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
- u32 i;
if (rcv_type >= RHF_RCV_TYPE_IB)
goto done;
@@ -2629,41 +2593,9 @@ static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
if (rcv_type == RHF_RCV_TYPE_EAGER) {
hfi1_restart_rc(qp, qp->s_last_psn + 1, 1);
hfi1_schedule_send(qp);
- goto done_unlock;
- }
-
- /*
- * For TID READ response, error out QP after freeing the tid
- * resources.
- */
- if (opcode == TID_OP(READ_RESP)) {
- ipsn = mask_psn(be32_to_cpu(ohdr->u.tid_rdma.r_rsp.verbs_psn));
- if (cmp_psn(ipsn, qp->s_last_psn) > 0 &&
- cmp_psn(ipsn, qp->s_psn) < 0) {
- hfi1_kern_read_tid_flow_free(qp);
- spin_unlock(&qp->s_lock);
- rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
- goto done;
- }
- goto done_unlock;
}
- /*
- * Error out the qp for TID RDMA WRITE
- */
- hfi1_kern_clear_hw_flow(qpriv->rcd, qp);
- for (i = 0; i < rvt_max_atomic(rdi); i++) {
- e = &qp->s_ack_queue[i];
- if (e->opcode == TID_OP(WRITE_REQ)) {
- req = ack_to_tid_req(e);
- hfi1_kern_exp_rcv_clear_all(req);
- }
- }
- spin_unlock(&qp->s_lock);
- rvt_rc_error(qp, IB_WC_LOC_LEN_ERR);
- goto done;
-
-done_unlock:
+ /* Since no payload is delivered, just drop the packet */
spin_unlock(&qp->s_lock);
done:
return true;
@@ -2714,12 +2646,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
u32 fpsn;
lockdep_assert_held(&qp->r_lock);
+ spin_lock(&qp->s_lock);
/* If the psn is out of valid range, drop the packet */
if (cmp_psn(ibpsn, qp->s_last_psn) < 0 ||
cmp_psn(ibpsn, qp->s_psn) > 0)
- return ret;
+ goto s_unlock;
- spin_lock(&qp->s_lock);
/*
* Note that NAKs implicitly ACK outstanding SEND and RDMA write
* requests and implicitly NAK RDMA read and atomic requests issued
@@ -2767,9 +2699,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
wqe = do_rc_completion(qp, wqe, ibp);
if (qp->s_acked == qp->s_tail)
- break;
+ goto s_unlock;
}
+ if (qp->s_acked == qp->s_tail)
+ goto s_unlock;
+
/* Handle the eflags for the request */
if (wqe->wr.opcode != IB_WR_TID_RDMA_READ)
goto s_unlock;
@@ -2788,19 +2723,7 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
* to prevent continuous Flow Sequence errors for any
* packets that could be still in the fabric.
*/
- flow = find_flow(req, psn, NULL);
- if (!flow) {
- /*
- * We can't find the IB PSN matching the
- * received KDETH PSN. The only thing we can
- * do at this point is report the error to
- * the QP.
- */
- hfi1_kern_read_tid_flow_free(qp);
- spin_unlock(&qp->s_lock);
- rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
- return ret;
- }
+ flow = &req->flows[req->clear_tail];
if (priv->s_flags & HFI1_R_TID_SW_PSN) {
diff = cmp_psn(psn,
flow->flow_state.r_next_psn);
@@ -2961,7 +2884,7 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
if (lnh == HFI1_LRH_GRH)
goto r_unlock;
- if (tid_rdma_tid_err(rcd, packet, rcv_type, opcode))
+ if (tid_rdma_tid_err(packet, rcv_type))
goto r_unlock;
}
@@ -2981,8 +2904,15 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
*/
spin_lock(&qp->s_lock);
qpriv = qp->priv;
+ if (qpriv->r_tid_tail == HFI1_QP_WQE_INVALID ||
+ qpriv->r_tid_tail == qpriv->r_tid_head)
+ goto unlock;
e = &qp->s_ack_queue[qpriv->r_tid_tail];
+ if (e->opcode != TID_OP(WRITE_REQ))
+ goto unlock;
req = ack_to_tid_req(e);
+ if (req->comp_seg == req->cur_seg)
+ goto unlock;
flow = &req->flows[req->clear_tail];
trace_hfi1_eflags_err_write(qp, rcv_type, rte, psn);
trace_hfi1_rsp_handle_kdeth_eflags(qp, psn);
@@ -4548,7 +4478,7 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
struct rvt_swqe *wqe;
struct tid_rdma_request *req;
struct tid_rdma_flow *flow;
- u32 aeth, psn, req_psn, ack_psn, resync_psn, ack_kpsn;
+ u32 aeth, psn, req_psn, ack_psn, flpsn, resync_psn, ack_kpsn;
unsigned long flags;
u16 fidx;
@@ -4577,6 +4507,9 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
ack_kpsn--;
}
+ if (unlikely(qp->s_acked == qp->s_tail))
+ goto ack_op_err;
+
wqe = rvt_get_swqe_ptr(qp, qp->s_acked);
if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE)
@@ -4589,7 +4522,8 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail, flow);
/* Drop stale ACK/NAK */
- if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0)
+ if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0 ||
+ cmp_psn(req_psn, flow->flow_state.resp_ib_psn) < 0)
goto ack_op_err;
while (cmp_psn(ack_kpsn,
@@ -4751,7 +4685,12 @@ done:
switch ((aeth >> IB_AETH_CREDIT_SHIFT) &
IB_AETH_CREDIT_MASK) {
case 0: /* PSN sequence error */
+ if (!req->flows)
+ break;
flow = &req->flows[req->acked_tail];
+ flpsn = full_flow_psn(flow, flow->flow_state.lpsn);
+ if (cmp_psn(psn, flpsn) > 0)
+ break;
trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail,
flow);
req->r_ack_psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index c4b243f50c76..646f61545ed6 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -54,6 +54,7 @@
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <rdma/opa_addr.h>
+#include <linux/nospec.h>
#include "hfi.h"
#include "common.h"
@@ -1536,6 +1537,7 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr)
sl = rdma_ah_get_sl(ah_attr);
if (sl >= ARRAY_SIZE(ibp->sl_to_sc))
return -EINVAL;
+ sl = array_index_nospec(sl, ARRAY_SIZE(ibp->sl_to_sc));
sc5 = ibp->sl_to_sc[sl];
if (sc_to_vlt(dd, sc5) > num_vls && sc_to_vlt(dd, sc5) != 0xf)
diff --git a/drivers/infiniband/hw/hns/Kconfig b/drivers/infiniband/hw/hns/Kconfig
index 8bf847bcd8d3..54782197c717 100644
--- a/drivers/infiniband/hw/hns/Kconfig
+++ b/drivers/infiniband/hw/hns/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config INFINIBAND_HNS
- tristate "HNS RoCE Driver"
+ bool "HNS RoCE Driver"
depends on NET_VENDOR_HISILICON
depends on ARM64 || (COMPILE_TEST && 64BIT)
---help---
@@ -11,7 +11,7 @@ config INFINIBAND_HNS
To compile HIP06 or HIP08 driver as module, choose M here.
config INFINIBAND_HNS_HIP06
- bool "Hisilicon Hip06 Family RoCE support"
+ tristate "Hisilicon Hip06 Family RoCE support"
depends on INFINIBAND_HNS && HNS && HNS_DSAF && HNS_ENET
---help---
RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip06 and
@@ -21,7 +21,7 @@ config INFINIBAND_HNS_HIP06
module will be called hns-roce-hw-v1
config INFINIBAND_HNS_HIP08
- bool "Hisilicon Hip08 Family RoCE support"
+ tristate "Hisilicon Hip08 Family RoCE support"
depends on INFINIBAND_HNS && PCI && HNS3
---help---
RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip08 SoC.
diff --git a/drivers/infiniband/hw/hns/Makefile b/drivers/infiniband/hw/hns/Makefile
index e105945b94a1..449a2d81319d 100644
--- a/drivers/infiniband/hw/hns/Makefile
+++ b/drivers/infiniband/hw/hns/Makefile
@@ -9,12 +9,8 @@ hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o
-ifdef CONFIG_INFINIBAND_HNS_HIP06
hns-roce-hw-v1-objs := hns_roce_hw_v1.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v1.o
-endif
+obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
-ifdef CONFIG_INFINIBAND_HNS_HIP08
hns-roce-hw-v2-objs := hns_roce_hw_v2.o hns_roce_hw_v2_dfx.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v2.o
-endif
+obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
diff --git a/drivers/infiniband/hw/hns/hns_roce_db.c b/drivers/infiniband/hw/hns/hns_roce_db.c
index 627aa46ef683..c00714c2f16a 100644
--- a/drivers/infiniband/hw/hns/hns_roce_db.c
+++ b/drivers/infiniband/hw/hns/hns_roce_db.c
@@ -12,13 +12,15 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
struct ib_udata *udata, unsigned long virt,
struct hns_roce_db *db)
{
+ unsigned long page_addr = virt & PAGE_MASK;
struct hns_roce_user_db_page *page;
+ unsigned int offset;
int ret = 0;
mutex_lock(&context->page_mutex);
list_for_each_entry(page, &context->page_list, list)
- if (page->user_virt == (virt & PAGE_MASK))
+ if (page->user_virt == page_addr)
goto found;
page = kmalloc(sizeof(*page), GFP_KERNEL);
@@ -28,8 +30,8 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
}
refcount_set(&page->refcount, 1);
- page->user_virt = (virt & PAGE_MASK);
- page->umem = ib_umem_get(udata, virt & PAGE_MASK, PAGE_SIZE, 0, 0);
+ page->user_virt = page_addr;
+ page->umem = ib_umem_get(udata, page_addr, PAGE_SIZE, 0, 0);
if (IS_ERR(page->umem)) {
ret = PTR_ERR(page->umem);
kfree(page);
@@ -39,10 +41,9 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
list_add(&page->list, &context->page_list);
found:
- db->dma = sg_dma_address(page->umem->sg_head.sgl) +
- (virt & ~PAGE_MASK);
- page->umem->sg_head.sgl->offset = virt & ~PAGE_MASK;
- db->virt_addr = sg_virt(page->umem->sg_head.sgl);
+ offset = virt - page_addr;
+ db->dma = sg_dma_address(page->umem->sg_head.sgl) + offset;
+ db->virt_addr = sg_virt(page->umem->sg_head.sgl) + offset;
db->u.user_page = page;
refcount_inc(&page->refcount);
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index 81e6dedb1e02..c07e387a07a3 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -750,8 +750,10 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
atomic_set(&free_mr->mr_free_cq->ib_cq.usecnt, 0);
pd = rdma_zalloc_drv_obj(ibdev, ib_pd);
- if (!pd)
+ if (!pd) {
+ ret = -ENOMEM;
goto alloc_mem_failed;
+ }
pd->device = ibdev;
ret = hns_roce_alloc_pd(pd, NULL);
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 68c951491a08..57079110af9b 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -1677,8 +1677,6 @@ tx_err:
tx_buf_size, DMA_TO_DEVICE);
kfree(tun_qp->tx_ring[i].buf.addr);
}
- kfree(tun_qp->tx_ring);
- tun_qp->tx_ring = NULL;
i = MLX4_NUM_TUNNEL_BUFS;
err:
while (i > 0) {
@@ -1687,6 +1685,8 @@ err:
rx_buf_size, DMA_FROM_DEVICE);
kfree(tun_qp->ring[i].addr);
}
+ kfree(tun_qp->tx_ring);
+ tun_qp->tx_ring = NULL;
kfree(tun_qp->ring);
tun_qp->ring = NULL;
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index ec4370f99381..af5bbb35c058 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -2026,7 +2026,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
event_sub->eventfd =
eventfd_ctx_fdget(redirect_fd);
- if (IS_ERR(event_sub)) {
+ if (IS_ERR(event_sub->eventfd)) {
err = PTR_ERR(event_sub->eventfd);
event_sub->eventfd = NULL;
goto err;
@@ -2644,12 +2644,13 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
struct devx_async_event_file *ev_file = filp->private_data;
struct devx_event_subscription *event_sub, *event_sub_tmp;
struct devx_async_event_data *entry, *tmp;
+ struct mlx5_ib_dev *dev = ev_file->dev;
- mutex_lock(&ev_file->dev->devx_event_table.event_xa_lock);
+ mutex_lock(&dev->devx_event_table.event_xa_lock);
/* delete the subscriptions which are related to this FD */
list_for_each_entry_safe(event_sub, event_sub_tmp,
&ev_file->subscribed_events_list, file_list) {
- devx_cleanup_subscription(ev_file->dev, event_sub);
+ devx_cleanup_subscription(dev, event_sub);
if (event_sub->eventfd)
eventfd_ctx_put(event_sub->eventfd);
@@ -2658,7 +2659,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
kfree_rcu(event_sub, rcu);
}
- mutex_unlock(&ev_file->dev->devx_event_table.event_xa_lock);
+ mutex_unlock(&dev->devx_event_table.event_xa_lock);
/* free the pending events allocation */
if (!ev_file->omit_data) {
@@ -2670,7 +2671,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
}
uverbs_close_fd(filp);
- put_device(&ev_file->dev->ib_dev.dev);
+ put_device(&dev->ib_dev.dev);
return 0;
}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index c2a5780cb394..0569bcab02d4 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1023,7 +1023,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
- if (MLX5_CAP_GEN(mdev, pg))
+ if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING;
props->odp_caps = dev->odp_caps;
}
@@ -5802,13 +5802,12 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
return;
}
- if (mpi->mdev_events.notifier_call)
- mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
- mpi->mdev_events.notifier_call = NULL;
-
mpi->ibdev = NULL;
spin_unlock(&port->mp.mpi_lock);
+ if (mpi->mdev_events.notifier_call)
+ mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
+ mpi->mdev_events.notifier_call = NULL;
mlx5_remove_netdev_notifier(ibdev, port_num);
spin_lock(&port->mp.mpi_lock);
@@ -6140,6 +6139,8 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
dev->port[i].roce.last_port_state = IB_PORT_DOWN;
}
+ mlx5_ib_internal_fill_odp_caps(dev);
+
err = mlx5_ib_init_multiport_master(dev);
if (err)
return err;
@@ -6564,8 +6565,6 @@ static void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
{
- mlx5_ib_internal_fill_odp_caps(dev);
-
return mlx5_ib_odp_init_one(dev);
}
diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c
index fe1a76d8531c..a40e0abf2338 100644
--- a/drivers/infiniband/hw/mlx5/mem.c
+++ b/drivers/infiniband/hw/mlx5/mem.c
@@ -57,9 +57,10 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
int entry;
if (umem->is_odp) {
- unsigned int page_shift = to_ib_umem_odp(umem)->page_shift;
+ struct ib_umem_odp *odp = to_ib_umem_odp(umem);
+ unsigned int page_shift = odp->page_shift;
- *ncont = ib_umem_page_count(umem);
+ *ncont = ib_umem_odp_num_pages(odp);
*count = *ncont << (page_shift - PAGE_SHIFT);
*shift = page_shift;
if (order)
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index c482f19958b3..9ae587b74b12 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -481,6 +481,7 @@ struct mlx5_umr_wr {
u64 length;
int access_flags;
u32 mkey;
+ u8 ignore_free_state:1;
};
static inline const struct mlx5_umr_wr *umr_wr(const struct ib_send_wr *wr)
@@ -1474,4 +1475,18 @@ int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
bool dyn_bfreg);
int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter);
+
+static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev,
+ bool do_modify_atomic)
+{
+ if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
+ return false;
+
+ if (do_modify_atomic &&
+ MLX5_CAP_GEN(dev->mdev, atomic) &&
+ MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
+ return false;
+
+ return true;
+}
#endif /* MLX5_IB_H */
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 20ece6e0b2fc..3401f5f6792e 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -51,22 +51,12 @@ static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
static int mr_cache_max_order(struct mlx5_ib_dev *dev);
static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
-static bool umr_can_modify_entity_size(struct mlx5_ib_dev *dev)
-{
- return !MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled);
-}
static bool umr_can_use_indirect_mkey(struct mlx5_ib_dev *dev)
{
return !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled);
}
-static bool use_umr(struct mlx5_ib_dev *dev, int order)
-{
- return order <= mr_cache_max_order(dev) &&
- umr_can_modify_entity_size(dev);
-}
-
static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
{
int err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
@@ -545,13 +535,16 @@ void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
return;
c = order2idx(dev, mr->order);
- if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
- mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c);
- return;
- }
+ WARN_ON(c < 0 || c >= MAX_MR_CACHE_ENTRIES);
- if (unreg_umr(dev, mr))
+ if (unreg_umr(dev, mr)) {
+ mr->allocated_from_cache = false;
+ destroy_mkey(dev, mr);
+ ent = &cache->ent[c];
+ if (ent->cur < ent->limit)
+ queue_work(cache->wq, &ent->work);
return;
+ }
ent = &cache->ent[c];
spin_lock_irq(&ent->lock);
@@ -1268,7 +1261,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
{
struct mlx5_ib_dev *dev = to_mdev(pd->device);
struct mlx5_ib_mr *mr = NULL;
- bool populate_mtts = false;
+ bool use_umr;
struct ib_umem *umem;
int page_shift;
int npages;
@@ -1300,29 +1293,28 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (err < 0)
return ERR_PTR(err);
- if (use_umr(dev, order)) {
+ use_umr = mlx5_ib_can_use_umr(dev, true);
+
+ if (order <= mr_cache_max_order(dev) && use_umr) {
mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
page_shift, order, access_flags);
if (PTR_ERR(mr) == -EAGAIN) {
mlx5_ib_dbg(dev, "cache empty for order %d\n", order);
mr = NULL;
}
- populate_mtts = false;
} else if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
if (access_flags & IB_ACCESS_ON_DEMAND) {
err = -EINVAL;
pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB\n");
goto error;
}
- populate_mtts = true;
+ use_umr = false;
}
if (!mr) {
- if (!umr_can_modify_entity_size(dev))
- populate_mtts = true;
mutex_lock(&dev->slow_path_mutex);
mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
- page_shift, access_flags, populate_mtts);
+ page_shift, access_flags, !use_umr);
mutex_unlock(&dev->slow_path_mutex);
}
@@ -1338,7 +1330,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
update_odp_mr(mr);
- if (!populate_mtts) {
+ if (use_umr) {
int update_xlt_flags = MLX5_IB_UPD_XLT_ENABLE;
if (access_flags & IB_ACCESS_ON_DEMAND)
@@ -1373,9 +1365,11 @@ static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
return 0;
umrwr.wr.send_flags = MLX5_IB_SEND_UMR_DISABLE_MR |
- MLX5_IB_SEND_UMR_FAIL_IF_FREE;
+ MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
umrwr.wr.opcode = MLX5_IB_WR_UMR;
+ umrwr.pd = dev->umrc.pd;
umrwr.mkey = mr->mmkey.key;
+ umrwr.ignore_free_state = 1;
return mlx5_ib_post_send_wait(dev, &umrwr);
}
@@ -1452,7 +1446,8 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
goto err;
}
- if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
+ if (!mlx5_ib_can_use_umr(dev, true) ||
+ (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len))) {
/*
* UMR can't be used - MKey needs to be replaced.
*/
@@ -1577,10 +1572,10 @@ static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
mr->sig = NULL;
}
- mlx5_free_priv_descs(mr);
-
- if (!allocated_from_cache)
+ if (!allocated_from_cache) {
destroy_mkey(dev, mr);
+ mlx5_free_priv_descs(mr);
+ }
}
static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c
index 5b642d81e617..0a59912a4cef 100644
--- a/drivers/infiniband/hw/mlx5/odp.c
+++ b/drivers/infiniband/hw/mlx5/odp.c
@@ -246,7 +246,7 @@ void mlx5_ib_invalidate_range(struct ib_umem_odp *umem_odp, unsigned long start,
* overwrite the same MTTs. Concurent invalidations might race us,
* but they will write 0s as well, so no difference in the end result.
*/
-
+ mutex_lock(&umem_odp->umem_mutex);
for (addr = start; addr < end; addr += BIT(umem_odp->page_shift)) {
idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift;
/*
@@ -278,6 +278,7 @@ void mlx5_ib_invalidate_range(struct ib_umem_odp *umem_odp, unsigned long start,
idx - blk_start_idx + 1, 0,
MLX5_IB_UPD_XLT_ZAP |
MLX5_IB_UPD_XLT_ATOMIC);
+ mutex_unlock(&umem_odp->umem_mutex);
/*
* We are now sure that the device will not access the
* memory. We can safely unmap it, and mark it as dirty if
@@ -300,7 +301,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
memset(caps, 0, sizeof(*caps));
- if (!MLX5_CAP_GEN(dev->mdev, pg))
+ if (!MLX5_CAP_GEN(dev->mdev, pg) ||
+ !mlx5_ib_can_use_umr(dev, true))
return;
caps->general_caps = IB_ODP_SUPPORT;
@@ -354,7 +356,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
if (MLX5_CAP_GEN(dev->mdev, fixed_buffer_size) &&
MLX5_CAP_GEN(dev->mdev, null_mkey) &&
- MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
+ MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
+ !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled))
caps->general_caps |= IB_ODP_SUPPORT_IMPLICIT;
return;
@@ -578,7 +581,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
u32 flags)
{
int npages = 0, current_seq, page_shift, ret, np;
- bool implicit = false;
struct ib_umem_odp *odp_mr = to_ib_umem_odp(mr->umem);
bool downgrade = flags & MLX5_PF_FLAGS_DOWNGRADE;
bool prefetch = flags & MLX5_PF_FLAGS_PREFETCH;
@@ -593,7 +595,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
if (IS_ERR(odp))
return PTR_ERR(odp);
mr = odp->private;
- implicit = true;
} else {
odp = odp_mr;
}
@@ -681,19 +682,15 @@ next_mr:
out:
if (ret == -EAGAIN) {
- if (implicit || !odp->dying) {
- unsigned long timeout =
- msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
-
- if (!wait_for_completion_timeout(
- &odp->notifier_completion,
- timeout)) {
- mlx5_ib_warn(dev, "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
- current_seq, odp->notifiers_seq, odp->notifiers_count);
- }
- } else {
- /* The MR is being killed, kill the QP as well. */
- ret = -EFAULT;
+ unsigned long timeout = msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
+
+ if (!wait_for_completion_timeout(&odp->notifier_completion,
+ timeout)) {
+ mlx5_ib_warn(
+ dev,
+ "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
+ current_seq, odp->notifiers_seq,
+ odp->notifiers_count);
}
}
@@ -1627,8 +1624,10 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
{
int ret = 0;
- if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
- ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
+ if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
+ return ret;
+
+ ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
if (dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT) {
ret = mlx5_cmd_null_mkey(dev->mdev, &dev->null_mkey);
@@ -1638,9 +1637,6 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
}
}
- if (!MLX5_CAP_GEN(dev->mdev, pg))
- return ret;
-
ret = mlx5_ib_create_pf_eq(dev, &dev->odp_pf_eq);
return ret;
@@ -1648,7 +1644,7 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *dev)
{
- if (!MLX5_CAP_GEN(dev->mdev, pg))
+ if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
return;
mlx5_ib_destroy_pf_eq(dev, &dev->odp_pf_eq);
@@ -1771,7 +1767,7 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
num_pending_prefetch_dec(to_mdev(w->pd->device), w->sg_list,
w->num_sge, 0);
- kfree(w);
+ kvfree(w);
}
int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
@@ -1813,7 +1809,7 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
if (valid_req)
queue_work(system_unbound_wq, &work->work);
else
- kfree(work);
+ kvfree(work);
srcu_read_unlock(&dev->mr_srcu, srcu_key);
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 2a97619ed603..72869ff4a334 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1713,7 +1713,6 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
}
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_TOEPLITZ);
- MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
memcpy(rss_key, ucmd.rx_hash_key, len);
break;
}
@@ -4163,7 +4162,7 @@ static u64 get_xlt_octo(u64 bytes)
MLX5_IB_UMR_OCTOWORD;
}
-static __be64 frwr_mkey_mask(void)
+static __be64 frwr_mkey_mask(bool atomic)
{
u64 result;
@@ -4176,10 +4175,12 @@ static __be64 frwr_mkey_mask(void)
MLX5_MKEY_MASK_LW |
MLX5_MKEY_MASK_RR |
MLX5_MKEY_MASK_RW |
- MLX5_MKEY_MASK_A |
MLX5_MKEY_MASK_SMALL_FENCE |
MLX5_MKEY_MASK_FREE;
+ if (atomic)
+ result |= MLX5_MKEY_MASK_A;
+
return cpu_to_be64(result);
}
@@ -4205,7 +4206,7 @@ static __be64 sig_mkey_mask(void)
}
static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
- struct mlx5_ib_mr *mr, u8 flags)
+ struct mlx5_ib_mr *mr, u8 flags, bool atomic)
{
int size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
@@ -4213,7 +4214,7 @@ static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
umr->flags = flags;
umr->xlt_octowords = cpu_to_be16(get_xlt_octo(size));
- umr->mkey_mask = frwr_mkey_mask();
+ umr->mkey_mask = frwr_mkey_mask(atomic);
}
static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
@@ -4295,10 +4296,14 @@ static int set_reg_umr_segment(struct mlx5_ib_dev *dev,
memset(umr, 0, sizeof(*umr));
- if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
- umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */
- else
- umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */
+ if (!umrwr->ignore_free_state) {
+ if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
+ /* fail if free */
+ umr->flags = MLX5_UMR_CHECK_FREE;
+ else
+ /* fail if not free */
+ umr->flags = MLX5_UMR_CHECK_NOT_FREE;
+ }
umr->xlt_octowords = cpu_to_be16(get_xlt_octo(umrwr->xlt_size));
if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) {
@@ -4808,10 +4813,22 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
{
struct mlx5_ib_mr *mr = to_mmr(wr->mr);
struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
+ struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
int mr_list_size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
+ bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
u8 flags = 0;
+ if (!mlx5_ib_can_use_umr(dev, atomic)) {
+ mlx5_ib_warn(to_mdev(qp->ibqp.device),
+ "Fast update of %s for MR is disabled\n",
+ (MLX5_CAP_GEN(dev->mdev,
+ umr_modify_entity_size_disabled)) ?
+ "entity size" :
+ "atomic access");
+ return -EINVAL;
+ }
+
if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
mlx5_ib_warn(to_mdev(qp->ibqp.device),
"Invalid IB_SEND_INLINE send flag\n");
@@ -4823,7 +4840,7 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
if (umr_inline)
flags |= MLX5_UMR_INLINE;
- set_reg_umr_seg(*seg, mr, flags);
+ set_reg_umr_seg(*seg, mr, flags, atomic);
*seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
*size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
index 533157a2a3be..f97b3d65b30c 100644
--- a/drivers/infiniband/hw/qedr/main.c
+++ b/drivers/infiniband/hw/qedr/main.c
@@ -125,14 +125,20 @@ static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr,
struct qedr_dev *dev =
rdma_device_to_drv_device(device, struct qedr_dev, ibdev);
- return scnprintf(buf, PAGE_SIZE, "0x%x\n", dev->pdev->vendor);
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", dev->attr.hw_ver);
}
static DEVICE_ATTR_RO(hw_rev);
static ssize_t hca_type_show(struct device *device,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%s\n", "HCA_TYPE_TO_SET");
+ struct qedr_dev *dev =
+ rdma_device_to_drv_device(device, struct qedr_dev, ibdev);
+
+ return scnprintf(buf, PAGE_SIZE, "FastLinQ QL%x %s\n",
+ dev->pdev->device,
+ rdma_protocol_iwarp(&dev->ibdev, 1) ?
+ "iWARP" : "RoCE");
}
static DEVICE_ATTR_RO(hca_type);
diff --git a/drivers/infiniband/sw/siw/Kconfig b/drivers/infiniband/sw/siw/Kconfig
index dace276aea14..b622fc62f2cd 100644
--- a/drivers/infiniband/sw/siw/Kconfig
+++ b/drivers/infiniband/sw/siw/Kconfig
@@ -1,6 +1,6 @@
config RDMA_SIW
tristate "Software RDMA over TCP/IP (iWARP) driver"
- depends on INET && INFINIBAND && LIBCRC32C && 64BIT
+ depends on INET && INFINIBAND && LIBCRC32C
select DMA_VIRT_OPS
help
This driver implements the iWARP RDMA transport over
diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h
index 03fd7b2f595f..dba4535494ab 100644
--- a/drivers/infiniband/sw/siw/siw.h
+++ b/drivers/infiniband/sw/siw/siw.h
@@ -138,9 +138,9 @@ struct siw_umem {
};
struct siw_pble {
- u64 addr; /* Address of assigned user buffer */
- u64 size; /* Size of this entry */
- u64 pbl_off; /* Total offset from start of PBL */
+ dma_addr_t addr; /* Address of assigned buffer */
+ unsigned int size; /* Size of this entry */
+ unsigned long pbl_off; /* Total offset from start of PBL */
};
struct siw_pbl {
@@ -214,7 +214,7 @@ struct siw_wqe {
struct siw_cq {
struct ib_cq base_cq;
spinlock_t lock;
- u64 *notify;
+ struct siw_cq_ctrl *notify;
struct siw_cqe *queue;
u32 cq_put;
u32 cq_get;
@@ -734,7 +734,7 @@ static inline void siw_crc_skb(struct siw_rx_stream *srx, unsigned int len)
"MEM[0x%08x] %s: " fmt, mem->stag, __func__, ##__VA_ARGS__)
#define siw_dbg_cep(cep, fmt, ...) \
- ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%p] %s: " fmt, \
+ ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%pK] %s: " fmt, \
cep, __func__, ##__VA_ARGS__)
void siw_cq_flush(struct siw_cq *cq);
diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
index a7cde98e73e8..8c1931a57f4a 100644
--- a/drivers/infiniband/sw/siw/siw_cm.c
+++ b/drivers/infiniband/sw/siw/siw_cm.c
@@ -220,13 +220,12 @@ static void siw_put_work(struct siw_cm_work *work)
static void siw_cep_set_inuse(struct siw_cep *cep)
{
unsigned long flags;
- int rv;
retry:
spin_lock_irqsave(&cep->lock, flags);
if (cep->in_use) {
spin_unlock_irqrestore(&cep->lock, flags);
- rv = wait_event_interruptible(cep->waitq, !cep->in_use);
+ wait_event_interruptible(cep->waitq, !cep->in_use);
if (signal_pending(current))
flush_signals(current);
goto retry;
@@ -356,8 +355,8 @@ static int siw_cm_upcall(struct siw_cep *cep, enum iw_cm_event_type reason,
getname_local(cep->sock, &event.local_addr);
getname_peer(cep->sock, &event.remote_addr);
}
- siw_dbg_cep(cep, "[QP %u]: id 0x%p, reason=%d, status=%d\n",
- cep->qp ? qp_id(cep->qp) : -1, id, reason, status);
+ siw_dbg_cep(cep, "[QP %u]: reason=%d, status=%d\n",
+ cep->qp ? qp_id(cep->qp) : UINT_MAX, reason, status);
return id->event_handler(id, &event);
}
@@ -948,8 +947,6 @@ static void siw_accept_newconn(struct siw_cep *cep)
siw_cep_get(new_cep);
new_s->sk->sk_user_data = new_cep;
- siw_dbg_cep(cep, "listen socket 0x%p, new 0x%p\n", s, new_s);
-
if (siw_tcp_nagle == false) {
int val = 1;
@@ -1012,7 +1009,8 @@ static void siw_cm_work_handler(struct work_struct *w)
cep = work->cep;
siw_dbg_cep(cep, "[QP %u]: work type: %d, state %d\n",
- cep->qp ? qp_id(cep->qp) : -1, work->type, cep->state);
+ cep->qp ? qp_id(cep->qp) : UINT_MAX,
+ work->type, cep->state);
siw_cep_set_inuse(cep);
@@ -1146,9 +1144,9 @@ static void siw_cm_work_handler(struct work_struct *w)
}
if (release_cep) {
siw_dbg_cep(cep,
- "release: timer=%s, QP[%u], id 0x%p\n",
+ "release: timer=%s, QP[%u]\n",
cep->mpa_timer ? "y" : "n",
- cep->qp ? qp_id(cep->qp) : -1, cep->cm_id);
+ cep->qp ? qp_id(cep->qp) : UINT_MAX);
siw_cancel_mpatimer(cep);
@@ -1212,8 +1210,8 @@ int siw_cm_queue_work(struct siw_cep *cep, enum siw_work_type type)
else
delay = MPAREP_TIMEOUT;
}
- siw_dbg_cep(cep, "[QP %u]: work type: %d, work 0x%p, timeout %lu\n",
- cep->qp ? qp_id(cep->qp) : -1, type, work, delay);
+ siw_dbg_cep(cep, "[QP %u]: work type: %d, timeout %lu\n",
+ cep->qp ? qp_id(cep->qp) : -1, type, delay);
queue_delayed_work(siw_cm_wq, &work->work, delay);
@@ -1377,16 +1375,16 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
}
if (v4)
siw_dbg_qp(qp,
- "id 0x%p, pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
- id, pd_len,
+ "pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
+ pd_len,
&((struct sockaddr_in *)(laddr))->sin_addr,
ntohs(((struct sockaddr_in *)(laddr))->sin_port),
&((struct sockaddr_in *)(raddr))->sin_addr,
ntohs(((struct sockaddr_in *)(raddr))->sin_port));
else
siw_dbg_qp(qp,
- "id 0x%p, pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
- id, pd_len,
+ "pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
+ pd_len,
&((struct sockaddr_in6 *)(laddr))->sin6_addr,
ntohs(((struct sockaddr_in6 *)(laddr))->sin6_port),
&((struct sockaddr_in6 *)(raddr))->sin6_addr,
@@ -1509,14 +1507,13 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
if (rv >= 0) {
rv = siw_cm_queue_work(cep, SIW_CM_WORK_MPATIMEOUT);
if (!rv) {
- siw_dbg_cep(cep, "id 0x%p, [QP %u]: exit\n", id,
- qp_id(qp));
+ siw_dbg_cep(cep, "[QP %u]: exit\n", qp_id(qp));
siw_cep_set_free(cep);
return 0;
}
}
error:
- siw_dbg_qp(qp, "failed: %d\n", rv);
+ siw_dbg(id->device, "failed: %d\n", rv);
if (cep) {
siw_socket_disassoc(s);
@@ -1541,7 +1538,8 @@ error:
} else if (s) {
sock_release(s);
}
- siw_qp_put(qp);
+ if (qp)
+ siw_qp_put(qp);
return rv;
}
@@ -1581,7 +1579,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
siw_cancel_mpatimer(cep);
if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
- siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+ siw_dbg_cep(cep, "out of state\n");
siw_cep_set_free(cep);
siw_cep_put(cep);
@@ -1602,7 +1600,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
up_write(&qp->state_lock);
goto error;
}
- siw_dbg_cep(cep, "id 0x%p\n", id);
+ siw_dbg_cep(cep, "[QP %d]\n", params->qpn);
if (try_gso && cep->mpa.hdr.params.bits & MPA_RR_FLAG_GSO_EXP) {
siw_dbg_cep(cep, "peer allows GSO on TX\n");
@@ -1612,8 +1610,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
params->ird > sdev->attrs.max_ird) {
siw_dbg_cep(
cep,
- "id 0x%p, [QP %u]: ord %d (max %d), ird %d (max %d)\n",
- id, qp_id(qp), params->ord, sdev->attrs.max_ord,
+ "[QP %u]: ord %d (max %d), ird %d (max %d)\n",
+ qp_id(qp), params->ord, sdev->attrs.max_ord,
params->ird, sdev->attrs.max_ird);
rv = -EINVAL;
up_write(&qp->state_lock);
@@ -1625,8 +1623,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
if (params->private_data_len > max_priv_data) {
siw_dbg_cep(
cep,
- "id 0x%p, [QP %u]: private data length: %d (max %d)\n",
- id, qp_id(qp), params->private_data_len, max_priv_data);
+ "[QP %u]: private data length: %d (max %d)\n",
+ qp_id(qp), params->private_data_len, max_priv_data);
rv = -EINVAL;
up_write(&qp->state_lock);
goto error;
@@ -1680,7 +1678,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
qp_attrs.flags = SIW_MPA_CRC;
qp_attrs.state = SIW_QP_STATE_RTS;
- siw_dbg_cep(cep, "id 0x%p, [QP%u]: moving to rts\n", id, qp_id(qp));
+ siw_dbg_cep(cep, "[QP%u]: moving to rts\n", qp_id(qp));
/* Associate QP with CEP */
siw_cep_get(cep);
@@ -1701,8 +1699,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
if (rv)
goto error;
- siw_dbg_cep(cep, "id 0x%p, [QP %u]: send mpa reply, %d byte pdata\n",
- id, qp_id(qp), params->private_data_len);
+ siw_dbg_cep(cep, "[QP %u]: send mpa reply, %d byte pdata\n",
+ qp_id(qp), params->private_data_len);
rv = siw_send_mpareqrep(cep, params->private_data,
params->private_data_len);
@@ -1760,14 +1758,14 @@ int siw_reject(struct iw_cm_id *id, const void *pdata, u8 pd_len)
siw_cancel_mpatimer(cep);
if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
- siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+ siw_dbg_cep(cep, "out of state\n");
siw_cep_set_free(cep);
siw_cep_put(cep); /* put last reference */
return -ECONNRESET;
}
- siw_dbg_cep(cep, "id 0x%p, cep->state %d, pd_len %d\n", id, cep->state,
+ siw_dbg_cep(cep, "cep->state %d, pd_len %d\n", cep->state,
pd_len);
if (__mpa_rr_revision(cep->mpa.hdr.params.bits) >= MPA_REVISION_1) {
@@ -1805,14 +1803,14 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val,
sizeof(s_val));
if (rv) {
- siw_dbg(id->device, "id 0x%p: setsockopt error: %d\n", id, rv);
+ siw_dbg(id->device, "setsockopt error: %d\n", rv);
goto error;
}
rv = s->ops->bind(s, laddr, addr_family == AF_INET ?
sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6));
if (rv) {
- siw_dbg(id->device, "id 0x%p: socket bind error: %d\n", id, rv);
+ siw_dbg(id->device, "socket bind error: %d\n", rv);
goto error;
}
cep = siw_cep_alloc(sdev);
@@ -1825,13 +1823,13 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
rv = siw_cm_alloc_work(cep, backlog);
if (rv) {
siw_dbg(id->device,
- "id 0x%p: alloc_work error %d, backlog %d\n", id,
+ "alloc_work error %d, backlog %d\n",
rv, backlog);
goto error;
}
rv = s->ops->listen(s, backlog);
if (rv) {
- siw_dbg(id->device, "id 0x%p: listen error %d\n", id, rv);
+ siw_dbg(id->device, "listen error %d\n", rv);
goto error;
}
cep->cm_id = id;
@@ -1915,8 +1913,7 @@ static void siw_drop_listeners(struct iw_cm_id *id)
list_del(p);
- siw_dbg_cep(cep, "id 0x%p: drop cep, state %d\n", id,
- cep->state);
+ siw_dbg_cep(cep, "drop cep, state %d\n", cep->state);
siw_cep_set_inuse(cep);
@@ -1953,7 +1950,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct net_device *dev = to_siw_dev(id->device)->netdev;
int rv = 0, listeners = 0;
- siw_dbg(id->device, "id 0x%p: backlog %d\n", id, backlog);
+ siw_dbg(id->device, "backlog %d\n", backlog);
/*
* For each attached address of the interface, create a
@@ -1965,12 +1962,16 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct sockaddr_in s_laddr, *s_raddr;
const struct in_ifaddr *ifa;
+ if (!in_dev) {
+ rv = -ENODEV;
+ goto out;
+ }
memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr));
s_raddr = (struct sockaddr_in *)&id->remote_addr;
siw_dbg(id->device,
- "id 0x%p: laddr %pI4:%d, raddr %pI4:%d\n",
- id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
+ "laddr %pI4:%d, raddr %pI4:%d\n",
+ &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
&s_raddr->sin_addr, ntohs(s_raddr->sin_port));
rtnl_lock();
@@ -1994,22 +1995,27 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct sockaddr_in6 *s_laddr = &to_sockaddr_in6(id->local_addr),
*s_raddr = &to_sockaddr_in6(id->remote_addr);
+ if (!in6_dev) {
+ rv = -ENODEV;
+ goto out;
+ }
siw_dbg(id->device,
- "id 0x%p: laddr %pI6:%d, raddr %pI6:%d\n",
- id, &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
+ "laddr %pI6:%d, raddr %pI6:%d\n",
+ &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
&s_raddr->sin6_addr, ntohs(s_raddr->sin6_port));
- read_lock_bh(&in6_dev->lock);
+ rtnl_lock();
list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
- struct sockaddr_in6 bind_addr;
-
+ if (ifp->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
+ continue;
if (ipv6_addr_any(&s_laddr->sin6_addr) ||
ipv6_addr_equal(&s_laddr->sin6_addr, &ifp->addr)) {
- bind_addr.sin6_family = AF_INET6;
- bind_addr.sin6_port = s_laddr->sin6_port;
- bind_addr.sin6_flowinfo = 0;
- bind_addr.sin6_addr = ifp->addr;
- bind_addr.sin6_scope_id = dev->ifindex;
+ struct sockaddr_in6 bind_addr = {
+ .sin6_family = AF_INET6,
+ .sin6_port = s_laddr->sin6_port,
+ .sin6_flowinfo = 0,
+ .sin6_addr = ifp->addr,
+ .sin6_scope_id = dev->ifindex };
rv = siw_listen_address(id, backlog,
(struct sockaddr *)&bind_addr,
@@ -2018,28 +2024,26 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
listeners++;
}
}
- read_unlock_bh(&in6_dev->lock);
-
+ rtnl_unlock();
in6_dev_put(in6_dev);
} else {
- return -EAFNOSUPPORT;
+ rv = -EAFNOSUPPORT;
}
+out:
if (listeners)
rv = 0;
else if (!rv)
rv = -EINVAL;
- siw_dbg(id->device, "id 0x%p: %s\n", id, rv ? "FAIL" : "OK");
+ siw_dbg(id->device, "%s\n", rv ? "FAIL" : "OK");
return rv;
}
int siw_destroy_listen(struct iw_cm_id *id)
{
- siw_dbg(id->device, "id 0x%p\n", id);
-
if (!id->provider_data) {
- siw_dbg(id->device, "id 0x%p: no cep(s)\n", id);
+ siw_dbg(id->device, "no cep(s)\n");
return 0;
}
siw_drop_listeners(id);
diff --git a/drivers/infiniband/sw/siw/siw_cq.c b/drivers/infiniband/sw/siw/siw_cq.c
index e381ae9b7d62..d8db3bee9da7 100644
--- a/drivers/infiniband/sw/siw/siw_cq.c
+++ b/drivers/infiniband/sw/siw/siw_cq.c
@@ -71,9 +71,10 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc)
wc->wc_flags = IB_WC_WITH_INVALIDATE;
}
wc->qp = cqe->base_qp;
- siw_dbg_cq(cq, "idx %u, type %d, flags %2x, id 0x%p\n",
+ siw_dbg_cq(cq,
+ "idx %u, type %d, flags %2x, id 0x%pK\n",
cq->cq_get % cq->num_cqe, cqe->opcode,
- cqe->flags, (void *)cqe->id);
+ cqe->flags, (void *)(uintptr_t)cqe->id);
}
WRITE_ONCE(cqe->flags, 0);
cq->cq_get++;
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c
index f55c4e80aea4..05a92f997f60 100644
--- a/drivers/infiniband/sw/siw/siw_main.c
+++ b/drivers/infiniband/sw/siw/siw_main.c
@@ -160,10 +160,8 @@ static int siw_init_cpulist(void)
out_err:
siw_cpu_info.num_nodes = 0;
- while (i) {
+ while (--i >= 0)
kfree(siw_cpu_info.tx_valid_cpus[i]);
- siw_cpu_info.tx_valid_cpus[i--] = NULL;
- }
kfree(siw_cpu_info.tx_valid_cpus);
siw_cpu_info.tx_valid_cpus = NULL;
@@ -612,6 +610,7 @@ static __init int siw_init_module(void)
if (!siw_create_tx_threads()) {
pr_info("siw: Could not start any TX thread\n");
+ rv = -ENOMEM;
goto out_error;
}
/*
diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
index 67171c82b0c4..87a56039f0ef 100644
--- a/drivers/infiniband/sw/siw/siw_mem.c
+++ b/drivers/infiniband/sw/siw/siw_mem.c
@@ -197,12 +197,12 @@ int siw_check_mem(struct ib_pd *pd, struct siw_mem *mem, u64 addr,
*/
if (addr < mem->va || addr + len > mem->va + mem->len) {
siw_dbg_pd(pd, "MEM interval len %d\n", len);
- siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] out of bounds\n",
- (unsigned long long)addr,
- (unsigned long long)(addr + len));
- siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] STag=0x%08x\n",
- (unsigned long long)mem->va,
- (unsigned long long)(mem->va + mem->len),
+ siw_dbg_pd(pd, "[0x%pK, 0x%pK] out of bounds\n",
+ (void *)(uintptr_t)addr,
+ (void *)(uintptr_t)(addr + len));
+ siw_dbg_pd(pd, "[0x%pK, 0x%pK] STag=0x%08x\n",
+ (void *)(uintptr_t)mem->va,
+ (void *)(uintptr_t)(mem->va + mem->len),
mem->stag);
return -E_BASE_BOUNDS;
@@ -330,7 +330,7 @@ out:
* Optionally, provides remaining len within current element, and
* current PBL index for later resume at same element.
*/
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
{
int i = idx ? *idx : 0;
diff --git a/drivers/infiniband/sw/siw/siw_mem.h b/drivers/infiniband/sw/siw/siw_mem.h
index f43daf280891..db138c8423da 100644
--- a/drivers/infiniband/sw/siw/siw_mem.h
+++ b/drivers/infiniband/sw/siw/siw_mem.h
@@ -9,7 +9,7 @@
struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable);
void siw_umem_release(struct siw_umem *umem, bool dirty);
struct siw_pbl *siw_pbl_alloc(u32 num_buf);
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
struct siw_mem *siw_mem_id2obj(struct siw_device *sdev, int stag_index);
int siw_mem_add(struct siw_device *sdev, struct siw_mem *m);
int siw_invalidate_stag(struct ib_pd *pd, u32 stag);
diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c
index 11383d9f95ef..430314c8abd9 100644
--- a/drivers/infiniband/sw/siw/siw_qp.c
+++ b/drivers/infiniband/sw/siw/siw_qp.c
@@ -220,12 +220,14 @@ static int siw_qp_enable_crc(struct siw_qp *qp)
{
struct siw_rx_stream *c_rx = &qp->rx_stream;
struct siw_iwarp_tx *c_tx = &qp->tx_ctx;
- int size = crypto_shash_descsize(siw_crypto_shash) +
- sizeof(struct shash_desc);
+ int size;
if (siw_crypto_shash == NULL)
return -ENOENT;
+ size = crypto_shash_descsize(siw_crypto_shash) +
+ sizeof(struct shash_desc);
+
c_tx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
c_rx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
if (!c_tx->mpa_crc_hd || !c_rx->mpa_crc_hd) {
@@ -947,7 +949,7 @@ skip_irq:
rv = -EINVAL;
goto out;
}
- wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+ wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1];
wqe->sqe.sge[0].lkey = 0;
wqe->sqe.num_sge = 1;
}
@@ -1011,18 +1013,24 @@ out:
*/
static bool siw_cq_notify_now(struct siw_cq *cq, u32 flags)
{
- u64 cq_notify;
+ u32 cq_notify;
if (!cq->base_cq.comp_handler)
return false;
- cq_notify = READ_ONCE(*cq->notify);
+ /* Read application shared notification state */
+ cq_notify = READ_ONCE(cq->notify->flags);
if ((cq_notify & SIW_NOTIFY_NEXT_COMPLETION) ||
((cq_notify & SIW_NOTIFY_SOLICITED) &&
(flags & SIW_WQE_SOLICITED))) {
- /* dis-arm CQ */
- smp_store_mb(*cq->notify, SIW_NOTIFY_NOT);
+ /*
+ * CQ notification is one-shot: Since the
+ * current CQE causes user notification,
+ * the CQ gets dis-aremd and must be re-aremd
+ * by the user for a new notification.
+ */
+ WRITE_ONCE(cq->notify->flags, SIW_NOTIFY_NOT);
return true;
}
diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c
index f87657a11657..c0a887240325 100644
--- a/drivers/infiniband/sw/siw/siw_qp_rx.c
+++ b/drivers/infiniband/sw/siw/siw_qp_rx.c
@@ -38,9 +38,10 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
p = siw_get_upage(umem, dest_addr);
if (unlikely(!p)) {
- pr_warn("siw: %s: [QP %u]: bogus addr: %p, %p\n",
+ pr_warn("siw: %s: [QP %u]: bogus addr: %pK, %pK\n",
__func__, qp_id(rx_qp(srx)),
- (void *)dest_addr, (void *)umem->fp_addr);
+ (void *)(uintptr_t)dest_addr,
+ (void *)(uintptr_t)umem->fp_addr);
/* siw internal error */
srx->skb_copied += copied;
srx->skb_new -= copied;
@@ -50,7 +51,7 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
pg_off = dest_addr & ~PAGE_MASK;
bytes = min(len, (int)PAGE_SIZE - pg_off);
- siw_dbg_qp(rx_qp(srx), "page %p, bytes=%u\n", p, bytes);
+ siw_dbg_qp(rx_qp(srx), "page %pK, bytes=%u\n", p, bytes);
dest = kmap_atomic(p);
rv = skb_copy_bits(srx->skb, srx->skb_offset, dest + pg_off,
@@ -104,11 +105,11 @@ static int siw_rx_kva(struct siw_rx_stream *srx, void *kva, int len)
{
int rv;
- siw_dbg_qp(rx_qp(srx), "kva: 0x%p, len: %u\n", kva, len);
+ siw_dbg_qp(rx_qp(srx), "kva: 0x%pK, len: %u\n", kva, len);
rv = skb_copy_bits(srx->skb, srx->skb_offset, kva, len);
if (unlikely(rv)) {
- pr_warn("siw: [QP %u]: %s, len %d, kva 0x%p, rv %d\n",
+ pr_warn("siw: [QP %u]: %s, len %d, kva 0x%pK, rv %d\n",
qp_id(rx_qp(srx)), __func__, len, kva, rv);
return rv;
@@ -132,7 +133,7 @@ static int siw_rx_pbl(struct siw_rx_stream *srx, int *pbl_idx,
while (len) {
int bytes;
- u64 buf_addr =
+ dma_addr_t buf_addr =
siw_pbl_get_buffer(pbl, offset, &bytes, pbl_idx);
if (!buf_addr)
break;
@@ -485,8 +486,8 @@ int siw_proc_send(struct siw_qp *qp)
mem_p = *mem;
if (mem_p->mem_obj == NULL)
rv = siw_rx_kva(srx,
- (void *)(sge->laddr + frx->sge_off),
- sge_bytes);
+ (void *)(uintptr_t)(sge->laddr + frx->sge_off),
+ sge_bytes);
else if (!mem_p->is_pbl)
rv = siw_rx_umem(srx, mem_p->umem,
sge->laddr + frx->sge_off, sge_bytes);
@@ -598,8 +599,8 @@ int siw_proc_write(struct siw_qp *qp)
if (mem->mem_obj == NULL)
rv = siw_rx_kva(srx,
- (void *)(srx->ddp_to + srx->fpdu_part_rcvd),
- bytes);
+ (void *)(uintptr_t)(srx->ddp_to + srx->fpdu_part_rcvd),
+ bytes);
else if (!mem->is_pbl)
rv = siw_rx_umem(srx, mem->umem,
srx->ddp_to + srx->fpdu_part_rcvd, bytes);
@@ -841,8 +842,9 @@ int siw_proc_rresp(struct siw_qp *qp)
bytes = min(srx->fpdu_part_rem, srx->skb_new);
if (mem_p->mem_obj == NULL)
- rv = siw_rx_kva(srx, (void *)(sge->laddr + wqe->processed),
- bytes);
+ rv = siw_rx_kva(srx,
+ (void *)(uintptr_t)(sge->laddr + wqe->processed),
+ bytes);
else if (!mem_p->is_pbl)
rv = siw_rx_umem(srx, mem_p->umem, sge->laddr + wqe->processed,
bytes);
diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c
index 43020d2040fc..438a2917a47c 100644
--- a/drivers/infiniband/sw/siw/siw_qp_tx.c
+++ b/drivers/infiniband/sw/siw/siw_qp_tx.c
@@ -26,7 +26,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
{
struct siw_pbl *pbl = mem->pbl;
u64 offset = addr - mem->va;
- u64 paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
+ dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
if (paddr)
return virt_to_page(paddr);
@@ -37,7 +37,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
/*
* Copy short payload at provided destination payload address
*/
-static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
+static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
{
struct siw_wqe *wqe = &c_tx->wqe_active;
struct siw_sge *sge = &wqe->sqe.sge[0];
@@ -50,16 +50,16 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
return 0;
if (tx_flags(wqe) & SIW_WQE_INLINE) {
- memcpy((void *)paddr, &wqe->sqe.sge[1], bytes);
+ memcpy(paddr, &wqe->sqe.sge[1], bytes);
} else {
struct siw_mem *mem = wqe->mem[0];
if (!mem->mem_obj) {
/* Kernel client using kva */
- memcpy((void *)paddr, (void *)sge->laddr, bytes);
+ memcpy(paddr,
+ (const void *)(uintptr_t)sge->laddr, bytes);
} else if (c_tx->in_syscall) {
- if (copy_from_user((void *)paddr,
- (const void __user *)sge->laddr,
+ if (copy_from_user(paddr, u64_to_user_ptr(sge->laddr),
bytes))
return -EFAULT;
} else {
@@ -79,12 +79,12 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
buffer = kmap_atomic(p);
if (likely(PAGE_SIZE - off >= bytes)) {
- memcpy((void *)paddr, buffer + off, bytes);
+ memcpy(paddr, buffer + off, bytes);
kunmap_atomic(buffer);
} else {
unsigned long part = bytes - (PAGE_SIZE - off);
- memcpy((void *)paddr, buffer + off, part);
+ memcpy(paddr, buffer + off, part);
kunmap_atomic(buffer);
if (!mem->is_pbl)
@@ -98,7 +98,7 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
return -EFAULT;
buffer = kmap_atomic(p);
- memcpy((void *)(paddr + part), buffer,
+ memcpy(paddr + part, buffer,
bytes - part);
kunmap_atomic(buffer);
}
@@ -166,7 +166,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
c_tx->ctrl_len = sizeof(struct iwarp_send);
crc = (char *)&c_tx->pkt.send_pkt.crc;
- data = siw_try_1seg(c_tx, (u64)crc);
+ data = siw_try_1seg(c_tx, crc);
break;
case SIW_OP_SEND_REMOTE_INV:
@@ -189,7 +189,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
c_tx->ctrl_len = sizeof(struct iwarp_send_inv);
crc = (char *)&c_tx->pkt.send_pkt.crc;
- data = siw_try_1seg(c_tx, (u64)crc);
+ data = siw_try_1seg(c_tx, crc);
break;
case SIW_OP_WRITE:
@@ -201,7 +201,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
c_tx->ctrl_len = sizeof(struct iwarp_rdma_write);
crc = (char *)&c_tx->pkt.write_pkt.crc;
- data = siw_try_1seg(c_tx, (u64)crc);
+ data = siw_try_1seg(c_tx, crc);
break;
case SIW_OP_READ_RESPONSE:
@@ -216,7 +216,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
c_tx->ctrl_len = sizeof(struct iwarp_rdma_rresp);
crc = (char *)&c_tx->pkt.write_pkt.crc;
- data = siw_try_1seg(c_tx, (u64)crc);
+ data = siw_try_1seg(c_tx, crc);
break;
default:
@@ -398,15 +398,13 @@ static int siw_0copy_tx(struct socket *s, struct page **page,
#define MAX_TRAILER (MPA_CRC_SIZE + 4)
-static void siw_unmap_pages(struct page **pages, int hdr_len, int num_maps)
+static void siw_unmap_pages(struct page **pp, unsigned long kmap_mask)
{
- if (hdr_len) {
- ++pages;
- --num_maps;
- }
- while (num_maps-- > 0) {
- kunmap(*pages);
- pages++;
+ while (kmap_mask) {
+ if (kmap_mask & BIT(0))
+ kunmap(*pp);
+ pp++;
+ kmap_mask >>= 1;
}
}
@@ -437,6 +435,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
unsigned int data_len = c_tx->bytes_unsent, hdr_len = 0, trl_len = 0,
sge_off = c_tx->sge_off, sge_idx = c_tx->sge_idx,
pbl_idx = c_tx->pbl_idx;
+ unsigned long kmap_mask = 0L;
if (c_tx->state == SIW_SEND_HDR) {
if (c_tx->use_sendpage) {
@@ -463,8 +462,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
if (!(tx_flags(wqe) & SIW_WQE_INLINE)) {
mem = wqe->mem[sge_idx];
- if (!mem->mem_obj)
- is_kva = 1;
+ is_kva = mem->mem_obj == NULL ? 1 : 0;
} else {
is_kva = 1;
}
@@ -473,7 +471,8 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
* tx from kernel virtual address: either inline data
* or memory region with assigned kernel buffer
*/
- iov[seg].iov_base = (void *)(sge->laddr + sge_off);
+ iov[seg].iov_base =
+ (void *)(uintptr_t)(sge->laddr + sge_off);
iov[seg].iov_len = sge_len;
if (do_crc)
@@ -500,12 +499,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
p = siw_get_upage(mem->umem,
sge->laddr + sge_off);
if (unlikely(!p)) {
- if (hdr_len)
- seg--;
- if (!c_tx->use_sendpage && seg) {
- siw_unmap_pages(page_array,
- hdr_len, seg);
- }
+ siw_unmap_pages(page_array, kmap_mask);
wqe->processed -= c_tx->bytes_unsent;
rv = -EFAULT;
goto done_crc;
@@ -515,6 +509,10 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
if (!c_tx->use_sendpage) {
iov[seg].iov_base = kmap(p) + fp_off;
iov[seg].iov_len = plen;
+
+ /* Remember for later kunmap() */
+ kmap_mask |= BIT(seg);
+
if (do_crc)
crypto_shash_update(
c_tx->mpa_crc_hd,
@@ -526,13 +524,13 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
page_address(p) + fp_off,
plen);
} else {
- u64 pa = ((sge->laddr + sge_off) & PAGE_MASK);
+ u64 va = sge->laddr + sge_off;
- page_array[seg] = virt_to_page(pa);
+ page_array[seg] = virt_to_page(va & PAGE_MASK);
if (do_crc)
crypto_shash_update(
c_tx->mpa_crc_hd,
- (void *)(sge->laddr + sge_off),
+ (void *)(uintptr_t)va,
plen);
}
@@ -543,10 +541,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
if (++seg > (int)MAX_ARRAY) {
siw_dbg_qp(tx_qp(c_tx), "to many fragments\n");
- if (!is_kva && !c_tx->use_sendpage) {
- siw_unmap_pages(page_array, hdr_len,
- seg - 1);
- }
+ siw_unmap_pages(page_array, kmap_mask);
wqe->processed -= c_tx->bytes_unsent;
rv = -EMSGSIZE;
goto done_crc;
@@ -597,8 +592,7 @@ sge_done:
} else {
rv = kernel_sendmsg(s, &msg, iov, seg + 1,
hdr_len + data_len + trl_len);
- if (!is_kva)
- siw_unmap_pages(page_array, hdr_len, seg);
+ siw_unmap_pages(page_array, kmap_mask);
}
if (rv < (int)hdr_len) {
/* Not even complete hdr pushed or negative rv */
@@ -829,7 +823,8 @@ static int siw_qp_sq_proc_tx(struct siw_qp *qp, struct siw_wqe *wqe)
rv = -EINVAL;
goto tx_error;
}
- wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+ wqe->sqe.sge[0].laddr =
+ (u64)(uintptr_t)&wqe->sqe.sge[1];
}
}
wqe->wr_status = SIW_WR_INPROGRESS;
@@ -924,7 +919,7 @@ tx_error:
static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
{
- struct ib_mr *base_mr = (struct ib_mr *)sqe->base_mr;
+ struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr;
struct siw_device *sdev = to_siw_dev(pd->device);
struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey >> 8);
int rv = 0;
@@ -954,8 +949,7 @@ static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
mem->stag = sqe->rkey;
mem->perms = sqe->access;
- siw_dbg_mem(mem, "STag now valid, MR va: 0x%016llx -> 0x%016llx\n",
- mem->va, base_mr->iova);
+ siw_dbg_mem(mem, "STag 0x%08x now valid\n", sqe->rkey);
mem->va = base_mr->iova;
mem->stag_valid = 1;
out:
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index 32dc79d0e898..da52c90e06d4 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -424,8 +424,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
*/
qp->srq = to_siw_srq(attrs->srq);
qp->attrs.rq_size = 0;
- siw_dbg(base_dev, "QP [%u]: [SRQ 0x%p] attached\n",
- qp->qp_num, qp->srq);
+ siw_dbg(base_dev, "QP [%u]: SRQ attached\n", qp->qp_num);
} else if (num_rqe) {
if (qp->kernel_verbs)
qp->recvq = vzalloc(num_rqe * sizeof(struct siw_rqe));
@@ -610,7 +609,7 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
base_ucontext);
struct siw_qp_attrs qp_attrs;
- siw_dbg_qp(qp, "state %d, cep 0x%p\n", qp->attrs.state, qp->cep);
+ siw_dbg_qp(qp, "state %d\n", qp->attrs.state);
/*
* Mark QP as in process of destruction to prevent from
@@ -662,7 +661,7 @@ static int siw_copy_inline_sgl(const struct ib_send_wr *core_wr,
void *kbuf = &sqe->sge[1];
int num_sge = core_wr->num_sge, bytes = 0;
- sqe->sge[0].laddr = (u64)kbuf;
+ sqe->sge[0].laddr = (uintptr_t)kbuf;
sqe->sge[0].lkey = 0;
while (num_sge--) {
@@ -825,7 +824,7 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
break;
case IB_WR_REG_MR:
- sqe->base_mr = (uint64_t)reg_wr(wr)->mr;
+ sqe->base_mr = (uintptr_t)reg_wr(wr)->mr;
sqe->rkey = reg_wr(wr)->key;
sqe->access = reg_wr(wr)->access & IWARP_ACCESS_MASK;
sqe->opcode = SIW_OP_REG_MR;
@@ -842,8 +841,9 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
rv = -EINVAL;
break;
}
- siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%p\n",
- sqe->opcode, sqe->flags, (void *)sqe->id);
+ siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%pK\n",
+ sqe->opcode, sqe->flags,
+ (void *)(uintptr_t)sqe->id);
if (unlikely(rv < 0))
break;
@@ -1049,7 +1049,7 @@ int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
spin_lock_init(&cq->lock);
- cq->notify = &((struct siw_cq_ctrl *)&cq->queue[size])->notify;
+ cq->notify = (struct siw_cq_ctrl *)&cq->queue[size];
if (udata) {
struct siw_uresp_create_cq uresp = {};
@@ -1141,11 +1141,17 @@ int siw_req_notify_cq(struct ib_cq *base_cq, enum ib_cq_notify_flags flags)
siw_dbg_cq(cq, "flags: 0x%02x\n", flags);
if ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
- /* CQ event for next solicited completion */
- smp_store_mb(*cq->notify, SIW_NOTIFY_SOLICITED);
+ /*
+ * Enable CQ event for next solicited completion.
+ * and make it visible to all associated producers.
+ */
+ smp_store_mb(cq->notify->flags, SIW_NOTIFY_SOLICITED);
else
- /* CQ event for any signalled completion */
- smp_store_mb(*cq->notify, SIW_NOTIFY_ALL);
+ /*
+ * Enable CQ event for any signalled completion.
+ * and make it visible to all associated producers.
+ */
+ smp_store_mb(cq->notify->flags, SIW_NOTIFY_ALL);
if (flags & IB_CQ_REPORT_MISSED_EVENTS)
return cq->cq_put - cq->cq_get;
@@ -1199,8 +1205,8 @@ struct ib_mr *siw_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
unsigned long mem_limit = rlimit(RLIMIT_MEMLOCK);
int rv;
- siw_dbg_pd(pd, "start: 0x%016llx, va: 0x%016llx, len: %llu\n",
- (unsigned long long)start, (unsigned long long)rnic_va,
+ siw_dbg_pd(pd, "start: 0x%pK, va: 0x%pK, len: %llu\n",
+ (void *)(uintptr_t)start, (void *)(uintptr_t)rnic_va,
(unsigned long long)len);
if (atomic_inc_return(&sdev->num_mr) > SIW_MAX_MR) {
@@ -1357,7 +1363,7 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
struct siw_mem *mem = mr->mem;
struct siw_pbl *pbl = mem->pbl;
struct siw_pble *pble;
- u64 pbl_size;
+ unsigned long pbl_size;
int i, rv;
if (!pbl) {
@@ -1396,16 +1402,18 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
pbl_size += sg_dma_len(slp);
}
siw_dbg_mem(mem,
- "sge[%d], size %llu, addr 0x%016llx, total %llu\n",
- i, pble->size, pble->addr, pbl_size);
+ "sge[%d], size %u, addr 0x%p, total %lu\n",
+ i, pble->size, (void *)(uintptr_t)pble->addr,
+ pbl_size);
}
rv = ib_sg_to_pages(base_mr, sl, num_sle, sg_off, siw_set_pbl_page);
if (rv > 0) {
mem->len = base_mr->length;
mem->va = base_mr->iova;
siw_dbg_mem(mem,
- "%llu bytes, start 0x%016llx, %u SLE to %u entries\n",
- mem->len, mem->va, num_sle, pbl->num_buf);
+ "%llu bytes, start 0x%pK, %u SLE to %u entries\n",
+ mem->len, (void *)(uintptr_t)mem->va, num_sle,
+ pbl->num_buf);
}
return rv;
}
@@ -1523,7 +1531,7 @@ int siw_create_srq(struct ib_srq *base_srq,
}
spin_lock_init(&srq->lock);
- siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: success\n", srq);
+ siw_dbg_pd(base_srq->pd, "[SRQ]: success\n");
return 0;
@@ -1644,8 +1652,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
if (unlikely(!srq->kernel_verbs)) {
siw_dbg_pd(base_srq->pd,
- "[SRQ 0x%p]: no kernel post_recv for mapped srq\n",
- srq);
+ "[SRQ]: no kernel post_recv for mapped srq\n");
rv = -EINVAL;
goto out;
}
@@ -1667,8 +1674,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
}
if (unlikely(wr->num_sge > srq->max_sge)) {
siw_dbg_pd(base_srq->pd,
- "[SRQ 0x%p]: too many sge's: %d\n", srq,
- wr->num_sge);
+ "[SRQ]: too many sge's: %d\n", wr->num_sge);
rv = -EINVAL;
break;
}
@@ -1687,7 +1693,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
spin_unlock_irqrestore(&srq->lock, flags);
out:
if (unlikely(rv < 0)) {
- siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: error %d\n", srq, rv);
+ siw_dbg_pd(base_srq->pd, "[SRQ]: error %d\n", rv);
*bad_wr = wr;
}
return rv;
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 29abfeeef9a5..6c554c11a7ac 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -201,7 +201,12 @@ static int iforce_usb_probe(struct usb_interface *intf,
return -ENODEV;
epirq = &interface->endpoint[0].desc;
+ if (!usb_endpoint_is_int_in(epirq))
+ return -ENODEV;
+
epout = &interface->endpoint[1].desc;
+ if (!usb_endpoint_is_int_out(epout))
+ return -ENODEV;
iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
if (!iforce_usb)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 8e9c3ea9d5e7..90e8a7f2f07c 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -76,6 +76,8 @@ config KEYBOARD_APPLESPI
depends on ACPI && EFI
depends on SPI
depends on X86 || COMPILE_TEST
+ depends on LEDS_CLASS
+ select CRC16
help
Say Y here if you are running Linux on any Apple MacBook8,1 or later,
or any MacBookPro13,* or MacBookPro14,*.
diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c
index 548737e7aeda..584289b67fb3 100644
--- a/drivers/input/keyboard/applespi.c
+++ b/drivers/input/keyboard/applespi.c
@@ -134,10 +134,10 @@ struct keyboard_protocol {
* struct tp_finger - single trackpad finger structure, le16-aligned
*
* @origin: zero when switching track finger
- * @abs_x: absolute x coodinate
- * @abs_y: absolute y coodinate
- * @rel_x: relative x coodinate
- * @rel_y: relative y coodinate
+ * @abs_x: absolute x coordinate
+ * @abs_y: absolute y coordinate
+ * @rel_x: relative x coordinate
+ * @rel_y: relative y coordinate
* @tool_major: tool area, major axis
* @tool_minor: tool area, minor axis
* @orientation: 16384 when point, else 15 bit angle
@@ -944,10 +944,14 @@ static inline int le16_to_int(__le16 x)
static void applespi_debug_update_dimensions(struct applespi_data *applespi,
const struct tp_finger *f)
{
- applespi->tp_dim_min_x = min_t(int, applespi->tp_dim_min_x, f->abs_x);
- applespi->tp_dim_max_x = max_t(int, applespi->tp_dim_max_x, f->abs_x);
- applespi->tp_dim_min_y = min_t(int, applespi->tp_dim_min_y, f->abs_y);
- applespi->tp_dim_max_y = max_t(int, applespi->tp_dim_max_y, f->abs_y);
+ applespi->tp_dim_min_x = min(applespi->tp_dim_min_x,
+ le16_to_int(f->abs_x));
+ applespi->tp_dim_max_x = max(applespi->tp_dim_max_x,
+ le16_to_int(f->abs_x));
+ applespi->tp_dim_min_y = min(applespi->tp_dim_min_y,
+ le16_to_int(f->abs_y));
+ applespi->tp_dim_max_y = max(applespi->tp_dim_max_y,
+ le16_to_int(f->abs_y));
}
static int applespi_tp_dim_open(struct inode *inode, struct file *file)
@@ -1490,8 +1494,7 @@ static void applespi_got_data(struct applespi_data *applespi)
size_t tp_len;
tp = &message->touchpad;
- tp_len = sizeof(*tp) +
- tp->number_of_fingers * sizeof(tp->fingers[0]);
+ tp_len = struct_size(tp, fingers, tp->number_of_fingers);
if (le16_to_cpu(message->length) + 2 != tp_len) {
dev_warn_ratelimited(&applespi->spi->dev,
@@ -1611,8 +1614,8 @@ static void applespi_save_bl_level(struct applespi_data *applespi,
efi_attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
- sts = efivar_entry_set_safe(EFI_BL_LEVEL_NAME, efi_guid, efi_attr, true,
- efi_data_len, &efi_data);
+ sts = efivar_entry_set_safe((efi_char16_t *)EFI_BL_LEVEL_NAME, efi_guid,
+ efi_attr, true, efi_data_len, &efi_data);
if (sts)
dev_warn(&applespi->spi->dev,
"Error saving backlight level to EFI vars: %d\n", sts);
@@ -1953,7 +1956,7 @@ static const struct acpi_device_id applespi_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, applespi_acpi_match);
-const struct dev_pm_ops applespi_pm_ops = {
+static const struct dev_pm_ops applespi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(applespi_suspend, applespi_resume)
.poweroff_late = applespi_poweroff_late,
};
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 2d8434b7b623..04fe43440a3c 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1827,6 +1827,31 @@ static int elantech_create_smbus(struct psmouse *psmouse,
leave_breadcrumbs);
}
+static bool elantech_use_host_notify(struct psmouse *psmouse,
+ struct elantech_device_info *info)
+{
+ if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+ return true;
+
+ switch (info->bus) {
+ case ETP_BUS_PS2_ONLY:
+ /* expected case */
+ break;
+ case ETP_BUS_SMB_HST_NTFY_ONLY:
+ case ETP_BUS_PS2_SMB_HST_NTFY:
+ /* SMbus implementation is stable since 2018 */
+ if (dmi_get_bios_year() >= 2018)
+ return true;
+ /* fall through */
+ default:
+ psmouse_dbg(psmouse,
+ "Ignoring SMBus bus provider %d\n", info->bus);
+ break;
+ }
+
+ return false;
+}
+
/**
* elantech_setup_smbus - called once the PS/2 devices are enumerated
* and decides to instantiate a SMBus InterTouch device.
@@ -1846,7 +1871,7 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
* i2c_blacklist_pnp_ids.
* Old ICs are up to the user to decide.
*/
- if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) ||
+ if (!elantech_use_host_notify(psmouse, info) ||
psmouse_matches_pnp_id(psmouse, i2c_blacklist_pnp_ids))
return -ENXIO;
}
@@ -1866,34 +1891,6 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
return 0;
}
-static bool elantech_use_host_notify(struct psmouse *psmouse,
- struct elantech_device_info *info)
-{
- if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
- return true;
-
- switch (info->bus) {
- case ETP_BUS_PS2_ONLY:
- /* expected case */
- break;
- case ETP_BUS_SMB_ALERT_ONLY:
- /* fall-through */
- case ETP_BUS_PS2_SMB_ALERT:
- psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
- break;
- case ETP_BUS_SMB_HST_NTFY_ONLY:
- /* fall-through */
- case ETP_BUS_PS2_SMB_HST_NTFY:
- return true;
- default:
- psmouse_dbg(psmouse,
- "Ignoring SMBus bus provider %d.\n",
- info->bus);
- }
-
- return false;
-}
-
int elantech_init_smbus(struct psmouse *psmouse)
{
struct elantech_device_info info;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index b1956ed4c0dd..46bbe99d6511 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -182,6 +182,7 @@ static const char * const smbus_pnp_ids[] = {
"LEN2055", /* E580 */
"SYN3052", /* HP EliteBook 840 G4 */
"SYN3221", /* HP 15-ay000 */
+ "SYN323d", /* HP Spectre X360 13-w013dx */
NULL
};
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index 871e5b5ab129..148245c69be7 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -16,12 +16,12 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <asm/hypervisor.h>
+#include <asm/vmware.h>
#include "psmouse.h"
#include "vmmouse.h"
#define VMMOUSE_PROTO_MAGIC 0x564D5868U
-#define VMMOUSE_PROTO_PORT 0x5658
/*
* Main commands supported by the vmmouse hypervisor port.
@@ -84,7 +84,7 @@ struct vmmouse_data {
#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \
({ \
unsigned long __dummy1, __dummy2; \
- __asm__ __volatile__ ("inl %%dx" : \
+ __asm__ __volatile__ (VMWARE_HYPERCALL : \
"=a"(out1), \
"=b"(out2), \
"=c"(out3), \
@@ -94,7 +94,7 @@ struct vmmouse_data {
"a"(VMMOUSE_PROTO_MAGIC), \
"b"(in1), \
"c"(VMMOUSE_PROTO_CMD_##cmd), \
- "d"(VMMOUSE_PROTO_PORT) : \
+ "d"(0) : \
"memory"); \
})
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
index 88ae7c2ac3c8..e486a8a74c40 100644
--- a/drivers/input/serio/hyperv-keyboard.c
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -237,40 +237,17 @@ static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
static void hv_kbd_on_channel_callback(void *context)
{
+ struct vmpacket_descriptor *desc;
struct hv_device *hv_dev = context;
- void *buffer;
- int bufferlen = 0x100; /* Start with sensible size */
u32 bytes_recvd;
u64 req_id;
- int error;
- buffer = kmalloc(bufferlen, GFP_ATOMIC);
- if (!buffer)
- return;
-
- while (1) {
- error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen,
- &bytes_recvd, &req_id);
- switch (error) {
- case 0:
- if (bytes_recvd == 0) {
- kfree(buffer);
- return;
- }
-
- hv_kbd_handle_received_packet(hv_dev, buffer,
- bytes_recvd, req_id);
- break;
+ foreach_vmbus_pkt(desc, hv_dev->channel) {
+ bytes_recvd = desc->len8 * 8;
+ req_id = desc->trans_id;
- case -ENOBUFS:
- kfree(buffer);
- /* Handle large packet */
- bufferlen = bytes_recvd;
- buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
- if (!buffer)
- return;
- break;
- }
+ hv_kbd_handle_received_packet(hv_dev, desc, bytes_recvd,
+ req_id);
}
}
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index 04b85571f41e..aa577898e952 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -117,6 +117,10 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
if (intf->cur_altsetting->desc.bNumEndpoints < 1)
return -ENODEV;
+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
+ if (!usb_endpoint_is_int_in(endpoint))
+ return -ENODEV;
+
kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
input_dev = input_allocate_device();
if (!kbtab || !input_dev)
@@ -155,8 +159,6 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
- endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
usb_fill_int_urb(kbtab->irq, dev,
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
kbtab->data, 8,
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index a2cec6cacf57..16d70201de4a 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -1659,6 +1659,8 @@ static int usbtouch_probe(struct usb_interface *intf,
if (!usbtouch || !input_dev)
goto out_free;
+ mutex_init(&usbtouch->pm_mutex);
+
type = &usbtouch_dev_info[id->driver_info];
usbtouch->type = type;
if (!type->process_pkt)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index e15cdcd8cb3c..e3842eabcfdd 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -177,11 +177,12 @@ config DMAR_TABLE
config INTEL_IOMMU
bool "Support for Intel IOMMU using DMA Remapping Devices"
- depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
+ depends on PCI_MSI && ACPI && (X86 || IA64)
select IOMMU_API
select IOMMU_IOVA
select NEED_DMA_MAP_STATE
select DMAR_TABLE
+ select SWIOTLB
help
DMA remapping (DMAR) devices support enables independent address
translations for Direct Memory Access (DMA) from devices.
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index f13f36ae1af6..4f405f926e73 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -10,13 +10,14 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
obj-$(CONFIG_IOMMU_IOVA) += iova.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
-obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
+obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o
obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
+obj-$(CONFIG_INTEL_IOMMU) += intel-trace.o
obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += intel-iommu-debugfs.o
obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b607a92791d3..1ed3b98324ba 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -436,7 +436,7 @@ static int iommu_init_device(struct device *dev)
* invalid address), we ignore the capability for the device so
* it'll be forced to go into translation mode.
*/
- if ((iommu_pass_through || !amd_iommu_force_isolation) &&
+ if ((iommu_default_passthrough() || !amd_iommu_force_isolation) &&
dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
struct amd_iommu *iommu;
@@ -1143,6 +1143,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu *iommu)
iommu_completion_wait(iommu);
}
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+ struct iommu_cmd cmd;
+
+ build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+ dom_id, 1);
+ iommu_queue_command(iommu, &cmd);
+
+ iommu_completion_wait(iommu);
+}
+
static void amd_iommu_flush_all(struct amd_iommu *iommu)
{
struct iommu_cmd cmd;
@@ -1424,18 +1435,21 @@ static void free_pagetable(struct protection_domain *domain)
* another level increases the size of the address space by 9 bits to a size up
* to 64 bits.
*/
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
gfp_t gfp)
{
+ unsigned long flags;
u64 *pte;
- if (domain->mode == PAGE_MODE_6_LEVEL)
+ spin_lock_irqsave(&domain->lock, flags);
+
+ if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
/* address space already 64 bit large */
- return false;
+ goto out;
pte = (void *)get_zeroed_page(gfp);
if (!pte)
- return false;
+ goto out;
*pte = PM_LEVEL_PDE(domain->mode,
iommu_virt_to_phys(domain->pt_root));
@@ -1443,7 +1457,10 @@ static bool increase_address_space(struct protection_domain *domain,
domain->mode += 1;
domain->updated = true;
- return true;
+out:
+ spin_unlock_irqrestore(&domain->lock, flags);
+
+ return;
}
static u64 *alloc_pte(struct protection_domain *domain,
@@ -1873,6 +1890,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
{
u64 pte_root = 0;
u64 flags = 0;
+ u32 old_domid;
if (domain->mode != PAGE_MODE_NONE)
pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1922,8 +1940,20 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
flags &= ~DEV_DOMID_MASK;
flags |= domain->id;
+ old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
amd_iommu_dev_table[devid].data[1] = flags;
amd_iommu_dev_table[devid].data[0] = pte_root;
+
+ /*
+ * A kdump kernel might be replacing a domain ID that was copied from
+ * the previous kernel--if so, it needs to flush the translation cache
+ * entries for the old domain ID that is being overwritten
+ */
+ if (old_domid) {
+ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+ amd_iommu_flush_tlb_domid(iommu, old_domid);
+ }
}
static void clear_dte_entry(u16 devid)
@@ -2226,7 +2256,7 @@ static int amd_iommu_add_device(struct device *dev)
BUG_ON(!dev_data);
- if (iommu_pass_through || dev_data->iommu_v2)
+ if (dev_data->iommu_v2)
iommu_request_dm_for_dev(dev);
/* Domains are initialized for this device - have a look what we ended up with */
@@ -2547,7 +2577,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
bus_addr = address + s->dma_address + (j << PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT);
- ret = iommu_map_page(domain, bus_addr, phys_addr, PAGE_SIZE, prot, GFP_ATOMIC);
+ ret = iommu_map_page(domain, bus_addr, phys_addr,
+ PAGE_SIZE, prot,
+ GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
@@ -2805,7 +2837,7 @@ int __init amd_iommu_init_api(void)
int __init amd_iommu_init_dma_ops(void)
{
- swiotlb = (iommu_pass_through || sme_me_mask) ? 1 : 0;
+ swiotlb = (iommu_default_passthrough() || sme_me_mask) ? 1 : 0;
iommu_detected = 1;
if (amd_iommu_unmap_flush)
@@ -3055,7 +3087,8 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
}
static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
- size_t page_size)
+ size_t page_size,
+ struct iommu_iotlb_gather *gather)
{
struct protection_domain *domain = to_pdomain(dom);
size_t unmap_size;
@@ -3196,9 +3229,10 @@ static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain)
domain_flush_complete(dom);
}
-static void amd_iommu_iotlb_range_add(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+static void amd_iommu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
{
+ amd_iommu_flush_iotlb_all(domain);
}
const struct iommu_ops amd_iommu_ops = {
@@ -3219,8 +3253,7 @@ const struct iommu_ops amd_iommu_ops = {
.is_attach_deferred = amd_iommu_is_attach_deferred,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
.flush_iotlb_all = amd_iommu_flush_iotlb_all,
- .iotlb_range_add = amd_iommu_iotlb_range_add,
- .iotlb_sync = amd_iommu_flush_iotlb_all,
+ .iotlb_sync = amd_iommu_iotlb_sync,
};
/*****************************************************************************
@@ -4313,13 +4346,62 @@ static const struct irq_domain_ops amd_ir_domain_ops = {
.deactivate = irq_remapping_deactivate,
};
+int amd_iommu_activate_guest_mode(void *data)
+{
+ struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
+ struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
+
+ if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
+ !entry || entry->lo.fields_vapic.guest_mode)
+ return 0;
+
+ entry->lo.val = 0;
+ entry->hi.val = 0;
+
+ entry->lo.fields_vapic.guest_mode = 1;
+ entry->lo.fields_vapic.ga_log_intr = 1;
+ entry->hi.fields.ga_root_ptr = ir_data->ga_root_ptr;
+ entry->hi.fields.vector = ir_data->ga_vector;
+ entry->lo.fields_vapic.ga_tag = ir_data->ga_tag;
+
+ return modify_irte_ga(ir_data->irq_2_irte.devid,
+ ir_data->irq_2_irte.index, entry, NULL);
+}
+EXPORT_SYMBOL(amd_iommu_activate_guest_mode);
+
+int amd_iommu_deactivate_guest_mode(void *data)
+{
+ struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
+ struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
+ struct irq_cfg *cfg = ir_data->cfg;
+
+ if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
+ !entry || !entry->lo.fields_vapic.guest_mode)
+ return 0;
+
+ entry->lo.val = 0;
+ entry->hi.val = 0;
+
+ entry->lo.fields_remap.dm = apic->irq_dest_mode;
+ entry->lo.fields_remap.int_type = apic->irq_delivery_mode;
+ entry->hi.fields.vector = cfg->vector;
+ entry->lo.fields_remap.destination =
+ APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
+ entry->hi.fields.destination =
+ APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
+
+ return modify_irte_ga(ir_data->irq_2_irte.devid,
+ ir_data->irq_2_irte.index, entry, NULL);
+}
+EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode);
+
static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
{
+ int ret;
struct amd_iommu *iommu;
struct amd_iommu_pi_data *pi_data = vcpu_info;
struct vcpu_data *vcpu_pi_info = pi_data->vcpu_data;
struct amd_ir_data *ir_data = data->chip_data;
- struct irte_ga *irte = (struct irte_ga *) ir_data->entry;
struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
struct iommu_dev_data *dev_data = search_dev_data(irte_info->devid);
@@ -4330,6 +4412,7 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
if (!dev_data || !dev_data->use_vapic)
return 0;
+ ir_data->cfg = irqd_cfg(data);
pi_data->ir_data = ir_data;
/* Note:
@@ -4348,37 +4431,24 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
pi_data->prev_ga_tag = ir_data->cached_ga_tag;
if (pi_data->is_guest_mode) {
- /* Setting */
- irte->hi.fields.ga_root_ptr = (pi_data->base >> 12);
- irte->hi.fields.vector = vcpu_pi_info->vector;
- irte->lo.fields_vapic.ga_log_intr = 1;
- irte->lo.fields_vapic.guest_mode = 1;
- irte->lo.fields_vapic.ga_tag = pi_data->ga_tag;
-
- ir_data->cached_ga_tag = pi_data->ga_tag;
+ ir_data->ga_root_ptr = (pi_data->base >> 12);
+ ir_data->ga_vector = vcpu_pi_info->vector;
+ ir_data->ga_tag = pi_data->ga_tag;
+ ret = amd_iommu_activate_guest_mode(ir_data);
+ if (!ret)
+ ir_data->cached_ga_tag = pi_data->ga_tag;
} else {
- /* Un-Setting */
- struct irq_cfg *cfg = irqd_cfg(data);
-
- irte->hi.val = 0;
- irte->lo.val = 0;
- irte->hi.fields.vector = cfg->vector;
- irte->lo.fields_remap.guest_mode = 0;
- irte->lo.fields_remap.destination =
- APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
- irte->hi.fields.destination =
- APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
- irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
- irte->lo.fields_remap.dm = apic->irq_dest_mode;
+ ret = amd_iommu_deactivate_guest_mode(ir_data);
/*
* This communicates the ga_tag back to the caller
* so that it can do all the necessary clean up.
*/
- ir_data->cached_ga_tag = 0;
+ if (!ret)
+ ir_data->cached_ga_tag = 0;
}
- return modify_irte_ga(irte_info->devid, irte_info->index, irte, ir_data);
+ return ret;
}
diff --git a/drivers/iommu/amd_iommu.h b/drivers/iommu/amd_iommu.h
new file mode 100644
index 000000000000..12d540d9b59b
--- /dev/null
+++ b/drivers/iommu/amd_iommu.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_IOMMU_H
+#define AMD_IOMMU_H
+
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line);
+
+#ifdef CONFIG_DMI
+void amd_iommu_apply_ivrs_quirks(void);
+#else
+static void amd_iommu_apply_ivrs_quirks(void) { }
+#endif
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index eb104c719629..568c52317757 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -23,6 +23,8 @@
#include <linux/mem_encrypt.h>
#include <asm/pci-direct.h>
#include <asm/iommu.h>
+#include <asm/apic.h>
+#include <asm/msidef.h>
#include <asm/gart.h>
#include <asm/x86_init.h>
#include <asm/iommu_table.h>
@@ -30,6 +32,7 @@
#include <asm/irq_remapping.h>
#include <linux/crash_dump.h>
+#include "amd_iommu.h"
#include "amd_iommu_proto.h"
#include "amd_iommu_types.h"
#include "irq_remapping.h"
@@ -1000,7 +1003,7 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
set_iommu_for_device(iommu, devid);
}
-static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
{
struct devid_map *entry;
struct list_head *list;
@@ -1151,6 +1154,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
if (ret)
return ret;
+ amd_iommu_apply_ivrs_quirks();
+
/*
* First save the recommended feature enable bits from ACPI
*/
@@ -1920,6 +1925,90 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
return 0;
}
+#define XT_INT_DEST_MODE(x) (((x) & 0x1ULL) << 2)
+#define XT_INT_DEST_LO(x) (((x) & 0xFFFFFFULL) << 8)
+#define XT_INT_VEC(x) (((x) & 0xFFULL) << 32)
+#define XT_INT_DEST_HI(x) ((((x) >> 24) & 0xFFULL) << 56)
+
+/**
+ * Setup the IntCapXT registers with interrupt routing information
+ * based on the PCI MSI capability block registers, accessed via
+ * MMIO MSI address low/hi and MSI data registers.
+ */
+static void iommu_update_intcapxt(struct amd_iommu *iommu)
+{
+ u64 val;
+ u32 addr_lo = readl(iommu->mmio_base + MMIO_MSI_ADDR_LO_OFFSET);
+ u32 addr_hi = readl(iommu->mmio_base + MMIO_MSI_ADDR_HI_OFFSET);
+ u32 data = readl(iommu->mmio_base + MMIO_MSI_DATA_OFFSET);
+ bool dm = (addr_lo >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
+ u32 dest = ((addr_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xFF);
+
+ if (x2apic_enabled())
+ dest |= MSI_ADDR_EXT_DEST_ID(addr_hi);
+
+ val = XT_INT_VEC(data & 0xFF) |
+ XT_INT_DEST_MODE(dm) |
+ XT_INT_DEST_LO(dest) |
+ XT_INT_DEST_HI(dest);
+
+ /**
+ * Current IOMMU implemtation uses the same IRQ for all
+ * 3 IOMMU interrupts.
+ */
+ writeq(val, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
+ writeq(val, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET);
+ writeq(val, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);
+}
+
+static void _irq_notifier_notify(struct irq_affinity_notify *notify,
+ const cpumask_t *mask)
+{
+ struct amd_iommu *iommu;
+
+ for_each_iommu(iommu) {
+ if (iommu->dev->irq == notify->irq) {
+ iommu_update_intcapxt(iommu);
+ break;
+ }
+ }
+}
+
+static void _irq_notifier_release(struct kref *ref)
+{
+}
+
+static int iommu_init_intcapxt(struct amd_iommu *iommu)
+{
+ int ret;
+ struct irq_affinity_notify *notify = &iommu->intcapxt_notify;
+
+ /**
+ * IntCapXT requires XTSup=1, which can be inferred
+ * amd_iommu_xt_mode.
+ */
+ if (amd_iommu_xt_mode != IRQ_REMAP_X2APIC_MODE)
+ return 0;
+
+ /**
+ * Also, we need to setup notifier to update the IntCapXT registers
+ * whenever the irq affinity is changed from user-space.
+ */
+ notify->irq = iommu->dev->irq;
+ notify->notify = _irq_notifier_notify,
+ notify->release = _irq_notifier_release,
+ ret = irq_set_affinity_notifier(iommu->dev->irq, notify);
+ if (ret) {
+ pr_err("Failed to register irq affinity notifier (devid=%#x, irq %d)\n",
+ iommu->devid, iommu->dev->irq);
+ return ret;
+ }
+
+ iommu_update_intcapxt(iommu);
+ iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN);
+ return ret;
+}
+
static int iommu_init_msi(struct amd_iommu *iommu)
{
int ret;
@@ -1936,6 +2025,10 @@ static int iommu_init_msi(struct amd_iommu *iommu)
return ret;
enable_faults:
+ ret = iommu_init_intcapxt(iommu);
+ if (ret)
+ return ret;
+
iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
if (iommu->ppr_log != NULL)
diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c
new file mode 100644
index 000000000000..c235f79b7a20
--- /dev/null
+++ b/drivers/iommu/amd_iommu_quirks.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Quirks for AMD IOMMU
+ *
+ * Copyright (C) 2019 Kai-Heng Feng <kai.heng.feng@canonical.com>
+ */
+
+#ifdef CONFIG_DMI
+#include <linux/dmi.h>
+
+#include "amd_iommu.h"
+
+#define IVHD_SPECIAL_IOAPIC 1
+
+struct ivrs_quirk_entry {
+ u8 id;
+ u16 devid;
+};
+
+enum {
+ DELL_INSPIRON_7375 = 0,
+ DELL_LATITUDE_5495,
+ LENOVO_IDEAPAD_330S_15ARR,
+};
+
+static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = {
+ /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */
+ [DELL_INSPIRON_7375] = {
+ { .id = 4, .devid = 0xa0 },
+ { .id = 5, .devid = 0x2 },
+ {}
+ },
+ /* ivrs_ioapic[4]=00:14.0 */
+ [DELL_LATITUDE_5495] = {
+ { .id = 4, .devid = 0xa0 },
+ {}
+ },
+ /* ivrs_ioapic[32]=00:14.0 */
+ [LENOVO_IDEAPAD_330S_15ARR] = {
+ { .id = 32, .devid = 0xa0 },
+ {}
+ },
+ {}
+};
+
+static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d)
+{
+ const struct ivrs_quirk_entry *i;
+
+ for (i = d->driver_data; i->id != 0 && i->devid != 0; i++)
+ add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 *)&i->devid, 0);
+
+ return 0;
+}
+
+static const struct dmi_system_id ivrs_quirks[] __initconst = {
+ {
+ .callback = ivrs_ioapic_quirk_cb,
+ .ident = "Dell Inspiron 7375",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"),
+ },
+ .driver_data = (void *)&ivrs_ioapic_quirks[DELL_INSPIRON_7375],
+ },
+ {
+ .callback = ivrs_ioapic_quirk_cb,
+ .ident = "Dell Latitude 5495",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 5495"),
+ },
+ .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495],
+ },
+ {
+ .callback = ivrs_ioapic_quirk_cb,
+ .ident = "Lenovo ideapad 330S-15ARR",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "81FB"),
+ },
+ .driver_data = (void *)&ivrs_ioapic_quirks[LENOVO_IDEAPAD_330S_15ARR],
+ },
+ {}
+};
+
+void __init amd_iommu_apply_ivrs_quirks(void)
+{
+ dmi_check_system(ivrs_quirks);
+}
+#endif
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 52c35d557fad..9ac229e92b07 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -60,6 +60,12 @@
#define MMIO_PPR_LOG_OFFSET 0x0038
#define MMIO_GA_LOG_BASE_OFFSET 0x00e0
#define MMIO_GA_LOG_TAIL_OFFSET 0x00e8
+#define MMIO_MSI_ADDR_LO_OFFSET 0x015C
+#define MMIO_MSI_ADDR_HI_OFFSET 0x0160
+#define MMIO_MSI_DATA_OFFSET 0x0164
+#define MMIO_INTCAPXT_EVT_OFFSET 0x0170
+#define MMIO_INTCAPXT_PPR_OFFSET 0x0178
+#define MMIO_INTCAPXT_GALOG_OFFSET 0x0180
#define MMIO_CMD_HEAD_OFFSET 0x2000
#define MMIO_CMD_TAIL_OFFSET 0x2008
#define MMIO_EVT_HEAD_OFFSET 0x2010
@@ -150,6 +156,7 @@
#define CONTROL_GALOG_EN 0x1CULL
#define CONTROL_GAINT_EN 0x1DULL
#define CONTROL_XT_EN 0x32ULL
+#define CONTROL_INTCAPXT_EN 0x33ULL
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
#define CTRL_INV_TO_NONE 0
@@ -592,6 +599,8 @@ struct amd_iommu {
/* DebugFS Info */
struct dentry *debugfs;
#endif
+ /* IRQ notifier for IntCapXT interrupt */
+ struct irq_affinity_notify intcapxt_notify;
};
static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)
@@ -864,6 +873,15 @@ struct amd_ir_data {
struct msi_msg msi_entry;
void *entry; /* Pointer to union irte or struct irte_ga */
void *ref; /* Pointer to the actual irte */
+
+ /**
+ * Store information for activate/de-activate
+ * Guest virtual APIC mode during runtime.
+ */
+ struct irq_cfg *cfg;
+ int ga_vector;
+ int ga_root_ptr;
+ int ga_tag;
};
struct amd_irte_ops {
diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c
new file mode 100644
index 000000000000..5c87a38620c4
--- /dev/null
+++ b/drivers/iommu/arm-smmu-impl.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Miscellaneous Arm SMMU implementation and integration quirks
+// Copyright (C) 2019 Arm Limited
+
+#define pr_fmt(fmt) "arm-smmu: " fmt
+
+#include <linux/bitfield.h>
+#include <linux/of.h>
+
+#include "arm-smmu.h"
+
+
+static int arm_smmu_gr0_ns(int offset)
+{
+ switch(offset) {
+ case ARM_SMMU_GR0_sCR0:
+ case ARM_SMMU_GR0_sACR:
+ case ARM_SMMU_GR0_sGFSR:
+ case ARM_SMMU_GR0_sGFSYNR0:
+ case ARM_SMMU_GR0_sGFSYNR1:
+ case ARM_SMMU_GR0_sGFSYNR2:
+ return offset + 0x400;
+ default:
+ return offset;
+ }
+}
+
+static u32 arm_smmu_read_ns(struct arm_smmu_device *smmu, int page,
+ int offset)
+{
+ if (page == ARM_SMMU_GR0)
+ offset = arm_smmu_gr0_ns(offset);
+ return readl_relaxed(arm_smmu_page(smmu, page) + offset);
+}
+
+static void arm_smmu_write_ns(struct arm_smmu_device *smmu, int page,
+ int offset, u32 val)
+{
+ if (page == ARM_SMMU_GR0)
+ offset = arm_smmu_gr0_ns(offset);
+ writel_relaxed(val, arm_smmu_page(smmu, page) + offset);
+}
+
+/* Since we don't care for sGFAR, we can do without 64-bit accessors */
+static const struct arm_smmu_impl calxeda_impl = {
+ .read_reg = arm_smmu_read_ns,
+ .write_reg = arm_smmu_write_ns,
+};
+
+
+struct cavium_smmu {
+ struct arm_smmu_device smmu;
+ u32 id_base;
+};
+
+static int cavium_cfg_probe(struct arm_smmu_device *smmu)
+{
+ static atomic_t context_count = ATOMIC_INIT(0);
+ struct cavium_smmu *cs = container_of(smmu, struct cavium_smmu, smmu);
+ /*
+ * Cavium CN88xx erratum #27704.
+ * Ensure ASID and VMID allocation is unique across all SMMUs in
+ * the system.
+ */
+ cs->id_base = atomic_fetch_add(smmu->num_context_banks, &context_count);
+ dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
+
+ return 0;
+}
+
+static int cavium_init_context(struct arm_smmu_domain *smmu_domain)
+{
+ struct cavium_smmu *cs = container_of(smmu_domain->smmu,
+ struct cavium_smmu, smmu);
+
+ if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2)
+ smmu_domain->cfg.vmid += cs->id_base;
+ else
+ smmu_domain->cfg.asid += cs->id_base;
+
+ return 0;
+}
+
+static const struct arm_smmu_impl cavium_impl = {
+ .cfg_probe = cavium_cfg_probe,
+ .init_context = cavium_init_context,
+};
+
+static struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smmu)
+{
+ struct cavium_smmu *cs;
+
+ cs = devm_kzalloc(smmu->dev, sizeof(*cs), GFP_KERNEL);
+ if (!cs)
+ return ERR_PTR(-ENOMEM);
+
+ cs->smmu = *smmu;
+ cs->smmu.impl = &cavium_impl;
+
+ devm_kfree(smmu->dev, smmu);
+
+ return &cs->smmu;
+}
+
+
+#define ARM_MMU500_ACTLR_CPRE (1 << 1)
+
+#define ARM_MMU500_ACR_CACHE_LOCK (1 << 26)
+#define ARM_MMU500_ACR_S2CRB_TLBEN (1 << 10)
+#define ARM_MMU500_ACR_SMTNMB_TLBEN (1 << 8)
+
+static int arm_mmu500_reset(struct arm_smmu_device *smmu)
+{
+ u32 reg, major;
+ int i;
+ /*
+ * On MMU-500 r2p0 onwards we need to clear ACR.CACHE_LOCK before
+ * writes to the context bank ACTLRs will stick. And we just hope that
+ * Secure has also cleared SACR.CACHE_LOCK for this to take effect...
+ */
+ reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID7);
+ major = FIELD_GET(ID7_MAJOR, reg);
+ reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sACR);
+ if (major >= 2)
+ reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
+ /*
+ * Allow unmatched Stream IDs to allocate bypass
+ * TLB entries for reduced latency.
+ */
+ reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN;
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sACR, reg);
+
+ /*
+ * Disable MMU-500's not-particularly-beneficial next-page
+ * prefetcher for the sake of errata #841119 and #826419.
+ */
+ for (i = 0; i < smmu->num_context_banks; ++i) {
+ reg = arm_smmu_cb_read(smmu, i, ARM_SMMU_CB_ACTLR);
+ reg &= ~ARM_MMU500_ACTLR_CPRE;
+ arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_ACTLR, reg);
+ }
+
+ return 0;
+}
+
+static const struct arm_smmu_impl arm_mmu500_impl = {
+ .reset = arm_mmu500_reset,
+};
+
+
+struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
+{
+ /*
+ * We will inevitably have to combine model-specific implementation
+ * quirks with platform-specific integration quirks, but everything
+ * we currently support happens to work out as straightforward
+ * mutually-exclusive assignments.
+ */
+ switch (smmu->model) {
+ case ARM_MMU500:
+ smmu->impl = &arm_mmu500_impl;
+ break;
+ case CAVIUM_SMMUV2:
+ return cavium_smmu_impl_init(smmu);
+ default:
+ break;
+ }
+
+ if (of_property_read_bool(smmu->dev->of_node,
+ "calxeda,smmu-secure-config-access"))
+ smmu->impl = &calxeda_impl;
+
+ return smmu;
+}
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
deleted file mode 100644
index 1c278f7ae888..000000000000
--- a/drivers/iommu/arm-smmu-regs.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * IOMMU API for ARM architected SMMU implementations.
- *
- * Copyright (C) 2013 ARM Limited
- *
- * Author: Will Deacon <will.deacon@arm.com>
- */
-
-#ifndef _ARM_SMMU_REGS_H
-#define _ARM_SMMU_REGS_H
-
-/* Configuration registers */
-#define ARM_SMMU_GR0_sCR0 0x0
-#define sCR0_CLIENTPD (1 << 0)
-#define sCR0_GFRE (1 << 1)
-#define sCR0_GFIE (1 << 2)
-#define sCR0_EXIDENABLE (1 << 3)
-#define sCR0_GCFGFRE (1 << 4)
-#define sCR0_GCFGFIE (1 << 5)
-#define sCR0_USFCFG (1 << 10)
-#define sCR0_VMIDPNE (1 << 11)
-#define sCR0_PTM (1 << 12)
-#define sCR0_FB (1 << 13)
-#define sCR0_VMID16EN (1 << 31)
-#define sCR0_BSU_SHIFT 14
-#define sCR0_BSU_MASK 0x3
-
-/* Auxiliary Configuration register */
-#define ARM_SMMU_GR0_sACR 0x10
-
-/* Identification registers */
-#define ARM_SMMU_GR0_ID0 0x20
-#define ARM_SMMU_GR0_ID1 0x24
-#define ARM_SMMU_GR0_ID2 0x28
-#define ARM_SMMU_GR0_ID3 0x2c
-#define ARM_SMMU_GR0_ID4 0x30
-#define ARM_SMMU_GR0_ID5 0x34
-#define ARM_SMMU_GR0_ID6 0x38
-#define ARM_SMMU_GR0_ID7 0x3c
-#define ARM_SMMU_GR0_sGFSR 0x48
-#define ARM_SMMU_GR0_sGFSYNR0 0x50
-#define ARM_SMMU_GR0_sGFSYNR1 0x54
-#define ARM_SMMU_GR0_sGFSYNR2 0x58
-
-#define ID0_S1TS (1 << 30)
-#define ID0_S2TS (1 << 29)
-#define ID0_NTS (1 << 28)
-#define ID0_SMS (1 << 27)
-#define ID0_ATOSNS (1 << 26)
-#define ID0_PTFS_NO_AARCH32 (1 << 25)
-#define ID0_PTFS_NO_AARCH32S (1 << 24)
-#define ID0_CTTW (1 << 14)
-#define ID0_NUMIRPT_SHIFT 16
-#define ID0_NUMIRPT_MASK 0xff
-#define ID0_NUMSIDB_SHIFT 9
-#define ID0_NUMSIDB_MASK 0xf
-#define ID0_EXIDS (1 << 8)
-#define ID0_NUMSMRG_SHIFT 0
-#define ID0_NUMSMRG_MASK 0xff
-
-#define ID1_PAGESIZE (1 << 31)
-#define ID1_NUMPAGENDXB_SHIFT 28
-#define ID1_NUMPAGENDXB_MASK 7
-#define ID1_NUMS2CB_SHIFT 16
-#define ID1_NUMS2CB_MASK 0xff
-#define ID1_NUMCB_SHIFT 0
-#define ID1_NUMCB_MASK 0xff
-
-#define ID2_OAS_SHIFT 4
-#define ID2_OAS_MASK 0xf
-#define ID2_IAS_SHIFT 0
-#define ID2_IAS_MASK 0xf
-#define ID2_UBS_SHIFT 8
-#define ID2_UBS_MASK 0xf
-#define ID2_PTFS_4K (1 << 12)
-#define ID2_PTFS_16K (1 << 13)
-#define ID2_PTFS_64K (1 << 14)
-#define ID2_VMID16 (1 << 15)
-
-#define ID7_MAJOR_SHIFT 4
-#define ID7_MAJOR_MASK 0xf
-
-/* Global TLB invalidation */
-#define ARM_SMMU_GR0_TLBIVMID 0x64
-#define ARM_SMMU_GR0_TLBIALLNSNH 0x68
-#define ARM_SMMU_GR0_TLBIALLH 0x6c
-#define ARM_SMMU_GR0_sTLBGSYNC 0x70
-#define ARM_SMMU_GR0_sTLBGSTATUS 0x74
-#define sTLBGSTATUS_GSACTIVE (1 << 0)
-
-/* Stream mapping registers */
-#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
-#define SMR_VALID (1 << 31)
-#define SMR_MASK_SHIFT 16
-#define SMR_ID_SHIFT 0
-
-#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
-#define S2CR_CBNDX_SHIFT 0
-#define S2CR_CBNDX_MASK 0xff
-#define S2CR_EXIDVALID (1 << 10)
-#define S2CR_TYPE_SHIFT 16
-#define S2CR_TYPE_MASK 0x3
-enum arm_smmu_s2cr_type {
- S2CR_TYPE_TRANS,
- S2CR_TYPE_BYPASS,
- S2CR_TYPE_FAULT,
-};
-
-#define S2CR_PRIVCFG_SHIFT 24
-#define S2CR_PRIVCFG_MASK 0x3
-enum arm_smmu_s2cr_privcfg {
- S2CR_PRIVCFG_DEFAULT,
- S2CR_PRIVCFG_DIPAN,
- S2CR_PRIVCFG_UNPRIV,
- S2CR_PRIVCFG_PRIV,
-};
-
-/* Context bank attribute registers */
-#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
-#define CBAR_VMID_SHIFT 0
-#define CBAR_VMID_MASK 0xff
-#define CBAR_S1_BPSHCFG_SHIFT 8
-#define CBAR_S1_BPSHCFG_MASK 3
-#define CBAR_S1_BPSHCFG_NSH 3
-#define CBAR_S1_MEMATTR_SHIFT 12
-#define CBAR_S1_MEMATTR_MASK 0xf
-#define CBAR_S1_MEMATTR_WB 0xf
-#define CBAR_TYPE_SHIFT 16
-#define CBAR_TYPE_MASK 0x3
-#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT)
-#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT)
-#define CBAR_IRPTNDX_SHIFT 24
-#define CBAR_IRPTNDX_MASK 0xff
-
-#define ARM_SMMU_GR1_CBFRSYNRA(n) (0x400 + ((n) << 2))
-
-#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
-#define CBA2R_RW64_32BIT (0 << 0)
-#define CBA2R_RW64_64BIT (1 << 0)
-#define CBA2R_VMID_SHIFT 16
-#define CBA2R_VMID_MASK 0xffff
-
-#define ARM_SMMU_CB_SCTLR 0x0
-#define ARM_SMMU_CB_ACTLR 0x4
-#define ARM_SMMU_CB_RESUME 0x8
-#define ARM_SMMU_CB_TTBCR2 0x10
-#define ARM_SMMU_CB_TTBR0 0x20
-#define ARM_SMMU_CB_TTBR1 0x28
-#define ARM_SMMU_CB_TTBCR 0x30
-#define ARM_SMMU_CB_CONTEXTIDR 0x34
-#define ARM_SMMU_CB_S1_MAIR0 0x38
-#define ARM_SMMU_CB_S1_MAIR1 0x3c
-#define ARM_SMMU_CB_PAR 0x50
-#define ARM_SMMU_CB_FSR 0x58
-#define ARM_SMMU_CB_FAR 0x60
-#define ARM_SMMU_CB_FSYNR0 0x68
-#define ARM_SMMU_CB_S1_TLBIVA 0x600
-#define ARM_SMMU_CB_S1_TLBIASID 0x610
-#define ARM_SMMU_CB_S1_TLBIVAL 0x620
-#define ARM_SMMU_CB_S2_TLBIIPAS2 0x630
-#define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638
-#define ARM_SMMU_CB_TLBSYNC 0x7f0
-#define ARM_SMMU_CB_TLBSTATUS 0x7f4
-#define ARM_SMMU_CB_ATS1PR 0x800
-#define ARM_SMMU_CB_ATSR 0x8f0
-
-#define SCTLR_S1_ASIDPNE (1 << 12)
-#define SCTLR_CFCFG (1 << 7)
-#define SCTLR_CFIE (1 << 6)
-#define SCTLR_CFRE (1 << 5)
-#define SCTLR_E (1 << 4)
-#define SCTLR_AFE (1 << 2)
-#define SCTLR_TRE (1 << 1)
-#define SCTLR_M (1 << 0)
-
-#define CB_PAR_F (1 << 0)
-
-#define ATSR_ACTIVE (1 << 0)
-
-#define RESUME_RETRY (0 << 0)
-#define RESUME_TERMINATE (1 << 0)
-
-#define TTBCR2_SEP_SHIFT 15
-#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
-#define TTBCR2_AS (1 << 4)
-
-#define TTBRn_ASID_SHIFT 48
-
-#define FSR_MULTI (1 << 31)
-#define FSR_SS (1 << 30)
-#define FSR_UUT (1 << 8)
-#define FSR_ASF (1 << 7)
-#define FSR_TLBLKF (1 << 6)
-#define FSR_TLBMCF (1 << 5)
-#define FSR_EF (1 << 4)
-#define FSR_PF (1 << 3)
-#define FSR_AFF (1 << 2)
-#define FSR_TF (1 << 1)
-
-#define FSR_IGN (FSR_AFF | FSR_ASF | \
- FSR_TLBMCF | FSR_TLBLKF)
-#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
- FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
-
-#define FSYNR0_WNR (1 << 4)
-
-#endif /* _ARM_SMMU_REGS_H */
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index a9a9fabd3968..4aa414843557 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -181,12 +181,13 @@
#define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1
#define ARM_SMMU_MEMATTR_OIWB 0xf
-#define Q_IDX(q, p) ((p) & ((1 << (q)->max_n_shift) - 1))
-#define Q_WRP(q, p) ((p) & (1 << (q)->max_n_shift))
-#define Q_OVERFLOW_FLAG (1 << 31)
-#define Q_OVF(q, p) ((p) & Q_OVERFLOW_FLAG)
+#define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1))
+#define Q_WRP(llq, p) ((p) & (1 << (llq)->max_n_shift))
+#define Q_OVERFLOW_FLAG (1U << 31)
+#define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG)
#define Q_ENT(q, p) ((q)->base + \
- Q_IDX(q, p) * (q)->ent_dwords)
+ Q_IDX(&((q)->llq), p) * \
+ (q)->ent_dwords)
#define Q_BASE_RWA (1UL << 62)
#define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5)
@@ -306,6 +307,15 @@
#define CMDQ_ERR_CERROR_ABT_IDX 2
#define CMDQ_ERR_CERROR_ATC_INV_IDX 3
+#define CMDQ_PROD_OWNED_FLAG Q_OVERFLOW_FLAG
+
+/*
+ * This is used to size the command queue and therefore must be at least
+ * BITS_PER_LONG so that the valid_map works correctly (it relies on the
+ * total number of queue entries being a multiple of BITS_PER_LONG).
+ */
+#define CMDQ_BATCH_ENTRIES BITS_PER_LONG
+
#define CMDQ_0_OP GENMASK_ULL(7, 0)
#define CMDQ_0_SSV (1UL << 11)
@@ -368,9 +378,8 @@
#define PRIQ_1_ADDR_MASK GENMASK_ULL(63, 12)
/* High-level queue structures */
-#define ARM_SMMU_POLL_TIMEOUT_US 100
-#define ARM_SMMU_CMDQ_SYNC_TIMEOUT_US 1000000 /* 1s! */
-#define ARM_SMMU_CMDQ_SYNC_SPIN_COUNT 10
+#define ARM_SMMU_POLL_TIMEOUT_US 1000000 /* 1s! */
+#define ARM_SMMU_POLL_SPIN_COUNT 10
#define MSI_IOVA_BASE 0x8000000
#define MSI_IOVA_LENGTH 0x100000
@@ -472,13 +481,29 @@ struct arm_smmu_cmdq_ent {
#define CMDQ_OP_CMD_SYNC 0x46
struct {
- u32 msidata;
u64 msiaddr;
} sync;
};
};
+struct arm_smmu_ll_queue {
+ union {
+ u64 val;
+ struct {
+ u32 prod;
+ u32 cons;
+ };
+ struct {
+ atomic_t prod;
+ atomic_t cons;
+ } atomic;
+ u8 __pad[SMP_CACHE_BYTES];
+ } ____cacheline_aligned_in_smp;
+ u32 max_n_shift;
+};
+
struct arm_smmu_queue {
+ struct arm_smmu_ll_queue llq;
int irq; /* Wired interrupt */
__le64 *base;
@@ -486,17 +511,23 @@ struct arm_smmu_queue {
u64 q_base;
size_t ent_dwords;
- u32 max_n_shift;
- u32 prod;
- u32 cons;
u32 __iomem *prod_reg;
u32 __iomem *cons_reg;
};
+struct arm_smmu_queue_poll {
+ ktime_t timeout;
+ unsigned int delay;
+ unsigned int spin_cnt;
+ bool wfe;
+};
+
struct arm_smmu_cmdq {
struct arm_smmu_queue q;
- spinlock_t lock;
+ atomic_long_t *valid_map;
+ atomic_t owner_prod;
+ atomic_t lock;
};
struct arm_smmu_evtq {
@@ -576,8 +607,6 @@ struct arm_smmu_device {
int gerr_irq;
int combined_irq;
- u32 sync_nr;
- u8 prev_cmd_opcode;
unsigned long ias; /* IPA */
unsigned long oas; /* PA */
@@ -596,12 +625,6 @@ struct arm_smmu_device {
struct arm_smmu_strtab_cfg strtab_cfg;
- /* Hi16xx adds an extra 32 bits of goodness to its MSI payload */
- union {
- u32 sync_count;
- u64 padding;
- };
-
/* IOMMU core code handle */
struct iommu_device iommu;
};
@@ -614,7 +637,7 @@ struct arm_smmu_master {
struct list_head domain_head;
u32 *sids;
unsigned int num_sids;
- bool ats_enabled :1;
+ bool ats_enabled;
};
/* SMMU private data for an IOMMU domain */
@@ -631,6 +654,7 @@ struct arm_smmu_domain {
struct io_pgtable_ops *pgtbl_ops;
bool non_strict;
+ atomic_t nr_ats_masters;
enum arm_smmu_domain_stage stage;
union {
@@ -685,85 +709,97 @@ static void parse_driver_options(struct arm_smmu_device *smmu)
}
/* Low-level queue manipulation functions */
-static bool queue_full(struct arm_smmu_queue *q)
+static bool queue_has_space(struct arm_smmu_ll_queue *q, u32 n)
+{
+ u32 space, prod, cons;
+
+ prod = Q_IDX(q, q->prod);
+ cons = Q_IDX(q, q->cons);
+
+ if (Q_WRP(q, q->prod) == Q_WRP(q, q->cons))
+ space = (1 << q->max_n_shift) - (prod - cons);
+ else
+ space = cons - prod;
+
+ return space >= n;
+}
+
+static bool queue_full(struct arm_smmu_ll_queue *q)
{
return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) &&
Q_WRP(q, q->prod) != Q_WRP(q, q->cons);
}
-static bool queue_empty(struct arm_smmu_queue *q)
+static bool queue_empty(struct arm_smmu_ll_queue *q)
{
return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) &&
Q_WRP(q, q->prod) == Q_WRP(q, q->cons);
}
-static void queue_sync_cons(struct arm_smmu_queue *q)
+static bool queue_consumed(struct arm_smmu_ll_queue *q, u32 prod)
{
- q->cons = readl_relaxed(q->cons_reg);
+ return ((Q_WRP(q, q->cons) == Q_WRP(q, prod)) &&
+ (Q_IDX(q, q->cons) > Q_IDX(q, prod))) ||
+ ((Q_WRP(q, q->cons) != Q_WRP(q, prod)) &&
+ (Q_IDX(q, q->cons) <= Q_IDX(q, prod)));
}
-static void queue_inc_cons(struct arm_smmu_queue *q)
+static void queue_sync_cons_out(struct arm_smmu_queue *q)
{
- u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
-
- q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-
/*
* Ensure that all CPU accesses (reads and writes) to the queue
* are complete before we update the cons pointer.
*/
mb();
- writel_relaxed(q->cons, q->cons_reg);
+ writel_relaxed(q->llq.cons, q->cons_reg);
+}
+
+static void queue_inc_cons(struct arm_smmu_ll_queue *q)
+{
+ u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
+ q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
}
-static int queue_sync_prod(struct arm_smmu_queue *q)
+static int queue_sync_prod_in(struct arm_smmu_queue *q)
{
int ret = 0;
u32 prod = readl_relaxed(q->prod_reg);
- if (Q_OVF(q, prod) != Q_OVF(q, q->prod))
+ if (Q_OVF(prod) != Q_OVF(q->llq.prod))
ret = -EOVERFLOW;
- q->prod = prod;
+ q->llq.prod = prod;
return ret;
}
-static void queue_inc_prod(struct arm_smmu_queue *q)
+static u32 queue_inc_prod_n(struct arm_smmu_ll_queue *q, int n)
{
- u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1;
-
- q->prod = Q_OVF(q, q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod);
- writel(q->prod, q->prod_reg);
+ u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + n;
+ return Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod);
}
-/*
- * Wait for the SMMU to consume items. If sync is true, wait until the queue
- * is empty. Otherwise, wait until there is at least one free slot.
- */
-static int queue_poll_cons(struct arm_smmu_queue *q, bool sync, bool wfe)
+static void queue_poll_init(struct arm_smmu_device *smmu,
+ struct arm_smmu_queue_poll *qp)
{
- ktime_t timeout;
- unsigned int delay = 1, spin_cnt = 0;
-
- /* Wait longer if it's a CMD_SYNC */
- timeout = ktime_add_us(ktime_get(), sync ?
- ARM_SMMU_CMDQ_SYNC_TIMEOUT_US :
- ARM_SMMU_POLL_TIMEOUT_US);
+ qp->delay = 1;
+ qp->spin_cnt = 0;
+ qp->wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
+ qp->timeout = ktime_add_us(ktime_get(), ARM_SMMU_POLL_TIMEOUT_US);
+}
- while (queue_sync_cons(q), (sync ? !queue_empty(q) : queue_full(q))) {
- if (ktime_compare(ktime_get(), timeout) > 0)
- return -ETIMEDOUT;
+static int queue_poll(struct arm_smmu_queue_poll *qp)
+{
+ if (ktime_compare(ktime_get(), qp->timeout) > 0)
+ return -ETIMEDOUT;
- if (wfe) {
- wfe();
- } else if (++spin_cnt < ARM_SMMU_CMDQ_SYNC_SPIN_COUNT) {
- cpu_relax();
- continue;
- } else {
- udelay(delay);
- delay *= 2;
- spin_cnt = 0;
- }
+ if (qp->wfe) {
+ wfe();
+ } else if (++qp->spin_cnt < ARM_SMMU_POLL_SPIN_COUNT) {
+ cpu_relax();
+ } else {
+ udelay(qp->delay);
+ qp->delay *= 2;
+ qp->spin_cnt = 0;
}
return 0;
@@ -777,16 +813,6 @@ static void queue_write(__le64 *dst, u64 *src, size_t n_dwords)
*dst++ = cpu_to_le64(*src++);
}
-static int queue_insert_raw(struct arm_smmu_queue *q, u64 *ent)
-{
- if (queue_full(q))
- return -ENOSPC;
-
- queue_write(Q_ENT(q, q->prod), ent, q->ent_dwords);
- queue_inc_prod(q);
- return 0;
-}
-
static void queue_read(__le64 *dst, u64 *src, size_t n_dwords)
{
int i;
@@ -797,11 +823,12 @@ static void queue_read(__le64 *dst, u64 *src, size_t n_dwords)
static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent)
{
- if (queue_empty(q))
+ if (queue_empty(&q->llq))
return -EAGAIN;
- queue_read(ent, Q_ENT(q, q->cons), q->ent_dwords);
- queue_inc_cons(q);
+ queue_read(ent, Q_ENT(q, q->llq.cons), q->ent_dwords);
+ queue_inc_cons(&q->llq);
+ queue_sync_cons_out(q);
return 0;
}
@@ -868,20 +895,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp);
break;
case CMDQ_OP_CMD_SYNC:
- if (ent->sync.msiaddr)
+ if (ent->sync.msiaddr) {
cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_IRQ);
- else
+ cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK;
+ } else {
cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV);
+ }
cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH);
cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB);
- /*
- * Commands are written little-endian, but we want the SMMU to
- * receive MSIData, and thus write it back to memory, in CPU
- * byte order, so big-endian needs an extra byteswap here.
- */
- cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIDATA,
- cpu_to_le32(ent->sync.msidata));
- cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK;
break;
default:
return -ENOENT;
@@ -890,6 +911,27 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
return 0;
}
+static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu,
+ u32 prod)
+{
+ struct arm_smmu_queue *q = &smmu->cmdq.q;
+ struct arm_smmu_cmdq_ent ent = {
+ .opcode = CMDQ_OP_CMD_SYNC,
+ };
+
+ /*
+ * Beware that Hi16xx adds an extra 32 bits of goodness to its MSI
+ * payload, so the write will zero the entire command on that platform.
+ */
+ if (smmu->features & ARM_SMMU_FEAT_MSI &&
+ smmu->features & ARM_SMMU_FEAT_COHERENCY) {
+ ent.sync.msiaddr = q->base_dma + Q_IDX(&q->llq, prod) *
+ q->ent_dwords * 8;
+ }
+
+ arm_smmu_cmdq_build_cmd(cmd, &ent);
+}
+
static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
{
static const char *cerror_str[] = {
@@ -948,109 +990,456 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
}
-static void arm_smmu_cmdq_insert_cmd(struct arm_smmu_device *smmu, u64 *cmd)
+/*
+ * Command queue locking.
+ * This is a form of bastardised rwlock with the following major changes:
+ *
+ * - The only LOCK routines are exclusive_trylock() and shared_lock().
+ * Neither have barrier semantics, and instead provide only a control
+ * dependency.
+ *
+ * - The UNLOCK routines are supplemented with shared_tryunlock(), which
+ * fails if the caller appears to be the last lock holder (yes, this is
+ * racy). All successful UNLOCK routines have RELEASE semantics.
+ */
+static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq)
{
- struct arm_smmu_queue *q = &smmu->cmdq.q;
- bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
+ int val;
+
+ /*
+ * We can try to avoid the cmpxchg() loop by simply incrementing the
+ * lock counter. When held in exclusive state, the lock counter is set
+ * to INT_MIN so these increments won't hurt as the value will remain
+ * negative.
+ */
+ if (atomic_fetch_inc_relaxed(&cmdq->lock) >= 0)
+ return;
+
+ do {
+ val = atomic_cond_read_relaxed(&cmdq->lock, VAL >= 0);
+ } while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) != val);
+}
+
+static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq)
+{
+ (void)atomic_dec_return_release(&cmdq->lock);
+}
- smmu->prev_cmd_opcode = FIELD_GET(CMDQ_0_OP, cmd[0]);
+static bool arm_smmu_cmdq_shared_tryunlock(struct arm_smmu_cmdq *cmdq)
+{
+ if (atomic_read(&cmdq->lock) == 1)
+ return false;
- while (queue_insert_raw(q, cmd) == -ENOSPC) {
- if (queue_poll_cons(q, false, wfe))
- dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
+ arm_smmu_cmdq_shared_unlock(cmdq);
+ return true;
+}
+
+#define arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags) \
+({ \
+ bool __ret; \
+ local_irq_save(flags); \
+ __ret = !atomic_cmpxchg_relaxed(&cmdq->lock, 0, INT_MIN); \
+ if (!__ret) \
+ local_irq_restore(flags); \
+ __ret; \
+})
+
+#define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags) \
+({ \
+ atomic_set_release(&cmdq->lock, 0); \
+ local_irq_restore(flags); \
+})
+
+
+/*
+ * Command queue insertion.
+ * This is made fiddly by our attempts to achieve some sort of scalability
+ * since there is one queue shared amongst all of the CPUs in the system. If
+ * you like mixed-size concurrency, dependency ordering and relaxed atomics,
+ * then you'll *love* this monstrosity.
+ *
+ * The basic idea is to split the queue up into ranges of commands that are
+ * owned by a given CPU; the owner may not have written all of the commands
+ * itself, but is responsible for advancing the hardware prod pointer when
+ * the time comes. The algorithm is roughly:
+ *
+ * 1. Allocate some space in the queue. At this point we also discover
+ * whether the head of the queue is currently owned by another CPU,
+ * or whether we are the owner.
+ *
+ * 2. Write our commands into our allocated slots in the queue.
+ *
+ * 3. Mark our slots as valid in arm_smmu_cmdq.valid_map.
+ *
+ * 4. If we are an owner:
+ * a. Wait for the previous owner to finish.
+ * b. Mark the queue head as unowned, which tells us the range
+ * that we are responsible for publishing.
+ * c. Wait for all commands in our owned range to become valid.
+ * d. Advance the hardware prod pointer.
+ * e. Tell the next owner we've finished.
+ *
+ * 5. If we are inserting a CMD_SYNC (we may or may not have been an
+ * owner), then we need to stick around until it has completed:
+ * a. If we have MSIs, the SMMU can write back into the CMD_SYNC
+ * to clear the first 4 bytes.
+ * b. Otherwise, we spin waiting for the hardware cons pointer to
+ * advance past our command.
+ *
+ * The devil is in the details, particularly the use of locking for handling
+ * SYNC completion and freeing up space in the queue before we think that it is
+ * full.
+ */
+static void __arm_smmu_cmdq_poll_set_valid_map(struct arm_smmu_cmdq *cmdq,
+ u32 sprod, u32 eprod, bool set)
+{
+ u32 swidx, sbidx, ewidx, ebidx;
+ struct arm_smmu_ll_queue llq = {
+ .max_n_shift = cmdq->q.llq.max_n_shift,
+ .prod = sprod,
+ };
+
+ ewidx = BIT_WORD(Q_IDX(&llq, eprod));
+ ebidx = Q_IDX(&llq, eprod) % BITS_PER_LONG;
+
+ while (llq.prod != eprod) {
+ unsigned long mask;
+ atomic_long_t *ptr;
+ u32 limit = BITS_PER_LONG;
+
+ swidx = BIT_WORD(Q_IDX(&llq, llq.prod));
+ sbidx = Q_IDX(&llq, llq.prod) % BITS_PER_LONG;
+
+ ptr = &cmdq->valid_map[swidx];
+
+ if ((swidx == ewidx) && (sbidx < ebidx))
+ limit = ebidx;
+
+ mask = GENMASK(limit - 1, sbidx);
+
+ /*
+ * The valid bit is the inverse of the wrap bit. This means
+ * that a zero-initialised queue is invalid and, after marking
+ * all entries as valid, they become invalid again when we
+ * wrap.
+ */
+ if (set) {
+ atomic_long_xor(mask, ptr);
+ } else { /* Poll */
+ unsigned long valid;
+
+ valid = (ULONG_MAX + !!Q_WRP(&llq, llq.prod)) & mask;
+ atomic_long_cond_read_relaxed(ptr, (VAL & mask) == valid);
+ }
+
+ llq.prod = queue_inc_prod_n(&llq, limit - sbidx);
}
}
-static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
- struct arm_smmu_cmdq_ent *ent)
+/* Mark all entries in the range [sprod, eprod) as valid */
+static void arm_smmu_cmdq_set_valid_map(struct arm_smmu_cmdq *cmdq,
+ u32 sprod, u32 eprod)
+{
+ __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, true);
+}
+
+/* Wait for all entries in the range [sprod, eprod) to become valid */
+static void arm_smmu_cmdq_poll_valid_map(struct arm_smmu_cmdq *cmdq,
+ u32 sprod, u32 eprod)
+{
+ __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, false);
+}
+
+/* Wait for the command queue to become non-full */
+static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu,
+ struct arm_smmu_ll_queue *llq)
{
- u64 cmd[CMDQ_ENT_DWORDS];
unsigned long flags;
+ struct arm_smmu_queue_poll qp;
+ struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ int ret = 0;
- if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
- dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
- ent->opcode);
- return;
+ /*
+ * Try to update our copy of cons by grabbing exclusive cmdq access. If
+ * that fails, spin until somebody else updates it for us.
+ */
+ if (arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags)) {
+ WRITE_ONCE(cmdq->q.llq.cons, readl_relaxed(cmdq->q.cons_reg));
+ arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags);
+ llq->val = READ_ONCE(cmdq->q.llq.val);
+ return 0;
}
- spin_lock_irqsave(&smmu->cmdq.lock, flags);
- arm_smmu_cmdq_insert_cmd(smmu, cmd);
- spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
+ queue_poll_init(smmu, &qp);
+ do {
+ llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+ if (!queue_full(llq))
+ break;
+
+ ret = queue_poll(&qp);
+ } while (!ret);
+
+ return ret;
}
/*
- * The difference between val and sync_idx is bounded by the maximum size of
- * a queue at 2^20 entries, so 32 bits is plenty for wrap-safe arithmetic.
+ * Wait until the SMMU signals a CMD_SYNC completion MSI.
+ * Must be called with the cmdq lock held in some capacity.
*/
-static int __arm_smmu_sync_poll_msi(struct arm_smmu_device *smmu, u32 sync_idx)
+static int __arm_smmu_cmdq_poll_until_msi(struct arm_smmu_device *smmu,
+ struct arm_smmu_ll_queue *llq)
{
- ktime_t timeout;
- u32 val;
+ int ret = 0;
+ struct arm_smmu_queue_poll qp;
+ struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ u32 *cmd = (u32 *)(Q_ENT(&cmdq->q, llq->prod));
- timeout = ktime_add_us(ktime_get(), ARM_SMMU_CMDQ_SYNC_TIMEOUT_US);
- val = smp_cond_load_acquire(&smmu->sync_count,
- (int)(VAL - sync_idx) >= 0 ||
- !ktime_before(ktime_get(), timeout));
+ queue_poll_init(smmu, &qp);
- return (int)(val - sync_idx) < 0 ? -ETIMEDOUT : 0;
+ /*
+ * The MSI won't generate an event, since it's being written back
+ * into the command queue.
+ */
+ qp.wfe = false;
+ smp_cond_load_relaxed(cmd, !VAL || (ret = queue_poll(&qp)));
+ llq->cons = ret ? llq->prod : queue_inc_prod_n(llq, 1);
+ return ret;
}
-static int __arm_smmu_cmdq_issue_sync_msi(struct arm_smmu_device *smmu)
+/*
+ * Wait until the SMMU cons index passes llq->prod.
+ * Must be called with the cmdq lock held in some capacity.
+ */
+static int __arm_smmu_cmdq_poll_until_consumed(struct arm_smmu_device *smmu,
+ struct arm_smmu_ll_queue *llq)
{
- u64 cmd[CMDQ_ENT_DWORDS];
- unsigned long flags;
- struct arm_smmu_cmdq_ent ent = {
- .opcode = CMDQ_OP_CMD_SYNC,
- .sync = {
- .msiaddr = virt_to_phys(&smmu->sync_count),
- },
- };
+ struct arm_smmu_queue_poll qp;
+ struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ u32 prod = llq->prod;
+ int ret = 0;
+
+ queue_poll_init(smmu, &qp);
+ llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+ do {
+ if (queue_consumed(llq, prod))
+ break;
- spin_lock_irqsave(&smmu->cmdq.lock, flags);
+ ret = queue_poll(&qp);
- /* Piggy-back on the previous command if it's a SYNC */
- if (smmu->prev_cmd_opcode == CMDQ_OP_CMD_SYNC) {
- ent.sync.msidata = smmu->sync_nr;
- } else {
- ent.sync.msidata = ++smmu->sync_nr;
- arm_smmu_cmdq_build_cmd(cmd, &ent);
- arm_smmu_cmdq_insert_cmd(smmu, cmd);
- }
+ /*
+ * This needs to be a readl() so that our subsequent call
+ * to arm_smmu_cmdq_shared_tryunlock() can fail accurately.
+ *
+ * Specifically, we need to ensure that we observe all
+ * shared_lock()s by other CMD_SYNCs that share our owner,
+ * so that a failing call to tryunlock() means that we're
+ * the last one out and therefore we can safely advance
+ * cmdq->q.llq.cons. Roughly speaking:
+ *
+ * CPU 0 CPU1 CPU2 (us)
+ *
+ * if (sync)
+ * shared_lock();
+ *
+ * dma_wmb();
+ * set_valid_map();
+ *
+ * if (owner) {
+ * poll_valid_map();
+ * <control dependency>
+ * writel(prod_reg);
+ *
+ * readl(cons_reg);
+ * tryunlock();
+ *
+ * Requires us to see CPU 0's shared_lock() acquisition.
+ */
+ llq->cons = readl(cmdq->q.cons_reg);
+ } while (!ret);
- spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
+ return ret;
+}
+
+static int arm_smmu_cmdq_poll_until_sync(struct arm_smmu_device *smmu,
+ struct arm_smmu_ll_queue *llq)
+{
+ if (smmu->features & ARM_SMMU_FEAT_MSI &&
+ smmu->features & ARM_SMMU_FEAT_COHERENCY)
+ return __arm_smmu_cmdq_poll_until_msi(smmu, llq);
- return __arm_smmu_sync_poll_msi(smmu, ent.sync.msidata);
+ return __arm_smmu_cmdq_poll_until_consumed(smmu, llq);
}
-static int __arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds,
+ u32 prod, int n)
{
- u64 cmd[CMDQ_ENT_DWORDS];
+ int i;
+ struct arm_smmu_ll_queue llq = {
+ .max_n_shift = cmdq->q.llq.max_n_shift,
+ .prod = prod,
+ };
+
+ for (i = 0; i < n; ++i) {
+ u64 *cmd = &cmds[i * CMDQ_ENT_DWORDS];
+
+ prod = queue_inc_prod_n(&llq, i);
+ queue_write(Q_ENT(&cmdq->q, prod), cmd, CMDQ_ENT_DWORDS);
+ }
+}
+
+/*
+ * This is the actual insertion function, and provides the following
+ * ordering guarantees to callers:
+ *
+ * - There is a dma_wmb() before publishing any commands to the queue.
+ * This can be relied upon to order prior writes to data structures
+ * in memory (such as a CD or an STE) before the command.
+ *
+ * - On completion of a CMD_SYNC, there is a control dependency.
+ * This can be relied upon to order subsequent writes to memory (e.g.
+ * freeing an IOVA) after completion of the CMD_SYNC.
+ *
+ * - Command insertion is totally ordered, so if two CPUs each race to
+ * insert their own list of commands then all of the commands from one
+ * CPU will appear before any of the commands from the other CPU.
+ */
+static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
+ u64 *cmds, int n, bool sync)
+{
+ u64 cmd_sync[CMDQ_ENT_DWORDS];
+ u32 prod;
unsigned long flags;
- bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
- struct arm_smmu_cmdq_ent ent = { .opcode = CMDQ_OP_CMD_SYNC };
- int ret;
+ bool owner;
+ struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ struct arm_smmu_ll_queue llq = {
+ .max_n_shift = cmdq->q.llq.max_n_shift,
+ }, head = llq;
+ int ret = 0;
- arm_smmu_cmdq_build_cmd(cmd, &ent);
+ /* 1. Allocate some space in the queue */
+ local_irq_save(flags);
+ llq.val = READ_ONCE(cmdq->q.llq.val);
+ do {
+ u64 old;
+
+ while (!queue_has_space(&llq, n + sync)) {
+ local_irq_restore(flags);
+ if (arm_smmu_cmdq_poll_until_not_full(smmu, &llq))
+ dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
+ local_irq_save(flags);
+ }
+
+ head.cons = llq.cons;
+ head.prod = queue_inc_prod_n(&llq, n + sync) |
+ CMDQ_PROD_OWNED_FLAG;
- spin_lock_irqsave(&smmu->cmdq.lock, flags);
- arm_smmu_cmdq_insert_cmd(smmu, cmd);
- ret = queue_poll_cons(&smmu->cmdq.q, true, wfe);
- spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
+ old = cmpxchg_relaxed(&cmdq->q.llq.val, llq.val, head.val);
+ if (old == llq.val)
+ break;
+
+ llq.val = old;
+ } while (1);
+ owner = !(llq.prod & CMDQ_PROD_OWNED_FLAG);
+ head.prod &= ~CMDQ_PROD_OWNED_FLAG;
+ llq.prod &= ~CMDQ_PROD_OWNED_FLAG;
+
+ /*
+ * 2. Write our commands into the queue
+ * Dependency ordering from the cmpxchg() loop above.
+ */
+ arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
+ if (sync) {
+ prod = queue_inc_prod_n(&llq, n);
+ arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+ queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS);
+
+ /*
+ * In order to determine completion of our CMD_SYNC, we must
+ * ensure that the queue can't wrap twice without us noticing.
+ * We achieve that by taking the cmdq lock as shared before
+ * marking our slot as valid.
+ */
+ arm_smmu_cmdq_shared_lock(cmdq);
+ }
+
+ /* 3. Mark our slots as valid, ensuring commands are visible first */
+ dma_wmb();
+ arm_smmu_cmdq_set_valid_map(cmdq, llq.prod, head.prod);
+
+ /* 4. If we are the owner, take control of the SMMU hardware */
+ if (owner) {
+ /* a. Wait for previous owner to finish */
+ atomic_cond_read_relaxed(&cmdq->owner_prod, VAL == llq.prod);
+
+ /* b. Stop gathering work by clearing the owned flag */
+ prod = atomic_fetch_andnot_relaxed(CMDQ_PROD_OWNED_FLAG,
+ &cmdq->q.llq.atomic.prod);
+ prod &= ~CMDQ_PROD_OWNED_FLAG;
+
+ /*
+ * c. Wait for any gathered work to be written to the queue.
+ * Note that we read our own entries so that we have the control
+ * dependency required by (d).
+ */
+ arm_smmu_cmdq_poll_valid_map(cmdq, llq.prod, prod);
+
+ /*
+ * d. Advance the hardware prod pointer
+ * Control dependency ordering from the entries becoming valid.
+ */
+ writel_relaxed(prod, cmdq->q.prod_reg);
+
+ /*
+ * e. Tell the next owner we're done
+ * Make sure we've updated the hardware first, so that we don't
+ * race to update prod and potentially move it backwards.
+ */
+ atomic_set_release(&cmdq->owner_prod, prod);
+ }
+
+ /* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */
+ if (sync) {
+ llq.prod = queue_inc_prod_n(&llq, n);
+ ret = arm_smmu_cmdq_poll_until_sync(smmu, &llq);
+ if (ret) {
+ dev_err_ratelimited(smmu->dev,
+ "CMD_SYNC timeout at 0x%08x [hwprod 0x%08x, hwcons 0x%08x]\n",
+ llq.prod,
+ readl_relaxed(cmdq->q.prod_reg),
+ readl_relaxed(cmdq->q.cons_reg));
+ }
+
+ /*
+ * Try to unlock the cmq lock. This will fail if we're the last
+ * reader, in which case we can safely update cmdq->q.llq.cons
+ */
+ if (!arm_smmu_cmdq_shared_tryunlock(cmdq)) {
+ WRITE_ONCE(cmdq->q.llq.cons, llq.cons);
+ arm_smmu_cmdq_shared_unlock(cmdq);
+ }
+ }
+ local_irq_restore(flags);
return ret;
}
-static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq_ent *ent)
{
- int ret;
- bool msi = (smmu->features & ARM_SMMU_FEAT_MSI) &&
- (smmu->features & ARM_SMMU_FEAT_COHERENCY);
+ u64 cmd[CMDQ_ENT_DWORDS];
- ret = msi ? __arm_smmu_cmdq_issue_sync_msi(smmu)
- : __arm_smmu_cmdq_issue_sync(smmu);
- if (ret)
- dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n");
- return ret;
+ if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
+ dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
+ ent->opcode);
+ return -EINVAL;
+ }
+
+ return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
+}
+
+static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+{
+ return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
}
/* Context descriptor manipulation functions */
@@ -1186,8 +1575,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
ste_live = true;
break;
case STRTAB_STE_0_CFG_ABORT:
- if (disable_bypass)
- break;
+ BUG_ON(!disable_bypass);
+ break;
default:
BUG(); /* STE corruption */
}
@@ -1305,6 +1694,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
int i;
struct arm_smmu_device *smmu = dev;
struct arm_smmu_queue *q = &smmu->evtq.q;
+ struct arm_smmu_ll_queue *llq = &q->llq;
u64 evt[EVTQ_ENT_DWORDS];
do {
@@ -1322,12 +1712,13 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
* Not much we can do on overflow, so scream and pretend we're
* trying harder.
*/
- if (queue_sync_prod(q) == -EOVERFLOW)
+ if (queue_sync_prod_in(q) == -EOVERFLOW)
dev_err(smmu->dev, "EVTQ overflow detected -- events lost\n");
- } while (!queue_empty(q));
+ } while (!queue_empty(llq));
/* Sync our overflow flag, as we believe we're up to speed */
- q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
+ llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
+ Q_IDX(llq, llq->cons);
return IRQ_HANDLED;
}
@@ -1373,19 +1764,21 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
{
struct arm_smmu_device *smmu = dev;
struct arm_smmu_queue *q = &smmu->priq.q;
+ struct arm_smmu_ll_queue *llq = &q->llq;
u64 evt[PRIQ_ENT_DWORDS];
do {
while (!queue_remove_raw(q, evt))
arm_smmu_handle_ppr(smmu, evt);
- if (queue_sync_prod(q) == -EOVERFLOW)
+ if (queue_sync_prod_in(q) == -EOVERFLOW)
dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
- } while (!queue_empty(q));
+ } while (!queue_empty(llq));
/* Sync our overflow flag, as we believe we're up to speed */
- q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
- writel(q->cons, q->cons_reg);
+ llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
+ Q_IDX(llq, llq->cons);
+ queue_sync_cons_out(q);
return IRQ_HANDLED;
}
@@ -1534,6 +1927,23 @@ static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain,
if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
return 0;
+ /*
+ * Ensure that we've completed prior invalidation of the main TLBs
+ * before we read 'nr_ats_masters' in case of a concurrent call to
+ * arm_smmu_enable_ats():
+ *
+ * // unmap() // arm_smmu_enable_ats()
+ * TLBI+SYNC atomic_inc(&nr_ats_masters);
+ * smp_mb(); [...]
+ * atomic_read(&nr_ats_masters); pci_enable_ats() // writel()
+ *
+ * Ensures that we always see the incremented 'nr_ats_masters' count if
+ * ATS was enabled at the PCI device before completion of the TLBI.
+ */
+ smp_mb();
+ if (!atomic_read(&smmu_domain->nr_ats_masters))
+ return 0;
+
arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd);
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
@@ -1545,13 +1955,6 @@ static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain,
}
/* IO_PGTABLE API */
-static void arm_smmu_tlb_sync(void *cookie)
-{
- struct arm_smmu_domain *smmu_domain = cookie;
-
- arm_smmu_cmdq_issue_sync(smmu_domain->smmu);
-}
-
static void arm_smmu_tlb_inv_context(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
@@ -1570,25 +1973,32 @@ static void arm_smmu_tlb_inv_context(void *cookie)
/*
* NOTE: when io-pgtable is in non-strict mode, we may get here with
* PTEs previously cleared by unmaps on the current CPU not yet visible
- * to the SMMU. We are relying on the DSB implicit in queue_inc_prod()
- * to guarantee those are observed before the TLBI. Do be careful, 007.
+ * to the SMMU. We are relying on the dma_wmb() implicit during cmd
+ * insertion to guarantee those are observed before the TLBI. Do be
+ * careful, 007.
*/
arm_smmu_cmdq_issue_cmd(smmu, &cmd);
arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
}
-static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size,
+ size_t granule, bool leaf,
+ struct arm_smmu_domain *smmu_domain)
{
- struct arm_smmu_domain *smmu_domain = cookie;
+ u64 cmds[CMDQ_BATCH_ENTRIES * CMDQ_ENT_DWORDS];
struct arm_smmu_device *smmu = smmu_domain->smmu;
+ unsigned long start = iova, end = iova + size;
+ int i = 0;
struct arm_smmu_cmdq_ent cmd = {
.tlbi = {
.leaf = leaf,
- .addr = iova,
},
};
+ if (!size)
+ return;
+
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
cmd.opcode = CMDQ_OP_TLBI_NH_VA;
cmd.tlbi.asid = smmu_domain->s1_cfg.cd.asid;
@@ -1597,16 +2007,54 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid;
}
- do {
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- cmd.tlbi.addr += granule;
- } while (size -= granule);
+ while (iova < end) {
+ if (i == CMDQ_BATCH_ENTRIES) {
+ arm_smmu_cmdq_issue_cmdlist(smmu, cmds, i, false);
+ i = 0;
+ }
+
+ cmd.tlbi.addr = iova;
+ arm_smmu_cmdq_build_cmd(&cmds[i * CMDQ_ENT_DWORDS], &cmd);
+ iova += granule;
+ i++;
+ }
+
+ arm_smmu_cmdq_issue_cmdlist(smmu, cmds, i, true);
+
+ /*
+ * Unfortunately, this can't be leaf-only since we may have
+ * zapped an entire table.
+ */
+ arm_smmu_atc_inv_domain(smmu_domain, 0, start, size);
+}
+
+static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule,
+ void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ struct iommu_domain *domain = &smmu_domain->domain;
+
+ iommu_iotlb_gather_add_page(domain, gather, iova, granule);
}
-static const struct iommu_gather_ops arm_smmu_gather_ops = {
+static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ arm_smmu_tlb_inv_range(iova, size, granule, false, cookie);
+}
+
+static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ arm_smmu_tlb_inv_range(iova, size, granule, true, cookie);
+}
+
+static const struct iommu_flush_ops arm_smmu_flush_ops = {
.tlb_flush_all = arm_smmu_tlb_inv_context,
- .tlb_add_flush = arm_smmu_tlb_inv_range_nosync,
- .tlb_sync = arm_smmu_tlb_sync,
+ .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+ .tlb_add_page = arm_smmu_tlb_inv_page_nosync,
};
/* IOMMU API */
@@ -1796,7 +2244,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
.ias = ias,
.oas = oas,
.coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY,
- .tlb = &arm_smmu_gather_ops,
+ .tlb = &arm_smmu_flush_ops,
.iommu_dev = smmu->dev,
};
@@ -1863,44 +2311,65 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
}
}
-static int arm_smmu_enable_ats(struct arm_smmu_master *master)
+#ifdef CONFIG_PCI_ATS
+static bool arm_smmu_ats_supported(struct arm_smmu_master *master)
{
- int ret;
- size_t stu;
struct pci_dev *pdev;
struct arm_smmu_device *smmu = master->smmu;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
if (!(smmu->features & ARM_SMMU_FEAT_ATS) || !dev_is_pci(master->dev) ||
!(fwspec->flags & IOMMU_FWSPEC_PCI_RC_ATS) || pci_ats_disabled())
- return -ENXIO;
+ return false;
pdev = to_pci_dev(master->dev);
- if (pdev->untrusted)
- return -EPERM;
+ return !pdev->untrusted && pdev->ats_cap;
+}
+#else
+static bool arm_smmu_ats_supported(struct arm_smmu_master *master)
+{
+ return false;
+}
+#endif
+
+static void arm_smmu_enable_ats(struct arm_smmu_master *master)
+{
+ size_t stu;
+ struct pci_dev *pdev;
+ struct arm_smmu_device *smmu = master->smmu;
+ struct arm_smmu_domain *smmu_domain = master->domain;
+
+ /* Don't enable ATS at the endpoint if it's not enabled in the STE */
+ if (!master->ats_enabled)
+ return;
/* Smallest Translation Unit: log2 of the smallest supported granule */
stu = __ffs(smmu->pgsize_bitmap);
+ pdev = to_pci_dev(master->dev);
- ret = pci_enable_ats(pdev, stu);
- if (ret)
- return ret;
-
- master->ats_enabled = true;
- return 0;
+ atomic_inc(&smmu_domain->nr_ats_masters);
+ arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
+ if (pci_enable_ats(pdev, stu))
+ dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu);
}
static void arm_smmu_disable_ats(struct arm_smmu_master *master)
{
struct arm_smmu_cmdq_ent cmd;
+ struct arm_smmu_domain *smmu_domain = master->domain;
- if (!master->ats_enabled || !dev_is_pci(master->dev))
+ if (!master->ats_enabled)
return;
+ pci_disable_ats(to_pci_dev(master->dev));
+ /*
+ * Ensure ATS is disabled at the endpoint before we issue the
+ * ATC invalidation via the SMMU.
+ */
+ wmb();
arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
arm_smmu_atc_inv_master(master, &cmd);
- pci_disable_ats(to_pci_dev(master->dev));
- master->ats_enabled = false;
+ atomic_dec(&smmu_domain->nr_ats_masters);
}
static void arm_smmu_detach_dev(struct arm_smmu_master *master)
@@ -1911,14 +2380,15 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
if (!smmu_domain)
return;
+ arm_smmu_disable_ats(master);
+
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_del(&master->domain_head);
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
master->domain = NULL;
+ master->ats_enabled = false;
arm_smmu_install_ste_for_dev(master);
-
- arm_smmu_disable_ats(master);
}
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -1958,17 +2428,20 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
master->domain = smmu_domain;
- spin_lock_irqsave(&smmu_domain->devices_lock, flags);
- list_add(&master->domain_head, &smmu_domain->devices);
- spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
-
if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
- arm_smmu_enable_ats(master);
+ master->ats_enabled = arm_smmu_ats_supported(master);
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1)
arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg);
arm_smmu_install_ste_for_dev(master);
+
+ spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+ list_add(&master->domain_head, &smmu_domain->devices);
+ spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+
+ arm_smmu_enable_ats(master);
+
out_unlock:
mutex_unlock(&smmu_domain->init_mutex);
return ret;
@@ -1985,21 +2458,16 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
return ops->map(ops, iova, paddr, size, prot);
}
-static size_t
-arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
+static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
+ size_t size, struct iommu_iotlb_gather *gather)
{
- int ret;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
if (!ops)
return 0;
- ret = ops->unmap(ops, iova, size);
- if (ret && arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size))
- return 0;
-
- return ret;
+ return ops->unmap(ops, iova, size, gather);
}
static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
@@ -2010,12 +2478,13 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
arm_smmu_tlb_inv_context(smmu_domain);
}
-static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
+static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
{
- struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- if (smmu)
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_tlb_inv_range(gather->start, gather->end - gather->start,
+ gather->pgsize, true, smmu_domain);
}
static phys_addr_t
@@ -2286,13 +2755,13 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
size_t qsz;
do {
- qsz = ((1 << q->max_n_shift) * dwords) << 3;
+ qsz = ((1 << q->llq.max_n_shift) * dwords) << 3;
q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma,
GFP_KERNEL);
if (q->base || qsz < PAGE_SIZE)
break;
- q->max_n_shift--;
+ q->llq.max_n_shift--;
} while (1);
if (!q->base) {
@@ -2304,7 +2773,7 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
if (!WARN_ON(q->base_dma & (qsz - 1))) {
dev_info(smmu->dev, "allocated %u entries for %s\n",
- 1 << q->max_n_shift, name);
+ 1 << q->llq.max_n_shift, name);
}
q->prod_reg = arm_smmu_page1_fixup(prod_off, smmu);
@@ -2313,24 +2782,55 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
q->q_base = Q_BASE_RWA;
q->q_base |= q->base_dma & Q_BASE_ADDR_MASK;
- q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->max_n_shift);
+ q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->llq.max_n_shift);
- q->prod = q->cons = 0;
+ q->llq.prod = q->llq.cons = 0;
return 0;
}
+static void arm_smmu_cmdq_free_bitmap(void *data)
+{
+ unsigned long *bitmap = data;
+ bitmap_free(bitmap);
+}
+
+static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu)
+{
+ int ret = 0;
+ struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
+ atomic_long_t *bitmap;
+
+ atomic_set(&cmdq->owner_prod, 0);
+ atomic_set(&cmdq->lock, 0);
+
+ bitmap = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL);
+ if (!bitmap) {
+ dev_err(smmu->dev, "failed to allocate cmdq bitmap\n");
+ ret = -ENOMEM;
+ } else {
+ cmdq->valid_map = bitmap;
+ devm_add_action(smmu->dev, arm_smmu_cmdq_free_bitmap, bitmap);
+ }
+
+ return ret;
+}
+
static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
{
int ret;
/* cmdq */
- spin_lock_init(&smmu->cmdq.lock);
ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD,
ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS,
"cmdq");
if (ret)
return ret;
+ ret = arm_smmu_cmdq_init(smmu);
+ if (ret)
+ return ret;
+
/* evtq */
ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, ARM_SMMU_EVTQ_PROD,
ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS,
@@ -2708,8 +3208,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
/* Command queue */
writeq_relaxed(smmu->cmdq.q.q_base, smmu->base + ARM_SMMU_CMDQ_BASE);
- writel_relaxed(smmu->cmdq.q.prod, smmu->base + ARM_SMMU_CMDQ_PROD);
- writel_relaxed(smmu->cmdq.q.cons, smmu->base + ARM_SMMU_CMDQ_CONS);
+ writel_relaxed(smmu->cmdq.q.llq.prod, smmu->base + ARM_SMMU_CMDQ_PROD);
+ writel_relaxed(smmu->cmdq.q.llq.cons, smmu->base + ARM_SMMU_CMDQ_CONS);
enables = CR0_CMDQEN;
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
@@ -2736,9 +3236,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
/* Event queue */
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
- writel_relaxed(smmu->evtq.q.prod,
+ writel_relaxed(smmu->evtq.q.llq.prod,
arm_smmu_page1_fixup(ARM_SMMU_EVTQ_PROD, smmu));
- writel_relaxed(smmu->evtq.q.cons,
+ writel_relaxed(smmu->evtq.q.llq.cons,
arm_smmu_page1_fixup(ARM_SMMU_EVTQ_CONS, smmu));
enables |= CR0_EVTQEN;
@@ -2753,9 +3253,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
if (smmu->features & ARM_SMMU_FEAT_PRI) {
writeq_relaxed(smmu->priq.q.q_base,
smmu->base + ARM_SMMU_PRIQ_BASE);
- writel_relaxed(smmu->priq.q.prod,
+ writel_relaxed(smmu->priq.q.llq.prod,
arm_smmu_page1_fixup(ARM_SMMU_PRIQ_PROD, smmu));
- writel_relaxed(smmu->priq.q.cons,
+ writel_relaxed(smmu->priq.q.llq.cons,
arm_smmu_page1_fixup(ARM_SMMU_PRIQ_CONS, smmu));
enables |= CR0_PRIQEN;
@@ -2909,18 +3409,24 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
}
/* Queue sizes, capped to ensure natural alignment */
- smmu->cmdq.q.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
- FIELD_GET(IDR1_CMDQS, reg));
- if (!smmu->cmdq.q.max_n_shift) {
- /* Odd alignment restrictions on the base, so ignore for now */
- dev_err(smmu->dev, "unit-length command queue not supported\n");
+ smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_CMDQS, reg));
+ if (smmu->cmdq.q.llq.max_n_shift <= ilog2(CMDQ_BATCH_ENTRIES)) {
+ /*
+ * We don't support splitting up batches, so one batch of
+ * commands plus an extra sync needs to fit inside the command
+ * queue. There's also no way we can handle the weird alignment
+ * restrictions on the base pointer for a unit-length queue.
+ */
+ dev_err(smmu->dev, "command queue size <= %d entries not supported\n",
+ CMDQ_BATCH_ENTRIES);
return -ENXIO;
}
- smmu->evtq.q.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT,
- FIELD_GET(IDR1_EVTQS, reg));
- smmu->priq.q.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT,
- FIELD_GET(IDR1_PRIQS, reg));
+ smmu->evtq.q.llq.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_EVTQS, reg));
+ smmu->priq.q.llq.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_PRIQS, reg));
/* SID/SSID sizes */
smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 64977c131ee6..5b93c79371e9 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -19,16 +19,13 @@
#include <linux/acpi.h>
#include <linux/acpi_iort.h>
-#include <linux/atomic.h>
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/io-64-nonatomic-hi-lo.h>
-#include <linux/io-pgtable.h>
-#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
@@ -40,12 +37,11 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
#include <linux/amba/bus.h>
#include <linux/fsl/mc.h>
-#include "arm-smmu-regs.h"
+#include "arm-smmu.h"
/*
* Apparently, some Qualcomm arm64 platforms which appear to expose their SMMU
@@ -56,46 +52,9 @@
*/
#define QCOM_DUMMY_VAL -1
-#define ARM_MMU500_ACTLR_CPRE (1 << 1)
-
-#define ARM_MMU500_ACR_CACHE_LOCK (1 << 26)
-#define ARM_MMU500_ACR_S2CRB_TLBEN (1 << 10)
-#define ARM_MMU500_ACR_SMTNMB_TLBEN (1 << 8)
-
#define TLB_LOOP_TIMEOUT 1000000 /* 1s! */
#define TLB_SPIN_COUNT 10
-/* Maximum number of context banks per SMMU */
-#define ARM_SMMU_MAX_CBS 128
-
-/* SMMU global address space */
-#define ARM_SMMU_GR0(smmu) ((smmu)->base)
-#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift))
-
-/*
- * SMMU global address space with conditional offset to access secure
- * aliases of non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448,
- * nsGFSYNR0: 0x450)
- */
-#define ARM_SMMU_GR0_NS(smmu) \
- ((smmu)->base + \
- ((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS) \
- ? 0x400 : 0))
-
-/*
- * Some 64-bit registers only make sense to write atomically, but in such
- * cases all the data relevant to AArch32 formats lies within the lower word,
- * therefore this actually makes more sense than it might first appear.
- */
-#ifdef CONFIG_64BIT
-#define smmu_write_atomic_lq writeq_relaxed
-#else
-#define smmu_write_atomic_lq writel_relaxed
-#endif
-
-/* Translation context bank */
-#define ARM_SMMU_CB(smmu, n) ((smmu)->cb_base + ((n) << (smmu)->pgshift))
-
#define MSI_IOVA_BASE 0x8000000
#define MSI_IOVA_LENGTH 0x100000
@@ -113,19 +72,6 @@ module_param(disable_bypass, bool, S_IRUGO);
MODULE_PARM_DESC(disable_bypass,
"Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
-enum arm_smmu_arch_version {
- ARM_SMMU_V1,
- ARM_SMMU_V1_64K,
- ARM_SMMU_V2,
-};
-
-enum arm_smmu_implementation {
- GENERIC_SMMU,
- ARM_MMU500,
- CAVIUM_SMMUV2,
- QCOM_SMMUV2,
-};
-
struct arm_smmu_s2cr {
struct iommu_group *group;
int count;
@@ -163,117 +109,8 @@ struct arm_smmu_master_cfg {
#define for_each_cfg_sme(fw, i, idx) \
for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i)
-struct arm_smmu_device {
- struct device *dev;
-
- void __iomem *base;
- void __iomem *cb_base;
- unsigned long pgshift;
-
-#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
-#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1)
-#define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
-#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
-#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
-#define ARM_SMMU_FEAT_TRANS_OPS (1 << 5)
-#define ARM_SMMU_FEAT_VMID16 (1 << 6)
-#define ARM_SMMU_FEAT_FMT_AARCH64_4K (1 << 7)
-#define ARM_SMMU_FEAT_FMT_AARCH64_16K (1 << 8)
-#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
-#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
-#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
-#define ARM_SMMU_FEAT_EXIDS (1 << 12)
- u32 features;
-
-#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
- u32 options;
- enum arm_smmu_arch_version version;
- enum arm_smmu_implementation model;
-
- u32 num_context_banks;
- u32 num_s2_context_banks;
- DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
- struct arm_smmu_cb *cbs;
- atomic_t irptndx;
-
- u32 num_mapping_groups;
- u16 streamid_mask;
- u16 smr_mask_mask;
- struct arm_smmu_smr *smrs;
- struct arm_smmu_s2cr *s2crs;
- struct mutex stream_map_mutex;
-
- unsigned long va_size;
- unsigned long ipa_size;
- unsigned long pa_size;
- unsigned long pgsize_bitmap;
-
- u32 num_global_irqs;
- u32 num_context_irqs;
- unsigned int *irqs;
- struct clk_bulk_data *clks;
- int num_clks;
-
- u32 cavium_id_base; /* Specific to Cavium */
-
- spinlock_t global_sync_lock;
-
- /* IOMMU core code handle */
- struct iommu_device iommu;
-};
-
-enum arm_smmu_context_fmt {
- ARM_SMMU_CTX_FMT_NONE,
- ARM_SMMU_CTX_FMT_AARCH64,
- ARM_SMMU_CTX_FMT_AARCH32_L,
- ARM_SMMU_CTX_FMT_AARCH32_S,
-};
-
-struct arm_smmu_cfg {
- u8 cbndx;
- u8 irptndx;
- union {
- u16 asid;
- u16 vmid;
- };
- u32 cbar;
- enum arm_smmu_context_fmt fmt;
-};
-#define INVALID_IRPTNDX 0xff
-
-enum arm_smmu_domain_stage {
- ARM_SMMU_DOMAIN_S1 = 0,
- ARM_SMMU_DOMAIN_S2,
- ARM_SMMU_DOMAIN_NESTED,
- ARM_SMMU_DOMAIN_BYPASS,
-};
-
-struct arm_smmu_domain {
- struct arm_smmu_device *smmu;
- struct io_pgtable_ops *pgtbl_ops;
- const struct iommu_gather_ops *tlb_ops;
- struct arm_smmu_cfg cfg;
- enum arm_smmu_domain_stage stage;
- bool non_strict;
- struct mutex init_mutex; /* Protects smmu pointer */
- spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */
- struct iommu_domain domain;
-};
-
-struct arm_smmu_option_prop {
- u32 opt;
- const char *prop;
-};
-
-static atomic_t cavium_smmu_context_count = ATOMIC_INIT(0);
-
static bool using_legacy_binding, using_generic_binding;
-static struct arm_smmu_option_prop arm_smmu_options[] = {
- { ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
- { 0, NULL},
-};
-
static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu)
{
if (pm_runtime_enabled(smmu->dev))
@@ -293,20 +130,6 @@ static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
return container_of(dom, struct arm_smmu_domain, domain);
}
-static void parse_driver_options(struct arm_smmu_device *smmu)
-{
- int i = 0;
-
- do {
- if (of_property_read_bool(smmu->dev->of_node,
- arm_smmu_options[i].prop)) {
- smmu->options |= arm_smmu_options[i].opt;
- dev_notice(smmu->dev, "option %s\n",
- arm_smmu_options[i].prop);
- }
- } while (arm_smmu_options[++i].opt);
-}
-
static struct device_node *dev_get_dev_node(struct device *dev)
{
if (dev_is_pci(dev)) {
@@ -415,15 +238,17 @@ static void __arm_smmu_free_bitmap(unsigned long *map, int idx)
}
/* Wait for any pending TLB invalidations to complete */
-static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
- void __iomem *sync, void __iomem *status)
+static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
+ int sync, int status)
{
unsigned int spin_cnt, delay;
+ u32 reg;
- writel_relaxed(QCOM_DUMMY_VAL, sync);
+ arm_smmu_writel(smmu, page, sync, QCOM_DUMMY_VAL);
for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) {
for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) {
- if (!(readl_relaxed(status) & sTLBGSTATUS_GSACTIVE))
+ reg = arm_smmu_readl(smmu, page, status);
+ if (!(reg & sTLBGSTATUS_GSACTIVE))
return;
cpu_relax();
}
@@ -435,12 +260,11 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
static void arm_smmu_tlb_sync_global(struct arm_smmu_device *smmu)
{
- void __iomem *base = ARM_SMMU_GR0(smmu);
unsigned long flags;
spin_lock_irqsave(&smmu->global_sync_lock, flags);
- __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_GR0_sTLBGSYNC,
- base + ARM_SMMU_GR0_sTLBGSTATUS);
+ __arm_smmu_tlb_sync(smmu, ARM_SMMU_GR0, ARM_SMMU_GR0_sTLBGSYNC,
+ ARM_SMMU_GR0_sTLBGSTATUS);
spin_unlock_irqrestore(&smmu->global_sync_lock, flags);
}
@@ -448,12 +272,11 @@ static void arm_smmu_tlb_sync_context(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- void __iomem *base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx);
unsigned long flags;
spin_lock_irqsave(&smmu_domain->cb_lock, flags);
- __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_CB_TLBSYNC,
- base + ARM_SMMU_CB_TLBSTATUS);
+ __arm_smmu_tlb_sync(smmu, ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx),
+ ARM_SMMU_CB_TLBSYNC, ARM_SMMU_CB_TLBSTATUS);
spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
}
@@ -467,14 +290,13 @@ static void arm_smmu_tlb_sync_vmid(void *cookie)
static void arm_smmu_tlb_inv_context_s1(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
- struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
- void __iomem *base = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx);
-
/*
- * NOTE: this is not a relaxed write; it needs to guarantee that PTEs
- * cleared by the current CPU are visible to the SMMU before the TLBI.
+ * The TLBI write may be relaxed, so ensure that PTEs cleared by the
+ * current CPU are visible beforehand.
*/
- writel(cfg->asid, base + ARM_SMMU_CB_S1_TLBIASID);
+ wmb();
+ arm_smmu_cb_write(smmu_domain->smmu, smmu_domain->cfg.cbndx,
+ ARM_SMMU_CB_S1_TLBIASID, smmu_domain->cfg.asid);
arm_smmu_tlb_sync_context(cookie);
}
@@ -482,87 +304,143 @@ static void arm_smmu_tlb_inv_context_s2(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- void __iomem *base = ARM_SMMU_GR0(smmu);
- /* NOTE: see above */
- writel(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID);
+ /* See above */
+ wmb();
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIVMID, smmu_domain->cfg.vmid);
arm_smmu_tlb_sync_global(smmu);
}
-static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void arm_smmu_tlb_inv_range_s1(unsigned long iova, size_t size,
+ size_t granule, bool leaf, void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
- bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
- void __iomem *reg = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx);
+ int reg, idx = cfg->cbndx;
- if (smmu_domain->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
wmb();
- if (stage1) {
- reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
-
- if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {
- iova &= ~12UL;
- iova |= cfg->asid;
- do {
- writel_relaxed(iova, reg);
- iova += granule;
- } while (size -= granule);
- } else {
- iova >>= 12;
- iova |= (u64)cfg->asid << 48;
- do {
- writeq_relaxed(iova, reg);
- iova += granule >> 12;
- } while (size -= granule);
- }
+ reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
+
+ if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {
+ iova = (iova >> 12) << 12;
+ iova |= cfg->asid;
+ do {
+ arm_smmu_cb_write(smmu, idx, reg, iova);
+ iova += granule;
+ } while (size -= granule);
} else {
- reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L :
- ARM_SMMU_CB_S2_TLBIIPAS2;
iova >>= 12;
+ iova |= (u64)cfg->asid << 48;
do {
- smmu_write_atomic_lq(iova, reg);
+ arm_smmu_cb_writeq(smmu, idx, reg, iova);
iova += granule >> 12;
} while (size -= granule);
}
}
+static void arm_smmu_tlb_inv_range_s2(unsigned long iova, size_t size,
+ size_t granule, bool leaf, void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ int reg, idx = smmu_domain->cfg.cbndx;
+
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
+ wmb();
+
+ reg = leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L : ARM_SMMU_CB_S2_TLBIIPAS2;
+ iova >>= 12;
+ do {
+ if (smmu_domain->cfg.fmt == ARM_SMMU_CTX_FMT_AARCH64)
+ arm_smmu_cb_writeq(smmu, idx, reg, iova);
+ else
+ arm_smmu_cb_write(smmu, idx, reg, iova);
+ iova += granule >> 12;
+ } while (size -= granule);
+}
+
/*
* On MMU-401 at least, the cost of firing off multiple TLBIVMIDs appears
* almost negligible, but the benefit of getting the first one in as far ahead
* of the sync as possible is significant, hence we don't just make this a
- * no-op and set .tlb_sync to arm_smmu_inv_context_s2() as you might think.
+ * no-op and set .tlb_sync to arm_smmu_tlb_inv_context_s2() as you might think.
*/
static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size,
size_t granule, bool leaf, void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
- void __iomem *base = ARM_SMMU_GR0(smmu_domain->smmu);
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
- if (smmu_domain->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
wmb();
- writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIVMID, smmu_domain->cfg.vmid);
+}
+
+static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
+
+ ops->tlb_inv_range(iova, size, granule, false, cookie);
+ ops->tlb_sync(cookie);
+}
+
+static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
+
+ ops->tlb_inv_range(iova, size, granule, true, cookie);
+ ops->tlb_sync(cookie);
+}
+
+static void arm_smmu_tlb_add_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule,
+ void *cookie)
+{
+ struct arm_smmu_domain *smmu_domain = cookie;
+ const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops;
+
+ ops->tlb_inv_range(iova, granule, granule, true, cookie);
}
-static const struct iommu_gather_ops arm_smmu_s1_tlb_ops = {
- .tlb_flush_all = arm_smmu_tlb_inv_context_s1,
- .tlb_add_flush = arm_smmu_tlb_inv_range_nosync,
- .tlb_sync = arm_smmu_tlb_sync_context,
+static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = {
+ .tlb = {
+ .tlb_flush_all = arm_smmu_tlb_inv_context_s1,
+ .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+ .tlb_add_page = arm_smmu_tlb_add_page,
+ },
+ .tlb_inv_range = arm_smmu_tlb_inv_range_s1,
+ .tlb_sync = arm_smmu_tlb_sync_context,
};
-static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v2 = {
- .tlb_flush_all = arm_smmu_tlb_inv_context_s2,
- .tlb_add_flush = arm_smmu_tlb_inv_range_nosync,
- .tlb_sync = arm_smmu_tlb_sync_context,
+static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = {
+ .tlb = {
+ .tlb_flush_all = arm_smmu_tlb_inv_context_s2,
+ .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+ .tlb_add_page = arm_smmu_tlb_add_page,
+ },
+ .tlb_inv_range = arm_smmu_tlb_inv_range_s2,
+ .tlb_sync = arm_smmu_tlb_sync_context,
};
-static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v1 = {
- .tlb_flush_all = arm_smmu_tlb_inv_context_s2,
- .tlb_add_flush = arm_smmu_tlb_inv_vmid_nosync,
- .tlb_sync = arm_smmu_tlb_sync_vmid,
+static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = {
+ .tlb = {
+ .tlb_flush_all = arm_smmu_tlb_inv_context_s2,
+ .tlb_flush_walk = arm_smmu_tlb_inv_walk,
+ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf,
+ .tlb_add_page = arm_smmu_tlb_add_page,
+ },
+ .tlb_inv_range = arm_smmu_tlb_inv_vmid_nosync,
+ .tlb_sync = arm_smmu_tlb_sync_vmid,
};
static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
@@ -571,26 +449,22 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
unsigned long iova;
struct iommu_domain *domain = dev;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- void __iomem *gr1_base = ARM_SMMU_GR1(smmu);
- void __iomem *cb_base;
-
- cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
- fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
+ int idx = smmu_domain->cfg.cbndx;
+ fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
if (!(fsr & FSR_FAULT))
return IRQ_NONE;
- fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
- iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR);
- cbfrsynra = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
+ fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
+ iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
+ cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
dev_err_ratelimited(smmu->dev,
"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
- fsr, iova, fsynr, cbfrsynra, cfg->cbndx);
+ fsr, iova, fsynr, cbfrsynra, idx);
- writel(fsr, cb_base + ARM_SMMU_CB_FSR);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);
return IRQ_HANDLED;
}
@@ -598,12 +472,11 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
{
u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
struct arm_smmu_device *smmu = dev;
- void __iomem *gr0_base = ARM_SMMU_GR0_NS(smmu);
- gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
- gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0);
- gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1);
- gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2);
+ gfsr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSR);
+ gfsynr0 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR0);
+ gfsynr1 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR1);
+ gfsynr2 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR2);
if (!gfsr)
return IRQ_NONE;
@@ -614,7 +487,7 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
"\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
gfsr, gfsynr0, gfsynr1, gfsynr2);
- writel(gfsr, gr0_base + ARM_SMMU_GR0_sGFSR);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sGFSR, gfsr);
return IRQ_HANDLED;
}
@@ -627,16 +500,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
cb->cfg = cfg;
- /* TTBCR */
+ /* TCR */
if (stage1) {
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
cb->tcr[0] = pgtbl_cfg->arm_v7s_cfg.tcr;
} else {
cb->tcr[0] = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
cb->tcr[1] = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
- cb->tcr[1] |= TTBCR2_SEP_UPSTREAM;
+ cb->tcr[1] |= FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM);
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
- cb->tcr[1] |= TTBCR2_AS;
+ cb->tcr[1] |= TCR2_AS;
}
} else {
cb->tcr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
@@ -649,9 +522,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
cb->ttbr[1] = pgtbl_cfg->arm_v7s_cfg.ttbr[1];
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
- cb->ttbr[0] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+ cb->ttbr[0] |= FIELD_PREP(TTBRn_ASID, cfg->asid);
cb->ttbr[1] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
- cb->ttbr[1] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+ cb->ttbr[1] |= FIELD_PREP(TTBRn_ASID, cfg->asid);
}
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
@@ -675,74 +548,71 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
bool stage1;
struct arm_smmu_cb *cb = &smmu->cbs[idx];
struct arm_smmu_cfg *cfg = cb->cfg;
- void __iomem *cb_base, *gr1_base;
-
- cb_base = ARM_SMMU_CB(smmu, idx);
/* Unassigned context banks only need disabling */
if (!cfg) {
- writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, 0);
return;
}
- gr1_base = ARM_SMMU_GR1(smmu);
stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
/* CBA2R */
if (smmu->version > ARM_SMMU_V1) {
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
- reg = CBA2R_RW64_64BIT;
+ reg = CBA2R_VA64;
else
- reg = CBA2R_RW64_32BIT;
+ reg = 0;
/* 16-bit VMIDs live in CBA2R */
if (smmu->features & ARM_SMMU_FEAT_VMID16)
- reg |= cfg->vmid << CBA2R_VMID_SHIFT;
+ reg |= FIELD_PREP(CBA2R_VMID16, cfg->vmid);
- writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(idx));
+ arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBA2R(idx), reg);
}
/* CBAR */
- reg = cfg->cbar;
+ reg = FIELD_PREP(CBAR_TYPE, cfg->cbar);
if (smmu->version < ARM_SMMU_V2)
- reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
+ reg |= FIELD_PREP(CBAR_IRPTNDX, cfg->irptndx);
/*
* Use the weakest shareability/memory types, so they are
* overridden by the ttbcr/pte.
*/
if (stage1) {
- reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
- (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+ reg |= FIELD_PREP(CBAR_S1_BPSHCFG, CBAR_S1_BPSHCFG_NSH) |
+ FIELD_PREP(CBAR_S1_MEMATTR, CBAR_S1_MEMATTR_WB);
} else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {
/* 8-bit VMIDs live in CBAR */
- reg |= cfg->vmid << CBAR_VMID_SHIFT;
+ reg |= FIELD_PREP(CBAR_VMID, cfg->vmid);
}
- writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(idx));
+ arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBAR(idx), reg);
/*
- * TTBCR
+ * TCR
* We must write this before the TTBRs, since it determines the
* access behaviour of some fields (in particular, ASID[15:8]).
*/
if (stage1 && smmu->version > ARM_SMMU_V1)
- writel_relaxed(cb->tcr[1], cb_base + ARM_SMMU_CB_TTBCR2);
- writel_relaxed(cb->tcr[0], cb_base + ARM_SMMU_CB_TTBCR);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_TCR2, cb->tcr[1]);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_TCR, cb->tcr[0]);
/* TTBRs */
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
- writel_relaxed(cfg->asid, cb_base + ARM_SMMU_CB_CONTEXTIDR);
- writel_relaxed(cb->ttbr[0], cb_base + ARM_SMMU_CB_TTBR0);
- writel_relaxed(cb->ttbr[1], cb_base + ARM_SMMU_CB_TTBR1);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_CONTEXTIDR, cfg->asid);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_TTBR0, cb->ttbr[0]);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_TTBR1, cb->ttbr[1]);
} else {
- writeq_relaxed(cb->ttbr[0], cb_base + ARM_SMMU_CB_TTBR0);
+ arm_smmu_cb_writeq(smmu, idx, ARM_SMMU_CB_TTBR0, cb->ttbr[0]);
if (stage1)
- writeq_relaxed(cb->ttbr[1], cb_base + ARM_SMMU_CB_TTBR1);
+ arm_smmu_cb_writeq(smmu, idx, ARM_SMMU_CB_TTBR1,
+ cb->ttbr[1]);
}
/* MAIRs (stage-1 only) */
if (stage1) {
- writel_relaxed(cb->mair[0], cb_base + ARM_SMMU_CB_S1_MAIR0);
- writel_relaxed(cb->mair[1], cb_base + ARM_SMMU_CB_S1_MAIR1);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_S1_MAIR0, cb->mair[0]);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_S1_MAIR1, cb->mair[1]);
}
/* SCTLR */
@@ -752,7 +622,7 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
reg |= SCTLR_E;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg);
}
static int arm_smmu_init_domain_context(struct iommu_domain *domain,
@@ -842,7 +712,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
ias = min(ias, 32UL);
oas = min(oas, 32UL);
}
- smmu_domain->tlb_ops = &arm_smmu_s1_tlb_ops;
+ smmu_domain->flush_ops = &arm_smmu_s1_tlb_ops;
break;
case ARM_SMMU_DOMAIN_NESTED:
/*
@@ -862,9 +732,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
oas = min(oas, 40UL);
}
if (smmu->version == ARM_SMMU_V2)
- smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v2;
+ smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v2;
else
- smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v1;
+ smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v1;
break;
default:
ret = -EINVAL;
@@ -884,23 +754,29 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
}
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2)
- cfg->vmid = cfg->cbndx + 1 + smmu->cavium_id_base;
+ cfg->vmid = cfg->cbndx + 1;
else
- cfg->asid = cfg->cbndx + smmu->cavium_id_base;
+ cfg->asid = cfg->cbndx;
+
+ smmu_domain->smmu = smmu;
+ if (smmu->impl && smmu->impl->init_context) {
+ ret = smmu->impl->init_context(smmu_domain);
+ if (ret)
+ goto out_unlock;
+ }
pgtbl_cfg = (struct io_pgtable_cfg) {
.pgsize_bitmap = smmu->pgsize_bitmap,
.ias = ias,
.oas = oas,
.coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK,
- .tlb = smmu_domain->tlb_ops,
+ .tlb = &smmu_domain->flush_ops->tlb,
.iommu_dev = smmu->dev,
};
if (smmu_domain->non_strict)
pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT;
- smmu_domain->smmu = smmu;
pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
if (!pgtbl_ops) {
ret = -ENOMEM;
@@ -1019,24 +895,24 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
{
struct arm_smmu_smr *smr = smmu->smrs + idx;
- u32 reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
+ u32 reg = FIELD_PREP(SMR_ID, smr->id) | FIELD_PREP(SMR_MASK, smr->mask);
if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
reg |= SMR_VALID;
- writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_SMR(idx), reg);
}
static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
{
struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
- u32 reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
- (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
- (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+ u32 reg = FIELD_PREP(S2CR_TYPE, s2cr->type) |
+ FIELD_PREP(S2CR_CBNDX, s2cr->cbndx) |
+ FIELD_PREP(S2CR_PRIVCFG, s2cr->privcfg);
if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs &&
smmu->smrs[idx].valid)
reg |= S2CR_EXIDVALID;
- writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_S2CR(idx));
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_S2CR(idx), reg);
}
static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
@@ -1052,7 +928,6 @@ static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
*/
static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
{
- void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
u32 smr;
if (!smmu->smrs)
@@ -1063,15 +938,15 @@ static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
* bits are set, so check each one separately. We can reject
* masters later if they try to claim IDs outside these masks.
*/
- smr = smmu->streamid_mask << SMR_ID_SHIFT;
- writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
- smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->streamid_mask = smr >> SMR_ID_SHIFT;
+ smr = FIELD_PREP(SMR_ID, smmu->streamid_mask);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_SMR(0), smr);
+ smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(0));
+ smmu->streamid_mask = FIELD_GET(SMR_ID, smr);
- smr = smmu->streamid_mask << SMR_MASK_SHIFT;
- writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
- smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
+ smr = FIELD_PREP(SMR_MASK, smmu->streamid_mask);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_SMR(0), smr);
+ smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(0));
+ smmu->smr_mask_mask = FIELD_GET(SMR_MASK, smr);
}
static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
@@ -1140,8 +1015,8 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
mutex_lock(&smmu->stream_map_mutex);
/* Figure out a viable stream map entry allocation */
for_each_cfg_sme(fwspec, i, idx) {
- u16 sid = fwspec->ids[i];
- u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
+ u16 sid = FIELD_GET(SMR_ID, fwspec->ids[i]);
+ u16 mask = FIELD_GET(SMR_MASK, fwspec->ids[i]);
if (idx != INVALID_SMENDX) {
ret = -EEXIST;
@@ -1301,7 +1176,7 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
@@ -1311,7 +1186,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
return 0;
arm_smmu_rpm_get(smmu);
- ret = ops->unmap(ops, iova, size);
+ ret = ops->unmap(ops, iova, size, gather);
arm_smmu_rpm_put(smmu);
return ret;
@@ -1322,21 +1197,22 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
- if (smmu_domain->tlb_ops) {
+ if (smmu_domain->flush_ops) {
arm_smmu_rpm_get(smmu);
- smmu_domain->tlb_ops->tlb_flush_all(smmu_domain);
+ smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain);
arm_smmu_rpm_put(smmu);
}
}
-static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
+static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
- if (smmu_domain->tlb_ops) {
+ if (smmu_domain->flush_ops) {
arm_smmu_rpm_get(smmu);
- smmu_domain->tlb_ops->tlb_sync(smmu_domain);
+ smmu_domain->flush_ops->tlb_sync(smmu_domain);
arm_smmu_rpm_put(smmu);
}
}
@@ -1349,28 +1225,25 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
struct device *dev = smmu->dev;
- void __iomem *cb_base;
+ void __iomem *reg;
u32 tmp;
u64 phys;
unsigned long va, flags;
- int ret;
+ int ret, idx = cfg->cbndx;
ret = arm_smmu_rpm_get(smmu);
if (ret < 0)
return 0;
- cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
-
spin_lock_irqsave(&smmu_domain->cb_lock, flags);
- /* ATS1 registers can only be written atomically */
va = iova & ~0xfffUL;
- if (smmu->version == ARM_SMMU_V2)
- smmu_write_atomic_lq(va, cb_base + ARM_SMMU_CB_ATS1PR);
- else /* Register is only 32-bit in v1 */
- writel_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);
+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
+ arm_smmu_cb_writeq(smmu, idx, ARM_SMMU_CB_ATS1PR, va);
+ else
+ arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_ATS1PR, va);
- if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
- !(tmp & ATSR_ACTIVE), 5, 50)) {
+ reg = arm_smmu_page(smmu, ARM_SMMU_CB(smmu, idx)) + ARM_SMMU_CB_ATSR;
+ if (readl_poll_timeout_atomic(reg, tmp, !(tmp & ATSR_ACTIVE), 5, 50)) {
spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
dev_err(dev,
"iova to phys timed out on %pad. Falling back to software table walk.\n",
@@ -1378,7 +1251,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
return ops->iova_to_phys(ops, iova);
}
- phys = readq_relaxed(cb_base + ARM_SMMU_CB_PAR);
+ phys = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_PAR);
spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
if (phys & CB_PAR_F) {
dev_err(dev, "translation fault!\n");
@@ -1466,8 +1339,8 @@ static int arm_smmu_add_device(struct device *dev)
ret = -EINVAL;
for (i = 0; i < fwspec->num_ids; i++) {
- u16 sid = fwspec->ids[i];
- u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
+ u16 sid = FIELD_GET(SMR_ID, fwspec->ids[i]);
+ u16 mask = FIELD_GET(SMR_MASK, fwspec->ids[i]);
if (sid & ~smmu->streamid_mask) {
dev_err(dev, "stream ID 0x%x out of range for SMMU (0x%x)\n",
@@ -1648,12 +1521,12 @@ static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
u32 mask, fwid = 0;
if (args->args_count > 0)
- fwid |= (u16)args->args[0];
+ fwid |= FIELD_PREP(SMR_ID, args->args[0]);
if (args->args_count > 1)
- fwid |= (u16)args->args[1] << SMR_MASK_SHIFT;
+ fwid |= FIELD_PREP(SMR_MASK, args->args[1]);
else if (!of_property_read_u32(args->np, "stream-match-mask", &mask))
- fwid |= (u16)mask << SMR_MASK_SHIFT;
+ fwid |= FIELD_PREP(SMR_MASK, mask);
return iommu_fwspec_add_ids(dev, &fwid, 1);
}
@@ -1706,13 +1579,12 @@ static struct iommu_ops arm_smmu_ops = {
static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
{
- void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
int i;
- u32 reg, major;
+ u32 reg;
/* clear global FSR */
- reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
- writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
+ reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSR);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sGFSR, reg);
/*
* Reset stream mapping groups: Initial values mark all SMRn as
@@ -1721,47 +1593,17 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
for (i = 0; i < smmu->num_mapping_groups; ++i)
arm_smmu_write_sme(smmu, i);
- if (smmu->model == ARM_MMU500) {
- /*
- * Before clearing ARM_MMU500_ACTLR_CPRE, need to
- * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
- * bit is only present in MMU-500r2 onwards.
- */
- reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
- major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
- reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
- if (major >= 2)
- reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
- /*
- * Allow unmatched Stream IDs to allocate bypass
- * TLB entries for reduced latency.
- */
- reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN;
- writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
- }
-
/* Make sure all context banks are disabled and clear CB_FSR */
for (i = 0; i < smmu->num_context_banks; ++i) {
- void __iomem *cb_base = ARM_SMMU_CB(smmu, i);
-
arm_smmu_write_context_bank(smmu, i);
- writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
- /*
- * Disable MMU-500's not-particularly-beneficial next-page
- * prefetcher for the sake of errata #841119 and #826419.
- */
- if (smmu->model == ARM_MMU500) {
- reg = readl_relaxed(cb_base + ARM_SMMU_CB_ACTLR);
- reg &= ~ARM_MMU500_ACTLR_CPRE;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_ACTLR);
- }
+ arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_FSR, FSR_FAULT);
}
/* Invalidate the TLB, just in case */
- writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLH);
- writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIALLH, QCOM_DUMMY_VAL);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIALLNSNH, QCOM_DUMMY_VAL);
- reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+ reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sCR0);
/* Enable fault reporting */
reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
@@ -1780,7 +1622,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
reg &= ~sCR0_FB;
/* Don't upgrade barriers */
- reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);
+ reg &= ~(sCR0_BSU);
if (smmu->features & ARM_SMMU_FEAT_VMID16)
reg |= sCR0_VMID16EN;
@@ -1788,9 +1630,12 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
if (smmu->features & ARM_SMMU_FEAT_EXIDS)
reg |= sCR0_EXIDENABLE;
+ if (smmu->impl && smmu->impl->reset)
+ smmu->impl->reset(smmu);
+
/* Push the button */
arm_smmu_tlb_sync_global(smmu);
- writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, reg);
}
static int arm_smmu_id_size_to_bits(int size)
@@ -1814,8 +1659,7 @@ static int arm_smmu_id_size_to_bits(int size)
static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
{
- unsigned long size;
- void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+ unsigned int size;
u32 id;
bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
int i;
@@ -1825,7 +1669,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu->version == ARM_SMMU_V2 ? 2 : 1);
/* ID0 */
- id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0);
+ id = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID0);
/* Restrict available stages based on module parameter */
if (force_stage == 1)
@@ -1879,12 +1723,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu->features |= ARM_SMMU_FEAT_EXIDS;
size = 1 << 16;
} else {
- size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
+ size = 1 << FIELD_GET(ID0_NUMSIDB, id);
}
smmu->streamid_mask = size - 1;
if (id & ID0_SMS) {
smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH;
- size = (id >> ID0_NUMSMRG_SHIFT) & ID0_NUMSMRG_MASK;
+ size = FIELD_GET(ID0_NUMSMRG, id);
if (size == 0) {
dev_err(smmu->dev,
"stream-matching supported, but no SMRs present!\n");
@@ -1898,7 +1742,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
return -ENOMEM;
dev_notice(smmu->dev,
- "\tstream matching with %lu register groups", size);
+ "\tstream matching with %u register groups", size);
}
/* s2cr->type == 0 means translation, so initialise explicitly */
smmu->s2crs = devm_kmalloc_array(smmu->dev, size, sizeof(*smmu->s2crs),
@@ -1919,49 +1763,38 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
}
/* ID1 */
- id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1);
+ id = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID1);
smmu->pgshift = (id & ID1_PAGESIZE) ? 16 : 12;
/* Check for size mismatch of SMMU address space from mapped region */
- size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
- size <<= smmu->pgshift;
- if (smmu->cb_base != gr0_base + size)
+ size = 1 << (FIELD_GET(ID1_NUMPAGENDXB, id) + 1);
+ if (smmu->numpage != 2 * size << smmu->pgshift)
dev_warn(smmu->dev,
- "SMMU address space size (0x%lx) differs from mapped region size (0x%tx)!\n",
- size * 2, (smmu->cb_base - gr0_base) * 2);
+ "SMMU address space size (0x%x) differs from mapped region size (0x%x)!\n",
+ 2 * size << smmu->pgshift, smmu->numpage);
+ /* Now properly encode NUMPAGE to subsequently derive SMMU_CB_BASE */
+ smmu->numpage = size;
- smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & ID1_NUMS2CB_MASK;
- smmu->num_context_banks = (id >> ID1_NUMCB_SHIFT) & ID1_NUMCB_MASK;
+ smmu->num_s2_context_banks = FIELD_GET(ID1_NUMS2CB, id);
+ smmu->num_context_banks = FIELD_GET(ID1_NUMCB, id);
if (smmu->num_s2_context_banks > smmu->num_context_banks) {
dev_err(smmu->dev, "impossible number of S2 context banks!\n");
return -ENODEV;
}
dev_notice(smmu->dev, "\t%u context banks (%u stage-2 only)\n",
smmu->num_context_banks, smmu->num_s2_context_banks);
- /*
- * Cavium CN88xx erratum #27704.
- * Ensure ASID and VMID allocation is unique across all SMMUs in
- * the system.
- */
- if (smmu->model == CAVIUM_SMMUV2) {
- smmu->cavium_id_base =
- atomic_add_return(smmu->num_context_banks,
- &cavium_smmu_context_count);
- smmu->cavium_id_base -= smmu->num_context_banks;
- dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
- }
smmu->cbs = devm_kcalloc(smmu->dev, smmu->num_context_banks,
sizeof(*smmu->cbs), GFP_KERNEL);
if (!smmu->cbs)
return -ENOMEM;
/* ID2 */
- id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2);
- size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & ID2_IAS_MASK);
+ id = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID2);
+ size = arm_smmu_id_size_to_bits(FIELD_GET(ID2_IAS, id));
smmu->ipa_size = size;
/* The output mask is also applied for bypass */
- size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
+ size = arm_smmu_id_size_to_bits(FIELD_GET(ID2_OAS, id));
smmu->pa_size = size;
if (id & ID2_VMID16)
@@ -1981,7 +1814,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
if (smmu->version == ARM_SMMU_V1_64K)
smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_64K;
} else {
- size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK;
+ size = FIELD_GET(ID2_UBS, id);
smmu->va_size = arm_smmu_id_size_to_bits(size);
if (id & ID2_PTFS_4K)
smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_4K;
@@ -2018,6 +1851,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
dev_notice(smmu->dev, "\tStage-2: %lu-bit IPA -> %lu-bit PA\n",
smmu->ipa_size, smmu->pa_size);
+ if (smmu->impl && smmu->impl->cfg_probe)
+ return smmu->impl->cfg_probe(smmu);
+
return 0;
}
@@ -2130,8 +1966,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev,
smmu->version = data->version;
smmu->model = data->model;
- parse_driver_options(smmu);
-
legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
if (legacy_binding && !using_generic_binding) {
if (!using_legacy_binding)
@@ -2194,12 +2028,20 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
if (err)
return err;
+ smmu = arm_smmu_impl_init(smmu);
+ if (IS_ERR(smmu))
+ return PTR_ERR(smmu);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ioaddr = res->start;
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
- smmu->cb_base = smmu->base + resource_size(res) / 2;
+ /*
+ * The resource size should effectively match the value of SMMU_TOP;
+ * stash that temporarily until we know PAGESIZE to validate it with.
+ */
+ smmu->numpage = resource_size(res);
num_irqs = 0;
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
@@ -2339,7 +2181,7 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev)
arm_smmu_rpm_get(smmu);
/* Turn the thing off */
- writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, sCR0_CLIENTPD);
arm_smmu_rpm_put(smmu);
if (pm_runtime_enabled(smmu->dev))
diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h
new file mode 100644
index 000000000000..b19b6cae9b5e
--- /dev/null
+++ b/drivers/iommu/arm-smmu.h
@@ -0,0 +1,402 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * IOMMU API for ARM architected SMMU implementations.
+ *
+ * Copyright (C) 2013 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#ifndef _ARM_SMMU_H
+#define _ARM_SMMU_H
+
+#include <linux/atomic.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/io-pgtable.h>
+#include <linux/iommu.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+/* Configuration registers */
+#define ARM_SMMU_GR0_sCR0 0x0
+#define sCR0_VMID16EN BIT(31)
+#define sCR0_BSU GENMASK(15, 14)
+#define sCR0_FB BIT(13)
+#define sCR0_PTM BIT(12)
+#define sCR0_VMIDPNE BIT(11)
+#define sCR0_USFCFG BIT(10)
+#define sCR0_GCFGFIE BIT(5)
+#define sCR0_GCFGFRE BIT(4)
+#define sCR0_EXIDENABLE BIT(3)
+#define sCR0_GFIE BIT(2)
+#define sCR0_GFRE BIT(1)
+#define sCR0_CLIENTPD BIT(0)
+
+/* Auxiliary Configuration register */
+#define ARM_SMMU_GR0_sACR 0x10
+
+/* Identification registers */
+#define ARM_SMMU_GR0_ID0 0x20
+#define ID0_S1TS BIT(30)
+#define ID0_S2TS BIT(29)
+#define ID0_NTS BIT(28)
+#define ID0_SMS BIT(27)
+#define ID0_ATOSNS BIT(26)
+#define ID0_PTFS_NO_AARCH32 BIT(25)
+#define ID0_PTFS_NO_AARCH32S BIT(24)
+#define ID0_NUMIRPT GENMASK(23, 16)
+#define ID0_CTTW BIT(14)
+#define ID0_NUMSIDB GENMASK(12, 9)
+#define ID0_EXIDS BIT(8)
+#define ID0_NUMSMRG GENMASK(7, 0)
+
+#define ARM_SMMU_GR0_ID1 0x24
+#define ID1_PAGESIZE BIT(31)
+#define ID1_NUMPAGENDXB GENMASK(30, 28)
+#define ID1_NUMS2CB GENMASK(23, 16)
+#define ID1_NUMCB GENMASK(7, 0)
+
+#define ARM_SMMU_GR0_ID2 0x28
+#define ID2_VMID16 BIT(15)
+#define ID2_PTFS_64K BIT(14)
+#define ID2_PTFS_16K BIT(13)
+#define ID2_PTFS_4K BIT(12)
+#define ID2_UBS GENMASK(11, 8)
+#define ID2_OAS GENMASK(7, 4)
+#define ID2_IAS GENMASK(3, 0)
+
+#define ARM_SMMU_GR0_ID3 0x2c
+#define ARM_SMMU_GR0_ID4 0x30
+#define ARM_SMMU_GR0_ID5 0x34
+#define ARM_SMMU_GR0_ID6 0x38
+
+#define ARM_SMMU_GR0_ID7 0x3c
+#define ID7_MAJOR GENMASK(7, 4)
+#define ID7_MINOR GENMASK(3, 0)
+
+#define ARM_SMMU_GR0_sGFSR 0x48
+#define ARM_SMMU_GR0_sGFSYNR0 0x50
+#define ARM_SMMU_GR0_sGFSYNR1 0x54
+#define ARM_SMMU_GR0_sGFSYNR2 0x58
+
+/* Global TLB invalidation */
+#define ARM_SMMU_GR0_TLBIVMID 0x64
+#define ARM_SMMU_GR0_TLBIALLNSNH 0x68
+#define ARM_SMMU_GR0_TLBIALLH 0x6c
+#define ARM_SMMU_GR0_sTLBGSYNC 0x70
+
+#define ARM_SMMU_GR0_sTLBGSTATUS 0x74
+#define sTLBGSTATUS_GSACTIVE BIT(0)
+
+/* Stream mapping registers */
+#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
+#define SMR_VALID BIT(31)
+#define SMR_MASK GENMASK(31, 16)
+#define SMR_ID GENMASK(15, 0)
+
+#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
+#define S2CR_PRIVCFG GENMASK(25, 24)
+enum arm_smmu_s2cr_privcfg {
+ S2CR_PRIVCFG_DEFAULT,
+ S2CR_PRIVCFG_DIPAN,
+ S2CR_PRIVCFG_UNPRIV,
+ S2CR_PRIVCFG_PRIV,
+};
+#define S2CR_TYPE GENMASK(17, 16)
+enum arm_smmu_s2cr_type {
+ S2CR_TYPE_TRANS,
+ S2CR_TYPE_BYPASS,
+ S2CR_TYPE_FAULT,
+};
+#define S2CR_EXIDVALID BIT(10)
+#define S2CR_CBNDX GENMASK(7, 0)
+
+/* Context bank attribute registers */
+#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
+#define CBAR_IRPTNDX GENMASK(31, 24)
+#define CBAR_TYPE GENMASK(17, 16)
+enum arm_smmu_cbar_type {
+ CBAR_TYPE_S2_TRANS,
+ CBAR_TYPE_S1_TRANS_S2_BYPASS,
+ CBAR_TYPE_S1_TRANS_S2_FAULT,
+ CBAR_TYPE_S1_TRANS_S2_TRANS,
+};
+#define CBAR_S1_MEMATTR GENMASK(15, 12)
+#define CBAR_S1_MEMATTR_WB 0xf
+#define CBAR_S1_BPSHCFG GENMASK(9, 8)
+#define CBAR_S1_BPSHCFG_NSH 3
+#define CBAR_VMID GENMASK(7, 0)
+
+#define ARM_SMMU_GR1_CBFRSYNRA(n) (0x400 + ((n) << 2))
+
+#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
+#define CBA2R_VMID16 GENMASK(31, 16)
+#define CBA2R_VA64 BIT(0)
+
+#define ARM_SMMU_CB_SCTLR 0x0
+#define SCTLR_S1_ASIDPNE BIT(12)
+#define SCTLR_CFCFG BIT(7)
+#define SCTLR_CFIE BIT(6)
+#define SCTLR_CFRE BIT(5)
+#define SCTLR_E BIT(4)
+#define SCTLR_AFE BIT(2)
+#define SCTLR_TRE BIT(1)
+#define SCTLR_M BIT(0)
+
+#define ARM_SMMU_CB_ACTLR 0x4
+
+#define ARM_SMMU_CB_RESUME 0x8
+#define RESUME_TERMINATE BIT(0)
+
+#define ARM_SMMU_CB_TCR2 0x10
+#define TCR2_SEP GENMASK(17, 15)
+#define TCR2_SEP_UPSTREAM 0x7
+#define TCR2_AS BIT(4)
+
+#define ARM_SMMU_CB_TTBR0 0x20
+#define ARM_SMMU_CB_TTBR1 0x28
+#define TTBRn_ASID GENMASK_ULL(63, 48)
+
+#define ARM_SMMU_CB_TCR 0x30
+#define ARM_SMMU_CB_CONTEXTIDR 0x34
+#define ARM_SMMU_CB_S1_MAIR0 0x38
+#define ARM_SMMU_CB_S1_MAIR1 0x3c
+
+#define ARM_SMMU_CB_PAR 0x50
+#define CB_PAR_F BIT(0)
+
+#define ARM_SMMU_CB_FSR 0x58
+#define FSR_MULTI BIT(31)
+#define FSR_SS BIT(30)
+#define FSR_UUT BIT(8)
+#define FSR_ASF BIT(7)
+#define FSR_TLBLKF BIT(6)
+#define FSR_TLBMCF BIT(5)
+#define FSR_EF BIT(4)
+#define FSR_PF BIT(3)
+#define FSR_AFF BIT(2)
+#define FSR_TF BIT(1)
+
+#define FSR_IGN (FSR_AFF | FSR_ASF | \
+ FSR_TLBMCF | FSR_TLBLKF)
+#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
+ FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
+
+#define ARM_SMMU_CB_FAR 0x60
+
+#define ARM_SMMU_CB_FSYNR0 0x68
+#define FSYNR0_WNR BIT(4)
+
+#define ARM_SMMU_CB_S1_TLBIVA 0x600
+#define ARM_SMMU_CB_S1_TLBIASID 0x610
+#define ARM_SMMU_CB_S1_TLBIVAL 0x620
+#define ARM_SMMU_CB_S2_TLBIIPAS2 0x630
+#define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638
+#define ARM_SMMU_CB_TLBSYNC 0x7f0
+#define ARM_SMMU_CB_TLBSTATUS 0x7f4
+#define ARM_SMMU_CB_ATS1PR 0x800
+
+#define ARM_SMMU_CB_ATSR 0x8f0
+#define ATSR_ACTIVE BIT(0)
+
+
+/* Maximum number of context banks per SMMU */
+#define ARM_SMMU_MAX_CBS 128
+
+
+/* Shared driver definitions */
+enum arm_smmu_arch_version {
+ ARM_SMMU_V1,
+ ARM_SMMU_V1_64K,
+ ARM_SMMU_V2,
+};
+
+enum arm_smmu_implementation {
+ GENERIC_SMMU,
+ ARM_MMU500,
+ CAVIUM_SMMUV2,
+ QCOM_SMMUV2,
+};
+
+struct arm_smmu_device {
+ struct device *dev;
+
+ void __iomem *base;
+ unsigned int numpage;
+ unsigned int pgshift;
+
+#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
+#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1)
+#define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
+#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
+#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
+#define ARM_SMMU_FEAT_TRANS_OPS (1 << 5)
+#define ARM_SMMU_FEAT_VMID16 (1 << 6)
+#define ARM_SMMU_FEAT_FMT_AARCH64_4K (1 << 7)
+#define ARM_SMMU_FEAT_FMT_AARCH64_16K (1 << 8)
+#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
+#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
+#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
+#define ARM_SMMU_FEAT_EXIDS (1 << 12)
+ u32 features;
+
+ enum arm_smmu_arch_version version;
+ enum arm_smmu_implementation model;
+ const struct arm_smmu_impl *impl;
+
+ u32 num_context_banks;
+ u32 num_s2_context_banks;
+ DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
+ struct arm_smmu_cb *cbs;
+ atomic_t irptndx;
+
+ u32 num_mapping_groups;
+ u16 streamid_mask;
+ u16 smr_mask_mask;
+ struct arm_smmu_smr *smrs;
+ struct arm_smmu_s2cr *s2crs;
+ struct mutex stream_map_mutex;
+
+ unsigned long va_size;
+ unsigned long ipa_size;
+ unsigned long pa_size;
+ unsigned long pgsize_bitmap;
+
+ u32 num_global_irqs;
+ u32 num_context_irqs;
+ unsigned int *irqs;
+ struct clk_bulk_data *clks;
+ int num_clks;
+
+ spinlock_t global_sync_lock;
+
+ /* IOMMU core code handle */
+ struct iommu_device iommu;
+};
+
+enum arm_smmu_context_fmt {
+ ARM_SMMU_CTX_FMT_NONE,
+ ARM_SMMU_CTX_FMT_AARCH64,
+ ARM_SMMU_CTX_FMT_AARCH32_L,
+ ARM_SMMU_CTX_FMT_AARCH32_S,
+};
+
+struct arm_smmu_cfg {
+ u8 cbndx;
+ u8 irptndx;
+ union {
+ u16 asid;
+ u16 vmid;
+ };
+ enum arm_smmu_cbar_type cbar;
+ enum arm_smmu_context_fmt fmt;
+};
+#define INVALID_IRPTNDX 0xff
+
+enum arm_smmu_domain_stage {
+ ARM_SMMU_DOMAIN_S1 = 0,
+ ARM_SMMU_DOMAIN_S2,
+ ARM_SMMU_DOMAIN_NESTED,
+ ARM_SMMU_DOMAIN_BYPASS,
+};
+
+struct arm_smmu_flush_ops {
+ struct iommu_flush_ops tlb;
+ void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule,
+ bool leaf, void *cookie);
+ void (*tlb_sync)(void *cookie);
+};
+
+struct arm_smmu_domain {
+ struct arm_smmu_device *smmu;
+ struct io_pgtable_ops *pgtbl_ops;
+ const struct arm_smmu_flush_ops *flush_ops;
+ struct arm_smmu_cfg cfg;
+ enum arm_smmu_domain_stage stage;
+ bool non_strict;
+ struct mutex init_mutex; /* Protects smmu pointer */
+ spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */
+ struct iommu_domain domain;
+};
+
+
+/* Implementation details, yay! */
+struct arm_smmu_impl {
+ u32 (*read_reg)(struct arm_smmu_device *smmu, int page, int offset);
+ void (*write_reg)(struct arm_smmu_device *smmu, int page, int offset,
+ u32 val);
+ u64 (*read_reg64)(struct arm_smmu_device *smmu, int page, int offset);
+ void (*write_reg64)(struct arm_smmu_device *smmu, int page, int offset,
+ u64 val);
+ int (*cfg_probe)(struct arm_smmu_device *smmu);
+ int (*reset)(struct arm_smmu_device *smmu);
+ int (*init_context)(struct arm_smmu_domain *smmu_domain);
+};
+
+static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n)
+{
+ return smmu->base + (n << smmu->pgshift);
+}
+
+static inline u32 arm_smmu_readl(struct arm_smmu_device *smmu, int page, int offset)
+{
+ if (smmu->impl && unlikely(smmu->impl->read_reg))
+ return smmu->impl->read_reg(smmu, page, offset);
+ return readl_relaxed(arm_smmu_page(smmu, page) + offset);
+}
+
+static inline void arm_smmu_writel(struct arm_smmu_device *smmu, int page,
+ int offset, u32 val)
+{
+ if (smmu->impl && unlikely(smmu->impl->write_reg))
+ smmu->impl->write_reg(smmu, page, offset, val);
+ else
+ writel_relaxed(val, arm_smmu_page(smmu, page) + offset);
+}
+
+static inline u64 arm_smmu_readq(struct arm_smmu_device *smmu, int page, int offset)
+{
+ if (smmu->impl && unlikely(smmu->impl->read_reg64))
+ return smmu->impl->read_reg64(smmu, page, offset);
+ return readq_relaxed(arm_smmu_page(smmu, page) + offset);
+}
+
+static inline void arm_smmu_writeq(struct arm_smmu_device *smmu, int page,
+ int offset, u64 val)
+{
+ if (smmu->impl && unlikely(smmu->impl->write_reg64))
+ smmu->impl->write_reg64(smmu, page, offset, val);
+ else
+ writeq_relaxed(val, arm_smmu_page(smmu, page) + offset);
+}
+
+#define ARM_SMMU_GR0 0
+#define ARM_SMMU_GR1 1
+#define ARM_SMMU_CB(s, n) ((s)->numpage + (n))
+
+#define arm_smmu_gr0_read(s, o) \
+ arm_smmu_readl((s), ARM_SMMU_GR0, (o))
+#define arm_smmu_gr0_write(s, o, v) \
+ arm_smmu_writel((s), ARM_SMMU_GR0, (o), (v))
+
+#define arm_smmu_gr1_read(s, o) \
+ arm_smmu_readl((s), ARM_SMMU_GR1, (o))
+#define arm_smmu_gr1_write(s, o, v) \
+ arm_smmu_writel((s), ARM_SMMU_GR1, (o), (v))
+
+#define arm_smmu_cb_read(s, n, o) \
+ arm_smmu_readl((s), ARM_SMMU_CB((s), (n)), (o))
+#define arm_smmu_cb_write(s, n, o, v) \
+ arm_smmu_writel((s), ARM_SMMU_CB((s), (n)), (o), (v))
+#define arm_smmu_cb_readq(s, n, o) \
+ arm_smmu_readq((s), ARM_SMMU_CB((s), (n)), (o))
+#define arm_smmu_cb_writeq(s, n, o, v) \
+ arm_smmu_writeq((s), ARM_SMMU_CB((s), (n)), (o), (v))
+
+struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu);
+
+#endif /* _ARM_SMMU_H */
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index a7f9c3edbcb2..8f412af84247 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -303,13 +303,15 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
u64 size, struct device *dev)
{
struct iommu_dma_cookie *cookie = domain->iova_cookie;
- struct iova_domain *iovad = &cookie->iovad;
unsigned long order, base_pfn;
+ struct iova_domain *iovad;
int attr;
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
return -EINVAL;
+ iovad = &cookie->iovad;
+
/* Use the smallest supported page size for IOVA granularity */
order = __ffs(domain->pgsize_bitmap);
base_pfn = max_t(unsigned long, 1, base >> order);
@@ -444,13 +446,18 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iova_domain *iovad = &cookie->iovad;
size_t iova_off = iova_offset(iovad, dma_addr);
+ struct iommu_iotlb_gather iotlb_gather;
+ size_t unmapped;
dma_addr -= iova_off;
size = iova_align(iovad, size + iova_off);
+ iommu_iotlb_gather_init(&iotlb_gather);
+
+ unmapped = iommu_unmap_fast(domain, dma_addr, size, &iotlb_gather);
+ WARN_ON(unmapped != size);
- WARN_ON(iommu_unmap_fast(domain, dma_addr, size) != size);
if (!cookie->fq_domain)
- iommu_tlb_sync(domain);
+ iommu_tlb_sync(domain, &iotlb_gather);
iommu_dma_free_iova(cookie, dma_addr, size);
}
@@ -459,13 +466,11 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
{
struct iommu_domain *domain = iommu_get_dma_domain(dev);
struct iommu_dma_cookie *cookie = domain->iova_cookie;
- size_t iova_off = 0;
+ struct iova_domain *iovad = &cookie->iovad;
+ size_t iova_off = iova_offset(iovad, phys);
dma_addr_t iova;
- if (cookie->type == IOMMU_DMA_IOVA_COOKIE) {
- iova_off = iova_offset(&cookie->iovad, phys);
- size = iova_align(&cookie->iovad, size + iova_off);
- }
+ size = iova_align(iovad, size + iova_off);
iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
if (!iova)
@@ -574,7 +579,7 @@ static void *iommu_dma_alloc_remap(struct device *dev, size_t size,
struct iova_domain *iovad = &cookie->iovad;
bool coherent = dev_is_dma_coherent(dev);
int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs);
- pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+ pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
struct page **pages;
struct sg_table sgt;
@@ -764,7 +769,7 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
* - and wouldn't make the resulting output segment too long
*/
if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
- (cur_len + s_length <= max_len)) {
+ (max_len - cur_len >= s_length)) {
/* ...then concatenate it with the previous one */
cur_len += s_length;
} else {
@@ -967,15 +972,18 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
{
bool coherent = dev_is_dma_coherent(dev);
size_t alloc_size = PAGE_ALIGN(size);
+ int node = dev_to_node(dev);
struct page *page = NULL;
void *cpu_addr;
page = dma_alloc_contiguous(dev, alloc_size, gfp);
if (!page)
+ page = alloc_pages_node(node, gfp, get_order(alloc_size));
+ if (!page)
return NULL;
if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
- pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+ pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
cpu_addr = dma_common_contiguous_remap(page, alloc_size,
VM_USERMAP, prot, __builtin_return_address(0));
@@ -1035,7 +1043,7 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
unsigned long pfn, off = vma->vm_pgoff;
int ret;
- vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+ vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
@@ -1147,16 +1155,21 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
if (!msi_page)
return NULL;
- iova = __iommu_dma_map(dev, msi_addr, size, prot);
- if (iova == DMA_MAPPING_ERROR)
+ iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
+ if (!iova)
goto out_free_page;
+ if (iommu_map(domain, iova, msi_addr, size, prot))
+ goto out_free_iova;
+
INIT_LIST_HEAD(&msi_page->list);
msi_page->phys = msi_addr;
msi_page->iova = iova;
list_add(&msi_page->list, &cookie->msi_page_list);
return msi_page;
+out_free_iova:
+ iommu_dma_free_iova(cookie, iova, size);
out_free_page:
kfree(msi_page);
return NULL;
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 5d0754ed5fa0..eecd6a421667 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1519,6 +1519,64 @@ static const char *dma_remap_fault_reasons[] =
"PCE for translation request specifies blocking",
};
+static const char * const dma_remap_sm_fault_reasons[] = {
+ "SM: Invalid Root Table Address",
+ "SM: TTM 0 for request with PASID",
+ "SM: TTM 0 for page group request",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x33-0x37 */
+ "SM: Error attempting to access Root Entry",
+ "SM: Present bit in Root Entry is clear",
+ "SM: Non-zero reserved field set in Root Entry",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x3B-0x3F */
+ "SM: Error attempting to access Context Entry",
+ "SM: Present bit in Context Entry is clear",
+ "SM: Non-zero reserved field set in the Context Entry",
+ "SM: Invalid Context Entry",
+ "SM: DTE field in Context Entry is clear",
+ "SM: PASID Enable field in Context Entry is clear",
+ "SM: PASID is larger than the max in Context Entry",
+ "SM: PRE field in Context-Entry is clear",
+ "SM: RID_PASID field error in Context-Entry",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x49-0x4F */
+ "SM: Error attempting to access the PASID Directory Entry",
+ "SM: Present bit in Directory Entry is clear",
+ "SM: Non-zero reserved field set in PASID Directory Entry",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x53-0x57 */
+ "SM: Error attempting to access PASID Table Entry",
+ "SM: Present bit in PASID Table Entry is clear",
+ "SM: Non-zero reserved field set in PASID Table Entry",
+ "SM: Invalid Scalable-Mode PASID Table Entry",
+ "SM: ERE field is clear in PASID Table Entry",
+ "SM: SRE field is clear in PASID Table Entry",
+ "Unknown", "Unknown",/* 0x5E-0x5F */
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x60-0x67 */
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x68-0x6F */
+ "SM: Error attempting to access first-level paging entry",
+ "SM: Present bit in first-level paging entry is clear",
+ "SM: Non-zero reserved field set in first-level paging entry",
+ "SM: Error attempting to access FL-PML4 entry",
+ "SM: First-level entry address beyond MGAW in Nested translation",
+ "SM: Read permission error in FL-PML4 entry in Nested translation",
+ "SM: Read permission error in first-level paging entry in Nested translation",
+ "SM: Write permission error in first-level paging entry in Nested translation",
+ "SM: Error attempting to access second-level paging entry",
+ "SM: Read/Write permission error in second-level paging entry",
+ "SM: Non-zero reserved field set in second-level paging entry",
+ "SM: Invalid second-level page table pointer",
+ "SM: A/D bit update needed in second-level entry when set up in no snoop",
+ "Unknown", "Unknown", "Unknown", /* 0x7D-0x7F */
+ "SM: Address in first-level translation is not canonical",
+ "SM: U/S set 0 for first-level translation with user privilege",
+ "SM: No execute permission for request with PASID and ER=1",
+ "SM: Address beyond the DMA hardware max",
+ "SM: Second-level entry address beyond the max",
+ "SM: No write permission for Write/AtomicOp request",
+ "SM: No read permission for Read/AtomicOp request",
+ "SM: Invalid address-interrupt address",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", /* 0x88-0x8F */
+ "SM: A/D bit update needed in first-level entry when set up in no snoop",
+};
+
static const char *irq_remap_fault_reasons[] =
{
"Detected reserved fields in the decoded interrupt-remapped request",
@@ -1536,6 +1594,10 @@ static const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
ARRAY_SIZE(irq_remap_fault_reasons))) {
*fault_type = INTR_REMAP;
return irq_remap_fault_reasons[fault_reason - 0x20];
+ } else if (fault_reason >= 0x30 && (fault_reason - 0x30 <
+ ARRAY_SIZE(dma_remap_sm_fault_reasons))) {
+ *fault_type = DMA_REMAP;
+ return dma_remap_sm_fault_reasons[fault_reason - 0x30];
} else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
*fault_type = DMA_REMAP;
return dma_remap_fault_reasons[fault_reason];
@@ -1611,7 +1673,8 @@ void dmar_msi_read(int irq, struct msi_msg *msg)
}
static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
- u8 fault_reason, u16 source_id, unsigned long long addr)
+ u8 fault_reason, int pasid, u16 source_id,
+ unsigned long long addr)
{
const char *reason;
int fault_type;
@@ -1624,10 +1687,11 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
PCI_FUNC(source_id & 0xFF), addr >> 48,
fault_reason, reason);
else
- pr_err("[%s] Request device [%02x:%02x.%d] fault addr %llx [fault reason %02d] %s\n",
+ pr_err("[%s] Request device [%02x:%02x.%d] PASID %x fault addr %llx [fault reason %02d] %s\n",
type ? "DMA Read" : "DMA Write",
source_id >> 8, PCI_SLOT(source_id & 0xFF),
- PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
+ PCI_FUNC(source_id & 0xFF), pasid, addr,
+ fault_reason, reason);
return 0;
}
@@ -1659,8 +1723,9 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
u8 fault_reason;
u16 source_id;
u64 guest_addr;
- int type;
+ int type, pasid;
u32 data;
+ bool pasid_present;
/* highest 32 bits */
data = readl(iommu->reg + reg +
@@ -1672,10 +1737,12 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
fault_reason = dma_frcd_fault_reason(data);
type = dma_frcd_type(data);
+ pasid = dma_frcd_pasid_value(data);
data = readl(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN + 8);
source_id = dma_frcd_source_id(data);
+ pasid_present = dma_frcd_pasid_present(data);
guest_addr = dmar_readq(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN);
guest_addr = dma_frcd_page_addr(guest_addr);
@@ -1688,7 +1755,9 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
if (!ratelimited)
+ /* Using pasid -1 if pasid is not present */
dmar_fault_do_one(iommu, type, fault_reason,
+ pasid_present ? pasid : -1,
source_id, guest_addr);
fault_index++;
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index b0c1e5f9daae..9c94e16fb127 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -566,7 +566,7 @@ static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
static const struct iommu_ops exynos_iommu_ops;
-static int __init exynos_sysmmu_probe(struct platform_device *pdev)
+static int exynos_sysmmu_probe(struct platform_device *pdev)
{
int irq, ret;
struct device *dev = &pdev->dev;
@@ -583,10 +583,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
return PTR_ERR(data->sfrbase);
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(dev, "Unable to find IRQ resource\n");
+ if (irq <= 0)
return irq;
- }
ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0,
dev_name(dev), data);
@@ -1130,7 +1128,8 @@ static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *domain
}
static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain,
- unsigned long l_iova, size_t size)
+ unsigned long l_iova, size_t size,
+ struct iommu_iotlb_gather *gather)
{
struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain);
sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
diff --git a/drivers/iommu/intel-iommu-debugfs.c b/drivers/iommu/intel-iommu-debugfs.c
index 73a552914455..471f05d452e0 100644
--- a/drivers/iommu/intel-iommu-debugfs.c
+++ b/drivers/iommu/intel-iommu-debugfs.c
@@ -162,9 +162,9 @@ static inline void print_tbl_walk(struct seq_file *m)
(u64)0, (u64)0, (u64)0);
else
seq_printf(m, "%-6d\t0x%016llx:0x%016llx:0x%016llx\n",
- tbl_wlk->pasid, tbl_wlk->pasid_tbl_entry->val[0],
+ tbl_wlk->pasid, tbl_wlk->pasid_tbl_entry->val[2],
tbl_wlk->pasid_tbl_entry->val[1],
- tbl_wlk->pasid_tbl_entry->val[2]);
+ tbl_wlk->pasid_tbl_entry->val[0]);
}
static void pasid_tbl_walk(struct seq_file *m, struct pasid_entry *tbl_entry,
@@ -235,7 +235,7 @@ static void ctx_tbl_walk(struct seq_file *m, struct intel_iommu *iommu, u16 bus)
tbl_wlk.ctx_entry = context;
m->private = &tbl_wlk;
- if (pasid_supported(iommu) && is_pasid_enabled(context)) {
+ if (dmar_readq(iommu->reg + DMAR_RTADDR_REG) & DMA_RTADDR_SMT) {
pasid_dir_ptr = context->lo & VTD_PAGE_MASK;
pasid_dir_size = get_pasid_dir_size(context);
pasid_dir_walk(m, pasid_dir_ptr, pasid_dir_size);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index ac4172c02244..87de0b975672 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -41,9 +41,11 @@
#include <linux/dma-direct.h>
#include <linux/crash_dump.h>
#include <linux/numa.h>
+#include <linux/swiotlb.h>
#include <asm/irq_remapping.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
+#include <trace/events/intel_iommu.h>
#include "irq_remapping.h"
#include "intel-pasid.h"
@@ -346,6 +348,8 @@ static int domain_detach_iommu(struct dmar_domain *domain,
static bool device_is_rmrr_locked(struct device *dev);
static int intel_iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
+static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
+ dma_addr_t iova);
#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
int dmar_disabled = 0;
@@ -362,6 +366,7 @@ static int dmar_forcedac;
static int intel_iommu_strict;
static int intel_iommu_superpage = 1;
static int iommu_identity_mapping;
+static int intel_no_bounce;
#define IDENTMAP_ALL 1
#define IDENTMAP_GFX 2
@@ -375,6 +380,9 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
static DEFINE_SPINLOCK(device_domain_lock);
static LIST_HEAD(device_domain_list);
+#define device_needs_bounce(d) (!intel_no_bounce && dev_is_pci(d) && \
+ to_pci_dev(d)->untrusted)
+
/*
* Iterate over elements in device_domain_list and call the specified
* callback @fn against each element.
@@ -457,6 +465,9 @@ static int __init intel_iommu_setup(char *str)
printk(KERN_INFO
"Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
intel_iommu_tboot_noforce = 1;
+ } else if (!strncmp(str, "nobounce", 8)) {
+ pr_info("Intel-IOMMU: No bounce buffer. This could expose security risks of DMA attacks\n");
+ intel_no_bounce = 1;
}
str += strcspn(str, ",");
@@ -1833,9 +1844,65 @@ static inline int guestwidth_to_adjustwidth(int gaw)
return agaw;
}
+static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
+ int guest_width)
+{
+ int adjust_width, agaw;
+ unsigned long sagaw;
+ int err;
+
+ init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
+
+ err = init_iova_flush_queue(&domain->iovad,
+ iommu_flush_iova, iova_entry_free);
+ if (err)
+ return err;
+
+ domain_reserve_special_ranges(domain);
+
+ /* calculate AGAW */
+ if (guest_width > cap_mgaw(iommu->cap))
+ guest_width = cap_mgaw(iommu->cap);
+ domain->gaw = guest_width;
+ adjust_width = guestwidth_to_adjustwidth(guest_width);
+ agaw = width_to_agaw(adjust_width);
+ sagaw = cap_sagaw(iommu->cap);
+ if (!test_bit(agaw, &sagaw)) {
+ /* hardware doesn't support it, choose a bigger one */
+ pr_debug("Hardware doesn't support agaw %d\n", agaw);
+ agaw = find_next_bit(&sagaw, 5, agaw);
+ if (agaw >= 5)
+ return -ENODEV;
+ }
+ domain->agaw = agaw;
+
+ if (ecap_coherent(iommu->ecap))
+ domain->iommu_coherency = 1;
+ else
+ domain->iommu_coherency = 0;
+
+ if (ecap_sc_support(iommu->ecap))
+ domain->iommu_snooping = 1;
+ else
+ domain->iommu_snooping = 0;
+
+ if (intel_iommu_superpage)
+ domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
+ else
+ domain->iommu_superpage = 0;
+
+ domain->nid = iommu->node;
+
+ /* always allocate the top pgd */
+ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+ if (!domain->pgd)
+ return -ENOMEM;
+ __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
+ return 0;
+}
+
static void domain_exit(struct dmar_domain *domain)
{
- struct page *freelist;
/* Remove associated devices and clear attached or cached domains */
domain_remove_dev_info(domain);
@@ -1843,9 +1910,12 @@ static void domain_exit(struct dmar_domain *domain)
/* destroy iovas */
put_iova_domain(&domain->iovad);
- freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+ if (domain->pgd) {
+ struct page *freelist;
- dma_free_pagelist(freelist);
+ freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+ dma_free_pagelist(freelist);
+ }
free_domain_mem(domain);
}
@@ -2513,31 +2583,6 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
return 0;
}
-static int domain_init(struct dmar_domain *domain, int guest_width)
-{
- int adjust_width;
-
- init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
- domain_reserve_special_ranges(domain);
-
- /* calculate AGAW */
- domain->gaw = guest_width;
- adjust_width = guestwidth_to_adjustwidth(guest_width);
- domain->agaw = width_to_agaw(adjust_width);
-
- domain->iommu_coherency = 0;
- domain->iommu_snooping = 0;
- domain->iommu_superpage = 0;
- domain->max_addr = 0;
-
- /* always allocate the top pgd */
- domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
- if (!domain->pgd)
- return -ENOMEM;
- domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
- return 0;
-}
-
static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
{
struct device_domain_info *info;
@@ -2575,19 +2620,11 @@ static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
domain = alloc_domain(0);
if (!domain)
return NULL;
-
- if (domain_init(domain, gaw)) {
+ if (domain_init(domain, iommu, gaw)) {
domain_exit(domain);
return NULL;
}
- if (init_iova_flush_queue(&domain->iovad,
- iommu_flush_iova,
- iova_entry_free)) {
- pr_warn("iova flush queue initialization failed\n");
- intel_iommu_strict = 1;
- }
-
out:
return domain;
}
@@ -2692,6 +2729,8 @@ static int domain_prepare_identity_map(struct device *dev,
return iommu_domain_identity_map(domain, start, end);
}
+static int md_domain_init(struct dmar_domain *domain, int guest_width);
+
static int __init si_domain_init(int hw)
{
struct dmar_rmrr_unit *rmrr;
@@ -2702,7 +2741,7 @@ static int __init si_domain_init(int hw)
if (!si_domain)
return -EFAULT;
- if (domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+ if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
domain_exit(si_domain);
return -EFAULT;
}
@@ -3268,7 +3307,7 @@ static int __init init_dmars(void)
iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
}
- if (iommu_pass_through)
+ if (iommu_default_passthrough())
iommu_identity_mapping |= IDENTMAP_ALL;
#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
@@ -3450,6 +3489,7 @@ static bool iommu_need_mapping(struct device *dev)
dmar_domain = to_dmar_domain(domain);
dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
}
+ dmar_remove_one_dev_info(dev);
get_private_domain_for_dev(dev);
}
@@ -3505,6 +3545,9 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
start_paddr += paddr & ~PAGE_MASK;
+
+ trace_map_single(dev, start_paddr, paddr, size << VTD_PAGE_SHIFT);
+
return start_paddr;
error:
@@ -3560,11 +3603,9 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
if (dev_is_pci(dev))
pdev = to_pci_dev(dev);
- dev_dbg(dev, "Device unmapping: pfn %lx-%lx\n", start_pfn, last_pfn);
-
freelist = domain_unmap(domain, start_pfn, last_pfn);
-
- if (intel_iommu_strict || (pdev && pdev->untrusted)) {
+ if (intel_iommu_strict || (pdev && pdev->untrusted) ||
+ !has_iova_flush_queue(&domain->iovad)) {
iommu_flush_iotlb_psi(iommu, domain, start_pfn,
nrpages, !freelist, 0);
/* free iova */
@@ -3578,6 +3619,8 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
* cpu used up by the iotlb flush operation...
*/
}
+
+ trace_unmap_single(dev, dev_addr, size);
}
static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
@@ -3668,6 +3711,8 @@ static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
}
intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
+
+ trace_unmap_sg(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
}
static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
@@ -3724,6 +3769,9 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
return 0;
}
+ trace_map_sg(dev, iova_pfn << PAGE_SHIFT,
+ sg_phys(sglist), size << VTD_PAGE_SHIFT);
+
return nelems;
}
@@ -3739,6 +3787,252 @@ static const struct dma_map_ops intel_dma_ops = {
.dma_supported = dma_direct_supported,
};
+static void
+bounce_sync_single(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, enum dma_sync_target target)
+{
+ struct dmar_domain *domain;
+ phys_addr_t tlb_addr;
+
+ domain = find_domain(dev);
+ if (WARN_ON(!domain))
+ return;
+
+ tlb_addr = intel_iommu_iova_to_phys(&domain->domain, addr);
+ if (is_swiotlb_buffer(tlb_addr))
+ swiotlb_tbl_sync_single(dev, tlb_addr, size, dir, target);
+}
+
+static dma_addr_t
+bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs,
+ u64 dma_mask)
+{
+ size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
+ struct dmar_domain *domain;
+ struct intel_iommu *iommu;
+ unsigned long iova_pfn;
+ unsigned long nrpages;
+ phys_addr_t tlb_addr;
+ int prot = 0;
+ int ret;
+
+ domain = find_domain(dev);
+ if (WARN_ON(dir == DMA_NONE || !domain))
+ return DMA_MAPPING_ERROR;
+
+ iommu = domain_get_iommu(domain);
+ if (WARN_ON(!iommu))
+ return DMA_MAPPING_ERROR;
+
+ nrpages = aligned_nrpages(0, size);
+ iova_pfn = intel_alloc_iova(dev, domain,
+ dma_to_mm_pfn(nrpages), dma_mask);
+ if (!iova_pfn)
+ return DMA_MAPPING_ERROR;
+
+ /*
+ * Check if DMAR supports zero-length reads on write only
+ * mappings..
+ */
+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL ||
+ !cap_zlr(iommu->cap))
+ prot |= DMA_PTE_READ;
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+ prot |= DMA_PTE_WRITE;
+
+ /*
+ * If both the physical buffer start address and size are
+ * page aligned, we don't need to use a bounce page.
+ */
+ if (!IS_ALIGNED(paddr | size, VTD_PAGE_SIZE)) {
+ tlb_addr = swiotlb_tbl_map_single(dev,
+ __phys_to_dma(dev, io_tlb_start),
+ paddr, size, aligned_size, dir, attrs);
+ if (tlb_addr == DMA_MAPPING_ERROR) {
+ goto swiotlb_error;
+ } else {
+ /* Cleanup the padding area. */
+ void *padding_start = phys_to_virt(tlb_addr);
+ size_t padding_size = aligned_size;
+
+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+ (dir == DMA_TO_DEVICE ||
+ dir == DMA_BIDIRECTIONAL)) {
+ padding_start += size;
+ padding_size -= size;
+ }
+
+ memset(padding_start, 0, padding_size);
+ }
+ } else {
+ tlb_addr = paddr;
+ }
+
+ ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
+ tlb_addr >> VTD_PAGE_SHIFT, nrpages, prot);
+ if (ret)
+ goto mapping_error;
+
+ trace_bounce_map_single(dev, iova_pfn << PAGE_SHIFT, paddr, size);
+
+ return (phys_addr_t)iova_pfn << PAGE_SHIFT;
+
+mapping_error:
+ if (is_swiotlb_buffer(tlb_addr))
+ swiotlb_tbl_unmap_single(dev, tlb_addr, size,
+ aligned_size, dir, attrs);
+swiotlb_error:
+ free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
+ dev_err(dev, "Device bounce map: %zx@%llx dir %d --- failed\n",
+ size, (unsigned long long)paddr, dir);
+
+ return DMA_MAPPING_ERROR;
+}
+
+static void
+bounce_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
+ struct dmar_domain *domain;
+ phys_addr_t tlb_addr;
+
+ domain = find_domain(dev);
+ if (WARN_ON(!domain))
+ return;
+
+ tlb_addr = intel_iommu_iova_to_phys(&domain->domain, dev_addr);
+ if (WARN_ON(!tlb_addr))
+ return;
+
+ intel_unmap(dev, dev_addr, size);
+ if (is_swiotlb_buffer(tlb_addr))
+ swiotlb_tbl_unmap_single(dev, tlb_addr, size,
+ aligned_size, dir, attrs);
+
+ trace_bounce_unmap_single(dev, dev_addr, size);
+}
+
+static dma_addr_t
+bounce_map_page(struct device *dev, struct page *page, unsigned long offset,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+ return bounce_map_single(dev, page_to_phys(page) + offset,
+ size, dir, attrs, *dev->dma_mask);
+}
+
+static dma_addr_t
+bounce_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ return bounce_map_single(dev, phys_addr, size,
+ dir, attrs, *dev->dma_mask);
+}
+
+static void
+bounce_unmap_page(struct device *dev, dma_addr_t dev_addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ bounce_unmap_single(dev, dev_addr, size, dir, attrs);
+}
+
+static void
+bounce_unmap_resource(struct device *dev, dma_addr_t dev_addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ bounce_unmap_single(dev, dev_addr, size, dir, attrs);
+}
+
+static void
+bounce_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ struct scatterlist *sg;
+ int i;
+
+ for_each_sg(sglist, sg, nelems, i)
+ bounce_unmap_page(dev, sg->dma_address,
+ sg_dma_len(sg), dir, attrs);
+}
+
+static int
+bounce_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ int i;
+ struct scatterlist *sg;
+
+ for_each_sg(sglist, sg, nelems, i) {
+ sg->dma_address = bounce_map_page(dev, sg_page(sg),
+ sg->offset, sg->length,
+ dir, attrs);
+ if (sg->dma_address == DMA_MAPPING_ERROR)
+ goto out_unmap;
+ sg_dma_len(sg) = sg->length;
+ }
+
+ return nelems;
+
+out_unmap:
+ bounce_unmap_sg(dev, sglist, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
+ return 0;
+}
+
+static void
+bounce_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+{
+ bounce_sync_single(dev, addr, size, dir, SYNC_FOR_CPU);
+}
+
+static void
+bounce_sync_single_for_device(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+{
+ bounce_sync_single(dev, addr, size, dir, SYNC_FOR_DEVICE);
+}
+
+static void
+bounce_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction dir)
+{
+ struct scatterlist *sg;
+ int i;
+
+ for_each_sg(sglist, sg, nelems, i)
+ bounce_sync_single(dev, sg_dma_address(sg),
+ sg_dma_len(sg), dir, SYNC_FOR_CPU);
+}
+
+static void
+bounce_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction dir)
+{
+ struct scatterlist *sg;
+ int i;
+
+ for_each_sg(sglist, sg, nelems, i)
+ bounce_sync_single(dev, sg_dma_address(sg),
+ sg_dma_len(sg), dir, SYNC_FOR_DEVICE);
+}
+
+static const struct dma_map_ops bounce_dma_ops = {
+ .alloc = intel_alloc_coherent,
+ .free = intel_free_coherent,
+ .map_sg = bounce_map_sg,
+ .unmap_sg = bounce_unmap_sg,
+ .map_page = bounce_map_page,
+ .unmap_page = bounce_unmap_page,
+ .sync_single_for_cpu = bounce_sync_single_for_cpu,
+ .sync_single_for_device = bounce_sync_single_for_device,
+ .sync_sg_for_cpu = bounce_sync_sg_for_cpu,
+ .sync_sg_for_device = bounce_sync_sg_for_device,
+ .map_resource = bounce_map_resource,
+ .unmap_resource = bounce_unmap_resource,
+ .dma_supported = dma_direct_supported,
+};
+
static inline int iommu_domain_cache_init(void)
{
int ret = 0;
@@ -4539,22 +4833,20 @@ const struct attribute_group *intel_iommu_groups[] = {
NULL,
};
-static int __init platform_optin_force_iommu(void)
+static inline bool has_untrusted_dev(void)
{
struct pci_dev *pdev = NULL;
- bool has_untrusted_dev = false;
- if (!dmar_platform_optin() || no_platform_optin)
- return 0;
+ for_each_pci_dev(pdev)
+ if (pdev->untrusted)
+ return true;
- for_each_pci_dev(pdev) {
- if (pdev->untrusted) {
- has_untrusted_dev = true;
- break;
- }
- }
+ return false;
+}
- if (!has_untrusted_dev)
+static int __init platform_optin_force_iommu(void)
+{
+ if (!dmar_platform_optin() || no_platform_optin || !has_untrusted_dev())
return 0;
if (no_iommu || dmar_disabled)
@@ -4568,9 +4860,6 @@ static int __init platform_optin_force_iommu(void)
iommu_identity_mapping |= IDENTMAP_ALL;
dmar_disabled = 0;
-#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
- swiotlb = 0;
-#endif
no_iommu = 0;
return 1;
@@ -4710,7 +4999,14 @@ int __init intel_iommu_init(void)
up_write(&dmar_global_lock);
#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
- swiotlb = 0;
+ /*
+ * If the system has no untrusted device or the user has decided
+ * to disable the bounce page mechanisms, we don't need swiotlb.
+ * Mark this and the pre-allocated bounce pages will be released
+ * later.
+ */
+ if (!has_untrusted_dev() || intel_no_bounce)
+ swiotlb = 0;
#endif
dma_ops = &intel_dma_ops;
@@ -4812,7 +5108,8 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
/* free the private domain */
if (domain->flags & DOMAIN_FLAG_LOSE_CHILDREN &&
- !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY))
+ !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+ list_empty(&domain->devices))
domain_exit(info->domain);
free_devinfo_mem(info);
@@ -4825,10 +5122,36 @@ static void dmar_remove_one_dev_info(struct device *dev)
spin_lock_irqsave(&device_domain_lock, flags);
info = dev->archdata.iommu;
- __dmar_remove_one_dev_info(info);
+ if (info)
+ __dmar_remove_one_dev_info(info);
spin_unlock_irqrestore(&device_domain_lock, flags);
}
+static int md_domain_init(struct dmar_domain *domain, int guest_width)
+{
+ int adjust_width;
+
+ init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
+ domain_reserve_special_ranges(domain);
+
+ /* calculate AGAW */
+ domain->gaw = guest_width;
+ adjust_width = guestwidth_to_adjustwidth(guest_width);
+ domain->agaw = width_to_agaw(adjust_width);
+
+ domain->iommu_coherency = 0;
+ domain->iommu_snooping = 0;
+ domain->iommu_superpage = 0;
+ domain->max_addr = 0;
+
+ /* always allocate the top pgd */
+ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+ if (!domain->pgd)
+ return -ENOMEM;
+ domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
+ return 0;
+}
+
static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
{
struct dmar_domain *dmar_domain;
@@ -4843,7 +5166,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
pr_err("Can't allocate dmar_domain\n");
return NULL;
}
- if (domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+ if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
pr_err("Domain initialization failed\n");
domain_exit(dmar_domain);
return NULL;
@@ -5147,7 +5470,8 @@ static int intel_iommu_map(struct iommu_domain *domain,
}
static size_t intel_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *gather)
{
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
struct page *freelist = NULL;
@@ -5278,6 +5602,7 @@ static int intel_iommu_add_device(struct device *dev)
if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
ret = iommu_request_dm_for_dev(dev);
if (ret) {
+ dmar_remove_one_dev_info(dev);
dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
domain_add_dev_info(si_domain, dev);
dev_info(dev,
@@ -5288,6 +5613,7 @@ static int intel_iommu_add_device(struct device *dev)
if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) {
ret = iommu_request_dma_domain_for_dev(dev);
if (ret) {
+ dmar_remove_one_dev_info(dev);
dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
if (!get_private_domain_for_dev(dev)) {
dev_warn(dev,
@@ -5301,6 +5627,11 @@ static int intel_iommu_add_device(struct device *dev)
}
}
+ if (device_needs_bounce(dev)) {
+ dev_info(dev, "Use Intel IOMMU bounce page dma_ops\n");
+ set_dma_ops(dev, &bounce_dma_ops);
+ }
+
return 0;
}
@@ -5313,9 +5644,14 @@ static void intel_iommu_remove_device(struct device *dev)
if (!iommu)
return;
+ dmar_remove_one_dev_info(dev);
+
iommu_group_remove_device(dev);
iommu_device_unlink(&iommu->iommu, dev);
+
+ if (device_needs_bounce(dev))
+ set_dma_ops(dev, NULL);
}
static void intel_iommu_get_resv_regions(struct device *device,
@@ -5629,20 +5965,46 @@ const struct iommu_ops intel_iommu_ops = {
.pgsize_bitmap = INTEL_IOMMU_PGSIZES,
};
-static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
+static void quirk_iommu_igfx(struct pci_dev *dev)
{
- /* G4x/GM45 integrated gfx dmar support is totally busted. */
pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
dmar_map_gfx = 0;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
+/* G4x/GM45 integrated gfx dmar support is totally busted. */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_igfx);
+
+/* Broadwell igfx malfunctions with dmar */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1606, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160B, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160E, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1602, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160A, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160D, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1616, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161B, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161E, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1612, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161A, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161D, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1626, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162B, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162E, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1622, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162A, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162D, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1636, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163B, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163E, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
static void quirk_iommu_rwbf(struct pci_dev *dev)
{
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 780de0caafe8..9b159132405d 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -100,24 +100,19 @@ int intel_svm_finish_prq(struct intel_iommu *iommu)
}
static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
- unsigned long address, unsigned long pages, int ih, int gl)
+ unsigned long address, unsigned long pages, int ih)
{
struct qi_desc desc;
- if (pages == -1) {
- /* For global kernel pages we have to flush them in *all* PASIDs
- * because that's the only option the hardware gives us. Despite
- * the fact that they are actually only accessible through one. */
- if (gl)
- desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
- QI_EIOTLB_DID(sdev->did) |
- QI_EIOTLB_GRAN(QI_GRAN_ALL_ALL) |
- QI_EIOTLB_TYPE;
- else
- desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
- QI_EIOTLB_DID(sdev->did) |
- QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
- QI_EIOTLB_TYPE;
+ /*
+ * Do PASID granu IOTLB invalidation if page selective capability is
+ * not available.
+ */
+ if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+ desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
+ QI_EIOTLB_DID(sdev->did) |
+ QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
+ QI_EIOTLB_TYPE;
desc.qw1 = 0;
} else {
int mask = ilog2(__roundup_pow_of_two(pages));
@@ -127,7 +122,6 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
QI_EIOTLB_GRAN(QI_GRAN_PSI_PASID) |
QI_EIOTLB_TYPE;
desc.qw1 = QI_EIOTLB_ADDR(address) |
- QI_EIOTLB_GL(gl) |
QI_EIOTLB_IH(ih) |
QI_EIOTLB_AM(mask);
}
@@ -162,13 +156,13 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
}
static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
- unsigned long pages, int ih, int gl)
+ unsigned long pages, int ih)
{
struct intel_svm_dev *sdev;
rcu_read_lock();
list_for_each_entry_rcu(sdev, &svm->devs, list)
- intel_flush_svm_range_dev(svm, sdev, address, pages, ih, gl);
+ intel_flush_svm_range_dev(svm, sdev, address, pages, ih);
rcu_read_unlock();
}
@@ -180,7 +174,7 @@ static void intel_invalidate_range(struct mmu_notifier *mn,
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
intel_flush_svm_range(svm, start,
- (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0, 0);
+ (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0);
}
static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
@@ -203,7 +197,7 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
rcu_read_lock();
list_for_each_entry_rcu(sdev, &svm->devs, list) {
intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid);
- intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+ intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
}
rcu_read_unlock();
@@ -425,7 +419,7 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
* large and has to be physically contiguous. So it's
* hard to be as defensive as we might like. */
intel_pasid_tear_down_entry(iommu, dev, svm->pasid);
- intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+ intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
kfree_rcu(sdev, rcu);
if (list_empty(&svm->devs)) {
diff --git a/drivers/iommu/intel-trace.c b/drivers/iommu/intel-trace.c
new file mode 100644
index 000000000000..bfb6a6e37a88
--- /dev/null
+++ b/drivers/iommu/intel-trace.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel IOMMU trace support
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_iommu.h>
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 4786ca061e31..81e43c1df7ec 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -376,13 +376,13 @@ static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque)
{
struct set_msi_sid_data *data = opaque;
+ if (data->count == 0 || PCI_BUS_NUM(alias) == PCI_BUS_NUM(data->alias))
+ data->busmatch_count++;
+
data->pdev = pdev;
data->alias = alias;
data->count++;
- if (PCI_BUS_NUM(alias) == pdev->bus->number)
- data->busmatch_count++;
-
return 0;
}
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 0fc8dfab2abf..4cb394937700 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -112,7 +112,9 @@
#define ARM_V7S_TEX_MASK 0x7
#define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)
-#define ARM_V7S_ATTR_MTK_4GB BIT(9) /* MTK extend it for 4GB mode */
+/* MediaTek extend the two bits for PA 32bit/33bit */
+#define ARM_V7S_ATTR_MTK_PA_BIT32 BIT(9)
+#define ARM_V7S_ATTR_MTK_PA_BIT33 BIT(4)
/* *well, except for TEX on level 2 large pages, of course :( */
#define ARM_V7S_CONT_PAGE_TEX_SHIFT 6
@@ -169,18 +171,62 @@ struct arm_v7s_io_pgtable {
spinlock_t split_lock;
};
+static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl);
+
static dma_addr_t __arm_v7s_dma_addr(void *pages)
{
return (dma_addr_t)virt_to_phys(pages);
}
-static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl)
+static bool arm_v7s_is_mtk_enabled(struct io_pgtable_cfg *cfg)
+{
+ return IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) &&
+ (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_EXT);
+}
+
+static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
+ struct io_pgtable_cfg *cfg)
+{
+ arm_v7s_iopte pte = paddr & ARM_V7S_LVL_MASK(lvl);
+
+ if (!arm_v7s_is_mtk_enabled(cfg))
+ return pte;
+
+ if (paddr & BIT_ULL(32))
+ pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
+ if (paddr & BIT_ULL(33))
+ pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
+ return pte;
+}
+
+static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
+ struct io_pgtable_cfg *cfg)
{
+ arm_v7s_iopte mask;
+ phys_addr_t paddr;
+
if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
- pte &= ARM_V7S_TABLE_MASK;
+ mask = ARM_V7S_TABLE_MASK;
+ else if (arm_v7s_pte_is_cont(pte, lvl))
+ mask = ARM_V7S_LVL_MASK(lvl) * ARM_V7S_CONT_PAGES;
else
- pte &= ARM_V7S_LVL_MASK(lvl);
- return phys_to_virt(pte);
+ mask = ARM_V7S_LVL_MASK(lvl);
+
+ paddr = pte & mask;
+ if (!arm_v7s_is_mtk_enabled(cfg))
+ return paddr;
+
+ if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
+ paddr |= BIT_ULL(32);
+ if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
+ paddr |= BIT_ULL(33);
+ return paddr;
+}
+
+static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
+ struct arm_v7s_io_pgtable *data)
+{
+ return phys_to_virt(iopte_to_paddr(pte, lvl, &data->iop.cfg));
}
static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
@@ -295,9 +341,6 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS))
pte |= ARM_V7S_ATTR_NS_SECTION;
- if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)
- pte |= ARM_V7S_ATTR_MTK_4GB;
-
return pte;
}
@@ -362,7 +405,8 @@ static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl)
return false;
}
-static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *, unsigned long,
+static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *,
+ struct iommu_iotlb_gather *, unsigned long,
size_t, int, arm_v7s_iopte *);
static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
@@ -383,7 +427,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
size_t sz = ARM_V7S_BLOCK_SIZE(lvl);
tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl);
- if (WARN_ON(__arm_v7s_unmap(data, iova + i * sz,
+ if (WARN_ON(__arm_v7s_unmap(data, NULL, iova + i * sz,
sz, lvl, tblp) != sz))
return -EINVAL;
} else if (ptep[i]) {
@@ -396,7 +440,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
if (num_entries > 1)
pte = arm_v7s_pte_to_cont(pte, lvl);
- pte |= paddr & ARM_V7S_LVL_MASK(lvl);
+ pte |= paddr_to_iopte(paddr, lvl, cfg);
__arm_v7s_set_pte(ptep, pte, num_entries, cfg);
return 0;
@@ -462,7 +506,7 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
}
if (ARM_V7S_PTE_IS_TABLE(pte, lvl)) {
- cptep = iopte_deref(pte, lvl);
+ cptep = iopte_deref(pte, lvl, data);
} else if (pte) {
/* We require an unmap first */
WARN_ON(!selftest_running);
@@ -484,7 +528,8 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;
- if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
+ if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) ||
+ paddr >= (1ULL << data->iop.cfg.oas)))
return -ERANGE;
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
@@ -493,9 +538,8 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
* a chance for anything to kick off a table walk for the new iova.
*/
if (iop->cfg.quirks & IO_PGTABLE_QUIRK_TLBI_ON_MAP) {
- io_pgtable_tlb_add_flush(iop, iova, size,
- ARM_V7S_BLOCK_SIZE(2), false);
- io_pgtable_tlb_sync(iop);
+ io_pgtable_tlb_flush_walk(iop, iova, size,
+ ARM_V7S_BLOCK_SIZE(2));
} else {
wmb();
}
@@ -512,7 +556,8 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
arm_v7s_iopte pte = data->pgd[i];
if (ARM_V7S_PTE_IS_TABLE(pte, 1))
- __arm_v7s_free_table(iopte_deref(pte, 1), 2, data);
+ __arm_v7s_free_table(iopte_deref(pte, 1, data),
+ 2, data);
}
__arm_v7s_free_table(data->pgd, 1, data);
kmem_cache_destroy(data->l2_tables);
@@ -541,12 +586,12 @@ static arm_v7s_iopte arm_v7s_split_cont(struct arm_v7s_io_pgtable *data,
__arm_v7s_pte_sync(ptep, ARM_V7S_CONT_PAGES, &iop->cfg);
size *= ARM_V7S_CONT_PAGES;
- io_pgtable_tlb_add_flush(iop, iova, size, size, true);
- io_pgtable_tlb_sync(iop);
+ io_pgtable_tlb_flush_leaf(iop, iova, size, size);
return pte;
}
static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size,
arm_v7s_iopte blk_pte,
arm_v7s_iopte *ptep)
@@ -582,16 +627,16 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
if (!ARM_V7S_PTE_IS_TABLE(pte, 1))
return 0;
- tablep = iopte_deref(pte, 1);
- return __arm_v7s_unmap(data, iova, size, 2, tablep);
+ tablep = iopte_deref(pte, 1, data);
+ return __arm_v7s_unmap(data, gather, iova, size, 2, tablep);
}
- io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true);
- io_pgtable_tlb_sync(&data->iop);
+ io_pgtable_tlb_add_page(&data->iop, gather, iova, size);
return size;
}
static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size, int lvl,
arm_v7s_iopte *ptep)
{
@@ -638,10 +683,9 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
for (i = 0; i < num_entries; i++) {
if (ARM_V7S_PTE_IS_TABLE(pte[i], lvl)) {
/* Also flush any partial walks */
- io_pgtable_tlb_add_flush(iop, iova, blk_size,
- ARM_V7S_BLOCK_SIZE(lvl + 1), false);
- io_pgtable_tlb_sync(iop);
- ptep = iopte_deref(pte[i], lvl);
+ io_pgtable_tlb_flush_walk(iop, iova, blk_size,
+ ARM_V7S_BLOCK_SIZE(lvl + 1));
+ ptep = iopte_deref(pte[i], lvl, data);
__arm_v7s_free_table(ptep, lvl + 1, data);
} else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) {
/*
@@ -651,8 +695,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
*/
smp_wmb();
} else {
- io_pgtable_tlb_add_flush(iop, iova, blk_size,
- blk_size, true);
+ io_pgtable_tlb_add_page(iop, gather, iova, blk_size);
}
iova += blk_size;
}
@@ -662,23 +705,24 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
* Insert a table at the next level to map the old region,
* minus the part we want to unmap
*/
- return arm_v7s_split_blk_unmap(data, iova, size, pte[0], ptep);
+ return arm_v7s_split_blk_unmap(data, gather, iova, size, pte[0],
+ ptep);
}
/* Keep on walkin' */
- ptep = iopte_deref(pte[0], lvl);
- return __arm_v7s_unmap(data, iova, size, lvl + 1, ptep);
+ ptep = iopte_deref(pte[0], lvl, data);
+ return __arm_v7s_unmap(data, gather, iova, size, lvl + 1, ptep);
}
static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
if (WARN_ON(upper_32_bits(iova)))
return 0;
- return __arm_v7s_unmap(data, iova, size, 1, data->pgd);
+ return __arm_v7s_unmap(data, gather, iova, size, 1, data->pgd);
}
static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
@@ -692,7 +736,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
do {
ptep += ARM_V7S_LVL_IDX(iova, ++lvl);
pte = READ_ONCE(*ptep);
- ptep = iopte_deref(pte, lvl);
+ ptep = iopte_deref(pte, lvl, data);
} while (ARM_V7S_PTE_IS_TABLE(pte, lvl));
if (!ARM_V7S_PTE_IS_VALID(pte))
@@ -701,7 +745,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
mask = ARM_V7S_LVL_MASK(lvl);
if (arm_v7s_pte_is_cont(pte, lvl))
mask *= ARM_V7S_CONT_PAGES;
- return (pte & mask) | (iova & ~mask);
+ return iopte_to_paddr(pte, lvl, &data->iop.cfg) | (iova & ~mask);
}
static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
@@ -709,18 +753,21 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
{
struct arm_v7s_io_pgtable *data;
- if (cfg->ias > ARM_V7S_ADDR_BITS || cfg->oas > ARM_V7S_ADDR_BITS)
+ if (cfg->ias > ARM_V7S_ADDR_BITS)
+ return NULL;
+
+ if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
return NULL;
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_NO_PERMS |
IO_PGTABLE_QUIRK_TLBI_ON_MAP |
- IO_PGTABLE_QUIRK_ARM_MTK_4GB |
+ IO_PGTABLE_QUIRK_ARM_MTK_EXT |
IO_PGTABLE_QUIRK_NON_STRICT))
return NULL;
/* If ARM_MTK_4GB is enabled, the NO_PERMS is also expected. */
- if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB &&
+ if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_EXT &&
!(cfg->quirks & IO_PGTABLE_QUIRK_NO_PERMS))
return NULL;
@@ -806,22 +853,24 @@ static void dummy_tlb_flush_all(void *cookie)
WARN_ON(cookie != cfg_cookie);
}
-static void dummy_tlb_add_flush(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule,
+ void *cookie)
{
WARN_ON(cookie != cfg_cookie);
WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
}
-static void dummy_tlb_sync(void *cookie)
+static void dummy_tlb_add_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule, void *cookie)
{
- WARN_ON(cookie != cfg_cookie);
+ dummy_tlb_flush(iova, granule, granule, cookie);
}
-static const struct iommu_gather_ops dummy_tlb_ops = {
+static const struct iommu_flush_ops dummy_tlb_ops = {
.tlb_flush_all = dummy_tlb_flush_all,
- .tlb_add_flush = dummy_tlb_add_flush,
- .tlb_sync = dummy_tlb_sync,
+ .tlb_flush_walk = dummy_tlb_flush,
+ .tlb_flush_leaf = dummy_tlb_flush,
+ .tlb_add_page = dummy_tlb_add_page,
};
#define __FAIL(ops) ({ \
@@ -896,7 +945,7 @@ static int __init arm_v7s_do_selftests(void)
size = 1UL << __ffs(cfg.pgsize_bitmap);
while (i < loopnr) {
iova_start = i * SZ_16M;
- if (ops->unmap(ops, iova_start + size, size) != size)
+ if (ops->unmap(ops, iova_start + size, size, NULL) != size)
return __FAIL(ops);
/* Remap of partial unmap */
@@ -914,7 +963,7 @@ static int __init arm_v7s_do_selftests(void)
for_each_set_bit(i, &cfg.pgsize_bitmap, BITS_PER_LONG) {
size = 1UL << i;
- if (ops->unmap(ops, iova, size) != size)
+ if (ops->unmap(ops, iova, size, NULL) != size)
return __FAIL(ops);
if (ops->iova_to_phys(ops, iova + 42))
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 161a7d56264d..4c91359057c5 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -12,7 +12,6 @@
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/io-pgtable.h>
-#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -290,6 +289,7 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
}
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size, int lvl,
arm_lpae_iopte *ptep);
@@ -335,8 +335,10 @@ static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
tblp = ptep - ARM_LPAE_LVL_IDX(iova, lvl, data);
- if (WARN_ON(__arm_lpae_unmap(data, iova, sz, lvl, tblp) != sz))
+ if (__arm_lpae_unmap(data, NULL, iova, sz, lvl, tblp) != sz) {
+ WARN_ON(1);
return -EINVAL;
+ }
}
__arm_lpae_init_pte(data, paddr, prot, lvl, ptep);
@@ -537,6 +539,7 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
}
static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size,
arm_lpae_iopte blk_pte, int lvl,
arm_lpae_iopte *ptep)
@@ -582,15 +585,15 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
tablep = iopte_deref(pte, data);
} else if (unmap_idx >= 0) {
- io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true);
- io_pgtable_tlb_sync(&data->iop);
+ io_pgtable_tlb_add_page(&data->iop, gather, iova, size);
return size;
}
- return __arm_lpae_unmap(data, iova, size, lvl, tablep);
+ return __arm_lpae_unmap(data, gather, iova, size, lvl, tablep);
}
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size, int lvl,
arm_lpae_iopte *ptep)
{
@@ -612,9 +615,8 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
if (!iopte_leaf(pte, lvl, iop->fmt)) {
/* Also flush any partial walks */
- io_pgtable_tlb_add_flush(iop, iova, size,
- ARM_LPAE_GRANULE(data), false);
- io_pgtable_tlb_sync(iop);
+ io_pgtable_tlb_flush_walk(iop, iova, size,
+ ARM_LPAE_GRANULE(data));
ptep = iopte_deref(pte, data);
__arm_lpae_free_pgtable(data, lvl + 1, ptep);
} else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) {
@@ -625,7 +627,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
*/
smp_wmb();
} else {
- io_pgtable_tlb_add_flush(iop, iova, size, size, true);
+ io_pgtable_tlb_add_page(iop, gather, iova, size);
}
return size;
@@ -634,17 +636,17 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
* Insert a table at the next level to map the old region,
* minus the part we want to unmap
*/
- return arm_lpae_split_blk_unmap(data, iova, size, pte,
+ return arm_lpae_split_blk_unmap(data, gather, iova, size, pte,
lvl + 1, ptep);
}
/* Keep on walkin' */
ptep = iopte_deref(pte, data);
- return __arm_lpae_unmap(data, iova, size, lvl + 1, ptep);
+ return __arm_lpae_unmap(data, gather, iova, size, lvl + 1, ptep);
}
static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
arm_lpae_iopte *ptep = data->pgd;
@@ -653,7 +655,7 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
return 0;
- return __arm_lpae_unmap(data, iova, size, lvl, ptep);
+ return __arm_lpae_unmap(data, gather, iova, size, lvl, ptep);
}
static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
@@ -1070,22 +1072,24 @@ static void dummy_tlb_flush_all(void *cookie)
WARN_ON(cookie != cfg_cookie);
}
-static void dummy_tlb_add_flush(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule,
+ void *cookie)
{
WARN_ON(cookie != cfg_cookie);
WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
}
-static void dummy_tlb_sync(void *cookie)
+static void dummy_tlb_add_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule, void *cookie)
{
- WARN_ON(cookie != cfg_cookie);
+ dummy_tlb_flush(iova, granule, granule, cookie);
}
-static const struct iommu_gather_ops dummy_tlb_ops __initconst = {
+static const struct iommu_flush_ops dummy_tlb_ops __initconst = {
.tlb_flush_all = dummy_tlb_flush_all,
- .tlb_add_flush = dummy_tlb_add_flush,
- .tlb_sync = dummy_tlb_sync,
+ .tlb_flush_walk = dummy_tlb_flush,
+ .tlb_flush_leaf = dummy_tlb_flush,
+ .tlb_add_page = dummy_tlb_add_page,
};
static void __init arm_lpae_dump_ops(struct io_pgtable_ops *ops)
@@ -1168,7 +1172,7 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
/* Partial unmap */
size = 1UL << __ffs(cfg->pgsize_bitmap);
- if (ops->unmap(ops, SZ_1G + size, size) != size)
+ if (ops->unmap(ops, SZ_1G + size, size, NULL) != size)
return __FAIL(ops, i);
/* Remap of partial unmap */
@@ -1183,7 +1187,7 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
size = 1UL << j;
- if (ops->unmap(ops, iova, size) != size)
+ if (ops->unmap(ops, iova, size, NULL) != size)
return __FAIL(ops, i);
if (ops->iova_to_phys(ops, iova + 42))
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0c674d80c37f..d658c7c6a2ab 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -26,12 +26,10 @@
static struct kset *iommu_group_kset;
static DEFINE_IDA(iommu_group_ida);
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;
-#else
-static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
-#endif
+
+static unsigned int iommu_def_domain_type __read_mostly;
static bool iommu_dma_strict __read_mostly = true;
+static u32 iommu_cmd_line __read_mostly;
struct iommu_group {
struct kobject kobj;
@@ -68,6 +66,18 @@ static const char * const iommu_group_resv_type_string[] = {
[IOMMU_RESV_SW_MSI] = "msi",
};
+#define IOMMU_CMD_LINE_DMA_API BIT(0)
+
+static void iommu_set_cmd_line_dma_api(void)
+{
+ iommu_cmd_line |= IOMMU_CMD_LINE_DMA_API;
+}
+
+static bool iommu_cmd_line_dma_api(void)
+{
+ return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API);
+}
+
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
struct iommu_group_attribute iommu_group_attr_##_name = \
__ATTR(_name, _mode, _show, _store)
@@ -80,12 +90,55 @@ struct iommu_group_attribute iommu_group_attr_##_name = \
static LIST_HEAD(iommu_device_list);
static DEFINE_SPINLOCK(iommu_device_lock);
+/*
+ * Use a function instead of an array here because the domain-type is a
+ * bit-field, so an array would waste memory.
+ */
+static const char *iommu_domain_type_str(unsigned int t)
+{
+ switch (t) {
+ case IOMMU_DOMAIN_BLOCKED:
+ return "Blocked";
+ case IOMMU_DOMAIN_IDENTITY:
+ return "Passthrough";
+ case IOMMU_DOMAIN_UNMANAGED:
+ return "Unmanaged";
+ case IOMMU_DOMAIN_DMA:
+ return "Translated";
+ default:
+ return "Unknown";
+ }
+}
+
+static int __init iommu_subsys_init(void)
+{
+ bool cmd_line = iommu_cmd_line_dma_api();
+
+ if (!cmd_line) {
+ if (IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH))
+ iommu_set_default_passthrough(false);
+ else
+ iommu_set_default_translated(false);
+
+ if (iommu_default_passthrough() && mem_encrypt_active()) {
+ pr_info("Memory encryption detected - Disabling default IOMMU Passthrough\n");
+ iommu_set_default_translated(false);
+ }
+ }
+
+ pr_info("Default domain type: %s %s\n",
+ iommu_domain_type_str(iommu_def_domain_type),
+ cmd_line ? "(set via kernel command line)" : "");
+
+ return 0;
+}
+subsys_initcall(iommu_subsys_init);
+
int iommu_device_register(struct iommu_device *iommu)
{
spin_lock(&iommu_device_lock);
list_add_tail(&iommu->list, &iommu_device_list);
spin_unlock(&iommu_device_lock);
-
return 0;
}
@@ -165,7 +218,11 @@ static int __init iommu_set_def_domain_type(char *str)
if (ret)
return ret;
- iommu_def_domain_type = pt ? IOMMU_DOMAIN_IDENTITY : IOMMU_DOMAIN_DMA;
+ if (pt)
+ iommu_set_default_passthrough(true);
+ else
+ iommu_set_default_translated(true);
+
return 0;
}
early_param("iommu.passthrough", iommu_set_def_domain_type);
@@ -229,60 +286,58 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf)
* @new: new region to insert
* @regions: list of regions
*
- * The new element is sorted by address with respect to the other
- * regions of the same type. In case it overlaps with another
- * region of the same type, regions are merged. In case it
- * overlaps with another region of different type, regions are
- * not merged.
+ * Elements are sorted by start address and overlapping segments
+ * of the same type are merged.
*/
-static int iommu_insert_resv_region(struct iommu_resv_region *new,
- struct list_head *regions)
+int iommu_insert_resv_region(struct iommu_resv_region *new,
+ struct list_head *regions)
{
- struct iommu_resv_region *region;
- phys_addr_t start = new->start;
- phys_addr_t end = new->start + new->length - 1;
- struct list_head *pos = regions->next;
-
- while (pos != regions) {
- struct iommu_resv_region *entry =
- list_entry(pos, struct iommu_resv_region, list);
- phys_addr_t a = entry->start;
- phys_addr_t b = entry->start + entry->length - 1;
- int type = entry->type;
-
- if (end < a) {
- goto insert;
- } else if (start > b) {
- pos = pos->next;
- } else if ((start >= a) && (end <= b)) {
- if (new->type == type)
- return 0;
- else
- pos = pos->next;
+ struct iommu_resv_region *iter, *tmp, *nr, *top;
+ LIST_HEAD(stack);
+
+ nr = iommu_alloc_resv_region(new->start, new->length,
+ new->prot, new->type);
+ if (!nr)
+ return -ENOMEM;
+
+ /* First add the new element based on start address sorting */
+ list_for_each_entry(iter, regions, list) {
+ if (nr->start < iter->start ||
+ (nr->start == iter->start && nr->type <= iter->type))
+ break;
+ }
+ list_add_tail(&nr->list, &iter->list);
+
+ /* Merge overlapping segments of type nr->type in @regions, if any */
+ list_for_each_entry_safe(iter, tmp, regions, list) {
+ phys_addr_t top_end, iter_end = iter->start + iter->length - 1;
+
+ /* no merge needed on elements of different types than @nr */
+ if (iter->type != nr->type) {
+ list_move_tail(&iter->list, &stack);
+ continue;
+ }
+
+ /* look for the last stack element of same type as @iter */
+ list_for_each_entry_reverse(top, &stack, list)
+ if (top->type == iter->type)
+ goto check_overlap;
+
+ list_move_tail(&iter->list, &stack);
+ continue;
+
+check_overlap:
+ top_end = top->start + top->length - 1;
+
+ if (iter->start > top_end + 1) {
+ list_move_tail(&iter->list, &stack);
} else {
- if (new->type == type) {
- phys_addr_t new_start = min(a, start);
- phys_addr_t new_end = max(b, end);
- int ret;
-
- list_del(&entry->list);
- entry->start = new_start;
- entry->length = new_end - new_start + 1;
- ret = iommu_insert_resv_region(entry, regions);
- kfree(entry);
- return ret;
- } else {
- pos = pos->next;
- }
+ top->length = max(top_end, iter_end) - top->start + 1;
+ list_del(&iter->list);
+ kfree(iter);
}
}
-insert:
- region = iommu_alloc_resv_region(new->start, new->length,
- new->prot, new->type);
- if (!region)
- return -ENOMEM;
-
- list_add_tail(&region->list, pos);
+ list_splice(&stack, regions);
return 0;
}
@@ -1862,7 +1917,7 @@ EXPORT_SYMBOL_GPL(iommu_map);
static size_t __iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size,
- bool sync)
+ struct iommu_iotlb_gather *iotlb_gather)
{
const struct iommu_ops *ops = domain->ops;
size_t unmapped_page, unmapped = 0;
@@ -1899,13 +1954,10 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
while (unmapped < size) {
size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
- unmapped_page = ops->unmap(domain, iova, pgsize);
+ unmapped_page = ops->unmap(domain, iova, pgsize, iotlb_gather);
if (!unmapped_page)
break;
- if (sync && ops->iotlb_range_add)
- ops->iotlb_range_add(domain, iova, pgsize);
-
pr_debug("unmapped: iova 0x%lx size 0x%zx\n",
iova, unmapped_page);
@@ -1913,9 +1965,6 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
unmapped += unmapped_page;
}
- if (sync && ops->iotlb_sync)
- ops->iotlb_sync(domain);
-
trace_unmap(orig_iova, size, unmapped);
return unmapped;
}
@@ -1923,14 +1972,22 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
size_t iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size)
{
- return __iommu_unmap(domain, iova, size, true);
+ struct iommu_iotlb_gather iotlb_gather;
+ size_t ret;
+
+ iommu_iotlb_gather_init(&iotlb_gather);
+ ret = __iommu_unmap(domain, iova, size, &iotlb_gather);
+ iommu_tlb_sync(domain, &iotlb_gather);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(iommu_unmap);
size_t iommu_unmap_fast(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *iotlb_gather)
{
- return __iommu_unmap(domain, iova, size, false);
+ return __iommu_unmap(domain, iova, size, iotlb_gather);
}
EXPORT_SYMBOL_GPL(iommu_unmap_fast);
@@ -2143,7 +2200,6 @@ request_default_domain_for_dev(struct device *dev, unsigned long type)
mutex_lock(&group->mutex);
- /* Check if the default domain is already direct mapped */
ret = 0;
if (group->default_domain && group->default_domain->type == type)
goto out;
@@ -2153,7 +2209,6 @@ request_default_domain_for_dev(struct device *dev, unsigned long type)
if (iommu_group_device_count(group) != 1)
goto out;
- /* Allocate a direct mapped domain */
ret = -ENOMEM;
domain = __iommu_domain_alloc(dev->bus, type);
if (!domain)
@@ -2168,7 +2223,7 @@ request_default_domain_for_dev(struct device *dev, unsigned long type)
iommu_group_create_direct_mappings(group, dev);
- /* Make the direct mapped domain the default for this group */
+ /* Make the domain the default for this group */
if (group->default_domain)
iommu_domain_free(group->default_domain);
group->default_domain = domain;
@@ -2196,6 +2251,28 @@ int iommu_request_dma_domain_for_dev(struct device *dev)
return request_default_domain_for_dev(dev, IOMMU_DOMAIN_DMA);
}
+void iommu_set_default_passthrough(bool cmd_line)
+{
+ if (cmd_line)
+ iommu_set_cmd_line_dma_api();
+
+ iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;
+}
+
+void iommu_set_default_translated(bool cmd_line)
+{
+ if (cmd_line)
+ iommu_set_cmd_line_dma_api();
+
+ iommu_def_domain_type = IOMMU_DOMAIN_DMA;
+}
+
+bool iommu_default_passthrough(void)
+{
+ return iommu_def_domain_type == IOMMU_DOMAIN_IDENTITY;
+}
+EXPORT_SYMBOL_GPL(iommu_default_passthrough);
+
const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
{
const struct iommu_ops *ops = NULL;
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index d499b2621239..41c605b0058f 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -54,9 +54,14 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
}
EXPORT_SYMBOL_GPL(init_iova_domain);
+bool has_iova_flush_queue(struct iova_domain *iovad)
+{
+ return !!iovad->fq;
+}
+
static void free_iova_flush_queue(struct iova_domain *iovad)
{
- if (!iovad->fq)
+ if (!has_iova_flush_queue(iovad))
return;
if (timer_pending(&iovad->fq_timer))
@@ -74,13 +79,14 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
int init_iova_flush_queue(struct iova_domain *iovad,
iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
{
+ struct iova_fq __percpu *queue;
int cpu;
atomic64_set(&iovad->fq_flush_start_cnt, 0);
atomic64_set(&iovad->fq_flush_finish_cnt, 0);
- iovad->fq = alloc_percpu(struct iova_fq);
- if (!iovad->fq)
+ queue = alloc_percpu(struct iova_fq);
+ if (!queue)
return -ENOMEM;
iovad->flush_cb = flush_cb;
@@ -89,13 +95,17 @@ int init_iova_flush_queue(struct iova_domain *iovad,
for_each_possible_cpu(cpu) {
struct iova_fq *fq;
- fq = per_cpu_ptr(iovad->fq, cpu);
+ fq = per_cpu_ptr(queue, cpu);
fq->head = 0;
fq->tail = 0;
spin_lock_init(&fq->lock);
}
+ smp_wmb();
+
+ iovad->fq = queue;
+
timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
atomic_set(&iovad->fq_timer_on, 0);
@@ -127,8 +137,9 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
struct iova *cached_iova;
cached_iova = rb_entry(iovad->cached32_node, struct iova, node);
- if (free->pfn_hi < iovad->dma_32bit_pfn &&
- free->pfn_lo >= cached_iova->pfn_lo) {
+ if (free == cached_iova ||
+ (free->pfn_hi < iovad->dma_32bit_pfn &&
+ free->pfn_lo >= cached_iova->pfn_lo)) {
iovad->cached32_node = rb_next(&free->node);
iovad->max32_alloc_size = iovad->dma_32bit_pfn;
}
@@ -566,7 +577,9 @@ void queue_iova(struct iova_domain *iovad,
spin_unlock_irqrestore(&fq->lock, flags);
- if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
+ /* Avoid false sharing as much as possible. */
+ if (!atomic_read(&iovad->fq_timer_on) &&
+ !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1))
mod_timer(&iovad->fq_timer,
jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
}
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index ad0098c0c87c..9da8309f7170 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -49,6 +49,7 @@ struct ipmmu_features {
bool setup_imbuscr;
bool twobit_imttbcr_sl0;
bool reserved_context;
+ bool cache_snoop;
};
struct ipmmu_vmsa_device {
@@ -115,45 +116,44 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
#define IMTTBCR 0x0008
#define IMTTBCR_EAE (1 << 31)
#define IMTTBCR_PMB (1 << 30)
-#define IMTTBCR_SH1_NON_SHAREABLE (0 << 28)
-#define IMTTBCR_SH1_OUTER_SHAREABLE (2 << 28)
-#define IMTTBCR_SH1_INNER_SHAREABLE (3 << 28)
-#define IMTTBCR_SH1_MASK (3 << 28)
-#define IMTTBCR_ORGN1_NC (0 << 26)
-#define IMTTBCR_ORGN1_WB_WA (1 << 26)
-#define IMTTBCR_ORGN1_WT (2 << 26)
-#define IMTTBCR_ORGN1_WB (3 << 26)
-#define IMTTBCR_ORGN1_MASK (3 << 26)
-#define IMTTBCR_IRGN1_NC (0 << 24)
-#define IMTTBCR_IRGN1_WB_WA (1 << 24)
-#define IMTTBCR_IRGN1_WT (2 << 24)
-#define IMTTBCR_IRGN1_WB (3 << 24)
-#define IMTTBCR_IRGN1_MASK (3 << 24)
+#define IMTTBCR_SH1_NON_SHAREABLE (0 << 28) /* R-Car Gen2 only */
+#define IMTTBCR_SH1_OUTER_SHAREABLE (2 << 28) /* R-Car Gen2 only */
+#define IMTTBCR_SH1_INNER_SHAREABLE (3 << 28) /* R-Car Gen2 only */
+#define IMTTBCR_SH1_MASK (3 << 28) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN1_NC (0 << 26) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN1_WB_WA (1 << 26) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN1_WT (2 << 26) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN1_WB (3 << 26) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN1_MASK (3 << 26) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN1_NC (0 << 24) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN1_WB_WA (1 << 24) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN1_WT (2 << 24) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN1_WB (3 << 24) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN1_MASK (3 << 24) /* R-Car Gen2 only */
#define IMTTBCR_TSZ1_MASK (7 << 16)
#define IMTTBCR_TSZ1_SHIFT 16
-#define IMTTBCR_SH0_NON_SHAREABLE (0 << 12)
-#define IMTTBCR_SH0_OUTER_SHAREABLE (2 << 12)
-#define IMTTBCR_SH0_INNER_SHAREABLE (3 << 12)
-#define IMTTBCR_SH0_MASK (3 << 12)
-#define IMTTBCR_ORGN0_NC (0 << 10)
-#define IMTTBCR_ORGN0_WB_WA (1 << 10)
-#define IMTTBCR_ORGN0_WT (2 << 10)
-#define IMTTBCR_ORGN0_WB (3 << 10)
-#define IMTTBCR_ORGN0_MASK (3 << 10)
-#define IMTTBCR_IRGN0_NC (0 << 8)
-#define IMTTBCR_IRGN0_WB_WA (1 << 8)
-#define IMTTBCR_IRGN0_WT (2 << 8)
-#define IMTTBCR_IRGN0_WB (3 << 8)
-#define IMTTBCR_IRGN0_MASK (3 << 8)
+#define IMTTBCR_SH0_NON_SHAREABLE (0 << 12) /* R-Car Gen2 only */
+#define IMTTBCR_SH0_OUTER_SHAREABLE (2 << 12) /* R-Car Gen2 only */
+#define IMTTBCR_SH0_INNER_SHAREABLE (3 << 12) /* R-Car Gen2 only */
+#define IMTTBCR_SH0_MASK (3 << 12) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN0_NC (0 << 10) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN0_WB_WA (1 << 10) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN0_WT (2 << 10) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN0_WB (3 << 10) /* R-Car Gen2 only */
+#define IMTTBCR_ORGN0_MASK (3 << 10) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN0_NC (0 << 8) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN0_WB_WA (1 << 8) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN0_WT (2 << 8) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN0_WB (3 << 8) /* R-Car Gen2 only */
+#define IMTTBCR_IRGN0_MASK (3 << 8) /* R-Car Gen2 only */
+#define IMTTBCR_SL0_TWOBIT_LVL_3 (0 << 6) /* R-Car Gen3 only */
+#define IMTTBCR_SL0_TWOBIT_LVL_2 (1 << 6) /* R-Car Gen3 only */
+#define IMTTBCR_SL0_TWOBIT_LVL_1 (2 << 6) /* R-Car Gen3 only */
#define IMTTBCR_SL0_LVL_2 (0 << 4)
#define IMTTBCR_SL0_LVL_1 (1 << 4)
#define IMTTBCR_TSZ0_MASK (7 << 0)
#define IMTTBCR_TSZ0_SHIFT O
-#define IMTTBCR_SL0_TWOBIT_LVL_3 (0 << 6)
-#define IMTTBCR_SL0_TWOBIT_LVL_2 (1 << 6)
-#define IMTTBCR_SL0_TWOBIT_LVL_1 (2 << 6)
-
#define IMBUSCR 0x000c
#define IMBUSCR_DVM (1 << 2)
#define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -361,16 +361,16 @@ static void ipmmu_tlb_flush_all(void *cookie)
ipmmu_tlb_invalidate(domain);
}
-static void ipmmu_tlb_add_flush(unsigned long iova, size_t size,
- size_t granule, bool leaf, void *cookie)
+static void ipmmu_tlb_flush(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
{
- /* The hardware doesn't support selective TLB flush. */
+ ipmmu_tlb_flush_all(cookie);
}
-static const struct iommu_gather_ops ipmmu_gather_ops = {
+static const struct iommu_flush_ops ipmmu_flush_ops = {
.tlb_flush_all = ipmmu_tlb_flush_all,
- .tlb_add_flush = ipmmu_tlb_add_flush,
- .tlb_sync = ipmmu_tlb_flush_all,
+ .tlb_flush_walk = ipmmu_tlb_flush,
+ .tlb_flush_leaf = ipmmu_tlb_flush,
};
/* -----------------------------------------------------------------------------
@@ -422,17 +422,19 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain)
/*
* TTBCR
- * We use long descriptors with inner-shareable WBWA tables and allocate
- * the whole 32-bit VA space to TTBR0.
+ * We use long descriptors and allocate the whole 32-bit VA space to
+ * TTBR0.
*/
if (domain->mmu->features->twobit_imttbcr_sl0)
tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
else
tmp = IMTTBCR_SL0_LVL_1;
- ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
- IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
- IMTTBCR_IRGN0_WB_WA | tmp);
+ if (domain->mmu->features->cache_snoop)
+ tmp |= IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+ IMTTBCR_IRGN0_WB_WA;
+
+ ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE | tmp);
/* MAIR0 */
ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -480,7 +482,7 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K;
domain->cfg.ias = 32;
domain->cfg.oas = 40;
- domain->cfg.tlb = &ipmmu_gather_ops;
+ domain->cfg.tlb = &ipmmu_flush_ops;
domain->io_domain.geometry.aperture_end = DMA_BIT_MASK(32);
domain->io_domain.geometry.force_aperture = true;
/*
@@ -733,14 +735,14 @@ static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova,
}
static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
- return domain->iop->unmap(domain->iop, iova, size);
+ return domain->iop->unmap(domain->iop, iova, size, gather);
}
-static void ipmmu_iotlb_sync(struct iommu_domain *io_domain)
+static void ipmmu_flush_iotlb_all(struct iommu_domain *io_domain)
{
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
@@ -748,6 +750,12 @@ static void ipmmu_iotlb_sync(struct iommu_domain *io_domain)
ipmmu_tlb_flush_all(domain);
}
+static void ipmmu_iotlb_sync(struct iommu_domain *io_domain,
+ struct iommu_iotlb_gather *gather)
+{
+ ipmmu_flush_iotlb_all(io_domain);
+}
+
static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
dma_addr_t iova)
{
@@ -957,7 +965,7 @@ static const struct iommu_ops ipmmu_ops = {
.detach_dev = ipmmu_detach_device,
.map = ipmmu_map,
.unmap = ipmmu_unmap,
- .flush_iotlb_all = ipmmu_iotlb_sync,
+ .flush_iotlb_all = ipmmu_flush_iotlb_all,
.iotlb_sync = ipmmu_iotlb_sync,
.iova_to_phys = ipmmu_iova_to_phys,
.add_device = ipmmu_add_device,
@@ -988,6 +996,7 @@ static const struct ipmmu_features ipmmu_features_default = {
.setup_imbuscr = true,
.twobit_imttbcr_sl0 = false,
.reserved_context = false,
+ .cache_snoop = true,
};
static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
@@ -998,6 +1007,7 @@ static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
.setup_imbuscr = false,
.twobit_imttbcr_sl0 = true,
.reserved_context = true,
+ .cache_snoop = false,
};
static const struct of_device_id ipmmu_of_ids[] = {
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index b25e2eb9e038..be99d408cf35 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -168,20 +168,29 @@ fail:
return;
}
-static void __flush_iotlb_sync(void *cookie)
+static void __flush_iotlb_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
{
- /*
- * Nothing is needed here, the barrier to guarantee
- * completion of the tlb sync operation is implicitly
- * taken care when the iommu client does a writel before
- * kick starting the other master.
- */
+ __flush_iotlb_range(iova, size, granule, false, cookie);
+}
+
+static void __flush_iotlb_leaf(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ __flush_iotlb_range(iova, size, granule, true, cookie);
}
-static const struct iommu_gather_ops msm_iommu_gather_ops = {
+static void __flush_iotlb_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule, void *cookie)
+{
+ __flush_iotlb_range(iova, granule, granule, true, cookie);
+}
+
+static const struct iommu_flush_ops msm_iommu_flush_ops = {
.tlb_flush_all = __flush_iotlb,
- .tlb_add_flush = __flush_iotlb_range,
- .tlb_sync = __flush_iotlb_sync,
+ .tlb_flush_walk = __flush_iotlb_walk,
+ .tlb_flush_leaf = __flush_iotlb_leaf,
+ .tlb_add_page = __flush_iotlb_page,
};
static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
@@ -345,7 +354,7 @@ static int msm_iommu_domain_config(struct msm_priv *priv)
.pgsize_bitmap = msm_iommu_ops.pgsize_bitmap,
.ias = 32,
.oas = 32,
- .tlb = &msm_iommu_gather_ops,
+ .tlb = &msm_iommu_flush_ops,
.iommu_dev = priv->dev,
};
@@ -509,13 +518,13 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t len)
+ size_t len, struct iommu_iotlb_gather *gather)
{
struct msm_priv *priv = to_msm_priv(domain);
unsigned long flags;
spin_lock_irqsave(&priv->pgtlock, flags);
- len = priv->iop->unmap(priv->iop, iova, len);
+ len = priv->iop->unmap(priv->iop, iova, len, gather);
spin_unlock_irqrestore(&priv->pgtlock, flags);
return len;
@@ -691,6 +700,13 @@ static struct iommu_ops msm_iommu_ops = {
.detach_dev = msm_iommu_detach_dev,
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
+ /*
+ * Nothing is needed here, the barrier to guarantee
+ * completion of the tlb sync operation is implicitly
+ * taken care when the iommu client does a writel before
+ * kick starting the other master.
+ */
+ .iotlb_sync = NULL,
.iova_to_phys = msm_iommu_iova_to_phys,
.add_device = msm_iommu_add_device,
.remove_device = msm_iommu_remove_device,
@@ -750,7 +766,6 @@ static int msm_iommu_probe(struct platform_device *pdev)
iommu->irq = platform_get_irq(pdev, 0);
if (iommu->irq < 0) {
- dev_err(iommu->dev, "could not get iommu irq\n");
ret = -ENODEV;
goto fail;
}
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 82e4be4dfdaf..67a483c1a935 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -28,6 +28,7 @@
#include "mtk_iommu.h"
#define REG_MMU_PT_BASE_ADDR 0x000
+#define MMU_PT_ADDR_MASK GENMASK(31, 7)
#define REG_MMU_INVALIDATE 0x020
#define F_ALL_INVLD 0x2
@@ -44,12 +45,9 @@
#define REG_MMU_DCM_DIS 0x050
#define REG_MMU_CTRL_REG 0x110
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR (2 << 4)
#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
-#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
- ((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
-/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
-#define F_MMU_TF_PROTECT_SEL(prot, data) \
- (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173 (2 << 5)
#define REG_MMU_IVRP_PADDR 0x114
@@ -66,26 +64,32 @@
#define F_INT_CLR_BIT BIT(12)
#define REG_MMU_INT_MAIN_CONTROL 0x124
-#define F_INT_TRANSLATION_FAULT BIT(0)
-#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
-#define F_INT_INVALID_PA_FAULT BIT(2)
-#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
-#define F_INT_TLB_MISS_FAULT BIT(4)
-#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
-#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
+ /* mmu0 | mmu1 */
+#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
+#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
+#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
+#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
+#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
+#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
+#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))
#define REG_MMU_CPE_DONE 0x12C
#define REG_MMU_FAULT_ST1 0x134
+#define F_REG_MMU0_FAULT_MASK GENMASK(6, 0)
+#define F_REG_MMU1_FAULT_MASK GENMASK(13, 7)
-#define REG_MMU_FAULT_VA 0x13c
+#define REG_MMU0_FAULT_VA 0x13c
#define F_MMU_FAULT_VA_WRITE_BIT BIT(1)
#define F_MMU_FAULT_VA_LAYER_BIT BIT(0)
-#define REG_MMU_INVLD_PA 0x140
-#define REG_MMU_INT_ID 0x150
-#define F_MMU0_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
-#define F_MMU0_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
+#define REG_MMU0_INVLD_PA 0x140
+#define REG_MMU1_FAULT_VA 0x144
+#define REG_MMU1_INVLD_PA 0x148
+#define REG_MMU0_INT_ID 0x150
+#define REG_MMU1_INT_ID 0x154
+#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
+#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
#define MTK_PROTECT_PA_ALIGN 128
@@ -107,6 +111,30 @@ struct mtk_iommu_domain {
static const struct iommu_ops mtk_iommu_ops;
+/*
+ * In M4U 4GB mode, the physical address is remapped as below:
+ *
+ * CPU Physical address:
+ * ====================
+ *
+ * 0 1G 2G 3G 4G 5G
+ * |---A---|---B---|---C---|---D---|---E---|
+ * +--I/O--+------------Memory-------------+
+ *
+ * IOMMU output physical address:
+ * =============================
+ *
+ * 4G 5G 6G 7G 8G
+ * |---E---|---B---|---C---|---D---|
+ * +------------Memory-------------+
+ *
+ * The Region 'A'(I/O) can NOT be mapped by M4U; For Region 'B'/'C'/'D', the
+ * bit32 of the CPU physical address always is needed to set, and for Region
+ * 'E', the CPU physical address keep as is.
+ * Additionally, The iommu consumers always use the CPU phyiscal address.
+ */
+#define MTK_IOMMU_4GB_MODE_REMAP_BASE 0x140000000UL
+
static LIST_HEAD(m4ulist); /* List all the M4U HWs */
#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
@@ -188,10 +216,32 @@ static void mtk_iommu_tlb_sync(void *cookie)
}
}
-static const struct iommu_gather_ops mtk_iommu_gather_ops = {
+static void mtk_iommu_tlb_flush_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ mtk_iommu_tlb_add_flush_nosync(iova, size, granule, false, cookie);
+ mtk_iommu_tlb_sync(cookie);
+}
+
+static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ mtk_iommu_tlb_add_flush_nosync(iova, size, granule, true, cookie);
+ mtk_iommu_tlb_sync(cookie);
+}
+
+static void mtk_iommu_tlb_flush_page_nosync(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule,
+ void *cookie)
+{
+ mtk_iommu_tlb_add_flush_nosync(iova, granule, granule, true, cookie);
+}
+
+static const struct iommu_flush_ops mtk_iommu_flush_ops = {
.tlb_flush_all = mtk_iommu_tlb_flush_all,
- .tlb_add_flush = mtk_iommu_tlb_add_flush_nosync,
- .tlb_sync = mtk_iommu_tlb_sync,
+ .tlb_flush_walk = mtk_iommu_tlb_flush_walk,
+ .tlb_flush_leaf = mtk_iommu_tlb_flush_leaf,
+ .tlb_add_page = mtk_iommu_tlb_flush_page_nosync,
};
static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
@@ -204,13 +254,21 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
/* Read error info from registers */
int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
- fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+ if (int_state & F_REG_MMU0_FAULT_MASK) {
+ regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
+ fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
+ fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+ } else {
+ regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
+ fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
+ fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+ }
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
- fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
- regval = readl_relaxed(data->base + REG_MMU_INT_ID);
- fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
- fault_port = F_MMU0_INT_ID_PORT_ID(regval);
+ fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+ fault_port = F_MMU_INT_ID_PORT_ID(regval);
+
+ fault_larb = data->plat_data->larbid_remap[fault_larb];
if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
@@ -242,7 +300,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
for (i = 0; i < fwspec->num_ids; ++i) {
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
portid = MTK_M4U_TO_PORT(fwspec->ids[i]);
- larb_mmu = &data->smi_imu.larb_imu[larbid];
+ larb_mmu = &data->larb_imu[larbid];
dev_dbg(dev, "%s iommu port: %d\n",
enable ? "enable" : "disable", portid);
@@ -263,17 +321,15 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
dom->cfg = (struct io_pgtable_cfg) {
.quirks = IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_NO_PERMS |
- IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+ IO_PGTABLE_QUIRK_TLBI_ON_MAP |
+ IO_PGTABLE_QUIRK_ARM_MTK_EXT,
.pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
.ias = 32,
- .oas = 32,
- .tlb = &mtk_iommu_gather_ops,
+ .oas = 34,
+ .tlb = &mtk_iommu_flush_ops,
.iommu_dev = data->dev,
};
- if (data->enable_4GB)
- dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_4GB;
-
dom->iop = alloc_io_pgtable_ops(ARM_V7S, &dom->cfg, data);
if (!dom->iop) {
dev_err(data->dev, "Failed to alloc io pgtable\n");
@@ -336,7 +392,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) {
data->m4u_dom = dom;
- writel(dom->cfg.arm_v7s_cfg.ttbr[0],
+ writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
data->base + REG_MMU_PT_BASE_ADDR);
}
@@ -359,32 +415,43 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+ struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
unsigned long flags;
int ret;
+ /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
+ if (data->enable_4GB)
+ paddr |= BIT_ULL(32);
+
spin_lock_irqsave(&dom->pgtlock, flags);
- ret = dom->iop->map(dom->iop, iova, paddr & DMA_BIT_MASK(32),
- size, prot);
+ ret = dom->iop->map(dom->iop, iova, paddr, size, prot);
spin_unlock_irqrestore(&dom->pgtlock, flags);
return ret;
}
static size_t mtk_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *gather)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
unsigned long flags;
size_t unmapsz;
spin_lock_irqsave(&dom->pgtlock, flags);
- unmapsz = dom->iop->unmap(dom->iop, iova, size);
+ unmapsz = dom->iop->unmap(dom->iop, iova, size, gather);
spin_unlock_irqrestore(&dom->pgtlock, flags);
return unmapsz;
}
-static void mtk_iommu_iotlb_sync(struct iommu_domain *domain)
+static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain)
+{
+ mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data());
+}
+
+static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
{
mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data());
}
@@ -401,8 +468,8 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
pa = dom->iop->iova_to_phys(dom->iop, iova);
spin_unlock_irqrestore(&dom->pgtlock, flags);
- if (data->enable_4GB)
- pa |= BIT_ULL(32);
+ if (data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
+ pa &= ~BIT_ULL(32);
return pa;
}
@@ -490,7 +557,7 @@ static const struct iommu_ops mtk_iommu_ops = {
.detach_dev = mtk_iommu_detach_device,
.map = mtk_iommu_map,
.unmap = mtk_iommu_unmap,
- .flush_iotlb_all = mtk_iommu_iotlb_sync,
+ .flush_iotlb_all = mtk_iommu_flush_iotlb_all,
.iotlb_sync = mtk_iommu_iotlb_sync,
.iova_to_phys = mtk_iommu_iova_to_phys,
.add_device = mtk_iommu_add_device,
@@ -511,9 +578,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
return ret;
}
- regval = F_MMU_TF_PROTECT_SEL(2, data);
- if (data->m4u_plat == M4U_MT8173)
- regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
+ if (data->plat_data->m4u_plat == M4U_MT8173)
+ regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
+ F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
+ else
+ regval = F_MMU_TF_PROT_TO_PROGRAM_ADDR;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
regval = F_L2_MULIT_HIT_EN |
@@ -533,14 +602,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
- if (data->m4u_plat == M4U_MT8173)
+ if (data->plat_data->m4u_plat == M4U_MT8173)
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
upper_32_bits(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
- if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
+ if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
/*
* If 4GB mode is enabled, the validate PA range is from
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -550,8 +619,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
- /* It's MISC control register whose default value is ok except mt8173.*/
- if (data->m4u_plat == M4U_MT8173)
+ if (data->plat_data->reset_axi)
writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -584,7 +652,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->dev = dev;
- data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
+ data->plat_data = of_device_get_match_data(dev);
/* Protect memory. HW will access here while translation fault.*/
protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -594,6 +662,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
/* Whether the current dram is over 4GB */
data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
+ if (!data->plat_data->has_4gb_mode)
+ data->enable_4GB = false;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(dev, res);
@@ -605,15 +675,16 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (data->irq < 0)
return data->irq;
- data->bclk = devm_clk_get(dev, "bclk");
- if (IS_ERR(data->bclk))
- return PTR_ERR(data->bclk);
+ if (data->plat_data->has_bclk) {
+ data->bclk = devm_clk_get(dev, "bclk");
+ if (IS_ERR(data->bclk))
+ return PTR_ERR(data->bclk);
+ }
larb_nr = of_count_phandle_with_args(dev->of_node,
"mediatek,larbs", NULL);
if (larb_nr < 0)
return larb_nr;
- data->smi_imu.larb_nr = larb_nr;
for (i = 0; i < larb_nr; i++) {
struct device_node *larbnode;
@@ -638,7 +709,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
of_node_put(larbnode);
return -EPROBE_DEFER;
}
- data->smi_imu.larb_imu[id].dev = &plarbdev->dev;
+ data->larb_imu[id].dev = &plarbdev->dev;
component_match_add_release(dev, &match, release_of,
compare_of, larbnode);
@@ -699,6 +770,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+ reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
clk_disable_unprepare(data->bclk);
return 0;
}
@@ -707,6 +779,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
+ struct mtk_iommu_domain *m4u_dom = data->m4u_dom;
void __iomem *base = data->base;
int ret;
@@ -722,8 +795,9 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
- if (data->m4u_dom)
- writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
+ writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
+ if (m4u_dom)
+ writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
base + REG_MMU_PT_BASE_ADDR);
return 0;
}
@@ -732,9 +806,32 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
};
+static const struct mtk_iommu_plat_data mt2712_data = {
+ .m4u_plat = M4U_MT2712,
+ .has_4gb_mode = true,
+ .has_bclk = true,
+ .has_vld_pa_rng = true,
+ .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+};
+
+static const struct mtk_iommu_plat_data mt8173_data = {
+ .m4u_plat = M4U_MT8173,
+ .has_4gb_mode = true,
+ .has_bclk = true,
+ .reset_axi = true,
+ .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
+};
+
+static const struct mtk_iommu_plat_data mt8183_data = {
+ .m4u_plat = M4U_MT8183,
+ .reset_axi = true,
+ .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
+};
+
static const struct of_device_id mtk_iommu_of_ids[] = {
- { .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
- { .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
+ { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
+ { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
+ { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
{}
};
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 59337323db58..fc0f16eabacd 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -24,12 +24,25 @@ struct mtk_iommu_suspend_reg {
u32 int_control0;
u32 int_main_control;
u32 ivrp_paddr;
+ u32 vld_pa_rng;
};
enum mtk_iommu_plat {
M4U_MT2701,
M4U_MT2712,
M4U_MT8173,
+ M4U_MT8183,
+};
+
+struct mtk_iommu_plat_data {
+ enum mtk_iommu_plat m4u_plat;
+ bool has_4gb_mode;
+
+ /* HW will use the EMI clock if there isn't the "bclk". */
+ bool has_bclk;
+ bool has_vld_pa_rng;
+ bool reset_axi;
+ unsigned char larbid_remap[MTK_LARB_NR_MAX];
};
struct mtk_iommu_domain;
@@ -43,14 +56,14 @@ struct mtk_iommu_data {
struct mtk_iommu_suspend_reg reg;
struct mtk_iommu_domain *m4u_dom;
struct iommu_group *m4u_group;
- struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
bool enable_4GB;
bool tlb_flush_active;
struct iommu_device iommu;
- enum mtk_iommu_plat m4u_plat;
+ const struct mtk_iommu_plat_data *plat_data;
struct list_head list;
+ struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
};
static inline int compare_of(struct device *dev, void *data)
@@ -67,14 +80,14 @@ static inline int mtk_iommu_bind(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
- return component_bind_all(dev, &data->smi_imu);
+ return component_bind_all(dev, &data->larb_imu);
}
static inline void mtk_iommu_unbind(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
- component_unbind_all(dev, &data->smi_imu);
+ component_unbind_all(dev, &data->larb_imu);
}
#endif
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index abeeac488372..210b1c7c0bda 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -206,7 +206,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
for (i = 0; i < fwspec->num_ids; ++i) {
larbid = mt2701_m4u_to_larb(fwspec->ids[i]);
portid = mt2701_m4u_to_port(fwspec->ids[i]);
- larb_mmu = &data->smi_imu.larb_imu[larbid];
+ larb_mmu = &data->larb_imu[larbid];
dev_dbg(dev, "%s iommu port: %d\n",
enable ? "enable" : "disable", portid);
@@ -324,7 +324,8 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t mtk_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *gather)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
unsigned long flags;
@@ -610,14 +611,12 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}
}
- data->smi_imu.larb_imu[larb_nr].dev = &plarbdev->dev;
+ data->larb_imu[larb_nr].dev = &plarbdev->dev;
component_match_add_release(dev, &match, release_of,
compare_of, larb_spec.np);
larb_nr++;
}
- data->smi_imu.larb_nr = larb_nr;
-
platform_set_drvdata(pdev, data);
ret = mtk_iommu_hw_init(data);
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index dfb961d8c21b..09c6e1c680db 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -35,6 +35,15 @@
static const struct iommu_ops omap_iommu_ops;
+struct orphan_dev {
+ struct device *dev;
+ struct list_head node;
+};
+
+static LIST_HEAD(orphan_dev_list);
+
+static DEFINE_SPINLOCK(orphan_lock);
+
#define to_iommu(dev) ((struct omap_iommu *)dev_get_drvdata(dev))
/* bitmap of the page sizes currently supported */
@@ -53,6 +62,8 @@ static const struct iommu_ops omap_iommu_ops;
static struct platform_driver omap_iommu_driver;
static struct kmem_cache *iopte_cachep;
+static int _omap_iommu_add_device(struct device *dev);
+
/**
* to_omap_domain - Get struct omap_iommu_domain from generic iommu_domain
* @dom: generic iommu domain handle
@@ -65,6 +76,9 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom)
/**
* omap_iommu_save_ctx - Save registers for pm off-mode support
* @dev: client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver.
**/
void omap_iommu_save_ctx(struct device *dev)
{
@@ -92,6 +106,9 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
/**
* omap_iommu_restore_ctx - Restore registers for pm off-mode support
* @dev: client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver.
**/
void omap_iommu_restore_ctx(struct device *dev)
{
@@ -186,36 +203,18 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
static int iommu_enable(struct omap_iommu *obj)
{
- int err;
- struct platform_device *pdev = to_platform_device(obj->dev);
- struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
- if (pdata && pdata->deassert_reset) {
- err = pdata->deassert_reset(pdev, pdata->reset_name);
- if (err) {
- dev_err(obj->dev, "deassert_reset failed: %d\n", err);
- return err;
- }
- }
-
- pm_runtime_get_sync(obj->dev);
+ int ret;
- err = omap2_iommu_enable(obj);
+ ret = pm_runtime_get_sync(obj->dev);
+ if (ret < 0)
+ pm_runtime_put_noidle(obj->dev);
- return err;
+ return ret < 0 ? ret : 0;
}
static void iommu_disable(struct omap_iommu *obj)
{
- struct platform_device *pdev = to_platform_device(obj->dev);
- struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
- omap2_iommu_disable(obj);
-
pm_runtime_put_sync(obj->dev);
-
- if (pdata && pdata->assert_reset)
- pdata->assert_reset(pdev, pdata->reset_name);
}
/*
@@ -901,15 +900,219 @@ static void omap_iommu_detach(struct omap_iommu *obj)
dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE,
DMA_TO_DEVICE);
- iommu_disable(obj);
obj->pd_dma = 0;
obj->iopgd = NULL;
+ iommu_disable(obj);
spin_unlock(&obj->iommu_lock);
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
}
+static void omap_iommu_save_tlb_entries(struct omap_iommu *obj)
+{
+ struct iotlb_lock lock;
+ struct cr_regs cr;
+ struct cr_regs *tmp;
+ int i;
+
+ /* check if there are any locked tlbs to save */
+ iotlb_lock_get(obj, &lock);
+ obj->num_cr_ctx = lock.base;
+ if (!obj->num_cr_ctx)
+ return;
+
+ tmp = obj->cr_ctx;
+ for_each_iotlb_cr(obj, obj->num_cr_ctx, i, cr)
+ * tmp++ = cr;
+}
+
+static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj)
+{
+ struct iotlb_lock l;
+ struct cr_regs *tmp;
+ int i;
+
+ /* no locked tlbs to restore */
+ if (!obj->num_cr_ctx)
+ return;
+
+ l.base = 0;
+ tmp = obj->cr_ctx;
+ for (i = 0; i < obj->num_cr_ctx; i++, tmp++) {
+ l.vict = i;
+ iotlb_lock_set(obj, &l);
+ iotlb_load_cr(obj, tmp);
+ }
+ l.base = obj->num_cr_ctx;
+ l.vict = i;
+ iotlb_lock_set(obj, &l);
+}
+
+/**
+ * omap_iommu_domain_deactivate - deactivate attached iommu devices
+ * @domain: iommu domain attached to the target iommu device
+ *
+ * This API allows the client devices of IOMMU devices to suspend
+ * the IOMMUs they control at runtime, after they are idled and
+ * suspended all activity. System Suspend will leverage the PM
+ * driver late callbacks.
+ **/
+int omap_iommu_domain_deactivate(struct iommu_domain *domain)
+{
+ struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
+ struct omap_iommu_device *iommu;
+ struct omap_iommu *oiommu;
+ int i;
+
+ if (!omap_domain->dev)
+ return 0;
+
+ iommu = omap_domain->iommus;
+ iommu += (omap_domain->num_iommus - 1);
+ for (i = 0; i < omap_domain->num_iommus; i++, iommu--) {
+ oiommu = iommu->iommu_dev;
+ pm_runtime_put_sync(oiommu->dev);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_domain_deactivate);
+
+/**
+ * omap_iommu_domain_activate - activate attached iommu devices
+ * @domain: iommu domain attached to the target iommu device
+ *
+ * This API allows the client devices of IOMMU devices to resume the
+ * IOMMUs they control at runtime, before they can resume operations.
+ * System Resume will leverage the PM driver late callbacks.
+ **/
+int omap_iommu_domain_activate(struct iommu_domain *domain)
+{
+ struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
+ struct omap_iommu_device *iommu;
+ struct omap_iommu *oiommu;
+ int i;
+
+ if (!omap_domain->dev)
+ return 0;
+
+ iommu = omap_domain->iommus;
+ for (i = 0; i < omap_domain->num_iommus; i++, iommu++) {
+ oiommu = iommu->iommu_dev;
+ pm_runtime_get_sync(oiommu->dev);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_domain_activate);
+
+/**
+ * omap_iommu_runtime_suspend - disable an iommu device
+ * @dev: iommu device
+ *
+ * This function performs all that is necessary to disable an
+ * IOMMU device, either during final detachment from a client
+ * device, or during system/runtime suspend of the device. This
+ * includes programming all the appropriate IOMMU registers, and
+ * managing the associated omap_hwmod's state and the device's
+ * reset line. This function also saves the context of any
+ * locked TLBs if suspending.
+ **/
+static __maybe_unused int omap_iommu_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct iommu_platform_data *pdata = dev_get_platdata(dev);
+ struct omap_iommu *obj = to_iommu(dev);
+ int ret;
+
+ /* save the TLBs only during suspend, and not for power down */
+ if (obj->domain && obj->iopgd)
+ omap_iommu_save_tlb_entries(obj);
+
+ omap2_iommu_disable(obj);
+
+ if (pdata && pdata->device_idle)
+ pdata->device_idle(pdev);
+
+ if (pdata && pdata->assert_reset)
+ pdata->assert_reset(pdev, pdata->reset_name);
+
+ if (pdata && pdata->set_pwrdm_constraint) {
+ ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
+ if (ret) {
+ dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n",
+ ret);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * omap_iommu_runtime_resume - enable an iommu device
+ * @dev: iommu device
+ *
+ * This function performs all that is necessary to enable an
+ * IOMMU device, either during initial attachment to a client
+ * device, or during system/runtime resume of the device. This
+ * includes programming all the appropriate IOMMU registers, and
+ * managing the associated omap_hwmod's state and the device's
+ * reset line. The function also restores any locked TLBs if
+ * resuming after a suspend.
+ **/
+static __maybe_unused int omap_iommu_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct iommu_platform_data *pdata = dev_get_platdata(dev);
+ struct omap_iommu *obj = to_iommu(dev);
+ int ret = 0;
+
+ if (pdata && pdata->set_pwrdm_constraint) {
+ ret = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
+ if (ret) {
+ dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n",
+ ret);
+ }
+ }
+
+ if (pdata && pdata->deassert_reset) {
+ ret = pdata->deassert_reset(pdev, pdata->reset_name);
+ if (ret) {
+ dev_err(dev, "deassert_reset failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (pdata && pdata->device_enable)
+ pdata->device_enable(pdev);
+
+ /* restore the TLBs only during resume, and not for power up */
+ if (obj->domain)
+ omap_iommu_restore_tlb_entries(obj);
+
+ ret = omap2_iommu_enable(obj);
+
+ return ret;
+}
+
+/**
+ * omap_iommu_suspend_prepare - prepare() dev_pm_ops implementation
+ * @dev: iommu device
+ *
+ * This function performs the necessary checks to determine if the IOMMU
+ * device needs suspending or not. The function checks if the runtime_pm
+ * status of the device is suspended, and returns 1 in that case. This
+ * results in the PM core to skip invoking any of the Sleep PM callbacks
+ * (suspend, suspend_late, resume, resume_early etc).
+ */
+static int omap_iommu_prepare(struct device *dev)
+{
+ if (pm_runtime_status_suspended(dev))
+ return 1;
+ return 0;
+}
+
static bool omap_iommu_can_register(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -974,6 +1177,7 @@ static int omap_iommu_probe(struct platform_device *pdev)
struct omap_iommu *obj;
struct resource *res;
struct device_node *of = pdev->dev.of_node;
+ struct orphan_dev *orphan_dev, *tmp;
if (!of) {
pr_err("%s: only DT-based devices are supported\n", __func__);
@@ -984,6 +1188,15 @@ static int omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
+ /*
+ * self-manage the ordering dependencies between omap_device_enable/idle
+ * and omap_device_assert/deassert_hardreset API
+ */
+ if (pdev->dev.pm_domain) {
+ dev_dbg(&pdev->dev, "device pm_domain is being reset\n");
+ pdev->dev.pm_domain = NULL;
+ }
+
obj->name = dev_name(&pdev->dev);
obj->nr_tlb_entries = 32;
err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries);
@@ -996,6 +1209,11 @@ static int omap_iommu_probe(struct platform_device *pdev)
obj->dev = &pdev->dev;
obj->ctx = (void *)obj + sizeof(*obj);
+ obj->cr_ctx = devm_kzalloc(&pdev->dev,
+ sizeof(*obj->cr_ctx) * obj->nr_tlb_entries,
+ GFP_KERNEL);
+ if (!obj->cr_ctx)
+ return -ENOMEM;
spin_lock_init(&obj->iommu_lock);
spin_lock_init(&obj->page_table_lock);
@@ -1036,13 +1254,20 @@ static int omap_iommu_probe(struct platform_device *pdev)
goto out_sysfs;
}
- pm_runtime_irq_safe(obj->dev);
pm_runtime_enable(obj->dev);
omap_iommu_debugfs_add(obj);
dev_info(&pdev->dev, "%s registered\n", obj->name);
+ list_for_each_entry_safe(orphan_dev, tmp, &orphan_dev_list, node) {
+ err = _omap_iommu_add_device(orphan_dev->dev);
+ if (!err) {
+ list_del(&orphan_dev->node);
+ kfree(orphan_dev);
+ }
+ }
+
return 0;
out_sysfs:
@@ -1072,6 +1297,14 @@ static int omap_iommu_remove(struct platform_device *pdev)
return 0;
}
+static const struct dev_pm_ops omap_iommu_pm_ops = {
+ .prepare = omap_iommu_prepare,
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+ omap_iommu_runtime_resume, NULL)
+};
+
static const struct of_device_id omap_iommu_of_match[] = {
{ .compatible = "ti,omap2-iommu" },
{ .compatible = "ti,omap4-iommu" },
@@ -1085,6 +1318,7 @@ static struct platform_driver omap_iommu_driver = {
.remove = omap_iommu_remove,
.driver = {
.name = "omap-iommu",
+ .pm = &omap_iommu_pm_ops,
.of_match_table = of_match_ptr(omap_iommu_of_match),
},
};
@@ -1149,7 +1383,7 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
}
static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
struct device *dev = omap_domain->dev;
@@ -1423,7 +1657,7 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
return ret;
}
-static int omap_iommu_add_device(struct device *dev)
+static int _omap_iommu_add_device(struct device *dev)
{
struct omap_iommu_arch_data *arch_data, *tmp;
struct omap_iommu *oiommu;
@@ -1432,6 +1666,8 @@ static int omap_iommu_add_device(struct device *dev)
struct platform_device *pdev;
int num_iommus, i;
int ret;
+ struct orphan_dev *orphan_dev;
+ unsigned long flags;
/*
* Allocate the archdata iommu structure for DT-based devices.
@@ -1463,10 +1699,26 @@ static int omap_iommu_add_device(struct device *dev)
}
pdev = of_find_device_by_node(np);
- if (WARN_ON(!pdev)) {
+ if (!pdev) {
of_node_put(np);
kfree(arch_data);
- return -EINVAL;
+ spin_lock_irqsave(&orphan_lock, flags);
+ list_for_each_entry(orphan_dev, &orphan_dev_list,
+ node) {
+ if (orphan_dev->dev == dev)
+ break;
+ }
+ spin_unlock_irqrestore(&orphan_lock, flags);
+
+ if (orphan_dev && orphan_dev->dev == dev)
+ return -EPROBE_DEFER;
+
+ orphan_dev = kzalloc(sizeof(*orphan_dev), GFP_KERNEL);
+ orphan_dev->dev = dev;
+ spin_lock_irqsave(&orphan_lock, flags);
+ list_add(&orphan_dev->node, &orphan_dev_list);
+ spin_unlock_irqrestore(&orphan_lock, flags);
+ return -EPROBE_DEFER;
}
oiommu = platform_get_drvdata(pdev);
@@ -1477,6 +1729,7 @@ static int omap_iommu_add_device(struct device *dev)
}
tmp->iommu_dev = oiommu;
+ tmp->dev = &pdev->dev;
of_node_put(np);
}
@@ -1511,6 +1764,17 @@ static int omap_iommu_add_device(struct device *dev)
return 0;
}
+static int omap_iommu_add_device(struct device *dev)
+{
+ int ret;
+
+ ret = _omap_iommu_add_device(dev);
+ if (ret == -EPROBE_DEFER)
+ return 0;
+
+ return ret;
+}
+
static void omap_iommu_remove_device(struct device *dev)
{
struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
@@ -1554,7 +1818,7 @@ static const struct iommu_ops omap_iommu_ops = {
static int __init omap_iommu_init(void)
{
struct kmem_cache *p;
- const unsigned long flags = SLAB_HWCACHE_ALIGN;
+ const slab_flags_t flags = SLAB_HWCACHE_ALIGN;
size_t align = 1 << 10; /* L2 pagetable alignement */
struct device_node *np;
int ret;
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 09968a02d291..18ee713ede78 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -73,16 +73,22 @@ struct omap_iommu {
void *ctx; /* iommu context: registres saved area */
+ struct cr_regs *cr_ctx;
+ u32 num_cr_ctx;
+
int has_bus_err_back;
u32 id;
struct iommu_device iommu;
struct iommu_group *group;
+
+ u8 pwrst;
};
/**
* struct omap_iommu_arch_data - omap iommu private data
- * @iommu_dev: handle of the iommu device
+ * @iommu_dev: handle of the OMAP iommu device
+ * @dev: handle of the iommu device
*
* This is an omap iommu private data object, which binds an iommu user
* to its iommu device. This object should be placed at the iommu user's
@@ -91,6 +97,7 @@ struct omap_iommu {
*/
struct omap_iommu_arch_data {
struct omap_iommu *iommu_dev;
+ struct device *dev;
};
struct cr_regs {
diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c
index 34d0b9783b3e..c31e7bc4ccbe 100644
--- a/drivers/iommu/qcom_iommu.c
+++ b/drivers/iommu/qcom_iommu.c
@@ -7,6 +7,7 @@
*/
#include <linux/atomic.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
@@ -32,7 +33,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include "arm-smmu-regs.h"
+#include "arm-smmu.h"
#define SMMU_INTR_SEL_NS 0x2000
@@ -155,7 +156,7 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size,
struct qcom_iommu_ctx *ctx = to_ctx(fwspec, fwspec->ids[i]);
size_t s = size;
- iova &= ~12UL;
+ iova = (iova >> 12) << 12;
iova |= ctx->asid;
do {
iommu_writel(ctx, reg, iova);
@@ -164,10 +165,32 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size,
}
}
-static const struct iommu_gather_ops qcom_gather_ops = {
+static void qcom_iommu_tlb_flush_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ qcom_iommu_tlb_inv_range_nosync(iova, size, granule, false, cookie);
+ qcom_iommu_tlb_sync(cookie);
+}
+
+static void qcom_iommu_tlb_flush_leaf(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ qcom_iommu_tlb_inv_range_nosync(iova, size, granule, true, cookie);
+ qcom_iommu_tlb_sync(cookie);
+}
+
+static void qcom_iommu_tlb_add_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule,
+ void *cookie)
+{
+ qcom_iommu_tlb_inv_range_nosync(iova, granule, granule, true, cookie);
+}
+
+static const struct iommu_flush_ops qcom_flush_ops = {
.tlb_flush_all = qcom_iommu_tlb_inv_context,
- .tlb_add_flush = qcom_iommu_tlb_inv_range_nosync,
- .tlb_sync = qcom_iommu_tlb_sync,
+ .tlb_flush_walk = qcom_iommu_tlb_flush_walk,
+ .tlb_flush_leaf = qcom_iommu_tlb_flush_leaf,
+ .tlb_add_page = qcom_iommu_tlb_add_page,
};
static irqreturn_t qcom_iommu_fault(int irq, void *dev)
@@ -215,7 +238,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
.pgsize_bitmap = qcom_iommu_ops.pgsize_bitmap,
.ias = 32,
.oas = 40,
- .tlb = &qcom_gather_ops,
+ .tlb = &qcom_flush_ops,
.iommu_dev = qcom_iommu->dev,
};
@@ -247,16 +270,16 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
/* TTBRs */
iommu_writeq(ctx, ARM_SMMU_CB_TTBR0,
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0] |
- ((u64)ctx->asid << TTBRn_ASID_SHIFT));
+ FIELD_PREP(TTBRn_ASID, ctx->asid));
iommu_writeq(ctx, ARM_SMMU_CB_TTBR1,
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1] |
- ((u64)ctx->asid << TTBRn_ASID_SHIFT));
+ FIELD_PREP(TTBRn_ASID, ctx->asid));
- /* TTBCR */
- iommu_writel(ctx, ARM_SMMU_CB_TTBCR2,
+ /* TCR */
+ iommu_writel(ctx, ARM_SMMU_CB_TCR2,
(pgtbl_cfg.arm_lpae_s1_cfg.tcr >> 32) |
- TTBCR2_SEP_UPSTREAM);
- iommu_writel(ctx, ARM_SMMU_CB_TTBCR,
+ FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM));
+ iommu_writel(ctx, ARM_SMMU_CB_TCR,
pgtbl_cfg.arm_lpae_s1_cfg.tcr);
/* MAIRs (stage-1 only) */
@@ -417,7 +440,7 @@ static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t qcom_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
size_t ret;
unsigned long flags;
@@ -434,14 +457,14 @@ static size_t qcom_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
*/
pm_runtime_get_sync(qcom_domain->iommu->dev);
spin_lock_irqsave(&qcom_domain->pgtbl_lock, flags);
- ret = ops->unmap(ops, iova, size);
+ ret = ops->unmap(ops, iova, size, gather);
spin_unlock_irqrestore(&qcom_domain->pgtbl_lock, flags);
pm_runtime_put_sync(qcom_domain->iommu->dev);
return ret;
}
-static void qcom_iommu_iotlb_sync(struct iommu_domain *domain)
+static void qcom_iommu_flush_iotlb_all(struct iommu_domain *domain)
{
struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
struct io_pgtable *pgtable = container_of(qcom_domain->pgtbl_ops,
@@ -454,6 +477,12 @@ static void qcom_iommu_iotlb_sync(struct iommu_domain *domain)
pm_runtime_put_sync(qcom_domain->iommu->dev);
}
+static void qcom_iommu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
+{
+ qcom_iommu_flush_iotlb_all(domain);
+}
+
static phys_addr_t qcom_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
@@ -581,7 +610,7 @@ static const struct iommu_ops qcom_iommu_ops = {
.detach_dev = qcom_iommu_detach_dev,
.map = qcom_iommu_map,
.unmap = qcom_iommu_unmap,
- .flush_iotlb_all = qcom_iommu_iotlb_sync,
+ .flush_iotlb_all = qcom_iommu_flush_iotlb_all,
.iotlb_sync = qcom_iommu_iotlb_sync,
.iova_to_phys = qcom_iommu_iova_to_phys,
.add_device = qcom_iommu_add_device,
@@ -696,10 +725,8 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
return PTR_ERR(ctx->base);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "failed to get irq\n");
+ if (irq < 0)
return -ENODEV;
- }
/* clear IRQs before registering fault handler, just in case the
* boot-loader left us a surprise:
@@ -775,7 +802,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
struct qcom_iommu_dev *qcom_iommu;
struct device *dev = &pdev->dev;
struct resource *res;
- int ret, sz, max_asid = 0;
+ int ret, max_asid = 0;
/* find the max asid (which is 1:1 to ctx bank idx), so we know how
* many child ctx devices we have:
@@ -783,9 +810,8 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
for_each_child_of_node(dev->of_node, child)
max_asid = max(max_asid, get_asid(child));
- sz = sizeof(*qcom_iommu) + (max_asid * sizeof(qcom_iommu->ctxs[0]));
-
- qcom_iommu = devm_kzalloc(dev, sz, GFP_KERNEL);
+ qcom_iommu = devm_kzalloc(dev, struct_size(qcom_iommu, ctxs, max_asid),
+ GFP_KERNEL);
if (!qcom_iommu)
return -ENOMEM;
qcom_iommu->num_ctxs = max_asid;
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index dc26d74d79c2..26290f310f90 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -794,7 +794,7 @@ static int rk_iommu_map(struct iommu_domain *domain, unsigned long _iova,
}
static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index 22d4db302c1c..3b0b18e23187 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -314,7 +314,8 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
}
static size_t s390_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *gather)
{
struct s390_domain *s390_domain = to_s390_domain(domain);
int flags = ZPCI_PTE_INVALID;
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 6d40bc1b38bf..3924f7c05544 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -207,7 +207,7 @@ static inline int __gart_iommu_unmap(struct gart_device *gart,
}
static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t bytes)
+ size_t bytes, struct iommu_iotlb_gather *gather)
{
struct gart_device *gart = gart_handle;
int err;
@@ -273,11 +273,17 @@ static int gart_iommu_of_xlate(struct device *dev,
return 0;
}
-static void gart_iommu_sync(struct iommu_domain *domain)
+static void gart_iommu_sync_map(struct iommu_domain *domain)
{
FLUSH_GART_REGS(gart_handle);
}
+static void gart_iommu_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
+{
+ gart_iommu_sync_map(domain);
+}
+
static const struct iommu_ops gart_iommu_ops = {
.capable = gart_iommu_capable,
.domain_alloc = gart_iommu_domain_alloc,
@@ -292,7 +298,7 @@ static const struct iommu_ops gart_iommu_ops = {
.iova_to_phys = gart_iommu_iova_to_phys,
.pgsize_bitmap = GART_IOMMU_PGSIZES,
.of_xlate = gart_iommu_of_xlate,
- .iotlb_sync_map = gart_iommu_sync,
+ .iotlb_sync_map = gart_iommu_sync_map,
.iotlb_sync = gart_iommu_sync,
};
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index c4a652b227f8..7293fc3f796d 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -680,7 +680,7 @@ static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
struct tegra_smmu_as *as = to_smmu_as(domain);
dma_addr_t pte_dma;
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 433f4d2ee956..3ea9d7682999 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -2,7 +2,7 @@
/*
* Virtio driver for the paravirtualized IOMMU
*
- * Copyright (C) 2018 Arm Limited
+ * Copyright (C) 2019 Arm Limited
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -47,7 +47,10 @@ struct viommu_dev {
/* Device configuration */
struct iommu_domain_geometry geometry;
u64 pgsize_bitmap;
- u8 domain_bits;
+ u32 first_domain;
+ u32 last_domain;
+ /* Supported MAP flags */
+ u32 map_flags;
u32 probe_size;
};
@@ -62,6 +65,7 @@ struct viommu_domain {
struct viommu_dev *viommu;
struct mutex mutex; /* protects viommu pointer */
unsigned int id;
+ u32 map_flags;
spinlock_t mappings_lock;
struct rb_root_cached mappings;
@@ -113,6 +117,8 @@ static int viommu_get_req_errno(void *buf, size_t len)
return -ENOENT;
case VIRTIO_IOMMU_S_FAULT:
return -EFAULT;
+ case VIRTIO_IOMMU_S_NOMEM:
+ return -ENOMEM;
case VIRTIO_IOMMU_S_IOERR:
case VIRTIO_IOMMU_S_DEVERR:
default:
@@ -607,15 +613,15 @@ static int viommu_domain_finalise(struct viommu_dev *viommu,
{
int ret;
struct viommu_domain *vdomain = to_viommu_domain(domain);
- unsigned int max_domain = viommu->domain_bits > 31 ? ~0 :
- (1U << viommu->domain_bits) - 1;
vdomain->viommu = viommu;
+ vdomain->map_flags = viommu->map_flags;
domain->pgsize_bitmap = viommu->pgsize_bitmap;
domain->geometry = viommu->geometry;
- ret = ida_alloc_max(&viommu->domain_ids, max_domain, GFP_KERNEL);
+ ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
+ viommu->last_domain, GFP_KERNEL);
if (ret >= 0)
vdomain->id = (unsigned int)ret;
@@ -710,7 +716,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
int ret;
- int flags;
+ u32 flags;
struct virtio_iommu_req_map map;
struct viommu_domain *vdomain = to_viommu_domain(domain);
@@ -718,6 +724,9 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
(prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
(prot & IOMMU_MMIO ? VIRTIO_IOMMU_MAP_F_MMIO : 0);
+ if (flags & ~vdomain->map_flags)
+ return -EINVAL;
+
ret = viommu_add_mapping(vdomain, iova, paddr, size, flags);
if (ret)
return ret;
@@ -742,7 +751,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
}
static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size)
+ size_t size, struct iommu_iotlb_gather *gather)
{
int ret = 0;
size_t unmapped;
@@ -788,7 +797,8 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
return paddr;
}
-static void viommu_iotlb_sync(struct iommu_domain *domain)
+static void viommu_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
{
struct viommu_domain *vdomain = to_viommu_domain(domain);
@@ -1027,7 +1037,8 @@ static int viommu_probe(struct virtio_device *vdev)
goto err_free_vqs;
}
- viommu->domain_bits = 32;
+ viommu->map_flags = VIRTIO_IOMMU_MAP_F_READ | VIRTIO_IOMMU_MAP_F_WRITE;
+ viommu->last_domain = ~0U;
/* Optional features */
virtio_cread_feature(vdev, VIRTIO_IOMMU_F_INPUT_RANGE,
@@ -1038,9 +1049,13 @@ static int viommu_probe(struct virtio_device *vdev)
struct virtio_iommu_config, input_range.end,
&input_end);
- virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_BITS,
- struct virtio_iommu_config, domain_bits,
- &viommu->domain_bits);
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
+ struct virtio_iommu_config, domain_range.start,
+ &viommu->first_domain);
+
+ virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
+ struct virtio_iommu_config, domain_range.end,
+ &viommu->last_domain);
virtio_cread_feature(vdev, VIRTIO_IOMMU_F_PROBE,
struct virtio_iommu_config, probe_size,
@@ -1052,6 +1067,9 @@ static int viommu_probe(struct virtio_device *vdev)
.force_aperture = true,
};
+ if (virtio_has_feature(vdev, VIRTIO_IOMMU_F_MMIO))
+ viommu->map_flags |= VIRTIO_IOMMU_MAP_F_MMIO;
+
viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap;
virtio_device_ready(vdev);
@@ -1130,9 +1148,10 @@ static void viommu_config_changed(struct virtio_device *vdev)
static unsigned int features[] = {
VIRTIO_IOMMU_F_MAP_UNMAP,
- VIRTIO_IOMMU_F_DOMAIN_BITS,
VIRTIO_IOMMU_F_INPUT_RANGE,
+ VIRTIO_IOMMU_F_DOMAIN_RANGE,
VIRTIO_IOMMU_F_PROBE,
+ VIRTIO_IOMMU_F_MMIO,
};
static struct virtio_device_id id_table[] = {
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index b0a8215a13fc..82520006195d 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -41,6 +41,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data)
{
for (; quirks->desc; quirks++) {
+ if (quirks->compatible)
+ continue;
if (quirks->iidr != (quirks->mask & iidr))
continue;
if (quirks->init(data))
@@ -63,7 +65,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
* for "irq", depending on "type".
*/
raw_spin_lock_irqsave(&irq_controller_lock, flags);
- val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
+ val = oldval = readl_relaxed(base + confoff);
if (type & IRQ_TYPE_LEVEL_MASK)
val &= ~confmask;
else if (type & IRQ_TYPE_EDGE_BOTH)
@@ -83,14 +85,10 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
* does not allow us to set the configuration or we are in a
* non-secure mode, and hence it may not be catastrophic.
*/
- writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
- if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) {
- if (WARN_ON(irq >= 32))
- ret = -EINVAL;
- else
- pr_warn("GIC: PPI%d is secure or misconfigured\n",
- irq - 16);
- }
+ writel_relaxed(val, base + confoff);
+ if (readl_relaxed(base + confoff) != val)
+ ret = -EINVAL;
+
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
if (sync_access)
@@ -132,26 +130,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
sync_access();
}
-void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
+void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
{
int i;
/*
* Deal with the banked PPI and SGI interrupts - disable all
- * PPI interrupts, ensure all SGI interrupts are enabled.
- * Make sure everything is deactivated.
+ * private interrupts. Make sure everything is deactivated.
*/
- writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
- writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
- writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
+ for (i = 0; i < nr; i += 32) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ base + GIC_DIST_ACTIVE_CLEAR + i / 8);
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ base + GIC_DIST_ENABLE_CLEAR + i / 8);
+ }
/*
* Set priority on PPI and SGI interrupts
*/
- for (i = 0; i < 32; i += 4)
+ for (i = 0; i < nr; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4,
base + GIC_DIST_PRI + i * 4 / 4);
+ /* Ensure all SGI interrupts are now enabled */
+ writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
+
if (sync_access)
sync_access();
}
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index 5a46b6b57750..ccba8b0fe0f5 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void));
-void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void));
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data);
void gic_enable_of_quirks(const struct device_node *np,
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 7338f90b2f9e..e88e75c22b6a 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header,
spi_start, nr_spis);
}
- fwnode = irq_domain_alloc_fwnode((void *)m->base_address);
+ fwnode = irq_domain_alloc_fwnode(&res.start);
if (!fwnode) {
pr_err("Unable to allocate GICv2m domain token\n");
return -EINVAL;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 730fbe0e2a9d..62e54f1a248b 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -2464,6 +2464,7 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
{
int idx;
+ /* Find a free LPI region in lpi_map and allocate them. */
idx = bitmap_find_free_region(dev->event_map.lpi_map,
dev->event_map.nr_lpis,
get_count_order(nvecs));
@@ -2471,7 +2472,6 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
return -ENOSPC;
*hwirq = dev->event_map.lpi_base + idx;
- set_bit(idx, dev->event_map.lpi_map);
return 0;
}
@@ -2641,14 +2641,13 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
struct its_node *its = its_dev->its;
int i;
+ bitmap_release_region(its_dev->event_map.lpi_map,
+ its_get_event_id(irq_domain_get_irq_data(domain, virq)),
+ get_count_order(nr_irqs));
+
for (i = 0; i < nr_irqs; i++) {
struct irq_data *data = irq_domain_get_irq_data(domain,
virq + i);
- u32 event = its_get_event_id(data);
-
- /* Mark interrupt index as unused */
- clear_bit(event, its_dev->event_map.lpi_map);
-
/* Nuke the entry in the domain */
irq_domain_reset_irq_data(data);
}
@@ -3010,7 +3009,7 @@ static int its_vpe_init(struct its_vpe *vpe)
if (!its_alloc_vpe_table(vpe_id)) {
its_vpe_id_free(vpe_id);
- its_free_pending_table(vpe->vpt_page);
+ its_free_pending_table(vpt_page);
return -ENOMEM;
}
@@ -3921,7 +3920,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
res.flags = IORESOURCE_MEM;
- dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
+ dom_handle = irq_domain_alloc_fwnode(&res.start);
if (!dom_handle) {
pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
&res.start);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 9bca4896fa6f..422664ac5f53 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -51,13 +51,17 @@ struct gic_chip_data {
u32 nr_redist_regions;
u64 flags;
bool has_rss;
- unsigned int irq_nr;
- struct partition_desc *ppi_descs[16];
+ unsigned int ppi_nr;
+ struct partition_desc **ppi_descs;
};
static struct gic_chip_data gic_data __read_mostly;
static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
+#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
+#define GIC_LINE_NR max(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
+#define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
+
/*
* The behaviours of RPR and PMR registers differ depending on the value of
* SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
@@ -84,7 +88,7 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
-static refcount_t ppi_nmi_refs[16];
+static refcount_t *ppi_nmi_refs;
static struct gic_kvm_info gic_v3_kvm_info;
static DEFINE_PER_CPU(bool, has_rss);
@@ -97,6 +101,38 @@ static DEFINE_PER_CPU(bool, has_rss);
/* Our default, arbitrary priority value. Linux only uses one anyway. */
#define DEFAULT_PMR_VALUE 0xf0
+enum gic_intid_range {
+ PPI_RANGE,
+ SPI_RANGE,
+ EPPI_RANGE,
+ ESPI_RANGE,
+ LPI_RANGE,
+ __INVALID_RANGE__
+};
+
+static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
+{
+ switch (hwirq) {
+ case 16 ... 31:
+ return PPI_RANGE;
+ case 32 ... 1019:
+ return SPI_RANGE;
+ case EPPI_BASE_INTID ... (EPPI_BASE_INTID + 63):
+ return EPPI_RANGE;
+ case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023):
+ return ESPI_RANGE;
+ case 8192 ... GENMASK(23, 0):
+ return LPI_RANGE;
+ default:
+ return __INVALID_RANGE__;
+ }
+}
+
+static enum gic_intid_range get_intid_range(struct irq_data *d)
+{
+ return __get_intid_range(d->hwirq);
+}
+
static inline unsigned int gic_irq(struct irq_data *d)
{
return d->hwirq;
@@ -104,18 +140,26 @@ static inline unsigned int gic_irq(struct irq_data *d)
static inline int gic_irq_in_rdist(struct irq_data *d)
{
- return gic_irq(d) < 32;
+ enum gic_intid_range range = get_intid_range(d);
+ return range == PPI_RANGE || range == EPPI_RANGE;
}
static inline void __iomem *gic_dist_base(struct irq_data *d)
{
- if (gic_irq_in_rdist(d)) /* SGI+PPI -> SGI_base for this CPU */
+ switch (get_intid_range(d)) {
+ case PPI_RANGE:
+ case EPPI_RANGE:
+ /* SGI+PPI -> SGI_base for this CPU */
return gic_data_rdist_sgi_base();
- if (d->hwirq <= 1023) /* SPI -> dist_base */
+ case SPI_RANGE:
+ case ESPI_RANGE:
+ /* SPI -> dist_base */
return gic_data.dist_base;
- return NULL;
+ default:
+ return NULL;
+ }
}
static void gic_do_wait_for_rwp(void __iomem *base)
@@ -196,24 +240,79 @@ static void gic_enable_redist(bool enable)
/*
* Routines to disable, enable, EOI and route interrupts
*/
+static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
+{
+ switch (get_intid_range(d)) {
+ case PPI_RANGE:
+ case SPI_RANGE:
+ *index = d->hwirq;
+ return offset;
+ case EPPI_RANGE:
+ /*
+ * Contrary to the ESPI range, the EPPI range is contiguous
+ * to the PPI range in the registers, so let's adjust the
+ * displacement accordingly. Consistency is overrated.
+ */
+ *index = d->hwirq - EPPI_BASE_INTID + 32;
+ return offset;
+ case ESPI_RANGE:
+ *index = d->hwirq - ESPI_BASE_INTID;
+ switch (offset) {
+ case GICD_ISENABLER:
+ return GICD_ISENABLERnE;
+ case GICD_ICENABLER:
+ return GICD_ICENABLERnE;
+ case GICD_ISPENDR:
+ return GICD_ISPENDRnE;
+ case GICD_ICPENDR:
+ return GICD_ICPENDRnE;
+ case GICD_ISACTIVER:
+ return GICD_ISACTIVERnE;
+ case GICD_ICACTIVER:
+ return GICD_ICACTIVERnE;
+ case GICD_IPRIORITYR:
+ return GICD_IPRIORITYRnE;
+ case GICD_ICFGR:
+ return GICD_ICFGRnE;
+ case GICD_IROUTER:
+ return GICD_IROUTERnE;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ WARN_ON(1);
+ *index = d->hwirq;
+ return offset;
+}
+
static int gic_peek_irq(struct irq_data *d, u32 offset)
{
- u32 mask = 1 << (gic_irq(d) % 32);
void __iomem *base;
+ u32 index, mask;
+
+ offset = convert_offset_index(d, offset, &index);
+ mask = 1 << (index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
else
base = gic_data.dist_base;
- return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+ return !!(readl_relaxed(base + offset + (index / 32) * 4) & mask);
}
static void gic_poke_irq(struct irq_data *d, u32 offset)
{
- u32 mask = 1 << (gic_irq(d) % 32);
void (*rwp_wait)(void);
void __iomem *base;
+ u32 index, mask;
+
+ offset = convert_offset_index(d, offset, &index);
+ mask = 1 << (index % 32);
if (gic_irq_in_rdist(d)) {
base = gic_data_rdist_sgi_base();
@@ -223,7 +322,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
rwp_wait = gic_dist_wait_for_rwp;
}
- writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
+ writel_relaxed(mask, base + offset + (index / 32) * 4);
rwp_wait();
}
@@ -263,7 +362,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
{
u32 reg;
- if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+ if (d->hwirq >= 8192) /* PPI/SPI only */
return -EINVAL;
switch (which) {
@@ -290,7 +389,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
static int gic_irq_get_irqchip_state(struct irq_data *d,
enum irqchip_irq_state which, bool *val)
{
- if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+ if (d->hwirq >= 8192) /* PPI/SPI only */
return -EINVAL;
switch (which) {
@@ -316,8 +415,23 @@ static int gic_irq_get_irqchip_state(struct irq_data *d,
static void gic_irq_set_prio(struct irq_data *d, u8 prio)
{
void __iomem *base = gic_dist_base(d);
+ u32 offset, index;
+
+ offset = convert_offset_index(d, GICD_IPRIORITYR, &index);
- writeb_relaxed(prio, base + GICD_IPRIORITYR + gic_irq(d));
+ writeb_relaxed(prio, base + offset + index);
+}
+
+static u32 gic_get_ppi_index(struct irq_data *d)
+{
+ switch (get_intid_range(d)) {
+ case PPI_RANGE:
+ return d->hwirq - 16;
+ case EPPI_RANGE:
+ return d->hwirq - EPPI_BASE_INTID + 16;
+ default:
+ unreachable();
+ }
}
static int gic_irq_nmi_setup(struct irq_data *d)
@@ -340,10 +454,12 @@ static int gic_irq_nmi_setup(struct irq_data *d)
return -EINVAL;
/* desc lock should already be held */
- if (gic_irq(d) < 32) {
+ if (gic_irq_in_rdist(d)) {
+ u32 idx = gic_get_ppi_index(d);
+
/* Setting up PPI as NMI, only switch handler for first NMI */
- if (!refcount_inc_not_zero(&ppi_nmi_refs[gic_irq(d) - 16])) {
- refcount_set(&ppi_nmi_refs[gic_irq(d) - 16], 1);
+ if (!refcount_inc_not_zero(&ppi_nmi_refs[idx])) {
+ refcount_set(&ppi_nmi_refs[idx], 1);
desc->handle_irq = handle_percpu_devid_fasteoi_nmi;
}
} else {
@@ -375,9 +491,11 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
return;
/* desc lock should already be held */
- if (gic_irq(d) < 32) {
+ if (gic_irq_in_rdist(d)) {
+ u32 idx = gic_get_ppi_index(d);
+
/* Tearing down NMI, only switch handler for last NMI */
- if (refcount_dec_and_test(&ppi_nmi_refs[gic_irq(d) - 16]))
+ if (refcount_dec_and_test(&ppi_nmi_refs[idx]))
desc->handle_irq = handle_percpu_devid_irq;
} else {
desc->handle_irq = handle_fasteoi_irq;
@@ -404,17 +522,22 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
static int gic_set_type(struct irq_data *d, unsigned int type)
{
+ enum gic_intid_range range;
unsigned int irq = gic_irq(d);
void (*rwp_wait)(void);
void __iomem *base;
+ u32 offset, index;
+ int ret;
/* Interrupt configuration for SGIs can't be changed */
if (irq < 16)
return -EINVAL;
+ range = get_intid_range(d);
+
/* SPIs have restrictions on the supported types */
- if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
- type != IRQ_TYPE_EDGE_RISING)
+ if ((range == SPI_RANGE || range == ESPI_RANGE) &&
+ type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
if (gic_irq_in_rdist(d)) {
@@ -425,7 +548,16 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
rwp_wait = gic_dist_wait_for_rwp;
}
- return gic_configure_irq(irq, type, base, rwp_wait);
+ offset = convert_offset_index(d, GICD_ICFGR, &index);
+
+ ret = gic_configure_irq(index, type, base + offset, rwp_wait);
+ if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
+ /* Misconfigured PPIs are usually not fatal */
+ pr_warn("GIC: PPI INTID%d is secure or misconfigured\n", irq);
+ ret = 0;
+ }
+
+ return ret;
}
static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
@@ -500,7 +632,12 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
gic_arch_enable_irqs();
}
- if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
+ /* Check for special IDs first */
+ if ((irqnr >= 1020 && irqnr <= 1023))
+ return;
+
+ /* Treat anything but SGIs in a uniform way */
+ if (likely(irqnr > 15)) {
int err;
if (static_branch_likely(&supports_deactivate_key))
@@ -588,10 +725,26 @@ static void __init gic_dist_init(void)
* do the right thing if the kernel is running in secure mode,
* but that's not the intended use case anyway.
*/
- for (i = 32; i < gic_data.irq_nr; i += 32)
+ for (i = 32; i < GIC_LINE_NR; i += 32)
writel_relaxed(~0, base + GICD_IGROUPR + i / 8);
- gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
+ /* Extended SPI range, not handled by the GICv2/GICv3 common code */
+ for (i = 0; i < GIC_ESPI_NR; i += 32) {
+ writel_relaxed(~0U, base + GICD_ICENABLERnE + i / 8);
+ writel_relaxed(~0U, base + GICD_ICACTIVERnE + i / 8);
+ }
+
+ for (i = 0; i < GIC_ESPI_NR; i += 32)
+ writel_relaxed(~0U, base + GICD_IGROUPRnE + i / 8);
+
+ for (i = 0; i < GIC_ESPI_NR; i += 16)
+ writel_relaxed(0, base + GICD_ICFGRnE + i / 4);
+
+ for (i = 0; i < GIC_ESPI_NR; i += 4)
+ writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
+
+ /* Now do the common stuff, and wait for the distributor to drain */
+ gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
/* Enable distributor with ARE, Group1 */
writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
@@ -602,8 +755,11 @@ static void __init gic_dist_init(void)
* enabled.
*/
affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
- for (i = 32; i < gic_data.irq_nr; i++)
+ for (i = 32; i < GIC_LINE_NR; i++)
gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
+
+ for (i = 0; i < GIC_ESPI_NR; i++)
+ gic_write_irouter(affinity, base + GICD_IROUTERnE + i * 8);
}
static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
@@ -689,19 +845,24 @@ static int gic_populate_rdist(void)
return -ENODEV;
}
-static int __gic_update_vlpi_properties(struct redist_region *region,
- void __iomem *ptr)
+static int __gic_update_rdist_properties(struct redist_region *region,
+ void __iomem *ptr)
{
u64 typer = gic_read_typer(ptr + GICR_TYPER);
gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
+ gic_data.ppi_nr = min(GICR_TYPER_NR_PPIS(typer), gic_data.ppi_nr);
return 1;
}
-static void gic_update_vlpi_properties(void)
+static void gic_update_rdist_properties(void)
{
- gic_iterate_rdists(__gic_update_vlpi_properties);
+ gic_data.ppi_nr = UINT_MAX;
+ gic_iterate_rdists(__gic_update_rdist_properties);
+ if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
+ gic_data.ppi_nr = 0;
+ pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
pr_info("%sVLPI support, %sdirect LPI support\n",
!gic_data.rdists.has_vlpis ? "no " : "",
!gic_data.rdists.has_direct_lpi ? "no " : "");
@@ -771,8 +932,10 @@ static void gic_cpu_sys_reg_init(void)
case 7:
write_gicreg(0, ICC_AP0R3_EL1);
write_gicreg(0, ICC_AP0R2_EL1);
+ /* Fall through */
case 6:
write_gicreg(0, ICC_AP0R1_EL1);
+ /* Fall through */
case 5:
case 4:
write_gicreg(0, ICC_AP0R0_EL1);
@@ -786,8 +949,10 @@ static void gic_cpu_sys_reg_init(void)
case 7:
write_gicreg(0, ICC_AP1R3_EL1);
write_gicreg(0, ICC_AP1R2_EL1);
+ /* Fall through */
case 6:
write_gicreg(0, ICC_AP1R1_EL1);
+ /* Fall through */
case 5:
case 4:
write_gicreg(0, ICC_AP1R0_EL1);
@@ -841,6 +1006,7 @@ static int gic_dist_supports_lpis(void)
static void gic_cpu_init(void)
{
void __iomem *rbase;
+ int i;
/* Register ourselves with the rest of the world */
if (gic_populate_rdist())
@@ -848,12 +1014,18 @@ static void gic_cpu_init(void)
gic_enable_redist(true);
+ WARN((gic_data.ppi_nr > 16 || GIC_ESPI_NR != 0) &&
+ !(gic_read_ctlr() & ICC_CTLR_EL1_ExtRange),
+ "Distributor has extended ranges, but CPU%d doesn't\n",
+ smp_processor_id());
+
rbase = gic_data_rdist_sgi_base();
/* Configure SGIs/PPIs as non-secure Group-1 */
- writel_relaxed(~0, rbase + GICR_IGROUPR0);
+ for (i = 0; i < gic_data.ppi_nr + 16; i += 32)
+ writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);
- gic_cpu_config(rbase, gic_redist_wait_for_rwp);
+ gic_cpu_config(rbase, gic_data.ppi_nr + 16, gic_redist_wait_for_rwp);
/* initialise system registers */
gic_cpu_sys_reg_init();
@@ -957,6 +1129,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
unsigned int cpu;
+ u32 offset, index;
void __iomem *reg;
int enabled;
u64 val;
@@ -977,7 +1150,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if (enabled)
gic_mask_irq(d);
- reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
+ offset = convert_offset_index(d, GICD_IROUTER, &index);
+ reg = gic_dist_base(d) + offset + (index * 8);
val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
gic_write_irouter(val, reg);
@@ -1061,8 +1235,6 @@ static struct irq_chip gic_eoimode1_chip = {
IRQCHIP_MASK_ON_SUSPEND,
};
-#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
-
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
@@ -1071,36 +1243,32 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
if (static_branch_likely(&supports_deactivate_key))
chip = &gic_eoimode1_chip;
- /* SGIs are private to the core kernel */
- if (hw < 16)
- return -EPERM;
- /* Nothing here */
- if (hw >= gic_data.irq_nr && hw < 8192)
- return -EPERM;
- /* Off limits */
- if (hw >= GIC_ID_NR)
- return -EPERM;
-
- /* PPIs */
- if (hw < 32) {
+ switch (__get_intid_range(hw)) {
+ case PPI_RANGE:
+ case EPPI_RANGE:
irq_set_percpu_devid(irq);
irq_domain_set_info(d, irq, hw, chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
irq_set_status_flags(irq, IRQ_NOAUTOEN);
- }
- /* SPIs */
- if (hw >= 32 && hw < gic_data.irq_nr) {
+ break;
+
+ case SPI_RANGE:
+ case ESPI_RANGE:
irq_domain_set_info(d, irq, hw, chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
- }
- /* LPIs */
- if (hw >= 8192 && hw < GIC_ID_NR) {
+ break;
+
+ case LPI_RANGE:
if (!gic_dist_supports_lpis())
return -EPERM;
irq_domain_set_info(d, irq, hw, chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
+ break;
+
+ default:
+ return -EPERM;
}
return 0;
@@ -1122,12 +1290,24 @@ static int gic_irq_domain_translate(struct irq_domain *d,
*hwirq = fwspec->param[1] + 32;
break;
case 1: /* PPI */
- case GIC_IRQ_TYPE_PARTITION:
*hwirq = fwspec->param[1] + 16;
break;
+ case 2: /* ESPI */
+ *hwirq = fwspec->param[1] + ESPI_BASE_INTID;
+ break;
+ case 3: /* EPPI */
+ *hwirq = fwspec->param[1] + EPPI_BASE_INTID;
+ break;
case GIC_IRQ_TYPE_LPI: /* LPI */
*hwirq = fwspec->param[1];
break;
+ case GIC_IRQ_TYPE_PARTITION:
+ *hwirq = fwspec->param[1];
+ if (fwspec->param[1] >= 16)
+ *hwirq += EPPI_BASE_INTID - 16;
+ else
+ *hwirq += 16;
+ break;
default:
return -EINVAL;
}
@@ -1207,7 +1387,8 @@ static int gic_irq_domain_select(struct irq_domain *d,
* then we need to match the partition domain.
*/
if (fwspec->param_count >= 4 &&
- fwspec->param[0] == 1 && fwspec->param[3] != 0)
+ fwspec->param[0] == 1 && fwspec->param[3] != 0 &&
+ gic_data.ppi_descs)
return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
return d == gic_data.domain;
@@ -1228,6 +1409,9 @@ static int partition_domain_translate(struct irq_domain *d,
struct device_node *np;
int ret;
+ if (!gic_data.ppi_descs)
+ return -ENOMEM;
+
np = of_find_node_by_phandle(fwspec->param[3]);
if (WARN_ON(!np))
return -EINVAL;
@@ -1257,11 +1441,65 @@ static bool gic_enable_quirk_msm8996(void *data)
return true;
}
+static bool gic_enable_quirk_hip06_07(void *data)
+{
+ struct gic_chip_data *d = data;
+
+ /*
+ * HIP06 GICD_IIDR clashes with GIC-600 product number (despite
+ * not being an actual ARM implementation). The saving grace is
+ * that GIC-600 doesn't have ESPI, so nothing to do in that case.
+ * HIP07 doesn't even have a proper IIDR, and still pretends to
+ * have ESPI. In both cases, put them right.
+ */
+ if (d->rdists.gicd_typer & GICD_TYPER_ESPI) {
+ /* Zero both ESPI and the RES0 field next to it... */
+ d->rdists.gicd_typer &= ~GENMASK(9, 8);
+ return true;
+ }
+
+ return false;
+}
+
+static const struct gic_quirk gic_quirks[] = {
+ {
+ .desc = "GICv3: Qualcomm MSM8996 broken firmware",
+ .compatible = "qcom,msm8996-gic-v3",
+ .init = gic_enable_quirk_msm8996,
+ },
+ {
+ .desc = "GICv3: HIP06 erratum 161010803",
+ .iidr = 0x0204043b,
+ .mask = 0xffffffff,
+ .init = gic_enable_quirk_hip06_07,
+ },
+ {
+ .desc = "GICv3: HIP07 erratum 161010803",
+ .iidr = 0x00000000,
+ .mask = 0xffffffff,
+ .init = gic_enable_quirk_hip06_07,
+ },
+ {
+ }
+};
+
static void gic_enable_nmi_support(void)
{
int i;
- for (i = 0; i < 16; i++)
+ if (!gic_prio_masking_enabled())
+ return;
+
+ if (gic_has_group0() && !gic_dist_security_disabled()) {
+ pr_warn("SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs\n");
+ return;
+ }
+
+ ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
+ if (!ppi_nmi_refs)
+ return;
+
+ for (i = 0; i < gic_data.ppi_nr; i++)
refcount_set(&ppi_nmi_refs[i], 0);
static_branch_enable(&supports_pseudo_nmis);
@@ -1279,7 +1517,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
struct fwnode_handle *handle)
{
u32 typer;
- int gic_irqs;
int err;
if (!is_hyp_mode_available())
@@ -1296,15 +1533,15 @@ static int __init gic_init_bases(void __iomem *dist_base,
/*
* Find out how many interrupts are supported.
- * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
*/
typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
gic_data.rdists.gicd_typer = typer;
- gic_irqs = GICD_TYPER_IRQS(typer);
- if (gic_irqs > 1020)
- gic_irqs = 1020;
- gic_data.irq_nr = gic_irqs;
+ gic_enable_quirks(readl_relaxed(gic_data.dist_base + GICD_IIDR),
+ gic_quirks, &gic_data);
+
+ pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
+ pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
&gic_data);
irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
@@ -1329,7 +1566,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
set_handle_irq(gic_handle_irq);
- gic_update_vlpi_properties();
+ gic_update_rdist_properties();
gic_smp_init();
gic_dist_init();
@@ -1344,12 +1581,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
gicv2m_init(handle, gic_data.domain);
}
- if (gic_prio_masking_enabled()) {
- if (!gic_has_group0() || gic_dist_security_disabled())
- gic_enable_nmi_support();
- else
- pr_warn("SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs\n");
- }
+ gic_enable_nmi_support();
return 0;
@@ -1382,6 +1614,10 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
if (!parts_node)
return;
+ gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL);
+ if (!gic_data.ppi_descs)
+ return;
+
nr_parts = of_get_child_count(parts_node);
if (!nr_parts)
@@ -1433,7 +1669,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
part_idx++;
}
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < gic_data.ppi_nr; i++) {
unsigned int irq;
struct partition_desc *desc;
struct irq_fwspec ppi_fwspec = {
@@ -1486,16 +1722,6 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
gic_set_kvm_info(&gic_v3_kvm_info);
}
-static const struct gic_quirk gic_quirks[] = {
- {
- .desc = "GICv3: Qualcomm MSM8996 broken firmware",
- .compatible = "qcom,msm8996-gic-v3",
- .init = gic_enable_quirk_msm8996,
- },
- {
- }
-};
-
static int __init gic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *dist_base;
@@ -1841,7 +2067,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
if (err)
goto out_redist_unmap;
- domain_handle = irq_domain_alloc_fwnode(acpi_data.dist_base);
+ domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
if (!domain_handle) {
err = -ENOMEM;
goto out_redist_unmap;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index e45f45e68720..30ab623343d3 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -291,6 +291,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
+ int ret;
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
@@ -301,7 +302,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- return gic_configure_irq(gicirq, type, base, NULL);
+ ret = gic_configure_irq(gicirq, type, base + GIC_DIST_CONFIG, NULL);
+ if (ret && gicirq < 32) {
+ /* Misconfigured PPIs are usually not fatal */
+ pr_warn("GIC: PPI%d is secure or misconfigured\n", gicirq - 16);
+ ret = 0;
+ }
+
+ return ret;
}
static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
@@ -535,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
gic_cpu_map[i] &= ~cpu_mask;
}
- gic_cpu_config(dist_base, NULL);
+ gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
gic_cpu_if_up(gic);
@@ -1627,7 +1635,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
/*
* Initialize GIC instance zero (no multi-GIC support).
*/
- domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
+ domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
if (!domain_handle) {
pr_err("Unable to allocate domain handle\n");
gic_teardown(gic);
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index cf705827599c..130caa1c9d93 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -130,7 +130,12 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
raw_spin_lock(&irq_controller_lock);
- ret = gic_configure_irq(irq, type, base, NULL);
+ ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG, NULL);
+ if (ret && irq < 32) {
+ /* Misconfigured PPIs are usually not fatal */
+ pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
+ ret = 0;
+ }
raw_spin_unlock(&irq_controller_lock);
@@ -268,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask;
- gic_cpu_config(dist_base, NULL);
+ gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index d00489a4b54f..698d07f48fed 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -362,10 +362,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
}
for (i = 0; i < priv->nr_perips; ++i) {
irq = platform_get_irq(pdev, 1 + i);
- if (irq < 0) {
- dev_err(&pdev->dev, "cannot find perip IRQ #%u\n", i);
+ if (irq < 0)
return irq;
- }
priv->perip_irqs[i] = irq;
}
/* check if too many were provided */
@@ -376,10 +374,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
/* Get syswake IRQ number */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "cannot find syswake IRQ\n");
+ if (irq < 0)
return irq;
- }
priv->syswake_irq = irq;
/* Set up an IRQ domain */
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index bf2237ac5d09..4f74c15c4755 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -131,6 +131,7 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
.irq_unmask = imx_gpcv2_irq_unmask,
.irq_set_wake = imx_gpcv2_irq_set_wake,
.irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_type = irq_chip_set_type_parent,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
#endif
diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
index 6751c35b7e1d..37e0749215c7 100644
--- a/drivers/irqchip/irq-ixp4xx.c
+++ b/drivers/irqchip/irq-ixp4xx.c
@@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase,
pr_crit("IXP4XX: could not ioremap interrupt controller\n");
return;
}
- fwnode = irq_domain_alloc_fwnode(base);
+ fwnode = irq_domain_alloc_fwnode(&irqbase);
if (!fwnode) {
pr_crit("IXP4XX: no domain handle\n");
return;
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index efbcf8435185..8118ebe80b09 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -164,10 +164,8 @@ static int keystone_irq_probe(struct platform_device *pdev)
}
kirq->irq = platform_get_irq(pdev, 0);
- if (kirq->irq < 0) {
- dev_err(dev, "no irq resource %d\n", kirq->irq);
+ if (kirq->irq < 0)
return kirq->irq;
- }
kirq->dev = dev;
kirq->mask = ~0x0;
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
index 3dd28382d5f5..3f09f658e8e2 100644
--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -241,12 +241,15 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
parent = platform_bus_type.dev_root;
child = of_platform_device_create(np, NULL, parent);
- if (!child)
+ if (!child) {
+ of_node_put(np);
return -ENOMEM;
+ }
if (of_property_read_u32(child->dev.of_node, "num-pins",
&num_pins) < 0) {
dev_err(&pdev->dev, "No num-pins property\n");
+ of_node_put(np);
return -EINVAL;
}
@@ -254,8 +257,10 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
mbigen_write_msg,
&mbigen_domain_ops,
mgn_chip);
- if (!domain)
+ if (!domain) {
+ of_node_put(np);
return -ENOMEM;
+ }
}
return 0;
diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index dcdc23b9dce6..829084b568fa 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -24,14 +24,25 @@
#define REG_PIN_47_SEL 0x08
#define REG_FILTER_SEL 0x0c
-#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x)))
+/*
+ * Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
+ * bits 24 to 31. Tests on the actual HW show that these bits are
+ * stuck at 0. Bits 8 to 15 are responsive and have the expected
+ * effect.
+ */
#define REG_EDGE_POL_EDGE(x) BIT(x)
#define REG_EDGE_POL_LOW(x) BIT(16 + (x))
+#define REG_BOTH_EDGE(x) BIT(8 + (x))
+#define REG_EDGE_POL_MASK(x) ( \
+ REG_EDGE_POL_EDGE(x) | \
+ REG_EDGE_POL_LOW(x) | \
+ REG_BOTH_EDGE(x))
#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
#define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
struct meson_gpio_irq_params {
unsigned int nr_hwirq;
+ bool support_edge_both;
};
static const struct meson_gpio_irq_params meson8_params = {
@@ -54,6 +65,11 @@ static const struct meson_gpio_irq_params axg_params = {
.nr_hwirq = 100,
};
+static const struct meson_gpio_irq_params sm1_params = {
+ .nr_hwirq = 100,
+ .support_edge_both = true,
+};
+
static const struct of_device_id meson_irq_gpio_matches[] = {
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
@@ -61,11 +77,12 @@ static const struct of_device_id meson_irq_gpio_matches[] = {
{ .compatible = "amlogic,meson-gxl-gpio-intc", .data = &gxl_params },
{ .compatible = "amlogic,meson-axg-gpio-intc", .data = &axg_params },
{ .compatible = "amlogic,meson-g12a-gpio-intc", .data = &axg_params },
+ { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
{ }
};
struct meson_gpio_irq_controller {
- unsigned int nr_hwirq;
+ const struct meson_gpio_irq_params *params;
void __iomem *base;
u32 channel_irqs[NUM_CHANNEL];
DECLARE_BITMAP(channel_map, NUM_CHANNEL);
@@ -168,14 +185,22 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
*/
type &= IRQ_TYPE_SENSE_MASK;
- if (type == IRQ_TYPE_EDGE_BOTH)
- return -EINVAL;
+ /*
+ * New controller support EDGE_BOTH trigger. This setting takes
+ * precedence over the other edge/polarity settings
+ */
+ if (type == IRQ_TYPE_EDGE_BOTH) {
+ if (!ctl->params->support_edge_both)
+ return -EINVAL;
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
- val |= REG_EDGE_POL_EDGE(idx);
+ val |= REG_BOTH_EDGE(idx);
+ } else {
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ val |= REG_EDGE_POL_EDGE(idx);
- if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
- val |= REG_EDGE_POL_LOW(idx);
+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
+ val |= REG_EDGE_POL_LOW(idx);
+ }
spin_lock(&ctl->lock);
@@ -199,7 +224,7 @@ static unsigned int meson_gpio_irq_type_output(unsigned int type)
*/
if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
type |= IRQ_TYPE_LEVEL_HIGH;
- else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ else
type |= IRQ_TYPE_EDGE_RISING;
return type;
@@ -328,15 +353,13 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node,
struct meson_gpio_irq_controller *ctl)
{
const struct of_device_id *match;
- const struct meson_gpio_irq_params *params;
int ret;
match = of_match_node(meson_irq_gpio_matches, node);
if (!match)
return -ENODEV;
- params = match->data;
- ctl->nr_hwirq = params->nr_hwirq;
+ ctl->params = match->data;
ret = of_property_read_variable_u32_array(node,
"amlogic,channel-interrupts",
@@ -385,7 +408,8 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
if (ret)
goto free_channel_irqs;
- domain = irq_domain_create_hierarchy(parent_domain, 0, ctl->nr_hwirq,
+ domain = irq_domain_create_hierarchy(parent_domain, 0,
+ ctl->params->nr_hwirq,
of_node_to_fwnode(node),
&meson_gpio_irq_domain_ops,
ctl);
@@ -396,7 +420,7 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
}
pr_info("%d to %d gpio interrupt mux initialized\n",
- ctl->nr_hwirq, NUM_CHANNEL);
+ ctl->params->nr_hwirq, NUM_CHANNEL);
return 0;
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
index 14618dc0bd39..4a74ac7b7c42 100644
--- a/drivers/irqchip/irq-mmp.c
+++ b/drivers/irqchip/irq-mmp.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/ioport.h>
@@ -43,6 +44,7 @@ struct icu_chip_data {
unsigned int conf_enable;
unsigned int conf_disable;
unsigned int conf_mask;
+ unsigned int conf2_mask;
unsigned int clr_mfp_irq_base;
unsigned int clr_mfp_hwirq;
struct irq_domain *domain;
@@ -52,9 +54,11 @@ struct mmp_intc_conf {
unsigned int conf_enable;
unsigned int conf_disable;
unsigned int conf_mask;
+ unsigned int conf2_mask;
};
static void __iomem *mmp_icu_base;
+static void __iomem *mmp_icu2_base;
static struct icu_chip_data icu_data[MAX_ICU_NR];
static int max_icu_nr;
@@ -97,6 +101,16 @@ static void icu_mask_irq(struct irq_data *d)
r &= ~data->conf_mask;
r |= data->conf_disable;
writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+
+ if (data->conf2_mask) {
+ /*
+ * ICU1 (above) only controls PJ4 MP1; if using SMP,
+ * we need to also mask the MP2 and MM cores via ICU2.
+ */
+ r = readl_relaxed(mmp_icu2_base + (hwirq << 2));
+ r &= ~data->conf2_mask;
+ writel_relaxed(r, mmp_icu2_base + (hwirq << 2));
+ }
} else {
r = readl_relaxed(data->reg_mask) | (1 << hwirq);
writel_relaxed(r, data->reg_mask);
@@ -132,11 +146,14 @@ struct irq_chip icu_irq_chip = {
static void icu_mux_irq_demux(struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *domain;
struct icu_chip_data *data;
int i;
unsigned long mask, status, n;
+ chained_irq_enter(chip, desc);
+
for (i = 1; i < max_icu_nr; i++) {
if (irq == icu_data[i].cascade_irq) {
domain = icu_data[i].domain;
@@ -146,7 +163,7 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
}
if (i >= max_icu_nr) {
pr_err("Spurious irq %d in MMP INTC\n", irq);
- return;
+ goto out;
}
mask = readl_relaxed(data->reg_mask);
@@ -158,6 +175,9 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
generic_handle_irq(icu_data[i].virq_base + n);
}
}
+
+out:
+ chained_irq_exit(chip, desc);
}
static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
@@ -194,6 +214,14 @@ static const struct mmp_intc_conf mmp2_conf = {
MMP2_ICU_INT_ROUTE_PJ4_FIQ,
};
+static struct mmp_intc_conf mmp3_conf = {
+ .conf_enable = 0x20,
+ .conf_disable = 0x0,
+ .conf_mask = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
+ MMP2_ICU_INT_ROUTE_PJ4_FIQ,
+ .conf2_mask = 0xf0,
+};
+
static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
{
int hwirq;
@@ -395,7 +423,6 @@ static int __init mmp_of_init(struct device_node *node,
icu_data[0].conf_enable = mmp_conf.conf_enable;
icu_data[0].conf_disable = mmp_conf.conf_disable;
icu_data[0].conf_mask = mmp_conf.conf_mask;
- irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp_handle_irq);
max_icu_nr = 1;
return 0;
@@ -414,19 +441,50 @@ static int __init mmp2_of_init(struct device_node *node,
icu_data[0].conf_enable = mmp2_conf.conf_enable;
icu_data[0].conf_disable = mmp2_conf.conf_disable;
icu_data[0].conf_mask = mmp2_conf.conf_mask;
- irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp2_handle_irq);
max_icu_nr = 1;
return 0;
}
IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init);
+static int __init mmp3_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ int ret;
+
+ mmp_icu2_base = of_iomap(node, 1);
+ if (!mmp_icu2_base) {
+ pr_err("Failed to get interrupt controller register #2\n");
+ return -ENODEV;
+ }
+
+ ret = mmp_init_bases(node);
+ if (ret < 0) {
+ iounmap(mmp_icu2_base);
+ return ret;
+ }
+
+ icu_data[0].conf_enable = mmp3_conf.conf_enable;
+ icu_data[0].conf_disable = mmp3_conf.conf_disable;
+ icu_data[0].conf_mask = mmp3_conf.conf_mask;
+ icu_data[0].conf2_mask = mmp3_conf.conf2_mask;
+
+ if (!parent) {
+ /* This is the main interrupt controller. */
+ set_handle_irq(mmp2_handle_irq);
+ }
+
+ max_icu_nr = 1;
+ return 0;
+}
+IRQCHIP_DECLARE(mmp3_intc, "marvell,mmp3-intc", mmp3_of_init);
+
static int __init mmp2_mux_of_init(struct device_node *node,
struct device_node *parent)
{
- struct resource res;
int i, ret, irq, j = 0;
u32 nr_irqs, mfp_irq;
+ u32 reg[4];
if (!parent)
return -ENODEV;
@@ -438,18 +496,22 @@ static int __init mmp2_mux_of_init(struct device_node *node,
pr_err("Not found mrvl,intc-nr-irqs property\n");
return -EINVAL;
}
- ret = of_address_to_resource(node, 0, &res);
- if (ret < 0) {
- pr_err("Not found reg property\n");
- return -EINVAL;
- }
- icu_data[i].reg_status = mmp_icu_base + res.start;
- ret = of_address_to_resource(node, 1, &res);
+
+ /*
+ * For historical reasons, the "regs" property of the
+ * mrvl,mmp2-mux-intc is not a regular "regs" property containing
+ * addresses on the parent bus, but offsets from the intc's base.
+ * That is why we can't use of_address_to_resource() here.
+ */
+ ret = of_property_read_variable_u32_array(node, "reg", reg,
+ ARRAY_SIZE(reg),
+ ARRAY_SIZE(reg));
if (ret < 0) {
pr_err("Not found reg property\n");
return -EINVAL;
}
- icu_data[i].reg_mask = mmp_icu_base + res.start;
+ icu_data[i].reg_status = mmp_icu_base + reg[0];
+ icu_data[i].reg_mask = mmp_icu_base + reg[2];
icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
if (!icu_data[i].cascade_irq)
return -EINVAL;
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index cf755964f2f8..c72c036aea76 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -244,6 +244,7 @@ static int __init plic_init(struct device_node *node,
struct plic_handler *handler;
irq_hw_number_t hwirq;
int cpu, hartid;
+ u32 threshold = 0;
if (of_irq_parse_one(node, i, &parent)) {
pr_err("failed to parse parent for context %d.\n", i);
@@ -266,10 +267,16 @@ static int __init plic_init(struct device_node *node,
continue;
}
+ /*
+ * When running in M-mode we need to ignore the S-mode handler.
+ * Here we assume it always comes later, but that might be a
+ * little fragile.
+ */
handler = per_cpu_ptr(&plic_handlers, cpu);
if (handler->present) {
pr_warn("handler already present for context %d.\n", i);
- continue;
+ threshold = 0xffffffff;
+ goto done;
}
handler->present = true;
@@ -279,8 +286,9 @@ static int __init plic_init(struct device_node *node,
handler->enable_base =
plic_regs + ENABLE_BASE + i * ENABLE_PER_HART;
+done:
/* priority must be > threshold to trigger an interrupt */
- writel(0, handler->hart_base + CONTEXT_THRESHOLD);
+ writel(threshold, handler->hart_base + CONTEXT_THRESHOLD);
for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
plic_toggle(handler, hwirq, 0);
nr_handlers++;
diff --git a/drivers/irqchip/irq-uniphier-aidet.c b/drivers/irqchip/irq-uniphier-aidet.c
index ed7b4f47ff3f..89121b39be26 100644
--- a/drivers/irqchip/irq-uniphier-aidet.c
+++ b/drivers/irqchip/irq-uniphier-aidet.c
@@ -166,7 +166,6 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
struct device_node *parent_np;
struct irq_domain *parent_domain;
struct uniphier_aidet_priv *priv;
- struct resource *res;
parent_np = of_irq_find_parent(dev->of_node);
if (!parent_np)
@@ -181,8 +180,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->reg_base = devm_ioremap_resource(dev, res);
+ priv->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->reg_base))
return PTR_ERR(priv->reg_base);
diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c
index d88e993aa66d..abfe59284ff2 100644
--- a/drivers/irqchip/qcom-irq-combiner.c
+++ b/drivers/irqchip/qcom-irq-combiner.c
@@ -248,10 +248,8 @@ static int __init combiner_probe(struct platform_device *pdev)
return err;
combiner->parent_irq = platform_get_irq(pdev, 0);
- if (combiner->parent_irq <= 0) {
- dev_err(&pdev->dev, "Error getting IRQ resource\n");
+ if (combiner->parent_irq <= 0)
return -EPROBE_DEFER;
- }
combiner->domain = irq_domain_create_linear(pdev->dev.fwnode, combiner->nirqs,
&domain_ops, combiner);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 3c3ad42f22bf..c92b405b7646 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -688,6 +688,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
if (!cdev->ap.applid)
return -ENODEV;
+ if (count < CAPIMSG_BASELEN)
+ return -EINVAL;
+
skb = alloc_skb(count, GFP_USER);
if (!skb)
return -ENOMEM;
@@ -698,7 +701,8 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
}
mlen = CAPIMSG_LEN(skb->data);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
- if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
+ if (count < CAPI_DATA_B3_REQ_LEN ||
+ (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
kfree_skb(skb);
return -EINVAL;
}
@@ -711,6 +715,10 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
+ if (count < CAPI_DISCONNECT_B3_RESP_LEN) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
mutex_lock(&cdev->lock);
capincci_free(cdev, CAPIMSG_NCCI(skb->data));
mutex_unlock(&cdev->lock);
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 0e224232f746..008a74a1ed44 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -1394,6 +1394,7 @@ start_isoc_chain(struct usb_fifo *fifo, int num_packets_per_urb,
printk(KERN_DEBUG
"%s: %s: alloc urb for fifo %i failed",
hw->name, __func__, fifo->fifonum);
+ continue;
}
fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
fifo->iso[i].indx = i;
@@ -1692,13 +1693,23 @@ hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel)
static int
setup_hfcsusb(struct hfcsusb *hw)
{
+ void *dmabuf = kmalloc(sizeof(u_char), GFP_KERNEL);
u_char b;
+ int ret;
if (debug & DBG_HFC_CALL_TRACE)
printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+ if (!dmabuf)
+ return -ENOMEM;
+
+ ret = read_reg_atomic(hw, HFCUSB_CHIP_ID, dmabuf);
+
+ memcpy(&b, dmabuf, sizeof(u_char));
+ kfree(dmabuf);
+
/* check the chip id */
- if (read_reg_atomic(hw, HFCUSB_CHIP_ID, &b) != 1) {
+ if (ret != 1) {
printk(KERN_DEBUG "%s: %s: cannot read chip id\n",
hw->name, __func__);
return 1;
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 276065c888bc..23f1f41c8602 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -852,6 +852,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
break;
case SMU_I2C_TRANSFER_COMBINED:
cmd->info.devaddr &= 0xfe;
+ /* fall through */
case SMU_I2C_TRANSFER_STDSUB:
if (cmd->info.sublen > 3)
return -EINVAL;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 26e374fbf57c..20ed838e9413 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -931,6 +931,9 @@ int bch_cached_dev_run(struct cached_dev *dc)
if (dc->io_disable) {
pr_err("I/O disabled on cached dev %s",
dc->backing_dev_name);
+ kfree(env[1]);
+ kfree(env[2]);
+ kfree(buf);
return -EIO;
}
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 9f0826712845..e2059af90791 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -23,24 +23,28 @@ static const char * const bch_cache_modes[] = {
"writethrough",
"writeback",
"writearound",
- "none"
+ "none",
+ NULL
};
/* Default is 0 ("auto") */
static const char * const bch_stop_on_failure_modes[] = {
"auto",
- "always"
+ "always",
+ NULL
};
static const char * const cache_replacement_policies[] = {
"lru",
"fifo",
- "random"
+ "random",
+ NULL
};
static const char * const error_actions[] = {
"unregister",
- "panic"
+ "panic",
+ NULL
};
write_attribute(attach);
@@ -338,7 +342,7 @@ STORE(__cached_dev)
}
if (attr == &sysfs_cache_mode) {
- v = sysfs_match_string(bch_cache_modes, buf);
+ v = __sysfs_match_string(bch_cache_modes, -1, buf);
if (v < 0)
return v;
@@ -349,7 +353,7 @@ STORE(__cached_dev)
}
if (attr == &sysfs_stop_when_cache_set_failed) {
- v = sysfs_match_string(bch_stop_on_failure_modes, buf);
+ v = __sysfs_match_string(bch_stop_on_failure_modes, -1, buf);
if (v < 0)
return v;
@@ -816,7 +820,7 @@ STORE(__bch_cache_set)
0, UINT_MAX);
if (attr == &sysfs_errors) {
- v = sysfs_match_string(error_actions, buf);
+ v = __sysfs_match_string(error_actions, -1, buf);
if (v < 0)
return v;
@@ -1088,7 +1092,7 @@ STORE(__bch_cache)
}
if (attr == &sysfs_cache_replacement_policy) {
- v = sysfs_match_string(cache_replacement_policies, buf);
+ v = __sysfs_match_string(cache_replacement_policies, -1, buf);
if (v < 0)
return v;
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index b6b5acc92ca2..2a48ea3f1b30 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1599,7 +1599,9 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
unsigned long freed;
c = container_of(shrink, struct dm_bufio_client, shrinker);
- if (!dm_bufio_trylock(c))
+ if (sc->gfp_mask & __GFP_FS)
+ dm_bufio_lock(c);
+ else if (!dm_bufio_trylock(c))
return SHRINK_STOP;
freed = __scan(c, sc->nr_to_scan, sc->gfp_mask);
diff --git a/drivers/md/dm-dust.c b/drivers/md/dm-dust.c
index 845f376a72d9..8288887b7f94 100644
--- a/drivers/md/dm-dust.c
+++ b/drivers/md/dm-dust.c
@@ -25,6 +25,7 @@ struct dust_device {
unsigned long long badblock_count;
spinlock_t dust_lock;
unsigned int blksz;
+ int sect_per_block_shift;
unsigned int sect_per_block;
sector_t start;
bool fail_read_on_bb:1;
@@ -79,7 +80,7 @@ static int dust_remove_block(struct dust_device *dd, unsigned long long block)
unsigned long flags;
spin_lock_irqsave(&dd->dust_lock, flags);
- bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+ bblock = dust_rb_search(&dd->badblocklist, block);
if (bblock == NULL) {
if (!dd->quiet_mode) {
@@ -113,7 +114,7 @@ static int dust_add_block(struct dust_device *dd, unsigned long long block)
}
spin_lock_irqsave(&dd->dust_lock, flags);
- bblock->bb = block * dd->sect_per_block;
+ bblock->bb = block;
if (!dust_rb_insert(&dd->badblocklist, bblock)) {
if (!dd->quiet_mode) {
DMERR("%s: block %llu already in badblocklist",
@@ -138,7 +139,7 @@ static int dust_query_block(struct dust_device *dd, unsigned long long block)
unsigned long flags;
spin_lock_irqsave(&dd->dust_lock, flags);
- bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+ bblock = dust_rb_search(&dd->badblocklist, block);
if (bblock != NULL)
DMINFO("%s: block %llu found in badblocklist", __func__, block);
else
@@ -165,6 +166,7 @@ static int dust_map_read(struct dust_device *dd, sector_t thisblock,
int ret = DM_MAPIO_REMAPPED;
if (fail_read_on_bb) {
+ thisblock >>= dd->sect_per_block_shift;
spin_lock_irqsave(&dd->dust_lock, flags);
ret = __dust_map_read(dd, thisblock);
spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -195,6 +197,7 @@ static int dust_map_write(struct dust_device *dd, sector_t thisblock,
unsigned long flags;
if (fail_read_on_bb) {
+ thisblock >>= dd->sect_per_block_shift;
spin_lock_irqsave(&dd->dust_lock, flags);
__dust_map_write(dd, thisblock);
spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -331,6 +334,8 @@ static int dust_ctr(struct dm_target *ti, unsigned int argc, char **argv)
dd->blksz = blksz;
dd->start = tmp;
+ dd->sect_per_block_shift = __ffs(sect_per_block);
+
/*
* Whether to fail a read on a "bad" block.
* Defaults to false; enabled later by message.
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index b1b0de402dfc..9118ab85cb3a 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1943,7 +1943,22 @@ offload_to_thread:
queue_work(ic->wait_wq, &dio->work);
return;
}
+ if (journal_read_pos != NOT_FOUND)
+ dio->range.n_sectors = ic->sectors_per_block;
wait_and_add_new_range(ic, &dio->range);
+ /*
+ * wait_and_add_new_range drops the spinlock, so the journal
+ * may have been changed arbitrarily. We need to recheck.
+ * To simplify the code, we restrict I/O size to just one block.
+ */
+ if (journal_read_pos != NOT_FOUND) {
+ sector_t next_sector;
+ unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+ if (unlikely(new_pos != journal_read_pos)) {
+ remove_range_unlocked(ic, &dio->range);
+ goto retry;
+ }
+ }
}
spin_unlock_irq(&ic->endio_wait.lock);
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index df2011de7be2..1bbe4a34ef4c 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -566,8 +566,10 @@ static int run_io_job(struct kcopyd_job *job)
* no point in continuing.
*/
if (test_bit(DM_KCOPYD_WRITE_SEQ, &job->flags) &&
- job->master_job->write_err)
+ job->master_job->write_err) {
+ job->write_err = job->master_job->write_err;
return -EIO;
+ }
io_job_start(job->kc->throttle);
@@ -619,6 +621,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
else
job->read_err = 1;
push(&kc->complete_jobs, job);
+ wake(kc);
break;
}
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 8a60a4a070ac..1f933dd197cd 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3194,7 +3194,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
*/
r = rs_prepare_reshape(rs);
if (r)
- return r;
+ goto bad;
/* Reshaping ain't recovery, so disable recovery */
rs_setup_recovery(rs, MaxSector);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index caaee8032afe..8820931ec7d2 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -882,23 +882,23 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
/* validate the dax capability of the target device span */
int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
+ sector_t start, sector_t len, void *data)
{
int blocksize = *(int *) data;
return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
- start, len);
+ start, len);
}
/* Check devices support synchronous DAX */
-static int device_synchronous(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
+static int device_dax_synchronous(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
{
- return dax_synchronous(dev->dax_dev);
+ return dev->dax_dev && dax_synchronous(dev->dax_dev);
}
bool dm_table_supports_dax(struct dm_table *t,
- iterate_devices_callout_fn iterate_fn, int *blocksize)
+ iterate_devices_callout_fn iterate_fn, int *blocksize)
{
struct dm_target *ti;
unsigned i;
@@ -911,7 +911,7 @@ bool dm_table_supports_dax(struct dm_table *t,
return false;
if (!ti->type->iterate_devices ||
- !ti->type->iterate_devices(ti, iterate_fn, blocksize))
+ !ti->type->iterate_devices(ti, iterate_fn, blocksize))
return false;
}
@@ -1342,7 +1342,7 @@ void dm_table_event(struct dm_table *t)
}
EXPORT_SYMBOL(dm_table_event);
-sector_t dm_table_get_size(struct dm_table *t)
+inline sector_t dm_table_get_size(struct dm_table *t)
{
return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0;
}
@@ -1367,6 +1367,9 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
unsigned int l, n = 0, k = 0;
sector_t *node;
+ if (unlikely(sector >= dm_table_get_size(t)))
+ return &t->targets[t->num_targets];
+
for (l = 0; l < t->depth; l++) {
n = get_child(n, k);
node = get_node(t, l, n);
@@ -1921,7 +1924,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (dm_table_supports_dax(t, device_supports_dax, &page_size)) {
blk_queue_flag_set(QUEUE_FLAG_DAX, q);
- if (dm_table_supports_dax(t, device_synchronous, NULL))
+ if (dm_table_supports_dax(t, device_dax_synchronous, NULL))
set_dax_synchronous(t->md->dax_dev);
}
else
diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c
index 8545dcee9fd0..595a73110e17 100644
--- a/drivers/md/dm-zoned-metadata.c
+++ b/drivers/md/dm-zoned-metadata.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017 Western Digital Corporation or its affiliates.
*
@@ -34,7 +35,7 @@
* (1) Super block (1 block)
* (2) Chunk mapping table (nr_map_blocks)
* (3) Bitmap blocks (nr_bitmap_blocks)
- * All metadata blocks are stored in conventional zones, starting from the
+ * All metadata blocks are stored in conventional zones, starting from
* the first conventional zone found on disk.
*/
struct dmz_super {
@@ -233,7 +234,7 @@ void dmz_unlock_map(struct dmz_metadata *zmd)
* Lock/unlock metadata access. This is a "read" lock on a semaphore
* that prevents metadata flush from running while metadata are being
* modified. The actual metadata write mutual exclusion is achieved with
- * the map lock and zone styate management (active and reclaim state are
+ * the map lock and zone state management (active and reclaim state are
* mutually exclusive).
*/
void dmz_lock_metadata(struct dmz_metadata *zmd)
@@ -402,15 +403,18 @@ static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd,
sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no;
struct bio *bio;
+ if (dmz_bdev_is_dying(zmd->dev))
+ return ERR_PTR(-EIO);
+
/* Get a new block and a BIO to read it */
mblk = dmz_alloc_mblock(zmd, mblk_no);
if (!mblk)
- return NULL;
+ return ERR_PTR(-ENOMEM);
bio = bio_alloc(GFP_NOIO, 1);
if (!bio) {
dmz_free_mblock(zmd, mblk);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
spin_lock(&zmd->mblk_lock);
@@ -541,8 +545,8 @@ static struct dmz_mblock *dmz_get_mblock(struct dmz_metadata *zmd,
if (!mblk) {
/* Cache miss: read the block from disk */
mblk = dmz_get_mblock_slow(zmd, mblk_no);
- if (!mblk)
- return ERR_PTR(-ENOMEM);
+ if (IS_ERR(mblk))
+ return mblk;
}
/* Wait for on-going read I/O and check for error */
@@ -570,16 +574,19 @@ static void dmz_dirty_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk)
/*
* Issue a metadata block write BIO.
*/
-static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
- unsigned int set)
+static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
+ unsigned int set)
{
sector_t block = zmd->sb[set].block + mblk->no;
struct bio *bio;
+ if (dmz_bdev_is_dying(zmd->dev))
+ return -EIO;
+
bio = bio_alloc(GFP_NOIO, 1);
if (!bio) {
set_bit(DMZ_META_ERROR, &mblk->state);
- return;
+ return -ENOMEM;
}
set_bit(DMZ_META_WRITING, &mblk->state);
@@ -591,6 +598,8 @@ static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_META | REQ_PRIO);
bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
submit_bio(bio);
+
+ return 0;
}
/*
@@ -602,6 +611,9 @@ static int dmz_rdwr_block(struct dmz_metadata *zmd, int op, sector_t block,
struct bio *bio;
int ret;
+ if (dmz_bdev_is_dying(zmd->dev))
+ return -EIO;
+
bio = bio_alloc(GFP_NOIO, 1);
if (!bio)
return -ENOMEM;
@@ -659,22 +671,29 @@ static int dmz_write_dirty_mblocks(struct dmz_metadata *zmd,
{
struct dmz_mblock *mblk;
struct blk_plug plug;
- int ret = 0;
+ int ret = 0, nr_mblks_submitted = 0;
/* Issue writes */
blk_start_plug(&plug);
- list_for_each_entry(mblk, write_list, link)
- dmz_write_mblock(zmd, mblk, set);
+ list_for_each_entry(mblk, write_list, link) {
+ ret = dmz_write_mblock(zmd, mblk, set);
+ if (ret)
+ break;
+ nr_mblks_submitted++;
+ }
blk_finish_plug(&plug);
/* Wait for completion */
list_for_each_entry(mblk, write_list, link) {
+ if (!nr_mblks_submitted)
+ break;
wait_on_bit_io(&mblk->state, DMZ_META_WRITING,
TASK_UNINTERRUPTIBLE);
if (test_bit(DMZ_META_ERROR, &mblk->state)) {
clear_bit(DMZ_META_ERROR, &mblk->state);
ret = -EIO;
}
+ nr_mblks_submitted--;
}
/* Flush drive cache (this will also sync data) */
@@ -736,6 +755,11 @@ int dmz_flush_metadata(struct dmz_metadata *zmd)
*/
dmz_lock_flush(zmd);
+ if (dmz_bdev_is_dying(zmd->dev)) {
+ ret = -EIO;
+ goto out;
+ }
+
/* Get dirty blocks */
spin_lock(&zmd->mblk_lock);
list_splice_init(&zmd->mblk_dirty_list, &write_list);
@@ -1542,7 +1566,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
struct dm_zone *zone;
if (list_empty(&zmd->map_rnd_list))
- return NULL;
+ return ERR_PTR(-EBUSY);
list_for_each_entry(zone, &zmd->map_rnd_list, link) {
if (dmz_is_buf(zone))
@@ -1553,7 +1577,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
return dzone;
}
- return NULL;
+ return ERR_PTR(-EBUSY);
}
/*
@@ -1564,7 +1588,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
struct dm_zone *zone;
if (list_empty(&zmd->map_seq_list))
- return NULL;
+ return ERR_PTR(-EBUSY);
list_for_each_entry(zone, &zmd->map_seq_list, link) {
if (!zone->bzone)
@@ -1573,7 +1597,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
return zone;
}
- return NULL;
+ return ERR_PTR(-EBUSY);
}
/*
@@ -1628,9 +1652,13 @@ again:
if (op != REQ_OP_WRITE)
goto out;
- /* Alloate a random zone */
+ /* Allocate a random zone */
dzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
if (!dzone) {
+ if (dmz_bdev_is_dying(zmd->dev)) {
+ dzone = ERR_PTR(-EIO);
+ goto out;
+ }
dmz_wait_for_free_zones(zmd);
goto again;
}
@@ -1725,9 +1753,13 @@ again:
if (bzone)
goto out;
- /* Alloate a random zone */
+ /* Allocate a random zone */
bzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
if (!bzone) {
+ if (dmz_bdev_is_dying(zmd->dev)) {
+ bzone = ERR_PTR(-EIO);
+ goto out;
+ }
dmz_wait_for_free_zones(zmd);
goto again;
}
diff --git a/drivers/md/dm-zoned-reclaim.c b/drivers/md/dm-zoned-reclaim.c
index edf4b95eb075..d240d7ca8a8a 100644
--- a/drivers/md/dm-zoned-reclaim.c
+++ b/drivers/md/dm-zoned-reclaim.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017 Western Digital Corporation or its affiliates.
*
@@ -37,7 +38,7 @@ enum {
/*
* Number of seconds of target BIO inactivity to consider the target idle.
*/
-#define DMZ_IDLE_PERIOD (10UL * HZ)
+#define DMZ_IDLE_PERIOD (10UL * HZ)
/*
* Percentage of unmapped (free) random zones below which reclaim starts
@@ -134,6 +135,9 @@ static int dmz_reclaim_copy(struct dmz_reclaim *zrc,
set_bit(DM_KCOPYD_WRITE_SEQ, &flags);
while (block < end_block) {
+ if (dev->flags & DMZ_BDEV_DYING)
+ return -EIO;
+
/* Get a valid region from the source zone */
ret = dmz_first_valid_block(zmd, src_zone, &block);
if (ret <= 0)
@@ -215,7 +219,7 @@ static int dmz_reclaim_buf(struct dmz_reclaim *zrc, struct dm_zone *dzone)
dmz_unlock_flush(zmd);
- return 0;
+ return ret;
}
/*
@@ -259,7 +263,7 @@ static int dmz_reclaim_seq_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
dmz_unlock_flush(zmd);
- return 0;
+ return ret;
}
/*
@@ -312,7 +316,7 @@ static int dmz_reclaim_rnd_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
dmz_unlock_flush(zmd);
- return 0;
+ return ret;
}
/*
@@ -334,7 +338,7 @@ static void dmz_reclaim_empty(struct dmz_reclaim *zrc, struct dm_zone *dzone)
/*
* Find a candidate zone for reclaim and process it.
*/
-static void dmz_reclaim(struct dmz_reclaim *zrc)
+static int dmz_do_reclaim(struct dmz_reclaim *zrc)
{
struct dmz_metadata *zmd = zrc->metadata;
struct dm_zone *dzone;
@@ -344,8 +348,8 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
/* Get a data zone */
dzone = dmz_get_zone_for_reclaim(zmd);
- if (!dzone)
- return;
+ if (IS_ERR(dzone))
+ return PTR_ERR(dzone);
start = jiffies;
@@ -391,13 +395,20 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
out:
if (ret) {
dmz_unlock_zone_reclaim(dzone);
- return;
+ return ret;
}
- (void) dmz_flush_metadata(zrc->metadata);
+ ret = dmz_flush_metadata(zrc->metadata);
+ if (ret) {
+ dmz_dev_debug(zrc->dev,
+ "Metadata flush for zone %u failed, err %d\n",
+ dmz_id(zmd, rzone), ret);
+ return ret;
+ }
dmz_dev_debug(zrc->dev, "Reclaimed zone %u in %u ms",
dmz_id(zmd, rzone), jiffies_to_msecs(jiffies - start));
+ return 0;
}
/*
@@ -427,7 +438,7 @@ static bool dmz_should_reclaim(struct dmz_reclaim *zrc)
return false;
/*
- * If the percentage of unmappped random zones is low,
+ * If the percentage of unmapped random zones is low,
* reclaim even if the target is busy.
*/
return p_unmap_rnd <= DMZ_RECLAIM_LOW_UNMAP_RND;
@@ -442,6 +453,10 @@ static void dmz_reclaim_work(struct work_struct *work)
struct dmz_metadata *zmd = zrc->metadata;
unsigned int nr_rnd, nr_unmap_rnd;
unsigned int p_unmap_rnd;
+ int ret;
+
+ if (dmz_bdev_is_dying(zrc->dev))
+ return;
if (!dmz_should_reclaim(zrc)) {
mod_delayed_work(zrc->wq, &zrc->work, DMZ_IDLE_PERIOD);
@@ -471,7 +486,17 @@ static void dmz_reclaim_work(struct work_struct *work)
(dmz_target_idle(zrc) ? "Idle" : "Busy"),
p_unmap_rnd, nr_unmap_rnd, nr_rnd);
- dmz_reclaim(zrc);
+ ret = dmz_do_reclaim(zrc);
+ if (ret) {
+ dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret);
+ if (ret == -EIO)
+ /*
+ * LLD might be performing some error handling sequence
+ * at the underlying device. To not interfere, do not
+ * attempt to schedule the next reclaim run immediately.
+ */
+ return;
+ }
dmz_schedule_reclaim(zrc);
}
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index 51d029bbb740..31478fef6032 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017 Western Digital Corporation or its affiliates.
*
@@ -133,6 +134,8 @@ static int dmz_submit_bio(struct dmz_target *dmz, struct dm_zone *zone,
refcount_inc(&bioctx->ref);
generic_make_request(clone);
+ if (clone->bi_status == BLK_STS_IOERR)
+ return -EIO;
if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone))
zone->wp_block += nr_blocks;
@@ -277,8 +280,8 @@ static int dmz_handle_buffered_write(struct dmz_target *dmz,
/* Get the buffer zone. One will be allocated if needed */
bzone = dmz_get_chunk_buffer(zmd, zone);
- if (!bzone)
- return -ENOSPC;
+ if (IS_ERR(bzone))
+ return PTR_ERR(bzone);
if (dmz_is_readonly(bzone))
return -EROFS;
@@ -389,6 +392,11 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
dmz_lock_metadata(zmd);
+ if (dmz->dev->flags & DMZ_BDEV_DYING) {
+ ret = -EIO;
+ goto out;
+ }
+
/*
* Get the data zone mapping the chunk. There may be no
* mapping for read and discard. If a mapping is obtained,
@@ -493,6 +501,8 @@ static void dmz_flush_work(struct work_struct *work)
/* Flush dirty metadata blocks */
ret = dmz_flush_metadata(dmz->metadata);
+ if (ret)
+ dmz_dev_debug(dmz->dev, "Metadata flush failed, rc=%d\n", ret);
/* Process queued flush requests */
while (1) {
@@ -513,22 +523,24 @@ static void dmz_flush_work(struct work_struct *work)
* Get a chunk work and start it to process a new BIO.
* If the BIO chunk has no work yet, create one.
*/
-static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
+static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
{
unsigned int chunk = dmz_bio_chunk(dmz->dev, bio);
struct dm_chunk_work *cw;
+ int ret = 0;
mutex_lock(&dmz->chunk_lock);
/* Get the BIO chunk work. If one is not active yet, create one */
cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
if (!cw) {
- int ret;
/* Create a new chunk work */
cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
- if (!cw)
+ if (unlikely(!cw)) {
+ ret = -ENOMEM;
goto out;
+ }
INIT_WORK(&cw->work, dmz_chunk_work);
refcount_set(&cw->refcount, 0);
@@ -539,7 +551,6 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
ret = radix_tree_insert(&dmz->chunk_rxtree, chunk, cw);
if (unlikely(ret)) {
kfree(cw);
- cw = NULL;
goto out;
}
}
@@ -547,10 +558,38 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
bio_list_add(&cw->bio_list, bio);
dmz_get_chunk_work(cw);
+ dmz_reclaim_bio_acc(dmz->reclaim);
if (queue_work(dmz->chunk_wq, &cw->work))
dmz_get_chunk_work(cw);
out:
mutex_unlock(&dmz->chunk_lock);
+ return ret;
+}
+
+/*
+ * Check the backing device availability. If it's on the way out,
+ * start failing I/O. Reclaim and metadata components also call this
+ * function to cleanly abort operation in the event of such failure.
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev)
+{
+ struct gendisk *disk;
+
+ if (!(dmz_dev->flags & DMZ_BDEV_DYING)) {
+ disk = dmz_dev->bdev->bd_disk;
+ if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) {
+ dmz_dev_warn(dmz_dev, "Backing device queue dying");
+ dmz_dev->flags |= DMZ_BDEV_DYING;
+ } else if (disk->fops->check_events) {
+ if (disk->fops->check_events(disk, 0) &
+ DISK_EVENT_MEDIA_CHANGE) {
+ dmz_dev_warn(dmz_dev, "Backing device offline");
+ dmz_dev->flags |= DMZ_BDEV_DYING;
+ }
+ }
+ }
+
+ return dmz_dev->flags & DMZ_BDEV_DYING;
}
/*
@@ -564,6 +603,10 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
sector_t sector = bio->bi_iter.bi_sector;
unsigned int nr_sectors = bio_sectors(bio);
sector_t chunk_sector;
+ int ret;
+
+ if (dmz_bdev_is_dying(dmz->dev))
+ return DM_MAPIO_KILL;
dmz_dev_debug(dev, "BIO op %d sector %llu + %u => chunk %llu, block %llu, %u blocks",
bio_op(bio), (unsigned long long)sector, nr_sectors,
@@ -601,8 +644,14 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
dm_accept_partial_bio(bio, dev->zone_nr_sectors - chunk_sector);
/* Now ready to handle this BIO */
- dmz_reclaim_bio_acc(dmz->reclaim);
- dmz_queue_chunk_work(dmz, bio);
+ ret = dmz_queue_chunk_work(dmz, bio);
+ if (ret) {
+ dmz_dev_debug(dmz->dev,
+ "BIO op %d, can't process chunk %llu, err %i\n",
+ bio_op(bio), (u64)dmz_bio_chunk(dmz->dev, bio),
+ ret);
+ return DM_MAPIO_REQUEUE;
+ }
return DM_MAPIO_SUBMITTED;
}
@@ -855,6 +904,9 @@ static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
{
struct dmz_target *dmz = ti->private;
+ if (dmz_bdev_is_dying(dmz->dev))
+ return -ENODEV;
+
*bdev = dmz->dev->bdev;
return 0;
diff --git a/drivers/md/dm-zoned.h b/drivers/md/dm-zoned.h
index ed8de49c9a08..d8e70b0ade35 100644
--- a/drivers/md/dm-zoned.h
+++ b/drivers/md/dm-zoned.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Western Digital Corporation or its affiliates.
*
@@ -56,6 +57,8 @@ struct dmz_dev {
unsigned int nr_zones;
+ unsigned int flags;
+
sector_t zone_nr_sectors;
unsigned int zone_nr_sectors_shift;
@@ -67,6 +70,9 @@ struct dmz_dev {
(dev)->zone_nr_sectors_shift)
#define dmz_chunk_block(dev, b) ((b) & ((dev)->zone_nr_blocks - 1))
+/* Device flags. */
+#define DMZ_BDEV_DYING (1 << 0)
+
/*
* Zone descriptor.
*/
@@ -245,4 +251,9 @@ void dmz_resume_reclaim(struct dmz_reclaim *zrc);
void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc);
void dmz_schedule_reclaim(struct dmz_reclaim *zrc);
+/*
+ * Functions defined in dm-zoned-target.c
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev);
+
#endif /* DM_ZONED_H */
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index 58b319757b1e..8aae0624a297 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -628,39 +628,40 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
new_parent = shadow_current(s);
+ pn = dm_block_data(new_parent);
+ size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+ sizeof(__le64) : s->info->value_type.size;
+
+ /* create & init the left block */
r = new_block(s->info, &left);
if (r < 0)
return r;
+ ln = dm_block_data(left);
+ nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+
+ ln->header.flags = pn->header.flags;
+ ln->header.nr_entries = cpu_to_le32(nr_left);
+ ln->header.max_entries = pn->header.max_entries;
+ ln->header.value_size = pn->header.value_size;
+ memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+ memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
+
+ /* create & init the right block */
r = new_block(s->info, &right);
if (r < 0) {
unlock_block(s->info, left);
return r;
}
- pn = dm_block_data(new_parent);
- ln = dm_block_data(left);
rn = dm_block_data(right);
-
- nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
- ln->header.flags = pn->header.flags;
- ln->header.nr_entries = cpu_to_le32(nr_left);
- ln->header.max_entries = pn->header.max_entries;
- ln->header.value_size = pn->header.value_size;
-
rn->header.flags = pn->header.flags;
rn->header.nr_entries = cpu_to_le32(nr_right);
rn->header.max_entries = pn->header.max_entries;
rn->header.value_size = pn->header.value_size;
-
- memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
-
- size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
- sizeof(__le64) : s->info->value_type.size;
- memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left),
nr_right * size);
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index aec449243966..25328582cc48 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -249,7 +249,7 @@ static int out(struct sm_metadata *smm)
}
if (smm->recursion_count == 1)
- apply_bops(smm);
+ r = apply_bops(smm);
smm->recursion_count--;
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 29e3f5da59c1..11ec048929e8 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -253,8 +253,7 @@ int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
*/
pixsize = vout->bpp * vout->vrfb_bpp;
- dst_icg = ((MAX_PIXELS_PER_LINE * pixsize) -
- (vout->pix.width * vout->bpp)) + 1;
+ dst_icg = MAX_PIXELS_PER_LINE * pixsize - vout->pix.width * vout->bpp;
xt->src_start = vout->buf_phy_addr[vb->i];
xt->dst_start = vout->vrfb_context[vb->i].paddr[0];
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index bc2a176937a4..d535aac68ce1 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1099,6 +1099,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
/* start creating the vb2 queues */
if (dev->has_vid_cap) {
+ snprintf(dev->vid_cap_dev.name, sizeof(dev->vid_cap_dev.name),
+ "vivid-%03d-vid-cap", inst);
/* initialize vid_cap queue */
q = &dev->vb_vid_cap_q;
q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
@@ -1122,6 +1124,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
}
if (dev->has_vid_out) {
+ snprintf(dev->vid_out_dev.name, sizeof(dev->vid_out_dev.name),
+ "vivid-%03d-vid-out", inst);
/* initialize vid_out queue */
q = &dev->vb_vid_out_q;
q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
@@ -1265,8 +1269,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
/* finally start creating the device nodes */
if (dev->has_vid_cap) {
vfd = &dev->vid_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vid-cap", inst);
vfd->fops = &vivid_fops;
vfd->ioctl_ops = &vivid_ioctl_ops;
vfd->device_caps = dev->vid_cap_caps;
@@ -1312,8 +1314,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
if (dev->has_vid_out) {
vfd = &dev->vid_out_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vid-out", inst);
vfd->vfl_dir = VFL_DIR_TX;
vfd->fops = &vivid_fops;
vfd->ioctl_ops = &vivid_ioctl_ops;
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 42ab43affbff..439d7d886873 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -41,17 +41,40 @@
#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
#define F_MMU_EN BIT(0)
+/* SMI COMMON */
+#define SMI_BUS_SEL 0x220
+#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
+/* All are MMU0 defaultly. Only specialize mmu1 here. */
+#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
+
+enum mtk_smi_gen {
+ MTK_SMI_GEN1,
+ MTK_SMI_GEN2
+};
+
+struct mtk_smi_common_plat {
+ enum mtk_smi_gen gen;
+ bool has_gals;
+ u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
+};
+
struct mtk_smi_larb_gen {
- bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
+ unsigned int larb_direct_to_common_mask;
+ bool has_gals;
};
struct mtk_smi {
struct device *dev;
struct clk *clk_apb, *clk_smi;
+ struct clk *clk_gals0, *clk_gals1;
struct clk *clk_async; /*only needed by mt2701*/
- void __iomem *smi_ao_base;
+ union {
+ void __iomem *smi_ao_base; /* only for gen1 */
+ void __iomem *base; /* only for gen2 */
+ };
+ const struct mtk_smi_common_plat *plat;
};
struct mtk_smi_larb { /* larb: local arbiter */
@@ -63,82 +86,56 @@ struct mtk_smi_larb { /* larb: local arbiter */
u32 *mmu;
};
-enum mtk_smi_gen {
- MTK_SMI_GEN1,
- MTK_SMI_GEN2
-};
-
-static int mtk_smi_enable(const struct mtk_smi *smi)
+static int mtk_smi_clk_enable(const struct mtk_smi *smi)
{
int ret;
- ret = pm_runtime_get_sync(smi->dev);
- if (ret < 0)
- return ret;
-
ret = clk_prepare_enable(smi->clk_apb);
if (ret)
- goto err_put_pm;
+ return ret;
ret = clk_prepare_enable(smi->clk_smi);
if (ret)
goto err_disable_apb;
+ ret = clk_prepare_enable(smi->clk_gals0);
+ if (ret)
+ goto err_disable_smi;
+
+ ret = clk_prepare_enable(smi->clk_gals1);
+ if (ret)
+ goto err_disable_gals0;
+
return 0;
+err_disable_gals0:
+ clk_disable_unprepare(smi->clk_gals0);
+err_disable_smi:
+ clk_disable_unprepare(smi->clk_smi);
err_disable_apb:
clk_disable_unprepare(smi->clk_apb);
-err_put_pm:
- pm_runtime_put_sync(smi->dev);
return ret;
}
-static void mtk_smi_disable(const struct mtk_smi *smi)
+static void mtk_smi_clk_disable(const struct mtk_smi *smi)
{
+ clk_disable_unprepare(smi->clk_gals1);
+ clk_disable_unprepare(smi->clk_gals0);
clk_disable_unprepare(smi->clk_smi);
clk_disable_unprepare(smi->clk_apb);
- pm_runtime_put_sync(smi->dev);
}
int mtk_smi_larb_get(struct device *larbdev)
{
- struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
- const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
- struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
- int ret;
-
- /* Enable the smi-common's power and clocks */
- ret = mtk_smi_enable(common);
- if (ret)
- return ret;
+ int ret = pm_runtime_get_sync(larbdev);
- /* Enable the larb's power and clocks */
- ret = mtk_smi_enable(&larb->smi);
- if (ret) {
- mtk_smi_disable(common);
- return ret;
- }
-
- /* Configure the iommu info for this larb */
- larb_gen->config_port(larbdev);
-
- return 0;
+ return (ret < 0) ? ret : 0;
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
void mtk_smi_larb_put(struct device *larbdev)
{
- struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
- struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
-
- /*
- * Don't de-configure the iommu info for this larb since there may be
- * several modules in this larb.
- * The iommu info will be reset after power off.
- */
-
- mtk_smi_disable(&larb->smi);
- mtk_smi_disable(common);
+ pm_runtime_put_sync(larbdev);
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
@@ -146,39 +143,26 @@ static int
mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
- struct mtk_smi_iommu *smi_iommu = data;
+ struct mtk_smi_larb_iommu *larb_mmu = data;
unsigned int i;
- if (larb->larb_gen->need_larbid) {
- larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
- return 0;
- }
-
- /*
- * If there is no larbid property, Loop to find the corresponding
- * iommu information.
- */
- for (i = 0; i < smi_iommu->larb_nr; i++) {
- if (dev == smi_iommu->larb_imu[i].dev) {
- /* The 'mmu' may be updated in iommu-attach/detach. */
- larb->mmu = &smi_iommu->larb_imu[i].mmu;
+ for (i = 0; i < MTK_LARB_NR_MAX; i++) {
+ if (dev == larb_mmu[i].dev) {
+ larb->larbid = i;
+ larb->mmu = &larb_mmu[i].mmu;
return 0;
}
}
return -ENODEV;
}
-static void mtk_smi_larb_config_port_mt2712(struct device *dev)
+static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
u32 reg;
int i;
- /*
- * larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
- * Don't need to set it again.
- */
- if (larb->larbid == 8 || larb->larbid == 9)
+ if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
return;
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
@@ -243,7 +227,6 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
- .need_larbid = true,
.port_in_larb = {
LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
@@ -252,8 +235,15 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
- .need_larbid = true,
- .config_port = mtk_smi_larb_config_port_mt2712,
+ .config_port = mtk_smi_larb_config_port_gen2_general,
+ .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
+};
+
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
+ .has_gals = true,
+ .config_port = mtk_smi_larb_config_port_gen2_general,
+ .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7),
+ /* IPU0 | IPU1 | CCU */
};
static const struct of_device_id mtk_smi_larb_of_ids[] = {
@@ -269,6 +259,10 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
.compatible = "mediatek,mt2712-smi-larb",
.data = &mtk_smi_larb_mt2712
},
+ {
+ .compatible = "mediatek,mt8183-smi-larb",
+ .data = &mtk_smi_larb_mt8183
+ },
{}
};
@@ -279,7 +273,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *smi_node;
struct platform_device *smi_pdev;
- int err;
larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
if (!larb)
@@ -298,16 +291,16 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
larb->smi.clk_smi = devm_clk_get(dev, "smi");
if (IS_ERR(larb->smi.clk_smi))
return PTR_ERR(larb->smi.clk_smi);
- larb->smi.dev = dev;
- if (larb->larb_gen->need_larbid) {
- err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
- &larb->larbid);
- if (err) {
- dev_err(dev, "missing larbid property\n");
- return err;
- }
+ if (larb->larb_gen->has_gals) {
+ /* The larbs may still haven't gals even if the SoC support.*/
+ larb->smi.clk_gals0 = devm_clk_get(dev, "gals");
+ if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT)
+ larb->smi.clk_gals0 = NULL;
+ else if (IS_ERR(larb->smi.clk_gals0))
+ return PTR_ERR(larb->smi.clk_gals0);
}
+ larb->smi.dev = dev;
smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
if (!smi_node)
@@ -336,27 +329,86 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
+{
+ struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+ const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+ int ret;
+
+ /* Power on smi-common. */
+ ret = pm_runtime_get_sync(larb->smi_common_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
+ return ret;
+ }
+
+ ret = mtk_smi_clk_enable(&larb->smi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable clock(%d).\n", ret);
+ pm_runtime_put_sync(larb->smi_common_dev);
+ return ret;
+ }
+
+ /* Configure the basic setting for this larb */
+ larb_gen->config_port(dev);
+
+ return 0;
+}
+
+static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
+{
+ struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+ mtk_smi_clk_disable(&larb->smi);
+ pm_runtime_put_sync(larb->smi_common_dev);
+ return 0;
+}
+
+static const struct dev_pm_ops smi_larb_pm_ops = {
+ SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
+};
+
static struct platform_driver mtk_smi_larb_driver = {
.probe = mtk_smi_larb_probe,
.remove = mtk_smi_larb_remove,
.driver = {
.name = "mtk-smi-larb",
.of_match_table = mtk_smi_larb_of_ids,
+ .pm = &smi_larb_pm_ops,
}
};
+static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
+ .gen = MTK_SMI_GEN1,
+};
+
+static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
+ .gen = MTK_SMI_GEN2,
+};
+
+static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
+ .gen = MTK_SMI_GEN2,
+ .has_gals = true,
+ .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
+ F_MMU1_LARB(7),
+};
+
static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
- .data = (void *)MTK_SMI_GEN2
+ .data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt2701-smi-common",
- .data = (void *)MTK_SMI_GEN1
+ .data = &mtk_smi_common_gen1,
},
{
.compatible = "mediatek,mt2712-smi-common",
- .data = (void *)MTK_SMI_GEN2
+ .data = &mtk_smi_common_gen2,
+ },
+ {
+ .compatible = "mediatek,mt8183-smi-common",
+ .data = &mtk_smi_common_mt8183,
},
{}
};
@@ -366,13 +418,13 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct mtk_smi *common;
struct resource *res;
- enum mtk_smi_gen smi_gen;
int ret;
common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
if (!common)
return -ENOMEM;
common->dev = dev;
+ common->plat = of_device_get_match_data(dev);
common->clk_apb = devm_clk_get(dev, "apb");
if (IS_ERR(common->clk_apb))
@@ -382,14 +434,23 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
if (IS_ERR(common->clk_smi))
return PTR_ERR(common->clk_smi);
+ if (common->plat->has_gals) {
+ common->clk_gals0 = devm_clk_get(dev, "gals0");
+ if (IS_ERR(common->clk_gals0))
+ return PTR_ERR(common->clk_gals0);
+
+ common->clk_gals1 = devm_clk_get(dev, "gals1");
+ if (IS_ERR(common->clk_gals1))
+ return PTR_ERR(common->clk_gals1);
+ }
+
/*
* for mtk smi gen 1, we need to get the ao(always on) base to config
* m4u port, and we need to enable the aync clock for transform the smi
* clock into emi clock domain, but for mtk smi gen2, there's no smi ao
* base.
*/
- smi_gen = (enum mtk_smi_gen)of_device_get_match_data(dev);
- if (smi_gen == MTK_SMI_GEN1) {
+ if (common->plat->gen == MTK_SMI_GEN1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
common->smi_ao_base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->smi_ao_base))
@@ -402,6 +463,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
ret = clk_prepare_enable(common->clk_async);
if (ret)
return ret;
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ common->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(common->base))
+ return PTR_ERR(common->base);
}
pm_runtime_enable(dev);
platform_set_drvdata(pdev, common);
@@ -414,12 +480,42 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused mtk_smi_common_resume(struct device *dev)
+{
+ struct mtk_smi *common = dev_get_drvdata(dev);
+ u32 bus_sel = common->plat->bus_sel;
+ int ret;
+
+ ret = mtk_smi_clk_enable(common);
+ if (ret) {
+ dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
+ return ret;
+ }
+
+ if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
+ writel(bus_sel, common->base + SMI_BUS_SEL);
+ return 0;
+}
+
+static int __maybe_unused mtk_smi_common_suspend(struct device *dev)
+{
+ struct mtk_smi *common = dev_get_drvdata(dev);
+
+ mtk_smi_clk_disable(common);
+ return 0;
+}
+
+static const struct dev_pm_ops smi_common_pm_ops = {
+ SET_RUNTIME_PM_OPS(mtk_smi_common_suspend, mtk_smi_common_resume, NULL)
+};
+
static struct platform_driver mtk_smi_common_driver = {
.probe = mtk_smi_common_probe,
.remove = mtk_smi_common_remove,
.driver = {
.name = "mtk-smi-common",
.of_match_table = mtk_smi_common_of_ids,
+ .pm = &smi_common_pm_ops,
}
};
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 3f21e26b8d36..90e0f21bc49c 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -1590,8 +1590,10 @@ static unsigned long dsiclk_rate(u8 n)
switch (divsel) {
case PRCM_DSI_PLLOUT_SEL_PHI_4:
div *= 2;
+ /* Fall through */
case PRCM_DSI_PLLOUT_SEL_PHI_2:
div *= 2;
+ /* Fall through */
case PRCM_DSI_PLLOUT_SEL_PHI:
return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
PLL_RAW) / div;
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 792b855a9104..4798d9f3f9d5 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -308,7 +308,7 @@ static int usbhs_runtime_resume(struct device *dev)
i, r);
}
}
- /* Fall through as HSIC mode needs utmi_clk */
+ /* Fall through - as HSIC mode needs utmi_clk */
case OMAP_EHCI_PORT_MODE_TLL:
if (!IS_ERR(omap->utmi_clk[i])) {
@@ -344,7 +344,7 @@ static int usbhs_runtime_suspend(struct device *dev)
if (!IS_ERR(omap->hsic480m_clk[i]))
clk_disable_unprepare(omap->hsic480m_clk[i]);
- /* Fall through as utmi_clks were used in HSIC mode */
+ /* Fall through - as utmi_clks were used in HSIC mode */
case OMAP_EHCI_PORT_MODE_TLL:
if (!IS_ERR(omap->utmi_clk[i]))
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 601cefb5c9d8..050478cabc95 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -729,7 +729,7 @@ static int rk808_remove(struct i2c_client *client)
return 0;
}
-static int rk8xx_suspend(struct device *dev)
+static int __maybe_unused rk8xx_suspend(struct device *dev)
{
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
int ret = 0;
@@ -749,7 +749,7 @@ static int rk8xx_suspend(struct device *dev)
return ret;
}
-static int rk8xx_resume(struct device *dev)
+static int __maybe_unused rk8xx_resume(struct device *dev)
{
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
int ret = 0;
@@ -768,7 +768,7 @@ static int rk8xx_resume(struct device *dev)
return ret;
}
-SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
+static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
static struct i2c_driver rk808_i2c_driver = {
.driver = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6abfc8e92fcc..45b61b8d8442 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -126,18 +126,6 @@ config INTEL_MID_PTI
an Intel Atom (non-netbook) mobile device containing a MIPI
P1149.7 standard implementation.
-config SGI_IOC4
- tristate "SGI IOC4 Base IO support"
- depends on PCI
- ---help---
- This option enables basic support for the IOC4 chip on certain
- SGI IO controller cards (IO9, IO10, and PCI-RT). This option
- does not enable any specific functions on such a card, but provides
- necessary infrastructure for other drivers to utilize.
-
- If you have an SGI Altix with an IOC4-based card say Y.
- Otherwise say N.
-
config TIFM_CORE
tristate "TI Flash Media interface support"
depends on PCI
@@ -200,9 +188,8 @@ config ENCLOSURE_SERVICES
config SGI_XP
tristate "Support communication between SGI SSIs"
depends on NET
- depends on (IA64_GENERIC || IA64_SGI_SN2 || IA64_SGI_UV || X86_UV) && SMP
- select IA64_UNCACHED_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
- select GENERIC_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
+ depends on (IA64_SGI_UV || X86_UV) && SMP
+ depends on X86_64 || BROKEN
select SGI_GRU if X86_64 && SMP
---help---
An SGI machine can be divided into multiple Single System
@@ -465,6 +452,7 @@ config PCI_ENDPOINT_TEST
config XILINX_SDFEC
tristate "Xilinx SDFEC 16"
+ depends on HAS_IOMEM
help
This option enables support for the Xilinx SDFEC (Soft Decision
Forward Error Correction) driver. This enables a char driver
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index abd8ae249746..8dae0a976200 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
-obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index f88094719552..f2abe27010ef 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -5,6 +5,7 @@ config EEPROM_AT24
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
depends on I2C && SYSFS
select NVMEM
+ select NVMEM_SYSFS
select REGMAP_I2C
help
Enable this driver to get read/write support to most I2C EEPROMs
@@ -34,6 +35,7 @@ config EEPROM_AT25
tristate "SPI EEPROMs from most vendors"
depends on SPI && SYSFS
select NVMEM
+ select NVMEM_SYSFS
help
Enable this driver to get read/write support to most SPI EEPROMs,
after you configure the board init code to know about each eeprom
@@ -80,6 +82,7 @@ config EEPROM_93XX46
depends on SPI && SYSFS
select REGMAP
select NVMEM
+ select NVMEM_SYSFS
help
Driver for the microwire EEPROM chipsets 93xx46x. The driver
supports both read and write commands and also the command to
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 35bf2477693d..518945b2f737 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -685,7 +685,7 @@ static int at24_probe(struct i2c_client *client)
nvmem_config.name = dev_name(dev);
nvmem_config.dev = dev;
nvmem_config.read_only = !writable;
- nvmem_config.root_only = true;
+ nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
nvmem_config.owner = THIS_MODULE;
nvmem_config.compat = true;
nvmem_config.base_dev = dev;
diff --git a/drivers/misc/habanalabs/command_submission.c b/drivers/misc/habanalabs/command_submission.c
index 6ad83d5ef4b0..f00d1c32f6d6 100644
--- a/drivers/misc/habanalabs/command_submission.c
+++ b/drivers/misc/habanalabs/command_submission.c
@@ -683,7 +683,7 @@ int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data)
rc = hl_poll_timeout_memory(hdev,
&ctx->thread_ctx_switch_wait_token, tmp, (tmp == 1),
- 100, jiffies_to_usecs(hdev->timeout_jiffies));
+ 100, jiffies_to_usecs(hdev->timeout_jiffies), false);
if (rc == -ETIMEDOUT) {
dev_err(hdev->dev,
diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c
index 0c4894dd9c02..7a8f9d0b71b5 100644
--- a/drivers/misc/habanalabs/device.c
+++ b/drivers/misc/habanalabs/device.c
@@ -970,7 +970,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
if (rc) {
dev_err(hdev->dev, "failed to initialize kernel context\n");
- goto free_ctx;
+ kfree(hdev->kernel_ctx);
+ goto mmu_fini;
}
rc = hl_cb_pool_init(hdev);
@@ -1053,8 +1054,6 @@ release_ctx:
if (hl_ctx_put(hdev->kernel_ctx) != 1)
dev_err(hdev->dev,
"kernel ctx is still alive on initialization failure\n");
-free_ctx:
- kfree(hdev->kernel_ctx);
mmu_fini:
hl_mmu_fini(hdev);
eq_fini:
diff --git a/drivers/misc/habanalabs/firmware_if.c b/drivers/misc/habanalabs/firmware_if.c
index cc8168bacb24..ea2ca67fbfbf 100644
--- a/drivers/misc/habanalabs/firmware_if.c
+++ b/drivers/misc/habanalabs/firmware_if.c
@@ -24,7 +24,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
{
const struct firmware *fw;
const u64 *fw_data;
- size_t fw_size, i;
+ size_t fw_size;
int rc;
rc = request_firmware(&fw, fw_name, hdev->dev);
@@ -45,22 +45,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
fw_data = (const u64 *) fw->data;
- if ((fw->size % 8) != 0)
- fw_size -= 8;
-
- for (i = 0 ; i < fw_size ; i += 8, fw_data++, dst += 8) {
- if (!(i & (0x80000 - 1))) {
- dev_dbg(hdev->dev,
- "copied so far %zu out of %zu for %s firmware",
- i, fw_size, fw_name);
- usleep_range(20, 100);
- }
-
- writeq(*fw_data, dst);
- }
-
- if ((fw->size % 8) != 0)
- writel(*(const u32 *) fw_data, dst);
+ memcpy_toio(dst, fw_data, fw_size);
out:
release_firmware(fw);
@@ -112,7 +97,8 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
}
rc = hl_poll_timeout_memory(hdev, &pkt->fence, tmp,
- (tmp == ARMCP_PACKET_FENCE_VAL), 1000, timeout);
+ (tmp == ARMCP_PACKET_FENCE_VAL), 1000,
+ timeout, true);
hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c
index 75294ec65257..271c5c8f53b4 100644
--- a/drivers/misc/habanalabs/goya/goya.c
+++ b/drivers/misc/habanalabs/goya/goya.c
@@ -695,8 +695,8 @@ static int goya_sw_init(struct hl_device *hdev)
goto free_dma_pool;
}
- dev_dbg(hdev->dev, "cpu accessible memory at bus address 0x%llx\n",
- hdev->cpu_accessible_dma_address);
+ dev_dbg(hdev->dev, "cpu accessible memory at bus address %pad\n",
+ &hdev->cpu_accessible_dma_address);
hdev->cpu_accessible_dma_pool = gen_pool_create(ilog2(32), -1);
if (!hdev->cpu_accessible_dma_pool) {
@@ -2729,9 +2729,10 @@ void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi)
GOYA_ASYNC_EVENT_ID_PI_UPDATE);
}
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val)
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd)
{
- /* Not needed in Goya */
+ /* The QMANs are on the SRAM so need to copy to IO space */
+ memcpy_toio((void __iomem *) pqe, bd, sizeof(struct hl_bd));
}
static void *goya_dma_alloc_coherent(struct hl_device *hdev, size_t size,
@@ -2864,7 +2865,8 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
}
rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp,
- (tmp == GOYA_QMAN0_FENCE_VAL), 1000, timeout);
+ (tmp == GOYA_QMAN0_FENCE_VAL), 1000,
+ timeout, true);
hl_hw_queue_inc_ci_kernel(hdev, GOYA_QUEUE_ID_DMA_0);
@@ -2945,7 +2947,7 @@ int goya_test_queue(struct hl_device *hdev, u32 hw_queue_id)
}
rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp, (tmp == fence_val),
- 1000, GOYA_TEST_QUEUE_WAIT_USEC);
+ 1000, GOYA_TEST_QUEUE_WAIT_USEC, true);
hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
@@ -3312,9 +3314,11 @@ static int goya_validate_dma_pkt_no_mmu(struct hl_device *hdev,
int rc;
dev_dbg(hdev->dev, "DMA packet details:\n");
- dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
- dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
- dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+ dev_dbg(hdev->dev, "source == 0x%llx\n",
+ le64_to_cpu(user_dma_pkt->src_addr));
+ dev_dbg(hdev->dev, "destination == 0x%llx\n",
+ le64_to_cpu(user_dma_pkt->dst_addr));
+ dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
ctl = le32_to_cpu(user_dma_pkt->ctl);
user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
@@ -3343,9 +3347,11 @@ static int goya_validate_dma_pkt_mmu(struct hl_device *hdev,
struct packet_lin_dma *user_dma_pkt)
{
dev_dbg(hdev->dev, "DMA packet details:\n");
- dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
- dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
- dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+ dev_dbg(hdev->dev, "source == 0x%llx\n",
+ le64_to_cpu(user_dma_pkt->src_addr));
+ dev_dbg(hdev->dev, "destination == 0x%llx\n",
+ le64_to_cpu(user_dma_pkt->dst_addr));
+ dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
/*
* WA for HW-23.
@@ -3385,7 +3391,8 @@ static int goya_validate_wreg32(struct hl_device *hdev,
dev_dbg(hdev->dev, "WREG32 packet details:\n");
dev_dbg(hdev->dev, "reg_offset == 0x%x\n", reg_offset);
- dev_dbg(hdev->dev, "value == 0x%x\n", wreg_pkt->value);
+ dev_dbg(hdev->dev, "value == 0x%x\n",
+ le32_to_cpu(wreg_pkt->value));
if (reg_offset != (mmDMA_CH_0_WR_COMP_ADDR_LO & 0x1FFF)) {
dev_err(hdev->dev, "WREG32 packet with illegal address 0x%x\n",
@@ -3427,12 +3434,13 @@ static int goya_validate_cb(struct hl_device *hdev,
while (cb_parsed_length < parser->user_cb_size) {
enum packet_id pkt_id;
u16 pkt_size;
- void *user_pkt;
+ struct goya_packet *user_pkt;
- user_pkt = (void *) (uintptr_t)
+ user_pkt = (struct goya_packet *) (uintptr_t)
(parser->user_cb->kernel_address + cb_parsed_length);
- pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+ pkt_id = (enum packet_id) (
+ (le64_to_cpu(user_pkt->header) &
PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT);
@@ -3452,7 +3460,8 @@ static int goya_validate_cb(struct hl_device *hdev,
* need to validate here as well because patch_cb() is
* not called in MMU path while this function is called
*/
- rc = goya_validate_wreg32(hdev, parser, user_pkt);
+ rc = goya_validate_wreg32(hdev,
+ parser, (struct packet_wreg32 *) user_pkt);
break;
case PACKET_WREG_BULK:
@@ -3480,10 +3489,10 @@ static int goya_validate_cb(struct hl_device *hdev,
case PACKET_LIN_DMA:
if (is_mmu)
rc = goya_validate_dma_pkt_mmu(hdev, parser,
- user_pkt);
+ (struct packet_lin_dma *) user_pkt);
else
rc = goya_validate_dma_pkt_no_mmu(hdev, parser,
- user_pkt);
+ (struct packet_lin_dma *) user_pkt);
break;
case PACKET_MSG_LONG:
@@ -3656,15 +3665,16 @@ static int goya_patch_cb(struct hl_device *hdev,
enum packet_id pkt_id;
u16 pkt_size;
u32 new_pkt_size = 0;
- void *user_pkt, *kernel_pkt;
+ struct goya_packet *user_pkt, *kernel_pkt;
- user_pkt = (void *) (uintptr_t)
+ user_pkt = (struct goya_packet *) (uintptr_t)
(parser->user_cb->kernel_address + cb_parsed_length);
- kernel_pkt = (void *) (uintptr_t)
+ kernel_pkt = (struct goya_packet *) (uintptr_t)
(parser->patched_cb->kernel_address +
cb_patched_cur_length);
- pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+ pkt_id = (enum packet_id) (
+ (le64_to_cpu(user_pkt->header) &
PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT);
@@ -3679,15 +3689,18 @@ static int goya_patch_cb(struct hl_device *hdev,
switch (pkt_id) {
case PACKET_LIN_DMA:
- rc = goya_patch_dma_packet(hdev, parser, user_pkt,
- kernel_pkt, &new_pkt_size);
+ rc = goya_patch_dma_packet(hdev, parser,
+ (struct packet_lin_dma *) user_pkt,
+ (struct packet_lin_dma *) kernel_pkt,
+ &new_pkt_size);
cb_patched_cur_length += new_pkt_size;
break;
case PACKET_WREG_32:
memcpy(kernel_pkt, user_pkt, pkt_size);
cb_patched_cur_length += pkt_size;
- rc = goya_validate_wreg32(hdev, parser, kernel_pkt);
+ rc = goya_validate_wreg32(hdev, parser,
+ (struct packet_wreg32 *) kernel_pkt);
break;
case PACKET_WREG_BULK:
@@ -4351,6 +4364,8 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
size_t total_pkt_size;
long result;
int rc;
+ int irq_num_entries, irq_arr_index;
+ __le32 *goya_irq_arr;
total_pkt_size = sizeof(struct armcp_unmask_irq_arr_packet) +
irq_arr_size;
@@ -4368,8 +4383,16 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
if (!pkt)
return -ENOMEM;
- pkt->length = cpu_to_le32(irq_arr_size / sizeof(irq_arr[0]));
- memcpy(&pkt->irqs, irq_arr, irq_arr_size);
+ irq_num_entries = irq_arr_size / sizeof(irq_arr[0]);
+ pkt->length = cpu_to_le32(irq_num_entries);
+
+ /* We must perform any necessary endianness conversation on the irq
+ * array being passed to the goya hardware
+ */
+ for (irq_arr_index = 0, goya_irq_arr = (__le32 *) &pkt->irqs;
+ irq_arr_index < irq_num_entries ; irq_arr_index++)
+ goya_irq_arr[irq_arr_index] =
+ cpu_to_le32(irq_arr[irq_arr_index]);
pkt->armcp_pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY <<
ARMCP_PKT_CTL_OPCODE_SHIFT);
@@ -4449,7 +4472,6 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
case GOYA_ASYNC_EVENT_ID_AXI_ECC:
case GOYA_ASYNC_EVENT_ID_L2_RAM_ECC:
case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET:
- case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT:
goya_print_irq_info(hdev, event_type, false);
hl_device_reset(hdev, true, false);
break;
@@ -4485,6 +4507,7 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
goya_unmask_irq(hdev, event_type);
break;
+ case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT:
case GOYA_ASYNC_EVENT_ID_TPC0_BMON_SPMU:
case GOYA_ASYNC_EVENT_ID_TPC1_BMON_SPMU:
case GOYA_ASYNC_EVENT_ID_TPC2_BMON_SPMU:
@@ -5041,7 +5064,7 @@ static const struct hl_asic_funcs goya_funcs = {
.resume = goya_resume,
.cb_mmap = goya_cb_mmap,
.ring_doorbell = goya_ring_doorbell,
- .flush_pq_write = goya_flush_pq_write,
+ .pqe_write = goya_pqe_write,
.asic_dma_alloc_coherent = goya_dma_alloc_coherent,
.asic_dma_free_coherent = goya_dma_free_coherent,
.get_int_queue_base = goya_get_int_queue_base,
diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/misc/habanalabs/goya/goyaP.h
index f8c611883dc1..d7f48c9c41cd 100644
--- a/drivers/misc/habanalabs/goya/goyaP.h
+++ b/drivers/misc/habanalabs/goya/goyaP.h
@@ -177,7 +177,7 @@ int goya_late_init(struct hl_device *hdev);
void goya_late_fini(struct hl_device *hdev);
void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val);
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd);
void goya_update_eq_ci(struct hl_device *hdev, u32 val);
void goya_restore_phase_topology(struct hl_device *hdev);
int goya_context_switch(struct hl_device *hdev, u32 asid);
diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h
index 10da9940ee0d..ce83adafcf2d 100644
--- a/drivers/misc/habanalabs/habanalabs.h
+++ b/drivers/misc/habanalabs/habanalabs.h
@@ -441,7 +441,11 @@ enum hl_pll_frequency {
* @resume: handles IP specific H/W or SW changes for resume.
* @cb_mmap: maps a CB.
* @ring_doorbell: increment PI on a given QMAN.
- * @flush_pq_write: flush PQ entry write if necessary, WARN if flushing failed.
+ * @pqe_write: Write the PQ entry to the PQ. This is ASIC-specific
+ * function because the PQs are located in different memory areas
+ * per ASIC (SRAM, DRAM, Host memory) and therefore, the method of
+ * writing the PQE must match the destination memory area
+ * properties.
* @asic_dma_alloc_coherent: Allocate coherent DMA memory by calling
* dma_alloc_coherent(). This is ASIC function because
* its implementation is not trivial when the driver
@@ -510,7 +514,8 @@ struct hl_asic_funcs {
int (*cb_mmap)(struct hl_device *hdev, struct vm_area_struct *vma,
u64 kaddress, phys_addr_t paddress, u32 size);
void (*ring_doorbell)(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
- void (*flush_pq_write)(struct hl_device *hdev, u64 *pq, u64 exp_val);
+ void (*pqe_write)(struct hl_device *hdev, __le64 *pqe,
+ struct hl_bd *bd);
void* (*asic_dma_alloc_coherent)(struct hl_device *hdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);
void (*asic_dma_free_coherent)(struct hl_device *hdev, size_t size,
@@ -1062,9 +1067,17 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
/*
* address in this macro points always to a memory location in the
* host's (server's) memory. That location is updated asynchronously
- * either by the direct access of the device or by another core
+ * either by the direct access of the device or by another core.
+ *
+ * To work both in LE and BE architectures, we need to distinguish between the
+ * two states (device or another core updates the memory location). Therefore,
+ * if mem_written_by_device is true, the host memory being polled will be
+ * updated directly by the device. If false, the host memory being polled will
+ * be updated by host CPU. Required so host knows whether or not the memory
+ * might need to be byte-swapped before returning value to caller.
*/
-#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us) \
+#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us, \
+ mem_written_by_device) \
({ \
ktime_t __timeout; \
/* timeout should be longer when working with simulator */ \
@@ -1077,10 +1090,14 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
/* Verify we read updates done by other cores or by device */ \
mb(); \
(val) = *((u32 *) (uintptr_t) (addr)); \
+ if (mem_written_by_device) \
+ (val) = le32_to_cpu(val); \
if (cond) \
break; \
if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) { \
(val) = *((u32 *) (uintptr_t) (addr)); \
+ if (mem_written_by_device) \
+ (val) = le32_to_cpu(val); \
break; \
} \
if (sleep_us) \
diff --git a/drivers/misc/habanalabs/hw_queue.c b/drivers/misc/habanalabs/hw_queue.c
index e3b5517897ea..5f5673b74985 100644
--- a/drivers/misc/habanalabs/hw_queue.c
+++ b/drivers/misc/habanalabs/hw_queue.c
@@ -290,23 +290,19 @@ static void int_hw_queue_schedule_job(struct hl_cs_job *job)
struct hl_device *hdev = job->cs->ctx->hdev;
struct hl_hw_queue *q = &hdev->kernel_queues[job->hw_queue_id];
struct hl_bd bd;
- u64 *pi, *pbd = (u64 *) &bd;
+ __le64 *pi;
bd.ctl = 0;
- bd.len = __cpu_to_le32(job->job_cb_size);
- bd.ptr = __cpu_to_le64((u64) (uintptr_t) job->user_cb);
+ bd.len = cpu_to_le32(job->job_cb_size);
+ bd.ptr = cpu_to_le64((u64) (uintptr_t) job->user_cb);
- pi = (u64 *) (uintptr_t) (q->kernel_address +
+ pi = (__le64 *) (uintptr_t) (q->kernel_address +
((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
- pi[0] = pbd[0];
- pi[1] = pbd[1];
-
q->pi++;
q->pi &= ((q->int_queue_len << 1) - 1);
- /* Flush PQ entry write. Relevant only for specific ASICs */
- hdev->asic_funcs->flush_pq_write(hdev, pi, pbd[0]);
+ hdev->asic_funcs->pqe_write(hdev, pi, &bd);
hdev->asic_funcs->ring_doorbell(hdev, q->hw_queue_id, q->pi);
}
diff --git a/drivers/misc/habanalabs/include/goya/goya_packets.h b/drivers/misc/habanalabs/include/goya/goya_packets.h
index a14407b975e4..ef54bad20509 100644
--- a/drivers/misc/habanalabs/include/goya/goya_packets.h
+++ b/drivers/misc/habanalabs/include/goya/goya_packets.h
@@ -52,6 +52,19 @@ enum goya_dma_direction {
#define GOYA_PKT_CTL_MB_SHIFT 31
#define GOYA_PKT_CTL_MB_MASK 0x80000000
+/* All packets have, at least, an 8-byte header, which contains
+ * the packet type. The kernel driver uses the packet header for packet
+ * validation and to perform any necessary required preparation before
+ * sending them off to the hardware.
+ */
+struct goya_packet {
+ __le64 header;
+ /* The rest of the packet data follows. Use the corresponding
+ * packet_XXX struct to deference the data, based on packet type
+ */
+ u8 contents[0];
+};
+
struct packet_nop {
__le32 reserved;
__le32 ctl;
diff --git a/drivers/misc/habanalabs/irq.c b/drivers/misc/habanalabs/irq.c
index ea9f72ff456c..199791b57caf 100644
--- a/drivers/misc/habanalabs/irq.c
+++ b/drivers/misc/habanalabs/irq.c
@@ -80,8 +80,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
struct hl_cs_job *job;
bool shadow_index_valid;
u16 shadow_index;
- u32 *cq_entry;
- u32 *cq_base;
+ struct hl_cq_entry *cq_entry, *cq_base;
if (hdev->disabled) {
dev_dbg(hdev->dev,
@@ -90,29 +89,29 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
return IRQ_HANDLED;
}
- cq_base = (u32 *) (uintptr_t) cq->kernel_address;
+ cq_base = (struct hl_cq_entry *) (uintptr_t) cq->kernel_address;
while (1) {
- bool entry_ready = ((cq_base[cq->ci] & CQ_ENTRY_READY_MASK)
+ bool entry_ready = ((le32_to_cpu(cq_base[cq->ci].data) &
+ CQ_ENTRY_READY_MASK)
>> CQ_ENTRY_READY_SHIFT);
if (!entry_ready)
break;
- cq_entry = (u32 *) &cq_base[cq->ci];
+ cq_entry = (struct hl_cq_entry *) &cq_base[cq->ci];
- /*
- * Make sure we read CQ entry contents after we've
+ /* Make sure we read CQ entry contents after we've
* checked the ownership bit.
*/
dma_rmb();
- shadow_index_valid =
- ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
+ shadow_index_valid = ((le32_to_cpu(cq_entry->data) &
+ CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
>> CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT);
- shadow_index = (u16)
- ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_MASK)
+ shadow_index = (u16) ((le32_to_cpu(cq_entry->data) &
+ CQ_ENTRY_SHADOW_INDEX_MASK)
>> CQ_ENTRY_SHADOW_INDEX_SHIFT);
queue = &hdev->kernel_queues[cq->hw_queue_id];
@@ -122,8 +121,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
queue_work(hdev->cq_wq, &job->finish_work);
}
- /*
- * Update ci of the context's queue. There is no
+ /* Update ci of the context's queue. There is no
* need to protect it with spinlock because this update is
* done only inside IRQ and there is a different IRQ per
* queue
@@ -131,7 +129,8 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
queue->ci = hl_queue_inc_ptr(queue->ci);
/* Clear CQ entry ready bit */
- cq_base[cq->ci] &= ~CQ_ENTRY_READY_MASK;
+ cq_entry->data = cpu_to_le32(le32_to_cpu(cq_entry->data) &
+ ~CQ_ENTRY_READY_MASK);
cq->ci = hl_cq_inc_ptr(cq->ci);
diff --git a/drivers/misc/habanalabs/memory.c b/drivers/misc/habanalabs/memory.c
index 42d237cae1dc..365fb0cb8dff 100644
--- a/drivers/misc/habanalabs/memory.c
+++ b/drivers/misc/habanalabs/memory.c
@@ -1629,6 +1629,8 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx)
dev_dbg(hdev->dev,
"page list 0x%p of asid %d is still alive\n",
phys_pg_list, ctx->asid);
+ atomic64_sub(phys_pg_list->total_size,
+ &hdev->dram_used_mem);
free_phys_pg_pack(hdev, phys_pg_list);
idr_remove(&vm->phys_pg_pack_handles, i);
}
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
deleted file mode 100644
index 9d0445a567db..000000000000
--- a/drivers/misc/ioc4.c
+++ /dev/null
@@ -1,498 +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) 2005-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/* This file contains the master driver module for use by SGI IOC4 subdrivers.
- *
- * It allocates any resources shared between multiple subdevices, and
- * provides accessor functions (where needed) and the like for those
- * resources. It also provides a mechanism for the subdevice modules
- * to support loading and unloading.
- *
- * Non-shared resources (e.g. external interrupt A_INT_OUT register page
- * alias, serial port and UART registers) are handled by the subdevice
- * modules themselves.
- *
- * This is all necessary because IOC4 is not implemented as a multi-function
- * PCI device, but an amalgamation of disparate registers for several
- * types of device (ATA, serial, external interrupts). The normal
- * resource management in the kernel doesn't have quite the right interfaces
- * to handle this situation (e.g. multiple modules can't claim the same
- * PCI ID), thus this IOC4 master module.
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ioc4.h>
-#include <linux/ktime.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/time.h>
-#include <asm/io.h>
-
-/***************
- * Definitions *
- ***************/
-
-/* Tweakable values */
-
-/* PCI bus speed detection/calibration */
-#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */
-#define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */
-#define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */
-#define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */
-#define IOC4_CALIBRATE_HIGH_MHZ 75 /* Upper bound on bus speed sanity */
-#define IOC4_CALIBRATE_DEFAULT_MHZ 66 /* Assumed if sanity check fails */
-
-/************************
- * Submodule management *
- ************************/
-
-static DEFINE_MUTEX(ioc4_mutex);
-
-static LIST_HEAD(ioc4_devices);
-static LIST_HEAD(ioc4_submodules);
-
-/* Register an IOC4 submodule */
-int
-ioc4_register_submodule(struct ioc4_submodule *is)
-{
- struct ioc4_driver_data *idd;
-
- mutex_lock(&ioc4_mutex);
- list_add(&is->is_list, &ioc4_submodules);
-
- /* Initialize submodule for each IOC4 */
- if (!is->is_probe)
- goto out;
-
- list_for_each_entry(idd, &ioc4_devices, idd_list) {
- if (is->is_probe(idd)) {
- printk(KERN_WARNING
- "%s: IOC4 submodule %s probe failed "
- "for pci_dev %s",
- __func__, module_name(is->is_owner),
- pci_name(idd->idd_pdev));
- }
- }
- out:
- mutex_unlock(&ioc4_mutex);
- return 0;
-}
-
-/* Unregister an IOC4 submodule */
-void
-ioc4_unregister_submodule(struct ioc4_submodule *is)
-{
- struct ioc4_driver_data *idd;
-
- mutex_lock(&ioc4_mutex);
- list_del(&is->is_list);
-
- /* Remove submodule for each IOC4 */
- if (!is->is_remove)
- goto out;
-
- list_for_each_entry(idd, &ioc4_devices, idd_list) {
- if (is->is_remove(idd)) {
- printk(KERN_WARNING
- "%s: IOC4 submodule %s remove failed "
- "for pci_dev %s.\n",
- __func__, module_name(is->is_owner),
- pci_name(idd->idd_pdev));
- }
- }
- out:
- mutex_unlock(&ioc4_mutex);
-}
-
-/*********************
- * Device management *
- *********************/
-
-#define IOC4_CALIBRATE_LOW_LIMIT \
- (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
-#define IOC4_CALIBRATE_HIGH_LIMIT \
- (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
-#define IOC4_CALIBRATE_DEFAULT \
- (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
-
-#define IOC4_CALIBRATE_END \
- (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
-
-#define IOC4_INT_OUT_MODE_TOGGLE 0x7 /* Toggle INT_OUT every COUNT+1 ticks */
-
-/* Determines external interrupt output clock period of the PCI bus an
- * IOC4 is attached to. This value can be used to determine the PCI
- * bus speed.
- *
- * IOC4 has a design feature that various internal timers are derived from
- * the PCI bus clock. This causes IOC4 device drivers to need to take the
- * bus speed into account when setting various register values (e.g. INT_OUT
- * register COUNT field, UART divisors, etc). Since this information is
- * needed by several subdrivers, it is determined by the main IOC4 driver,
- * even though the following code utilizes external interrupt registers
- * to perform the speed calculation.
- */
-static void
-ioc4_clock_calibrate(struct ioc4_driver_data *idd)
-{
- union ioc4_int_out int_out;
- union ioc4_gpcr gpcr;
- unsigned int state, last_state;
- uint64_t start, end, period;
- unsigned int count;
-
- /* Enable output */
- gpcr.raw = 0;
- gpcr.fields.dir = IOC4_GPCR_DIR_0;
- gpcr.fields.int_out_en = 1;
- writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
-
- /* Reset to power-on state */
- writel(0, &idd->idd_misc_regs->int_out.raw);
-
- /* Set up square wave */
- int_out.raw = 0;
- int_out.fields.count = IOC4_CALIBRATE_COUNT;
- int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
- int_out.fields.diag = 0;
- writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
-
- /* Check square wave period averaged over some number of cycles */
- start = ktime_get_ns();
- state = 1; /* make sure the first read isn't a rising edge */
- for (count = 0; count <= IOC4_CALIBRATE_END; count++) {
- do { /* wait for a rising edge */
- last_state = state;
- int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
- state = int_out.fields.int_out;
- } while (last_state || !state);
-
- /* discard the first few cycles */
- if (count == IOC4_CALIBRATE_DISCARD)
- start = ktime_get_ns();
- }
- end = ktime_get_ns();
-
- /* Calculation rearranged to preserve intermediate precision.
- * Logically:
- * 1. "end - start" gives us the measurement period over all
- * the square wave cycles.
- * 2. Divide by number of square wave cycles to get the period
- * of a square wave cycle.
- * 3. Divide by 2*(int_out.fields.count+1), which is the formula
- * by which the IOC4 generates the square wave, to get the
- * period of an IOC4 INT_OUT count.
- */
- period = (end - start) /
- (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
-
- /* Bounds check the result. */
- if (period > IOC4_CALIBRATE_LOW_LIMIT ||
- period < IOC4_CALIBRATE_HIGH_LIMIT) {
- printk(KERN_INFO
- "IOC4 %s: Clock calibration failed. Assuming"
- "PCI clock is %d ns.\n",
- pci_name(idd->idd_pdev),
- IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
- period = IOC4_CALIBRATE_DEFAULT;
- } else {
- u64 ns = period;
-
- do_div(ns, IOC4_EXTINT_COUNT_DIVISOR);
- printk(KERN_DEBUG
- "IOC4 %s: PCI clock is %llu ns.\n",
- pci_name(idd->idd_pdev), (unsigned long long)ns);
- }
-
- /* Remember results. We store the extint clock period rather
- * than the PCI clock period so that greater precision is
- * retained. Divide by IOC4_EXTINT_COUNT_DIVISOR to get
- * PCI clock period.
- */
- idd->count_period = period;
-}
-
-/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
- * Each brings out different combinations of IOC4 signals, thus.
- * the IOC4 subdrivers need to know to which we're attached.
- *
- * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
- * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
- * If neither is present, it's a PCI-RT.
- */
-static unsigned int
-ioc4_variant(struct ioc4_driver_data *idd)
-{
- struct pci_dev *pdev = NULL;
- int found = 0;
-
- /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
- do {
- pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
- PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
- if (pdev &&
- idd->idd_pdev->bus->number == pdev->bus->number &&
- 3 == PCI_SLOT(pdev->devfn))
- found = 1;
- } while (pdev && !found);
- if (NULL != pdev) {
- pci_dev_put(pdev);
- return IOC4_VARIANT_IO9;
- }
-
- /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
- pdev = NULL;
- do {
- pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
- PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
- if (pdev &&
- idd->idd_pdev->bus->number == pdev->bus->number &&
- 3 == PCI_SLOT(pdev->devfn))
- found = 1;
- } while (pdev && !found);
- if (NULL != pdev) {
- pci_dev_put(pdev);
- return IOC4_VARIANT_IO10;
- }
-
- /* PCI-RT: No SCSI/SATA controller will be present */
- return IOC4_VARIANT_PCI_RT;
-}
-
-static void
-ioc4_load_modules(struct work_struct *work)
-{
- request_module("sgiioc4");
-}
-
-static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
-
-/* Adds a new instance of an IOC4 card */
-static int
-ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
- struct ioc4_driver_data *idd;
- struct ioc4_submodule *is;
- uint32_t pcmd;
- int ret;
-
- /* Enable IOC4 and take ownership of it */
- if ((ret = pci_enable_device(pdev))) {
- printk(KERN_WARNING
- "%s: Failed to enable IOC4 device for pci_dev %s.\n",
- __func__, pci_name(pdev));
- goto out;
- }
- pci_set_master(pdev);
-
- /* Set up per-IOC4 data */
- idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
- if (!idd) {
- printk(KERN_WARNING
- "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
- __func__, pci_name(pdev));
- ret = -ENODEV;
- goto out_idd;
- }
- idd->idd_pdev = pdev;
- idd->idd_pci_id = pci_id;
-
- /* Map IOC4 misc registers. These are shared between subdevices
- * so the main IOC4 module manages them.
- */
- idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
- if (!idd->idd_bar0) {
- printk(KERN_WARNING
- "%s: Unable to find IOC4 misc resource "
- "for pci_dev %s.\n",
- __func__, pci_name(idd->idd_pdev));
- ret = -ENODEV;
- goto out_pci;
- }
- if (!request_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
- "ioc4_misc")) {
- printk(KERN_WARNING
- "%s: Unable to request IOC4 misc region "
- "for pci_dev %s.\n",
- __func__, pci_name(idd->idd_pdev));
- ret = -ENODEV;
- goto out_pci;
- }
- idd->idd_misc_regs = ioremap(idd->idd_bar0,
- sizeof(struct ioc4_misc_regs));
- if (!idd->idd_misc_regs) {
- printk(KERN_WARNING
- "%s: Unable to remap IOC4 misc region "
- "for pci_dev %s.\n",
- __func__, pci_name(idd->idd_pdev));
- ret = -ENODEV;
- goto out_misc_region;
- }
-
- /* Failsafe portion of per-IOC4 initialization */
-
- /* Detect card variant */
- idd->idd_variant = ioc4_variant(idd);
- printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
- idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
- idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
- idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
-
- /* Initialize IOC4 */
- pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
- pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
- pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-
- /* Determine PCI clock */
- ioc4_clock_calibrate(idd);
-
- /* Disable/clear all interrupts. Need to do this here lest
- * one submodule request the shared IOC4 IRQ, but interrupt
- * is generated by a different subdevice.
- */
- /* Disable */
- writel(~0, &idd->idd_misc_regs->other_iec.raw);
- writel(~0, &idd->idd_misc_regs->sio_iec);
- /* Clear (i.e. acknowledge) */
- writel(~0, &idd->idd_misc_regs->other_ir.raw);
- writel(~0, &idd->idd_misc_regs->sio_ir);
-
- /* Track PCI-device specific data */
- idd->idd_serial_data = NULL;
- pci_set_drvdata(idd->idd_pdev, idd);
-
- mutex_lock(&ioc4_mutex);
- list_add_tail(&idd->idd_list, &ioc4_devices);
-
- /* Add this IOC4 to all submodules */
- list_for_each_entry(is, &ioc4_submodules, is_list) {
- if (is->is_probe && is->is_probe(idd)) {
- printk(KERN_WARNING
- "%s: IOC4 submodule 0x%s probe failed "
- "for pci_dev %s.\n",
- __func__, module_name(is->is_owner),
- pci_name(idd->idd_pdev));
- }
- }
- mutex_unlock(&ioc4_mutex);
-
- /* Request sgiioc4 IDE driver on boards that bring that functionality
- * off of IOC4. The root filesystem may be hosted on a drive connected
- * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it
- * won't be picked up by modprobes due to the ioc4 module owning the
- * PCI device.
- */
- if (idd->idd_variant != IOC4_VARIANT_PCI_RT) {
- /* Request the module from a work procedure as the modprobe
- * goes out to a userland helper and that will hang if done
- * directly from ioc4_probe().
- */
- printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
- schedule_work(&ioc4_load_modules_work);
- }
-
- return 0;
-
-out_misc_region:
- release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
-out_pci:
- kfree(idd);
-out_idd:
- pci_disable_device(pdev);
-out:
- return ret;
-}
-
-/* Removes a particular instance of an IOC4 card. */
-static void
-ioc4_remove(struct pci_dev *pdev)
-{
- struct ioc4_submodule *is;
- struct ioc4_driver_data *idd;
-
- idd = pci_get_drvdata(pdev);
-
- /* Remove this IOC4 from all submodules */
- mutex_lock(&ioc4_mutex);
- list_for_each_entry(is, &ioc4_submodules, is_list) {
- if (is->is_remove && is->is_remove(idd)) {
- printk(KERN_WARNING
- "%s: IOC4 submodule 0x%s remove failed "
- "for pci_dev %s.\n",
- __func__, module_name(is->is_owner),
- pci_name(idd->idd_pdev));
- }
- }
- mutex_unlock(&ioc4_mutex);
-
- /* Release resources */
- iounmap(idd->idd_misc_regs);
- if (!idd->idd_bar0) {
- printk(KERN_WARNING
- "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
- "Device removal may be incomplete.\n",
- __func__, pci_name(idd->idd_pdev));
- }
- release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
-
- /* Disable IOC4 and relinquish */
- pci_disable_device(pdev);
-
- /* Remove and free driver data */
- mutex_lock(&ioc4_mutex);
- list_del(&idd->idd_list);
- mutex_unlock(&ioc4_mutex);
- kfree(idd);
-}
-
-static const struct pci_device_id ioc4_id_table[] = {
- {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
- PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
- {0}
-};
-
-static struct pci_driver ioc4_driver = {
- .name = "IOC4",
- .id_table = ioc4_id_table,
- .probe = ioc4_probe,
- .remove = ioc4_remove,
-};
-
-MODULE_DEVICE_TABLE(pci, ioc4_id_table);
-
-/*********************
- * Module management *
- *********************/
-
-/* Module load */
-static int __init
-ioc4_init(void)
-{
- return pci_register_driver(&ioc4_driver);
-}
-
-/* Module unload */
-static void __exit
-ioc4_exit(void)
-{
- /* Ensure ioc4_load_modules() has completed before exiting */
- flush_work(&ioc4_load_modules_work);
- pci_unregister_driver(&ioc4_driver);
-}
-
-module_init(ioc4_init);
-module_exit(ioc4_exit);
-
-MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
-MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_register_submodule);
-EXPORT_SYMBOL(ioc4_unregister_submodule);
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 1606658b9b7e..24245ccdba72 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -22,7 +22,7 @@ struct lkdtm_list {
* recurse past the end of THREAD_SIZE by default.
*/
#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
-#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2)
+#define REC_STACK_SIZE (_AC(CONFIG_FRAME_WARN, UL) / 2)
#else
#define REC_STACK_SIZE (THREAD_SIZE / 8)
#endif
@@ -91,7 +91,7 @@ void lkdtm_LOOP(void)
void lkdtm_EXHAUST_STACK(void)
{
- pr_info("Calling function with %d frame size to depth %d ...\n",
+ pr_info("Calling function with %lu frame size to depth %d ...\n",
REC_STACK_SIZE, recur_count);
recursive_loop(recur_count);
pr_info("FAIL: survived without exhausting stack?!\n");
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index d74b182e19f3..77f7dff7098d 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -81,6 +81,11 @@
#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
+#define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */
+
+#define MEI_DEV_ID_MCC 0x4B70 /* Mule Creek Canyon (EHL) */
+#define MEI_DEV_ID_MCC_4 0x4B75 /* Mule Creek Canyon 4 (EHL) */
+
/*
* MEI HW Section
*/
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 7a2b3545a7f9..541538eff8b1 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -98,6 +98,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
+
+ {MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
+
/* required last entry */
{0, }
};
diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
index bbb622c19c06..34c55a4045af 100644
--- a/drivers/misc/sgi-xp/Makefile
+++ b/drivers/misc/sgi-xp/Makefile
@@ -4,17 +4,10 @@
#
obj-$(CONFIG_SGI_XP) += xp.o
-xp-y := xp_main.o
-xp-$(CONFIG_IA64_SGI_SN2) += xp_sn2.o xp_nofault.o
-xp-$(CONFIG_IA64_GENERIC) += xp_sn2.o xp_nofault.o
-xp-$(CONFIG_IA64_SGI_UV) += xp_uv.o
-xp-$(CONFIG_X86_64) += xp_uv.o
+xp-y := xp_main.o xp_uv.o
obj-$(CONFIG_SGI_XP) += xpc.o
-xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
-xpc-$(CONFIG_IA64_SGI_SN2) += xpc_sn2.o
-xpc-$(CONFIG_IA64_GENERIC) += xpc_sn2.o
-xpc-$(CONFIG_IA64_SGI_UV) += xpc_uv.o
-xpc-$(CONFIG_X86_64) += xpc_uv.o
+xpc-y := xpc_main.o xpc_channel.o xpc_partition.o \
+ xpc_uv.o
obj-$(CONFIG_SGI_XP) += xpnet.o
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index b8069eec18cb..06469b12aced 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -24,23 +24,6 @@
#define is_uv() 0
#endif
-#if defined CONFIG_IA64
-#include <asm/sn/arch.h> /* defines is_shub1() and is_shub2() */
-#define is_shub() ia64_platform_is("sn2")
-#endif
-
-#ifndef is_shub1
-#define is_shub1() 0
-#endif
-
-#ifndef is_shub2
-#define is_shub2() 0
-#endif
-
-#ifndef is_shub
-#define is_shub() 0
-#endif
-
#ifdef USE_DBUG_ON
#define DBUG_ON(condition) BUG_ON(condition)
#else
@@ -360,9 +343,7 @@ extern int xp_nofault_PIOR(void *);
extern int xp_error_PIOR(void);
extern struct device *xp;
-extern enum xp_retval xp_init_sn2(void);
extern enum xp_retval xp_init_uv(void);
-extern void xp_exit_sn2(void);
extern void xp_exit_uv(void);
#endif /* _DRIVERS_MISC_SGIXP_XP_H */
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 6d7f557fd1c1..5fd94d836070 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -233,9 +233,7 @@ xp_init(void)
for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
mutex_init(&xpc_registrations[ch_number].mutex);
- if (is_shub())
- ret = xp_init_sn2();
- else if (is_uv())
+ if (is_uv())
ret = xp_init_uv();
else
ret = 0;
@@ -251,9 +249,7 @@ module_init(xp_init);
void __exit
xp_exit(void)
{
- if (is_shub())
- xp_exit_sn2();
- else if (is_uv())
+ if (is_uv())
xp_exit_uv();
}
diff --git a/drivers/misc/sgi-xp/xp_nofault.S b/drivers/misc/sgi-xp/xp_nofault.S
deleted file mode 100644
index e38d43319429..000000000000
--- a/drivers/misc/sgi-xp/xp_nofault.S
+++ /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) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * The xp_nofault_PIOR function takes a pointer to a remote PIO register
- * and attempts to load and consume a value from it. This function
- * will be registered as a nofault code block. In the event that the
- * PIO read fails, the MCA handler will force the error to look
- * corrected and vector to the xp_error_PIOR which will return an error.
- *
- * The definition of "consumption" and the time it takes for an MCA
- * to surface is processor implementation specific. This code
- * is sufficient on Itanium through the Montvale processor family.
- * It may need to be adjusted for future processor implementations.
- *
- * extern int xp_nofault_PIOR(void *remote_register);
- */
-
- .global xp_nofault_PIOR
-xp_nofault_PIOR:
- mov r8=r0 // Stage a success return value
- ld8.acq r9=[r32];; // PIO Read the specified register
- adds r9=1,r9;; // Add to force consumption
- srlz.i;; // Allow time for MCA to surface
- br.ret.sptk.many b0;; // Return success
-
- .global xp_error_PIOR
-xp_error_PIOR:
- mov r8=1 // Return value of 1
- br.ret.sptk.many b0;; // Return failure
diff --git a/drivers/misc/sgi-xp/xp_sn2.c b/drivers/misc/sgi-xp/xp_sn2.c
deleted file mode 100644
index d8e463f87241..000000000000
--- a/drivers/misc/sgi-xp/xp_sn2.c
+++ /dev/null
@@ -1,190 +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) 2008 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * Cross Partition (XP) sn2-based functions.
- *
- * Architecture specific implementation of common functions.
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <asm/sn/bte.h>
-#include <asm/sn/sn_sal.h>
-#include "xp.h"
-
-/*
- * The export of xp_nofault_PIOR needs to happen here since it is defined
- * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
- * defined here.
- */
-EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
-
-u64 xp_nofault_PIOR_target;
-EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);
-
-/*
- * Register a nofault code region which performs a cross-partition PIO read.
- * If the PIO read times out, the MCA handler will consume the error and
- * return to a kernel-provided instruction to indicate an error. This PIO read
- * exists because it is guaranteed to timeout if the destination is down
- * (amo operations do not timeout on at least some CPUs on Shubs <= v1.2,
- * which unfortunately we have to work around).
- */
-static enum xp_retval
-xp_register_nofault_code_sn2(void)
-{
- int ret;
- u64 func_addr;
- u64 err_func_addr;
-
- func_addr = *(u64 *)xp_nofault_PIOR;
- err_func_addr = *(u64 *)xp_error_PIOR;
- ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
- 1, 1);
- if (ret != 0) {
- dev_err(xp, "can't register nofault code, error=%d\n", ret);
- return xpSalError;
- }
- /*
- * Setup the nofault PIO read target. (There is no special reason why
- * SH_IPI_ACCESS was selected.)
- */
- if (is_shub1())
- xp_nofault_PIOR_target = SH1_IPI_ACCESS;
- else if (is_shub2())
- xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
-
- return xpSuccess;
-}
-
-static void
-xp_unregister_nofault_code_sn2(void)
-{
- u64 func_addr = *(u64 *)xp_nofault_PIOR;
- u64 err_func_addr = *(u64 *)xp_error_PIOR;
-
- /* unregister the PIO read nofault code region */
- (void)sn_register_nofault_code(func_addr, err_func_addr,
- err_func_addr, 1, 0);
-}
-
-/*
- * Convert a virtual memory address to a physical memory address.
- */
-static unsigned long
-xp_pa_sn2(void *addr)
-{
- return __pa(addr);
-}
-
-/*
- * Convert a global physical to a socket physical address.
- */
-static unsigned long
-xp_socket_pa_sn2(unsigned long gpa)
-{
- return gpa;
-}
-
-/*
- * Wrapper for bte_copy().
- *
- * dst_pa - physical address of the destination of the transfer.
- * src_pa - physical address of the source of the transfer.
- * len - number of bytes to transfer from source to destination.
- *
- * Note: xp_remote_memcpy_sn2() should never be called while holding a spinlock.
- */
-static enum xp_retval
-xp_remote_memcpy_sn2(unsigned long dst_pa, const unsigned long src_pa,
- size_t len)
-{
- bte_result_t ret;
-
- ret = bte_copy(src_pa, dst_pa, len, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
- if (ret == BTE_SUCCESS)
- return xpSuccess;
-
- if (is_shub2()) {
- dev_err(xp, "bte_copy() on shub2 failed, error=0x%x dst_pa="
- "0x%016lx src_pa=0x%016lx len=%ld\\n", ret, dst_pa,
- src_pa, len);
- } else {
- dev_err(xp, "bte_copy() failed, error=%d dst_pa=0x%016lx "
- "src_pa=0x%016lx len=%ld\\n", ret, dst_pa, src_pa, len);
- }
-
- return xpBteCopyError;
-}
-
-static int
-xp_cpu_to_nasid_sn2(int cpuid)
-{
- return cpuid_to_nasid(cpuid);
-}
-
-static enum xp_retval
-xp_expand_memprotect_sn2(unsigned long phys_addr, unsigned long size)
-{
- u64 nasid_array = 0;
- int ret;
-
- ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1,
- &nasid_array);
- if (ret != 0) {
- dev_err(xp, "sn_change_memprotect(,, "
- "SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret);
- return xpSalError;
- }
- return xpSuccess;
-}
-
-static enum xp_retval
-xp_restrict_memprotect_sn2(unsigned long phys_addr, unsigned long size)
-{
- u64 nasid_array = 0;
- int ret;
-
- ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0,
- &nasid_array);
- if (ret != 0) {
- dev_err(xp, "sn_change_memprotect(,, "
- "SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret);
- return xpSalError;
- }
- return xpSuccess;
-}
-
-enum xp_retval
-xp_init_sn2(void)
-{
- BUG_ON(!is_shub());
-
- xp_max_npartitions = XP_MAX_NPARTITIONS_SN2;
- xp_partition_id = sn_partition_id;
- xp_region_size = sn_region_size;
-
- xp_pa = xp_pa_sn2;
- xp_socket_pa = xp_socket_pa_sn2;
- xp_remote_memcpy = xp_remote_memcpy_sn2;
- xp_cpu_to_nasid = xp_cpu_to_nasid_sn2;
- xp_expand_memprotect = xp_expand_memprotect_sn2;
- xp_restrict_memprotect = xp_restrict_memprotect_sn2;
-
- return xp_register_nofault_code_sn2();
-}
-
-void
-xp_exit_sn2(void)
-{
- BUG_ON(!is_shub());
-
- xp_unregister_nofault_code_sn2();
-}
-
diff --git a/drivers/misc/sgi-xp/xp_uv.c b/drivers/misc/sgi-xp/xp_uv.c
index a0d093274dc0..f15a9f2ac1dd 100644
--- a/drivers/misc/sgi-xp/xp_uv.c
+++ b/drivers/misc/sgi-xp/xp_uv.c
@@ -17,7 +17,7 @@
#include <asm/uv/uv_hub.h>
#if defined CONFIG_X86_64
#include <asm/uv/bios.h>
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
#include <asm/sn/sn_sal.h>
#endif
#include "../sgi-gru/grukservices.h"
@@ -99,7 +99,7 @@ xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size)
return xpBiosError;
}
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
u64 nasid_array;
ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1,
@@ -129,7 +129,7 @@ xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
return xpBiosError;
}
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
u64 nasid_array;
ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0,
@@ -151,9 +151,10 @@ xp_init_uv(void)
BUG_ON(!is_uv());
xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
+#ifdef CONFIG_X86
xp_partition_id = sn_partition_id;
xp_region_size = sn_region_size;
-
+#endif
xp_pa = xp_pa_uv;
xp_socket_pa = xp_socket_pa_uv;
xp_remote_memcpy = xp_remote_memcpy_uv;
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index b94d5f767703..71db60edff65 100644
--- a/drivers/misc/sgi-xp/xpc.h
+++ b/drivers/misc/sgi-xp/xpc.h
@@ -71,14 +71,10 @@
* 'SAL_nasids_size'. (Local partition's mask pointers are xpc_part_nasids
* and xpc_mach_nasids.)
*
- * vars (ia64-sn2 only)
- * vars part (ia64-sn2 only)
- *
* Immediately following the mach_nasids mask are the XPC variables
* required by other partitions. First are those that are generic to all
* partitions (vars), followed on the next available cacheline by those
* which are partition specific (vars part). These are setup by XPC.
- * (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
*
* Note: Until 'ts_jiffies' is set non-zero, the partition XPC code has not been
* initialized.
@@ -93,9 +89,6 @@ struct xpc_rsvd_page {
unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
union {
struct {
- unsigned long vars_pa; /* phys addr */
- } sn2;
- struct {
unsigned long heartbeat_gpa; /* phys addr */
unsigned long activate_gru_mq_desc_gpa; /* phys addr */
} uv;
@@ -106,84 +99,14 @@ struct xpc_rsvd_page {
#define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */
-/*
- * Define the structures by which XPC variables can be exported to other
- * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
- */
-
-/*
- * The following structure describes the partition generic variables
- * needed by other partitions in order to properly initialize.
- *
- * struct xpc_vars version number also applies to struct xpc_vars_part.
- * Changes to either structure and/or related functionality should be
- * reflected by incrementing either the major or minor version numbers
- * of struct xpc_vars.
- */
-struct xpc_vars_sn2 {
- u8 version;
- u64 heartbeat;
- DECLARE_BITMAP(heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
- u64 heartbeat_offline; /* if 0, heartbeat should be changing */
- int activate_IRQ_nasid;
- int activate_IRQ_phys_cpuid;
- unsigned long vars_part_pa;
- unsigned long amos_page_pa;/* paddr of page of amos from MSPEC driver */
- struct amo *amos_page; /* vaddr of page of amos from MSPEC driver */
-};
-
-#define XPC_V_VERSION _XPC_VERSION(3, 1) /* version 3.1 of the cross vars */
-
-/*
- * The following structure describes the per partition specific variables.
- *
- * An array of these structures, one per partition, will be defined. As a
- * partition becomes active XPC will copy the array entry corresponding to
- * itself from that partition. It is desirable that the size of this structure
- * evenly divides into a 128-byte cacheline, such that none of the entries in
- * this array crosses a 128-byte cacheline boundary. As it is now, each entry
- * occupies 64-bytes.
- */
-struct xpc_vars_part_sn2 {
- u64 magic;
-
- unsigned long openclose_args_pa; /* phys addr of open and close args */
- unsigned long GPs_pa; /* physical address of Get/Put values */
-
- unsigned long chctl_amo_pa; /* physical address of chctl flags' amo */
-
- int notify_IRQ_nasid; /* nasid of where to send notify IRQs */
- int notify_IRQ_phys_cpuid; /* CPUID of where to send notify IRQs */
-
- u8 nchannels; /* #of defined channels supported */
-
- u8 reserved[23]; /* pad to a full 64 bytes */
-};
-
-/*
- * The vars_part MAGIC numbers play a part in the first contact protocol.
- *
- * MAGIC1 indicates that the per partition specific variables for a remote
- * partition have been initialized by this partition.
- *
- * MAGIC2 indicates that this partition has pulled the remote partititions
- * per partition variables that pertain to this partition.
- */
-#define XPC_VP_MAGIC1_SN2 0x0053524156435058L /* 'XPCVARS\0'L (little endian) */
-#define XPC_VP_MAGIC2_SN2 0x0073726176435058L /* 'XPCvars\0'L (little endian) */
-
/* the reserved page sizes and offsets */
#define XPC_RP_HEADER_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
-#define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars_sn2))
#define XPC_RP_PART_NASIDS(_rp) ((unsigned long *)((u8 *)(_rp) + \
XPC_RP_HEADER_SIZE))
#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + \
xpc_nasid_mask_nlongs)
-#define XPC_RP_VARS(_rp) ((struct xpc_vars_sn2 *) \
- (XPC_RP_MACH_NASIDS(_rp) + \
- xpc_nasid_mask_nlongs))
/*
@@ -298,17 +221,6 @@ struct xpc_activate_mq_msg_chctl_opencomplete_uv {
#define XPC_UNPACK_ARG2(_args) ((((u64)_args) >> 32) & 0xffffffff)
/*
- * Define a Get/Put value pair (pointers) used with a message queue.
- */
-struct xpc_gp_sn2 {
- s64 get; /* Get value */
- s64 put; /* Put value */
-};
-
-#define XPC_GP_SIZE \
- L1_CACHE_ALIGN(sizeof(struct xpc_gp_sn2) * XPC_MAX_NCHANNELS)
-
-/*
* Define a structure that contains arguments associated with opening and
* closing a channel.
*/
@@ -341,30 +253,6 @@ struct xpc_fifo_head_uv {
};
/*
- * Define a sn2 styled message.
- *
- * A user-defined message resides in the payload area. The max size of the
- * payload is defined by the user via xpc_connect().
- *
- * The size of a message entry (within a message queue) must be a 128-byte
- * cacheline sized multiple in order to facilitate the BTE transfer of messages
- * from one message queue to another.
- */
-struct xpc_msg_sn2 {
- u8 flags; /* FOR XPC INTERNAL USE ONLY */
- u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */
- s64 number; /* FOR XPC INTERNAL USE ONLY */
-
- u64 payload; /* user defined portion of message */
-};
-
-/* struct xpc_msg_sn2 flags */
-
-#define XPC_M_SN2_DONE 0x01 /* msg has been received/consumed */
-#define XPC_M_SN2_READY 0x02 /* msg is ready to be sent */
-#define XPC_M_SN2_INTERRUPT 0x04 /* send interrupt when msg consumed */
-
-/*
* The format of a uv XPC notify_mq GRU message is as follows:
*
* A user-defined message resides in the payload area. The max size of the
@@ -390,20 +278,6 @@ struct xpc_notify_mq_msg_uv {
unsigned long payload;
};
-/*
- * Define sn2's notify entry.
- *
- * This is used to notify a message's sender that their message was received
- * and consumed by the intended recipient.
- */
-struct xpc_notify_sn2 {
- u8 type; /* type of notification */
-
- /* the following two fields are only used if type == XPC_N_CALL */
- xpc_notify_func func; /* user's notify function */
- void *key; /* pointer to user's key */
-};
-
/* struct xpc_notify_sn2 type of notification */
#define XPC_N_CALL 0x01 /* notify function provided by user */
@@ -431,102 +305,6 @@ struct xpc_send_msg_slot_uv {
* of these structures for each potential channel connection to that partition.
*/
-/*
- * The following is sn2 only.
- *
- * Each channel structure manages two message queues (circular buffers).
- * They are allocated at the time a channel connection is made. One of
- * these message queues (local_msgqueue) holds the locally created messages
- * that are destined for the remote partition. The other of these message
- * queues (remote_msgqueue) is a locally cached copy of the remote partition's
- * own local_msgqueue.
- *
- * The following is a description of the Get/Put pointers used to manage these
- * two message queues. Consider the local_msgqueue to be on one partition
- * and the remote_msgqueue to be its cached copy on another partition. A
- * description of what each of the lettered areas contains is included.
- *
- *
- * local_msgqueue remote_msgqueue
- *
- * |/////////| |/////////|
- * w_remote_GP.get --> +---------+ |/////////|
- * | F | |/////////|
- * remote_GP.get --> +---------+ +---------+ <-- local_GP->get
- * | | | |
- * | | | E |
- * | | | |
- * | | +---------+ <-- w_local_GP.get
- * | B | |/////////|
- * | | |////D////|
- * | | |/////////|
- * | | +---------+ <-- w_remote_GP.put
- * | | |////C////|
- * local_GP->put --> +---------+ +---------+ <-- remote_GP.put
- * | | |/////////|
- * | A | |/////////|
- * | | |/////////|
- * w_local_GP.put --> +---------+ |/////////|
- * |/////////| |/////////|
- *
- *
- * ( remote_GP.[get|put] are cached copies of the remote
- * partition's local_GP->[get|put], and thus their values can
- * lag behind their counterparts on the remote partition. )
- *
- *
- * A - Messages that have been allocated, but have not yet been sent to the
- * remote partition.
- *
- * B - Messages that have been sent, but have not yet been acknowledged by the
- * remote partition as having been received.
- *
- * C - Area that needs to be prepared for the copying of sent messages, by
- * the clearing of the message flags of any previously received messages.
- *
- * D - Area into which sent messages are to be copied from the remote
- * partition's local_msgqueue and then delivered to their intended
- * recipients. [ To allow for a multi-message copy, another pointer
- * (next_msg_to_pull) has been added to keep track of the next message
- * number needing to be copied (pulled). It chases after w_remote_GP.put.
- * Any messages lying between w_local_GP.get and next_msg_to_pull have
- * been copied and are ready to be delivered. ]
- *
- * E - Messages that have been copied and delivered, but have not yet been
- * acknowledged by the recipient as having been received.
- *
- * F - Messages that have been acknowledged, but XPC has not yet notified the
- * sender that the message was received by its intended recipient.
- * This is also an area that needs to be prepared for the allocating of
- * new messages, by the clearing of the message flags of the acknowledged
- * messages.
- */
-
-struct xpc_channel_sn2 {
- struct xpc_openclose_args *local_openclose_args; /* args passed on */
- /* opening or closing of channel */
-
- void *local_msgqueue_base; /* base address of kmalloc'd space */
- struct xpc_msg_sn2 *local_msgqueue; /* local message queue */
- void *remote_msgqueue_base; /* base address of kmalloc'd space */
- struct xpc_msg_sn2 *remote_msgqueue; /* cached copy of remote */
- /* partition's local message queue */
- unsigned long remote_msgqueue_pa; /* phys addr of remote partition's */
- /* local message queue */
-
- struct xpc_notify_sn2 *notify_queue;/* notify queue for messages sent */
-
- /* various flavors of local and remote Get/Put values */
-
- struct xpc_gp_sn2 *local_GP; /* local Get/Put values */
- struct xpc_gp_sn2 remote_GP; /* remote Get/Put values */
- struct xpc_gp_sn2 w_local_GP; /* working local Get/Put values */
- struct xpc_gp_sn2 w_remote_GP; /* working remote Get/Put values */
- s64 next_msg_to_pull; /* Put value of next msg to pull */
-
- struct mutex msg_to_pull_mutex; /* next msg to pull serialization */
-};
-
struct xpc_channel_uv {
void *cached_notify_gru_mq_desc; /* remote partition's notify mq's */
/* gru mq descriptor */
@@ -579,7 +357,6 @@ struct xpc_channel {
wait_queue_head_t idle_wq; /* idle kthread wait queue */
union {
- struct xpc_channel_sn2 sn2;
struct xpc_channel_uv uv;
} sn;
@@ -666,43 +443,6 @@ xpc_any_msg_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
return 0;
}
-/*
- * Manage channels on a partition basis. There is one of these structures
- * for each partition (a partition will never utilize the structure that
- * represents itself).
- */
-
-struct xpc_partition_sn2 {
- unsigned long remote_amos_page_pa; /* paddr of partition's amos page */
- int activate_IRQ_nasid; /* active partition's act/deact nasid */
- int activate_IRQ_phys_cpuid; /* active part's act/deact phys cpuid */
-
- unsigned long remote_vars_pa; /* phys addr of partition's vars */
- unsigned long remote_vars_part_pa; /* paddr of partition's vars part */
- u8 remote_vars_version; /* version# of partition's vars */
-
- void *local_GPs_base; /* base address of kmalloc'd space */
- struct xpc_gp_sn2 *local_GPs; /* local Get/Put values */
- void *remote_GPs_base; /* base address of kmalloc'd space */
- struct xpc_gp_sn2 *remote_GPs; /* copy of remote partition's local */
- /* Get/Put values */
- unsigned long remote_GPs_pa; /* phys addr of remote partition's local */
- /* Get/Put values */
-
- void *local_openclose_args_base; /* base address of kmalloc'd space */
- struct xpc_openclose_args *local_openclose_args; /* local's args */
- unsigned long remote_openclose_args_pa; /* phys addr of remote's args */
-
- int notify_IRQ_nasid; /* nasid of where to send notify IRQs */
- int notify_IRQ_phys_cpuid; /* CPUID of where to send notify IRQs */
- char notify_IRQ_owner[8]; /* notify IRQ's owner's name */
-
- struct amo *remote_chctl_amo_va; /* addr of remote chctl flags' amo */
- struct amo *local_chctl_amo_va; /* address of chctl flags' amo */
-
- struct timer_list dropped_notify_IRQ_timer; /* dropped IRQ timer */
-};
-
struct xpc_partition_uv {
unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */
struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */
@@ -774,7 +514,6 @@ struct xpc_partition {
wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
union {
- struct xpc_partition_sn2 sn2;
struct xpc_partition_uv uv;
} sn;
@@ -854,14 +593,6 @@ struct xpc_arch_operations {
#define XPC_P_SS_WTEARDOWN 0x02 /* waiting to teardown infrastructure */
#define XPC_P_SS_TORNDOWN 0x03 /* infrastructure is torndown */
-/*
- * struct xpc_partition_sn2's dropped notify IRQ timer is set to wait the
- * following interval #of seconds before checking for dropped notify IRQs.
- * These can occur whenever an IRQ's associated amo write doesn't complete
- * until after the IRQ was received.
- */
-#define XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL (0.25 * HZ)
-
/* number of seconds to wait for other partitions to disengage */
#define XPC_DISENGAGE_DEFAULT_TIMELIMIT 90
@@ -888,10 +619,6 @@ extern void xpc_activate_kthreads(struct xpc_channel *, int);
extern void xpc_create_kthreads(struct xpc_channel *, int, int);
extern void xpc_disconnect_wait(int);
-/* found in xpc_sn2.c */
-extern int xpc_init_sn2(void);
-extern void xpc_exit_sn2(void);
-
/* found in xpc_uv.c */
extern int xpc_init_uv(void);
extern void xpc_exit_uv(void);
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 83fc748a91a7..79a963105983 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -279,13 +279,6 @@ xpc_hb_checker(void *ignore)
dev_dbg(xpc_part, "checking remote heartbeats\n");
xpc_check_remote_hb();
-
- /*
- * On sn2 we need to periodically recheck to ensure no
- * IRQ/amo pairs have been missed.
- */
- if (is_shub())
- force_IRQ = 1;
}
/* check for outstanding IRQs */
@@ -1050,9 +1043,7 @@ xpc_do_exit(enum xp_retval reason)
xpc_teardown_partitions();
- if (is_shub())
- xpc_exit_sn2();
- else if (is_uv())
+ if (is_uv())
xpc_exit_uv();
}
@@ -1235,21 +1226,7 @@ xpc_init(void)
dev_set_name(xpc_part, "part");
dev_set_name(xpc_chan, "chan");
- if (is_shub()) {
- /*
- * The ia64-sn2 architecture supports at most 64 partitions.
- * And the inability to unregister remote amos restricts us
- * further to only support exactly 64 partitions on this
- * architecture, no less.
- */
- if (xp_max_npartitions != 64) {
- dev_err(xpc_part, "max #of partitions not set to 64\n");
- ret = -EINVAL;
- } else {
- ret = xpc_init_sn2();
- }
-
- } else if (is_uv()) {
+ if (is_uv()) {
ret = xpc_init_uv();
} else {
@@ -1335,9 +1312,7 @@ out_2:
xpc_teardown_partitions();
out_1:
- if (is_shub())
- xpc_exit_sn2();
- else if (is_uv())
+ if (is_uv())
xpc_exit_uv();
return ret;
}
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
index 782ce95d3f17..21a04bc97d40 100644
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -93,10 +93,6 @@ xpc_get_rsvd_page_pa(int nasid)
if (ret != xpNeedMoreInfo)
break;
- /* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */
- if (is_shub())
- len = L1_CACHE_ALIGN(len);
-
if (len > buf_len) {
kfree(buf_base);
buf_len = L1_CACHE_ALIGN(len);
@@ -452,7 +448,6 @@ xpc_discovery(void)
case 32:
max_regions *= 2;
region_size = 16;
- DBUG_ON(!is_shub2());
}
}
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
deleted file mode 100644
index 0ae69b9390ce..000000000000
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ /dev/null
@@ -1,2459 +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) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * Cross Partition Communication (XPC) sn2-based functions.
- *
- * Architecture specific implementation of common functions.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <asm/uncached.h>
-#include <asm/sn/mspec.h>
-#include <asm/sn/sn_sal.h>
-#include "xpc.h"
-
-/*
- * Define the number of u64s required to represent all the C-brick nasids
- * as a bitmap. The cross-partition kernel modules deal only with
- * C-brick nasids, thus the need for bitmaps which don't account for
- * odd-numbered (non C-brick) nasids.
- */
-#define XPC_MAX_PHYSNODES_SN2 (MAX_NUMALINK_NODES / 2)
-#define XP_NASID_MASK_BYTES_SN2 ((XPC_MAX_PHYSNODES_SN2 + 7) / 8)
-#define XP_NASID_MASK_WORDS_SN2 ((XPC_MAX_PHYSNODES_SN2 + 63) / 64)
-
-/*
- * Memory for XPC's amo variables is allocated by the MSPEC driver. These
- * pages are located in the lowest granule. The lowest granule uses 4k pages
- * for cached references and an alternate TLB handler to never provide a
- * cacheable mapping for the entire region. This will prevent speculative
- * reading of cached copies of our lines from being issued which will cause
- * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
- * amo variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of
- * NOTIFY IRQs, 128 amo variables (based on XP_NASID_MASK_WORDS_SN2) to identify
- * the senders of ACTIVATE IRQs, 1 amo variable to identify which remote
- * partitions (i.e., XPCs) consider themselves currently engaged with the
- * local XPC and 1 amo variable to request partition deactivation.
- */
-#define XPC_NOTIFY_IRQ_AMOS_SN2 0
-#define XPC_ACTIVATE_IRQ_AMOS_SN2 (XPC_NOTIFY_IRQ_AMOS_SN2 + \
- XP_MAX_NPARTITIONS_SN2)
-#define XPC_ENGAGED_PARTITIONS_AMO_SN2 (XPC_ACTIVATE_IRQ_AMOS_SN2 + \
- XP_NASID_MASK_WORDS_SN2)
-#define XPC_DEACTIVATE_REQUEST_AMO_SN2 (XPC_ENGAGED_PARTITIONS_AMO_SN2 + 1)
-
-/*
- * Buffer used to store a local copy of portions of a remote partition's
- * reserved page (either its header and part_nasids mask, or its vars).
- */
-static void *xpc_remote_copy_buffer_base_sn2;
-static char *xpc_remote_copy_buffer_sn2;
-
-static struct xpc_vars_sn2 *xpc_vars_sn2;
-static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
-
-static int
-xpc_setup_partitions_sn2(void)
-{
- /* nothing needs to be done */
- return 0;
-}
-
-static void
-xpc_teardown_partitions_sn2(void)
-{
- /* nothing needs to be done */
-}
-
-/* SH_IPI_ACCESS shub register value on startup */
-static u64 xpc_sh1_IPI_access_sn2;
-static u64 xpc_sh2_IPI_access0_sn2;
-static u64 xpc_sh2_IPI_access1_sn2;
-static u64 xpc_sh2_IPI_access2_sn2;
-static u64 xpc_sh2_IPI_access3_sn2;
-
-/*
- * Change protections to allow IPI operations.
- */
-static void
-xpc_allow_IPI_ops_sn2(void)
-{
- int node;
- int nasid;
-
- /* !!! The following should get moved into SAL. */
- if (is_shub2()) {
- xpc_sh2_IPI_access0_sn2 =
- (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
- xpc_sh2_IPI_access1_sn2 =
- (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
- xpc_sh2_IPI_access2_sn2 =
- (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
- xpc_sh2_IPI_access3_sn2 =
- (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
-
- for_each_online_node(node) {
- nasid = cnodeid_to_nasid(node);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
- -1UL);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
- -1UL);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
- -1UL);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
- -1UL);
- }
- } else {
- xpc_sh1_IPI_access_sn2 =
- (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
-
- for_each_online_node(node) {
- nasid = cnodeid_to_nasid(node);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
- -1UL);
- }
- }
-}
-
-/*
- * Restrict protections to disallow IPI operations.
- */
-static void
-xpc_disallow_IPI_ops_sn2(void)
-{
- int node;
- int nasid;
-
- /* !!! The following should get moved into SAL. */
- if (is_shub2()) {
- for_each_online_node(node) {
- nasid = cnodeid_to_nasid(node);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
- xpc_sh2_IPI_access0_sn2);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
- xpc_sh2_IPI_access1_sn2);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
- xpc_sh2_IPI_access2_sn2);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
- xpc_sh2_IPI_access3_sn2);
- }
- } else {
- for_each_online_node(node) {
- nasid = cnodeid_to_nasid(node);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
- xpc_sh1_IPI_access_sn2);
- }
- }
-}
-
-/*
- * The following set of functions are used for the sending and receiving of
- * IRQs (also known as IPIs). There are two flavors of IRQs, one that is
- * associated with partition activity (SGI_XPC_ACTIVATE) and the other that
- * is associated with channel activity (SGI_XPC_NOTIFY).
- */
-
-static u64
-xpc_receive_IRQ_amo_sn2(struct amo *amo)
-{
- return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
-}
-
-static enum xp_retval
-xpc_send_IRQ_sn2(struct amo *amo, u64 flag, int nasid, int phys_cpuid,
- int vector)
-{
- int ret = 0;
- unsigned long irq_flags;
-
- local_irq_save(irq_flags);
-
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
- sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
-
- /*
- * We must always use the nofault function regardless of whether we
- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
- * didn't, we'd never know that the other partition is down and would
- * keep sending IRQs and amos to it until the heartbeat times out.
- */
- ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
- xp_nofault_PIOR_target));
-
- local_irq_restore(irq_flags);
-
- return (ret == 0) ? xpSuccess : xpPioReadError;
-}
-
-static struct amo *
-xpc_init_IRQ_amo_sn2(int index)
-{
- struct amo *amo = xpc_vars_sn2->amos_page + index;
-
- (void)xpc_receive_IRQ_amo_sn2(amo); /* clear amo variable */
- return amo;
-}
-
-/*
- * Functions associated with SGI_XPC_ACTIVATE IRQ.
- */
-
-/*
- * Notify the heartbeat check thread that an activate IRQ has been received.
- */
-static irqreturn_t
-xpc_handle_activate_IRQ_sn2(int irq, void *dev_id)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
- xpc_activate_IRQ_rcvd++;
- spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
- wake_up_interruptible(&xpc_activate_IRQ_wq);
- return IRQ_HANDLED;
-}
-
-/*
- * Flag the appropriate amo variable and send an IRQ to the specified node.
- */
-static void
-xpc_send_activate_IRQ_sn2(unsigned long amos_page_pa, int from_nasid,
- int to_nasid, int to_phys_cpuid)
-{
- struct amo *amos = (struct amo *)__va(amos_page_pa +
- (XPC_ACTIVATE_IRQ_AMOS_SN2 *
- sizeof(struct amo)));
-
- (void)xpc_send_IRQ_sn2(&amos[BIT_WORD(from_nasid / 2)],
- BIT_MASK(from_nasid / 2), to_nasid,
- to_phys_cpuid, SGI_XPC_ACTIVATE);
-}
-
-static void
-xpc_send_local_activate_IRQ_sn2(int from_nasid)
-{
- unsigned long irq_flags;
- struct amo *amos = (struct amo *)__va(xpc_vars_sn2->amos_page_pa +
- (XPC_ACTIVATE_IRQ_AMOS_SN2 *
- sizeof(struct amo)));
-
- /* fake the sending and receipt of an activate IRQ from remote nasid */
- FETCHOP_STORE_OP(TO_AMO((u64)&amos[BIT_WORD(from_nasid / 2)].variable),
- FETCHOP_OR, BIT_MASK(from_nasid / 2));
-
- spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
- xpc_activate_IRQ_rcvd++;
- spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
- wake_up_interruptible(&xpc_activate_IRQ_wq);
-}
-
-/*
- * Functions associated with SGI_XPC_NOTIFY IRQ.
- */
-
-/*
- * Check to see if any chctl flags were sent from the specified partition.
- */
-static void
-xpc_check_for_sent_chctl_flags_sn2(struct xpc_partition *part)
-{
- union xpc_channel_ctl_flags chctl;
- unsigned long irq_flags;
-
- chctl.all_flags = xpc_receive_IRQ_amo_sn2(part->sn.sn2.
- local_chctl_amo_va);
- if (chctl.all_flags == 0)
- return;
-
- spin_lock_irqsave(&part->chctl_lock, irq_flags);
- part->chctl.all_flags |= chctl.all_flags;
- spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
- dev_dbg(xpc_chan, "received notify IRQ from partid=%d, chctl.all_flags="
- "0x%llx\n", XPC_PARTID(part), chctl.all_flags);
-
- xpc_wakeup_channel_mgr(part);
-}
-
-/*
- * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
- * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
- * than one partition, we use an amo structure per partition to indicate
- * whether a partition has sent an IRQ or not. If it has, then wake up the
- * associated kthread to handle it.
- *
- * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IRQs sent by XPC
- * running on other partitions.
- *
- * Noteworthy Arguments:
- *
- * irq - Interrupt ReQuest number. NOT USED.
- *
- * dev_id - partid of IRQ's potential sender.
- */
-static irqreturn_t
-xpc_handle_notify_IRQ_sn2(int irq, void *dev_id)
-{
- short partid = (short)(u64)dev_id;
- struct xpc_partition *part = &xpc_partitions[partid];
-
- DBUG_ON(partid < 0 || partid >= XP_MAX_NPARTITIONS_SN2);
-
- if (xpc_part_ref(part)) {
- xpc_check_for_sent_chctl_flags_sn2(part);
-
- xpc_part_deref(part);
- }
- return IRQ_HANDLED;
-}
-
-/*
- * Check to see if xpc_handle_notify_IRQ_sn2() dropped any IRQs on the floor
- * because the write to their associated amo variable completed after the IRQ
- * was received.
- */
-static void
-xpc_check_for_dropped_notify_IRQ_sn2(struct timer_list *t)
-{
- struct xpc_partition *part =
- from_timer(part, t, sn.sn2.dropped_notify_IRQ_timer);
-
- if (xpc_part_ref(part)) {
- xpc_check_for_sent_chctl_flags_sn2(part);
-
- t->expires = jiffies + XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
- add_timer(t);
- xpc_part_deref(part);
- }
-}
-
-/*
- * Send a notify IRQ to the remote partition that is associated with the
- * specified channel.
- */
-static void
-xpc_send_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
- char *chctl_flag_string, unsigned long *irq_flags)
-{
- struct xpc_partition *part = &xpc_partitions[ch->partid];
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- union xpc_channel_ctl_flags chctl = { 0 };
- enum xp_retval ret;
-
- if (likely(part->act_state != XPC_P_AS_DEACTIVATING)) {
- chctl.flags[ch->number] = chctl_flag;
- ret = xpc_send_IRQ_sn2(part_sn2->remote_chctl_amo_va,
- chctl.all_flags,
- part_sn2->notify_IRQ_nasid,
- part_sn2->notify_IRQ_phys_cpuid,
- SGI_XPC_NOTIFY);
- dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
- chctl_flag_string, ch->partid, ch->number, ret);
- if (unlikely(ret != xpSuccess)) {
- if (irq_flags != NULL)
- spin_unlock_irqrestore(&ch->lock, *irq_flags);
- XPC_DEACTIVATE_PARTITION(part, ret);
- if (irq_flags != NULL)
- spin_lock_irqsave(&ch->lock, *irq_flags);
- }
- }
-}
-
-#define XPC_SEND_NOTIFY_IRQ_SN2(_ch, _ipi_f, _irq_f) \
- xpc_send_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
-
-/*
- * Make it look like the remote partition, which is associated with the
- * specified channel, sent us a notify IRQ. This faked IRQ will be handled
- * by xpc_check_for_dropped_notify_IRQ_sn2().
- */
-static void
-xpc_send_local_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
- char *chctl_flag_string)
-{
- struct xpc_partition *part = &xpc_partitions[ch->partid];
- union xpc_channel_ctl_flags chctl = { 0 };
-
- chctl.flags[ch->number] = chctl_flag;
- FETCHOP_STORE_OP(TO_AMO((u64)&part->sn.sn2.local_chctl_amo_va->
- variable), FETCHOP_OR, chctl.all_flags);
- dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
- chctl_flag_string, ch->partid, ch->number);
-}
-
-#define XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(_ch, _ipi_f) \
- xpc_send_local_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f)
-
-static void
-xpc_send_chctl_closerequest_sn2(struct xpc_channel *ch,
- unsigned long *irq_flags)
-{
- struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
-
- args->reason = ch->reason;
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREQUEST, irq_flags);
-}
-
-static void
-xpc_send_chctl_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
-{
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREPLY, irq_flags);
-}
-
-static void
-xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
-{
- struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
-
- args->entry_size = ch->entry_size;
- args->local_nentries = ch->local_nentries;
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREQUEST, irq_flags);
-}
-
-static void
-xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
-{
- struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
-
- args->remote_nentries = ch->remote_nentries;
- args->local_nentries = ch->local_nentries;
- args->local_msgqueue_pa = xp_pa(ch->sn.sn2.local_msgqueue);
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREPLY, irq_flags);
-}
-
-static void
-xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch,
- unsigned long *irq_flags)
-{
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags);
-}
-
-static void
-xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch)
-{
- XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL);
-}
-
-static void
-xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch)
-{
- XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST);
-}
-
-static enum xp_retval
-xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch,
- unsigned long msgqueue_pa)
-{
- ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa;
- return xpSuccess;
-}
-
-/*
- * This next set of functions are used to keep track of when a partition is
- * potentially engaged in accessing memory belonging to another partition.
- */
-
-static void
-xpc_indicate_partition_engaged_sn2(struct xpc_partition *part)
-{
- unsigned long irq_flags;
- struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
- (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
- sizeof(struct amo)));
-
- local_irq_save(irq_flags);
-
- /* set bit corresponding to our partid in remote partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
- BIT(sn_partition_id));
-
- /*
- * We must always use the nofault function regardless of whether we
- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
- * didn't, we'd never know that the other partition is down and would
- * keep sending IRQs and amos to it until the heartbeat times out.
- */
- (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
- variable),
- xp_nofault_PIOR_target));
-
- local_irq_restore(irq_flags);
-}
-
-static void
-xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- unsigned long irq_flags;
- struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
- (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
- sizeof(struct amo)));
-
- local_irq_save(irq_flags);
-
- /* clear bit corresponding to our partid in remote partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
- ~BIT(sn_partition_id));
-
- /*
- * We must always use the nofault function regardless of whether we
- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
- * didn't, we'd never know that the other partition is down and would
- * keep sending IRQs and amos to it until the heartbeat times out.
- */
- (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
- variable),
- xp_nofault_PIOR_target));
-
- local_irq_restore(irq_flags);
-
- /*
- * Send activate IRQ to get other side to see that we've cleared our
- * bit in their engaged partitions amo.
- */
- xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
- cnodeid_to_nasid(0),
- part_sn2->activate_IRQ_nasid,
- part_sn2->activate_IRQ_phys_cpuid);
-}
-
-static void
-xpc_assume_partition_disengaged_sn2(short partid)
-{
- struct amo *amo = xpc_vars_sn2->amos_page +
- XPC_ENGAGED_PARTITIONS_AMO_SN2;
-
- /* clear bit(s) based on partid mask in our partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
- ~BIT(partid));
-}
-
-static int
-xpc_partition_engaged_sn2(short partid)
-{
- struct amo *amo = xpc_vars_sn2->amos_page +
- XPC_ENGAGED_PARTITIONS_AMO_SN2;
-
- /* our partition's amo variable ANDed with partid mask */
- return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
- BIT(partid)) != 0;
-}
-
-static int
-xpc_any_partition_engaged_sn2(void)
-{
- struct amo *amo = xpc_vars_sn2->amos_page +
- XPC_ENGAGED_PARTITIONS_AMO_SN2;
-
- /* our partition's amo variable */
- return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0;
-}
-
-/* original protection values for each node */
-static u64 xpc_prot_vec_sn2[MAX_NUMNODES];
-
-/*
- * Change protections to allow amo operations on non-Shub 1.1 systems.
- */
-static enum xp_retval
-xpc_allow_amo_ops_sn2(struct amo *amos_page)
-{
- enum xp_retval ret = xpSuccess;
-
- /*
- * On SHUB 1.1, we cannot call sn_change_memprotect() since the BIST
- * collides with memory operations. On those systems we call
- * xpc_allow_amo_ops_shub_wars_1_1_sn2() instead.
- */
- if (!enable_shub_wars_1_1())
- ret = xp_expand_memprotect(ia64_tpa((u64)amos_page), PAGE_SIZE);
-
- return ret;
-}
-
-/*
- * Change protections to allow amo operations on Shub 1.1 systems.
- */
-static void
-xpc_allow_amo_ops_shub_wars_1_1_sn2(void)
-{
- int node;
- int nasid;
-
- if (!enable_shub_wars_1_1())
- return;
-
- for_each_online_node(node) {
- nasid = cnodeid_to_nasid(node);
- /* save current protection values */
- xpc_prot_vec_sn2[node] =
- (u64)HUB_L((u64 *)GLOBAL_MMR_ADDR(nasid,
- SH1_MD_DQLP_MMR_DIR_PRIVEC0));
- /* open up everything */
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
- SH1_MD_DQLP_MMR_DIR_PRIVEC0),
- -1UL);
- HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
- SH1_MD_DQRP_MMR_DIR_PRIVEC0),
- -1UL);
- }
-}
-
-static enum xp_retval
-xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
- size_t *len)
-{
- s64 status;
- enum xp_retval ret;
-
- status = sn_partition_reserved_page_pa((u64)buf, cookie,
- (u64 *)rp_pa, (u64 *)len);
- if (status == SALRET_OK)
- ret = xpSuccess;
- else if (status == SALRET_MORE_PASSES)
- ret = xpNeedMoreInfo;
- else
- ret = xpSalError;
-
- return ret;
-}
-
-
-static int
-xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp)
-{
- struct amo *amos_page;
- int i;
- int ret;
-
- xpc_vars_sn2 = XPC_RP_VARS(rp);
-
- rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2);
-
- /* vars_part array follows immediately after vars */
- xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
- XPC_RP_VARS_SIZE);
-
- /*
- * Before clearing xpc_vars_sn2, see if a page of amos had been
- * previously allocated. If not we'll need to allocate one and set
- * permissions so that cross-partition amos are allowed.
- *
- * The allocated amo page needs MCA reporting to remain disabled after
- * XPC has unloaded. To make this work, we keep a copy of the pointer
- * to this page (i.e., amos_page) in the struct xpc_vars_sn2 structure,
- * which is pointed to by the reserved page, and re-use that saved copy
- * on subsequent loads of XPC. This amo page is never freed, and its
- * memory protections are never restricted.
- */
- amos_page = xpc_vars_sn2->amos_page;
- if (amos_page == NULL) {
- amos_page = (struct amo *)TO_AMO(uncached_alloc_page(0, 1));
- if (amos_page == NULL) {
- dev_err(xpc_part, "can't allocate page of amos\n");
- return -ENOMEM;
- }
-
- /*
- * Open up amo-R/W to cpu. This is done on Shub 1.1 systems
- * when xpc_allow_amo_ops_shub_wars_1_1_sn2() is called.
- */
- ret = xpc_allow_amo_ops_sn2(amos_page);
- if (ret != xpSuccess) {
- dev_err(xpc_part, "can't allow amo operations\n");
- uncached_free_page(__IA64_UNCACHED_OFFSET |
- TO_PHYS((u64)amos_page), 1);
- return -EPERM;
- }
- }
-
- /* clear xpc_vars_sn2 */
- memset(xpc_vars_sn2, 0, sizeof(struct xpc_vars_sn2));
-
- xpc_vars_sn2->version = XPC_V_VERSION;
- xpc_vars_sn2->activate_IRQ_nasid = cpuid_to_nasid(0);
- xpc_vars_sn2->activate_IRQ_phys_cpuid = cpu_physical_id(0);
- xpc_vars_sn2->vars_part_pa = xp_pa(xpc_vars_part_sn2);
- xpc_vars_sn2->amos_page_pa = ia64_tpa((u64)amos_page);
- xpc_vars_sn2->amos_page = amos_page; /* save for next load of XPC */
-
- /* clear xpc_vars_part_sn2 */
- memset((u64 *)xpc_vars_part_sn2, 0, sizeof(struct xpc_vars_part_sn2) *
- XP_MAX_NPARTITIONS_SN2);
-
- /* initialize the activate IRQ related amo variables */
- for (i = 0; i < xpc_nasid_mask_nlongs; i++)
- (void)xpc_init_IRQ_amo_sn2(XPC_ACTIVATE_IRQ_AMOS_SN2 + i);
-
- /* initialize the engaged remote partitions related amo variables */
- (void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO_SN2);
- (void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO_SN2);
-
- return 0;
-}
-
-static int
-xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
-{
- return test_bit(partid, heartbeating_to_mask);
-}
-
-static void
-xpc_allow_hb_sn2(short partid)
-{
- DBUG_ON(xpc_vars_sn2 == NULL);
- set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
-}
-
-static void
-xpc_disallow_hb_sn2(short partid)
-{
- DBUG_ON(xpc_vars_sn2 == NULL);
- clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
-}
-
-static void
-xpc_disallow_all_hbs_sn2(void)
-{
- DBUG_ON(xpc_vars_sn2 == NULL);
- bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions);
-}
-
-static void
-xpc_increment_heartbeat_sn2(void)
-{
- xpc_vars_sn2->heartbeat++;
-}
-
-static void
-xpc_offline_heartbeat_sn2(void)
-{
- xpc_increment_heartbeat_sn2();
- xpc_vars_sn2->heartbeat_offline = 1;
-}
-
-static void
-xpc_online_heartbeat_sn2(void)
-{
- xpc_increment_heartbeat_sn2();
- xpc_vars_sn2->heartbeat_offline = 0;
-}
-
-static void
-xpc_heartbeat_init_sn2(void)
-{
- DBUG_ON(xpc_vars_sn2 == NULL);
-
- bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
- xpc_online_heartbeat_sn2();
-}
-
-static void
-xpc_heartbeat_exit_sn2(void)
-{
- xpc_offline_heartbeat_sn2();
-}
-
-static enum xp_retval
-xpc_get_remote_heartbeat_sn2(struct xpc_partition *part)
-{
- struct xpc_vars_sn2 *remote_vars;
- enum xp_retval ret;
-
- remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
-
- /* pull the remote vars structure that contains the heartbeat */
- ret = xp_remote_memcpy(xp_pa(remote_vars),
- part->sn.sn2.remote_vars_pa,
- XPC_RP_VARS_SIZE);
- if (ret != xpSuccess)
- return ret;
-
- dev_dbg(xpc_part, "partid=%d, heartbeat=%lld, last_heartbeat=%lld, "
- "heartbeat_offline=%lld, HB_mask[0]=0x%lx\n", XPC_PARTID(part),
- remote_vars->heartbeat, part->last_heartbeat,
- remote_vars->heartbeat_offline,
- remote_vars->heartbeating_to_mask[0]);
-
- if ((remote_vars->heartbeat == part->last_heartbeat &&
- !remote_vars->heartbeat_offline) ||
- !xpc_hb_allowed_sn2(sn_partition_id,
- remote_vars->heartbeating_to_mask)) {
- ret = xpNoHeartbeat;
- } else {
- part->last_heartbeat = remote_vars->heartbeat;
- }
-
- return ret;
-}
-
-/*
- * Get a copy of the remote partition's XPC variables from the reserved page.
- *
- * remote_vars points to a buffer that is cacheline aligned for BTE copies and
- * assumed to be of size XPC_RP_VARS_SIZE.
- */
-static enum xp_retval
-xpc_get_remote_vars_sn2(unsigned long remote_vars_pa,
- struct xpc_vars_sn2 *remote_vars)
-{
- enum xp_retval ret;
-
- if (remote_vars_pa == 0)
- return xpVarsNotSet;
-
- /* pull over the cross partition variables */
- ret = xp_remote_memcpy(xp_pa(remote_vars), remote_vars_pa,
- XPC_RP_VARS_SIZE);
- if (ret != xpSuccess)
- return ret;
-
- if (XPC_VERSION_MAJOR(remote_vars->version) !=
- XPC_VERSION_MAJOR(XPC_V_VERSION)) {
- return xpBadVersion;
- }
-
- return xpSuccess;
-}
-
-static void
-xpc_request_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
- unsigned long remote_rp_pa, int nasid)
-{
- xpc_send_local_activate_IRQ_sn2(nasid);
-}
-
-static void
-xpc_request_partition_reactivation_sn2(struct xpc_partition *part)
-{
- xpc_send_local_activate_IRQ_sn2(part->sn.sn2.activate_IRQ_nasid);
-}
-
-static void
-xpc_request_partition_deactivation_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- unsigned long irq_flags;
- struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
- (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
- sizeof(struct amo)));
-
- local_irq_save(irq_flags);
-
- /* set bit corresponding to our partid in remote partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
- BIT(sn_partition_id));
-
- /*
- * We must always use the nofault function regardless of whether we
- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
- * didn't, we'd never know that the other partition is down and would
- * keep sending IRQs and amos to it until the heartbeat times out.
- */
- (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
- variable),
- xp_nofault_PIOR_target));
-
- local_irq_restore(irq_flags);
-
- /*
- * Send activate IRQ to get other side to see that we've set our
- * bit in their deactivate request amo.
- */
- xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
- cnodeid_to_nasid(0),
- part_sn2->activate_IRQ_nasid,
- part_sn2->activate_IRQ_phys_cpuid);
-}
-
-static void
-xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part)
-{
- unsigned long irq_flags;
- struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
- (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
- sizeof(struct amo)));
-
- local_irq_save(irq_flags);
-
- /* clear bit corresponding to our partid in remote partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
- ~BIT(sn_partition_id));
-
- /*
- * We must always use the nofault function regardless of whether we
- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
- * didn't, we'd never know that the other partition is down and would
- * keep sending IRQs and amos to it until the heartbeat times out.
- */
- (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
- variable),
- xp_nofault_PIOR_target));
-
- local_irq_restore(irq_flags);
-}
-
-static int
-xpc_partition_deactivation_requested_sn2(short partid)
-{
- struct amo *amo = xpc_vars_sn2->amos_page +
- XPC_DEACTIVATE_REQUEST_AMO_SN2;
-
- /* our partition's amo variable ANDed with partid mask */
- return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
- BIT(partid)) != 0;
-}
-
-/*
- * Update the remote partition's info.
- */
-static void
-xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
- unsigned long *remote_rp_ts_jiffies,
- unsigned long remote_rp_pa,
- unsigned long remote_vars_pa,
- struct xpc_vars_sn2 *remote_vars)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
-
- part->remote_rp_version = remote_rp_version;
- dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n",
- part->remote_rp_version);
-
- part->remote_rp_ts_jiffies = *remote_rp_ts_jiffies;
- dev_dbg(xpc_part, " remote_rp_ts_jiffies = 0x%016lx\n",
- part->remote_rp_ts_jiffies);
-
- part->remote_rp_pa = remote_rp_pa;
- dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
-
- part_sn2->remote_vars_pa = remote_vars_pa;
- dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
- part_sn2->remote_vars_pa);
-
- part->last_heartbeat = remote_vars->heartbeat - 1;
- dev_dbg(xpc_part, " last_heartbeat = 0x%016llx\n",
- part->last_heartbeat);
-
- part_sn2->remote_vars_part_pa = remote_vars->vars_part_pa;
- dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",
- part_sn2->remote_vars_part_pa);
-
- part_sn2->activate_IRQ_nasid = remote_vars->activate_IRQ_nasid;
- dev_dbg(xpc_part, " activate_IRQ_nasid = 0x%x\n",
- part_sn2->activate_IRQ_nasid);
-
- part_sn2->activate_IRQ_phys_cpuid =
- remote_vars->activate_IRQ_phys_cpuid;
- dev_dbg(xpc_part, " activate_IRQ_phys_cpuid = 0x%x\n",
- part_sn2->activate_IRQ_phys_cpuid);
-
- part_sn2->remote_amos_page_pa = remote_vars->amos_page_pa;
- dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",
- part_sn2->remote_amos_page_pa);
-
- part_sn2->remote_vars_version = remote_vars->version;
- dev_dbg(xpc_part, " remote_vars_version = 0x%x\n",
- part_sn2->remote_vars_version);
-}
-
-/*
- * Prior code has determined the nasid which generated a activate IRQ.
- * Inspect that nasid to determine if its partition needs to be activated
- * or deactivated.
- *
- * A partition is considered "awaiting activation" if our partition
- * flags indicate it is not active and it has a heartbeat. A
- * partition is considered "awaiting deactivation" if our partition
- * flags indicate it is active but it has no heartbeat or it is not
- * sending its heartbeat to us.
- *
- * To determine the heartbeat, the remote nasid must have a properly
- * initialized reserved page.
- */
-static void
-xpc_identify_activate_IRQ_req_sn2(int nasid)
-{
- struct xpc_rsvd_page *remote_rp;
- struct xpc_vars_sn2 *remote_vars;
- unsigned long remote_rp_pa;
- unsigned long remote_vars_pa;
- int remote_rp_version;
- int reactivate = 0;
- unsigned long remote_rp_ts_jiffies = 0;
- short partid;
- struct xpc_partition *part;
- struct xpc_partition_sn2 *part_sn2;
- enum xp_retval ret;
-
- /* pull over the reserved page structure */
-
- remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer_sn2;
-
- ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
- if (ret != xpSuccess) {
- dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
- "which sent interrupt, reason=%d\n", nasid, ret);
- return;
- }
-
- remote_vars_pa = remote_rp->sn.sn2.vars_pa;
- remote_rp_version = remote_rp->version;
- remote_rp_ts_jiffies = remote_rp->ts_jiffies;
-
- partid = remote_rp->SAL_partid;
- part = &xpc_partitions[partid];
- part_sn2 = &part->sn.sn2;
-
- /* pull over the cross partition variables */
-
- remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
-
- ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
- if (ret != xpSuccess) {
- dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
- "which sent interrupt, reason=%d\n", nasid, ret);
-
- XPC_DEACTIVATE_PARTITION(part, ret);
- return;
- }
-
- part->activate_IRQ_rcvd++;
-
- dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
- "%lld:0x%lx\n", (int)nasid, (int)partid,
- part->activate_IRQ_rcvd,
- remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
-
- if (xpc_partition_disengaged(part) &&
- part->act_state == XPC_P_AS_INACTIVE) {
-
- xpc_update_partition_info_sn2(part, remote_rp_version,
- &remote_rp_ts_jiffies,
- remote_rp_pa, remote_vars_pa,
- remote_vars);
-
- if (xpc_partition_deactivation_requested_sn2(partid)) {
- /*
- * Other side is waiting on us to deactivate even though
- * we already have.
- */
- return;
- }
-
- xpc_activate_partition(part);
- return;
- }
-
- DBUG_ON(part->remote_rp_version == 0);
- DBUG_ON(part_sn2->remote_vars_version == 0);
-
- if (remote_rp_ts_jiffies != part->remote_rp_ts_jiffies) {
-
- /* the other side rebooted */
-
- DBUG_ON(xpc_partition_engaged_sn2(partid));
- DBUG_ON(xpc_partition_deactivation_requested_sn2(partid));
-
- xpc_update_partition_info_sn2(part, remote_rp_version,
- &remote_rp_ts_jiffies,
- remote_rp_pa, remote_vars_pa,
- remote_vars);
- reactivate = 1;
- }
-
- if (part->disengage_timeout > 0 && !xpc_partition_disengaged(part)) {
- /* still waiting on other side to disengage from us */
- return;
- }
-
- if (reactivate)
- XPC_DEACTIVATE_PARTITION(part, xpReactivating);
- else if (xpc_partition_deactivation_requested_sn2(partid))
- XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
-}
-
-/*
- * Loop through the activation amo variables and process any bits
- * which are set. Each bit indicates a nasid sending a partition
- * activation or deactivation request.
- *
- * Return #of IRQs detected.
- */
-int
-xpc_identify_activate_IRQ_sender_sn2(void)
-{
- int l;
- int b;
- unsigned long nasid_mask_long;
- u64 nasid; /* remote nasid */
- int n_IRQs_detected = 0;
- struct amo *act_amos;
-
- act_amos = xpc_vars_sn2->amos_page + XPC_ACTIVATE_IRQ_AMOS_SN2;
-
- /* scan through activate amo variables looking for non-zero entries */
- for (l = 0; l < xpc_nasid_mask_nlongs; l++) {
-
- if (xpc_exiting)
- break;
-
- nasid_mask_long = xpc_receive_IRQ_amo_sn2(&act_amos[l]);
-
- b = find_first_bit(&nasid_mask_long, BITS_PER_LONG);
- if (b >= BITS_PER_LONG) {
- /* no IRQs from nasids in this amo variable */
- continue;
- }
-
- dev_dbg(xpc_part, "amo[%d] gave back 0x%lx\n", l,
- nasid_mask_long);
-
- /*
- * If this nasid has been added to the machine since
- * our partition was reset, this will retain the
- * remote nasid in our reserved pages machine mask.
- * This is used in the event of module reload.
- */
- xpc_mach_nasids[l] |= nasid_mask_long;
-
- /* locate the nasid(s) which sent interrupts */
-
- do {
- n_IRQs_detected++;
- nasid = (l * BITS_PER_LONG + b) * 2;
- dev_dbg(xpc_part, "interrupt from nasid %lld\n", nasid);
- xpc_identify_activate_IRQ_req_sn2(nasid);
-
- b = find_next_bit(&nasid_mask_long, BITS_PER_LONG,
- b + 1);
- } while (b < BITS_PER_LONG);
- }
- return n_IRQs_detected;
-}
-
-static void
-xpc_process_activate_IRQ_rcvd_sn2(void)
-{
- unsigned long irq_flags;
- int n_IRQs_expected;
- int n_IRQs_detected;
-
- spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
- n_IRQs_expected = xpc_activate_IRQ_rcvd;
- xpc_activate_IRQ_rcvd = 0;
- spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
- n_IRQs_detected = xpc_identify_activate_IRQ_sender_sn2();
- if (n_IRQs_detected < n_IRQs_expected) {
- /* retry once to help avoid missing amo */
- (void)xpc_identify_activate_IRQ_sender_sn2();
- }
-}
-
-/*
- * Setup the channel structures that are sn2 specific.
- */
-static enum xp_retval
-xpc_setup_ch_structures_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- struct xpc_channel_sn2 *ch_sn2;
- enum xp_retval retval;
- int ret;
- int cpuid;
- int ch_number;
- struct timer_list *timer;
- short partid = XPC_PARTID(part);
-
- /* allocate all the required GET/PUT values */
-
- part_sn2->local_GPs =
- xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
- &part_sn2->local_GPs_base);
- if (part_sn2->local_GPs == NULL) {
- dev_err(xpc_chan, "can't get memory for local get/put "
- "values\n");
- return xpNoMemory;
- }
-
- part_sn2->remote_GPs =
- xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
- &part_sn2->remote_GPs_base);
- if (part_sn2->remote_GPs == NULL) {
- dev_err(xpc_chan, "can't get memory for remote get/put "
- "values\n");
- retval = xpNoMemory;
- goto out_1;
- }
-
- part_sn2->remote_GPs_pa = 0;
-
- /* allocate all the required open and close args */
-
- part_sn2->local_openclose_args =
- xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
- GFP_KERNEL, &part_sn2->
- local_openclose_args_base);
- if (part_sn2->local_openclose_args == NULL) {
- dev_err(xpc_chan, "can't get memory for local connect args\n");
- retval = xpNoMemory;
- goto out_2;
- }
-
- part_sn2->remote_openclose_args_pa = 0;
-
- part_sn2->local_chctl_amo_va = xpc_init_IRQ_amo_sn2(partid);
-
- part_sn2->notify_IRQ_nasid = 0;
- part_sn2->notify_IRQ_phys_cpuid = 0;
- part_sn2->remote_chctl_amo_va = NULL;
-
- sprintf(part_sn2->notify_IRQ_owner, "xpc%02d", partid);
- ret = request_irq(SGI_XPC_NOTIFY, xpc_handle_notify_IRQ_sn2,
- IRQF_SHARED, part_sn2->notify_IRQ_owner,
- (void *)(u64)partid);
- if (ret != 0) {
- dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
- "errno=%d\n", -ret);
- retval = xpLackOfResources;
- goto out_3;
- }
-
- /* Setup a timer to check for dropped notify IRQs */
- timer = &part_sn2->dropped_notify_IRQ_timer;
- timer_setup(timer, xpc_check_for_dropped_notify_IRQ_sn2, 0);
- timer->expires = jiffies + XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
- add_timer(timer);
-
- for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
- ch_sn2 = &part->channels[ch_number].sn.sn2;
-
- ch_sn2->local_GP = &part_sn2->local_GPs[ch_number];
- ch_sn2->local_openclose_args =
- &part_sn2->local_openclose_args[ch_number];
-
- mutex_init(&ch_sn2->msg_to_pull_mutex);
- }
-
- /*
- * Setup the per partition specific variables required by the
- * remote partition to establish channel connections with us.
- *
- * The setting of the magic # indicates that these per partition
- * specific variables are ready to be used.
- */
- xpc_vars_part_sn2[partid].GPs_pa = xp_pa(part_sn2->local_GPs);
- xpc_vars_part_sn2[partid].openclose_args_pa =
- xp_pa(part_sn2->local_openclose_args);
- xpc_vars_part_sn2[partid].chctl_amo_pa =
- xp_pa(part_sn2->local_chctl_amo_va);
- cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
- xpc_vars_part_sn2[partid].notify_IRQ_nasid = cpuid_to_nasid(cpuid);
- xpc_vars_part_sn2[partid].notify_IRQ_phys_cpuid =
- cpu_physical_id(cpuid);
- xpc_vars_part_sn2[partid].nchannels = part->nchannels;
- xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC1_SN2;
-
- return xpSuccess;
-
- /* setup of ch structures failed */
-out_3:
- kfree(part_sn2->local_openclose_args_base);
- part_sn2->local_openclose_args = NULL;
-out_2:
- kfree(part_sn2->remote_GPs_base);
- part_sn2->remote_GPs = NULL;
-out_1:
- kfree(part_sn2->local_GPs_base);
- part_sn2->local_GPs = NULL;
- return retval;
-}
-
-/*
- * Teardown the channel structures that are sn2 specific.
- */
-static void
-xpc_teardown_ch_structures_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- short partid = XPC_PARTID(part);
-
- /*
- * Indicate that the variables specific to the remote partition are no
- * longer available for its use.
- */
- xpc_vars_part_sn2[partid].magic = 0;
-
- /* in case we've still got outstanding timers registered... */
- del_timer_sync(&part_sn2->dropped_notify_IRQ_timer);
- free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
-
- kfree(part_sn2->local_openclose_args_base);
- part_sn2->local_openclose_args = NULL;
- kfree(part_sn2->remote_GPs_base);
- part_sn2->remote_GPs = NULL;
- kfree(part_sn2->local_GPs_base);
- part_sn2->local_GPs = NULL;
- part_sn2->local_chctl_amo_va = NULL;
-}
-
-/*
- * Create a wrapper that hides the underlying mechanism for pulling a cacheline
- * (or multiple cachelines) from a remote partition.
- *
- * src_pa must be a cacheline aligned physical address on the remote partition.
- * dst must be a cacheline aligned virtual address on this partition.
- * cnt must be cacheline sized
- */
-/* ??? Replace this function by call to xp_remote_memcpy() or bte_copy()? */
-static enum xp_retval
-xpc_pull_remote_cachelines_sn2(struct xpc_partition *part, void *dst,
- const unsigned long src_pa, size_t cnt)
-{
- enum xp_retval ret;
-
- DBUG_ON(src_pa != L1_CACHE_ALIGN(src_pa));
- DBUG_ON((unsigned long)dst != L1_CACHE_ALIGN((unsigned long)dst));
- DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
-
- if (part->act_state == XPC_P_AS_DEACTIVATING)
- return part->reason;
-
- ret = xp_remote_memcpy(xp_pa(dst), src_pa, cnt);
- if (ret != xpSuccess) {
- dev_dbg(xpc_chan, "xp_remote_memcpy() from partition %d failed,"
- " ret=%d\n", XPC_PARTID(part), ret);
- }
- return ret;
-}
-
-/*
- * Pull the remote per partition specific variables from the specified
- * partition.
- */
-static enum xp_retval
-xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- u8 buffer[L1_CACHE_BYTES * 2];
- struct xpc_vars_part_sn2 *pulled_entry_cacheline =
- (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer);
- struct xpc_vars_part_sn2 *pulled_entry;
- unsigned long remote_entry_cacheline_pa;
- unsigned long remote_entry_pa;
- short partid = XPC_PARTID(part);
- enum xp_retval ret;
-
- /* pull the cacheline that contains the variables we're interested in */
-
- DBUG_ON(part_sn2->remote_vars_part_pa !=
- L1_CACHE_ALIGN(part_sn2->remote_vars_part_pa));
- DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2);
-
- remote_entry_pa = part_sn2->remote_vars_part_pa +
- sn_partition_id * sizeof(struct xpc_vars_part_sn2);
-
- remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
-
- pulled_entry = (struct xpc_vars_part_sn2 *)((u64)pulled_entry_cacheline
- + (remote_entry_pa &
- (L1_CACHE_BYTES - 1)));
-
- ret = xpc_pull_remote_cachelines_sn2(part, pulled_entry_cacheline,
- remote_entry_cacheline_pa,
- L1_CACHE_BYTES);
- if (ret != xpSuccess) {
- dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
- "partition %d, ret=%d\n", partid, ret);
- return ret;
- }
-
- /* see if they've been set up yet */
-
- if (pulled_entry->magic != XPC_VP_MAGIC1_SN2 &&
- pulled_entry->magic != XPC_VP_MAGIC2_SN2) {
-
- if (pulled_entry->magic != 0) {
- dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
- "partition %d has bad magic value (=0x%llx)\n",
- partid, sn_partition_id, pulled_entry->magic);
- return xpBadMagic;
- }
-
- /* they've not been initialized yet */
- return xpRetry;
- }
-
- if (xpc_vars_part_sn2[partid].magic == XPC_VP_MAGIC1_SN2) {
-
- /* validate the variables */
-
- if (pulled_entry->GPs_pa == 0 ||
- pulled_entry->openclose_args_pa == 0 ||
- pulled_entry->chctl_amo_pa == 0) {
-
- dev_err(xpc_chan, "partition %d's XPC vars_part for "
- "partition %d are not valid\n", partid,
- sn_partition_id);
- return xpInvalidAddress;
- }
-
- /* the variables we imported look to be valid */
-
- part_sn2->remote_GPs_pa = pulled_entry->GPs_pa;
- part_sn2->remote_openclose_args_pa =
- pulled_entry->openclose_args_pa;
- part_sn2->remote_chctl_amo_va =
- (struct amo *)__va(pulled_entry->chctl_amo_pa);
- part_sn2->notify_IRQ_nasid = pulled_entry->notify_IRQ_nasid;
- part_sn2->notify_IRQ_phys_cpuid =
- pulled_entry->notify_IRQ_phys_cpuid;
-
- if (part->nchannels > pulled_entry->nchannels)
- part->nchannels = pulled_entry->nchannels;
-
- /* let the other side know that we've pulled their variables */
-
- xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC2_SN2;
- }
-
- if (pulled_entry->magic == XPC_VP_MAGIC1_SN2)
- return xpRetry;
-
- return xpSuccess;
-}
-
-/*
- * Establish first contact with the remote partititon. This involves pulling
- * the XPC per partition variables from the remote partition and waiting for
- * the remote partition to pull ours.
- */
-static enum xp_retval
-xpc_make_first_contact_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- enum xp_retval ret;
-
- /*
- * Register the remote partition's amos with SAL so it can handle
- * and cleanup errors within that address range should the remote
- * partition go down. We don't unregister this range because it is
- * difficult to tell when outstanding writes to the remote partition
- * are finished and thus when it is safe to unregister. This should
- * not result in wasted space in the SAL xp_addr_region table because
- * we should get the same page for remote_amos_page_pa after module
- * reloads and system reboots.
- */
- if (sn_register_xp_addr_region(part_sn2->remote_amos_page_pa,
- PAGE_SIZE, 1) < 0) {
- dev_warn(xpc_part, "xpc_activating(%d) failed to register "
- "xp_addr region\n", XPC_PARTID(part));
-
- ret = xpPhysAddrRegFailed;
- XPC_DEACTIVATE_PARTITION(part, ret);
- return ret;
- }
-
- /*
- * Send activate IRQ to get other side to activate if they've not
- * already begun to do so.
- */
- xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
- cnodeid_to_nasid(0),
- part_sn2->activate_IRQ_nasid,
- part_sn2->activate_IRQ_phys_cpuid);
-
- while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
- if (ret != xpRetry) {
- XPC_DEACTIVATE_PARTITION(part, ret);
- return ret;
- }
-
- dev_dbg(xpc_part, "waiting to make first contact with "
- "partition %d\n", XPC_PARTID(part));
-
- /* wait a 1/4 of a second or so */
- (void)msleep_interruptible(250);
-
- if (part->act_state == XPC_P_AS_DEACTIVATING)
- return part->reason;
- }
-
- return xpSuccess;
-}
-
-/*
- * Get the chctl flags and pull the openclose args and/or remote GPs as needed.
- */
-static u64
-xpc_get_chctl_all_flags_sn2(struct xpc_partition *part)
-{
- struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
- unsigned long irq_flags;
- union xpc_channel_ctl_flags chctl;
- enum xp_retval ret;
-
- /*
- * See if there are any chctl flags to be handled.
- */
-
- spin_lock_irqsave(&part->chctl_lock, irq_flags);
- chctl = part->chctl;
- if (chctl.all_flags != 0)
- part->chctl.all_flags = 0;
-
- spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
- if (xpc_any_openclose_chctl_flags_set(&chctl)) {
- ret = xpc_pull_remote_cachelines_sn2(part, part->
- remote_openclose_args,
- part_sn2->
- remote_openclose_args_pa,
- XPC_OPENCLOSE_ARGS_SIZE);
- if (ret != xpSuccess) {
- XPC_DEACTIVATE_PARTITION(part, ret);
-
- dev_dbg(xpc_chan, "failed to pull openclose args from "
- "partition %d, ret=%d\n", XPC_PARTID(part),
- ret);
-
- /* don't bother processing chctl flags anymore */
- chctl.all_flags = 0;
- }
- }
-
- if (xpc_any_msg_chctl_flags_set(&chctl)) {
- ret = xpc_pull_remote_cachelines_sn2(part, part_sn2->remote_GPs,
- part_sn2->remote_GPs_pa,
- XPC_GP_SIZE);
- if (ret != xpSuccess) {
- XPC_DEACTIVATE_PARTITION(part, ret);
-
- dev_dbg(xpc_chan, "failed to pull GPs from partition "
- "%d, ret=%d\n", XPC_PARTID(part), ret);
-
- /* don't bother processing chctl flags anymore */
- chctl.all_flags = 0;
- }
- }
-
- return chctl.all_flags;
-}
-
-/*
- * Allocate the local message queue and the notify queue.
- */
-static enum xp_retval
-xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- unsigned long irq_flags;
- int nentries;
- size_t nbytes;
-
- for (nentries = ch->local_nentries; nentries > 0; nentries--) {
-
- nbytes = nentries * ch->entry_size;
- ch_sn2->local_msgqueue =
- xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL,
- &ch_sn2->local_msgqueue_base);
- if (ch_sn2->local_msgqueue == NULL)
- continue;
-
- nbytes = nentries * sizeof(struct xpc_notify_sn2);
- ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL);
- if (ch_sn2->notify_queue == NULL) {
- kfree(ch_sn2->local_msgqueue_base);
- ch_sn2->local_msgqueue = NULL;
- continue;
- }
-
- spin_lock_irqsave(&ch->lock, irq_flags);
- if (nentries < ch->local_nentries) {
- dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
- "partid=%d, channel=%d\n", nentries,
- ch->local_nentries, ch->partid, ch->number);
-
- ch->local_nentries = nentries;
- }
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return xpSuccess;
- }
-
- dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
- "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
- return xpNoMemory;
-}
-
-/*
- * Allocate the cached remote message queue.
- */
-static enum xp_retval
-xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- unsigned long irq_flags;
- int nentries;
- size_t nbytes;
-
- DBUG_ON(ch->remote_nentries <= 0);
-
- for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
-
- nbytes = nentries * ch->entry_size;
- ch_sn2->remote_msgqueue =
- xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2->
- remote_msgqueue_base);
- if (ch_sn2->remote_msgqueue == NULL)
- continue;
-
- spin_lock_irqsave(&ch->lock, irq_flags);
- if (nentries < ch->remote_nentries) {
- dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
- "partid=%d, channel=%d\n", nentries,
- ch->remote_nentries, ch->partid, ch->number);
-
- ch->remote_nentries = nentries;
- }
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return xpSuccess;
- }
-
- dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
- "partid=%d, channel=%d\n", ch->partid, ch->number);
- return xpNoMemory;
-}
-
-/*
- * Allocate message queues and other stuff associated with a channel.
- *
- * Note: Assumes all of the channel sizes are filled in.
- */
-static enum xp_retval
-xpc_setup_msg_structures_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- enum xp_retval ret;
-
- DBUG_ON(ch->flags & XPC_C_SETUP);
-
- ret = xpc_allocate_local_msgqueue_sn2(ch);
- if (ret == xpSuccess) {
-
- ret = xpc_allocate_remote_msgqueue_sn2(ch);
- if (ret != xpSuccess) {
- kfree(ch_sn2->local_msgqueue_base);
- ch_sn2->local_msgqueue = NULL;
- kfree(ch_sn2->notify_queue);
- ch_sn2->notify_queue = NULL;
- }
- }
- return ret;
-}
-
-/*
- * Free up message queues and other stuff that were allocated for the specified
- * channel.
- */
-static void
-xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
-
- lockdep_assert_held(&ch->lock);
-
- ch_sn2->remote_msgqueue_pa = 0;
-
- ch_sn2->local_GP->get = 0;
- ch_sn2->local_GP->put = 0;
- ch_sn2->remote_GP.get = 0;
- ch_sn2->remote_GP.put = 0;
- ch_sn2->w_local_GP.get = 0;
- ch_sn2->w_local_GP.put = 0;
- ch_sn2->w_remote_GP.get = 0;
- ch_sn2->w_remote_GP.put = 0;
- ch_sn2->next_msg_to_pull = 0;
-
- if (ch->flags & XPC_C_SETUP) {
- dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
- ch->flags, ch->partid, ch->number);
-
- kfree(ch_sn2->local_msgqueue_base);
- ch_sn2->local_msgqueue = NULL;
- kfree(ch_sn2->remote_msgqueue_base);
- ch_sn2->remote_msgqueue = NULL;
- kfree(ch_sn2->notify_queue);
- ch_sn2->notify_queue = NULL;
- }
-}
-
-/*
- * Notify those who wanted to be notified upon delivery of their message.
- */
-static void
-xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
-{
- struct xpc_notify_sn2 *notify;
- u8 notify_type;
- s64 get = ch->sn.sn2.w_remote_GP.get - 1;
-
- while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
-
- notify = &ch->sn.sn2.notify_queue[get % ch->local_nentries];
-
- /*
- * See if the notify entry indicates it was associated with
- * a message who's sender wants to be notified. It is possible
- * that it is, but someone else is doing or has done the
- * notification.
- */
- notify_type = notify->type;
- if (notify_type == 0 ||
- cmpxchg(&notify->type, notify_type, 0) != notify_type) {
- continue;
- }
-
- DBUG_ON(notify_type != XPC_N_CALL);
-
- atomic_dec(&ch->n_to_notify);
-
- if (notify->func != NULL) {
- dev_dbg(xpc_chan, "notify->func() called, notify=0x%p "
- "msg_number=%lld partid=%d channel=%d\n",
- (void *)notify, get, ch->partid, ch->number);
-
- notify->func(reason, ch->partid, ch->number,
- notify->key);
-
- dev_dbg(xpc_chan, "notify->func() returned, notify=0x%p"
- " msg_number=%lld partid=%d channel=%d\n",
- (void *)notify, get, ch->partid, ch->number);
- }
- }
-}
-
-static void
-xpc_notify_senders_of_disconnect_sn2(struct xpc_channel *ch)
-{
- xpc_notify_senders_sn2(ch, ch->reason, ch->sn.sn2.w_local_GP.put);
-}
-
-/*
- * Clear some of the msg flags in the local message queue.
- */
-static inline void
-xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- s64 get;
-
- get = ch_sn2->w_remote_GP.get;
- do {
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
- (get % ch->local_nentries) *
- ch->entry_size);
- DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
- msg->flags = 0;
- } while (++get < ch_sn2->remote_GP.get);
-}
-
-/*
- * Clear some of the msg flags in the remote message queue.
- */
-static inline void
-xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- s64 put, remote_nentries = ch->remote_nentries;
-
- /* flags are zeroed when the buffer is allocated */
- if (ch_sn2->remote_GP.put < remote_nentries)
- return;
-
- put = max(ch_sn2->w_remote_GP.put, remote_nentries);
- do {
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
- (put % remote_nentries) *
- ch->entry_size);
- DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
- DBUG_ON(!(msg->flags & XPC_M_SN2_DONE));
- DBUG_ON(msg->number != put - remote_nentries);
- msg->flags = 0;
- } while (++put < ch_sn2->remote_GP.put);
-}
-
-static int
-xpc_n_of_deliverable_payloads_sn2(struct xpc_channel *ch)
-{
- return ch->sn.sn2.w_remote_GP.put - ch->sn.sn2.w_local_GP.get;
-}
-
-static void
-xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
-{
- struct xpc_channel *ch = &part->channels[ch_number];
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- int npayloads_sent;
-
- ch_sn2->remote_GP = part->sn.sn2.remote_GPs[ch_number];
-
- /* See what, if anything, has changed for each connected channel */
-
- xpc_msgqueue_ref(ch);
-
- if (ch_sn2->w_remote_GP.get == ch_sn2->remote_GP.get &&
- ch_sn2->w_remote_GP.put == ch_sn2->remote_GP.put) {
- /* nothing changed since GPs were last pulled */
- xpc_msgqueue_deref(ch);
- return;
- }
-
- if (!(ch->flags & XPC_C_CONNECTED)) {
- xpc_msgqueue_deref(ch);
- return;
- }
-
- /*
- * First check to see if messages recently sent by us have been
- * received by the other side. (The remote GET value will have
- * changed since we last looked at it.)
- */
-
- if (ch_sn2->w_remote_GP.get != ch_sn2->remote_GP.get) {
-
- /*
- * We need to notify any senders that want to be notified
- * that their sent messages have been received by their
- * intended recipients. We need to do this before updating
- * w_remote_GP.get so that we don't allocate the same message
- * queue entries prematurely (see xpc_allocate_msg()).
- */
- if (atomic_read(&ch->n_to_notify) > 0) {
- /*
- * Notify senders that messages sent have been
- * received and delivered by the other side.
- */
- xpc_notify_senders_sn2(ch, xpMsgDelivered,
- ch_sn2->remote_GP.get);
- }
-
- /*
- * Clear msg->flags in previously sent messages, so that
- * they're ready for xpc_allocate_msg().
- */
- xpc_clear_local_msgqueue_flags_sn2(ch);
-
- ch_sn2->w_remote_GP.get = ch_sn2->remote_GP.get;
-
- dev_dbg(xpc_chan, "w_remote_GP.get changed to %lld, partid=%d, "
- "channel=%d\n", ch_sn2->w_remote_GP.get, ch->partid,
- ch->number);
-
- /*
- * If anyone was waiting for message queue entries to become
- * available, wake them up.
- */
- if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
- wake_up(&ch->msg_allocate_wq);
- }
-
- /*
- * Now check for newly sent messages by the other side. (The remote
- * PUT value will have changed since we last looked at it.)
- */
-
- if (ch_sn2->w_remote_GP.put != ch_sn2->remote_GP.put) {
- /*
- * Clear msg->flags in previously received messages, so that
- * they're ready for xpc_get_deliverable_payload_sn2().
- */
- xpc_clear_remote_msgqueue_flags_sn2(ch);
-
- smp_wmb(); /* ensure flags have been cleared before bte_copy */
- ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put;
-
- dev_dbg(xpc_chan, "w_remote_GP.put changed to %lld, partid=%d, "
- "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid,
- ch->number);
-
- npayloads_sent = xpc_n_of_deliverable_payloads_sn2(ch);
- if (npayloads_sent > 0) {
- dev_dbg(xpc_chan, "msgs waiting to be copied and "
- "delivered=%d, partid=%d, channel=%d\n",
- npayloads_sent, ch->partid, ch->number);
-
- if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
- xpc_activate_kthreads(ch, npayloads_sent);
- }
- }
-
- xpc_msgqueue_deref(ch);
-}
-
-static struct xpc_msg_sn2 *
-xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
-{
- struct xpc_partition *part = &xpc_partitions[ch->partid];
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- unsigned long remote_msg_pa;
- struct xpc_msg_sn2 *msg;
- u32 msg_index;
- u32 nmsgs;
- u64 msg_offset;
- enum xp_retval ret;
-
- if (mutex_lock_interruptible(&ch_sn2->msg_to_pull_mutex) != 0) {
- /* we were interrupted by a signal */
- return NULL;
- }
-
- while (get >= ch_sn2->next_msg_to_pull) {
-
- /* pull as many messages as are ready and able to be pulled */
-
- msg_index = ch_sn2->next_msg_to_pull % ch->remote_nentries;
-
- DBUG_ON(ch_sn2->next_msg_to_pull >= ch_sn2->w_remote_GP.put);
- nmsgs = ch_sn2->w_remote_GP.put - ch_sn2->next_msg_to_pull;
- if (msg_index + nmsgs > ch->remote_nentries) {
- /* ignore the ones that wrap the msg queue for now */
- nmsgs = ch->remote_nentries - msg_index;
- }
-
- msg_offset = msg_index * ch->entry_size;
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
- msg_offset);
- remote_msg_pa = ch_sn2->remote_msgqueue_pa + msg_offset;
-
- ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa,
- nmsgs * ch->entry_size);
- if (ret != xpSuccess) {
-
- dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
- " msg %lld from partition %d, channel=%d, "
- "ret=%d\n", nmsgs, ch_sn2->next_msg_to_pull,
- ch->partid, ch->number, ret);
-
- XPC_DEACTIVATE_PARTITION(part, ret);
-
- mutex_unlock(&ch_sn2->msg_to_pull_mutex);
- return NULL;
- }
-
- ch_sn2->next_msg_to_pull += nmsgs;
- }
-
- mutex_unlock(&ch_sn2->msg_to_pull_mutex);
-
- /* return the message we were looking for */
- msg_offset = (get % ch->remote_nentries) * ch->entry_size;
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue + msg_offset);
-
- return msg;
-}
-
-/*
- * Get the next deliverable message's payload.
- */
-static void *
-xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- void *payload = NULL;
- s64 get;
-
- do {
- if (ch->flags & XPC_C_DISCONNECTING)
- break;
-
- get = ch_sn2->w_local_GP.get;
- smp_rmb(); /* guarantee that .get loads before .put */
- if (get == ch_sn2->w_remote_GP.put)
- break;
-
- /* There are messages waiting to be pulled and delivered.
- * We need to try to secure one for ourselves. We'll do this
- * by trying to increment w_local_GP.get and hope that no one
- * else beats us to it. If they do, we'll we'll simply have
- * to try again for the next one.
- */
-
- if (cmpxchg(&ch_sn2->w_local_GP.get, get, get + 1) == get) {
- /* we got the entry referenced by get */
-
- dev_dbg(xpc_chan, "w_local_GP.get changed to %lld, "
- "partid=%d, channel=%d\n", get + 1,
- ch->partid, ch->number);
-
- /* pull the message from the remote partition */
-
- msg = xpc_pull_remote_msg_sn2(ch, get);
-
- if (msg != NULL) {
- DBUG_ON(msg->number != get);
- DBUG_ON(msg->flags & XPC_M_SN2_DONE);
- DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
-
- payload = &msg->payload;
- }
- break;
- }
-
- } while (1);
-
- return payload;
-}
-
-/*
- * Now we actually send the messages that are ready to be sent by advancing
- * the local message queue's Put value and then send a chctl msgrequest to the
- * recipient partition.
- */
-static void
-xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- s64 put = initial_put + 1;
- int send_msgrequest = 0;
-
- while (1) {
-
- while (1) {
- if (put == ch_sn2->w_local_GP.put)
- break;
-
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
- local_msgqueue + (put %
- ch->local_nentries) *
- ch->entry_size);
-
- if (!(msg->flags & XPC_M_SN2_READY))
- break;
-
- put++;
- }
-
- if (put == initial_put) {
- /* nothing's changed */
- break;
- }
-
- if (cmpxchg_rel(&ch_sn2->local_GP->put, initial_put, put) !=
- initial_put) {
- /* someone else beat us to it */
- DBUG_ON(ch_sn2->local_GP->put < initial_put);
- break;
- }
-
- /* we just set the new value of local_GP->put */
-
- dev_dbg(xpc_chan, "local_GP->put changed to %lld, partid=%d, "
- "channel=%d\n", put, ch->partid, ch->number);
-
- send_msgrequest = 1;
-
- /*
- * We need to ensure that the message referenced by
- * local_GP->put is not XPC_M_SN2_READY or that local_GP->put
- * equals w_local_GP.put, so we'll go have a look.
- */
- initial_put = put;
- }
-
- if (send_msgrequest)
- xpc_send_chctl_msgrequest_sn2(ch);
-}
-
-/*
- * Allocate an entry for a message from the message queue associated with the
- * specified channel.
- */
-static enum xp_retval
-xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
- struct xpc_msg_sn2 **address_of_msg)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- enum xp_retval ret;
- s64 put;
-
- /*
- * Get the next available message entry from the local message queue.
- * If none are available, we'll make sure that we grab the latest
- * GP values.
- */
- ret = xpTimeout;
-
- while (1) {
-
- put = ch_sn2->w_local_GP.put;
- smp_rmb(); /* guarantee that .put loads before .get */
- if (put - ch_sn2->w_remote_GP.get < ch->local_nentries) {
-
- /* There are available message entries. We need to try
- * to secure one for ourselves. We'll do this by trying
- * to increment w_local_GP.put as long as someone else
- * doesn't beat us to it. If they do, we'll have to
- * try again.
- */
- if (cmpxchg(&ch_sn2->w_local_GP.put, put, put + 1) ==
- put) {
- /* we got the entry referenced by put */
- break;
- }
- continue; /* try again */
- }
-
- /*
- * There aren't any available msg entries at this time.
- *
- * In waiting for a message entry to become available,
- * we set a timeout in case the other side is not sending
- * completion interrupts. This lets us fake a notify IRQ
- * that will cause the notify IRQ handler to fetch the latest
- * GP values as if an interrupt was sent by the other side.
- */
- if (ret == xpTimeout)
- xpc_send_chctl_local_msgrequest_sn2(ch);
-
- if (flags & XPC_NOWAIT)
- return xpNoWait;
-
- ret = xpc_allocate_msg_wait(ch);
- if (ret != xpInterrupted && ret != xpTimeout)
- return ret;
- }
-
- /* get the message's address and initialize it */
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
- (put % ch->local_nentries) *
- ch->entry_size);
-
- DBUG_ON(msg->flags != 0);
- msg->number = put;
-
- dev_dbg(xpc_chan, "w_local_GP.put changed to %lld; msg=0x%p, "
- "msg_number=%lld, partid=%d, channel=%d\n", put + 1,
- (void *)msg, msg->number, ch->partid, ch->number);
-
- *address_of_msg = msg;
- return xpSuccess;
-}
-
-/*
- * Common code that does the actual sending of the message by advancing the
- * local message queue's Put value and sends a chctl msgrequest to the
- * partition the message is being sent to.
- */
-static enum xp_retval
-xpc_send_payload_sn2(struct xpc_channel *ch, u32 flags, void *payload,
- u16 payload_size, u8 notify_type, xpc_notify_func func,
- void *key)
-{
- enum xp_retval ret = xpSuccess;
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg = msg;
- struct xpc_notify_sn2 *notify = notify;
- s64 msg_number;
- s64 put;
-
- DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
-
- if (XPC_MSG_SIZE(payload_size) > ch->entry_size)
- return xpPayloadTooBig;
-
- xpc_msgqueue_ref(ch);
-
- if (ch->flags & XPC_C_DISCONNECTING) {
- ret = ch->reason;
- goto out_1;
- }
- if (!(ch->flags & XPC_C_CONNECTED)) {
- ret = xpNotConnected;
- goto out_1;
- }
-
- ret = xpc_allocate_msg_sn2(ch, flags, &msg);
- if (ret != xpSuccess)
- goto out_1;
-
- msg_number = msg->number;
-
- if (notify_type != 0) {
- /*
- * Tell the remote side to send an ACK interrupt when the
- * message has been delivered.
- */
- msg->flags |= XPC_M_SN2_INTERRUPT;
-
- atomic_inc(&ch->n_to_notify);
-
- notify = &ch_sn2->notify_queue[msg_number % ch->local_nentries];
- notify->func = func;
- notify->key = key;
- notify->type = notify_type;
-
- /* ??? Is a mb() needed here? */
-
- if (ch->flags & XPC_C_DISCONNECTING) {
- /*
- * An error occurred between our last error check and
- * this one. We will try to clear the type field from
- * the notify entry. If we succeed then
- * xpc_disconnect_channel() didn't already process
- * the notify entry.
- */
- if (cmpxchg(&notify->type, notify_type, 0) ==
- notify_type) {
- atomic_dec(&ch->n_to_notify);
- ret = ch->reason;
- }
- goto out_1;
- }
- }
-
- memcpy(&msg->payload, payload, payload_size);
-
- msg->flags |= XPC_M_SN2_READY;
-
- /*
- * The preceding store of msg->flags must occur before the following
- * load of local_GP->put.
- */
- smp_mb();
-
- /* see if the message is next in line to be sent, if so send it */
-
- put = ch_sn2->local_GP->put;
- if (put == msg_number)
- xpc_send_msgs_sn2(ch, put);
-
-out_1:
- xpc_msgqueue_deref(ch);
- return ret;
-}
-
-/*
- * Now we actually acknowledge the messages that have been delivered and ack'd
- * by advancing the cached remote message queue's Get value and if requested
- * send a chctl msgrequest to the message sender's partition.
- *
- * If a message has XPC_M_SN2_INTERRUPT set, send an interrupt to the partition
- * that sent the message.
- */
-static void
-xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
-{
- struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
- struct xpc_msg_sn2 *msg;
- s64 get = initial_get + 1;
- int send_msgrequest = 0;
-
- while (1) {
-
- while (1) {
- if (get == ch_sn2->w_local_GP.get)
- break;
-
- msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
- remote_msgqueue + (get %
- ch->remote_nentries) *
- ch->entry_size);
-
- if (!(msg->flags & XPC_M_SN2_DONE))
- break;
-
- msg_flags |= msg->flags;
- get++;
- }
-
- if (get == initial_get) {
- /* nothing's changed */
- break;
- }
-
- if (cmpxchg_rel(&ch_sn2->local_GP->get, initial_get, get) !=
- initial_get) {
- /* someone else beat us to it */
- DBUG_ON(ch_sn2->local_GP->get <= initial_get);
- break;
- }
-
- /* we just set the new value of local_GP->get */
-
- dev_dbg(xpc_chan, "local_GP->get changed to %lld, partid=%d, "
- "channel=%d\n", get, ch->partid, ch->number);
-
- send_msgrequest = (msg_flags & XPC_M_SN2_INTERRUPT);
-
- /*
- * We need to ensure that the message referenced by
- * local_GP->get is not XPC_M_SN2_DONE or that local_GP->get
- * equals w_local_GP.get, so we'll go have a look.
- */
- initial_get = get;
- }
-
- if (send_msgrequest)
- xpc_send_chctl_msgrequest_sn2(ch);
-}
-
-static void
-xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
-{
- struct xpc_msg_sn2 *msg;
- s64 msg_number;
- s64 get;
-
- msg = container_of(payload, struct xpc_msg_sn2, payload);
- msg_number = msg->number;
-
- dev_dbg(xpc_chan, "msg=0x%p, msg_number=%lld, partid=%d, channel=%d\n",
- (void *)msg, msg_number, ch->partid, ch->number);
-
- DBUG_ON((((u64)msg - (u64)ch->sn.sn2.remote_msgqueue) / ch->entry_size) !=
- msg_number % ch->remote_nentries);
- DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
- DBUG_ON(msg->flags & XPC_M_SN2_DONE);
-
- msg->flags |= XPC_M_SN2_DONE;
-
- /*
- * The preceding store of msg->flags must occur before the following
- * load of local_GP->get.
- */
- smp_mb();
-
- /*
- * See if this message is next in line to be acknowledged as having
- * been delivered.
- */
- get = ch->sn.sn2.local_GP->get;
- if (get == msg_number)
- xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
-}
-
-static struct xpc_arch_operations xpc_arch_ops_sn2 = {
- .setup_partitions = xpc_setup_partitions_sn2,
- .teardown_partitions = xpc_teardown_partitions_sn2,
- .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2,
- .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2,
- .setup_rsvd_page = xpc_setup_rsvd_page_sn2,
-
- .allow_hb = xpc_allow_hb_sn2,
- .disallow_hb = xpc_disallow_hb_sn2,
- .disallow_all_hbs = xpc_disallow_all_hbs_sn2,
- .increment_heartbeat = xpc_increment_heartbeat_sn2,
- .offline_heartbeat = xpc_offline_heartbeat_sn2,
- .online_heartbeat = xpc_online_heartbeat_sn2,
- .heartbeat_init = xpc_heartbeat_init_sn2,
- .heartbeat_exit = xpc_heartbeat_exit_sn2,
- .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2,
-
- .request_partition_activation =
- xpc_request_partition_activation_sn2,
- .request_partition_reactivation =
- xpc_request_partition_reactivation_sn2,
- .request_partition_deactivation =
- xpc_request_partition_deactivation_sn2,
- .cancel_partition_deactivation_request =
- xpc_cancel_partition_deactivation_request_sn2,
-
- .setup_ch_structures = xpc_setup_ch_structures_sn2,
- .teardown_ch_structures = xpc_teardown_ch_structures_sn2,
-
- .make_first_contact = xpc_make_first_contact_sn2,
-
- .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2,
- .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2,
- .send_chctl_closereply = xpc_send_chctl_closereply_sn2,
- .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2,
- .send_chctl_openreply = xpc_send_chctl_openreply_sn2,
- .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2,
- .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2,
-
- .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2,
-
- .setup_msg_structures = xpc_setup_msg_structures_sn2,
- .teardown_msg_structures = xpc_teardown_msg_structures_sn2,
-
- .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2,
- .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2,
- .partition_engaged = xpc_partition_engaged_sn2,
- .any_partition_engaged = xpc_any_partition_engaged_sn2,
- .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2,
-
- .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2,
- .send_payload = xpc_send_payload_sn2,
- .get_deliverable_payload = xpc_get_deliverable_payload_sn2,
- .received_payload = xpc_received_payload_sn2,
- .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2,
-};
-
-int
-xpc_init_sn2(void)
-{
- int ret;
- size_t buf_size;
-
- xpc_arch_ops = xpc_arch_ops_sn2;
-
- if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) {
- dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is "
- "larger than %d\n", XPC_MSG_HDR_MAX_SIZE);
- return -E2BIG;
- }
-
- buf_size = max(XPC_RP_VARS_SIZE,
- XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES_SN2);
- xpc_remote_copy_buffer_sn2 = xpc_kmalloc_cacheline_aligned(buf_size,
- GFP_KERNEL,
- &xpc_remote_copy_buffer_base_sn2);
- if (xpc_remote_copy_buffer_sn2 == NULL) {
- dev_err(xpc_part, "can't get memory for remote copy buffer\n");
- return -ENOMEM;
- }
-
- /* open up protections for IPI and [potentially] amo operations */
- xpc_allow_IPI_ops_sn2();
- xpc_allow_amo_ops_shub_wars_1_1_sn2();
-
- /*
- * This is safe to do before the xpc_hb_checker thread has started
- * because the handler releases a wait queue. If an interrupt is
- * received before the thread is waiting, it will not go to sleep,
- * but rather immediately process the interrupt.
- */
- ret = request_irq(SGI_XPC_ACTIVATE, xpc_handle_activate_IRQ_sn2, 0,
- "xpc hb", NULL);
- if (ret != 0) {
- dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
- "errno=%d\n", -ret);
- xpc_disallow_IPI_ops_sn2();
- kfree(xpc_remote_copy_buffer_base_sn2);
- }
- return ret;
-}
-
-void
-xpc_exit_sn2(void)
-{
- free_irq(SGI_XPC_ACTIVATE, NULL);
- xpc_disallow_IPI_ops_sn2();
- kfree(xpc_remote_copy_buffer_base_sn2);
-}
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 0c6de97dd347..09e24659ef3d 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -27,7 +27,7 @@
#if defined CONFIG_X86_64
#include <asm/uv/bios.h>
#include <asm/uv/uv_irq.h>
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
#include <asm/sn/intr.h>
#include <asm/sn/sn_sal.h>
#endif
@@ -35,7 +35,7 @@
#include "../sgi-gru/grukservices.h"
#include "xpc.h"
-#if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#if defined CONFIG_IA64_SGI_UV
struct uv_IO_APIC_route_entry {
__u64 vector : 8,
delivery_mode : 3,
@@ -48,6 +48,8 @@ struct uv_IO_APIC_route_entry {
__reserved_2 : 15,
dest : 32;
};
+
+#define sn_partition_id 0
#endif
static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
@@ -119,7 +121,7 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0)
mq->irq = SGI_XPC_ACTIVATE;
else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0)
@@ -142,7 +144,7 @@ xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
#if defined CONFIG_X86_64
uv_teardown_irq(mq->irq);
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
int mmr_pnode;
unsigned long mmr_value;
@@ -160,7 +162,7 @@ xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq)
{
int ret;
-#if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#if defined CONFIG_IA64_SGI_UV
int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
ret = sn_mq_watchlist_alloc(mmr_pnode, (void *)uv_gpa(mq->address),
@@ -195,7 +197,7 @@ xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
#if defined CONFIG_X86_64
ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
BUG_ON(ret != BIOS_STATUS_SUCCESS);
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
ret = sn_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
BUG_ON(ret != SALRET_OK);
#else
@@ -794,7 +796,7 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
else
ret = xpBiosError;
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+#elif defined CONFIG_IA64_SGI_UV
status = sn_partition_reserved_page_pa((u64)buf, cookie, rp_pa, len);
if (status == SALRET_OK)
ret = xpSuccess;
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 44d750d98bc8..f7d610a22347 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -515,7 +515,7 @@ xpnet_init(void)
{
int result;
- if (!is_shub() && !is_uv())
+ if (!is_uv())
return -ENODEV;
dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 8840299420e0..5e6be1527571 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -691,7 +691,6 @@ static int vmballoon_alloc_page_list(struct vmballoon *b,
}
if (page) {
- vmballoon_mark_page_offline(page, ctl->page_size);
/* Success. Add the page to the list and continue. */
list_add(&page->lru, &ctl->pages);
continue;
@@ -930,7 +929,6 @@ static void vmballoon_release_page_list(struct list_head *page_list,
list_for_each_entry_safe(page, tmp, page_list, lru) {
list_del(&page->lru);
- vmballoon_mark_page_online(page, page_size);
__free_pages(page, vmballoon_page_order(page_size));
}
@@ -1005,6 +1003,7 @@ static void vmballoon_enqueue_page_list(struct vmballoon *b,
enum vmballoon_page_size_type page_size)
{
unsigned long flags;
+ struct page *page;
if (page_size == VMW_BALLOON_4K_PAGE) {
balloon_page_list_enqueue(&b->b_dev_info, pages);
@@ -1014,6 +1013,11 @@ static void vmballoon_enqueue_page_list(struct vmballoon *b,
* for the balloon compaction mechanism.
*/
spin_lock_irqsave(&b->b_dev_info.pages_lock, flags);
+
+ list_for_each_entry(page, pages, lru) {
+ vmballoon_mark_page_offline(page, VMW_BALLOON_2M_PAGE);
+ }
+
list_splice_init(pages, &b->huge_pages);
__count_vm_events(BALLOON_INFLATE, *n_pages *
vmballoon_page_in_frames(VMW_BALLOON_2M_PAGE));
@@ -1056,6 +1060,8 @@ static void vmballoon_dequeue_page_list(struct vmballoon *b,
/* 2MB pages */
spin_lock_irqsave(&b->b_dev_info.pages_lock, flags);
list_for_each_entry_safe(page, tmp, &b->huge_pages, lru) {
+ vmballoon_mark_page_online(page, VMW_BALLOON_2M_PAGE);
+
list_move(&page->lru, pages);
if (++i == n_req_pages)
break;
diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c b/drivers/misc/vmw_vmci/vmci_doorbell.c
index bad89b6e0802..345addd9306d 100644
--- a/drivers/misc/vmw_vmci/vmci_doorbell.c
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -310,7 +310,8 @@ int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
entry = container_of(resource, struct dbell_entry, resource);
if (entry->run_delayed) {
- schedule_work(&entry->work);
+ if (!schedule_work(&entry->work))
+ vmci_resource_put(resource);
} else {
entry->notify_cb(entry->client_data);
vmci_resource_put(resource);
@@ -361,7 +362,8 @@ static void dbell_fire_entries(u32 notify_idx)
atomic_read(&dbell->active) == 1) {
if (dbell->run_delayed) {
vmci_resource_get(&dbell->resource);
- schedule_work(&dbell->work);
+ if (!schedule_work(&dbell->work))
+ vmci_resource_put(&dbell->resource);
} else {
dbell->notify_cb(dbell->client_data);
}
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 74e4364bc9fb..09113b9ad679 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -564,7 +564,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
- err = mmc_wait_for_cmd(host, &cmd, 0);
+ err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
if (err)
goto out;
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index e327f80ebe70..7102e2ebc614 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -10,6 +10,7 @@
#include <linux/kthread.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
+#include <linux/backing-dev.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -427,6 +428,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
goto free_tag_set;
}
+ if (mmc_host_is_spi(host) && host->use_spi_crc)
+ mq->queue->backing_dev_info->capabilities |=
+ BDI_CAP_STABLE_WRITES;
+
mq->queue->queuedata = mq;
blk_queue_rq_timeout(mq->queue, 60 * HZ);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index d681e8aaca83..fe914ff5f5d6 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1292,6 +1292,12 @@ int mmc_attach_sd(struct mmc_host *host)
goto err;
}
+ /*
+ * Some SD cards claims an out of spec VDD voltage range. Let's treat
+ * these bits as being in-valid and especially also bit7.
+ */
+ ocr &= ~0x7FFF;
+
rocr = mmc_select_voltage(host, ocr);
/*
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 7e0d3a49c06d..bb31e13648d6 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -597,7 +597,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
struct dma_chan *terminate_chan = NULL;
struct mmc_request *mrq;
- cancel_delayed_work_sync(&host->timeout_work);
+ cancel_delayed_work(&host->timeout_work);
mrq = host->mrq;
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
index ed5cefb83768..89deb451e0ac 100644
--- a/drivers/mmc/host/cavium.c
+++ b/drivers/mmc/host/cavium.c
@@ -374,6 +374,7 @@ static int finish_dma_single(struct cvm_mmc_host *host, struct mmc_data *data)
{
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
+ dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data));
return 1;
}
@@ -1046,7 +1047,8 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
mmc->max_segs = 1;
/* DMA size field can address up to 8 MB */
- mmc->max_seg_size = 8 * 1024 * 1024;
+ mmc->max_seg_size = min_t(unsigned int, 8 * 1024 * 1024,
+ dma_get_max_seg_size(host->dev));
mmc->max_req_size = mmc->max_seg_size;
/* External DMA is in 512 byte blocks */
mmc->max_blk_size = 512;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index faaaf52a46d2..eea52e2c5a0c 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2012,8 +2012,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
* delayed. Allowing the transfer to take place
* avoids races and keeps things simple.
*/
- if ((err != -ETIMEDOUT) &&
- (cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
+ if (err != -ETIMEDOUT) {
state = STATE_SENDING_DATA;
continue;
}
diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c
index 2d736e416775..ba9a63db73da 100644
--- a/drivers/mmc/host/meson-mx-sdio.c
+++ b/drivers/mmc/host/meson-mx-sdio.c
@@ -73,7 +73,7 @@
#define MESON_MX_SDIO_IRQC_IF_CONFIG_MASK GENMASK(7, 6)
#define MESON_MX_SDIO_IRQC_FORCE_DATA_CLK BIT(8)
#define MESON_MX_SDIO_IRQC_FORCE_DATA_CMD BIT(9)
- #define MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK GENMASK(10, 13)
+ #define MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK GENMASK(13, 10)
#define MESON_MX_SDIO_IRQC_SOFT_RESET BIT(15)
#define MESON_MX_SDIO_IRQC_FORCE_HALT BIT(30)
#define MESON_MX_SDIO_IRQC_HALT_HOLE BIT(31)
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 64d3b5fb7fe5..4a2872f49a60 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -774,8 +774,6 @@ int renesas_sdhi_probe(struct platform_device *pdev,
/* All SDHI have SDIO status bits which must be 1 */
mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS;
- pm_runtime_enable(&pdev->dev);
-
ret = renesas_sdhi_clk_enable(host);
if (ret)
goto efree;
@@ -856,8 +854,6 @@ edisclk:
efree:
tmio_mmc_host_free(host);
- pm_runtime_disable(&pdev->dev);
-
return ret;
}
EXPORT_SYMBOL_GPL(renesas_sdhi_probe);
@@ -869,8 +865,6 @@ int renesas_sdhi_remove(struct platform_device *pdev)
tmio_mmc_host_remove(host);
renesas_sdhi_clk_disable(host);
- pm_runtime_disable(&pdev->dev);
-
return 0;
}
EXPORT_SYMBOL_GPL(renesas_sdhi_remove);
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index b3a130a9ee23..1604f512c7bd 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -883,7 +883,7 @@ static int sdhci_acpi_runtime_resume(struct device *dev)
sdhci_acpi_byt_setting(&c->pdev->dev);
- return sdhci_runtime_resume_host(c->host);
+ return sdhci_runtime_resume_host(c->host, 0);
}
#endif
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 163d1cf4367e..44139fceac24 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -369,6 +369,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
host->mmc_host_ops.hs400_enhanced_strobe =
sdhci_cdns_hs400_enhanced_strobe;
+ sdhci_enable_v4_mode(host);
sdhci_get_of_property(pdev);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index c391510e9ef4..776a94216248 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1705,7 +1705,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
esdhc_pltfm_set_clock(host, imx_data->actual_clock);
}
- err = sdhci_runtime_resume_host(host);
+ err = sdhci_runtime_resume_host(host, 0);
if (err)
goto disable_ipg_clk;
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index e377b9bc55a4..e7d1920729fb 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -289,7 +289,7 @@ static int sdhci_at91_runtime_resume(struct device *dev)
}
out:
- return sdhci_runtime_resume_host(host);
+ return sdhci_runtime_resume_host(host, 0);
}
#endif /* CONFIG_PM */
@@ -357,6 +357,9 @@ static int sdhci_at91_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
+ /* HS200 is broken at this moment */
+ host->quirks2 = SDHCI_QUIRK2_BROKEN_HS200;
+
ret = sdhci_add_host(host);
if (ret)
goto pm_runtime_disable;
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 4041878eb0f3..7d06e2860c36 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -167,7 +167,7 @@ static int sdhci_pci_runtime_suspend_host(struct sdhci_pci_chip *chip)
err_pci_runtime_suspend:
while (--i >= 0)
- sdhci_runtime_resume_host(chip->slots[i]->host);
+ sdhci_runtime_resume_host(chip->slots[i]->host, 0);
return ret;
}
@@ -181,7 +181,7 @@ static int sdhci_pci_runtime_resume_host(struct sdhci_pci_chip *chip)
if (!slot)
continue;
- ret = sdhci_runtime_resume_host(slot->host);
+ ret = sdhci_runtime_resume_host(slot->host, 0);
if (ret)
return ret;
}
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 9dc4548271b4..19944b0049db 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -432,7 +432,6 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
mmc_hostname(host->mmc));
host->flags &= ~SDHCI_SIGNALING_330;
host->flags |= SDHCI_SIGNALING_180;
- host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
host->mmc->caps2 |= MMC_CAP2_NO_SD;
host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
pci_write_config_dword(chip->pdev,
@@ -682,6 +681,7 @@ static const struct sdhci_ops sdhci_pci_o2_ops = {
const struct sdhci_pci_fixes sdhci_o2 = {
.probe = sdhci_pci_o2_probe,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD,
.probe_slot = sdhci_pci_o2_probe_slot,
#ifdef CONFIG_PM_SLEEP
.resume = sdhci_pci_o2_resume,
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index 3ddecf479295..e55037ceda73 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -554,7 +554,7 @@ static int sdhci_pxav3_runtime_resume(struct device *dev)
if (!IS_ERR(pxa->clk_core))
clk_prepare_enable(pxa->clk_core);
- return sdhci_runtime_resume_host(host);
+ return sdhci_runtime_resume_host(host, 0);
}
#endif
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 8e4a8ba33f05..f5753aef7151 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -745,7 +745,7 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
clk_prepare_enable(busclk);
if (ourhost->cur_clk >= 0)
clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
- ret = sdhci_runtime_resume_host(host);
+ ret = sdhci_runtime_resume_host(host, 0);
return ret;
}
#endif
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index 6ee340a3fb3a..d07b9793380f 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -217,10 +217,11 @@ static inline void _sdhci_sprd_set_clock(struct sdhci_host *host,
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
u32 div, val, mask;
- div = sdhci_sprd_calc_div(sprd_host->base_rate, clk);
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- clk |= ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
- sdhci_enable_clk(host, clk);
+ div = sdhci_sprd_calc_div(sprd_host->base_rate, clk);
+ div = ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
+ sdhci_enable_clk(host, div);
/* enable auto gate sdhc_enable_auto_gate */
val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI);
@@ -373,6 +374,11 @@ static unsigned int sdhci_sprd_get_max_timeout_count(struct sdhci_host *host)
return 1 << 31;
}
+static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host)
+{
+ return 0;
+}
+
static struct sdhci_ops sdhci_sprd_ops = {
.read_l = sdhci_sprd_readl,
.write_l = sdhci_sprd_writel,
@@ -385,6 +391,7 @@ static struct sdhci_ops sdhci_sprd_ops = {
.set_uhs_signaling = sdhci_sprd_set_uhs_signaling,
.hw_reset = sdhci_sprd_hw_reset,
.get_max_timeout_count = sdhci_sprd_get_max_timeout_count,
+ .get_ro = sdhci_sprd_get_ro,
};
static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -501,9 +508,12 @@ static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host,
}
static const struct sdhci_pltfm_data sdhci_sprd_pdata = {
- .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+ .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ SDHCI_QUIRK_MISSING_CAPS,
.quirks2 = SDHCI_QUIRK2_BROKEN_HS200 |
- SDHCI_QUIRK2_USE_32BIT_BLK_CNT,
+ SDHCI_QUIRK2_USE_32BIT_BLK_CNT |
+ SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.ops = &sdhci_sprd_ops,
};
@@ -605,6 +615,16 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
sdhci_enable_v4_mode(host);
+ /*
+ * Supply the existing CAPS, but clear the UHS-I modes. This
+ * will allow these modes to be specified only by device
+ * tree properties through mmc_of_parse().
+ */
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_DDR50);
+
ret = sdhci_setup_host(host);
if (ret)
goto pm_runtime_disable;
@@ -624,6 +644,7 @@ err_cleanup_host:
sdhci_cleanup_host(host);
pm_runtime_disable:
+ pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
@@ -695,7 +716,7 @@ static int sdhci_sprd_runtime_resume(struct device *dev)
if (ret)
goto clk_disable;
- sdhci_runtime_resume_host(host);
+ sdhci_runtime_resume_host(host, 1);
return 0;
clk_disable:
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f4d4761cf20a..02d8f524bb9e 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -258,6 +258,16 @@ static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
}
}
+static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
+{
+ /*
+ * Write-enable shall be assumed if GPIO is missing in a board's
+ * device-tree because SDHCI's WRITE_PROTECT bit doesn't work on
+ * Tegra.
+ */
+ return mmc_gpio_get_ro(host->mmc);
+}
+
static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1224,6 +1234,7 @@ static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
};
static const struct sdhci_ops tegra_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
@@ -1279,6 +1290,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
};
static const struct sdhci_ops tegra114_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra_sdhci_writew,
.write_l = tegra_sdhci_writel,
@@ -1332,6 +1344,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
};
static const struct sdhci_ops tegra210_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra210_sdhci_writew,
.write_l = tegra_sdhci_writel,
@@ -1366,6 +1379,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
};
static const struct sdhci_ops tegra186_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index 8a18f14cf842..1dea1ba66f7b 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -638,7 +638,7 @@ static int xenon_runtime_resume(struct device *dev)
priv->restore_needed = false;
}
- ret = sdhci_runtime_resume_host(host);
+ ret = sdhci_runtime_resume_host(host, 0);
if (ret)
goto out;
return 0;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 59acf8e3331e..a5dc5aae973e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3320,7 +3320,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
}
EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
-int sdhci_runtime_resume_host(struct sdhci_host *host)
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
{
struct mmc_host *mmc = host->mmc;
unsigned long flags;
@@ -3331,7 +3331,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
host->ops->enable_dma(host);
}
- sdhci_init(host, 0);
+ sdhci_init(host, soft_reset);
if (mmc->ios.power_mode != MMC_POWER_UNDEFINED &&
mmc->ios.power_mode != MMC_POWER_OFF) {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 89fd96596a1f..902f855efe8f 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -781,7 +781,7 @@ void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
int sdhci_suspend_host(struct sdhci_host *host);
int sdhci_resume_host(struct sdhci_host *host);
int sdhci_runtime_suspend_host(struct sdhci_host *host);
-int sdhci_runtime_resume_host(struct sdhci_host *host);
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset);
#endif
void sdhci_cqe_enable(struct mmc_host *mmc);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 8539e10784b4..93e83ad25976 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -172,8 +172,6 @@ static int tmio_mmc_probe(struct platform_device *pdev)
host->mmc->f_max = pdata->hclk;
host->mmc->f_min = pdata->hclk / 512;
- pm_runtime_enable(&pdev->dev);
-
ret = tmio_mmc_host_probe(host);
if (ret)
goto host_free;
@@ -193,7 +191,6 @@ host_remove:
tmio_mmc_host_remove(host);
host_free:
tmio_mmc_host_free(host);
- pm_runtime_disable(&pdev->dev);
cell_disable:
if (cell->disable)
cell->disable(pdev);
@@ -210,8 +207,6 @@ static int tmio_mmc_remove(struct platform_device *pdev)
if (cell->disable)
cell->disable(pdev);
- pm_runtime_disable(&pdev->dev);
-
return 0;
}
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index c5ba13fae399..2f0b092d6dcc 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -163,6 +163,7 @@ struct tmio_mmc_host {
unsigned long last_req_ts;
struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug;
+ bool runtime_synced;
bool sdio_irq_enabled;
/* Mandatory callback */
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index 2cb3f951c3e2..9b6e1001e77c 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -1153,15 +1153,6 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host)
}
EXPORT_SYMBOL_GPL(tmio_mmc_host_free);
-/**
- * tmio_mmc_host_probe() - Common probe for all implementations
- * @_host: Host to probe
- *
- * Perform tasks common to all implementations probe functions.
- *
- * The caller should have called pm_runtime_enable() prior to calling
- * the common probe function.
- */
int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
{
struct platform_device *pdev = _host->pdev;
@@ -1257,19 +1248,22 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
/* See if we also get DMA */
tmio_mmc_request_dma(_host, pdata);
- pm_runtime_set_active(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
ret = mmc_add_host(mmc);
if (ret)
goto remove_host;
dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
+ pm_runtime_put(&pdev->dev);
return 0;
remove_host:
+ pm_runtime_put_noidle(&pdev->dev);
tmio_mmc_host_remove(_host);
return ret;
}
@@ -1280,12 +1274,11 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
struct platform_device *pdev = host->pdev;
struct mmc_host *mmc = host->mmc;
+ pm_runtime_get_sync(&pdev->dev);
+
if (host->pdata->flags & TMIO_MMC_SDIO_IRQ)
sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
- if (!host->native_hotplug)
- pm_runtime_get_sync(&pdev->dev);
-
dev_pm_qos_hide_latency_limit(&pdev->dev);
mmc_remove_host(mmc);
@@ -1294,7 +1287,10 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
tmio_mmc_release_dma(host);
pm_runtime_dont_use_autosuspend(&pdev->dev);
+ if (host->native_hotplug)
+ pm_runtime_put_noidle(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
}
EXPORT_SYMBOL_GPL(tmio_mmc_host_remove);
@@ -1337,6 +1333,11 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
{
struct tmio_mmc_host *host = dev_get_drvdata(dev);
+ if (!host->runtime_synced) {
+ host->runtime_synced = true;
+ return 0;
+ }
+
tmio_mmc_clk_enable(host);
tmio_mmc_hw_reset(host->mmc);
diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index 49aad9a79c18..91a2be41edf6 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -631,7 +631,6 @@ static int uniphier_sd_probe(struct platform_device *pdev)
host->clk_disable = uniphier_sd_clk_disable;
host->set_clock = uniphier_sd_set_clock;
- pm_runtime_enable(&pdev->dev);
ret = uniphier_sd_clk_enable(host);
if (ret)
goto free_host;
@@ -653,7 +652,6 @@ static int uniphier_sd_probe(struct platform_device *pdev)
free_host:
tmio_mmc_host_free(host);
- pm_runtime_disable(&pdev->dev);
return ret;
}
@@ -664,7 +662,6 @@ static int uniphier_sd_remove(struct platform_device *pdev)
tmio_mmc_host_remove(host);
uniphier_sd_clk_disable(host);
- pm_runtime_disable(&pdev->dev);
return 0;
}
diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig
index cff6bbd226f5..a4d8968d133d 100644
--- a/drivers/mtd/hyperbus/Kconfig
+++ b/drivers/mtd/hyperbus/Kconfig
@@ -1,5 +1,6 @@
menuconfig MTD_HYPERBUS
tristate "HyperBus support"
+ depends on HAS_IOMEM
select MTD_CFI
select MTD_MAP_BANK_WIDTH_2
select MTD_CFI_AMDSTD
@@ -14,8 +15,9 @@ if MTD_HYPERBUS
config HBMC_AM654
tristate "HyperBus controller driver for AM65x SoC"
+ depends on ARM64 || COMPILE_TEST
select MULTIPLEXER
- select MUX_MMIO
+ imply MUX_MMIO
help
This is the driver for HyperBus controller on TI's AM65x and
other SoCs
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 895510d40ce4..47602af4ee34 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -81,6 +81,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
default:
printk(KERN_WARNING "SA1100 flash: unknown base address "
"0x%08lx, assuming CS0\n", phys);
+ /* Fall through */
case SA1100_CS0_PHYS:
subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
index a1f8fe1abb10..e082d632fb74 100644
--- a/drivers/mtd/nand/onenand/onenand_base.c
+++ b/drivers/mtd/nand/onenand/onenand_base.c
@@ -3259,6 +3259,7 @@ static void onenand_check_features(struct mtd_info *mtd)
switch (density) {
case ONENAND_DEVICE_DENSITY_8Gb:
this->options |= ONENAND_HAS_NOP_1;
+ /* fall through */
case ONENAND_DEVICE_DENSITY_4Gb:
if (ONENAND_IS_DDP(this))
this->options |= ONENAND_HAS_2PLANE;
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 1622d3145587..8ca9fad6e6ad 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -390,6 +390,14 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
(chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2)
return MICRON_ON_DIE_UNSUPPORTED;
+ /*
+ * It seems that there are devices which do not support ECC officially.
+ * At least the MT29F2G08ABAGA / MT29F2G08ABBGA devices supports
+ * enabling the ECC feature but don't reflect that to the READ_ID table.
+ * So we have to guarantee that we disable the ECC feature directly
+ * after we did the READ_ID table command. Later we can evaluate the
+ * ECC_ENABLE support.
+ */
ret = micron_nand_on_die_ecc_setup(chip, true);
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
@@ -398,13 +406,13 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
- if (!(id[4] & MICRON_ID_ECC_ENABLED))
- return MICRON_ON_DIE_UNSUPPORTED;
-
ret = micron_nand_on_die_ecc_setup(chip, false);
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
+ if (!(id[4] & MICRON_ID_ECC_ENABLED))
+ return MICRON_ON_DIE_UNSUPPORTED;
+
ret = nand_readid_op(chip, 0, id, sizeof(id));
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 03cc788511d5..654bdc41fc99 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -3780,8 +3780,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
default:
/* Kept only for backward compatibility purpose. */
params->quad_enable = spansion_quad_enable;
- if (nor->clear_sr_bp)
- nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
break;
}
@@ -4035,6 +4033,9 @@ static int spi_nor_init(struct spi_nor *nor)
int err;
if (nor->clear_sr_bp) {
+ if (nor->quad_enable == spansion_quad_enable)
+ nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
+
err = nor->clear_sr_bp(nor);
if (err) {
dev_err(nor->dev,
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 11c5bad95226..14a5fb378145 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -363,10 +363,13 @@ static int __init arcrimi_setup(char *s)
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
+ /* Fall through */
case 3: /* Node ID */
node = ints[3];
+ /* Fall through */
case 2: /* IRQ */
irq = ints[2];
+ /* Fall through */
case 1: /* IO address */
io = ints[1];
}
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 28510e33924f..cd27fdc1059b 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -197,16 +197,22 @@ static int __init com20020isa_setup(char *s)
switch (ints[0]) {
default: /* ERROR */
pr_info("Too many arguments\n");
+ /* Fall through */
case 6: /* Timeout */
timeout = ints[6];
+ /* Fall through */
case 5: /* CKP value */
clockp = ints[5];
+ /* Fall through */
case 4: /* Backplane flag */
backplane = ints[4];
+ /* Fall through */
case 3: /* Node ID */
node = ints[3];
+ /* Fall through */
case 2: /* IRQ */
irq = ints[2];
+ /* Fall through */
case 1: /* IO address */
io = ints[1];
}
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 2c546013a980..186bbf87bc84 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -363,8 +363,10 @@ static int __init com90io_setup(char *s)
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
+ /* Fall through */
case 2: /* IRQ */
irq = ints[2];
+ /* Fall through */
case 1: /* IO address */
io = ints[1];
}
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index ca4a57c30bf8..bd75d06ad7df 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -693,10 +693,13 @@ static int __init com90xx_setup(char *s)
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
+ /* Fall through */
case 3: /* Mem address */
shmem = ints[3];
+ /* Fall through */
case 2: /* IRQ */
irq = ints[2];
+ /* Fall through */
case 1: /* IO address */
io = ints[1];
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 9b7016abca2f..931d9d935686 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1126,6 +1126,8 @@ static void bond_compute_features(struct bonding *bond)
done:
bond_dev->vlan_features = vlan_features;
bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX |
NETIF_F_GSO_UDP_L4;
bond_dev->mpls_features = mpls_features;
bond_dev->gso_max_segs = gso_max_segs;
@@ -2196,6 +2198,15 @@ static void bond_miimon_commit(struct bonding *bond)
bond_for_each_slave(bond, slave, iter) {
switch (slave->new_link) {
case BOND_LINK_NOCHANGE:
+ /* For 802.3ad mode, check current slave speed and
+ * duplex again in case its port was disabled after
+ * invalid speed/duplex reporting but recovered before
+ * link monitoring could make a decision on the actual
+ * link status
+ */
+ if (BOND_MODE(bond) == BOND_MODE_8023AD &&
+ slave->link == BOND_LINK_UP)
+ bond_3ad_adapter_speed_duplex_changed(slave);
continue;
case BOND_LINK_UP:
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 1d4075903971..c8e1a04ba384 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -898,7 +898,8 @@ static void at91_irq_err_state(struct net_device *dev,
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
}
- case CAN_STATE_ERROR_WARNING: /* fallthrough */
+ /* fall through */
+ case CAN_STATE_ERROR_WARNING:
/*
* from: ERROR_ACTIVE, ERROR_WARNING
* to : ERROR_PASSIVE, BUS_OFF
@@ -947,7 +948,8 @@ static void at91_irq_err_state(struct net_device *dev,
netdev_dbg(dev, "Error Active\n");
cf->can_id |= CAN_ERR_PROT;
cf->data[2] = CAN_ERR_PROT_ACTIVE;
- case CAN_STATE_ERROR_WARNING: /* fallthrough */
+ /* fall through */
+ case CAN_STATE_ERROR_WARNING:
reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF;
reg_ier = AT91_IRQ_ERRP;
break;
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index b6b93a2d93a5..483d270664cc 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -1249,6 +1249,8 @@ int register_candev(struct net_device *dev)
return -EINVAL;
dev->rtnl_link_ops = &can_link_ops;
+ netif_carrier_off(dev);
+
return register_netdev(dev);
}
EXPORT_SYMBOL_GPL(register_candev);
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index f2fe344593d5..fcec8bcb53d6 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -400,9 +400,10 @@ static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
priv->write(reg_mcr, &regs->mcr);
}
-static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
{
struct flexcan_regs __iomem *regs = priv->regs;
+ unsigned int ackval;
u32 reg_mcr;
reg_mcr = priv->read(&regs->mcr);
@@ -412,20 +413,37 @@ static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
/* enable stop request */
regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
+
+ /* get stop acknowledgment */
+ if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+ ackval, ackval & (1 << priv->stm.ack_bit),
+ 0, FLEXCAN_TIMEOUT_US))
+ return -ETIMEDOUT;
+
+ return 0;
}
-static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
{
struct flexcan_regs __iomem *regs = priv->regs;
+ unsigned int ackval;
u32 reg_mcr;
/* remove stop request */
regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
1 << priv->stm.req_bit, 0);
+ /* get stop acknowledgment */
+ if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+ ackval, !(ackval & (1 << priv->stm.ack_bit)),
+ 0, FLEXCAN_TIMEOUT_US))
+ return -ETIMEDOUT;
+
reg_mcr = priv->read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
priv->write(reg_mcr, &regs->mcr);
+
+ return 0;
}
static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -1437,10 +1455,10 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->stm.gpr = syscon_node_to_regmap(gpr_np);
- of_node_put(gpr_np);
if (IS_ERR(priv->stm.gpr)) {
dev_dbg(&pdev->dev, "could not find gpr regmap\n");
- return PTR_ERR(priv->stm.gpr);
+ ret = PTR_ERR(priv->stm.gpr);
+ goto out_put_node;
}
priv->stm.req_gpr = out_val[1];
@@ -1455,7 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true);
- return 0;
+out_put_node:
+ of_node_put(gpr_np);
+ return ret;
}
static const struct of_device_id flexcan_of_match[] = {
@@ -1612,7 +1632,9 @@ static int __maybe_unused flexcan_suspend(struct device *device)
*/
if (device_may_wakeup(device)) {
enable_irq_wake(dev->irq);
- flexcan_enter_stop_mode(priv);
+ err = flexcan_enter_stop_mode(priv);
+ if (err)
+ return err;
} else {
err = flexcan_chip_disable(priv);
if (err)
@@ -1662,10 +1684,13 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
+ int err;
if (netif_running(dev) && device_may_wakeup(device)) {
flexcan_enable_wakeup_irq(priv, false);
- flexcan_exit_stop_mode(priv);
+ err = flexcan_exit_stop_mode(priv);
+ if (err)
+ return err;
}
return 0;
diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c
index 7f6a3b971da9..13b10cbf236a 100644
--- a/drivers/net/can/peak_canfd/peak_pciefd_main.c
+++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c
@@ -660,7 +660,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd)
pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ,
PCIEFD_REG_CAN_CLK_SEL);
- /* fallthough */
+ /* fall through */
case CANFD_CLK_SEL_80MHZ:
priv->ucan.can.clock.freq = 80 * 1000 * 1000;
break;
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 05410008aa6b..de34a4b82d4a 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1508,10 +1508,11 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota)
/* All packets processed */
if (num_pkts < quota) {
- napi_complete_done(napi, num_pkts);
- /* Enable Rx FIFO interrupts */
- rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
- RCANFD_RFCC_RFIE);
+ if (napi_complete_done(napi, num_pkts)) {
+ /* Enable Rx FIFO interrupts */
+ rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
+ RCANFD_RFCC_RFIE);
+ }
}
return num_pkts;
}
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
index 185c7f7d38a4..5e0d5e8101c8 100644
--- a/drivers/net/can/sja1000/peak_pcmcia.c
+++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -479,7 +479,7 @@ static void pcan_free_channels(struct pcan_pccard *card)
if (!netdev)
continue;
- strncpy(name, netdev->name, IFNAMSIZ);
+ strlcpy(name, netdev->name, IFNAMSIZ);
unregister_sja1000dev(netdev);
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 44e99e3d7134..12358f06d194 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -664,17 +664,6 @@ static int mcp251x_power_enable(struct regulator *reg, int enable)
return regulator_disable(reg);
}
-static void mcp251x_open_clean(struct net_device *net)
-{
- struct mcp251x_priv *priv = netdev_priv(net);
- struct spi_device *spi = priv->spi;
-
- free_irq(spi->irq, priv);
- mcp251x_hw_sleep(spi);
- mcp251x_power_enable(priv->transceiver, 0);
- close_candev(net);
-}
-
static int mcp251x_stop(struct net_device *net)
{
struct mcp251x_priv *priv = netdev_priv(net);
@@ -860,7 +849,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if (new_state >= CAN_STATE_ERROR_WARNING &&
new_state <= CAN_STATE_BUS_OFF)
priv->can.can_stats.error_warning++;
- case CAN_STATE_ERROR_WARNING: /* fallthrough */
+ /* fall through */
+ case CAN_STATE_ERROR_WARNING:
if (new_state >= CAN_STATE_ERROR_PASSIVE &&
new_state <= CAN_STATE_BUS_OFF)
priv->can.can_stats.error_passive++;
@@ -940,37 +930,43 @@ static int mcp251x_open(struct net_device *net)
flags | IRQF_ONESHOT, DEVICE_NAME, priv);
if (ret) {
dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
- mcp251x_power_enable(priv->transceiver, 0);
- close_candev(net);
- goto open_unlock;
+ goto out_close;
}
priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
0);
+ if (!priv->wq) {
+ ret = -ENOMEM;
+ goto out_clean;
+ }
INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
ret = mcp251x_hw_reset(spi);
- if (ret) {
- mcp251x_open_clean(net);
- goto open_unlock;
- }
+ if (ret)
+ goto out_free_wq;
ret = mcp251x_setup(net, spi);
- if (ret) {
- mcp251x_open_clean(net);
- goto open_unlock;
- }
+ if (ret)
+ goto out_free_wq;
ret = mcp251x_set_normal_mode(spi);
- if (ret) {
- mcp251x_open_clean(net);
- goto open_unlock;
- }
+ if (ret)
+ goto out_free_wq;
can_led_event(net, CAN_LED_EVENT_OPEN);
netif_wake_queue(net);
+ mutex_unlock(&priv->mcp_lock);
-open_unlock:
+ return 0;
+
+out_free_wq:
+ destroy_workqueue(priv->wq);
+out_clean:
+ free_irq(spi->irq, priv);
+ mcp251x_hw_sleep(spi);
+out_close:
+ mcp251x_power_enable(priv->transceiver, 0);
+ close_candev(net);
mutex_unlock(&priv->mcp_lock);
return ret;
}
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index 15ce5ad1d632..617da295b6c1 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -415,7 +415,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
new_state = CAN_STATE_ERROR_WARNING;
break;
}
- /* else: fall through */
+ /* fall through */
case CAN_STATE_ERROR_WARNING:
if (n & PCAN_USB_ERROR_BUS_HEAVY) {
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 458154c9b482..65dce642b86b 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -568,16 +568,16 @@ static int peak_usb_ndo_stop(struct net_device *netdev)
dev->state &= ~PCAN_USB_STATE_STARTED;
netif_stop_queue(netdev);
+ close_candev(netdev);
+
+ dev->can.state = CAN_STATE_STOPPED;
+
/* unlink all pending urbs and free used memory */
peak_usb_unlink_all_urbs(dev);
if (dev->adapter->dev_stop)
dev->adapter->dev_stop(dev);
- close_candev(netdev);
-
- dev->can.state = CAN_STATE_STOPPED;
-
/* can set bus off now */
if (dev->adapter->dev_set_bus) {
int err = dev->adapter->dev_set_bus(dev, 0);
@@ -855,7 +855,7 @@ static void peak_usb_disconnect(struct usb_interface *intf)
dev_prev_siblings = dev->prev_siblings;
dev->state &= ~PCAN_USB_STATE_CONNECTED;
- strncpy(name, netdev->name, IFNAMSIZ);
+ strlcpy(name, netdev->name, IFNAMSIZ);
unregister_netdev(netdev);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
index 34761c3a6286..47cc1ff5b88e 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -841,7 +841,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
goto err_out;
/* allocate command buffer once for all for the interface */
- pdev->cmd_buffer_addr = kmalloc(PCAN_UFD_CMD_BUFFER_SIZE,
+ pdev->cmd_buffer_addr = kzalloc(PCAN_UFD_CMD_BUFFER_SIZE,
GFP_KERNEL);
if (!pdev->cmd_buffer_addr)
goto err_out_1;
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index 178bb7cff0c1..53cb2f72bdd0 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -494,7 +494,7 @@ static int pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
u8 *buffer;
int err;
- buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
+ buffer = kzalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 3811fdbda13e..28c963a21dac 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -478,6 +478,7 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
unsigned long *supported,
struct phylink_link_state *state)
{
+ struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
if (!phy_interface_mode_is_rgmii(state->interface) &&
@@ -487,8 +488,10 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
state->interface != PHY_INTERFACE_MODE_INTERNAL &&
state->interface != PHY_INTERFACE_MODE_MOCA) {
bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
- dev_err(ds->dev,
- "Unsupported interface: %d\n", state->interface);
+ if (port != core_readl(priv, CORE_IMP0_PRT_ID))
+ dev_err(ds->dev,
+ "Unsupported interface: %d for port %d\n",
+ state->interface, port);
return;
}
@@ -526,6 +529,9 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port,
u32 id_mode_dis = 0, port_mode;
u32 reg, offset;
+ if (port == core_readl(priv, CORE_IMP0_PRT_ID))
+ return;
+
if (priv->type == BCM7445_DEVICE_ID)
offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
else
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 5a9e27b337a8..098b01e4ed1a 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -81,6 +81,7 @@ static const struct of_device_id ksz9477_dt_ids[] = {
{ .compatible = "microchip,ksz9897" },
{ .compatible = "microchip,ksz9893" },
{ .compatible = "microchip,ksz9563" },
+ { .compatible = "microchip,ksz8563" },
{},
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index ee7096d8af07..72ec250b9540 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -128,6 +128,7 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \
{ \
+ .name = #width, \
.val_bits = (width), \
.reg_stride = (width) / 8, \
.reg_bits = (regbits) + (regalign), \
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 6b17cd961d06..d0a97eb73a37 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -27,7 +27,6 @@
#include <linux/platform_data/mv88e6xxx.h>
#include <linux/netdevice.h>
#include <linux/gpio/consumer.h>
-#include <linux/phy.h>
#include <linux/phylink.h>
#include <net/dsa.h>
@@ -430,7 +429,7 @@ int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
return 0;
/* Port's MAC control must not be changed unless the link is down */
- err = chip->info->ops->port_set_link(chip, port, 0);
+ err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
if (err)
return err;
@@ -482,30 +481,6 @@ static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
return port < chip->info->num_internal_phys;
}
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
- struct phy_device *phydev)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- int err;
-
- if (!phy_is_pseudo_fixed_link(phydev) &&
- mv88e6xxx_phy_is_internal(ds, port))
- return;
-
- mv88e6xxx_reg_lock(chip);
- err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
- phydev->duplex, phydev->pause,
- phydev->interface);
- mv88e6xxx_reg_unlock(chip);
-
- if (err && err != -EOPNOTSUPP)
- dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
-}
-
static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
unsigned long *mask,
struct phylink_link_state *state)
@@ -2721,6 +2696,7 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
err = mv88e6xxx_mdio_register(chip, child, true);
if (err) {
mv88e6xxx_mdios_unregister(chip);
+ of_node_put(child);
return err;
}
}
@@ -4638,7 +4614,6 @@ static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.get_tag_protocol = mv88e6xxx_get_tag_protocol,
.setup = mv88e6xxx_setup,
- .adjust_link = mv88e6xxx_adjust_link,
.phylink_validate = mv88e6xxx_validate,
.phylink_mac_link_state = mv88e6xxx_link_state,
.phylink_mac_config = mv88e6xxx_mac_config,
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 232e8cc96f6d..16f15c93a102 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016 John Crispin <john@phrozen.org>
*/
@@ -583,8 +583,11 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
for_each_available_child_of_node(ports, port) {
err = of_property_read_u32(port, "reg", &reg);
- if (err)
+ if (err) {
+ of_node_put(port);
+ of_node_put(ports);
return err;
+ }
if (!dsa_is_user_port(priv->ds, reg))
continue;
@@ -595,6 +598,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
internal_mdio_mask |= BIT(reg);
}
+ of_node_put(ports);
if (!external_mdio_mask && !internal_mdio_mask) {
dev_err(priv->dev, "no PHYs are defined.\n");
return -EINVAL;
@@ -935,6 +939,8 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
qca8k_port_set_status(priv, port, 1);
priv->port_sts[port].enabled = 1;
+ phy_support_asym_pause(phy);
+
return 0;
}
diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
index 6bfb1696a6f2..9988c9d18567 100644
--- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
+++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
@@ -277,6 +277,18 @@ sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
}
+static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
+ enum packing_op op)
+{
+ struct sja1105_l2_lookup_entry *entry = entry_ptr;
+ u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
+ const int size = SJA1105_SIZE_DYN_CMD;
+
+ sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
+
+ return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
+}
+
static void
sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
enum packing_op op)
@@ -477,7 +489,7 @@ sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
/* SJA1105E/T: First generation */
struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
[BLK_IDX_L2_LOOKUP] = {
- .entry_packing = sja1105et_l2_lookup_entry_packing,
+ .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
.cmd_packing = sja1105et_l2_lookup_cmd_packing,
.access = (OP_READ | OP_WRITE | OP_DEL),
.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 32bf3a7cc3b6..df976b259e43 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -218,7 +218,7 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
/* This selects between Independent VLAN Learning (IVL) and
* Shared VLAN Learning (SVL)
*/
- .shared_learn = false,
+ .shared_learn = true,
/* Don't discard management traffic based on ENFPORT -
* we don't perform SMAC port enforcement anyway, so
* what we are setting here doesn't matter.
@@ -625,6 +625,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
if (of_property_read_u32(child, "reg", &index) < 0) {
dev_err(dev, "Port number not defined in device tree "
"(property \"reg\")\n");
+ of_node_put(child);
return -ENODEV;
}
@@ -634,6 +635,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
dev_err(dev, "Failed to read phy-mode or "
"phy-interface-type property for port %d\n",
index);
+ of_node_put(child);
return -ENODEV;
}
ports[index].phy_mode = phy_mode;
@@ -643,6 +645,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
if (!of_phy_is_fixed_link(child)) {
dev_err(dev, "phy-handle or fixed-link "
"properties missing!\n");
+ of_node_put(child);
return -ENODEV;
}
/* phy-handle is missing, but fixed-link isn't.
@@ -1089,8 +1092,13 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
l2_lookup.vlanid = vid;
l2_lookup.iotag = SJA1105_S_TAG;
l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
- l2_lookup.mask_vlanid = VLAN_VID_MASK;
- l2_lookup.mask_iotag = BIT(0);
+ if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+ l2_lookup.mask_vlanid = VLAN_VID_MASK;
+ l2_lookup.mask_iotag = BIT(0);
+ } else {
+ l2_lookup.mask_vlanid = 0;
+ l2_lookup.mask_iotag = 0;
+ }
l2_lookup.destports = BIT(port);
rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1147,8 +1155,13 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port,
l2_lookup.vlanid = vid;
l2_lookup.iotag = SJA1105_S_TAG;
l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
- l2_lookup.mask_vlanid = VLAN_VID_MASK;
- l2_lookup.mask_iotag = BIT(0);
+ if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+ l2_lookup.mask_vlanid = VLAN_VID_MASK;
+ l2_lookup.mask_iotag = BIT(0);
+ } else {
+ l2_lookup.mask_vlanid = 0;
+ l2_lookup.mask_iotag = 0;
+ }
l2_lookup.destports = BIT(port);
rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1178,60 +1191,31 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
{
struct sja1105_private *priv = ds->priv;
- u16 rx_vid, tx_vid;
- int rc, i;
- if (dsa_port_is_vlan_filtering(&ds->ports[port]))
- return priv->info->fdb_add_cmd(ds, port, addr, vid);
-
- /* Since we make use of VLANs even when the bridge core doesn't tell us
- * to, translate these FDB entries into the correct dsa_8021q ones.
- * The basic idea (also repeats for removal below) is:
- * - Each of the other front-panel ports needs to be able to forward a
- * pvid-tagged (aka tagged with their rx_vid) frame that matches this
- * DMAC.
- * - The CPU port (aka the tx_vid of this port) needs to be able to
- * send a frame matching this DMAC to the specified port.
- * For a better picture see net/dsa/tag_8021q.c.
+ /* dsa_8021q is in effect when the bridge's vlan_filtering isn't,
+ * so the switch still does some VLAN processing internally.
+ * But Shared VLAN Learning (SVL) is also active, and it will take
+ * care of autonomous forwarding between the unique pvid's of each
+ * port. Here we just make sure that users can't add duplicate FDB
+ * entries when in this mode - the actual VID doesn't matter except
+ * for what gets printed in 'bridge fdb show'. In the case of zero,
+ * no VID gets printed at all.
*/
- for (i = 0; i < SJA1105_NUM_PORTS; i++) {
- if (i == port)
- continue;
- if (i == dsa_upstream_port(priv->ds, port))
- continue;
+ if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+ vid = 0;
- rx_vid = dsa_8021q_rx_vid(ds, i);
- rc = priv->info->fdb_add_cmd(ds, port, addr, rx_vid);
- if (rc < 0)
- return rc;
- }
- tx_vid = dsa_8021q_tx_vid(ds, port);
- return priv->info->fdb_add_cmd(ds, port, addr, tx_vid);
+ return priv->info->fdb_add_cmd(ds, port, addr, vid);
}
static int sja1105_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
{
struct sja1105_private *priv = ds->priv;
- u16 rx_vid, tx_vid;
- int rc, i;
- if (dsa_port_is_vlan_filtering(&ds->ports[port]))
- return priv->info->fdb_del_cmd(ds, port, addr, vid);
+ if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+ vid = 0;
- for (i = 0; i < SJA1105_NUM_PORTS; i++) {
- if (i == port)
- continue;
- if (i == dsa_upstream_port(priv->ds, port))
- continue;
-
- rx_vid = dsa_8021q_rx_vid(ds, i);
- rc = priv->info->fdb_del_cmd(ds, port, addr, rx_vid);
- if (rc < 0)
- return rc;
- }
- tx_vid = dsa_8021q_tx_vid(ds, port);
- return priv->info->fdb_del_cmd(ds, port, addr, tx_vid);
+ return priv->info->fdb_del_cmd(ds, port, addr, vid);
}
static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
@@ -1239,12 +1223,8 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
{
struct sja1105_private *priv = ds->priv;
struct device *dev = ds->dev;
- u16 rx_vid, tx_vid;
int i;
- rx_vid = dsa_8021q_rx_vid(ds, port);
- tx_vid = dsa_8021q_tx_vid(ds, port);
-
for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
struct sja1105_l2_lookup_entry l2_lookup = {0};
u8 macaddr[ETH_ALEN];
@@ -1270,39 +1250,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
continue;
u64_to_ether_addr(l2_lookup.macaddr, macaddr);
- /* On SJA1105 E/T, the switch doesn't implement the LOCKEDS
- * bit, so it doesn't tell us whether a FDB entry is static
- * or not.
- * But, of course, we can find out - we're the ones who added
- * it in the first place.
- */
- if (priv->info->device_id == SJA1105E_DEVICE_ID ||
- priv->info->device_id == SJA1105T_DEVICE_ID) {
- int match;
-
- match = sja1105_find_static_fdb_entry(priv, port,
- &l2_lookup);
- l2_lookup.lockeds = (match >= 0);
- }
-
- /* We need to hide the dsa_8021q VLANs from the user. This
- * basically means hiding the duplicates and only showing
- * the pvid that is supposed to be active in standalone and
- * non-vlan_filtering modes (aka 1).
- * - For statically added FDB entries (bridge fdb add), we
- * can convert the TX VID (coming from the CPU port) into the
- * pvid and ignore the RX VIDs of the other ports.
- * - For dynamically learned FDB entries, a single entry with
- * no duplicates is learned - that which has the real port's
- * pvid, aka RX VID.
- */
- if (!dsa_port_is_vlan_filtering(&ds->ports[port])) {
- if (l2_lookup.vlanid == tx_vid ||
- l2_lookup.vlanid == rx_vid)
- l2_lookup.vlanid = 1;
- else
- continue;
- }
+ /* We need to hide the dsa_8021q VLANs from the user. */
+ if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+ l2_lookup.vlanid = 0;
cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
}
return 0;
@@ -1594,6 +1544,7 @@ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port,
*/
static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
{
+ struct sja1105_l2_lookup_params_entry *l2_lookup_params;
struct sja1105_general_params_entry *general_params;
struct sja1105_private *priv = ds->priv;
struct sja1105_table *table;
@@ -1622,6 +1573,28 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
general_params->incl_srcpt1 = enabled;
general_params->incl_srcpt0 = enabled;
+ /* VLAN filtering => independent VLAN learning.
+ * No VLAN filtering => shared VLAN learning.
+ *
+ * In shared VLAN learning mode, untagged traffic still gets
+ * pvid-tagged, and the FDB table gets populated with entries
+ * containing the "real" (pvid or from VLAN tag) VLAN ID.
+ * However the switch performs a masked L2 lookup in the FDB,
+ * effectively only looking up a frame's DMAC (and not VID) for the
+ * forwarding decision.
+ *
+ * This is extremely convenient for us, because in modes with
+ * vlan_filtering=0, dsa_8021q actually installs unique pvid's into
+ * each front panel port. This is good for identification but breaks
+ * learning badly - the VID of the learnt FDB entry is unique, aka
+ * no frames coming from any other port are going to have it. So
+ * for forwarding purposes, this is as though learning was broken
+ * (all frames get flooded).
+ */
+ table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS];
+ l2_lookup_params = table->entries;
+ l2_lookup_params->shared_learn = !enabled;
+
rc = sja1105_static_config_reload(priv);
if (rc)
dev_err(ds->dev, "Failed to change VLAN Ethertype\n");
@@ -1751,6 +1724,8 @@ static void sja1105_teardown(struct dsa_switch *ds)
cancel_work_sync(&priv->tagger_data.rxtstamp_work);
skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue);
+ sja1105_ptp_clock_unregister(priv);
+ sja1105_static_config_free(&priv->static_config);
}
static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
@@ -2208,9 +2183,7 @@ static int sja1105_remove(struct spi_device *spi)
{
struct sja1105_private *priv = spi_get_drvdata(spi);
- sja1105_ptp_clock_unregister(priv);
dsa_unregister_switch(priv->ds);
- sja1105_static_config_free(&priv->static_config);
return 0;
}
diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c
index d19cfdf681af..d8e8dd59f3d1 100644
--- a/drivers/net/dsa/sja1105/sja1105_ptp.c
+++ b/drivers/net/dsa/sja1105/sja1105_ptp.c
@@ -369,16 +369,15 @@ int sja1105_ptp_clock_register(struct sja1105_private *priv)
.mult = SJA1105_CC_MULT,
};
mutex_init(&priv->ptp_lock);
- INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
-
- schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
-
priv->ptp_caps = sja1105_ptp_caps;
priv->clock = ptp_clock_register(&priv->ptp_caps, ds->dev);
if (IS_ERR_OR_NULL(priv->clock))
return PTR_ERR(priv->clock);
+ INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
+ schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
+
return sja1105_ptp_reset(priv);
}
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index 2a3e2450968e..a9478577b495 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -12,8 +12,8 @@ config NET_VENDOR_8390
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
- the questions about Western Digital cards. If you say Y, you will be
- asked for your specific card in the following questions.
+ the questions about National Semiconductor 8390 cards. If you say Y,
+ you will be asked for your specific card in the following questions.
if NET_VENDOR_8390
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 93a2d4deb27c..dc9dee55976b 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -151,7 +151,6 @@ config NET_NETX
To compile this driver as a module, choose M here. The module
will be called netx-eth.
-source "drivers/net/ethernet/nuvoton/Kconfig"
source "drivers/net/ethernet/nvidia/Kconfig"
source "drivers/net/ethernet/nxp/Kconfig"
source "drivers/net/ethernet/oki-semi/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index fb9155cffcff..4bc3c95562bf 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -65,7 +65,6 @@ obj-$(CONFIG_NET_VENDOR_NETERION) += neterion/
obj-$(CONFIG_NET_VENDOR_NETRONOME) += netronome/
obj-$(CONFIG_NET_VENDOR_NI) += ni/
obj-$(CONFIG_NET_NETX) += netx-eth.o
-obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/
obj-$(CONFIG_LPC_ENET) += nxp/
obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/
diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c
index ea34bcb868b5..edbb4b3604c7 100644
--- a/drivers/net/ethernet/agere/et131x.c
+++ b/drivers/net/ethernet/agere/et131x.c
@@ -2362,7 +2362,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
/* Allocate memory for the TCB's (Transmit Control Block) */
tx_ring->tcb_ring = kcalloc(NUM_TCB, sizeof(struct tcb),
- GFP_ATOMIC | GFP_DMA);
+ GFP_KERNEL | GFP_DMA);
if (!tx_ring->tcb_ring)
return -ENOMEM;
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index 3434730a7699..0537df06a9b5 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -860,7 +860,9 @@ static int emac_probe(struct platform_device *pdev)
goto out_clk_disable_unprepare;
}
- db->phy_node = of_parse_phandle(np, "phy", 0);
+ db->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (!db->phy_node)
+ db->phy_node = of_parse_phandle(np, "phy", 0);
if (!db->phy_node) {
dev_err(&pdev->dev, "no associated PHY\n");
ret = -ENODEV;
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index de4950d2022e..9f965cdfff5c 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -14,7 +14,7 @@ config NET_VENDOR_AMD
say Y.
Note that the answer to this question does not directly affect
- the kernel: saying N will just case the configurator to skip all
+ the kernel: saying N will just cause the configurator to skip all
the questions regarding AMD chipsets. If you say Y, you will be asked
for your specific chipset/driver in the following questions.
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index b41f23679a08..7ce9c69e9c44 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -469,13 +469,19 @@ static int __init xgbe_mod_init(void)
ret = xgbe_platform_init();
if (ret)
- return ret;
+ goto err_platform_init;
ret = xgbe_pci_init();
if (ret)
- return ret;
+ goto err_pci_init;
return 0;
+
+err_pci_init:
+ xgbe_platform_exit();
+err_platform_init:
+ unregister_netdevice_notifier(&xgbe_netdev_notifier);
+ return ret;
}
static void __exit xgbe_mod_exit(void)
diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig
index fde7ae33e302..f78b9c841296 100644
--- a/drivers/net/ethernet/apple/Kconfig
+++ b/drivers/net/ethernet/apple/Kconfig
@@ -11,8 +11,8 @@ config NET_VENDOR_APPLE
If you have a network (Ethernet) card belonging to this class, say Y.
Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about IBM devices. If you say Y, you will be asked for
+ kernel: saying N will just cause the configurator to skip all the
+ questions about Apple devices. If you say Y, you will be asked for
your specific card in the following questions.
if NET_VENDOR_APPLE
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
index 440690b18734..aee827f07c16 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
@@ -431,7 +431,8 @@ int aq_del_fvlan_by_vlan(struct aq_nic_s *aq_nic, u16 vlan_id)
if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id)
break;
}
- if (rule && be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
+ if (rule && rule->type == aq_rx_filter_vlan &&
+ be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
struct ethtool_rxnfc cmd;
cmd.fs.location = rule->aq_fsp.location;
@@ -843,7 +844,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
return err;
if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
- if (hweight < AQ_VLAN_MAX_FILTERS && hweight > 0) {
+ if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) {
err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
!(aq_nic->packet_filter & IFF_PROMISC));
aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index 100722ad5c2d..b4a0fb281e69 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -61,6 +61,10 @@ static int aq_ndev_open(struct net_device *ndev)
if (err < 0)
goto err_exit;
+ err = aq_filters_vlans_update(aq_nic);
+ if (err < 0)
+ goto err_exit;
+
err = aq_nic_start(aq_nic);
if (err < 0)
goto err_exit;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index e1392766e21e..8f66e7817811 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -393,7 +393,7 @@ int aq_nic_start(struct aq_nic_s *self)
self->aq_nic_cfg.link_irq_vec);
err = request_threaded_irq(irqvec, NULL,
aq_linkstate_threaded_isr,
- IRQF_SHARED,
+ IRQF_SHARED | IRQF_ONESHOT,
self->ndev->name, self);
if (err < 0)
goto err_exit;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
index 715685aa48c3..28892b8acd0e 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -86,6 +86,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
}
}
+err_exit:
if (!was_tx_cleaned)
work_done = budget;
@@ -95,7 +96,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
1U << self->aq_ring_param.vec_idx);
}
}
-err_exit:
+
return work_done;
}
diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c
index 8b69d0d7e726..6703960c7cf5 100644
--- a/drivers/net/ethernet/atheros/ag71xx.c
+++ b/drivers/net/ethernet/atheros/ag71xx.c
@@ -1141,7 +1141,7 @@ static int ag71xx_rings_init(struct ag71xx *ag)
tx->descs_cpu = dma_alloc_coherent(&ag->pdev->dev,
ring_size * AG71XX_DESC_SIZE,
- &tx->descs_dma, GFP_ATOMIC);
+ &tx->descs_dma, GFP_KERNEL);
if (!tx->descs_cpu) {
kfree(tx->buf);
tx->buf = NULL;
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index e9017caf024d..e24f5d2b6afe 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -14,9 +14,9 @@ config NET_VENDOR_BROADCOM
say Y.
Note that the answer to this question does not directly affect
- the kernel: saying N will just case the configurator to skip all
- the questions regarding AMD chipsets. If you say Y, you will be asked
- for your specific chipset/driver in the following questions.
+ the kernel: saying N will just cause the configurator to skip all
+ the questions regarding Broadcom chipsets. If you say Y, you will
+ be asked for your specific chipset/driver in the following questions.
if NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index b9c5cea8db16..9483553ce444 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -992,7 +992,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
{
struct bcm_sysport_priv *priv =
container_of(napi, struct bcm_sysport_priv, napi);
- struct dim_sample dim_sample;
+ struct dim_sample dim_sample = {};
unsigned int work_done = 0;
work_done = bcm_sysport_desc_rx(priv, budget);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e2be5a685130..d10b421ed1f1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1934,8 +1934,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
}
/* select a non-FCoE queue */
- return netdev_pick_tx(dev, skb, NULL) %
- (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
+ return netdev_pick_tx(dev, skb, NULL) % (BNX2X_NUM_ETH_QUEUES(bp));
}
void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3058,12 +3057,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
/* if VF indicate to PF this function is going down (PF will delete sp
* elements and clear initializations
*/
- if (IS_VF(bp))
+ if (IS_VF(bp)) {
+ bnx2x_clear_vlan_info(bp);
bnx2x_vfpf_close_vf(bp);
- else if (unload_mode != UNLOAD_RECOVERY)
+ } else if (unload_mode != UNLOAD_RECOVERY) {
/* if this is a normal/close unload need to clean up chip*/
bnx2x_chip_cleanup(bp, unload_mode, keep_link);
- else {
+ } else {
/* Send the UNLOAD_REQUEST to the MCP */
bnx2x_send_unload_req(bp, unload_mode);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index c2f6e44e9a3f..8b08cb18e363 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -425,6 +425,8 @@ void bnx2x_set_reset_global(struct bnx2x *bp);
void bnx2x_disable_close_the_gate(struct bnx2x *bp);
int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
+void bnx2x_clear_vlan_info(struct bnx2x *bp);
+
/**
* bnx2x_sp_event - handle ramrods completion.
*
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 2cc14db8f0ec..192ff8d5da32 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -8482,11 +8482,21 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
return rc;
}
+void bnx2x_clear_vlan_info(struct bnx2x *bp)
+{
+ struct bnx2x_vlan_entry *vlan;
+
+ /* Mark that hw forgot all entries */
+ list_for_each_entry(vlan, &bp->vlan_reg, link)
+ vlan->hw = false;
+
+ bp->vlan_cnt = 0;
+}
+
static int bnx2x_del_all_vlans(struct bnx2x *bp)
{
struct bnx2x_vlan_mac_obj *vlan_obj = &bp->sp_objs[0].vlan_obj;
unsigned long ramrod_flags = 0, vlan_flags = 0;
- struct bnx2x_vlan_entry *vlan;
int rc;
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
@@ -8495,10 +8505,7 @@ static int bnx2x_del_all_vlans(struct bnx2x *bp)
if (rc)
return rc;
- /* Mark that hw forgot all entries */
- list_for_each_entry(vlan, &bp->vlan_reg, link)
- vlan->hw = false;
- bp->vlan_cnt = 0;
+ bnx2x_clear_vlan_info(bp);
return 0;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 7134d2c3eb1c..8dce4069472b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2021,9 +2021,9 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
if (bnapi->events & BNXT_RX_EVENT) {
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
- bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
if (bnapi->events & BNXT_AGG_EVENT)
bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+ bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
}
bnapi->events = 0;
}
@@ -2136,7 +2136,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
}
}
if (bp->flags & BNXT_FLAG_DIM) {
- struct dim_sample dim_sample;
+ struct dim_sample dim_sample = {};
dim_update_sample(cpr->event_ctr,
cpr->rx_packets,
@@ -5064,6 +5064,7 @@ static void bnxt_set_db(struct bnxt *bp, struct bnxt_db_info *db, u32 ring_type,
static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
{
+ bool agg_rings = !!(bp->flags & BNXT_FLAG_AGG_RINGS);
int i, rc = 0;
u32 type;
@@ -5139,7 +5140,9 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
if (rc)
goto err_out;
bnxt_set_db(bp, &rxr->rx_db, type, map_idx, ring->fw_ring_id);
- bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
+ /* If we have agg rings, post agg buffers first. */
+ if (!agg_rings)
+ bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
if (bp->flags & BNXT_FLAG_CHIP_P5) {
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
@@ -5158,7 +5161,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
}
}
- if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+ if (agg_rings) {
type = HWRM_RING_ALLOC_AGG;
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -5174,6 +5177,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
bnxt_set_db(bp, &rxr->rx_agg_db, type, map_idx,
ring->fw_ring_id);
bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+ bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
bp->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
}
}
@@ -7016,19 +7020,29 @@ static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp)
bnxt_hwrm_vnic_set_rss(bp, i, false);
}
-static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
- bool irq_re_init)
+static void bnxt_clear_vnic(struct bnxt *bp)
{
- if (bp->vnic_info) {
- bnxt_hwrm_clear_vnic_filter(bp);
+ if (!bp->vnic_info)
+ return;
+
+ bnxt_hwrm_clear_vnic_filter(bp);
+ if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
/* clear all RSS setting before free vnic ctx */
bnxt_hwrm_clear_vnic_rss(bp);
bnxt_hwrm_vnic_ctx_free(bp);
- /* before free the vnic, undo the vnic tpa settings */
- if (bp->flags & BNXT_FLAG_TPA)
- bnxt_set_tpa(bp, false);
- bnxt_hwrm_vnic_free(bp);
}
+ /* before free the vnic, undo the vnic tpa settings */
+ if (bp->flags & BNXT_FLAG_TPA)
+ bnxt_set_tpa(bp, false);
+ bnxt_hwrm_vnic_free(bp);
+ if (bp->flags & BNXT_FLAG_CHIP_P5)
+ bnxt_hwrm_vnic_ctx_free(bp);
+}
+
+static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
+ bool irq_re_init)
+{
+ bnxt_clear_vnic(bp);
bnxt_hwrm_ring_free(bp, close_path);
bnxt_hwrm_ring_grp_free(bp);
if (irq_re_init) {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 549c90d3e465..c05d663212b2 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -98,10 +98,13 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
if (idx)
req->dimensions = cpu_to_le16(1);
- if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE))
+ if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
memcpy(data_addr, buf, bytesize);
-
- rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+ rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+ } else {
+ rc = hwrm_send_message_silent(bp, msg, msg_len,
+ HWRM_CMD_TIMEOUT);
+ }
if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE))
memcpy(buf, data_addr, bytesize);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index c7ee63d69679..8445a0cce849 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2016,21 +2016,19 @@ static int bnxt_flash_package_from_file(struct net_device *dev,
mutex_lock(&bp->hwrm_cmd_lock);
hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
- if (hwrm_err)
- goto flash_pkg_exit;
-
- if (resp->error_code) {
+ if (hwrm_err) {
u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
- if (error_code == NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
+ if (resp->error_code && error_code ==
+ NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
install.flags |= cpu_to_le16(
NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
hwrm_err = _hwrm_send_message(bp, &install,
sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
- if (hwrm_err)
- goto flash_pkg_exit;
}
+ if (hwrm_err)
+ goto flash_pkg_exit;
}
if (resp->result) {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 6fe4a7174271..dd621f6bd127 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -1236,7 +1236,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
static void bnxt_tc_set_flow_dir(struct bnxt *bp, struct bnxt_tc_flow *flow,
u16 src_fid)
{
- flow->dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
+ flow->l2_key.dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
}
static void bnxt_tc_set_src_fid(struct bnxt *bp, struct bnxt_tc_flow *flow,
@@ -1285,9 +1285,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
goto free_node;
bnxt_tc_set_src_fid(bp, flow, src_fid);
-
- if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
- bnxt_tc_set_flow_dir(bp, flow, src_fid);
+ bnxt_tc_set_flow_dir(bp, flow, flow->src_fid);
if (!bnxt_tc_can_offload(bp, flow)) {
rc = -EOPNOTSUPP;
@@ -1407,7 +1405,7 @@ static void bnxt_fill_cfa_stats_req(struct bnxt *bp,
* 2. 15th bit of flow_handle must specify the flow
* direction (TX/RX).
*/
- if (flow_node->flow.dir == BNXT_DIR_RX)
+ if (flow_node->flow.l2_key.dir == BNXT_DIR_RX)
handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_DIR_RX |
CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
else
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
index ffec57d1a5ec..4f05305052f2 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
@@ -23,6 +23,9 @@ struct bnxt_tc_l2_key {
__be16 inner_vlan_tci;
__be16 ether_type;
u8 num_vlans;
+ u8 dir;
+#define BNXT_DIR_RX 1
+#define BNXT_DIR_TX 0
};
struct bnxt_tc_l3_key {
@@ -98,9 +101,6 @@ struct bnxt_tc_flow {
/* flow applicable to pkts ingressing on this fid */
u16 src_fid;
- u8 dir;
-#define BNXT_DIR_RX 1
-#define BNXT_DIR_TX 0
struct bnxt_tc_l2_key l2_key;
struct bnxt_tc_l2_key l2_mask;
struct bnxt_tc_l3_key l3_key;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index a2b57807453b..b22196880d6d 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1124,6 +1124,7 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
.set_coalesce = bcmgenet_set_coalesce,
.get_link_ksettings = bcmgenet_get_link_ksettings,
.set_link_ksettings = bcmgenet_set_link_ksettings,
+ .get_ts_info = ethtool_op_get_ts_info,
};
/* Power down the unimac, based on mode. */
@@ -1895,7 +1896,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
{
struct bcmgenet_rx_ring *ring = container_of(napi,
struct bcmgenet_rx_ring, napi);
- struct dim_sample dim_sample;
+ struct dim_sample dim_sample = {};
unsigned int work_done;
work_done = bcmgenet_desc_rx(ring, budget);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 5ca17e62dc3e..35b59b5edf0f 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4154,7 +4154,7 @@ static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,emac", .data = &emac_config },
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
- { .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
+ { .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
index 73632b843749..b821c9e1604c 100644
--- a/drivers/net/ethernet/cavium/common/cavium_ptp.c
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -10,7 +10,7 @@
#include "cavium_ptp.h"
-#define DRV_NAME "Cavium PTP Driver"
+#define DRV_NAME "cavium_ptp"
#define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C
#define PCI_DEVICE_ID_CAVIUM_RST 0xA00E
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 032224178b64..6dd65f9b347c 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -237,8 +237,10 @@ int octeon_setup_iq(struct octeon_device *oct,
}
oct->num_iqs++;
- if (oct->fn_list.enable_io_queues(oct))
+ if (oct->fn_list.enable_io_queues(oct)) {
+ octeon_delete_instr_queue(oct, iq_no);
return 1;
+ }
return 0;
}
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index ad22554857bf..acb016834f04 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1381,24 +1381,18 @@ static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev,
u8 *dst)
{
u8 mac[ETH_ALEN];
- int ret;
+ u8 *addr;
- ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
- "mac-address", mac, ETH_ALEN);
- if (ret)
- goto out;
-
- if (!is_valid_ether_addr(mac)) {
+ addr = fwnode_get_mac_address(acpi_fwnode_handle(adev), mac, ETH_ALEN);
+ if (!addr) {
dev_err(dev, "MAC address invalid: %pM\n", mac);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
dev_info(dev, "MAC address set to: %pM\n", mac);
- memcpy(dst, mac, ETH_ALEN);
-out:
- return ret;
+ ether_addr_copy(dst, mac);
+ return 0;
}
/* Currently only sets the MAC address. */
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 1e82b9efe447..58f89f6a040f 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3269,7 +3269,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!adapter->regs) {
dev_err(&pdev->dev, "cannot map device registers\n");
err = -ENOMEM;
- goto out_free_adapter;
+ goto out_free_adapter_nofail;
}
adapter->pdev = pdev;
@@ -3397,6 +3397,9 @@ out_free_dev:
if (adapter->port[i])
free_netdev(adapter->port[i]);
+out_free_adapter_nofail:
+ kfree_skb(adapter->nofail_skb);
+
out_free_adapter:
kfree(adapter);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 02959035ed3f..d692251ee252 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -3236,8 +3236,10 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
return -ENOMEM;
err = bitmap_parse_user(ubuf, count, t, adap->sge.egr_sz);
- if (err)
+ if (err) {
+ kvfree(t);
return err;
+ }
bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
kvfree(t);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index ef5d61d57597..323976c811e9 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -550,7 +550,7 @@ int be_process_mcc(struct be_adapter *adapter)
int num = 0, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
- spin_lock(&adapter->mcc_cq_lock);
+ spin_lock_bh(&adapter->mcc_cq_lock);
while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
@@ -566,7 +566,7 @@ int be_process_mcc(struct be_adapter *adapter)
if (num)
be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
- spin_unlock(&adapter->mcc_cq_lock);
+ spin_unlock_bh(&adapter->mcc_cq_lock);
return status;
}
@@ -581,9 +581,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
if (be_check_error(adapter, BE_ERROR_ANY))
return -EIO;
- local_bh_disable();
status = be_process_mcc(adapter);
- local_bh_enable();
if (atomic_read(&mcc_obj->q.used) == 0)
break;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 2edb86ec9fe9..4d8e40ac66d2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5630,9 +5630,7 @@ static void be_worker(struct work_struct *work)
* mcc completions
*/
if (!netif_running(adapter->netdev)) {
- local_bh_disable();
be_process_mcc(adapter);
- local_bh_enable();
goto reschedule;
}
diff --git a/drivers/net/ethernet/ezchip/nps_enet.h b/drivers/net/ethernet/ezchip/nps_enet.h
index 133acca0bf31..092da2d90026 100644
--- a/drivers/net/ethernet/ezchip/nps_enet.h
+++ b/drivers/net/ethernet/ezchip/nps_enet.h
@@ -167,7 +167,7 @@ struct nps_enet_priv {
};
/**
- * nps_reg_set - Sets ENET register with provided value.
+ * nps_enet_reg_set - Sets ENET register with provided value.
* @priv: Pointer to EZchip ENET private data structure.
* @reg: Register offset from base address.
* @value: Value to set in register.
@@ -179,7 +179,7 @@ static inline void nps_enet_reg_set(struct nps_enet_priv *priv,
}
/**
- * nps_reg_get - Gets value of specified ENET register.
+ * nps_enet_reg_get - Gets value of specified ENET register.
* @priv: Pointer to EZchip ENET private data structure.
* @reg: Register offset from base address.
*
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index ed0d010c7cf2..04a59db03f2b 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -2,6 +2,7 @@
config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+ select PHYLIB
help
This driver supports NXP ENETC gigabit ethernet controller PCIe
physical function (PF) devices, managing ENETC Ports at a privileged
@@ -12,6 +13,7 @@ config FSL_ENETC
config FSL_ENETC_VF
tristate "ENETC VF driver"
depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+ select PHYLIB
help
This driver supports NXP ENETC gigabit ethernet controller PCIe
virtual function (VF) devices enabled by the ENETC PF driver.
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
index 2fd2586e42bf..bc594892507a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
@@ -82,7 +82,7 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
if (n != 1) {
err = -EPERM;
- goto err_irq;
+ goto err_irq_vectors;
}
ptp_qoriq->irq = pci_irq_vector(pdev, 0);
@@ -107,6 +107,8 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
err_no_clock:
free_irq(ptp_qoriq->irq, ptp_qoriq);
err_irq:
+ pci_free_irq_vectors(pdev);
+err_irq_vectors:
iounmap(base);
err_ioremap:
kfree(ptp_qoriq);
@@ -125,6 +127,7 @@ static void enetc_ptp_remove(struct pci_dev *pdev)
enetc_phc_index = -1;
ptp_qoriq_free(ptp_qoriq);
+ pci_free_irq_vectors(pdev);
kfree(ptp_qoriq);
pci_release_mem_regions(pdev);
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index e80fedb27cee..210749bf1eac 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -2439,9 +2439,6 @@ MODULE_PARM_DESC(fsl_fm_rx_extra_headroom, "Extra headroom for Rx buffers");
* buffers when not using jumbo frames.
* Must be large enough to accommodate the network MTU, but small enough
* to avoid wasting skb memory.
- *
- * Could be overridden once, at boot-time, via the
- * fm_set_max_frm() callback.
*/
static int fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE;
module_param(fsl_fm_max_frm, int, 0);
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 92372dc43be8..ebc37e256922 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -31,9 +31,6 @@
struct gve_rx_desc_queue {
struct gve_rx_desc *desc_ring; /* the descriptor ring */
dma_addr_t bus; /* the bus for the desc_ring */
- u32 cnt; /* free-running total number of completed packets */
- u32 fill_cnt; /* free-running total number of descriptors posted */
- u32 mask; /* masks the cnt to the size of the ring */
u8 seqno; /* the next expected seqno for this desc*/
};
@@ -60,8 +57,6 @@ struct gve_rx_data_queue {
dma_addr_t data_bus; /* dma mapping of the slots */
struct gve_rx_slot_page_info *page_info; /* page info of the buffers */
struct gve_queue_page_list *qpl; /* qpl assigned to this queue */
- u32 mask; /* masks the cnt to the size of the ring */
- u32 cnt; /* free-running total number of completed packets */
};
struct gve_priv;
@@ -73,6 +68,9 @@ struct gve_rx_ring {
struct gve_rx_data_queue data;
u64 rbytes; /* free-running bytes received */
u64 rpackets; /* free-running packets received */
+ u32 cnt; /* free-running total number of completed packets */
+ u32 fill_cnt; /* free-running total number of descs and buffs posted */
+ u32 mask; /* masks the cnt and fill_cnt to the size of the ring */
u32 q_num; /* queue index */
u32 ntfy_id; /* notification block index */
struct gve_queue_resources *q_resources; /* head and tail pointer idx */
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index 26540b856541..d8fa816f4473 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -138,8 +138,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
struct gve_rx_ring *rx = &priv->rx[ring];
- data[i++] = rx->desc.cnt;
- data[i++] = rx->desc.fill_cnt;
+ data[i++] = rx->cnt;
+ data[i++] = rx->fill_cnt;
}
} else {
i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 497298752381..aca95f64bde8 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -50,7 +50,7 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
u64_stats_fetch_begin(&priv->tx[ring].statss);
s->tx_packets += priv->tx[ring].pkt_done;
s->tx_bytes += priv->tx[ring].bytes_done;
- } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+ } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
start));
}
}
diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c
index 1914b8350da7..59564ac99d2a 100644
--- a/drivers/net/ethernet/google/gve/gve_rx.c
+++ b/drivers/net/ethernet/google/gve/gve_rx.c
@@ -37,7 +37,7 @@ static void gve_rx_free_ring(struct gve_priv *priv, int idx)
rx->data.qpl = NULL;
kvfree(rx->data.page_info);
- slots = rx->data.mask + 1;
+ slots = rx->mask + 1;
bytes = sizeof(*rx->data.data_ring) * slots;
dma_free_coherent(dev, bytes, rx->data.data_ring,
rx->data.data_bus);
@@ -64,7 +64,7 @@ static int gve_prefill_rx_pages(struct gve_rx_ring *rx)
/* Allocate one page per Rx queue slot. Each page is split into two
* packet buffers, when possible we "page flip" between the two.
*/
- slots = rx->data.mask + 1;
+ slots = rx->mask + 1;
rx->data.page_info = kvzalloc(slots *
sizeof(*rx->data.page_info), GFP_KERNEL);
@@ -111,7 +111,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
rx->q_num = idx;
slots = priv->rx_pages_per_qpl;
- rx->data.mask = slots - 1;
+ rx->mask = slots - 1;
/* alloc rx data ring */
bytes = sizeof(*rx->data.data_ring) * slots;
@@ -125,7 +125,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
err = -ENOMEM;
goto abort_with_slots;
}
- rx->desc.fill_cnt = filled_pages;
+ rx->fill_cnt = filled_pages;
/* Ensure data ring slots (packet buffers) are visible. */
dma_wmb();
@@ -156,8 +156,8 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
err = -ENOMEM;
goto abort_with_q_resources;
}
- rx->desc.mask = slots - 1;
- rx->desc.cnt = 0;
+ rx->mask = slots - 1;
+ rx->cnt = 0;
rx->desc.seqno = 1;
gve_rx_add_to_block(priv, idx);
@@ -213,7 +213,7 @@ void gve_rx_write_doorbell(struct gve_priv *priv, struct gve_rx_ring *rx)
{
u32 db_idx = be32_to_cpu(rx->q_resources->db_index);
- iowrite32be(rx->desc.fill_cnt, &priv->db_bar2[db_idx]);
+ iowrite32be(rx->fill_cnt, &priv->db_bar2[db_idx]);
}
static enum pkt_hash_types gve_rss_type(__be16 pkt_flags)
@@ -273,7 +273,7 @@ static void gve_rx_flip_buff(struct gve_rx_slot_page_info *page_info,
}
static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
- netdev_features_t feat)
+ netdev_features_t feat, u32 idx)
{
struct gve_rx_slot_page_info *page_info;
struct gve_priv *priv = rx->gve;
@@ -282,14 +282,12 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
struct sk_buff *skb;
int pagecount;
u16 len;
- u32 idx;
/* drop this packet */
if (unlikely(rx_desc->flags_seq & GVE_RXF_ERR))
return true;
len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD;
- idx = rx->data.cnt & rx->data.mask;
page_info = &rx->data.page_info[idx];
/* gvnic can only receive into registered segments. If the buffer
@@ -340,8 +338,6 @@ have_skb:
if (!skb)
return true;
- rx->data.cnt++;
-
if (likely(feat & NETIF_F_RXCSUM)) {
/* NIC passes up the partial sum */
if (rx_desc->csum)
@@ -370,7 +366,7 @@ static bool gve_rx_work_pending(struct gve_rx_ring *rx)
__be16 flags_seq;
u32 next_idx;
- next_idx = rx->desc.cnt & rx->desc.mask;
+ next_idx = rx->cnt & rx->mask;
desc = rx->desc.desc_ring + next_idx;
flags_seq = desc->flags_seq;
@@ -385,8 +381,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
{
struct gve_priv *priv = rx->gve;
struct gve_rx_desc *desc;
- u32 cnt = rx->desc.cnt;
- u32 idx = cnt & rx->desc.mask;
+ u32 cnt = rx->cnt;
+ u32 idx = cnt & rx->mask;
u32 work_done = 0;
u64 bytes = 0;
@@ -401,10 +397,10 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
rx->q_num, GVE_SEQNO(desc->flags_seq),
rx->desc.seqno);
bytes += be16_to_cpu(desc->len) - GVE_RX_PAD;
- if (!gve_rx(rx, desc, feat))
+ if (!gve_rx(rx, desc, feat, idx))
gve_schedule_reset(priv);
cnt++;
- idx = cnt & rx->desc.mask;
+ idx = cnt & rx->mask;
desc = rx->desc.desc_ring + idx;
rx->desc.seqno = gve_next_seqno(rx->desc.seqno);
work_done++;
@@ -417,8 +413,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
rx->rpackets += work_done;
rx->rbytes += bytes;
u64_stats_update_end(&rx->statss);
- rx->desc.cnt = cnt;
- rx->desc.fill_cnt += work_done;
+ rx->cnt = cnt;
+ rx->fill_cnt += work_done;
/* restock desc ring slots */
dma_wmb(); /* Ensure descs are visible before ringing doorbell */
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index d60452845539..c84167447abe 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -220,6 +220,7 @@ struct hip04_priv {
unsigned int reg_inten;
struct napi_struct napi;
+ struct device *dev;
struct net_device *ndev;
struct tx_desc *tx_desc;
@@ -248,7 +249,7 @@ struct hip04_priv {
static inline unsigned int tx_count(unsigned int head, unsigned int tail)
{
- return (head - tail) % (TX_DESC_NUM - 1);
+ return (head - tail) % TX_DESC_NUM;
}
static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
@@ -465,7 +466,7 @@ static int hip04_tx_reclaim(struct net_device *ndev, bool force)
}
if (priv->tx_phys[tx_tail]) {
- dma_unmap_single(&ndev->dev, priv->tx_phys[tx_tail],
+ dma_unmap_single(priv->dev, priv->tx_phys[tx_tail],
priv->tx_skb[tx_tail]->len,
DMA_TO_DEVICE);
priv->tx_phys[tx_tail] = 0;
@@ -516,8 +517,8 @@ hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_BUSY;
}
- phys = dma_map_single(&ndev->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&ndev->dev, phys)) {
+ phys = dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(priv->dev, phys)) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -585,6 +586,9 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
u16 len;
u32 err;
+ /* clean up tx descriptors */
+ tx_remaining = hip04_tx_reclaim(ndev, false);
+
while (cnt && !last) {
buf = priv->rx_buf[priv->rx_head];
skb = build_skb(buf, priv->rx_buf_size);
@@ -593,7 +597,7 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
goto refill;
}
- dma_unmap_single(&ndev->dev, priv->rx_phys[priv->rx_head],
+ dma_unmap_single(priv->dev, priv->rx_phys[priv->rx_head],
RX_BUF_SIZE, DMA_FROM_DEVICE);
priv->rx_phys[priv->rx_head] = 0;
@@ -622,9 +626,9 @@ refill:
buf = netdev_alloc_frag(priv->rx_buf_size);
if (!buf)
goto done;
- phys = dma_map_single(&ndev->dev, buf,
+ phys = dma_map_single(priv->dev, buf,
RX_BUF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&ndev->dev, phys))
+ if (dma_mapping_error(priv->dev, phys))
goto done;
priv->rx_buf[priv->rx_head] = buf;
priv->rx_phys[priv->rx_head] = phys;
@@ -645,8 +649,7 @@ refill:
}
napi_complete_done(napi, rx);
done:
- /* clean up tx descriptors and start a new timer if necessary */
- tx_remaining = hip04_tx_reclaim(ndev, false);
+ /* start a new timer if necessary */
if (rx < budget && tx_remaining)
hip04_start_tx_timer(priv);
@@ -728,9 +731,9 @@ static int hip04_mac_open(struct net_device *ndev)
for (i = 0; i < RX_DESC_NUM; i++) {
dma_addr_t phys;
- phys = dma_map_single(&ndev->dev, priv->rx_buf[i],
+ phys = dma_map_single(priv->dev, priv->rx_buf[i],
RX_BUF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&ndev->dev, phys))
+ if (dma_mapping_error(priv->dev, phys))
return -EIO;
priv->rx_phys[i] = phys;
@@ -764,7 +767,7 @@ static int hip04_mac_stop(struct net_device *ndev)
for (i = 0; i < RX_DESC_NUM; i++) {
if (priv->rx_phys[i]) {
- dma_unmap_single(&ndev->dev, priv->rx_phys[i],
+ dma_unmap_single(priv->dev, priv->rx_phys[i],
RX_BUF_SIZE, DMA_FROM_DEVICE);
priv->rx_phys[i] = 0;
}
@@ -907,6 +910,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
return -ENOMEM;
priv = netdev_priv(ndev);
+ priv->dev = d;
priv->ndev = ndev;
platform_set_drvdata(pdev, ndev);
SET_NETDEV_DEV(ndev, &pdev->dev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
index 0a7243825e7b..85a3b062371d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -98,7 +98,7 @@ static const struct hclge_hw_error hclge_igu_egu_tnl_int[] = {
.reset_level = HNAE3_GLOBAL_RESET },
{ .int_msk = BIT(1), .msg = "rx_stp_fifo_overflow",
.reset_level = HNAE3_GLOBAL_RESET },
- { .int_msk = BIT(2), .msg = "rx_stp_fifo_undeflow",
+ { .int_msk = BIT(2), .msg = "rx_stp_fifo_underflow",
.reset_level = HNAE3_GLOBAL_RESET },
{ .int_msk = BIT(3), .msg = "tx_buf_overflow",
.reset_level = HNAE3_GLOBAL_RESET },
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 4138a8480347..cca71ba7a74a 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -3251,7 +3251,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
switch (action) {
case MEM_CANCEL_OFFLINE:
pr_info("memory offlining canceled");
- /* Fall through: re-add canceled memory block */
+ /* Fall through - re-add canceled memory block */
case MEM_ONLINE:
pr_info("memory is going online");
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index d654c234aaf7..c5be4ebd8437 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1605,7 +1605,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
struct net_device *netdev;
struct ibmveth_adapter *adapter;
unsigned char *mac_addr_p;
- unsigned int *mcastFilterSize_p;
+ __be32 *mcastFilterSize_p;
long ret;
unsigned long ret_attr;
@@ -1627,8 +1627,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
return -EINVAL;
}
- mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
- VETH_MCAST_FILTER_SIZE, NULL);
+ mcastFilterSize_p = (__be32 *)vio_get_attribute(dev,
+ VETH_MCAST_FILTER_SIZE,
+ NULL);
if (!mcastFilterSize_p) {
dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
"attribute\n");
@@ -1645,7 +1646,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
adapter->vdev = dev;
adapter->netdev = netdev;
- adapter->mcastFilterSize = *mcastFilterSize_p;
+ adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p);
adapter->pool_config = 0;
netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 3da680073265..5cb55ea671e3 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1568,6 +1568,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
(u64)tx_buff->indir_dma,
(u64)num_entries);
+ dma_unmap_single(dev, tx_buff->indir_dma,
+ sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
} else {
tx_buff->num_entries = num_entries;
lpar_rc = send_subcrq(adapter, handle_array[queue_num],
@@ -1981,6 +1983,13 @@ static void __ibmvnic_reset(struct work_struct *work)
rwi = get_next_rwi(adapter);
while (rwi) {
+ if (adapter->state == VNIC_REMOVING ||
+ adapter->state == VNIC_REMOVED) {
+ kfree(rwi);
+ rc = EBUSY;
+ break;
+ }
+
if (adapter->force_reset_recovery) {
adapter->force_reset_recovery = false;
rc = do_hard_reset(adapter, rwi, reset_state);
@@ -2788,7 +2797,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
union sub_crq *next;
int index;
int i, j;
- u8 *first;
restart_loop:
while (pending_scrq(adapter, scrq)) {
@@ -2818,14 +2826,6 @@ restart_loop:
txbuff->data_dma[j] = 0;
}
- /* if sub_crq was sent indirectly */
- first = &txbuff->indir_arr[0].generic.first;
- if (*first == IBMVNIC_CRQ_CMD) {
- dma_unmap_single(dev, txbuff->indir_dma,
- sizeof(txbuff->indir_arr),
- DMA_TO_DEVICE);
- *first = 0;
- }
if (txbuff->last_frag) {
dev_kfree_skb_any(txbuff->skb);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index cbaf712d6529..51c696b6bf64 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -36,6 +36,7 @@
#include <net/vxlan.h>
#include <net/mpls.h>
#include <net/xdp_sock.h>
+#include <net/xfrm.h>
#include "ixgbe.h"
#include "ixgbe_common.h"
@@ -2621,7 +2622,7 @@ adjust_by_size:
/* 16K ints/sec to 9.2K ints/sec */
avg_wire_size *= 15;
avg_wire_size += 11452;
- } else if (avg_wire_size <= 1980) {
+ } else if (avg_wire_size < 1968) {
/* 9.2K ints/sec to 8K ints/sec */
avg_wire_size *= 5;
avg_wire_size += 22420;
@@ -2654,6 +2655,8 @@ adjust_by_size:
case IXGBE_LINK_SPEED_2_5GB_FULL:
case IXGBE_LINK_SPEED_1GB_FULL:
case IXGBE_LINK_SPEED_10_FULL:
+ if (avg_wire_size > 8064)
+ avg_wire_size = 8064;
itr += DIV_ROUND_UP(avg_wire_size,
IXGBE_ITR_ADAPTIVE_MIN_INC * 64) *
IXGBE_ITR_ADAPTIVE_MIN_INC;
@@ -7897,11 +7900,8 @@ static void ixgbe_service_task(struct work_struct *work)
return;
}
if (ixgbe_check_fw_error(adapter)) {
- if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
- rtnl_lock();
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
unregister_netdev(adapter->netdev);
- rtnl_unlock();
- }
ixgbe_service_event_complete(adapter);
return;
}
@@ -8698,7 +8698,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
#endif /* IXGBE_FCOE */
#ifdef CONFIG_IXGBE_IPSEC
- if (secpath_exists(skb) &&
+ if (xfrm_offload(skb) &&
!ixgbe_ipsec_tx(tx_ring, first, &ipsec_tx))
goto out_drop;
#endif
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
index 6b609553329f..a3b6d8c89127 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
@@ -633,19 +633,17 @@ static void ixgbe_clean_xdp_tx_buffer(struct ixgbe_ring *tx_ring,
bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *tx_ring, int napi_budget)
{
+ u16 ntc = tx_ring->next_to_clean, ntu = tx_ring->next_to_use;
unsigned int total_packets = 0, total_bytes = 0;
- u32 i = tx_ring->next_to_clean, xsk_frames = 0;
- unsigned int budget = q_vector->tx.work_limit;
struct xdp_umem *umem = tx_ring->xsk_umem;
union ixgbe_adv_tx_desc *tx_desc;
struct ixgbe_tx_buffer *tx_bi;
- bool xmit_done;
+ u32 xsk_frames = 0;
- tx_bi = &tx_ring->tx_buffer_info[i];
- tx_desc = IXGBE_TX_DESC(tx_ring, i);
- i -= tx_ring->count;
+ tx_bi = &tx_ring->tx_buffer_info[ntc];
+ tx_desc = IXGBE_TX_DESC(tx_ring, ntc);
- do {
+ while (ntc != ntu) {
if (!(tx_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
break;
@@ -661,22 +659,18 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
tx_bi++;
tx_desc++;
- i++;
- if (unlikely(!i)) {
- i -= tx_ring->count;
+ ntc++;
+ if (unlikely(ntc == tx_ring->count)) {
+ ntc = 0;
tx_bi = tx_ring->tx_buffer_info;
tx_desc = IXGBE_TX_DESC(tx_ring, 0);
}
/* issue prefetch for next Tx descriptor */
prefetch(tx_desc);
+ }
- /* update budget accounting */
- budget--;
- } while (likely(budget));
-
- i += tx_ring->count;
- tx_ring->next_to_clean = i;
+ tx_ring->next_to_clean = ntc;
u64_stats_update_begin(&tx_ring->syncp);
tx_ring->stats.bytes += total_bytes;
@@ -688,8 +682,7 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
if (xsk_frames)
xsk_umem_complete_tx(umem, xsk_frames);
- xmit_done = ixgbe_xmit_zc(tx_ring, q_vector->tx.work_limit);
- return budget > 0 && xmit_done;
+ return ixgbe_xmit_zc(tx_ring, q_vector->tx.work_limit);
}
int ixgbe_xsk_async_xmit(struct net_device *dev, u32 qid)
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index d2b41f9f87f8..72872d6ca80c 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -30,6 +30,7 @@
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <linux/atomic.h>
+#include <net/xfrm.h>
#include "ixgbevf.h"
@@ -4161,7 +4162,7 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb,
first->protocol = vlan_get_protocol(skb);
#ifdef CONFIG_IXGBEVF_IPSEC
- if (secpath_exists(skb) && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
+ if (xfrm_offload(skb) && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
goto out_drop;
#endif
tso = ixgbevf_tso(tx_ring, first, &hdr_len, &ipsec_tx);
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index f660cc2b8258..0b9e851f3da4 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -319,20 +319,33 @@ static int orion_mdio_probe(struct platform_device *pdev)
init_waitqueue_head(&dev->smi_busy_wait);
- for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
- dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
- if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+ if (pdev->dev.of_node) {
+ for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+ dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
+ if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out_clk;
+ }
+ if (IS_ERR(dev->clk[i]))
+ break;
+ clk_prepare_enable(dev->clk[i]);
+ }
+
+ if (!IS_ERR(of_clk_get(pdev->dev.of_node,
+ ARRAY_SIZE(dev->clk))))
+ dev_warn(&pdev->dev,
+ "unsupported number of clocks, limiting to the first "
+ __stringify(ARRAY_SIZE(dev->clk)) "\n");
+ } else {
+ dev->clk[0] = clk_get(&pdev->dev, NULL);
+ if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto out_clk;
}
- if (IS_ERR(dev->clk[i]))
- break;
- clk_prepare_enable(dev->clk[i]);
+ if (!IS_ERR(dev->clk[0]))
+ clk_prepare_enable(dev->clk[0]);
}
- if (!IS_ERR(of_clk_get(pdev->dev.of_node, ARRAY_SIZE(dev->clk))))
- dev_warn(&pdev->dev, "unsupported number of clocks, limiting to the first "
- __stringify(ARRAY_SIZE(dev->clk)) "\n");
dev->err_interrupt = platform_get_irq(pdev, 0);
if (dev->err_interrupt > 0 &&
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index c51f1d5b550b..ccdd47f3b8fb 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -811,6 +811,26 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
return 0;
}
+static void mvpp2_set_hw_csum(struct mvpp2_port *port,
+ enum mvpp2_bm_pool_log_num new_long_pool)
+{
+ const netdev_features_t csums = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+ /* Update L4 checksum when jumbo enable/disable on port.
+ * Only port 0 supports hardware checksum offload due to
+ * the Tx FIFO size limitation.
+ * Also, don't set NETIF_F_HW_CSUM because L3_offset in TX descriptor
+ * has 7 bits, so the maximum L3 offset is 128.
+ */
+ if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
+ port->dev->features &= ~csums;
+ port->dev->hw_features &= ~csums;
+ } else {
+ port->dev->features |= csums;
+ port->dev->hw_features |= csums;
+ }
+}
+
static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
{
struct mvpp2_port *port = netdev_priv(dev);
@@ -843,15 +863,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
/* Add port to new short & long pool */
mvpp2_swf_bm_pool_init(port);
- /* Update L4 checksum when jumbo enable/disable on port */
- if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
- dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- dev->hw_features &= ~(NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM);
- } else {
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
- dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
- }
+ mvpp2_set_hw_csum(port, new_long_pool);
}
dev->mtu = mtu;
@@ -3700,6 +3712,7 @@ static int mvpp2_set_mac_address(struct net_device *dev, void *p)
static int mvpp2_change_mtu(struct net_device *dev, int mtu)
{
struct mvpp2_port *port = netdev_priv(dev);
+ bool running = netif_running(dev);
int err;
if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
@@ -3708,40 +3721,24 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
}
- if (!netif_running(dev)) {
- err = mvpp2_bm_update_mtu(dev, mtu);
- if (!err) {
- port->pkt_size = MVPP2_RX_PKT_SIZE(mtu);
- return 0;
- }
-
- /* Reconfigure BM to the original MTU */
- err = mvpp2_bm_update_mtu(dev, dev->mtu);
- if (err)
- goto log_error;
- }
-
- mvpp2_stop_dev(port);
+ if (running)
+ mvpp2_stop_dev(port);
err = mvpp2_bm_update_mtu(dev, mtu);
- if (!err) {
+ if (err) {
+ netdev_err(dev, "failed to change MTU\n");
+ /* Reconfigure BM to the original MTU */
+ mvpp2_bm_update_mtu(dev, dev->mtu);
+ } else {
port->pkt_size = MVPP2_RX_PKT_SIZE(mtu);
- goto out_start;
}
- /* Reconfigure BM to the original MTU */
- err = mvpp2_bm_update_mtu(dev, dev->mtu);
- if (err)
- goto log_error;
-
-out_start:
- mvpp2_start_dev(port);
- mvpp2_egress_enable(port);
- mvpp2_ingress_enable(port);
+ if (running) {
+ mvpp2_start_dev(port);
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+ }
- return 0;
-log_error:
- netdev_err(dev, "failed to change MTU\n");
return err;
}
@@ -4739,9 +4736,9 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
else
ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
- ctrl4 &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC;
- ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC |
- MVPP22_XLG_CTRL4_EN_IDLE_CHECK;
+ ctrl4 &= ~(MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
+ MVPP22_XLG_CTRL4_EN_IDLE_CHECK);
+ ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
if (old_ctrl0 != ctrl0)
writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
@@ -5208,10 +5205,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
dev->features |= NETIF_F_NTUPLE;
}
- if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
- dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- }
+ mvpp2_set_hw_csum(port, port->pool_long->id);
dev->vlan_features |= features;
dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
@@ -5759,9 +5753,6 @@ static int mvpp2_remove(struct platform_device *pdev)
mvpp2_dbgfs_cleanup(priv);
- flush_workqueue(priv->stats_queue);
- destroy_workqueue(priv->stats_queue);
-
fwnode_for_each_available_child_node(fwnode, port_fwnode) {
if (priv->port_list[i]) {
mutex_destroy(&priv->port_list[i]->gather_stats_lock);
@@ -5770,6 +5761,8 @@ static int mvpp2_remove(struct platform_device *pdev)
i++;
}
+ destroy_workqueue(priv->stats_queue);
+
for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index f518312ffe69..e0363870f3a5 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4924,6 +4924,20 @@ static const struct dmi_system_id msi_blacklist[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
},
},
+ {
+ .ident = "ASUS P6T",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P6T"),
+ },
+ },
+ {
+ .ident = "ASUS P6X",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P6X"),
+ },
+ },
{}
};
diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
index 263cd0909fe0..1f7fff81f24d 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -9,7 +9,6 @@ if NET_VENDOR_MEDIATEK
config NET_MEDIATEK_SOC
tristate "MediaTek SoC Gigabit Ethernet support"
- depends on NET_VENDOR_MEDIATEK
select PHYLIB
---help---
This driver supports the gigabit ethernet MACs in the
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 6c01314e87b0..db3552f2d087 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -1187,7 +1187,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, rss_map->indir_qp);
if (err) {
en_err(priv, "Failed to allocate RSS indirection QP\n");
- goto rss_err;
+ goto qp_alloc_err;
}
rss_map->indir_qp->event = mlx4_en_sqp_event;
@@ -1241,6 +1241,7 @@ indir_err:
MLX4_QP_STATE_RST, NULL, 0, 0, rss_map->indir_qp);
mlx4_qp_remove(mdev->dev, rss_map->indir_qp);
mlx4_qp_free(mdev->dev, rss_map->indir_qp);
+qp_alloc_err:
kfree(rss_map->indir_qp);
rss_map->indir_qp = NULL;
rss_err:
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 1f6e16d5ea6b..309470ec0219 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2240,7 +2240,7 @@ static int mlx4_validate_optimized_steering(struct mlx4_dev *dev)
for (i = 1; i <= dev->caps.num_ports; i++) {
if (mlx4_dev_port(dev, i, &port_cap)) {
mlx4_err(dev,
- "QUERY_DEV_CAP command failed, can't veify DMFS high rate steering.\n");
+ "QUERY_DEV_CAP command failed, can't verify DMFS high rate steering.\n");
} else if ((dev->caps.dmfs_high_steer_mode !=
MLX4_STEERING_DMFS_A0_DEFAULT) &&
(port_cap.dmfs_optimized_state ==
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
index 5bb6a26ea267..50862275544e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
@@ -213,7 +213,7 @@ void mlx5_unregister_device(struct mlx5_core_dev *dev)
struct mlx5_interface *intf;
mutex_lock(&mlx5_intf_mutex);
- list_for_each_entry(intf, &intf_list, list)
+ list_for_each_entry_reverse(intf, &intf_list, list)
mlx5_remove_device(intf, priv);
list_del(&priv->dev_list);
mutex_unlock(&mlx5_intf_mutex);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 79d93d6c7d7a..65bec19a438f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -159,7 +159,7 @@ do { \
enum mlx5e_rq_group {
MLX5E_RQ_GROUP_REGULAR,
MLX5E_RQ_GROUP_XSK,
- MLX5E_NUM_RQ_GROUPS /* Keep last. */
+#define MLX5E_NUM_RQ_GROUPS(g) (1 + MLX5E_RQ_GROUP_##g)
};
static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
@@ -182,18 +182,15 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
min_t(int, mlx5_comp_vectors_count(mdev), MLX5E_MAX_NUM_CHANNELS);
}
-/* Use this function to get max num channels after netdev was created */
-static inline int mlx5e_get_netdev_max_channels(struct net_device *netdev)
-{
- return min_t(unsigned int,
- netdev->num_rx_queues / MLX5E_NUM_RQ_GROUPS,
- netdev->num_tx_queues);
-}
-
struct mlx5e_tx_wqe {
struct mlx5_wqe_ctrl_seg ctrl;
- struct mlx5_wqe_eth_seg eth;
- struct mlx5_wqe_data_seg data[0];
+ union {
+ struct {
+ struct mlx5_wqe_eth_seg eth;
+ struct mlx5_wqe_data_seg data[0];
+ };
+ u8 tls_progress_params_ctx[0];
+ };
};
struct mlx5e_rx_wqe_ll {
@@ -830,6 +827,7 @@ struct mlx5e_priv {
struct net_device *netdev;
struct mlx5e_stats stats;
struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS];
+ u16 max_nch;
u8 max_opened_tc;
struct hwtstamp_config tstamp;
u16 q_counter;
@@ -871,6 +869,7 @@ struct mlx5e_profile {
mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
} rx_handlers;
int max_tc;
+ u8 rq_groups;
};
void mlx5e_build_ptys2ethtool_map(void);
@@ -1106,6 +1105,8 @@ u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv);
u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv);
int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
struct ethtool_ts_info *info);
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+ struct ethtool_flash *flash);
void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
struct ethtool_pauseparam *pauseparam);
int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
index bd882b5ee9a7..3a615d663d84 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
@@ -66,9 +66,10 @@ static inline void mlx5e_qid_get_ch_and_group(struct mlx5e_params *params,
*group = qid / nch;
}
-static inline bool mlx5e_qid_validate(struct mlx5e_params *params, u64 qid)
+static inline bool mlx5e_qid_validate(const struct mlx5e_profile *profile,
+ struct mlx5e_params *params, u64 qid)
{
- return qid < params->num_channels * MLX5E_NUM_RQ_GROUPS;
+ return qid < params->num_channels * profile->rq_groups;
}
/* Parameter calculations */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
index d5e5afbdca6d..f777994f3005 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -78,9 +78,10 @@ static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
};
static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
- const u32 **arr, u32 *size)
+ const u32 **arr, u32 *size,
+ bool force_legacy)
{
- bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+ bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
*size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
ARRAY_SIZE(mlx5e_link_speed);
@@ -152,7 +153,8 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
sizeof(out), MLX5_REG_PTYS, 0, 1);
}
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+ bool force_legacy)
{
unsigned long temp = eth_proto_oper;
const u32 *table;
@@ -160,7 +162,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
u32 max_size;
int i;
- mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
i = find_first_bit(&temp, max_size);
if (i < max_size)
speed = table[i];
@@ -170,6 +172,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
{
struct mlx5e_port_eth_proto eproto;
+ bool force_legacy = false;
bool ext;
int err;
@@ -177,8 +180,13 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
if (err)
goto out;
-
- *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
+ if (ext && !eproto.admin) {
+ force_legacy = true;
+ err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
+ if (err)
+ goto out;
+ }
+ *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy);
if (!(*speed))
err = -EINVAL;
@@ -201,7 +209,7 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
if (err)
return err;
- mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, false);
for (i = 0; i < max_size; ++i)
if (eproto.cap & MLX5E_PROT_MASK(i))
max_speed = max(max_speed, table[i]);
@@ -210,14 +218,15 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
return 0;
}
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+ bool force_legacy)
{
u32 link_modes = 0;
const u32 *table;
u32 max_size;
int i;
- mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
for (i = 0; i < max_size; ++i) {
if (table[i] == speed)
link_modes |= MLX5E_PROT_MASK(i);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
index 70f536ec51c4..4a7f4497692b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -48,10 +48,12 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
u8 *an_disable_cap, u8 *an_disable_admin);
int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
u32 proto_admin, bool ext);
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+ bool force_legacy);
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+ bool force_legacy);
int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
index f3d98748b211..c7f86453c638 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
@@ -76,26 +76,21 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
u8 state;
int err;
- if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
- return 0;
-
err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
if (err) {
netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
sq->sqn, err);
- return err;
+ goto out;
}
- if (state != MLX5_SQC_STATE_ERR) {
- netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
- return -EINVAL;
- }
+ if (state != MLX5_SQC_STATE_ERR)
+ goto out;
mlx5e_tx_disable_queue(sq->txq);
err = mlx5e_wait_for_sq_flush(sq);
if (err)
- return err;
+ goto out;
/* At this point, no new packets will arrive from the stack as TXQ is
* marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
@@ -104,13 +99,17 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
err = mlx5e_sq_to_ready(sq, state);
if (err)
- return err;
+ goto out;
mlx5e_reset_txqsq_cc_pc(sq);
sq->stats->recover++;
+ clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
mlx5e_activate_txqsq(sq);
return 0;
+out:
+ clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+ return err;
}
static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
index aaffa6f68dc0..7f78c004d12f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
@@ -143,7 +143,10 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
{
set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
/* TX queue is created active. */
+
+ spin_lock(&c->xskicosq_lock);
mlx5e_trigger_irq(&c->xskicosq);
+ spin_unlock(&c->xskicosq_lock);
}
void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
index 407da83474ef..b7298f9ee3d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
@@ -11,12 +11,14 @@
#include "accel/tls.h"
#define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
- (sizeof(struct mlx5e_umr_wqe) + MLX5_ST_SZ_BYTES(tls_static_params))
+ (offsetof(struct mlx5e_umr_wqe, tls_static_params_ctx) + \
+ MLX5_ST_SZ_BYTES(tls_static_params))
#define MLX5E_KTLS_STATIC_WQEBBS \
(DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))
#define MLX5E_KTLS_PROGRESS_WQE_SZ \
- (sizeof(struct mlx5e_tx_wqe) + MLX5_ST_SZ_BYTES(tls_progress_params))
+ (offsetof(struct mlx5e_tx_wqe, tls_progress_params_ctx) + \
+ MLX5_ST_SZ_BYTES(tls_progress_params))
#define MLX5E_KTLS_PROGRESS_WQEBBS \
(DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
#define MLX5E_KTLS_MAX_DUMP_WQEBBS 2
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
index ea032f54197e..7833ddef0427 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -69,7 +69,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
cseg->qpn_ds = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
STATIC_PARAMS_DS_CNT);
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
- cseg->imm = cpu_to_be32(priv_tx->tisn);
+ cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
ucseg->flags = MLX5_UMR_INLINE;
ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
@@ -80,7 +80,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
static void
fill_progress_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
{
- MLX5_SET(tls_progress_params, ctx, pd, priv_tx->tisn);
+ MLX5_SET(tls_progress_params, ctx, tisn, priv_tx->tisn);
MLX5_SET(tls_progress_params, ctx, record_tracker_state,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
MLX5_SET(tls_progress_params, ctx, auth_state,
@@ -104,18 +104,20 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
PROGRESS_PARAMS_DS_CNT);
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
- fill_progress_params_ctx(wqe->data, priv_tx);
+ fill_progress_params_ctx(wqe->tls_progress_params_ctx, priv_tx);
}
static void tx_fill_wi(struct mlx5e_txqsq *sq,
u16 pi, u8 num_wqebbs,
- skb_frag_t *resync_dump_frag)
+ skb_frag_t *resync_dump_frag,
+ u32 num_bytes)
{
struct mlx5e_tx_wqe_info *wi = &sq->db.wqe_info[pi];
wi->skb = NULL;
wi->num_wqebbs = num_wqebbs;
wi->resync_dump_frag = resync_dump_frag;
+ wi->num_bytes = num_bytes;
}
void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx)
@@ -143,7 +145,7 @@ post_static_params(struct mlx5e_txqsq *sq,
umr_wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_STATIC_UMR_WQE_SZ, &pi);
build_static_params(umr_wqe, sq->pc, sq->sqn, priv_tx, fence);
- tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL);
+ tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL, 0);
sq->pc += MLX5E_KTLS_STATIC_WQEBBS;
}
@@ -157,7 +159,7 @@ post_progress_params(struct mlx5e_txqsq *sq,
wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_PROGRESS_WQE_SZ, &pi);
build_progress_params(wqe, sq->pc, sq->sqn, priv_tx, fence);
- tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL);
+ tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL, 0);
sq->pc += MLX5E_KTLS_PROGRESS_WQEBBS;
}
@@ -248,43 +250,37 @@ tx_post_resync_params(struct mlx5e_txqsq *sq,
mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, skip_static_post, true);
}
+struct mlx5e_dump_wqe {
+ struct mlx5_wqe_ctrl_seg ctrl;
+ struct mlx5_wqe_data_seg data;
+};
+
static int
tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
skb_frag_t *frag, u32 tisn, bool first)
{
struct mlx5_wqe_ctrl_seg *cseg;
- struct mlx5_wqe_eth_seg *eseg;
struct mlx5_wqe_data_seg *dseg;
- struct mlx5e_tx_wqe *wqe;
+ struct mlx5e_dump_wqe *wqe;
dma_addr_t dma_addr = 0;
- u16 ds_cnt, ds_cnt_inl;
u8 num_wqebbs;
- u16 pi, ihs;
+ u16 ds_cnt;
int fsz;
-
- ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
- ihs = eth_get_headlen(skb->dev, skb->data, skb_headlen(skb));
- ds_cnt_inl = DIV_ROUND_UP(ihs - INL_HDR_START_SZ, MLX5_SEND_WQE_DS);
- ds_cnt += ds_cnt_inl;
- ds_cnt += 1; /* one frag */
+ u16 pi;
wqe = mlx5e_sq_fetch_wqe(sq, sizeof(*wqe), &pi);
+ ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
cseg = &wqe->ctrl;
- eseg = &wqe->eth;
- dseg = wqe->data;
+ dseg = &wqe->data;
cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_DUMP);
cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
- cseg->imm = cpu_to_be32(tisn);
+ cseg->tisn = cpu_to_be32(tisn << 8);
cseg->fm_ce_se = first ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
- eseg->inline_hdr.sz = cpu_to_be16(ihs);
- memcpy(eseg->inline_hdr.start, skb->data, ihs);
- dseg += ds_cnt_inl;
-
fsz = skb_frag_size(frag);
dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz,
DMA_TO_DEVICE);
@@ -296,7 +292,7 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
dseg->byte_count = cpu_to_be32(fsz);
mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
- tx_fill_wi(sq, pi, num_wqebbs, frag);
+ tx_fill_wi(sq, pi, num_wqebbs, frag, fsz);
sq->pc += num_wqebbs;
WARN(num_wqebbs > MLX5E_KTLS_MAX_DUMP_WQEBBS,
@@ -323,7 +319,7 @@ static void tx_post_fence_nop(struct mlx5e_txqsq *sq)
struct mlx5_wq_cyc *wq = &sq->wq;
u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
- tx_fill_wi(sq, pi, 1, NULL);
+ tx_fill_wi(sq, pi, 1, NULL, 0);
mlx5e_post_nop_fence(wq, sq->sqn, &sq->pc);
}
@@ -412,7 +408,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
goto out;
tls_ctx = tls_get_ctx(skb->sk);
- if (unlikely(tls_ctx->netdev != netdev))
+ if (unlikely(WARN_ON_ONCE(tls_ctx->netdev != netdev)))
goto err_out;
priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
@@ -434,7 +430,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
priv_tx->expected_seq = seq + datalen;
cseg = &(*wqe)->ctrl;
- cseg->imm = cpu_to_be32(priv_tx->tisn);
+ cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
stats->tls_encrypted_bytes += datalen;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index 8657e0f26995..2c75b2752f58 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -437,12 +437,6 @@ arfs_hash_bucket(struct arfs_table *arfs_t, __be16 src_port,
return &arfs_t->rules_hash[bucket_idx];
}
-static u8 arfs_get_ip_proto(const struct sk_buff *skb)
-{
- return (skb->protocol == htons(ETH_P_IP)) ?
- ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
-}
-
static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
u8 ip_proto, __be16 etype)
{
@@ -602,31 +596,9 @@ out:
arfs_may_expire_flow(priv);
}
-/* return L4 destination port from ip4/6 packets */
-static __be16 arfs_get_dst_port(const struct sk_buff *skb)
-{
- char *transport_header;
-
- transport_header = skb_transport_header(skb);
- if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
- return ((struct tcphdr *)transport_header)->dest;
- return ((struct udphdr *)transport_header)->dest;
-}
-
-/* return L4 source port from ip4/6 packets */
-static __be16 arfs_get_src_port(const struct sk_buff *skb)
-{
- char *transport_header;
-
- transport_header = skb_transport_header(skb);
- if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
- return ((struct tcphdr *)transport_header)->source;
- return ((struct udphdr *)transport_header)->source;
-}
-
static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
struct arfs_table *arfs_t,
- const struct sk_buff *skb,
+ const struct flow_keys *fk,
u16 rxq, u32 flow_id)
{
struct arfs_rule *rule;
@@ -641,19 +613,19 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
INIT_WORK(&rule->arfs_work, arfs_handle_work);
tuple = &rule->tuple;
- tuple->etype = skb->protocol;
+ tuple->etype = fk->basic.n_proto;
+ tuple->ip_proto = fk->basic.ip_proto;
if (tuple->etype == htons(ETH_P_IP)) {
- tuple->src_ipv4 = ip_hdr(skb)->saddr;
- tuple->dst_ipv4 = ip_hdr(skb)->daddr;
+ tuple->src_ipv4 = fk->addrs.v4addrs.src;
+ tuple->dst_ipv4 = fk->addrs.v4addrs.dst;
} else {
- memcpy(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
+ memcpy(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
sizeof(struct in6_addr));
- memcpy(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
+ memcpy(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
sizeof(struct in6_addr));
}
- tuple->ip_proto = arfs_get_ip_proto(skb);
- tuple->src_port = arfs_get_src_port(skb);
- tuple->dst_port = arfs_get_dst_port(skb);
+ tuple->src_port = fk->ports.src;
+ tuple->dst_port = fk->ports.dst;
rule->flow_id = flow_id;
rule->filter_id = priv->fs.arfs.last_filter_id++ % RPS_NO_FILTER;
@@ -664,37 +636,33 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
return rule;
}
-static bool arfs_cmp_ips(struct arfs_tuple *tuple,
- const struct sk_buff *skb)
+static bool arfs_cmp(const struct arfs_tuple *tuple, const struct flow_keys *fk)
{
- if (tuple->etype == htons(ETH_P_IP) &&
- tuple->src_ipv4 == ip_hdr(skb)->saddr &&
- tuple->dst_ipv4 == ip_hdr(skb)->daddr)
- return true;
- if (tuple->etype == htons(ETH_P_IPV6) &&
- (!memcmp(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
- sizeof(struct in6_addr))) &&
- (!memcmp(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
- sizeof(struct in6_addr))))
- return true;
+ if (tuple->src_port != fk->ports.src || tuple->dst_port != fk->ports.dst)
+ return false;
+ if (tuple->etype != fk->basic.n_proto)
+ return false;
+ if (tuple->etype == htons(ETH_P_IP))
+ return tuple->src_ipv4 == fk->addrs.v4addrs.src &&
+ tuple->dst_ipv4 == fk->addrs.v4addrs.dst;
+ if (tuple->etype == htons(ETH_P_IPV6))
+ return !memcmp(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
+ sizeof(struct in6_addr)) &&
+ !memcmp(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
+ sizeof(struct in6_addr));
return false;
}
static struct arfs_rule *arfs_find_rule(struct arfs_table *arfs_t,
- const struct sk_buff *skb)
+ const struct flow_keys *fk)
{
struct arfs_rule *arfs_rule;
struct hlist_head *head;
- __be16 src_port = arfs_get_src_port(skb);
- __be16 dst_port = arfs_get_dst_port(skb);
- head = arfs_hash_bucket(arfs_t, src_port, dst_port);
+ head = arfs_hash_bucket(arfs_t, fk->ports.src, fk->ports.dst);
hlist_for_each_entry(arfs_rule, head, hlist) {
- if (arfs_rule->tuple.src_port == src_port &&
- arfs_rule->tuple.dst_port == dst_port &&
- arfs_cmp_ips(&arfs_rule->tuple, skb)) {
+ if (arfs_cmp(&arfs_rule->tuple, fk))
return arfs_rule;
- }
}
return NULL;
@@ -707,20 +675,24 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
struct arfs_table *arfs_t;
struct arfs_rule *arfs_rule;
+ struct flow_keys fk;
+
+ if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+ return -EPROTONOSUPPORT;
- if (skb->protocol != htons(ETH_P_IP) &&
- skb->protocol != htons(ETH_P_IPV6))
+ if (fk.basic.n_proto != htons(ETH_P_IP) &&
+ fk.basic.n_proto != htons(ETH_P_IPV6))
return -EPROTONOSUPPORT;
if (skb->encapsulation)
return -EPROTONOSUPPORT;
- arfs_t = arfs_get_table(arfs, arfs_get_ip_proto(skb), skb->protocol);
+ arfs_t = arfs_get_table(arfs, fk.basic.ip_proto, fk.basic.n_proto);
if (!arfs_t)
return -EPROTONOSUPPORT;
spin_lock_bh(&arfs->arfs_lock);
- arfs_rule = arfs_find_rule(arfs_t, skb);
+ arfs_rule = arfs_find_rule(arfs_t, &fk);
if (arfs_rule) {
if (arfs_rule->rxq == rxq_index) {
spin_unlock_bh(&arfs->arfs_lock);
@@ -728,8 +700,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
}
arfs_rule->rxq = rxq_index;
} else {
- arfs_rule = arfs_alloc_rule(priv, arfs_t, skb,
- rxq_index, flow_id);
+ arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);
if (!arfs_rule) {
spin_unlock_bh(&arfs->arfs_lock);
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 126ec4181286..20e628c907e5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -391,7 +391,7 @@ void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
{
mutex_lock(&priv->state_lock);
- ch->max_combined = mlx5e_get_netdev_max_channels(priv->netdev);
+ ch->max_combined = priv->max_nch;
ch->combined_count = priv->channels.params.num_channels;
if (priv->xsk.refcnt) {
/* The upper half are XSK queues. */
@@ -785,7 +785,7 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
}
static void get_speed_duplex(struct net_device *netdev,
- u32 eth_proto_oper,
+ u32 eth_proto_oper, bool force_legacy,
struct ethtool_link_ksettings *link_ksettings)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -795,7 +795,7 @@ static void get_speed_duplex(struct net_device *netdev,
if (!netif_carrier_ok(netdev))
goto out;
- speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
+ speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
if (!speed) {
speed = SPEED_UNKNOWN;
goto out;
@@ -914,8 +914,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
/* Fields: eth_proto_admin and ext_eth_proto_admin are
* mutually exclusive. Hence try reading legacy advertising
* when extended advertising is zero.
- * admin_ext indicates how eth_proto_admin should be
- * interpreted
+ * admin_ext indicates which proto_admin (ext vs. legacy)
+ * should be read and interpreted
*/
admin_ext = ext;
if (ext && !eth_proto_admin) {
@@ -924,7 +924,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
admin_ext = false;
}
- eth_proto_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+ eth_proto_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, admin_ext,
eth_proto_oper);
eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
@@ -939,7 +939,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
get_supported(mdev, eth_proto_cap, link_ksettings);
get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
admin_ext);
- get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
+ get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
+ link_ksettings);
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
@@ -1016,45 +1017,77 @@ static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
return ptys_modes;
}
+static bool ext_link_mode_requested(const unsigned long *adver)
+{
+#define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
+ int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
+
+ bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
+ return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
+static bool ext_speed_requested(u32 speed)
+{
+#define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
+ return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED);
+}
+
+static bool ext_requested(u8 autoneg, const unsigned long *adver, u32 speed)
+{
+ bool ext_link_mode = ext_link_mode_requested(adver);
+ bool ext_speed = ext_speed_requested(speed);
+
+ return autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed;
+}
+
int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
const struct ethtool_link_ksettings *link_ksettings)
{
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_port_eth_proto eproto;
+ const unsigned long *adver;
bool an_changes = false;
u8 an_disable_admin;
bool ext_supported;
- bool ext_requested;
u8 an_disable_cap;
bool an_disable;
u32 link_modes;
u8 an_status;
+ u8 autoneg;
u32 speed;
+ bool ext;
int err;
u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
-#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
+ adver = link_ksettings->link_modes.advertising;
+ autoneg = link_ksettings->base.autoneg;
+ speed = link_ksettings->base.speed;
- ext_requested = !!(link_ksettings->link_modes.advertising[0] >
- MLX5E_PTYS_EXT ||
- link_ksettings->link_modes.advertising[1]);
+ ext = ext_requested(autoneg, adver, speed),
ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
- ext_requested &= ext_supported;
+ if (!ext_supported && ext)
+ return -EOPNOTSUPP;
- speed = link_ksettings->base.speed;
- ethtool2ptys_adver_func = ext_requested ?
- mlx5e_ethtool2ptys_ext_adver_link :
+ ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
mlx5e_ethtool2ptys_adver_link;
- err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
+ err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
if (err) {
netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
__func__, err);
goto out;
}
- link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
- ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) :
- mlx5e_port_speed2linkmodes(mdev, speed);
+ link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
+ mlx5e_port_speed2linkmodes(mdev, speed, !ext);
+
+ if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
+ autoneg != AUTONEG_ENABLE) {
+ netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
+ __func__);
+ err = -EINVAL;
+ goto out;
+ }
link_modes = link_modes & eproto.cap;
if (!link_modes) {
@@ -1067,14 +1100,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
&an_disable_admin);
- an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE;
+ an_disable = autoneg == AUTONEG_DISABLE;
an_changes = ((!an_disable && an_disable_admin) ||
(an_disable && !an_disable_admin));
if (!an_changes && link_modes == eproto.admin)
goto out;
- mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
+ mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
mlx5_toggle_port_link(mdev);
out:
@@ -1313,6 +1346,9 @@ int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
struct mlx5_core_dev *mdev = priv->mdev;
int err;
+ if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+ return -EOPNOTSUPP;
+
if (pauseparam->autoneg)
return -EINVAL;
@@ -1654,6 +1690,40 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
return 0;
}
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+ struct ethtool_flash *flash)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->netdev;
+ const struct firmware *fw;
+ int err;
+
+ if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
+ return -EOPNOTSUPP;
+
+ err = request_firmware_direct(&fw, flash->data, &dev->dev);
+ if (err)
+ return err;
+
+ dev_hold(dev);
+ rtnl_unlock();
+
+ err = mlx5_firmware_flash(mdev, fw, NULL);
+ release_firmware(fw);
+
+ rtnl_lock();
+ dev_put(dev);
+ return err;
+}
+
+static int mlx5e_flash_device(struct net_device *dev,
+ struct ethtool_flash *flash)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
+ return mlx5e_ethtool_flash_device(priv, flash);
+}
+
static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
bool is_rx_cq)
{
@@ -1936,6 +2006,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.set_wol = mlx5e_set_wol,
.get_module_info = mlx5e_get_module_info,
.get_module_eeprom = mlx5e_get_module_eeprom,
+ .flash_device = mlx5e_flash_device,
.get_priv_flags = mlx5e_get_priv_flags,
.set_priv_flags = mlx5e_set_priv_flags,
.self_test = mlx5e_self_test,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
index ea3a490b569a..94304abc49e9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -611,7 +611,8 @@ static int validate_flow(struct mlx5e_priv *priv,
return -ENOSPC;
if (fs->ring_cookie != RX_CLS_FLOW_DISC)
- if (!mlx5e_qid_validate(&priv->channels.params, fs->ring_cookie))
+ if (!mlx5e_qid_validate(priv->profile, &priv->channels.params,
+ fs->ring_cookie))
return -EINVAL;
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 47eea6b3a1c3..9d5f6e56188f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -331,12 +331,11 @@ static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
{
- struct mlx5e_wqe_frag_info next_frag, *prev;
+ struct mlx5e_wqe_frag_info next_frag = {};
+ struct mlx5e_wqe_frag_info *prev = NULL;
int i;
next_frag.di = &rq->wqe.di[0];
- next_frag.offset = 0;
- prev = NULL;
for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
@@ -1322,7 +1321,6 @@ err_free_txqsq:
void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
{
sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
- clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
netdev_tx_reset_queue(sq->txq);
netif_tx_start_queue(sq->txq);
@@ -1677,10 +1675,10 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
struct mlx5e_channel_param *cparam)
{
struct mlx5e_priv *priv = c->priv;
- int err, tc, max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+ int err, tc;
for (tc = 0; tc < params->num_tc; tc++) {
- int txq_ix = c->ix + tc * max_nch;
+ int txq_ix = c->ix + tc * priv->max_nch;
err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix,
params, &cparam->sq, &c->sq[tc], tc);
@@ -2438,11 +2436,10 @@ int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv)
int mlx5e_create_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
{
- const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
int err;
int ix;
- for (ix = 0; ix < max_nch; ix++) {
+ for (ix = 0; ix < priv->max_nch; ix++) {
err = mlx5e_create_rqt(priv, 1 /*size */, &tirs[ix].rqt);
if (unlikely(err))
goto err_destroy_rqts;
@@ -2460,10 +2457,9 @@ err_destroy_rqts:
void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
{
- const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
int i;
- for (i = 0; i < max_nch; i++)
+ for (i = 0; i < priv->max_nch; i++)
mlx5e_destroy_rqt(priv, &tirs[i].rqt);
}
@@ -2557,7 +2553,7 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv,
mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
}
- for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+ for (ix = 0; ix < priv->max_nch; ix++) {
struct mlx5e_redirect_rqt_param direct_rrp = {
.is_rss = false,
{
@@ -2758,7 +2754,7 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
goto free_in;
}
- for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+ for (ix = 0; ix < priv->max_nch; ix++) {
err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
in, inlen);
if (err)
@@ -2858,12 +2854,11 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
{
- int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
int i, tc;
- for (i = 0; i < max_nch; i++)
+ for (i = 0; i < priv->max_nch; i++)
for (tc = 0; tc < priv->profile->max_tc; tc++)
- priv->channel_tc2txq[i][tc] = i + tc * max_nch;
+ priv->channel_tc2txq[i][tc] = i + tc * priv->max_nch;
}
static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
@@ -2884,7 +2879,7 @@ static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
{
int num_txqs = priv->channels.num * priv->channels.params.num_tc;
- int num_rxqs = priv->channels.num * MLX5E_NUM_RQ_GROUPS;
+ int num_rxqs = priv->channels.num * priv->profile->rq_groups;
struct net_device *netdev = priv->netdev;
mlx5e_netdev_set_tcs(netdev);
@@ -3306,7 +3301,6 @@ err_destroy_inner_tirs:
int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
{
- const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
struct mlx5e_tir *tir;
void *tirc;
int inlen;
@@ -3319,7 +3313,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
if (!in)
return -ENOMEM;
- for (ix = 0; ix < max_nch; ix++) {
+ for (ix = 0; ix < priv->max_nch; ix++) {
memset(in, 0, inlen);
tir = &tirs[ix];
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
@@ -3358,10 +3352,9 @@ void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc)
void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
{
- const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
int i;
- for (i = 0; i < max_nch; i++)
+ for (i = 0; i < priv->max_nch; i++)
mlx5e_destroy_tir(priv->mdev, &tirs[i]);
}
@@ -3487,7 +3480,7 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
{
int i;
- for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+ for (i = 0; i < priv->max_nch; i++) {
struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i];
struct mlx5e_rq_stats *xskrq_stats = &channel_stats->xskrq;
struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
@@ -4960,8 +4953,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
return err;
mlx5e_build_nic_params(mdev, &priv->xsk, rss, &priv->channels.params,
- mlx5e_get_netdev_max_channels(netdev),
- netdev->mtu);
+ priv->max_nch, netdev->mtu);
mlx5e_timestamp_init(priv);
@@ -5164,6 +5156,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
.rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe,
.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
.max_tc = MLX5E_MAX_NUM_TC,
+ .rq_groups = MLX5E_NUM_RQ_GROUPS(XSK),
};
/* mlx5e generic netdev management API (move to en_common.c) */
@@ -5181,6 +5174,7 @@ int mlx5e_netdev_init(struct net_device *netdev,
priv->profile = profile;
priv->ppriv = ppriv;
priv->msglevel = MLX5E_MSG_LEVEL;
+ priv->max_nch = netdev->num_rx_queues / max_t(u8, profile->rq_groups, 1);
priv->max_opened_tc = 1;
mutex_init(&priv->state_lock);
@@ -5218,7 +5212,7 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
nch * profile->max_tc,
- nch * MLX5E_NUM_RQ_GROUPS);
+ nch * profile->rq_groups);
if (!netdev) {
mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 7f747cb1a4f4..d0684fdb69e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1701,6 +1701,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
.rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe_rep,
.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
.max_tc = 1,
+ .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR),
};
static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
@@ -1718,6 +1719,7 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
.rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe_rep,
.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
.max_tc = MLX5E_MAX_NUM_TC,
+ .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR),
};
static bool
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index 539b4d3656da..57f9f346d213 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -172,7 +172,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
memset(s, 0, sizeof(*s));
- for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+ for (i = 0; i < priv->max_nch; i++) {
struct mlx5e_channel_stats *channel_stats =
&priv->channel_stats[i];
struct mlx5e_xdpsq_stats *xdpsq_red_stats = &channel_stats->xdpsq;
@@ -1395,7 +1395,7 @@ static const struct counter_desc ch_stats_desc[] = {
static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
{
- int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+ int max_nch = priv->max_nch;
return (NUM_RQ_STATS * max_nch) +
(NUM_CH_STATS * max_nch) +
@@ -1409,8 +1409,8 @@ static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
int idx)
{
- int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
bool is_xsk = priv->xsk.ever_used;
+ int max_nch = priv->max_nch;
int i, j, tc;
for (i = 0; i < max_nch; i++)
@@ -1452,8 +1452,8 @@ static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
static int mlx5e_grp_channels_fill_stats(struct mlx5e_priv *priv, u64 *data,
int idx)
{
- int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
bool is_xsk = priv->xsk.ever_used;
+ int max_nch = priv->max_nch;
int i, j, tc;
for (i = 0; i < max_nch; i++)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index cc096f6011d9..00b2d4a86159 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1230,13 +1230,13 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
{
struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
- u64 bytes, packets, lastuse = 0;
struct mlx5e_tc_flow *flow;
struct mlx5e_encap_entry *e;
struct mlx5_fc *counter;
struct neigh_table *tbl;
bool neigh_used = false;
struct neighbour *n;
+ u64 lastuse;
if (m_neigh->family == AF_INET)
tbl = &arp_tbl;
@@ -1256,7 +1256,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
encaps[efi->index]);
if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
counter = mlx5e_tc_get_counter(flow);
- mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+ lastuse = mlx5_fc_query_lastuse(counter);
if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
neigh_used = true;
break;
@@ -1480,7 +1480,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
struct flow_cls_offload *f,
struct net_device *filter_dev,
- u8 *match_level, u8 *tunnel_match_level)
+ u8 *inner_match_level, u8 *outer_match_level)
{
struct netlink_ext_ack *extack = f->common.extack;
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1495,8 +1495,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct flow_dissector *dissector = rule->match.dissector;
u16 addr_type = 0;
u8 ip_proto = 0;
+ u8 *match_level;
- *match_level = MLX5_MATCH_NONE;
+ match_level = outer_match_level;
if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_META) |
@@ -1524,12 +1525,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
}
if (mlx5e_get_tc_tun(filter_dev)) {
- if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
+ if (parse_tunnel_attr(priv, spec, f, filter_dev,
+ outer_match_level))
return -EOPNOTSUPP;
- /* In decap flow, header pointers should point to the inner
+ /* At this point, header pointers should point to the inner
* headers, outer header were already set by parse_tunnel_attr
*/
+ match_level = inner_match_level;
headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
spec);
headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
@@ -1831,35 +1834,41 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
struct flow_cls_offload *f,
struct net_device *filter_dev)
{
+ u8 inner_match_level, outer_match_level, non_tunnel_match_level;
struct netlink_ext_ack *extack = f->common.extack;
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
- u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
struct mlx5_eswitch_rep *rep;
int err;
- err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
+ inner_match_level = MLX5_MATCH_NONE;
+ outer_match_level = MLX5_MATCH_NONE;
+
+ err = __parse_cls_flower(priv, spec, f, filter_dev, &inner_match_level,
+ &outer_match_level);
+ non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ?
+ outer_match_level : inner_match_level;
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
rep = rpriv->rep;
if (rep->vport != MLX5_VPORT_UPLINK &&
(esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
- esw->offloads.inline_mode < match_level)) {
+ esw->offloads.inline_mode < non_tunnel_match_level)) {
NL_SET_ERR_MSG_MOD(extack,
"Flow is not offloaded due to min inline setting");
netdev_warn(priv->netdev,
"Flow is not offloaded due to min inline setting, required %d actual %d\n",
- match_level, esw->offloads.inline_mode);
+ non_tunnel_match_level, esw->offloads.inline_mode);
return -EOPNOTSUPP;
}
}
if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
- flow->esw_attr->match_level = match_level;
- flow->esw_attr->tunnel_match_level = tunnel_match_level;
+ flow->esw_attr->inner_match_level = inner_match_level;
+ flow->esw_attr->outer_match_level = outer_match_level;
} else {
- flow->nic_attr->match_level = match_level;
+ flow->nic_attr->match_level = non_tunnel_match_level;
}
return err;
@@ -3158,7 +3167,7 @@ mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
esw_attr->parse_attr = parse_attr;
esw_attr->chain = f->common.chain_index;
- esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
+ esw_attr->prio = f->common.prio;
esw_attr->in_rep = in_rep;
esw_attr->in_mdev = in_mdev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
index c50b6f0769c8..49b06b256c92 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -49,7 +49,7 @@ static inline bool mlx5e_channel_no_affinity_change(struct mlx5e_channel *c)
static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
{
struct mlx5e_sq_stats *stats = sq->stats;
- struct dim_sample dim_sample;
+ struct dim_sample dim_sample = {};
if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state)))
return;
@@ -61,7 +61,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
{
struct mlx5e_rq_stats *stats = rq->stats;
- struct dim_sample dim_sample;
+ struct dim_sample dim_sample = {};
if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state)))
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index a38e8a3c7c9a..04685dbb280c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -377,8 +377,8 @@ struct mlx5_esw_flow_attr {
struct mlx5_termtbl_handle *termtbl;
} dests[MLX5_MAX_FLOW_FWD_VPORTS];
u32 mod_hdr_id;
- u8 match_level;
- u8 tunnel_match_level;
+ u8 inner_match_level;
+ u8 outer_match_level;
struct mlx5_fc *counter;
u32 chain;
u16 prio;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 089ae4d48a82..0323fd078271 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -207,14 +207,10 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
mlx5_eswitch_set_rule_source_port(esw, spec, attr);
- if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
- if (attr->tunnel_match_level != MLX5_MATCH_NONE)
- spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
- if (attr->match_level != MLX5_MATCH_NONE)
- spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
- } else if (attr->match_level != MLX5_MATCH_NONE) {
+ if (attr->outer_match_level != MLX5_MATCH_NONE)
spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
- }
+ if (attr->inner_match_level != MLX5_MATCH_NONE)
+ spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
flow_act.modify_id = attr->mod_hdr_id;
@@ -290,7 +286,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
mlx5_eswitch_set_rule_source_port(esw, spec, attr);
spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
- if (attr->match_level != MLX5_MATCH_NONE)
+ if (attr->outer_match_level != MLX5_MATCH_NONE)
spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index c48c382f926f..c1252d6be0ef 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -68,7 +68,7 @@ enum fs_flow_table_type {
FS_FT_SNIFFER_RX = 0X5,
FS_FT_SNIFFER_TX = 0X6,
FS_FT_RDMA_RX = 0X7,
- FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX,
+ FS_FT_MAX_TYPE = FS_FT_RDMA_RX,
};
enum fs_flow_table_op_mod {
@@ -275,7 +275,8 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
(type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) : \
(type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) : \
(type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) : \
- (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\
+ (type == FS_FT_RDMA_RX) ? MLX5_CAP_FLOWTABLE_RDMA_RX(mdev, cap) : \
+ (BUILD_BUG_ON_ZERO(FS_FT_RDMA_RX != FS_FT_MAX_TYPE))\
)
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
index b3762123a69c..1834d9f3aa1c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
@@ -369,6 +369,11 @@ int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
}
EXPORT_SYMBOL(mlx5_fc_query);
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter)
+{
+ return counter->cache.lastuse;
+}
+
void mlx5_fc_query_cached(struct mlx5_fc *counter,
u64 *bytes, u64 *packets, u64 *lastuse)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 9314777d99e3..d685122d9ff7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -590,7 +590,8 @@ mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,
data_size = crdump_size - offset;
else
data_size = MLX5_CR_DUMP_CHUNK_SIZE;
- err = devlink_fmsg_binary_put(fmsg, cr_data, data_size);
+ err = devlink_fmsg_binary_put(fmsg, (char *)cr_data + offset,
+ data_size);
if (err)
goto free_data;
}
@@ -700,6 +701,16 @@ static void poll_health(struct timer_list *t)
if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
goto out;
+ fatal_error = check_fatal_sensors(dev);
+
+ if (fatal_error && !health->fatal_error) {
+ mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error);
+ dev->priv.health.fatal_error = fatal_error;
+ print_health_info(dev);
+ mlx5_trigger_health_work(dev);
+ goto out;
+ }
+
count = ioread32be(health->health_counter);
if (count == health->prev)
++health->miss_counter;
@@ -718,15 +729,6 @@ static void poll_health(struct timer_list *t)
if (health->synd && health->synd != prev_synd)
queue_work(health->wq, &health->report_work);
- fatal_error = check_fatal_sensors(dev);
-
- if (fatal_error && !health->fatal_error) {
- mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error);
- dev->priv.health.fatal_error = fatal_error;
- print_health_info(dev);
- mlx5_trigger_health_work(dev);
- }
-
out:
mod_timer(&health->timer, get_next_poll_jiffies());
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
index ebd81f6b556e..90cb50fe17fd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
@@ -122,6 +122,14 @@ static int mlx5i_get_ts_info(struct net_device *netdev,
return mlx5e_ethtool_get_ts_info(priv, info);
}
+static int mlx5i_flash_device(struct net_device *netdev,
+ struct ethtool_flash *flash)
+{
+ struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+ return mlx5e_ethtool_flash_device(priv, flash);
+}
+
enum mlx5_ptys_width {
MLX5_PTYS_WIDTH_1X = 1 << 0,
MLX5_PTYS_WIDTH_2X = 1 << 1,
@@ -233,6 +241,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
.get_ethtool_stats = mlx5i_get_ethtool_stats,
.get_ringparam = mlx5i_get_ringparam,
.set_ringparam = mlx5i_set_ringparam,
+ .flash_device = mlx5i_flash_device,
.get_channels = mlx5i_get_channels,
.set_channels = mlx5i_set_channels,
.get_coalesce = mlx5i_get_coalesce,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index 6bfaaab362dc..1a2560e3bf7c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -88,8 +88,7 @@ int mlx5i_init(struct mlx5_core_dev *mdev,
netdev->mtu = netdev->max_mtu;
mlx5e_build_nic_params(mdev, NULL, &priv->rss_params, &priv->channels.params,
- mlx5e_get_netdev_max_channels(netdev),
- netdev->mtu);
+ priv->max_nch, netdev->mtu);
mlx5i_build_nic_params(mdev, &priv->channels.params);
mlx5e_timestamp_init(priv);
@@ -118,11 +117,10 @@ void mlx5i_cleanup(struct mlx5e_priv *priv)
static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv)
{
- int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
struct mlx5e_sw_stats s = { 0 };
int i, j;
- for (i = 0; i < max_nch; i++) {
+ for (i = 0; i < priv->max_nch; i++) {
struct mlx5e_channel_stats *channel_stats;
struct mlx5e_rq_stats *rq_stats;
@@ -436,6 +434,7 @@ static const struct mlx5e_profile mlx5i_nic_profile = {
.rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe,
.rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
.max_tc = MLX5I_MAX_NUM_TC,
+ .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR),
};
/* mlx5i netdev NDos */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
index 6e56fa769d2e..c5a491e22e55 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
@@ -355,6 +355,7 @@ static const struct mlx5e_profile mlx5i_pkey_nic_profile = {
.rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe,
.rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
.max_tc = MLX5I_MAX_NUM_TC,
+ .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR),
};
const struct mlx5e_profile *mlx5i_pkey_get_profile(void)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
index ea9ee88491e5..ea1d4d26ece0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
@@ -27,6 +27,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
case 128:
general_obj_key_size =
MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_128;
+ key_p += sz_bytes;
break;
case 256:
general_obj_key_size =
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 650638152bbc..eda9c23e87b2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -6330,7 +6330,7 @@ static int __init mlxsw_sp_module_init(void)
return 0;
err_sp2_pci_driver_register:
- mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
+ mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
err_sp1_pci_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
err_sp2_core_driver_register:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 131f62ce9297..6664119fb0c8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -951,4 +951,8 @@ void mlxsw_sp_port_nve_fini(struct mlxsw_sp_port *mlxsw_sp_port);
int mlxsw_sp_nve_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp);
+/* spectrum_nve_vxlan.c */
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp);
+
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index e8ac90564dbe..84a87d059333 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -471,7 +471,7 @@ int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei)
void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
unsigned int priority)
{
- rulei->priority = priority >> 16;
+ rulei->priority = priority;
}
void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index 1537f70bc26d..888ba4300bcc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
};
-#define MLXSW_SP2_SB_PR_INGRESS_SIZE 38128752
-#define MLXSW_SP2_SB_PR_EGRESS_SIZE 38128752
+#define MLXSW_SP2_SB_PR_INGRESS_SIZE 35297568
+#define MLXSW_SP2_SB_PR_EGRESS_SIZE 35297568
#define MLXSW_SP2_SB_PR_CPU_SIZE (256 * 1000)
/* Order according to mlxsw_sp2_sb_pool_dess */
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
index 1df164a4b06d..17f334b46c40 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
@@ -775,6 +775,7 @@ static void mlxsw_sp_nve_tunnel_fini(struct mlxsw_sp *mlxsw_sp)
ops->fini(nve);
mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
nve->tunnel_index);
+ memset(&nve->config, 0, sizeof(nve->config));
}
nve->num_nve_tunnels--;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
index 0035640156a1..12f664f42f21 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
@@ -29,6 +29,7 @@ struct mlxsw_sp_nve {
unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
u32 tunnel_index;
u16 ul_rif_index; /* Reserved for Spectrum */
+ unsigned int inc_parsing_depth_refs;
};
struct mlxsw_sp_nve_ops {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
index 93ccd9fc2266..05517c7feaa5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
@@ -103,9 +103,9 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
config->udp_dport = cfg->dst_port;
}
-static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
- unsigned int parsing_depth,
- __be16 udp_dport)
+static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+ unsigned int parsing_depth,
+ __be16 udp_dport)
{
char mprs_pl[MLXSW_REG_MPRS_LEN];
@@ -113,6 +113,56 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
}
+static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+ __be16 udp_dport)
+{
+ int parsing_depth = mlxsw_sp->nve->inc_parsing_depth_refs ?
+ MLXSW_SP_NVE_VXLAN_PARSING_DEPTH :
+ MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH;
+
+ return __mlxsw_sp_nve_parsing_set(mlxsw_sp, parsing_depth, udp_dport);
+}
+
+static int
+__mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp,
+ __be16 udp_dport)
+{
+ int err;
+
+ mlxsw_sp->nve->inc_parsing_depth_refs++;
+
+ err = mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+ if (err)
+ goto err_nve_parsing_set;
+ return 0;
+
+err_nve_parsing_set:
+ mlxsw_sp->nve->inc_parsing_depth_refs--;
+ return err;
+}
+
+static void
+__mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp,
+ __be16 udp_dport)
+{
+ mlxsw_sp->nve->inc_parsing_depth_refs--;
+ mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+}
+
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp)
+{
+ __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+ return __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, udp_dport);
+}
+
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp)
+{
+ __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+ __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, udp_dport);
+}
+
static void
mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
const struct mlxsw_sp_nve_config *config)
@@ -176,9 +226,7 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
int err;
- err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
- MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
- config->udp_dport);
+ err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
if (err)
return err;
@@ -203,8 +251,7 @@ err_promote_decap:
err_rtdp_set:
mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
err_config_set:
- mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
- config->udp_dport);
+ __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
return err;
}
@@ -216,8 +263,7 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
config->ul_proto, &config->ul_sip);
mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
- mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
- config->udp_dport);
+ __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
}
static int
@@ -320,9 +366,7 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
int err;
- err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
- MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
- config->udp_dport);
+ err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
if (err)
return err;
@@ -348,8 +392,7 @@ err_promote_decap:
err_rtdp_set:
mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
err_config_set:
- mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
- config->udp_dport);
+ __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
return err;
}
@@ -361,8 +404,7 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
config->ul_proto, &config->ul_sip);
mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
- mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
- config->udp_dport);
+ __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
}
const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index bd9c2bc2d5d6..38bb1cfe4e8c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -29,7 +29,7 @@
struct mlxsw_sp_ptp_state {
struct mlxsw_sp *mlxsw_sp;
- struct rhashtable unmatched_ht;
+ struct rhltable unmatched_ht;
spinlock_t unmatched_lock; /* protects the HT */
struct delayed_work ht_gc_dw;
u32 gc_cycle;
@@ -45,7 +45,7 @@ struct mlxsw_sp1_ptp_key {
struct mlxsw_sp1_ptp_unmatched {
struct mlxsw_sp1_ptp_key key;
- struct rhash_head ht_node;
+ struct rhlist_head ht_node;
struct rcu_head rcu;
struct sk_buff *skb;
u64 timestamp;
@@ -359,7 +359,7 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
/* Returns NULL on successful insertion, a pointer on conflict, or an ERR_PTR on
* error.
*/
-static struct mlxsw_sp1_ptp_unmatched *
+static int
mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp1_ptp_key key,
struct sk_buff *skb,
@@ -368,41 +368,51 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
int cycles = MLXSW_SP1_PTP_HT_GC_TIMEOUT / MLXSW_SP1_PTP_HT_GC_INTERVAL;
struct mlxsw_sp_ptp_state *ptp_state = mlxsw_sp->ptp_state;
struct mlxsw_sp1_ptp_unmatched *unmatched;
- struct mlxsw_sp1_ptp_unmatched *conflict;
+ int err;
unmatched = kzalloc(sizeof(*unmatched), GFP_ATOMIC);
if (!unmatched)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
unmatched->key = key;
unmatched->skb = skb;
unmatched->timestamp = timestamp;
unmatched->gc_cycle = mlxsw_sp->ptp_state->gc_cycle + cycles;
- conflict = rhashtable_lookup_get_insert_fast(&ptp_state->unmatched_ht,
- &unmatched->ht_node,
- mlxsw_sp1_ptp_unmatched_ht_params);
- if (conflict)
+ err = rhltable_insert(&ptp_state->unmatched_ht, &unmatched->ht_node,
+ mlxsw_sp1_ptp_unmatched_ht_params);
+ if (err)
kfree(unmatched);
- return conflict;
+ return err;
}
static struct mlxsw_sp1_ptp_unmatched *
mlxsw_sp1_ptp_unmatched_lookup(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp1_ptp_key key)
+ struct mlxsw_sp1_ptp_key key, int *p_length)
{
- return rhashtable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
- mlxsw_sp1_ptp_unmatched_ht_params);
+ struct mlxsw_sp1_ptp_unmatched *unmatched, *last = NULL;
+ struct rhlist_head *tmp, *list;
+ int length = 0;
+
+ list = rhltable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
+ mlxsw_sp1_ptp_unmatched_ht_params);
+ rhl_for_each_entry_rcu(unmatched, tmp, list, ht_node) {
+ last = unmatched;
+ length++;
+ }
+
+ *p_length = length;
+ return last;
}
static int
mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp1_ptp_unmatched *unmatched)
{
- return rhashtable_remove_fast(&mlxsw_sp->ptp_state->unmatched_ht,
- &unmatched->ht_node,
- mlxsw_sp1_ptp_unmatched_ht_params);
+ return rhltable_remove(&mlxsw_sp->ptp_state->unmatched_ht,
+ &unmatched->ht_node,
+ mlxsw_sp1_ptp_unmatched_ht_params);
}
/* This function is called in the following scenarios:
@@ -489,75 +499,38 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp1_ptp_key key,
struct sk_buff *skb, u64 timestamp)
{
- struct mlxsw_sp1_ptp_unmatched *unmatched, *conflict;
+ struct mlxsw_sp1_ptp_unmatched *unmatched;
+ int length;
int err;
rcu_read_lock();
- unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key);
-
spin_lock(&mlxsw_sp->ptp_state->unmatched_lock);
- if (unmatched) {
- /* There was an unmatched entry when we looked, but it may have
- * been removed before we took the lock.
- */
- err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
- if (err)
- unmatched = NULL;
- }
-
- if (!unmatched) {
- /* We have no unmatched entry, but one may have been added after
- * we looked, but before we took the lock.
- */
- unmatched = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
- skb, timestamp);
- if (IS_ERR(unmatched)) {
- if (skb)
- mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
- key.local_port,
- key.ingress, NULL);
- unmatched = NULL;
- } else if (unmatched) {
- /* Save just told us, under lock, that the entry is
- * there, so this has to work.
- */
- err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp,
- unmatched);
- WARN_ON_ONCE(err);
- }
- }
-
- /* If unmatched is non-NULL here, it comes either from the lookup, or
- * from the save attempt above. In either case the entry was removed
- * from the hash table. If unmatched is NULL, a new unmatched entry was
- * added to the hash table, and there was no conflict.
- */
-
+ unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key, &length);
if (skb && unmatched && unmatched->timestamp) {
unmatched->skb = skb;
} else if (timestamp && unmatched && unmatched->skb) {
unmatched->timestamp = timestamp;
- } else if (unmatched) {
- /* unmatched holds an older entry of the same type: either an
- * skb if we are handling skb, or a timestamp if we are handling
- * timestamp. We can't match that up, so save what we have.
+ } else {
+ /* Either there is no entry to match, or one that is there is
+ * incompatible.
*/
- conflict = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
- skb, timestamp);
- if (IS_ERR(conflict)) {
- if (skb)
- mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
- key.local_port,
- key.ingress, NULL);
- } else {
- /* Above, we removed an object with this key from the
- * hash table, under lock, so conflict can not be a
- * valid pointer.
- */
- WARN_ON_ONCE(conflict);
- }
+ if (length < 100)
+ err = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
+ skb, timestamp);
+ else
+ err = -E2BIG;
+ if (err && skb)
+ mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
+ key.local_port,
+ key.ingress, NULL);
+ unmatched = NULL;
+ }
+
+ if (unmatched) {
+ err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
+ WARN_ON_ONCE(err);
}
spin_unlock(&mlxsw_sp->ptp_state->unmatched_lock);
@@ -669,9 +642,8 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
local_bh_disable();
spin_lock(&ptp_state->unmatched_lock);
- err = rhashtable_remove_fast(&ptp_state->unmatched_ht,
- &unmatched->ht_node,
- mlxsw_sp1_ptp_unmatched_ht_params);
+ err = rhltable_remove(&ptp_state->unmatched_ht, &unmatched->ht_node,
+ mlxsw_sp1_ptp_unmatched_ht_params);
spin_unlock(&ptp_state->unmatched_lock);
if (err)
@@ -702,7 +674,7 @@ static void mlxsw_sp1_ptp_ht_gc(struct work_struct *work)
ptp_state = container_of(dwork, struct mlxsw_sp_ptp_state, ht_gc_dw);
gc_cycle = ptp_state->gc_cycle++;
- rhashtable_walk_enter(&ptp_state->unmatched_ht, &iter);
+ rhltable_walk_enter(&ptp_state->unmatched_ht, &iter);
rhashtable_walk_start(&iter);
while ((obj = rhashtable_walk_next(&iter))) {
if (IS_ERR(obj))
@@ -855,8 +827,8 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
spin_lock_init(&ptp_state->unmatched_lock);
- err = rhashtable_init(&ptp_state->unmatched_ht,
- &mlxsw_sp1_ptp_unmatched_ht_params);
+ err = rhltable_init(&ptp_state->unmatched_ht,
+ &mlxsw_sp1_ptp_unmatched_ht_params);
if (err)
goto err_hashtable_init;
@@ -891,7 +863,7 @@ err_fifo_clr:
err_mtptpt1_set:
mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
err_mtptpt_set:
- rhashtable_destroy(&ptp_state->unmatched_ht);
+ rhltable_destroy(&ptp_state->unmatched_ht);
err_hashtable_init:
kfree(ptp_state);
return ERR_PTR(err);
@@ -906,8 +878,8 @@ void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
mlxsw_sp1_ptp_set_fifo_clr_on_trap(mlxsw_sp, false);
mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP1, 0);
mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
- rhashtable_free_and_destroy(&ptp_state->unmatched_ht,
- &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
+ rhltable_free_and_destroy(&ptp_state->unmatched_ht,
+ &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
kfree(ptp_state);
}
@@ -979,6 +951,9 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *tmp;
+ u16 orig_ing_types = 0;
+ u16 orig_egr_types = 0;
+ int err;
int i;
/* MTPPPC configures timestamping globally, not per port. Find the
@@ -986,12 +961,26 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
*/
for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
tmp = mlxsw_sp->ports[i];
+ if (tmp) {
+ orig_ing_types |= tmp->ptp.ing_types;
+ orig_egr_types |= tmp->ptp.egr_types;
+ }
if (tmp && tmp != mlxsw_sp_port) {
ing_types |= tmp->ptp.ing_types;
egr_types |= tmp->ptp.egr_types;
}
}
+ if ((ing_types || egr_types) && !(orig_ing_types || orig_egr_types)) {
+ err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
+ if (err) {
+ netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
+ return err;
+ }
+ }
+ if (!(ing_types || egr_types) && (orig_ing_types || orig_egr_types))
+ mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp);
+
return mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp_port->mlxsw_sp,
ing_types, egr_types);
}
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
index 90a8c6bead56..b9c4d48e28e4 100644
--- a/drivers/net/ethernet/micrel/Kconfig
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -6,8 +6,7 @@
config NET_VENDOR_MICREL
bool "Micrel devices"
default y
- depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
- (ARM && ARCH_KS8695)
+ depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -18,14 +17,6 @@ config NET_VENDOR_MICREL
if NET_VENDOR_MICREL
-config ARM_KS8695_ETHER
- tristate "KS8695 Ethernet support"
- depends on ARM && ARCH_KS8695
- select MII
- ---help---
- If you wish to compile a kernel for the KS8695 and want to
- use the internal ethernet then you should answer Y to this.
-
config KS8842
tristate "Micrel KSZ8841/42 with generic bus interface"
depends on HAS_IOMEM && DMA_ENGINE
diff --git a/drivers/net/ethernet/micrel/Makefile b/drivers/net/ethernet/micrel/Makefile
index 848fc1c5a5dc..6d8ac5527aef 100644
--- a/drivers/net/ethernet/micrel/Makefile
+++ b/drivers/net/ethernet/micrel/Makefile
@@ -3,7 +3,6 @@
# Makefile for the Micrel network device drivers.
#
-obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
obj-$(CONFIG_KS8842) += ks8842.o
obj-$(CONFIG_KS8851) += ks8851.o
obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
deleted file mode 100644
index 1390ef5323a2..000000000000
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ /dev/null
@@ -1,1632 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- * Vincent Sanders <vince@simtec.co.uk>
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <asm/irq.h>
-
-#include <mach/regs-switch.h>
-#include <mach/regs-misc.h>
-#include <asm/mach/irq.h>
-#include <mach/regs-irq.h>
-
-#include "ks8695net.h"
-
-#define MODULENAME "ks8695_ether"
-#define MODULEVERSION "1.02"
-
-/*
- * Transmit and device reset timeout, default 5 seconds.
- */
-static int watchdog = 5000;
-
-/* Hardware structures */
-
-/**
- * struct rx_ring_desc - Receive descriptor ring element
- * @status: The status of the descriptor element (E.g. who owns it)
- * @length: The number of bytes in the block pointed to by data_ptr
- * @data_ptr: The physical address of the data block to receive into
- * @next_desc: The physical address of the next descriptor element.
- */
-struct rx_ring_desc {
- __le32 status;
- __le32 length;
- __le32 data_ptr;
- __le32 next_desc;
-};
-
-/**
- * struct tx_ring_desc - Transmit descriptor ring element
- * @owner: Who owns the descriptor
- * @status: The number of bytes in the block pointed to by data_ptr
- * @data_ptr: The physical address of the data block to receive into
- * @next_desc: The physical address of the next descriptor element.
- */
-struct tx_ring_desc {
- __le32 owner;
- __le32 status;
- __le32 data_ptr;
- __le32 next_desc;
-};
-
-/**
- * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
- * @skb: The buffer in the ring
- * @dma_ptr: The mapped DMA pointer of the buffer
- * @length: The number of bytes mapped to dma_ptr
- */
-struct ks8695_skbuff {
- struct sk_buff *skb;
- dma_addr_t dma_ptr;
- u32 length;
-};
-
-/* Private device structure */
-
-#define MAX_TX_DESC 8
-#define MAX_TX_DESC_MASK 0x7
-#define MAX_RX_DESC 16
-#define MAX_RX_DESC_MASK 0xf
-
-/*napi_weight have better more than rx DMA buffers*/
-#define NAPI_WEIGHT 64
-
-#define MAX_RXBUF_SIZE 0x700
-
-#define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
-#define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
-#define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
-
-/**
- * enum ks8695_dtype - Device type
- * @KS8695_DTYPE_WAN: This device is a WAN interface
- * @KS8695_DTYPE_LAN: This device is a LAN interface
- * @KS8695_DTYPE_HPNA: This device is an HPNA interface
- */
-enum ks8695_dtype {
- KS8695_DTYPE_WAN,
- KS8695_DTYPE_LAN,
- KS8695_DTYPE_HPNA,
-};
-
-/**
- * struct ks8695_priv - Private data for the KS8695 Ethernet
- * @in_suspend: Flag to indicate if we're suspending/resuming
- * @ndev: The net_device for this interface
- * @dev: The platform device object for this interface
- * @dtype: The type of this device
- * @io_regs: The ioremapped registers for this interface
- * @napi : Add support NAPI for Rx
- * @rx_irq_name: The textual name of the RX IRQ from the platform data
- * @tx_irq_name: The textual name of the TX IRQ from the platform data
- * @link_irq_name: The textual name of the link IRQ from the
- * platform data if available
- * @rx_irq: The IRQ number for the RX IRQ
- * @tx_irq: The IRQ number for the TX IRQ
- * @link_irq: The IRQ number for the link IRQ if available
- * @regs_req: The resource request for the registers region
- * @phyiface_req: The resource request for the phy/switch region
- * if available
- * @phyiface_regs: The ioremapped registers for the phy/switch if available
- * @ring_base: The base pointer of the dma coherent memory for the rings
- * @ring_base_dma: The DMA mapped equivalent of ring_base
- * @tx_ring: The pointer in ring_base of the TX ring
- * @tx_ring_used: The number of slots in the TX ring which are occupied
- * @tx_ring_next_slot: The next slot to fill in the TX ring
- * @tx_ring_dma: The DMA mapped equivalent of tx_ring
- * @tx_buffers: The sk_buff mappings for the TX ring
- * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
- * @rx_ring: The pointer in ring_base of the RX ring
- * @rx_ring_dma: The DMA mapped equivalent of rx_ring
- * @rx_buffers: The sk_buff mappings for the RX ring
- * @next_rx_desc_read: The next RX descriptor to read from on IRQ
- * @rx_lock: A lock to protect Rx irq function
- * @msg_enable: The flags for which messages to emit
- */
-struct ks8695_priv {
- int in_suspend;
- struct net_device *ndev;
- struct device *dev;
- enum ks8695_dtype dtype;
- void __iomem *io_regs;
-
- struct napi_struct napi;
-
- const char *rx_irq_name, *tx_irq_name, *link_irq_name;
- int rx_irq, tx_irq, link_irq;
-
- struct resource *regs_req, *phyiface_req;
- void __iomem *phyiface_regs;
-
- void *ring_base;
- dma_addr_t ring_base_dma;
-
- struct tx_ring_desc *tx_ring;
- int tx_ring_used;
- int tx_ring_next_slot;
- dma_addr_t tx_ring_dma;
- struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
- spinlock_t txq_lock;
-
- struct rx_ring_desc *rx_ring;
- dma_addr_t rx_ring_dma;
- struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
- int next_rx_desc_read;
- spinlock_t rx_lock;
-
- int msg_enable;
-};
-
-/* Register access */
-
-/**
- * ks8695_readreg - Read from a KS8695 ethernet register
- * @ksp: The device to read from
- * @reg: The register to read
- */
-static inline u32
-ks8695_readreg(struct ks8695_priv *ksp, int reg)
-{
- return readl(ksp->io_regs + reg);
-}
-
-/**
- * ks8695_writereg - Write to a KS8695 ethernet register
- * @ksp: The device to write to
- * @reg: The register to write
- * @value: The value to write to the register
- */
-static inline void
-ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
-{
- writel(value, ksp->io_regs + reg);
-}
-
-/* Utility functions */
-
-/**
- * ks8695_port_type - Retrieve port-type as user-friendly string
- * @ksp: The device to return the type for
- *
- * Returns a string indicating which of the WAN, LAN or HPNA
- * ports this device is likely to represent.
- */
-static const char *
-ks8695_port_type(struct ks8695_priv *ksp)
-{
- switch (ksp->dtype) {
- case KS8695_DTYPE_LAN:
- return "LAN";
- case KS8695_DTYPE_WAN:
- return "WAN";
- case KS8695_DTYPE_HPNA:
- return "HPNA";
- }
-
- return "UNKNOWN";
-}
-
-/**
- * ks8695_update_mac - Update the MAC registers in the device
- * @ksp: The device to update
- *
- * Updates the MAC registers in the KS8695 device from the address in the
- * net_device structure associated with this interface.
- */
-static void
-ks8695_update_mac(struct ks8695_priv *ksp)
-{
- /* Update the HW with the MAC from the net_device */
- struct net_device *ndev = ksp->ndev;
- u32 machigh, maclow;
-
- maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
- (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0));
- machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0));
-
- ks8695_writereg(ksp, KS8695_MAL, maclow);
- ks8695_writereg(ksp, KS8695_MAH, machigh);
-
-}
-
-/**
- * ks8695_refill_rxbuffers - Re-fill the RX buffer ring
- * @ksp: The device to refill
- *
- * Iterates the RX ring of the device looking for empty slots.
- * For each empty slot, we allocate and map a new SKB and give it
- * to the hardware.
- * This can be called from interrupt context safely.
- */
-static void
-ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
-{
- /* Run around the RX ring, filling in any missing sk_buff's */
- int buff_n;
-
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- if (!ksp->rx_buffers[buff_n].skb) {
- struct sk_buff *skb =
- netdev_alloc_skb(ksp->ndev, MAX_RXBUF_SIZE);
- dma_addr_t mapping;
-
- ksp->rx_buffers[buff_n].skb = skb;
- if (skb == NULL) {
- /* Failed to allocate one, perhaps
- * we'll try again later.
- */
- break;
- }
-
- mapping = dma_map_single(ksp->dev, skb->data,
- MAX_RXBUF_SIZE,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
- /* Failed to DMA map this SKB, try later */
- dev_kfree_skb_irq(skb);
- ksp->rx_buffers[buff_n].skb = NULL;
- break;
- }
- ksp->rx_buffers[buff_n].dma_ptr = mapping;
- ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
-
- /* Record this into the DMA ring */
- ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
- ksp->rx_ring[buff_n].length =
- cpu_to_le32(MAX_RXBUF_SIZE);
-
- wmb();
-
- /* And give ownership over to the hardware */
- ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
- }
- }
-}
-
-/* Maximum number of multicast addresses which the KS8695 HW supports */
-#define KS8695_NR_ADDRESSES 16
-
-/**
- * ks8695_init_partial_multicast - Init the mcast addr registers
- * @ksp: The device to initialise
- * @addr: The multicast address list to use
- * @nr_addr: The number of addresses in the list
- *
- * This routine is a helper for ks8695_set_multicast - it writes
- * the additional-address registers in the KS8695 ethernet device
- * and cleans up any others left behind.
- */
-static void
-ks8695_init_partial_multicast(struct ks8695_priv *ksp,
- struct net_device *ndev)
-{
- u32 low, high;
- int i;
- struct netdev_hw_addr *ha;
-
- i = 0;
- netdev_for_each_mc_addr(ha, ndev) {
- /* Ran out of space in chip? */
- BUG_ON(i == KS8695_NR_ADDRESSES);
-
- low = (ha->addr[2] << 24) | (ha->addr[3] << 16) |
- (ha->addr[4] << 8) | (ha->addr[5]);
- high = (ha->addr[0] << 8) | (ha->addr[1]);
-
- ks8695_writereg(ksp, KS8695_AAL_(i), low);
- ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
- i++;
- }
-
- /* Clear the remaining Additional Station Addresses */
- for (; i < KS8695_NR_ADDRESSES; i++) {
- ks8695_writereg(ksp, KS8695_AAL_(i), 0);
- ks8695_writereg(ksp, KS8695_AAH_(i), 0);
- }
-}
-
-/* Interrupt handling */
-
-/**
- * ks8695_tx_irq - Transmit IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * Process the TX ring, clearing out any transmitted slots.
- * Allows the net_device to pass us new packets once slots are
- * freed.
- */
-static irqreturn_t
-ks8695_tx_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int buff_n;
-
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- if (ksp->tx_buffers[buff_n].skb &&
- !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
- rmb();
- /* An SKB which is not owned by HW is present */
- /* Update the stats for the net_device */
- ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
-
- /* Free the packet from the ring */
- ksp->tx_ring[buff_n].data_ptr = 0;
-
- /* Free the sk_buff */
- dma_unmap_single(ksp->dev,
- ksp->tx_buffers[buff_n].dma_ptr,
- ksp->tx_buffers[buff_n].length,
- DMA_TO_DEVICE);
- dev_consume_skb_irq(ksp->tx_buffers[buff_n].skb);
- ksp->tx_buffers[buff_n].skb = NULL;
- ksp->tx_ring_used--;
- }
- }
-
- netif_wake_queue(ndev);
-
- return IRQ_HANDLED;
-}
-
-/**
- * ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit
- * @ksp: Private data for the KS8695 Ethernet
- *
- * For KS8695 document:
- * Interrupt Enable Register (offset 0xE204)
- * Bit29 : WAN MAC Receive Interrupt Enable
- * Bit16 : LAN MAC Receive Interrupt Enable
- * Interrupt Status Register (Offset 0xF208)
- * Bit29: WAN MAC Receive Status
- * Bit16: LAN MAC Receive Status
- * So, this Rx interrupt enable/status bit number is equal
- * as Rx IRQ number.
- */
-static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
-{
- return ksp->rx_irq;
-}
-
-/**
- * ks8695_rx_irq - Receive IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * Inform NAPI that packet reception needs to be scheduled
- */
-
-static irqreturn_t
-ks8695_rx_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- spin_lock(&ksp->rx_lock);
-
- if (napi_schedule_prep(&ksp->napi)) {
- unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
- /*disable rx interrupt*/
- status &= ~mask_bit;
- writel(status , KS8695_IRQ_VA + KS8695_INTEN);
- __napi_schedule(&ksp->napi);
- }
-
- spin_unlock(&ksp->rx_lock);
- return IRQ_HANDLED;
-}
-
-/**
- * ks8695_rx - Receive packets called by NAPI poll method
- * @ksp: Private data for the KS8695 Ethernet
- * @budget: Number of packets allowed to process
- */
-static int ks8695_rx(struct ks8695_priv *ksp, int budget)
-{
- struct net_device *ndev = ksp->ndev;
- struct sk_buff *skb;
- int buff_n;
- u32 flags;
- int pktlen;
- int received = 0;
-
- buff_n = ksp->next_rx_desc_read;
- while (received < budget
- && ksp->rx_buffers[buff_n].skb
- && (!(ksp->rx_ring[buff_n].status &
- cpu_to_le32(RDES_OWN)))) {
- rmb();
- flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
-
- /* Found an SKB which we own, this means we
- * received a packet
- */
- if ((flags & (RDES_FS | RDES_LS)) !=
- (RDES_FS | RDES_LS)) {
- /* This packet is not the first and
- * the last segment. Therefore it is
- * a "spanning" packet and we can't
- * handle it
- */
- goto rx_failure;
- }
-
- if (flags & (RDES_ES | RDES_RE)) {
- /* It's an error packet */
- ndev->stats.rx_errors++;
- if (flags & RDES_TL)
- ndev->stats.rx_length_errors++;
- if (flags & RDES_RF)
- ndev->stats.rx_length_errors++;
- if (flags & RDES_CE)
- ndev->stats.rx_crc_errors++;
- if (flags & RDES_RE)
- ndev->stats.rx_missed_errors++;
-
- goto rx_failure;
- }
-
- pktlen = flags & RDES_FLEN;
- pktlen -= 4; /* Drop the CRC */
-
- /* Retrieve the sk_buff */
- skb = ksp->rx_buffers[buff_n].skb;
-
- /* Clear it from the ring */
- ksp->rx_buffers[buff_n].skb = NULL;
- ksp->rx_ring[buff_n].data_ptr = 0;
-
- /* Unmap the SKB */
- dma_unmap_single(ksp->dev,
- ksp->rx_buffers[buff_n].dma_ptr,
- ksp->rx_buffers[buff_n].length,
- DMA_FROM_DEVICE);
-
- /* Relinquish the SKB to the network layer */
- skb_put(skb, pktlen);
- skb->protocol = eth_type_trans(skb, ndev);
- napi_gro_receive(&ksp->napi, skb);
-
- /* Record stats */
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += pktlen;
- goto rx_finished;
-
-rx_failure:
- /* This ring entry is an error, but we can
- * re-use the skb
- */
- /* Give the ring entry back to the hardware */
- ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-rx_finished:
- received++;
- buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
- }
-
- /* And note which RX descriptor we last did */
- ksp->next_rx_desc_read = buff_n;
-
- /* And refill the buffers */
- ks8695_refill_rxbuffers(ksp);
-
- /* Kick the RX DMA engine, in case it became suspended */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
-
- return received;
-}
-
-
-/**
- * ks8695_poll - Receive packet by NAPI poll method
- * @ksp: Private data for the KS8695 Ethernet
- * @budget: The remaining number packets for network subsystem
- *
- * Invoked by the network core when it requests for new
- * packets from the driver
- */
-static int ks8695_poll(struct napi_struct *napi, int budget)
-{
- struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
- unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN);
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
- int work_done;
-
- work_done = ks8695_rx(ksp, budget);
-
- if (work_done < budget && napi_complete_done(napi, work_done)) {
- unsigned long flags;
-
- spin_lock_irqsave(&ksp->rx_lock, flags);
- /* enable rx interrupt */
- writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
- spin_unlock_irqrestore(&ksp->rx_lock, flags);
- }
- return work_done;
-}
-
-/**
- * ks8695_link_irq - Link change IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * The WAN interface can generate an IRQ when the link changes,
- * report this to the net layer and the user.
- */
-static irqreturn_t
-ks8695_link_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
- if (ctrl & WMC_WLS) {
- netif_carrier_on(ndev);
- if (netif_msg_link(ksp))
- dev_info(ksp->dev,
- "%s: Link is now up (10%sMbps/%s-duplex)\n",
- ndev->name,
- (ctrl & WMC_WSS) ? "0" : "",
- (ctrl & WMC_WDS) ? "Full" : "Half");
- } else {
- netif_carrier_off(ndev);
- if (netif_msg_link(ksp))
- dev_info(ksp->dev, "%s: Link is now down.\n",
- ndev->name);
- }
-
- return IRQ_HANDLED;
-}
-
-
-/* KS8695 Device functions */
-
-/**
- * ks8695_reset - Reset a KS8695 ethernet interface
- * @ksp: The interface to reset
- *
- * Perform an engine reset of the interface and re-program it
- * with sensible defaults.
- */
-static void
-ks8695_reset(struct ks8695_priv *ksp)
-{
- int reset_timeout = watchdog;
- /* Issue the reset via the TX DMA control register */
- ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
- while (reset_timeout--) {
- if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
- break;
- msleep(1);
- }
-
- if (reset_timeout < 0) {
- dev_crit(ksp->dev,
- "Timeout waiting for DMA engines to reset\n");
- /* And blithely carry on */
- }
-
- /* Definitely wait long enough before attempting to program
- * the engines
- */
- msleep(10);
-
- /* RX: unicast and broadcast */
- ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
- /* TX: pad and add CRC */
- ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
-}
-
-/**
- * ks8695_shutdown - Shut down a KS8695 ethernet interface
- * @ksp: The interface to shut down
- *
- * This disables packet RX/TX, cleans up IRQs, drains the rings,
- * and basically places the interface into a clean shutdown
- * state.
- */
-static void
-ks8695_shutdown(struct ks8695_priv *ksp)
-{
- u32 ctrl;
- int buff_n;
-
- /* Disable packet transmission */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
-
- /* Disable packet reception */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
-
- /* Release the IRQs */
- free_irq(ksp->rx_irq, ksp->ndev);
- free_irq(ksp->tx_irq, ksp->ndev);
- if (ksp->link_irq != -1)
- free_irq(ksp->link_irq, ksp->ndev);
-
- /* Throw away any pending TX packets */
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- if (ksp->tx_buffers[buff_n].skb) {
- /* Remove this SKB from the TX ring */
- ksp->tx_ring[buff_n].owner = 0;
- ksp->tx_ring[buff_n].status = 0;
- ksp->tx_ring[buff_n].data_ptr = 0;
-
- /* Unmap and bin this SKB */
- dma_unmap_single(ksp->dev,
- ksp->tx_buffers[buff_n].dma_ptr,
- ksp->tx_buffers[buff_n].length,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
- ksp->tx_buffers[buff_n].skb = NULL;
- }
- }
-
- /* Purge the RX buffers */
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- if (ksp->rx_buffers[buff_n].skb) {
- /* Remove the SKB from the RX ring */
- ksp->rx_ring[buff_n].status = 0;
- ksp->rx_ring[buff_n].data_ptr = 0;
-
- /* Unmap and bin the SKB */
- dma_unmap_single(ksp->dev,
- ksp->rx_buffers[buff_n].dma_ptr,
- ksp->rx_buffers[buff_n].length,
- DMA_FROM_DEVICE);
- dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
- ksp->rx_buffers[buff_n].skb = NULL;
- }
- }
-}
-
-
-/**
- * ks8695_setup_irq - IRQ setup helper function
- * @irq: The IRQ number to claim
- * @irq_name: The name to give the IRQ claimant
- * @handler: The function to call to handle the IRQ
- * @ndev: The net_device to pass in as the dev_id argument to the handler
- *
- * Return 0 on success.
- */
-static int
-ks8695_setup_irq(int irq, const char *irq_name,
- irq_handler_t handler, struct net_device *ndev)
-{
- int ret;
-
- ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
-
- if (ret) {
- dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
- return ret;
- }
-
- return 0;
-}
-
-/**
- * ks8695_init_net - Initialise a KS8695 ethernet interface
- * @ksp: The interface to initialise
- *
- * This routine fills the RX ring, initialises the DMA engines,
- * allocates the IRQs and then starts the packet TX and RX
- * engines.
- */
-static int
-ks8695_init_net(struct ks8695_priv *ksp)
-{
- int ret;
- u32 ctrl;
-
- ks8695_refill_rxbuffers(ksp);
-
- /* Initialise the DMA engines */
- ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
- ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
-
- /* Request the IRQs */
- ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
- ks8695_rx_irq, ksp->ndev);
- if (ret)
- return ret;
- ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
- ks8695_tx_irq, ksp->ndev);
- if (ret)
- return ret;
- if (ksp->link_irq != -1) {
- ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
- ks8695_link_irq, ksp->ndev);
- if (ret)
- return ret;
- }
-
- /* Set up the ring indices */
- ksp->next_rx_desc_read = 0;
- ksp->tx_ring_next_slot = 0;
- ksp->tx_ring_used = 0;
-
- /* Bring up transmission */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- /* Enable packet transmission */
- ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
-
- /* Bring up the reception */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- /* Enable packet reception */
- ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
- /* And start the DMA engine */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
-
- /* All done */
- return 0;
-}
-
-/**
- * ks8695_release_device - HW resource release for KS8695 e-net
- * @ksp: The device to be freed
- *
- * This unallocates io memory regions, dma-coherent regions etc
- * which were allocated in ks8695_probe.
- */
-static void
-ks8695_release_device(struct ks8695_priv *ksp)
-{
- /* Unmap the registers */
- iounmap(ksp->io_regs);
- if (ksp->phyiface_regs)
- iounmap(ksp->phyiface_regs);
-
- /* And release the request */
- release_resource(ksp->regs_req);
- kfree(ksp->regs_req);
- if (ksp->phyiface_req) {
- release_resource(ksp->phyiface_req);
- kfree(ksp->phyiface_req);
- }
-
- /* Free the ring buffers */
- dma_free_coherent(ksp->dev, RING_DMA_SIZE,
- ksp->ring_base, ksp->ring_base_dma);
-}
-
-/* Ethtool support */
-
-/**
- * ks8695_get_msglevel - Get the messages enabled for emission
- * @ndev: The network device to read from
- */
-static u32
-ks8695_get_msglevel(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- return ksp->msg_enable;
-}
-
-/**
- * ks8695_set_msglevel - Set the messages enabled for emission
- * @ndev: The network device to configure
- * @value: The messages to set for emission
- */
-static void
-ks8695_set_msglevel(struct net_device *ndev, u32 value)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- ksp->msg_enable = value;
-}
-
-/**
- * ks8695_wan_get_link_ksettings - Get device-specific settings.
- * @ndev: The network device to read settings from
- * @cmd: The ethtool structure to read into
- */
-static int
-ks8695_wan_get_link_ksettings(struct net_device *ndev,
- struct ethtool_link_ksettings *cmd)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
- u32 supported, advertising;
-
- /* All ports on the KS8695 support these... */
- supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
- SUPPORTED_TP | SUPPORTED_MII);
-
- advertising = ADVERTISED_TP | ADVERTISED_MII;
- cmd->base.port = PORT_MII;
- supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
- cmd->base.phy_address = 0;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
- if ((ctrl & WMC_WAND) == 0) {
- /* auto-negotiation is enabled */
- advertising |= ADVERTISED_Autoneg;
- if (ctrl & WMC_WANA100F)
- advertising |= ADVERTISED_100baseT_Full;
- if (ctrl & WMC_WANA100H)
- advertising |= ADVERTISED_100baseT_Half;
- if (ctrl & WMC_WANA10F)
- advertising |= ADVERTISED_10baseT_Full;
- if (ctrl & WMC_WANA10H)
- advertising |= ADVERTISED_10baseT_Half;
- if (ctrl & WMC_WANAP)
- advertising |= ADVERTISED_Pause;
- cmd->base.autoneg = AUTONEG_ENABLE;
-
- cmd->base.speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
- cmd->base.duplex = (ctrl & WMC_WDS) ?
- DUPLEX_FULL : DUPLEX_HALF;
- } else {
- /* auto-negotiation is disabled */
- cmd->base.autoneg = AUTONEG_DISABLE;
-
- cmd->base.speed = (ctrl & WMC_WANF100) ?
- SPEED_100 : SPEED_10;
- cmd->base.duplex = (ctrl & WMC_WANFF) ?
- DUPLEX_FULL : DUPLEX_HALF;
- }
-
- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
- supported);
- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
- advertising);
-
- return 0;
-}
-
-/**
- * ks8695_wan_set_link_ksettings - Set device-specific settings.
- * @ndev: The network device to configure
- * @cmd: The settings to configure
- */
-static int
-ks8695_wan_set_link_ksettings(struct net_device *ndev,
- const struct ethtool_link_ksettings *cmd)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
- u32 advertising;
-
- ethtool_convert_link_mode_to_legacy_u32(&advertising,
- cmd->link_modes.advertising);
-
- if ((cmd->base.speed != SPEED_10) && (cmd->base.speed != SPEED_100))
- return -EINVAL;
- if ((cmd->base.duplex != DUPLEX_HALF) &&
- (cmd->base.duplex != DUPLEX_FULL))
- return -EINVAL;
- if (cmd->base.port != PORT_MII)
- return -EINVAL;
- if ((cmd->base.autoneg != AUTONEG_DISABLE) &&
- (cmd->base.autoneg != AUTONEG_ENABLE))
- return -EINVAL;
-
- if (cmd->base.autoneg == AUTONEG_ENABLE) {
- if ((advertising & (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full)) == 0)
- return -EINVAL;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
- WMC_WANA10F | WMC_WANA10H);
- if (advertising & ADVERTISED_100baseT_Full)
- ctrl |= WMC_WANA100F;
- if (advertising & ADVERTISED_100baseT_Half)
- ctrl |= WMC_WANA100H;
- if (advertising & ADVERTISED_10baseT_Full)
- ctrl |= WMC_WANA10F;
- if (advertising & ADVERTISED_10baseT_Half)
- ctrl |= WMC_WANA10H;
-
- /* force a re-negotiation */
- ctrl |= WMC_WANR;
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
- } else {
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- /* disable auto-negotiation */
- ctrl |= WMC_WAND;
- ctrl &= ~(WMC_WANF100 | WMC_WANFF);
-
- if (cmd->base.speed == SPEED_100)
- ctrl |= WMC_WANF100;
- if (cmd->base.duplex == DUPLEX_FULL)
- ctrl |= WMC_WANFF;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
- }
-
- return 0;
-}
-
-/**
- * ks8695_wan_nwayreset - Restart the autonegotiation on the port.
- * @ndev: The network device to restart autoneotiation on
- */
-static int
-ks8695_wan_nwayreset(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- if ((ctrl & WMC_WAND) == 0)
- writel(ctrl | WMC_WANR,
- ksp->phyiface_regs + KS8695_WMC);
- else
- /* auto-negotiation not enabled */
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
- * @ndev: The device to retrieve settings from
- * @param: The structure to fill out with the information
- */
-static void
-ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- /* advertise Pause */
- param->autoneg = (ctrl & WMC_WANAP);
-
- /* current Rx Flow-control */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- param->rx_pause = (ctrl & DRXC_RFCE);
-
- /* current Tx Flow-control */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- param->tx_pause = (ctrl & DTXC_TFCE);
-}
-
-/**
- * ks8695_get_drvinfo - Retrieve driver information
- * @ndev: The network device to retrieve info about
- * @info: The info structure to fill out.
- */
-static void
-ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, MODULENAME, sizeof(info->driver));
- strlcpy(info->version, MODULEVERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(ndev->dev.parent),
- sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops ks8695_ethtool_ops = {
- .get_msglevel = ks8695_get_msglevel,
- .set_msglevel = ks8695_set_msglevel,
- .get_drvinfo = ks8695_get_drvinfo,
-};
-
-static const struct ethtool_ops ks8695_wan_ethtool_ops = {
- .get_msglevel = ks8695_get_msglevel,
- .set_msglevel = ks8695_set_msglevel,
- .nway_reset = ks8695_wan_nwayreset,
- .get_link = ethtool_op_get_link,
- .get_pauseparam = ks8695_wan_get_pause,
- .get_drvinfo = ks8695_get_drvinfo,
- .get_link_ksettings = ks8695_wan_get_link_ksettings,
- .set_link_ksettings = ks8695_wan_set_link_ksettings,
-};
-
-/* Network device interface functions */
-
-/**
- * ks8695_set_mac - Update MAC in net dev and HW
- * @ndev: The network device to update
- * @addr: The new MAC address to set
- */
-static int
-ks8695_set_mac(struct net_device *ndev, void *addr)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
-
- ks8695_update_mac(ksp);
-
- dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
- ndev->name, ndev->dev_addr);
-
- return 0;
-}
-
-/**
- * ks8695_set_multicast - Set up the multicast behaviour of the interface
- * @ndev: The net_device to configure
- *
- * This routine, called by the net layer, configures promiscuity
- * and multicast reception behaviour for the interface.
- */
-static void
-ks8695_set_multicast(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-
- if (ndev->flags & IFF_PROMISC) {
- /* enable promiscuous mode */
- ctrl |= DRXC_RA;
- } else if (ndev->flags & ~IFF_PROMISC) {
- /* disable promiscuous mode */
- ctrl &= ~DRXC_RA;
- }
-
- if (ndev->flags & IFF_ALLMULTI) {
- /* enable all multicast mode */
- ctrl |= DRXC_RM;
- } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) {
- /* more specific multicast addresses than can be
- * handled in hardware
- */
- ctrl |= DRXC_RM;
- } else {
- /* enable specific multicasts */
- ctrl &= ~DRXC_RM;
- ks8695_init_partial_multicast(ksp, ndev);
- }
-
- ks8695_writereg(ksp, KS8695_DRXC, ctrl);
-}
-
-/**
- * ks8695_timeout - Handle a network tx/rx timeout.
- * @ndev: The net_device which timed out.
- *
- * A network transaction timed out, reset the device.
- */
-static void
-ks8695_timeout(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- netif_stop_queue(ndev);
- ks8695_shutdown(ksp);
-
- ks8695_reset(ksp);
-
- ks8695_update_mac(ksp);
-
- /* We ignore the return from this since it managed to init
- * before it probably will be okay to init again.
- */
- ks8695_init_net(ksp);
-
- /* Reconfigure promiscuity etc */
- ks8695_set_multicast(ndev);
-
- /* And start the TX queue once more */
- netif_start_queue(ndev);
-}
-
-/**
- * ks8695_start_xmit - Start a packet transmission
- * @skb: The packet to transmit
- * @ndev: The network device to send the packet on
- *
- * This routine, called by the net layer, takes ownership of the
- * sk_buff and adds it to the TX ring. It then kicks the TX DMA
- * engine to ensure transmission begins.
- */
-static netdev_tx_t
-ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int buff_n;
- dma_addr_t dmap;
-
- spin_lock_irq(&ksp->txq_lock);
-
- if (ksp->tx_ring_used == MAX_TX_DESC) {
- /* Somehow we got entered when we have no room */
- spin_unlock_irq(&ksp->txq_lock);
- return NETDEV_TX_BUSY;
- }
-
- buff_n = ksp->tx_ring_next_slot;
-
- BUG_ON(ksp->tx_buffers[buff_n].skb);
-
- dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
- /* Failed to DMA map this SKB, give it back for now */
- spin_unlock_irq(&ksp->txq_lock);
- dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
- "transmission, trying later\n", ndev->name);
- return NETDEV_TX_BUSY;
- }
-
- ksp->tx_buffers[buff_n].dma_ptr = dmap;
- /* Mapped okay, store the buffer pointer and length for later */
- ksp->tx_buffers[buff_n].skb = skb;
- ksp->tx_buffers[buff_n].length = skb->len;
-
- /* Fill out the TX descriptor */
- ksp->tx_ring[buff_n].data_ptr =
- cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
- ksp->tx_ring[buff_n].status =
- cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
- (skb->len & TDES_TBS));
-
- wmb();
-
- /* Hand it over to the hardware */
- ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
-
- if (++ksp->tx_ring_used == MAX_TX_DESC)
- netif_stop_queue(ndev);
-
- /* Kick the TX DMA in case it decided to go IDLE */
- ks8695_writereg(ksp, KS8695_DTSC, 0);
-
- /* And update the next ring slot */
- ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
-
- spin_unlock_irq(&ksp->txq_lock);
- return NETDEV_TX_OK;
-}
-
-/**
- * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
- * @ndev: The net_device to stop
- *
- * This disables the TX queue and cleans up a KS8695 ethernet
- * device.
- */
-static int
-ks8695_stop(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- netif_stop_queue(ndev);
- napi_disable(&ksp->napi);
-
- ks8695_shutdown(ksp);
-
- return 0;
-}
-
-/**
- * ks8695_open - Open (bring up) a KS8695 ethernet interface
- * @ndev: The net_device to open
- *
- * This resets, configures the MAC, initialises the RX ring and
- * DMA engines and starts the TX queue for a KS8695 ethernet
- * device.
- */
-static int
-ks8695_open(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int ret;
-
- ks8695_reset(ksp);
-
- ks8695_update_mac(ksp);
-
- ret = ks8695_init_net(ksp);
- if (ret) {
- ks8695_shutdown(ksp);
- return ret;
- }
-
- napi_enable(&ksp->napi);
- netif_start_queue(ndev);
-
- return 0;
-}
-
-/* Platform device driver */
-
-/**
- * ks8695_init_switch - Init LAN switch to known good defaults.
- * @ksp: The device to initialise
- *
- * This initialises the LAN switch in the KS8695 to a known-good
- * set of defaults.
- */
-static void
-ks8695_init_switch(struct ks8695_priv *ksp)
-{
- u32 ctrl;
-
- /* Default value for SEC0 according to datasheet */
- ctrl = 0x40819e00;
-
- /* LED0 = Speed LED1 = Link/Activity */
- ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
- ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
-
- /* Enable Switch */
- ctrl |= SEC0_ENABLE;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
-
- /* Defaults for SEC1 */
- writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
-}
-
-/**
- * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
- * @ksp: The device to initialise
- *
- * This initialises a KS8695's WAN phy to sensible values for
- * autonegotiation etc.
- */
-static void
-ks8695_init_wan_phy(struct ks8695_priv *ksp)
-{
- u32 ctrl;
-
- /* Support auto-negotiation */
- ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
- WMC_WANA10F | WMC_WANA10H);
-
- /* LED0 = Activity , LED1 = Link */
- ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
-
- /* Restart Auto-negotiation */
- ctrl |= WMC_WANR;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-
- writel(0, ksp->phyiface_regs + KS8695_WPPM);
- writel(0, ksp->phyiface_regs + KS8695_PPS);
-}
-
-static const struct net_device_ops ks8695_netdev_ops = {
- .ndo_open = ks8695_open,
- .ndo_stop = ks8695_stop,
- .ndo_start_xmit = ks8695_start_xmit,
- .ndo_tx_timeout = ks8695_timeout,
- .ndo_set_mac_address = ks8695_set_mac,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_rx_mode = ks8695_set_multicast,
-};
-
-/**
- * ks8695_probe - Probe and initialise a KS8695 ethernet interface
- * @pdev: The platform device to probe
- *
- * Initialise a KS8695 ethernet device from platform data.
- *
- * This driver requires at least one IORESOURCE_MEM for the
- * registers and two IORESOURCE_IRQ for the RX and TX IRQs
- * respectively. It can optionally take an additional
- * IORESOURCE_MEM for the switch or phy in the case of the lan or
- * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
- * port.
- */
-static int
-ks8695_probe(struct platform_device *pdev)
-{
- struct ks8695_priv *ksp;
- struct net_device *ndev;
- struct resource *regs_res, *phyiface_res;
- struct resource *rxirq_res, *txirq_res, *linkirq_res;
- int ret = 0;
- int buff_n;
- bool inv_mac_addr = false;
- u32 machigh, maclow;
-
- /* Initialise a net_device */
- ndev = alloc_etherdev(sizeof(struct ks8695_priv));
- if (!ndev)
- return -ENOMEM;
-
- SET_NETDEV_DEV(ndev, &pdev->dev);
-
- dev_dbg(&pdev->dev, "ks8695_probe() called\n");
-
- /* Configure our private structure a little */
- ksp = netdev_priv(ndev);
-
- ksp->dev = &pdev->dev;
- ksp->ndev = ndev;
- ksp->msg_enable = NETIF_MSG_LINK;
-
- /* Retrieve resources */
- regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
- rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
- linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-
- if (!(regs_res && rxirq_res && txirq_res)) {
- dev_err(ksp->dev, "insufficient resources\n");
- ret = -ENOENT;
- goto failure;
- }
-
- ksp->regs_req = request_mem_region(regs_res->start,
- resource_size(regs_res),
- pdev->name);
-
- if (!ksp->regs_req) {
- dev_err(ksp->dev, "cannot claim register space\n");
- ret = -EIO;
- goto failure;
- }
-
- ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
-
- if (!ksp->io_regs) {
- dev_err(ksp->dev, "failed to ioremap registers\n");
- ret = -EINVAL;
- goto failure;
- }
-
- if (phyiface_res) {
- ksp->phyiface_req =
- request_mem_region(phyiface_res->start,
- resource_size(phyiface_res),
- phyiface_res->name);
-
- if (!ksp->phyiface_req) {
- dev_err(ksp->dev,
- "cannot claim switch register space\n");
- ret = -EIO;
- goto failure;
- }
-
- ksp->phyiface_regs = ioremap(phyiface_res->start,
- resource_size(phyiface_res));
-
- if (!ksp->phyiface_regs) {
- dev_err(ksp->dev,
- "failed to ioremap switch registers\n");
- ret = -EINVAL;
- goto failure;
- }
- }
-
- ksp->rx_irq = rxirq_res->start;
- ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
- ksp->tx_irq = txirq_res->start;
- ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
- ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
- ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
- linkirq_res->name : "Ethernet Link";
-
- /* driver system setup */
- ndev->netdev_ops = &ks8695_netdev_ops;
- ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
-
- netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
-
- /* Retrieve the default MAC addr from the chip. */
- /* The bootloader should have left it in there for us. */
-
- machigh = ks8695_readreg(ksp, KS8695_MAH);
- maclow = ks8695_readreg(ksp, KS8695_MAL);
-
- ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
- ndev->dev_addr[1] = machigh & 0xFF;
- ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
- ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
- ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
- ndev->dev_addr[5] = maclow & 0xFF;
-
- if (!is_valid_ether_addr(ndev->dev_addr))
- inv_mac_addr = true;
-
- /* In order to be efficient memory-wise, we allocate both
- * rings in one go.
- */
- ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
- &ksp->ring_base_dma, GFP_KERNEL);
- if (!ksp->ring_base) {
- ret = -ENOMEM;
- goto failure;
- }
-
- /* Specify the TX DMA ring buffer */
- ksp->tx_ring = ksp->ring_base;
- ksp->tx_ring_dma = ksp->ring_base_dma;
-
- /* And initialise the queue's lock */
- spin_lock_init(&ksp->txq_lock);
- spin_lock_init(&ksp->rx_lock);
-
- /* Specify the RX DMA ring buffer */
- ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
- ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
-
- /* Zero the descriptor rings */
- memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
- memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
-
- /* Build the rings */
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- ksp->tx_ring[buff_n].next_desc =
- cpu_to_le32(ksp->tx_ring_dma +
- (sizeof(struct tx_ring_desc) *
- ((buff_n + 1) & MAX_TX_DESC_MASK)));
- }
-
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- ksp->rx_ring[buff_n].next_desc =
- cpu_to_le32(ksp->rx_ring_dma +
- (sizeof(struct rx_ring_desc) *
- ((buff_n + 1) & MAX_RX_DESC_MASK)));
- }
-
- /* Initialise the port (physically) */
- if (ksp->phyiface_regs && ksp->link_irq == -1) {
- ks8695_init_switch(ksp);
- ksp->dtype = KS8695_DTYPE_LAN;
- ndev->ethtool_ops = &ks8695_ethtool_ops;
- } else if (ksp->phyiface_regs && ksp->link_irq != -1) {
- ks8695_init_wan_phy(ksp);
- ksp->dtype = KS8695_DTYPE_WAN;
- ndev->ethtool_ops = &ks8695_wan_ethtool_ops;
- } else {
- /* No initialisation since HPNA does not have a PHY */
- ksp->dtype = KS8695_DTYPE_HPNA;
- ndev->ethtool_ops = &ks8695_ethtool_ops;
- }
-
- /* And bring up the net_device with the net core */
- platform_set_drvdata(pdev, ndev);
- ret = register_netdev(ndev);
-
- if (ret == 0) {
- if (inv_mac_addr)
- dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please set using ip\n",
- ndev->name);
- dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
- ks8695_port_type(ksp), ndev->dev_addr);
- } else {
- /* Report the failure to register the net_device */
- dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
- goto failure;
- }
-
- /* All is well */
- return 0;
-
- /* Error exit path */
-failure:
- ks8695_release_device(ksp);
- free_netdev(ndev);
-
- return ret;
-}
-
-/**
- * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
- * @pdev: The device to suspend
- * @state: The suspend state
- *
- * This routine detaches and shuts down a KS8695 ethernet device.
- */
-static int
-ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- ksp->in_suspend = 1;
-
- if (netif_running(ndev)) {
- netif_device_detach(ndev);
- ks8695_shutdown(ksp);
- }
-
- return 0;
-}
-
-/**
- * ks8695_drv_resume - Resume a KS8695 ethernet platform device.
- * @pdev: The device to resume
- *
- * This routine re-initialises and re-attaches a KS8695 ethernet
- * device.
- */
-static int
-ks8695_drv_resume(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- if (netif_running(ndev)) {
- ks8695_reset(ksp);
- ks8695_init_net(ksp);
- ks8695_set_multicast(ndev);
- netif_device_attach(ndev);
- }
-
- ksp->in_suspend = 0;
-
- return 0;
-}
-
-/**
- * ks8695_drv_remove - Remove a KS8695 net device on driver unload.
- * @pdev: The platform device to remove
- *
- * This unregisters and releases a KS8695 ethernet device.
- */
-static int
-ks8695_drv_remove(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- netif_napi_del(&ksp->napi);
-
- unregister_netdev(ndev);
- ks8695_release_device(ksp);
- free_netdev(ndev);
-
- dev_dbg(&pdev->dev, "released and freed device\n");
- return 0;
-}
-
-static struct platform_driver ks8695_driver = {
- .driver = {
- .name = MODULENAME,
- },
- .probe = ks8695_probe,
- .remove = ks8695_drv_remove,
- .suspend = ks8695_drv_suspend,
- .resume = ks8695_drv_resume,
-};
-
-module_platform_driver(ks8695_driver);
-
-MODULE_AUTHOR("Simtec Electronics");
-MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" MODULENAME);
-
-module_param(watchdog, int, 0400);
-MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
diff --git a/drivers/net/ethernet/micrel/ks8695net.h b/drivers/net/ethernet/micrel/ks8695net.h
deleted file mode 100644
index b18fad4ad5fd..000000000000
--- a/drivers/net/ethernet/micrel/ks8695net.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- * Vincent Sanders <vince@simtec.co.uk>
- */
-
-#ifndef KS8695NET_H
-#define KS8695NET_H
-
-/* Receive descriptor flags */
-#define RDES_OWN (1 << 31) /* Ownership */
-#define RDES_FS (1 << 30) /* First Descriptor */
-#define RDES_LS (1 << 29) /* Last Descriptor */
-#define RDES_IPE (1 << 28) /* IP Checksum error */
-#define RDES_TCPE (1 << 27) /* TCP Checksum error */
-#define RDES_UDPE (1 << 26) /* UDP Checksum error */
-#define RDES_ES (1 << 25) /* Error summary */
-#define RDES_MF (1 << 24) /* Multicast Frame */
-#define RDES_RE (1 << 19) /* MII Error reported */
-#define RDES_TL (1 << 18) /* Frame too Long */
-#define RDES_RF (1 << 17) /* Runt Frame */
-#define RDES_CE (1 << 16) /* CRC error */
-#define RDES_FT (1 << 15) /* Frame Type */
-#define RDES_FLEN (0x7ff) /* Frame Length */
-
-#define RDES_RER (1 << 25) /* Receive End of Ring */
-#define RDES_RBS (0x7ff) /* Receive Buffer Size */
-
-/* Transmit descriptor flags */
-
-#define TDES_OWN (1 << 31) /* Ownership */
-
-#define TDES_IC (1 << 31) /* Interrupt on Completion */
-#define TDES_FS (1 << 30) /* First Segment */
-#define TDES_LS (1 << 29) /* Last Segment */
-#define TDES_IPCKG (1 << 28) /* IP Checksum generate */
-#define TDES_TCPCKG (1 << 27) /* TCP Checksum generate */
-#define TDES_UDPCKG (1 << 26) /* UDP Checksum generate */
-#define TDES_TER (1 << 25) /* Transmit End of Ring */
-#define TDES_TBS (0x7ff) /* Transmit Buffer Size */
-
-/*
- * Network controller register offsets
- */
-#define KS8695_DTXC (0x00) /* DMA Transmit Control */
-#define KS8695_DRXC (0x04) /* DMA Receive Control */
-#define KS8695_DTSC (0x08) /* DMA Transmit Start Command */
-#define KS8695_DRSC (0x0c) /* DMA Receive Start Command */
-#define KS8695_TDLB (0x10) /* Transmit Descriptor List
- * Base Address
- */
-#define KS8695_RDLB (0x14) /* Receive Descriptor List
- * Base Address
- */
-#define KS8695_MAL (0x18) /* MAC Station Address Low */
-#define KS8695_MAH (0x1c) /* MAC Station Address High */
-#define KS8695_AAL_(n) (0x80 + ((n)*8)) /* MAC Additional
- * Station Address
- * (0..15) Low
- */
-#define KS8695_AAH_(n) (0x84 + ((n)*8)) /* MAC Additional
- * Station Address
- * (0..15) High
- */
-
-
-/* DMA Transmit Control Register */
-#define DTXC_TRST (1 << 31) /* Soft Reset */
-#define DTXC_TBS (0x3f << 24) /* Transmit Burst Size */
-#define DTXC_TUCG (1 << 18) /* Transmit UDP
- * Checksum Generate
- */
-#define DTXC_TTCG (1 << 17) /* Transmit TCP
- * Checksum Generate
- */
-#define DTXC_TICG (1 << 16) /* Transmit IP
- * Checksum Generate
- */
-#define DTXC_TFCE (1 << 9) /* Transmit Flow
- * Control Enable
- */
-#define DTXC_TLB (1 << 8) /* Loopback mode */
-#define DTXC_TEP (1 << 2) /* Transmit Enable Padding */
-#define DTXC_TAC (1 << 1) /* Transmit Add CRC */
-#define DTXC_TE (1 << 0) /* TX Enable */
-
-/* DMA Receive Control Register */
-#define DRXC_RBS (0x3f << 24) /* Receive Burst Size */
-#define DRXC_RUCC (1 << 18) /* Receive UDP Checksum check */
-#define DRXC_RTCG (1 << 17) /* Receive TCP Checksum check */
-#define DRXC_RICG (1 << 16) /* Receive IP Checksum check */
-#define DRXC_RFCE (1 << 9) /* Receive Flow Control
- * Enable
- */
-#define DRXC_RB (1 << 6) /* Receive Broadcast */
-#define DRXC_RM (1 << 5) /* Receive Multicast */
-#define DRXC_RU (1 << 4) /* Receive Unicast */
-#define DRXC_RERR (1 << 3) /* Receive Error Frame */
-#define DRXC_RA (1 << 2) /* Receive All */
-#define DRXC_RE (1 << 0) /* RX Enable */
-
-/* Additional Station Address High */
-#define AAH_E (1 << 31) /* Address Enabled */
-
-#endif /* KS8695NET_H */
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index b71e4ecbe469..6932e615d4b0 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1818,6 +1818,7 @@ EXPORT_SYMBOL(ocelot_init);
void ocelot_deinit(struct ocelot *ocelot)
{
+ cancel_delayed_work(&ocelot->stats_work);
destroy_workqueue(ocelot->stats_queue);
mutex_destroy(&ocelot->stats_lock);
ocelot_ace_deinit();
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index 39aca1ab4687..86fc6e6b46dd 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -317,7 +317,7 @@ static void is2_action_set(struct vcap_data *data,
break;
case OCELOT_ACL_ACTION_TRAP:
VCAP_ACT_SET(PORT_MASK, 0x0);
- VCAP_ACT_SET(MASK_MODE, 0x0);
+ VCAP_ACT_SET(MASK_MODE, 0x1);
VCAP_ACT_SET(POLICE_ENA, 0x0);
VCAP_ACT_SET(POLICE_IDX, 0x0);
VCAP_ACT_SET(CPU_QU_NUM, 0x0);
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 59487d446a09..b894bc0c9c16 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -13,12 +13,6 @@ struct ocelot_port_block {
struct ocelot_port *port;
};
-static u16 get_prio(u32 prio)
-{
- /* prio starts from 0x1000 while the ids starts from 0 */
- return prio >> 16;
-}
-
static int ocelot_flower_parse_action(struct flow_cls_offload *f,
struct ocelot_ace_rule *rule)
{
@@ -168,7 +162,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
}
finished_key_parsing:
- ocelot_rule->prio = get_prio(f->common.prio);
+ ocelot_rule->prio = f->common.prio;
ocelot_rule->id = f->cookie;
return ocelot_flower_parse_action(f, ocelot_rule);
}
@@ -218,7 +212,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
struct ocelot_ace_rule rule;
int ret;
- rule.prio = get_prio(f->common.prio);
+ rule.prio = f->common.prio;
rule.port = port_block->port;
rule.id = f->cookie;
@@ -236,7 +230,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
struct ocelot_ace_rule rule;
int ret;
- rule.prio = get_prio(f->common.prio);
+ rule.prio = f->common.prio;
rule.port = port_block->port;
rule.id = f->cookie;
ret = ocelot_ace_rule_stats_update(&rule);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index d8b7fba96d58..337b0cbfd153 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3919,7 +3919,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* setup (if available). */
status = myri10ge_request_irq(mgp);
if (status != 0)
- goto abort_with_firmware;
+ goto abort_with_slices;
myri10ge_free_irq(mgp);
/* Save configuration space to be restored if the
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index d0a01e8f000a..b339125b2f09 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -232,9 +232,9 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
if (!laddr) {
- printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
- dev_kfree_skb(skb);
- return NETDEV_TX_BUSY;
+ pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index 4054b70d7719..5afcb3c4c2ef 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -1163,7 +1163,7 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
bool clr_gpr, lmem_step step)
{
s32 off = nfp_prog->stack_frame_depth + meta->insn.off + ptr_off;
- bool first = true, last;
+ bool first = true, narrow_ld, last;
bool needs_inc = false;
swreg stack_off_reg;
u8 prev_gpr = 255;
@@ -1209,13 +1209,22 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
needs_inc = true;
}
+
+ narrow_ld = clr_gpr && size < 8;
+
if (lm3) {
+ unsigned int nop_cnt;
+
emit_csr_wr(nfp_prog, imm_b(nfp_prog), NFP_CSR_ACT_LM_ADDR3);
- /* For size < 4 one slot will be filled by zeroing of upper. */
- wrp_nops(nfp_prog, clr_gpr && size < 8 ? 2 : 3);
+ /* For size < 4 one slot will be filled by zeroing of upper,
+ * but be careful, that zeroing could be eliminated by zext
+ * optimization.
+ */
+ nop_cnt = narrow_ld && meta->flags & FLAG_INSN_DO_ZEXT ? 2 : 3;
+ wrp_nops(nfp_prog, nop_cnt);
}
- if (clr_gpr && size < 8)
+ if (narrow_ld)
wrp_zext(nfp_prog, meta, gpr);
while (size) {
diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
index d5bbe3d6048b..05981b54eaab 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
@@ -260,9 +260,6 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
type = cmsg_hdr->type;
switch (type) {
- case NFP_FLOWER_CMSG_TYPE_PORT_REIFY:
- nfp_flower_cmsg_portreify_rx(app, skb);
- break;
case NFP_FLOWER_CMSG_TYPE_PORT_MOD:
nfp_flower_cmsg_portmod_rx(app, skb);
break;
@@ -328,8 +325,7 @@ nfp_flower_queue_ctl_msg(struct nfp_app *app, struct sk_buff *skb, int type)
struct nfp_flower_priv *priv = app->priv;
struct sk_buff_head *skb_head;
- if (type == NFP_FLOWER_CMSG_TYPE_PORT_REIFY ||
- type == NFP_FLOWER_CMSG_TYPE_PORT_MOD)
+ if (type == NFP_FLOWER_CMSG_TYPE_PORT_MOD)
skb_head = &priv->cmsg_skbs_high;
else
skb_head = &priv->cmsg_skbs_low;
@@ -368,6 +364,10 @@ void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb)
} else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH) {
/* Acks from the NFP that the route is added - ignore. */
dev_consume_skb_any(skb);
+ } else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_PORT_REIFY) {
+ /* Handle REIFY acks outside wq to prevent RTNL conflict. */
+ nfp_flower_cmsg_portreify_rx(app, skb);
+ dev_consume_skb_any(skb);
} else {
nfp_flower_queue_ctl_msg(app, skb, cmsg_hdr->type);
}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index e209f150c5f2..457bdc60f3ee 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1409,13 +1409,21 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
struct nfp_flower_priv *priv = app->priv;
struct flow_block_cb *block_cb;
- if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
- !(f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
- nfp_flower_internal_port_can_offload(app, netdev)))
+ if ((f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
+ !nfp_flower_internal_port_can_offload(app, netdev)) ||
+ (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
+ nfp_flower_internal_port_can_offload(app, netdev)))
return -EOPNOTSUPP;
switch (f->command) {
case FLOW_BLOCK_BIND:
+ cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev);
+ if (cb_priv &&
+ flow_block_cb_is_busy(nfp_flower_setup_indr_block_cb,
+ cb_priv,
+ &nfp_block_cb_list))
+ return -EBUSY;
+
cb_priv = kmalloc(sizeof(*cb_priv), GFP_KERNEL);
if (!cb_priv)
return -ENOMEM;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c b/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
index 86e968cd5ffd..124a43dc136a 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
@@ -93,7 +93,7 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
return -EOPNOTSUPP;
}
- if (flow->common.prio != (1 << 16)) {
+ if (flow->common.prio != 1) {
NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload requires highest priority");
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index a7a80f4b722a..f0ee982eb1b5 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -328,13 +328,13 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
flow.daddr = *(__be32 *)n->primary_key;
- /* Only concerned with route changes for representors. */
- if (!nfp_netdev_is_nfp_repr(n->dev))
- return NOTIFY_DONE;
-
app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
app = app_priv->app;
+ if (!nfp_netdev_is_nfp_repr(n->dev) &&
+ !nfp_flower_internal_port_can_offload(app, n->dev))
+ return NOTIFY_DONE;
+
/* Only concerned with changes to routes already added to NFP. */
if (!nfp_tun_has_route(app, flow.daddr))
return NOTIFY_DONE;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index d9cbe84ac6ad..1b840ee47339 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -444,12 +444,12 @@ static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data)
data = nfp_pr_et(data, "hw_rx_csum_complete");
data = nfp_pr_et(data, "hw_rx_csum_err");
data = nfp_pr_et(data, "rx_replace_buf_alloc_fail");
- data = nfp_pr_et(data, "rx_tls_decrypted");
+ data = nfp_pr_et(data, "rx_tls_decrypted_packets");
data = nfp_pr_et(data, "hw_tx_csum");
data = nfp_pr_et(data, "hw_tx_inner_csum");
data = nfp_pr_et(data, "tx_gather");
data = nfp_pr_et(data, "tx_lso");
- data = nfp_pr_et(data, "tx_tls_encrypted");
+ data = nfp_pr_et(data, "tx_tls_encrypted_packets");
data = nfp_pr_et(data, "tx_tls_ooo");
data = nfp_pr_et(data, "tx_tls_drop_no_sync_data");
diff --git a/drivers/net/ethernet/ni/Kconfig b/drivers/net/ethernet/ni/Kconfig
index 70b1a03c0953..01229190132d 100644
--- a/drivers/net/ethernet/ni/Kconfig
+++ b/drivers/net/ethernet/ni/Kconfig
@@ -11,7 +11,7 @@ config NET_VENDOR_NI
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
- the questions about National Instrument devices.
+ the questions about National Instruments devices.
If you say Y, you will be asked for your specific device in the
following questions.
diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig
deleted file mode 100644
index 325e26c549f8..000000000000
--- a/drivers/net/ethernet/nuvoton/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Nuvoton network device configuration
-#
-
-config NET_VENDOR_NUVOTON
- bool "Nuvoton devices"
- default y
- depends on ARM && ARCH_W90X900
- ---help---
- If you have a network (Ethernet) card belonging to this class, say Y.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about Nuvoton cards. If you say Y, you will be asked
- for your specific card in the following questions.
-
-if NET_VENDOR_NUVOTON
-
-config W90P910_ETH
- tristate "Nuvoton w90p910 Ethernet support"
- depends on ARM && ARCH_W90X900
- select PHYLIB
- select MII
- ---help---
- Say Y here if you want to use built-in Ethernet ports
- on w90p910 processor.
-
-endif # NET_VENDOR_NUVOTON
diff --git a/drivers/net/ethernet/nuvoton/Makefile b/drivers/net/ethernet/nuvoton/Makefile
deleted file mode 100644
index 66f6e728d54b..000000000000
--- a/drivers/net/ethernet/nuvoton/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the Nuvoton network device drivers.
-#
-
-obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
deleted file mode 100644
index 3d73970b3a2e..000000000000
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#define DRV_MODULE_NAME "w90p910-emc"
-#define DRV_MODULE_VERSION "0.1"
-
-/* Ethernet MAC Registers */
-#define REG_CAMCMR 0x00
-#define REG_CAMEN 0x04
-#define REG_CAMM_BASE 0x08
-#define REG_CAML_BASE 0x0c
-#define REG_TXDLSA 0x88
-#define REG_RXDLSA 0x8C
-#define REG_MCMDR 0x90
-#define REG_MIID 0x94
-#define REG_MIIDA 0x98
-#define REG_FFTCR 0x9C
-#define REG_TSDR 0xa0
-#define REG_RSDR 0xa4
-#define REG_DMARFC 0xa8
-#define REG_MIEN 0xac
-#define REG_MISTA 0xb0
-#define REG_CTXDSA 0xcc
-#define REG_CTXBSA 0xd0
-#define REG_CRXDSA 0xd4
-#define REG_CRXBSA 0xd8
-
-/* mac controller bit */
-#define MCMDR_RXON 0x01
-#define MCMDR_ACP (0x01 << 3)
-#define MCMDR_SPCRC (0x01 << 5)
-#define MCMDR_TXON (0x01 << 8)
-#define MCMDR_FDUP (0x01 << 18)
-#define MCMDR_ENMDC (0x01 << 19)
-#define MCMDR_OPMOD (0x01 << 20)
-#define SWR (0x01 << 24)
-
-/* cam command regiser */
-#define CAMCMR_AUP 0x01
-#define CAMCMR_AMP (0x01 << 1)
-#define CAMCMR_ABP (0x01 << 2)
-#define CAMCMR_CCAM (0x01 << 3)
-#define CAMCMR_ECMP (0x01 << 4)
-#define CAM0EN 0x01
-
-/* mac mii controller bit */
-#define MDCCR (0x0a << 20)
-#define PHYAD (0x01 << 8)
-#define PHYWR (0x01 << 16)
-#define PHYBUSY (0x01 << 17)
-#define PHYPRESP (0x01 << 18)
-#define CAM_ENTRY_SIZE 0x08
-
-/* rx and tx status */
-#define TXDS_TXCP (0x01 << 19)
-#define RXDS_CRCE (0x01 << 17)
-#define RXDS_PTLE (0x01 << 19)
-#define RXDS_RXGD (0x01 << 20)
-#define RXDS_ALIE (0x01 << 21)
-#define RXDS_RP (0x01 << 22)
-
-/* mac interrupt status*/
-#define MISTA_EXDEF (0x01 << 19)
-#define MISTA_TXBERR (0x01 << 24)
-#define MISTA_TDU (0x01 << 23)
-#define MISTA_RDU (0x01 << 10)
-#define MISTA_RXBERR (0x01 << 11)
-
-#define ENSTART 0x01
-#define ENRXINTR 0x01
-#define ENRXGD (0x01 << 4)
-#define ENRXBERR (0x01 << 11)
-#define ENTXINTR (0x01 << 16)
-#define ENTXCP (0x01 << 18)
-#define ENTXABT (0x01 << 21)
-#define ENTXBERR (0x01 << 24)
-#define ENMDC (0x01 << 19)
-#define PHYBUSY (0x01 << 17)
-#define MDCCR_VAL 0xa00000
-
-/* rx and tx owner bit */
-#define RX_OWEN_DMA (0x01 << 31)
-#define RX_OWEN_CPU (~(0x03 << 30))
-#define TX_OWEN_DMA (0x01 << 31)
-#define TX_OWEN_CPU (~(0x01 << 31))
-
-/* tx frame desc controller bit */
-#define MACTXINTEN 0x04
-#define CRCMODE 0x02
-#define PADDINGMODE 0x01
-
-/* fftcr controller bit */
-#define TXTHD (0x03 << 8)
-#define BLENGTH (0x01 << 20)
-
-/* global setting for driver */
-#define RX_DESC_SIZE 50
-#define TX_DESC_SIZE 10
-#define MAX_RBUFF_SZ 0x600
-#define MAX_TBUFF_SZ 0x600
-#define TX_TIMEOUT (HZ/2)
-#define DELAY 1000
-#define CAM0 0x0
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
-
-struct w90p910_rxbd {
- unsigned int sl;
- unsigned int buffer;
- unsigned int reserved;
- unsigned int next;
-};
-
-struct w90p910_txbd {
- unsigned int mode;
- unsigned int buffer;
- unsigned int sl;
- unsigned int next;
-};
-
-struct recv_pdesc {
- struct w90p910_rxbd desclist[RX_DESC_SIZE];
- char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
-};
-
-struct tran_pdesc {
- struct w90p910_txbd desclist[TX_DESC_SIZE];
- char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
-};
-
-struct w90p910_ether {
- struct recv_pdesc *rdesc;
- struct tran_pdesc *tdesc;
- dma_addr_t rdesc_phys;
- dma_addr_t tdesc_phys;
- struct platform_device *pdev;
- struct resource *res;
- struct sk_buff *skb;
- struct clk *clk;
- struct clk *rmiiclk;
- struct mii_if_info mii;
- struct timer_list check_timer;
- void __iomem *reg;
- int rxirq;
- int txirq;
- unsigned int cur_tx;
- unsigned int cur_rx;
- unsigned int finish_tx;
- unsigned int rx_packets;
- unsigned int rx_bytes;
- unsigned int start_tx_ptr;
- unsigned int start_rx_ptr;
- unsigned int linkflag;
-};
-
-static void update_linkspeed_register(struct net_device *dev,
- unsigned int speed, unsigned int duplex)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (speed == SPEED_100) {
- /* 100 full/half duplex */
- if (duplex == DUPLEX_FULL) {
- val |= (MCMDR_OPMOD | MCMDR_FDUP);
- } else {
- val |= MCMDR_OPMOD;
- val &= ~MCMDR_FDUP;
- }
- } else {
- /* 10 full/half duplex */
- if (duplex == DUPLEX_FULL) {
- val |= MCMDR_FDUP;
- val &= ~MCMDR_OPMOD;
- } else {
- val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
- }
- }
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void update_linkspeed(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int bmsr, bmcr, lpa, speed, duplex;
-
- pdev = ether->pdev;
-
- if (!mii_link_ok(&ether->mii)) {
- ether->linkflag = 0x0;
- netif_carrier_off(dev);
- dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
- return;
- }
-
- if (ether->linkflag == 1)
- return;
-
- bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
- bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
-
- if (bmcr & BMCR_ANENABLE) {
- if (!(bmsr & BMSR_ANEGCOMPLETE))
- return;
-
- lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
-
- if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
- speed = SPEED_100;
- else
- speed = SPEED_10;
-
- if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
- duplex = DUPLEX_FULL;
- else
- duplex = DUPLEX_HALF;
-
- } else {
- speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
- duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
- }
-
- update_linkspeed_register(dev, speed, duplex);
-
- dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
- (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
- ether->linkflag = 0x01;
-
- netif_carrier_on(dev);
-}
-
-static void w90p910_check_link(struct timer_list *t)
-{
- struct w90p910_ether *ether = from_timer(ether, t, check_timer);
- struct net_device *dev = ether->mii.dev;
-
- update_linkspeed(dev);
- mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-}
-
-static void w90p910_write_cam(struct net_device *dev,
- unsigned int x, unsigned char *pval)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int msw, lsw;
-
- msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
-
- lsw = (pval[4] << 24) | (pval[5] << 16);
-
- __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
- __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
-}
-
-static int w90p910_init_desc(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *tdesc;
- struct w90p910_rxbd *rdesc;
- struct platform_device *pdev;
- unsigned int i;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- ether->tdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- &ether->tdesc_phys, GFP_KERNEL);
- if (!ether->tdesc)
- return -ENOMEM;
-
- ether->rdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
- &ether->rdesc_phys, GFP_KERNEL);
- if (!ether->rdesc) {
- dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- ether->tdesc, ether->tdesc_phys);
- return -ENOMEM;
- }
-
- for (i = 0; i < TX_DESC_SIZE; i++) {
- unsigned int offset;
-
- tdesc = &(ether->tdesc->desclist[i]);
-
- if (i == TX_DESC_SIZE - 1)
- offset = offsetof(struct tran_pdesc, desclist[0]);
- else
- offset = offsetof(struct tran_pdesc, desclist[i + 1]);
-
- tdesc->next = ether->tdesc_phys + offset;
- tdesc->buffer = ether->tdesc_phys +
- offsetof(struct tran_pdesc, tran_buf[i]);
- tdesc->sl = 0;
- tdesc->mode = 0;
- }
-
- ether->start_tx_ptr = ether->tdesc_phys;
-
- for (i = 0; i < RX_DESC_SIZE; i++) {
- unsigned int offset;
-
- rdesc = &(ether->rdesc->desclist[i]);
-
- if (i == RX_DESC_SIZE - 1)
- offset = offsetof(struct recv_pdesc, desclist[0]);
- else
- offset = offsetof(struct recv_pdesc, desclist[i + 1]);
-
- rdesc->next = ether->rdesc_phys + offset;
- rdesc->sl = RX_OWEN_DMA;
- rdesc->buffer = ether->rdesc_phys +
- offsetof(struct recv_pdesc, recv_buf[i]);
- }
-
- ether->start_rx_ptr = ether->rdesc_phys;
-
- return 0;
-}
-
-static void w90p910_set_fifo_threshold(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = TXTHD | BLENGTH;
- __raw_writel(val, ether->reg + REG_FFTCR);
-}
-
-static void w90p910_return_default_idle(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
- val |= SWR;
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_trigger_rx(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ENSTART, ether->reg + REG_RSDR);
-}
-
-static void w90p910_trigger_tx(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ENSTART, ether->reg + REG_TSDR);
-}
-
-static void w90p910_enable_mac_interrupt(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
- val |= ENTXBERR | ENRXBERR | ENTXABT;
-
- __raw_writel(val, ether->reg + REG_MIEN);
-}
-
-static void w90p910_get_and_clear_int(struct net_device *dev,
- unsigned int *val)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- *val = __raw_readl(ether->reg + REG_MISTA);
- __raw_writel(*val, ether->reg + REG_MISTA);
-}
-
-static void w90p910_set_global_maccmd(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
- val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_cam(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
- val = __raw_readl(ether->reg + REG_CAMEN);
- val |= CAM0EN;
- __raw_writel(val, ether->reg + REG_CAMEN);
-}
-
-static void w90p910_enable_cam_command(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
- __raw_writel(val, ether->reg + REG_CAMCMR);
-}
-
-static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (enable)
- val |= MCMDR_TXON;
- else
- val &= ~MCMDR_TXON;
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (enable)
- val |= MCMDR_RXON;
- else
- val &= ~MCMDR_RXON;
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_set_curdest(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
- __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
-}
-
-static void w90p910_reset_mac(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- w90p910_enable_tx(dev, 0);
- w90p910_enable_rx(dev, 0);
- w90p910_set_fifo_threshold(dev);
- w90p910_return_default_idle(dev);
-
- if (!netif_queue_stopped(dev))
- netif_stop_queue(dev);
-
- w90p910_init_desc(dev);
-
- netif_trans_update(dev); /* prevent tx timeout */
- ether->cur_tx = 0x0;
- ether->finish_tx = 0x0;
- ether->cur_rx = 0x0;
-
- w90p910_set_curdest(dev);
- w90p910_enable_cam(dev);
- w90p910_enable_cam_command(dev);
- w90p910_enable_mac_interrupt(dev);
- w90p910_enable_tx(dev, 1);
- w90p910_enable_rx(dev, 1);
- w90p910_trigger_tx(dev);
- w90p910_trigger_rx(dev);
-
- netif_trans_update(dev); /* prevent tx timeout */
-
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-}
-
-static void w90p910_mdio_write(struct net_device *dev,
- int phy_id, int reg, int data)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int val, i;
-
- pdev = ether->pdev;
-
- __raw_writel(data, ether->reg + REG_MIID);
-
- val = (phy_id << 0x08) | reg;
- val |= PHYBUSY | PHYWR | MDCCR_VAL;
- __raw_writel(val, ether->reg + REG_MIIDA);
-
- for (i = 0; i < DELAY; i++) {
- if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
- break;
- }
-
- if (i == DELAY)
- dev_warn(&pdev->dev, "mdio write timed out\n");
-}
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int val, i, data;
-
- pdev = ether->pdev;
-
- val = (phy_id << 0x08) | reg;
- val |= PHYBUSY | MDCCR_VAL;
- __raw_writel(val, ether->reg + REG_MIIDA);
-
- for (i = 0; i < DELAY; i++) {
- if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
- break;
- }
-
- if (i == DELAY) {
- dev_warn(&pdev->dev, "mdio read timed out\n");
- data = 0xffff;
- } else {
- data = __raw_readl(ether->reg + REG_MIID);
- }
-
- return data;
-}
-
-static int w90p910_set_mac_address(struct net_device *dev, void *addr)
-{
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
- w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
- return 0;
-}
-
-static int w90p910_ether_close(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
-
- pdev = ether->pdev;
-
- dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
- ether->rdesc, ether->rdesc_phys);
- dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- ether->tdesc, ether->tdesc_phys);
-
- netif_stop_queue(dev);
-
- del_timer_sync(&ether->check_timer);
- clk_disable(ether->rmiiclk);
- clk_disable(ether->clk);
-
- free_irq(ether->txirq, dev);
- free_irq(ether->rxirq, dev);
-
- return 0;
-}
-
-static int w90p910_send_frame(struct net_device *dev,
- unsigned char *data, int length)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *txbd;
- struct platform_device *pdev;
- unsigned char *buffer;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- txbd = &ether->tdesc->desclist[ether->cur_tx];
- buffer = ether->tdesc->tran_buf[ether->cur_tx];
-
- if (length > 1514) {
- dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
- length = 1514;
- }
-
- txbd->sl = length & 0xFFFF;
-
- memcpy(buffer, data, length);
-
- txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
-
- w90p910_enable_tx(dev, 1);
-
- w90p910_trigger_tx(dev);
-
- if (++ether->cur_tx >= TX_DESC_SIZE)
- ether->cur_tx = 0;
-
- txbd = &ether->tdesc->desclist[ether->cur_tx];
-
- if (txbd->mode & TX_OWEN_DMA)
- netif_stop_queue(dev);
-
- return 0;
-}
-
-static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
- ether->skb = skb;
- dev_consume_skb_irq(skb);
- return 0;
- }
- return -EAGAIN;
-}
-
-static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *txbd;
- struct platform_device *pdev;
- struct net_device *dev;
- unsigned int cur_entry, entry, status;
-
- dev = dev_id;
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_get_and_clear_int(dev, &status);
-
- cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
-
- entry = ether->tdesc_phys +
- offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-
- while (entry != cur_entry) {
- txbd = &ether->tdesc->desclist[ether->finish_tx];
-
- if (++ether->finish_tx >= TX_DESC_SIZE)
- ether->finish_tx = 0;
-
- if (txbd->sl & TXDS_TXCP) {
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += txbd->sl & 0xFFFF;
- } else {
- dev->stats.tx_errors++;
- }
-
- txbd->sl = 0x0;
- txbd->mode = 0x0;
-
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-
- entry = ether->tdesc_phys +
- offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
- }
-
- if (status & MISTA_EXDEF) {
- dev_err(&pdev->dev, "emc defer exceed interrupt\n");
- } else if (status & MISTA_TXBERR) {
- dev_err(&pdev->dev, "emc bus error interrupt\n");
- w90p910_reset_mac(dev);
- } else if (status & MISTA_TDU) {
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
- }
-
- return IRQ_HANDLED;
-}
-
-static void netdev_rx(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct w90p910_rxbd *rxbd;
- struct platform_device *pdev;
- struct sk_buff *skb;
- unsigned char *data;
- unsigned int length, status, val, entry;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
- do {
- val = __raw_readl(ether->reg + REG_CRXDSA);
-
- entry = ether->rdesc_phys +
- offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
-
- if (val == entry)
- break;
-
- status = rxbd->sl;
- length = status & 0xFFFF;
-
- if (status & RXDS_RXGD) {
- data = ether->rdesc->recv_buf[ether->cur_rx];
- skb = netdev_alloc_skb(dev, length + 2);
- if (!skb) {
- dev->stats.rx_dropped++;
- return;
- }
-
- skb_reserve(skb, 2);
- skb_put(skb, length);
- skb_copy_to_linear_data(skb, data, length);
- skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += length;
- netif_rx(skb);
- } else {
- dev->stats.rx_errors++;
-
- if (status & RXDS_RP) {
- dev_err(&pdev->dev, "rx runt err\n");
- dev->stats.rx_length_errors++;
- } else if (status & RXDS_CRCE) {
- dev_err(&pdev->dev, "rx crc err\n");
- dev->stats.rx_crc_errors++;
- } else if (status & RXDS_ALIE) {
- dev_err(&pdev->dev, "rx alignment err\n");
- dev->stats.rx_frame_errors++;
- } else if (status & RXDS_PTLE) {
- dev_err(&pdev->dev, "rx longer err\n");
- dev->stats.rx_over_errors++;
- }
- }
-
- rxbd->sl = RX_OWEN_DMA;
- rxbd->reserved = 0x0;
-
- if (++ether->cur_rx >= RX_DESC_SIZE)
- ether->cur_rx = 0;
-
- rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
- } while (1);
-}
-
-static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev;
- struct w90p910_ether *ether;
- struct platform_device *pdev;
- unsigned int status;
-
- dev = dev_id;
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_get_and_clear_int(dev, &status);
-
- if (status & MISTA_RDU) {
- netdev_rx(dev);
- w90p910_trigger_rx(dev);
-
- return IRQ_HANDLED;
- } else if (status & MISTA_RXBERR) {
- dev_err(&pdev->dev, "emc rx bus error\n");
- w90p910_reset_mac(dev);
- }
-
- netdev_rx(dev);
- return IRQ_HANDLED;
-}
-
-static int w90p910_ether_open(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct platform_device *pdev;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_reset_mac(dev);
- w90p910_set_fifo_threshold(dev);
- w90p910_set_curdest(dev);
- w90p910_enable_cam(dev);
- w90p910_enable_cam_command(dev);
- w90p910_enable_mac_interrupt(dev);
- w90p910_set_global_maccmd(dev);
- w90p910_enable_rx(dev, 1);
-
- clk_enable(ether->rmiiclk);
- clk_enable(ether->clk);
-
- ether->rx_packets = 0x0;
- ether->rx_bytes = 0x0;
-
- if (request_irq(ether->txirq, w90p910_tx_interrupt,
- 0x0, pdev->name, dev)) {
- dev_err(&pdev->dev, "register irq tx failed\n");
- return -EAGAIN;
- }
-
- if (request_irq(ether->rxirq, w90p910_rx_interrupt,
- 0x0, pdev->name, dev)) {
- dev_err(&pdev->dev, "register irq rx failed\n");
- free_irq(ether->txirq, dev);
- return -EAGAIN;
- }
-
- mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
- netif_start_queue(dev);
- w90p910_trigger_rx(dev);
-
- dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
-
- return 0;
-}
-
-static void w90p910_ether_set_multicast_list(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- unsigned int rx_mode;
-
- ether = netdev_priv(dev);
-
- if (dev->flags & IFF_PROMISC)
- rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
- else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
- rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
- else
- rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
- __raw_writel(rx_mode, ether->reg + REG_CAMCMR);
-}
-
-static int w90p910_ether_ioctl(struct net_device *dev,
- struct ifreq *ifr, int cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct mii_ioctl_data *data = if_mii(ifr);
-
- return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
-}
-
-static void w90p910_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
- strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
-}
-
-static int w90p910_get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- mii_ethtool_get_link_ksettings(&ether->mii, cmd);
-
- return 0;
-}
-
-static int w90p910_set_link_ksettings(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_ethtool_set_link_ksettings(&ether->mii, cmd);
-}
-
-static int w90p910_nway_reset(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_nway_restart(&ether->mii);
-}
-
-static u32 w90p910_get_link(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_link_ok(&ether->mii);
-}
-
-static const struct ethtool_ops w90p910_ether_ethtool_ops = {
- .get_drvinfo = w90p910_get_drvinfo,
- .nway_reset = w90p910_nway_reset,
- .get_link = w90p910_get_link,
- .get_link_ksettings = w90p910_get_link_ksettings,
- .set_link_ksettings = w90p910_set_link_ksettings,
-};
-
-static const struct net_device_ops w90p910_ether_netdev_ops = {
- .ndo_open = w90p910_ether_open,
- .ndo_stop = w90p910_ether_close,
- .ndo_start_xmit = w90p910_ether_start_xmit,
- .ndo_set_rx_mode = w90p910_ether_set_multicast_list,
- .ndo_set_mac_address = w90p910_set_mac_address,
- .ndo_do_ioctl = w90p910_ether_ioctl,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static void get_mac_address(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- char addr[ETH_ALEN];
-
- pdev = ether->pdev;
-
- addr[0] = 0x00;
- addr[1] = 0x02;
- addr[2] = 0xac;
- addr[3] = 0x55;
- addr[4] = 0x88;
- addr[5] = 0xa8;
-
- if (is_valid_ether_addr(addr))
- memcpy(dev->dev_addr, &addr, ETH_ALEN);
- else
- dev_err(&pdev->dev, "invalid mac address\n");
-}
-
-static int w90p910_ether_setup(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- dev->netdev_ops = &w90p910_ether_netdev_ops;
- dev->ethtool_ops = &w90p910_ether_ethtool_ops;
-
- dev->tx_queue_len = 16;
- dev->dma = 0x0;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- get_mac_address(dev);
-
- ether->cur_tx = 0x0;
- ether->cur_rx = 0x0;
- ether->finish_tx = 0x0;
- ether->linkflag = 0x0;
- ether->mii.phy_id = 0x01;
- ether->mii.phy_id_mask = 0x1f;
- ether->mii.reg_num_mask = 0x1f;
- ether->mii.dev = dev;
- ether->mii.mdio_read = w90p910_mdio_read;
- ether->mii.mdio_write = w90p910_mdio_write;
-
- timer_setup(&ether->check_timer, w90p910_check_link, 0);
-
- return 0;
-}
-
-static int w90p910_ether_probe(struct platform_device *pdev)
-{
- struct w90p910_ether *ether;
- struct net_device *dev;
- int error;
-
- dev = alloc_etherdev(sizeof(struct w90p910_ether));
- if (!dev)
- return -ENOMEM;
-
- ether = netdev_priv(dev);
-
- ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (ether->res == NULL) {
- dev_err(&pdev->dev, "failed to get I/O memory\n");
- error = -ENXIO;
- goto failed_free;
- }
-
- if (!request_mem_region(ether->res->start,
- resource_size(ether->res), pdev->name)) {
- dev_err(&pdev->dev, "failed to request I/O memory\n");
- error = -EBUSY;
- goto failed_free;
- }
-
- ether->reg = ioremap(ether->res->start, resource_size(ether->res));
- if (ether->reg == NULL) {
- dev_err(&pdev->dev, "failed to remap I/O memory\n");
- error = -ENXIO;
- goto failed_free_mem;
- }
-
- ether->txirq = platform_get_irq(pdev, 0);
- if (ether->txirq < 0) {
- dev_err(&pdev->dev, "failed to get ether tx irq\n");
- error = -ENXIO;
- goto failed_free_io;
- }
-
- ether->rxirq = platform_get_irq(pdev, 1);
- if (ether->rxirq < 0) {
- dev_err(&pdev->dev, "failed to get ether rx irq\n");
- error = -ENXIO;
- goto failed_free_io;
- }
-
- platform_set_drvdata(pdev, dev);
-
- ether->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(ether->clk)) {
- dev_err(&pdev->dev, "failed to get ether clock\n");
- error = PTR_ERR(ether->clk);
- goto failed_free_io;
- }
-
- ether->rmiiclk = clk_get(&pdev->dev, "RMII");
- if (IS_ERR(ether->rmiiclk)) {
- dev_err(&pdev->dev, "failed to get ether clock\n");
- error = PTR_ERR(ether->rmiiclk);
- goto failed_put_clk;
- }
-
- ether->pdev = pdev;
-
- w90p910_ether_setup(dev);
-
- error = register_netdev(dev);
- if (error != 0) {
- dev_err(&pdev->dev, "Register EMC w90p910 FAILED\n");
- error = -ENODEV;
- goto failed_put_rmiiclk;
- }
-
- return 0;
-failed_put_rmiiclk:
- clk_put(ether->rmiiclk);
-failed_put_clk:
- clk_put(ether->clk);
-failed_free_io:
- iounmap(ether->reg);
-failed_free_mem:
- release_mem_region(ether->res->start, resource_size(ether->res));
-failed_free:
- free_netdev(dev);
- return error;
-}
-
-static int w90p910_ether_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct w90p910_ether *ether = netdev_priv(dev);
-
- unregister_netdev(dev);
-
- clk_put(ether->rmiiclk);
- clk_put(ether->clk);
-
- iounmap(ether->reg);
- release_mem_region(ether->res->start, resource_size(ether->res));
-
- del_timer_sync(&ether->check_timer);
-
- free_netdev(dev);
- return 0;
-}
-
-static struct platform_driver w90p910_ether_driver = {
- .probe = w90p910_ether_probe,
- .remove = w90p910_ether_remove,
- .driver = {
- .name = "nuc900-emc",
- },
-};
-
-module_platform_driver(w90p910_ether_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 MAC driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-emc");
-
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index b327b29f5d57..a6b4bfae4684 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -713,6 +713,21 @@ struct nv_skb_map {
struct nv_skb_map *next_tx_ctx;
};
+struct nv_txrx_stats {
+ u64 stat_rx_packets;
+ u64 stat_rx_bytes; /* not always available in HW */
+ u64 stat_rx_missed_errors;
+ u64 stat_rx_dropped;
+ u64 stat_tx_packets; /* not always available in HW */
+ u64 stat_tx_bytes;
+ u64 stat_tx_dropped;
+};
+
+#define nv_txrx_stats_inc(member) \
+ __this_cpu_inc(np->txrx_stats->member)
+#define nv_txrx_stats_add(member, count) \
+ __this_cpu_add(np->txrx_stats->member, (count))
+
/*
* SMP locking:
* All hardware access under netdev_priv(dev)->lock, except the performance
@@ -797,10 +812,7 @@ struct fe_priv {
/* RX software stats */
struct u64_stats_sync swstats_rx_syncp;
- u64 stat_rx_packets;
- u64 stat_rx_bytes; /* not always available in HW */
- u64 stat_rx_missed_errors;
- u64 stat_rx_dropped;
+ struct nv_txrx_stats __percpu *txrx_stats;
/* media detection workaround.
* Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
@@ -826,9 +838,6 @@ struct fe_priv {
/* TX software stats */
struct u64_stats_sync swstats_tx_syncp;
- u64 stat_tx_packets; /* not always available in HW */
- u64 stat_tx_bytes;
- u64 stat_tx_dropped;
/* msi/msi-x fields */
u32 msi_flags;
@@ -1721,6 +1730,39 @@ static void nv_update_stats(struct net_device *dev)
}
}
+static void nv_get_stats(int cpu, struct fe_priv *np,
+ struct rtnl_link_stats64 *storage)
+{
+ struct nv_txrx_stats *src = per_cpu_ptr(np->txrx_stats, cpu);
+ unsigned int syncp_start;
+ u64 rx_packets, rx_bytes, rx_dropped, rx_missed_errors;
+ u64 tx_packets, tx_bytes, tx_dropped;
+
+ do {
+ syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp);
+ rx_packets = src->stat_rx_packets;
+ rx_bytes = src->stat_rx_bytes;
+ rx_dropped = src->stat_rx_dropped;
+ rx_missed_errors = src->stat_rx_missed_errors;
+ } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start));
+
+ storage->rx_packets += rx_packets;
+ storage->rx_bytes += rx_bytes;
+ storage->rx_dropped += rx_dropped;
+ storage->rx_missed_errors += rx_missed_errors;
+
+ do {
+ syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp);
+ tx_packets = src->stat_tx_packets;
+ tx_bytes = src->stat_tx_bytes;
+ tx_dropped = src->stat_tx_dropped;
+ } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start));
+
+ storage->tx_packets += tx_packets;
+ storage->tx_bytes += tx_bytes;
+ storage->tx_dropped += tx_dropped;
+}
+
/*
* nv_get_stats64: dev->ndo_get_stats64 function
* Get latest stats value from the nic.
@@ -1733,7 +1775,7 @@ nv_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *storage)
__releases(&netdev_priv(dev)->hwstats_lock)
{
struct fe_priv *np = netdev_priv(dev);
- unsigned int syncp_start;
+ int cpu;
/*
* Note: because HW stats are not always available and for
@@ -1746,20 +1788,8 @@ nv_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *storage)
*/
/* software stats */
- do {
- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp);
- storage->rx_packets = np->stat_rx_packets;
- storage->rx_bytes = np->stat_rx_bytes;
- storage->rx_dropped = np->stat_rx_dropped;
- storage->rx_missed_errors = np->stat_rx_missed_errors;
- } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start));
-
- do {
- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp);
- storage->tx_packets = np->stat_tx_packets;
- storage->tx_bytes = np->stat_tx_bytes;
- storage->tx_dropped = np->stat_tx_dropped;
- } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start));
+ for_each_online_cpu(cpu)
+ nv_get_stats(cpu, np, storage);
/* If the nic supports hw counters then retrieve latest values */
if (np->driver_data & DEV_HAS_STATISTICS_V123) {
@@ -1827,7 +1857,7 @@ static int nv_alloc_rx(struct net_device *dev)
} else {
packet_dropped:
u64_stats_update_begin(&np->swstats_rx_syncp);
- np->stat_rx_dropped++;
+ nv_txrx_stats_inc(stat_rx_dropped);
u64_stats_update_end(&np->swstats_rx_syncp);
return 1;
}
@@ -1869,7 +1899,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
} else {
packet_dropped:
u64_stats_update_begin(&np->swstats_rx_syncp);
- np->stat_rx_dropped++;
+ nv_txrx_stats_inc(stat_rx_dropped);
u64_stats_update_end(&np->swstats_rx_syncp);
return 1;
}
@@ -2013,7 +2043,7 @@ static void nv_drain_tx(struct net_device *dev)
}
if (nv_release_txskb(np, &np->tx_skb[i])) {
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_dropped++;
+ nv_txrx_stats_inc(stat_tx_dropped);
u64_stats_update_end(&np->swstats_tx_syncp);
}
np->tx_skb[i].dma = 0;
@@ -2227,7 +2257,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* on DMA mapping error - drop the packet */
dev_kfree_skb_any(skb);
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_dropped++;
+ nv_txrx_stats_inc(stat_tx_dropped);
u64_stats_update_end(&np->swstats_tx_syncp);
return NETDEV_TX_OK;
}
@@ -2273,7 +2303,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
np->put_tx_ctx = start_tx_ctx;
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_dropped++;
+ nv_txrx_stats_inc(stat_tx_dropped);
u64_stats_update_end(&np->swstats_tx_syncp);
return NETDEV_TX_OK;
}
@@ -2384,7 +2414,7 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
/* on DMA mapping error - drop the packet */
dev_kfree_skb_any(skb);
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_dropped++;
+ nv_txrx_stats_inc(stat_tx_dropped);
u64_stats_update_end(&np->swstats_tx_syncp);
return NETDEV_TX_OK;
}
@@ -2431,7 +2461,7 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
dev_kfree_skb_any(skb);
np->put_tx_ctx = start_tx_ctx;
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_dropped++;
+ nv_txrx_stats_inc(stat_tx_dropped);
u64_stats_update_end(&np->swstats_tx_syncp);
return NETDEV_TX_OK;
}
@@ -2560,9 +2590,12 @@ static int nv_tx_done(struct net_device *dev, int limit)
&& !(flags & NV_TX_RETRYCOUNT_MASK))
nv_legacybackoff_reseed(dev);
} else {
+ unsigned int len;
+
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_packets++;
- np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+ nv_txrx_stats_inc(stat_tx_packets);
+ len = np->get_tx_ctx->skb->len;
+ nv_txrx_stats_add(stat_tx_bytes, len);
u64_stats_update_end(&np->swstats_tx_syncp);
}
bytes_compl += np->get_tx_ctx->skb->len;
@@ -2577,9 +2610,12 @@ static int nv_tx_done(struct net_device *dev, int limit)
&& !(flags & NV_TX2_RETRYCOUNT_MASK))
nv_legacybackoff_reseed(dev);
} else {
+ unsigned int len;
+
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_packets++;
- np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+ nv_txrx_stats_inc(stat_tx_packets);
+ len = np->get_tx_ctx->skb->len;
+ nv_txrx_stats_add(stat_tx_bytes, len);
u64_stats_update_end(&np->swstats_tx_syncp);
}
bytes_compl += np->get_tx_ctx->skb->len;
@@ -2627,9 +2663,12 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit)
nv_legacybackoff_reseed(dev);
}
} else {
+ unsigned int len;
+
u64_stats_update_begin(&np->swstats_tx_syncp);
- np->stat_tx_packets++;
- np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+ nv_txrx_stats_inc(stat_tx_packets);
+ len = np->get_tx_ctx->skb->len;
+ nv_txrx_stats_add(stat_tx_bytes, len);
u64_stats_update_end(&np->swstats_tx_syncp);
}
@@ -2806,6 +2845,15 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
}
}
+static void rx_missing_handler(u32 flags, struct fe_priv *np)
+{
+ if (flags & NV_RX_MISSEDFRAME) {
+ u64_stats_update_begin(&np->swstats_rx_syncp);
+ nv_txrx_stats_inc(stat_rx_missed_errors);
+ u64_stats_update_end(&np->swstats_rx_syncp);
+ }
+}
+
static int nv_rx_process(struct net_device *dev, int limit)
{
struct fe_priv *np = netdev_priv(dev);
@@ -2848,11 +2896,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
}
/* the rest are hard errors */
else {
- if (flags & NV_RX_MISSEDFRAME) {
- u64_stats_update_begin(&np->swstats_rx_syncp);
- np->stat_rx_missed_errors++;
- u64_stats_update_end(&np->swstats_rx_syncp);
- }
+ rx_missing_handler(flags, np);
dev_kfree_skb(skb);
goto next_pkt;
}
@@ -2896,8 +2940,8 @@ static int nv_rx_process(struct net_device *dev, int limit)
skb->protocol = eth_type_trans(skb, dev);
napi_gro_receive(&np->napi, skb);
u64_stats_update_begin(&np->swstats_rx_syncp);
- np->stat_rx_packets++;
- np->stat_rx_bytes += len;
+ nv_txrx_stats_inc(stat_rx_packets);
+ nv_txrx_stats_add(stat_rx_bytes, len);
u64_stats_update_end(&np->swstats_rx_syncp);
next_pkt:
if (unlikely(np->get_rx.orig++ == np->last_rx.orig))
@@ -2982,8 +3026,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
}
napi_gro_receive(&np->napi, skb);
u64_stats_update_begin(&np->swstats_rx_syncp);
- np->stat_rx_packets++;
- np->stat_rx_bytes += len;
+ nv_txrx_stats_inc(stat_rx_packets);
+ nv_txrx_stats_add(stat_rx_bytes, len);
u64_stats_update_end(&np->swstats_rx_syncp);
} else {
dev_kfree_skb(skb);
@@ -5651,6 +5695,12 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
SET_NETDEV_DEV(dev, &pci_dev->dev);
u64_stats_init(&np->swstats_rx_syncp);
u64_stats_init(&np->swstats_tx_syncp);
+ np->txrx_stats = alloc_percpu(struct nv_txrx_stats);
+ if (!np->txrx_stats) {
+ pr_err("np->txrx_stats, alloc memory error.\n");
+ err = -ENOMEM;
+ goto out_alloc_percpu;
+ }
timer_setup(&np->oom_kick, nv_do_rx_refill, 0);
timer_setup(&np->nic_poll, nv_do_nic_poll, 0);
@@ -6060,6 +6110,8 @@ out_relreg:
out_disable:
pci_disable_device(pci_dev);
out_free:
+ free_percpu(np->txrx_stats);
+out_alloc_percpu:
free_netdev(dev);
out:
return err;
@@ -6105,6 +6157,9 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
static void nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
+ struct fe_priv *np = netdev_priv(dev);
+
+ free_percpu(np->txrx_stats);
unregister_netdev(dev);
diff --git a/drivers/net/ethernet/nxp/Kconfig b/drivers/net/ethernet/nxp/Kconfig
index 261f107e2be0..418afb84c84b 100644
--- a/drivers/net/ethernet/nxp/Kconfig
+++ b/drivers/net/ethernet/nxp/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config LPC_ENET
tristate "NXP ethernet MAC on LPC devices"
- depends on ARCH_LPC32XX
+ depends on ARCH_LPC32XX || COMPILE_TEST
select PHYLIB
help
Say Y or M here if you want to use the NXP ethernet MAC included on
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index f7e11f1b0426..141571e2ec11 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -14,14 +14,12 @@
#include <linux/crc32.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
-
-#include <mach/board.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include <linux/soc/nxp/lpc32xx-misc.h>
#define MODNAME "lpc-eth"
#define DRV_VERSION "1.00"
@@ -1237,16 +1235,9 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
dma_addr_t dma_handle;
struct resource *res;
int irq, ret;
- u32 tmp;
/* Setup network interface for RMII or MII mode */
- tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
- tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
- if (lpc_phy_interface_mode(dev) == PHY_INTERFACE_MODE_MII)
- tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS;
- else
- tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
- __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
+ lpc32xx_set_phy_interface_mode(lpc_phy_interface_mode(dev));
/* Get platform resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1311,19 +1302,18 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
/* Get size of DMA buffers/descriptors region */
pldat->dma_buff_size = (ENET_TX_DESC + ENET_RX_DESC) * (ENET_MAXF_SIZE +
sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t));
- pldat->dma_buff_base_v = 0;
if (use_iram_for_net(dev)) {
- dma_handle = LPC32XX_IRAM_BASE;
- if (pldat->dma_buff_size <= lpc32xx_return_iram_size())
- pldat->dma_buff_base_v =
- io_p2v(LPC32XX_IRAM_BASE);
- else
+ if (pldat->dma_buff_size >
+ lpc32xx_return_iram(&pldat->dma_buff_base_v, &dma_handle)) {
+ pldat->dma_buff_base_v = NULL;
+ pldat->dma_buff_size = 0;
netdev_err(ndev,
"IRAM not big enough for net buffers, using SDRAM instead.\n");
+ }
}
- if (pldat->dma_buff_base_v == 0) {
+ if (pldat->dma_buff_base_v == NULL) {
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
goto err_out_free_irq;
@@ -1344,13 +1334,14 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
pldat->dma_buff_base_p = dma_handle;
netdev_dbg(ndev, "IO address space :%pR\n", res);
- netdev_dbg(ndev, "IO address size :%d\n", resource_size(res));
+ netdev_dbg(ndev, "IO address size :%zd\n",
+ (size_t)resource_size(res));
netdev_dbg(ndev, "IO address (mapped) :0x%p\n",
pldat->net_base);
netdev_dbg(ndev, "IRQ number :%d\n", ndev->irq);
- netdev_dbg(ndev, "DMA buffer size :%d\n", pldat->dma_buff_size);
- netdev_dbg(ndev, "DMA buffer P address :0x%08x\n",
- pldat->dma_buff_base_p);
+ netdev_dbg(ndev, "DMA buffer size :%zd\n", pldat->dma_buff_size);
+ netdev_dbg(ndev, "DMA buffer P address :%pad\n",
+ &pldat->dma_buff_base_p);
netdev_dbg(ndev, "DMA buffer V address :0x%p\n",
pldat->dma_buff_base_v);
@@ -1397,8 +1388,8 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
if (ret)
goto err_out_unregister_netdev;
- netdev_info(ndev, "LPC mac at 0x%08x irq %d\n",
- res->start, ndev->irq);
+ netdev_info(ndev, "LPC mac at 0x%08lx irq %d\n",
+ (unsigned long)res->start, ndev->irq);
device_init_wakeup(dev, 1);
device_set_wakeup_enable(dev, 0);
@@ -1409,7 +1400,7 @@ err_out_unregister_netdev:
unregister_netdev(ndev);
err_out_dma_unmap:
if (!use_iram_for_net(dev) ||
- pldat->dma_buff_size > lpc32xx_return_iram_size())
+ pldat->dma_buff_size > lpc32xx_return_iram(NULL, NULL))
dma_free_coherent(dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
pldat->dma_buff_base_p);
@@ -1436,7 +1427,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
unregister_netdev(ndev);
if (!use_iram_for_net(&pldat->pdev->dev) ||
- pldat->dma_buff_size > lpc32xx_return_iram_size())
+ pldat->dma_buff_size > lpc32xx_return_iram(NULL, NULL))
dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
pldat->dma_buff_base_p);
diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig
index 8161e308e64b..ead3750b4489 100644
--- a/drivers/net/ethernet/packetengines/Kconfig
+++ b/drivers/net/ethernet/packetengines/Kconfig
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
#
-# Packet engine device configuration
+# Packet Engines device configuration
#
config NET_VENDOR_PACKET_ENGINES
- bool "Packet Engine devices"
+ bool "Packet Engines devices"
default y
depends on PCI
---help---
@@ -12,7 +12,7 @@ config NET_VENDOR_PACKET_ENGINES
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
- the questions about packet engine devices. If you say Y, you will
+ the questions about Packet Engines devices. If you say Y, you will
be asked for your specific card in the following questions.
if NET_VENDOR_PACKET_ENGINES
diff --git a/drivers/net/ethernet/packetengines/Makefile b/drivers/net/ethernet/packetengines/Makefile
index 1553c9cfc254..cf054b796d11 100644
--- a/drivers/net/ethernet/packetengines/Makefile
+++ b/drivers/net/ethernet/packetengines/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
#
-# Makefile for the Packet Engine network device drivers.
+# Makefile for the Packet Engines network device drivers.
#
obj-$(CONFIG_HAMACHI) += hamachi.o
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c
index 4e8118a08654..9f5113639eaf 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -1093,7 +1093,7 @@ static int qed_int_deassertion(struct qed_hwfn *p_hwfn,
snprintf(bit_name, 30,
p_aeu->bit_name, num);
else
- strncpy(bit_name,
+ strlcpy(bit_name,
p_aeu->bit_name, 30);
/* We now need to pass bitmask in its
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 829dd60ab937..1efff7f68ef6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1325,7 +1325,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
&drv_version);
if (rc) {
DP_NOTICE(cdev, "Failed sending drv version command\n");
- return rc;
+ goto err4;
}
}
@@ -1333,6 +1333,8 @@ static int qed_slowpath_start(struct qed_dev *cdev,
return 0;
+err4:
+ qed_ll2_dealloc_if(cdev);
err3:
qed_hw_stop(cdev);
err2:
diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c
index 17c64e43d6c3..158ac0738911 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c
@@ -442,7 +442,7 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
/* Vendor specific information */
dev->vendor_id = cdev->vendor_id;
dev->vendor_part_id = cdev->device_id;
- dev->hw_ver = 0;
+ dev->hw_ver = cdev->chip_rev;
dev->fw_ver = (FW_MAJOR_VERSION << 24) | (FW_MINOR_VERSION << 16) |
(FW_REVISION_VERSION << 8) | (FW_ENGINEERING_VERSION);
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 60189923737a..21d38167f961 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr,
ul_header->csum_insert_offset = skb->csum_offset;
ul_header->csum_enabled = 1;
if (ip4h->protocol == IPPROTO_UDP)
- ul_header->udp_ip4_ind = 1;
+ ul_header->udp_ind = 1;
else
- ul_header->udp_ip4_ind = 0;
+ ul_header->udp_ind = 0;
/* Changing remaining fields to network order */
hdr++;
@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
struct rmnet_map_ul_csum_header *ul_header,
struct sk_buff *skb)
{
+ struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
__be16 *hdr = (__be16 *)ul_header, offset;
offset = htons((__force u16)(skb_transport_header(skb) -
@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
ul_header->csum_start_offset = offset;
ul_header->csum_insert_offset = skb->csum_offset;
ul_header->csum_enabled = 1;
- ul_header->udp_ip4_ind = 0;
+
+ if (ip6h->nexthdr == IPPROTO_UDP)
+ ul_header->udp_ind = 1;
+ else
+ ul_header->udp_ind = 0;
/* Changing remaining fields to network order */
hdr++;
@@ -419,7 +424,7 @@ sw_csum:
ul_header->csum_start_offset = 0;
ul_header->csum_insert_offset = 0;
ul_header->csum_enabled = 0;
- ul_header->udp_ip4_ind = 0;
+ ul_header->udp_ind = 0;
priv->stats.csum_sw++;
}
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 6272115b2848..bae0074ab9aa 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5921,6 +5921,7 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data,
skb = napi_alloc_skb(&tp->napi, pkt_size);
if (skb)
skb_copy_to_linear_data(skb, data, pkt_size);
+ dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
return skb;
}
@@ -6136,10 +6137,7 @@ static int r8169_phy_connect(struct rtl8169_private *tp)
if (ret)
return ret;
- if (tp->supports_gmii)
- phy_remove_link_mode(phydev,
- ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
- else
+ if (!tp->supports_gmii)
phy_set_max_speed(phydev, SPEED_100);
phy_support_asym_pause(phydev);
@@ -6589,13 +6587,18 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
{
unsigned int flags;
- if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
rtl_unlock_config_regs(tp);
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
rtl_lock_config_regs(tp);
+ /* fall through */
+ case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24:
flags = PCI_IRQ_LEGACY;
- } else {
+ break;
+ default:
flags = PCI_IRQ_ALL_TYPES;
+ break;
}
return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index ef8f08931fe8..6cacd5e893ac 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Renesas Ethernet AVB device driver
*
- * Copyright (C) 2014-2015 Renesas Electronics Corporation
+ * Copyright (C) 2014-2019 Renesas Electronics Corporation
* Copyright (C) 2015 Renesas Solutions Corp.
* Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
*
@@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
kfree(ts_skb);
if (tag == tfa_tag) {
skb_tstamp_tx(skb, &shhwtstamps);
+ dev_consume_skb_any(skb);
break;
+ } else {
+ dev_kfree_skb_any(skb);
}
}
ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
@@ -1564,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
goto unmap;
}
- ts_skb->skb = skb;
+ ts_skb->skb = skb_get(skb);
ts_skb->tag = priv->ts_skb_tag++;
priv->ts_skb_tag &= 0x3ff;
list_add_tail(&ts_skb->list, &priv->ts_skb_list);
@@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev)
/* Clear the timestamp list */
list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
list_del(&ts_skb->list);
+ kfree_skb(ts_skb->skb);
kfree(ts_skb);
}
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 079f459c73a5..2c5d3f5b84dd 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2208,10 +2208,12 @@ static int rocker_router_fib_event(struct notifier_block *nb,
if (fen_info->fi->fib_nh_is_v6) {
NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
+ kfree(fib_work);
return notifier_from_errno(-EINVAL);
}
if (fen_info->fi->nh) {
NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported");
+ kfree(fib_work);
return notifier_from_errno(-EINVAL);
}
}
diff --git a/drivers/net/ethernet/samsung/Kconfig b/drivers/net/ethernet/samsung/Kconfig
index 027938017579..e92a178a76df 100644
--- a/drivers/net/ethernet/samsung/Kconfig
+++ b/drivers/net/ethernet/samsung/Kconfig
@@ -11,7 +11,7 @@ config NET_VENDOR_SAMSUNG
say Y.
Note that the answer to this question does not directly affect
- the kernel: saying N will just case the configurator to skip all
+ the kernel: saying N will just cause the configurator to skip all
the questions about Samsung chipsets. If you say Y, you will be asked
for your specific chipset/driver in the following questions.
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 7a5e6c5abb57..276c7cae7cee 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -794,15 +794,16 @@ static int sgiseeq_probe(struct platform_device *pdev)
printk(KERN_ERR "Sgiseeq: Cannot register net device, "
"aborting.\n");
err = -ENODEV;
- goto err_out_free_page;
+ goto err_out_free_attrs;
}
printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
return 0;
-err_out_free_page:
- free_page((unsigned long) sp->srings);
+err_out_free_attrs:
+ dma_free_attrs(&pdev->dev, sizeof(*sp->srings), sp->srings,
+ sp->srings_dma, DMA_ATTR_NON_CONSISTENT);
err_out_free_dev:
free_netdev(dev);
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index bd14803545de..8d88e4083456 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -712,6 +712,7 @@ static void smc911x_phy_detect(struct net_device *dev)
/* Found an external PHY */
break;
}
+ /* Else, fall through */
default:
/* Internal media only */
SMC_GET_PHY_ID1(lp, 1, id1);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 4644b2aeeba1..e2e469c37a4d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1194,10 +1194,8 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
int ret;
struct device *dev = &bsp_priv->pdev->dev;
- if (!ldo) {
- dev_err(dev, "no regulator found\n");
- return -1;
- }
+ if (!ldo)
+ return 0;
if (enable) {
ret = regulator_enable(ldo);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 4083019c547a..f97a4096f8fc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -873,7 +873,12 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
int ret;
u32 reg, val;
- regmap_field_read(gmac->regmap_field, &val);
+ ret = regmap_field_read(gmac->regmap_field, &val);
+ if (ret) {
+ dev_err(priv->device, "Fail to read from regmap field.\n");
+ return ret;
+ }
+
reg = gmac->variant->default_syscon_value;
if (reg != val)
dev_warn(priv->device,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 01c2e2d83e76..fc9954e4a772 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -85,6 +85,8 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
u32 value;
base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
+ if (queue >= 4)
+ queue -= 4;
value = readl(ioaddr + base_register);
@@ -102,6 +104,8 @@ static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
u32 value;
base_register = (queue < 4) ? GMAC_TXQ_PRTY_MAP0 : GMAC_TXQ_PRTY_MAP1;
+ if (queue >= 4)
+ queue -= 4;
value = readl(ioaddr + base_register);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 7f86dffb264d..3174b701aa90 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -44,11 +44,13 @@
#define XGMAC_CORE_INIT_RX 0
#define XGMAC_PACKET_FILTER 0x00000008
#define XGMAC_FILTER_RA BIT(31)
+#define XGMAC_FILTER_HPF BIT(10)
#define XGMAC_FILTER_PCF BIT(7)
#define XGMAC_FILTER_PM BIT(4)
#define XGMAC_FILTER_HMC BIT(2)
#define XGMAC_FILTER_PR BIT(0)
#define XGMAC_HASH_TABLE(x) (0x00000010 + (x) * 4)
+#define XGMAC_MAX_HASH_TABLE 8
#define XGMAC_RXQ_CTRL0 0x000000a0
#define XGMAC_RXQEN(x) GENMASK((x) * 2 + 1, (x) * 2)
#define XGMAC_RXQEN_SHIFT(x) ((x) * 2)
@@ -99,11 +101,12 @@
#define XGMAC_MDIO_ADDR 0x00000200
#define XGMAC_MDIO_DATA 0x00000204
#define XGMAC_MDIO_C22P 0x00000220
-#define XGMAC_ADDR0_HIGH 0x00000300
+#define XGMAC_ADDRx_HIGH(x) (0x00000300 + (x) * 0x8)
+#define XGMAC_ADDR_MAX 32
#define XGMAC_AE BIT(31)
#define XGMAC_DCS GENMASK(19, 16)
#define XGMAC_DCS_SHIFT 16
-#define XGMAC_ADDR0_LOW 0x00000304
+#define XGMAC_ADDRx_LOW(x) (0x00000304 + (x) * 0x8)
#define XGMAC_ARP_ADDR 0x00000c10
#define XGMAC_TIMESTAMP_STATUS 0x00000d20
#define XGMAC_TXTSC BIT(15)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 0a32c96a7854..85c68b7ee8c6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -4,6 +4,8 @@
* stmmac XGMAC support.
*/
+#include <linux/bitrev.h>
+#include <linux/crc32.h>
#include "stmmac.h"
#include "dwxgmac2.h"
@@ -106,6 +108,8 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
u32 value, reg;
reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
+ if (queue >= 4)
+ queue -= 4;
value = readl(ioaddr + reg);
value &= ~XGMAC_PSRQ(queue);
@@ -169,6 +173,8 @@ static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue,
u32 value, reg;
reg = (queue < 4) ? XGMAC_MTL_RXQ_DMA_MAP0 : XGMAC_MTL_RXQ_DMA_MAP1;
+ if (queue >= 4)
+ queue -= 4;
value = readl(ioaddr + reg);
value &= ~XGMAC_QxMDMACH(queue);
@@ -278,10 +284,10 @@ static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
u32 value;
value = (addr[5] << 8) | addr[4];
- writel(value | XGMAC_AE, ioaddr + XGMAC_ADDR0_HIGH);
+ writel(value | XGMAC_AE, ioaddr + XGMAC_ADDRx_HIGH(reg_n));
value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
- writel(value, ioaddr + XGMAC_ADDR0_LOW);
+ writel(value, ioaddr + XGMAC_ADDRx_LOW(reg_n));
}
static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
@@ -291,8 +297,8 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
u32 hi_addr, lo_addr;
/* Read the MAC address from the hardware */
- hi_addr = readl(ioaddr + XGMAC_ADDR0_HIGH);
- lo_addr = readl(ioaddr + XGMAC_ADDR0_LOW);
+ hi_addr = readl(ioaddr + XGMAC_ADDRx_HIGH(reg_n));
+ lo_addr = readl(ioaddr + XGMAC_ADDRx_LOW(reg_n));
/* Extract the MAC address from the high and low words */
addr[0] = lo_addr & 0xff;
@@ -303,19 +309,82 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
addr[5] = (hi_addr >> 8) & 0xff;
}
+static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
+ int mcbitslog2)
+{
+ int numhashregs, regs;
+
+ switch (mcbitslog2) {
+ case 6:
+ numhashregs = 2;
+ break;
+ case 7:
+ numhashregs = 4;
+ break;
+ case 8:
+ numhashregs = 8;
+ break;
+ default:
+ return;
+ }
+
+ for (regs = 0; regs < numhashregs; regs++)
+ writel(mcfilterbits[regs], ioaddr + XGMAC_HASH_TABLE(regs));
+}
+
static void dwxgmac2_set_filter(struct mac_device_info *hw,
struct net_device *dev)
{
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
- u32 value = XGMAC_FILTER_RA;
+ u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
+ int mcbitslog2 = hw->mcast_bits_log2;
+ u32 mc_filter[8];
+ int i;
+
+ value &= ~(XGMAC_FILTER_PR | XGMAC_FILTER_HMC | XGMAC_FILTER_PM);
+ value |= XGMAC_FILTER_HPF;
+
+ memset(mc_filter, 0, sizeof(mc_filter));
if (dev->flags & IFF_PROMISC) {
- value |= XGMAC_FILTER_PR | XGMAC_FILTER_PCF;
+ value |= XGMAC_FILTER_PR;
+ value |= XGMAC_FILTER_PCF;
} else if ((dev->flags & IFF_ALLMULTI) ||
- (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
+ (netdev_mc_count(dev) > hw->multicast_filter_bins)) {
value |= XGMAC_FILTER_PM;
- writel(~0x0, ioaddr + XGMAC_HASH_TABLE(0));
- writel(~0x0, ioaddr + XGMAC_HASH_TABLE(1));
+
+ for (i = 0; i < XGMAC_MAX_HASH_TABLE; i++)
+ writel(~0x0, ioaddr + XGMAC_HASH_TABLE(i));
+ } else if (!netdev_mc_empty(dev)) {
+ struct netdev_hw_addr *ha;
+
+ value |= XGMAC_FILTER_HMC;
+
+ netdev_for_each_mc_addr(ha, dev) {
+ int nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
+ (32 - mcbitslog2));
+ mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
+ }
+ }
+
+ dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
+
+ /* Handle multiple unicast addresses */
+ if (netdev_uc_count(dev) > XGMAC_ADDR_MAX) {
+ value |= XGMAC_FILTER_PR;
+ } else {
+ struct netdev_hw_addr *ha;
+ int reg = 1;
+
+ netdev_for_each_uc_addr(ha, dev) {
+ dwxgmac2_set_umac_addr(hw, ha->addr, reg);
+ reg++;
+ }
+
+ for ( ; reg < XGMAC_ADDR_MAX; reg++) {
+ writel(0, ioaddr + XGMAC_ADDRx_HIGH(reg));
+ writel(0, ioaddr + XGMAC_ADDRx_LOW(reg));
+ }
}
writel(value, ioaddr + XGMAC_PACKET_FILTER);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c7c9e5f162e6..fd54c7c87485 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -814,20 +814,15 @@ static void stmmac_validate(struct phylink_config *config,
phylink_set(mac_supported, 10baseT_Full);
phylink_set(mac_supported, 100baseT_Half);
phylink_set(mac_supported, 100baseT_Full);
+ phylink_set(mac_supported, 1000baseT_Half);
+ phylink_set(mac_supported, 1000baseT_Full);
+ phylink_set(mac_supported, 1000baseKX_Full);
phylink_set(mac_supported, Autoneg);
phylink_set(mac_supported, Pause);
phylink_set(mac_supported, Asym_Pause);
phylink_set_port_modes(mac_supported);
- if (priv->plat->has_gmac ||
- priv->plat->has_gmac4 ||
- priv->plat->has_xgmac) {
- phylink_set(mac_supported, 1000baseT_Half);
- phylink_set(mac_supported, 1000baseT_Full);
- phylink_set(mac_supported, 1000baseKX_Full);
- }
-
/* Cut down 1G if asked to */
if ((max_speed > 0) && (max_speed < 1000)) {
phylink_set(mask, 1000baseT_Full);
@@ -1295,6 +1290,8 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
"(%s) dma_rx_phy=0x%08x\n", __func__,
(u32)rx_q->dma_rx_phy);
+ stmmac_clear_rx_descriptors(priv, queue);
+
for (i = 0; i < DMA_RX_SIZE; i++) {
struct dma_desc *p;
@@ -1312,8 +1309,6 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
rx_q->cur_rx = 0;
rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
- stmmac_clear_rx_descriptors(priv, queue);
-
/* Setup the chained descriptor addresses */
if (priv->mode == STMMAC_CHAIN_MODE) {
if (priv->extend_desc)
@@ -1555,9 +1550,8 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
goto err_dma;
}
- rx_q->buf_pool = kmalloc_array(DMA_RX_SIZE,
- sizeof(*rx_q->buf_pool),
- GFP_KERNEL);
+ rx_q->buf_pool = kcalloc(DMA_RX_SIZE, sizeof(*rx_q->buf_pool),
+ GFP_KERNEL);
if (!rx_q->buf_pool)
goto err_dma;
@@ -1608,15 +1602,15 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
tx_q->queue_index = queue;
tx_q->priv_data = priv;
- tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
- sizeof(*tx_q->tx_skbuff_dma),
- GFP_KERNEL);
+ tx_q->tx_skbuff_dma = kcalloc(DMA_TX_SIZE,
+ sizeof(*tx_q->tx_skbuff_dma),
+ GFP_KERNEL);
if (!tx_q->tx_skbuff_dma)
goto err_dma;
- tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE,
- sizeof(struct sk_buff *),
- GFP_KERNEL);
+ tx_q->tx_skbuff = kcalloc(DMA_TX_SIZE,
+ sizeof(struct sk_buff *),
+ GFP_KERNEL);
if (!tx_q->tx_skbuff)
goto err_dma;
@@ -3277,9 +3271,11 @@ static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q)
static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
- int dirty = stmmac_rx_dirty(priv, queue);
+ int len, dirty = stmmac_rx_dirty(priv, queue);
unsigned int entry = rx_q->dirty_rx;
+ len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+
while (dirty-- > 0) {
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
struct dma_desc *p;
@@ -3297,6 +3293,13 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
}
buf->addr = page_pool_get_dma_addr(buf->page);
+
+ /* Sync whole allocation to device. This will invalidate old
+ * data.
+ */
+ dma_sync_single_for_device(priv->device, buf->addr, len,
+ DMA_FROM_DEVICE);
+
stmmac_set_desc_addr(priv, p, buf->addr);
stmmac_refill_desc3(priv, rx_q, p);
@@ -3431,8 +3434,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
skb_copy_to_linear_data(skb, page_address(buf->page),
frame_len);
skb_put(skb, frame_len);
- dma_sync_single_for_device(priv->device, buf->addr,
- frame_len, DMA_FROM_DEVICE);
if (netif_msg_pktdata(priv)) {
netdev_dbg(priv->dev, "frame received (%dbytes)",
@@ -4319,8 +4320,9 @@ int stmmac_dvr_probe(struct device *device,
NAPI_POLL_WEIGHT);
}
if (queue < priv->plat->tx_queues_to_use) {
- netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx,
- NAPI_POLL_WEIGHT);
+ netif_tx_napi_add(ndev, &ch->tx_napi,
+ stmmac_napi_poll_tx,
+ NAPI_POLL_WEIGHT);
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 73fc2524372e..154daf4d1072 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -370,6 +370,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
return ERR_PTR(-ENOMEM);
*mac = of_get_mac_address(np);
+ if (IS_ERR(*mac)) {
+ if (PTR_ERR(*mac) == -EPROBE_DEFER)
+ return ERR_CAST(*mac);
+
+ *mac = NULL;
+ }
+
plat->interface = of_get_phy_mode(np);
/* Some wrapper drivers still rely on phy_node. Let's save it while
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 58ea18af9813..6c305b6ecad0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -37,7 +37,7 @@ static struct stmmac_tc_entry *tc_find_entry(struct stmmac_priv *priv,
entry = &priv->tc_entries[i];
if (!entry->in_use && !first && free)
first = entry;
- if (entry->handle == loc && !free)
+ if ((entry->handle == loc) && !free && !entry->is_frag)
dup = entry;
}
@@ -94,7 +94,7 @@ static int tc_fill_entry(struct stmmac_priv *priv,
struct stmmac_tc_entry *entry, *frag = NULL;
struct tc_u32_sel *sel = cls->knode.sel;
u32 off, data, mask, real_off, rem;
- u32 prio = cls->common.prio;
+ u32 prio = cls->common.prio << 16;
int ret;
/* Only 1 match per entry */
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 32a89744972d..a46b8b2e44e1 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2775,6 +2775,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (!cpsw)
return -ENOMEM;
+ platform_set_drvdata(pdev, cpsw);
cpsw->dev = dev;
mode = devm_gpiod_get_array_optional(dev, "mode", GPIOD_OUT_LOW);
@@ -2879,7 +2880,6 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_cpts;
}
- platform_set_drvdata(pdev, cpsw);
priv = netdev_priv(ndev);
priv->cpsw = cpsw;
priv->ndev = ndev;
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 5b196ebfed49..0f346761a2b2 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -788,6 +788,7 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
/* fallthrough, if we release the descriptors
* brutally (then we don't care about
* SPIDER_NET_DESCR_CARDOWNED) */
+ /* Fall through */
case SPIDER_NET_DESCR_RESPONSE_ERROR:
case SPIDER_NET_DESCR_PROTECTION_ERROR:
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 8479a440527b..12466a72cefc 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -1504,7 +1504,7 @@ tc35815_rx(struct net_device *dev, int limit)
pci_unmap_single(lp->pci_dev,
lp->rx_skbs[cur_bd].skb_dma,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN)
+ if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN != 0)
memmove(skb->data, skb->data - NET_IP_ALIGN,
pkt_len);
data = skb_put(skb, pkt_len);
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 78a7de3fb622..c62f474b6d08 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -371,9 +371,10 @@ tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
static void tsi108_stat_carry(struct net_device *dev)
{
struct tsi108_prv_data *data = netdev_priv(dev);
+ unsigned long flags;
u32 carry1, carry2;
- spin_lock_irq(&data->misclock);
+ spin_lock_irqsave(&data->misclock, flags);
carry1 = TSI_READ(TSI108_STAT_CARRY1);
carry2 = TSI_READ(TSI108_STAT_CARRY2);
@@ -441,7 +442,7 @@ static void tsi108_stat_carry(struct net_device *dev)
TSI108_STAT_TXPAUSEDROP_CARRY,
&data->tx_pause_drop);
- spin_unlock_irq(&data->misclock);
+ spin_unlock_irqrestore(&data->misclock, flags);
}
/* Read a stat counter atomically with respect to carries.
diff --git a/drivers/net/ethernet/xscale/Kconfig b/drivers/net/ethernet/xscale/Kconfig
index 2f354ba029a6..cd0a8f46e7c6 100644
--- a/drivers/net/ethernet/xscale/Kconfig
+++ b/drivers/net/ethernet/xscale/Kconfig
@@ -13,7 +13,7 @@ config NET_VENDOR_XSCALE
Note that the answer to this question does not directly affect the
kernel: saying N will just cause the configurator to skip all
- the questions about XSacle IXP devices. If you say Y, you will be
+ the questions about XScale IXP devices. If you say Y, you will be
asked for your specific card in the following questions.
if NET_VENDOR_XSCALE
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 331c16d30d5d..23281aeeb222 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -344,10 +344,10 @@ static void sp_bump(struct sixpack *sp, char cmd)
sp->dev->stats.rx_bytes += count;
- if ((skb = dev_alloc_skb(count)) == NULL)
+ if ((skb = dev_alloc_skb(count + 1)) == NULL)
goto out_mem;
- ptr = skb_put(skb, count);
+ ptr = skb_put(skb, count + 1);
*ptr++ = cmd; /* KISS command */
memcpy(ptr, sp->cooked_buf + 1, count);
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index daab2c07d891..9303aeb2595f 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -500,8 +500,9 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
}
break;
}
+ /* fall through */
- default: /* fall through */
+ default:
if (bc->hdlctx.calibrate <= 0)
return 0;
i = min_t(int, cnt, bc->hdlctx.calibrate);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 3544e1991579..e8fce6d715ef 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1239,12 +1239,15 @@ static void netvsc_get_stats64(struct net_device *net,
struct rtnl_link_stats64 *t)
{
struct net_device_context *ndev_ctx = netdev_priv(net);
- struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev);
+ struct netvsc_device *nvdev;
struct netvsc_vf_pcpu_stats vf_tot;
int i;
+ rcu_read_lock();
+
+ nvdev = rcu_dereference(ndev_ctx->nvdev);
if (!nvdev)
- return;
+ goto out;
netdev_stats_to_stats64(t, &net->stats);
@@ -1283,6 +1286,8 @@ static void netvsc_get_stats64(struct net_device *net,
t->rx_packets += packets;
t->multicast += multicast;
}
+out:
+ rcu_read_unlock();
}
static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index b41696e16bdc..c20e7ef18bc9 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -802,7 +802,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
err = hwsim_subscribe_all_others(phy);
if (err < 0) {
mutex_unlock(&hwsim_phys_lock);
- goto err_reg;
+ goto err_subscribe;
}
}
list_add_tail(&phy->list, &hwsim_phys);
@@ -812,6 +812,8 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
return idx;
+err_subscribe:
+ ieee802154_unregister_hw(phy->hw);
err_reg:
kfree(pib);
err_pib:
@@ -901,9 +903,9 @@ static __init int hwsim_init_module(void)
return 0;
platform_drv:
- genl_unregister_family(&hwsim_genl_family);
-platform_dev:
platform_device_unregister(mac802154hwsim_dev);
+platform_dev:
+ genl_unregister_family(&hwsim_genl_family);
return rc;
}
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index c5c417a3c0ce..bcc40a236624 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -73,46 +73,47 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
debugfs_remove_recursive(nsim_dev_port->ddir);
}
+static struct net *nsim_devlink_net(struct devlink *devlink)
+{
+ return &init_net;
+}
+
static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
{
- struct nsim_dev *nsim_dev = priv;
+ struct net *net = priv;
- return nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV4_FIB, false);
+ return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
}
static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
{
- struct nsim_dev *nsim_dev = priv;
+ struct net *net = priv;
- return nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV4_FIB_RULES, false);
+ return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
}
static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
{
- struct nsim_dev *nsim_dev = priv;
+ struct net *net = priv;
- return nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV6_FIB, false);
+ return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
}
static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
{
- struct nsim_dev *nsim_dev = priv;
+ struct net *net = priv;
- return nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV6_FIB_RULES, false);
+ return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
}
static int nsim_dev_resources_register(struct devlink *devlink)
{
- struct nsim_dev *nsim_dev = devlink_priv(devlink);
struct devlink_resource_size_params params = {
.size_max = (u64)-1,
.size_granularity = 1,
.unit = DEVLINK_RESOURCE_UNIT_ENTRY
};
+ struct net *net = nsim_devlink_net(devlink);
int err;
u64 n;
@@ -126,8 +127,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
goto out;
}
- n = nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV4_FIB, true);
+ n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
err = devlink_resource_register(devlink, "fib", n,
NSIM_RESOURCE_IPV4_FIB,
NSIM_RESOURCE_IPV4, &params);
@@ -136,8 +136,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
return err;
}
- n = nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV4_FIB_RULES, true);
+ n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
err = devlink_resource_register(devlink, "fib-rules", n,
NSIM_RESOURCE_IPV4_FIB_RULES,
NSIM_RESOURCE_IPV4, &params);
@@ -156,8 +155,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
goto out;
}
- n = nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV6_FIB, true);
+ n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
err = devlink_resource_register(devlink, "fib", n,
NSIM_RESOURCE_IPV6_FIB,
NSIM_RESOURCE_IPV6, &params);
@@ -166,8 +164,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
return err;
}
- n = nsim_fib_get_val(nsim_dev->fib_data,
- NSIM_RESOURCE_IPV6_FIB_RULES, true);
+ n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
err = devlink_resource_register(devlink, "fib-rules", n,
NSIM_RESOURCE_IPV6_FIB_RULES,
NSIM_RESOURCE_IPV6, &params);
@@ -179,19 +176,19 @@ static int nsim_dev_resources_register(struct devlink *devlink)
devlink_resource_occ_get_register(devlink,
NSIM_RESOURCE_IPV4_FIB,
nsim_dev_ipv4_fib_resource_occ_get,
- nsim_dev);
+ net);
devlink_resource_occ_get_register(devlink,
NSIM_RESOURCE_IPV4_FIB_RULES,
nsim_dev_ipv4_fib_rules_res_occ_get,
- nsim_dev);
+ net);
devlink_resource_occ_get_register(devlink,
NSIM_RESOURCE_IPV6_FIB,
nsim_dev_ipv6_fib_resource_occ_get,
- nsim_dev);
+ net);
devlink_resource_occ_get_register(devlink,
NSIM_RESOURCE_IPV6_FIB_RULES,
nsim_dev_ipv6_fib_rules_res_occ_get,
- nsim_dev);
+ net);
out:
return err;
}
@@ -199,11 +196,11 @@ out:
static int nsim_dev_reload(struct devlink *devlink,
struct netlink_ext_ack *extack)
{
- struct nsim_dev *nsim_dev = devlink_priv(devlink);
enum nsim_resource_id res_ids[] = {
NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
};
+ struct net *net = nsim_devlink_net(devlink);
int i;
for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
@@ -212,8 +209,7 @@ static int nsim_dev_reload(struct devlink *devlink,
err = devlink_resource_size_get(devlink, res_ids[i], &val);
if (!err) {
- err = nsim_fib_set_max(nsim_dev->fib_data,
- res_ids[i], val, extack);
+ err = nsim_fib_set_max(net, res_ids[i], val, extack);
if (err)
return err;
}
@@ -285,15 +281,9 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
mutex_init(&nsim_dev->port_list_lock);
nsim_dev->fw_update_status = true;
- nsim_dev->fib_data = nsim_fib_create();
- if (IS_ERR(nsim_dev->fib_data)) {
- err = PTR_ERR(nsim_dev->fib_data);
- goto err_devlink_free;
- }
-
err = nsim_dev_resources_register(devlink);
if (err)
- goto err_fib_destroy;
+ goto err_devlink_free;
err = devlink_register(devlink, &nsim_bus_dev->dev);
if (err)
@@ -315,8 +305,6 @@ err_dl_unregister:
devlink_unregister(devlink);
err_resources_unregister:
devlink_resources_unregister(devlink, NULL);
-err_fib_destroy:
- nsim_fib_destroy(nsim_dev->fib_data);
err_devlink_free:
devlink_free(devlink);
return ERR_PTR(err);
@@ -330,7 +318,6 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
nsim_dev_debugfs_exit(nsim_dev);
devlink_unregister(devlink);
devlink_resources_unregister(devlink, NULL);
- nsim_fib_destroy(nsim_dev->fib_data);
mutex_destroy(&nsim_dev->port_list_lock);
devlink_free(devlink);
}
diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c
index 8c57ba747772..f61d094746c0 100644
--- a/drivers/net/netdevsim/fib.c
+++ b/drivers/net/netdevsim/fib.c
@@ -18,6 +18,7 @@
#include <net/ip_fib.h>
#include <net/ip6_fib.h>
#include <net/fib_rules.h>
+#include <net/netns/generic.h>
#include "netdevsim.h"
@@ -32,14 +33,15 @@ struct nsim_per_fib_data {
};
struct nsim_fib_data {
- struct notifier_block fib_nb;
struct nsim_per_fib_data ipv4;
struct nsim_per_fib_data ipv6;
};
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
- enum nsim_resource_id res_id, bool max)
+static unsigned int nsim_fib_net_id;
+
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max)
{
+ struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
struct nsim_fib_entry *entry;
switch (res_id) {
@@ -62,10 +64,10 @@ u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
return max ? entry->max : entry->num;
}
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
- enum nsim_resource_id res_id, u64 val,
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
struct netlink_ext_ack *extack)
{
+ struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
struct nsim_fib_entry *entry;
int err = 0;
@@ -118,9 +120,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
return err;
}
-static int nsim_fib_rule_event(struct nsim_fib_data *data,
- struct fib_notifier_info *info, bool add)
+static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add)
{
+ struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
struct netlink_ext_ack *extack = info->extack;
int err = 0;
@@ -155,9 +157,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
return err;
}
-static int nsim_fib_event(struct nsim_fib_data *data,
- struct fib_notifier_info *info, bool add)
+static int nsim_fib_event(struct fib_notifier_info *info, bool add)
{
+ struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
struct netlink_ext_ack *extack = info->extack;
int err = 0;
@@ -176,22 +178,18 @@ static int nsim_fib_event(struct nsim_fib_data *data,
static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
void *ptr)
{
- struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
- fib_nb);
struct fib_notifier_info *info = ptr;
int err = 0;
switch (event) {
case FIB_EVENT_RULE_ADD: /* fall through */
case FIB_EVENT_RULE_DEL:
- err = nsim_fib_rule_event(data, info,
- event == FIB_EVENT_RULE_ADD);
+ err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD);
break;
case FIB_EVENT_ENTRY_ADD: /* fall through */
case FIB_EVENT_ENTRY_DEL:
- err = nsim_fib_event(data, info,
- event == FIB_EVENT_ENTRY_ADD);
+ err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
break;
}
@@ -201,23 +199,30 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
/* inconsistent dump, trying again */
static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
{
- struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
- fib_nb);
+ struct nsim_fib_data *data;
+ struct net *net;
+
+ rcu_read_lock();
+ for_each_net_rcu(net) {
+ data = net_generic(net, nsim_fib_net_id);
+
+ data->ipv4.fib.num = 0ULL;
+ data->ipv4.rules.num = 0ULL;
- data->ipv4.fib.num = 0ULL;
- data->ipv4.rules.num = 0ULL;
- data->ipv6.fib.num = 0ULL;
- data->ipv6.rules.num = 0ULL;
+ data->ipv6.fib.num = 0ULL;
+ data->ipv6.rules.num = 0ULL;
+ }
+ rcu_read_unlock();
}
-struct nsim_fib_data *nsim_fib_create(void)
-{
- struct nsim_fib_data *data;
- int err;
+static struct notifier_block nsim_fib_nb = {
+ .notifier_call = nsim_fib_event_nb,
+};
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return ERR_PTR(-ENOMEM);
+/* Initialize per network namespace state */
+static int __net_init nsim_fib_netns_init(struct net *net)
+{
+ struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);
data->ipv4.fib.max = (u64)-1;
data->ipv4.rules.max = (u64)-1;
@@ -225,22 +230,37 @@ struct nsim_fib_data *nsim_fib_create(void)
data->ipv6.fib.max = (u64)-1;
data->ipv6.rules.max = (u64)-1;
- data->fib_nb.notifier_call = nsim_fib_event_nb;
- err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent);
- if (err) {
- pr_err("Failed to register fib notifier\n");
- goto err_out;
- }
+ return 0;
+}
- return data;
+static struct pernet_operations nsim_fib_net_ops = {
+ .init = nsim_fib_netns_init,
+ .id = &nsim_fib_net_id,
+ .size = sizeof(struct nsim_fib_data),
+};
-err_out:
- kfree(data);
- return ERR_PTR(err);
+void nsim_fib_exit(void)
+{
+ unregister_pernet_subsys(&nsim_fib_net_ops);
+ unregister_fib_notifier(&nsim_fib_nb);
}
-void nsim_fib_destroy(struct nsim_fib_data *data)
+int nsim_fib_init(void)
{
- unregister_fib_notifier(&data->fib_nb);
- kfree(data);
+ int err;
+
+ err = register_pernet_subsys(&nsim_fib_net_ops);
+ if (err < 0) {
+ pr_err("Failed to register pernet subsystem\n");
+ goto err_out;
+ }
+
+ err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
+ if (err < 0) {
+ pr_err("Failed to register fib notifier\n");
+ goto err_out;
+ }
+
+err_out:
+ return err;
}
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 0740940f41b1..55f57f76d01b 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -357,12 +357,18 @@ static int __init nsim_module_init(void)
if (err)
goto err_dev_exit;
- err = rtnl_link_register(&nsim_link_ops);
+ err = nsim_fib_init();
if (err)
goto err_bus_exit;
+ err = rtnl_link_register(&nsim_link_ops);
+ if (err)
+ goto err_fib_exit;
+
return 0;
+err_fib_exit:
+ nsim_fib_exit();
err_bus_exit:
nsim_bus_exit();
err_dev_exit:
@@ -373,6 +379,7 @@ err_dev_exit:
static void __exit nsim_module_exit(void)
{
rtnl_link_unregister(&nsim_link_ops);
+ nsim_fib_exit();
nsim_bus_exit();
nsim_dev_exit();
}
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 79c05af2a7c0..9404637d34b7 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -169,12 +169,10 @@ int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
unsigned int port_index);
-struct nsim_fib_data *nsim_fib_create(void);
-void nsim_fib_destroy(struct nsim_fib_data *fib_data);
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
- enum nsim_resource_id res_id, bool max);
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
- enum nsim_resource_id res_id, u64 val,
+int nsim_fib_init(void);
+void nsim_fib_exit(void);
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max);
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
struct netlink_ext_ack *extack);
#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 222ccd9ecfce..6ad8b1c63c34 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -257,36 +257,20 @@ static int at803x_config_init(struct phy_device *phydev)
* after HW reset: RX delay enabled and TX delay disabled
* after SW reset: RX delay enabled, while TX delay retains the
* value before reset.
- *
- * So let's first disable the RX and TX delays in PHY and enable
- * them based on the mode selected (this also takes care of RGMII
- * mode where we expect delays to be disabled)
*/
-
- ret = at803x_disable_rx_delay(phydev);
- if (ret < 0)
- return ret;
- ret = at803x_disable_tx_delay(phydev);
- if (ret < 0)
- return ret;
-
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
- /* If RGMII_ID or RGMII_RXID are specified enable RX delay,
- * otherwise keep it disabled
- */
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
ret = at803x_enable_rx_delay(phydev);
- if (ret < 0)
- return ret;
- }
+ else
+ ret = at803x_disable_rx_delay(phydev);
+ if (ret < 0)
+ return ret;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
- /* If RGMII_ID or RGMII_TXID are specified enable TX delay,
- * otherwise keep it disabled
- */
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
ret = at803x_enable_tx_delay(phydev);
- }
+ else
+ ret = at803x_disable_tx_delay(phydev);
return ret;
}
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index 3ffe46df249e..7c5265fd2b94 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -216,8 +216,10 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
if (IS_ERR(gpiod)) {
if (PTR_ERR(gpiod) == -EPROBE_DEFER)
return gpiod;
- pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
- fixed_link_node);
+
+ if (PTR_ERR(gpiod) != -ENOENT)
+ pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
+ fixed_link_node);
gpiod = NULL;
}
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 28676af97b42..645d354ffb48 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -2226,8 +2226,8 @@ static int vsc8514_probe(struct phy_device *phydev)
vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
vsc8531->hw_stats = vsc85xx_hw_stats;
vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
- vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
- sizeof(u64), GFP_KERNEL);
+ vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+ sizeof(u64), GFP_KERNEL);
if (!vsc8531->stats)
return -ENOMEM;
@@ -2251,8 +2251,8 @@ static int vsc8574_probe(struct phy_device *phydev)
vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
vsc8531->hw_stats = vsc8584_hw_stats;
vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
- vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
- sizeof(u64), GFP_KERNEL);
+ vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+ sizeof(u64), GFP_KERNEL);
if (!vsc8531->stats)
return -ENOMEM;
@@ -2281,8 +2281,8 @@ static int vsc8584_probe(struct phy_device *phydev)
vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
vsc8531->hw_stats = vsc8584_hw_stats;
vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
- vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
- sizeof(u64), GFP_KERNEL);
+ vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+ sizeof(u64), GFP_KERNEL);
if (!vsc8531->stats)
return -ENOMEM;
@@ -2311,8 +2311,8 @@ static int vsc85xx_probe(struct phy_device *phydev)
vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
vsc8531->hw_stats = vsc85xx_hw_stats;
vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
- vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
- sizeof(u64), GFP_KERNEL);
+ vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+ sizeof(u64), GFP_KERNEL);
if (!vsc8531->stats)
return -ENOMEM;
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index b9d4145781ca..7935593debb1 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -219,6 +219,20 @@ int genphy_c45_read_link(struct phy_device *phydev)
int val, devad;
bool link = true;
+ if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ if (val < 0)
+ return val;
+
+ /* Autoneg is being started, therefore disregard current
+ * link status and report link as down.
+ */
+ if (val & MDIO_AN_CTRL1_RESTART) {
+ phydev->link = 0;
+ return 0;
+ }
+ }
+
while (mmd_mask && link) {
devad = __ffs(mmd_mask);
mmd_mask &= ~BIT(devad);
@@ -509,6 +523,32 @@ int genphy_c45_read_status(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_status);
+/**
+ * genphy_c45_config_aneg - restart auto-negotiation or forced setup
+ * @phydev: target phy_device struct
+ *
+ * Description: If auto-negotiation is enabled, we configure the
+ * advertising, and then restart auto-negotiation. If it is not
+ * enabled, then we force a configuration.
+ */
+int genphy_c45_config_aneg(struct phy_device *phydev)
+{
+ bool changed = false;
+ int ret;
+
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ return genphy_c45_pma_setup_forced(phydev);
+
+ ret = genphy_c45_an_config_aneg(phydev);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
+
/* The gen10g_* functions are the old Clause 45 stub */
int gen10g_config_aneg(struct phy_device *phydev)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef7aa738e0dc..6b0f89369b46 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -507,7 +507,7 @@ static int phy_config_aneg(struct phy_device *phydev)
* allowed to call genphy_config_aneg()
*/
if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
- return -EOPNOTSUPP;
+ return genphy_c45_config_aneg(phydev);
return genphy_config_aneg(phydev);
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 6b5cb87f3866..27ebc2c6c2d0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1752,7 +1752,17 @@ EXPORT_SYMBOL(genphy_aneg_done);
*/
int genphy_update_link(struct phy_device *phydev)
{
- int status;
+ int status = 0, bmcr;
+
+ bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
+ /* Autoneg is being started, therefore disregard BMSR value and
+ * report link as down.
+ */
+ if (bmcr & BMCR_ANRESTART)
+ goto done;
/* The link state is latched low so that momentary link
* drops can be detected. Do not double-read the status
@@ -1774,6 +1784,12 @@ done:
phydev->link = status & BMSR_LSTATUS ? 1 : 0;
phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
+ /* Consider the case that autoneg was started and "aneg complete"
+ * bit has been reset, but "link up" bit not yet.
+ */
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+ phydev->link = 0;
+
return 0;
}
EXPORT_SYMBOL(genphy_update_link);
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
index b86a4b2116f8..59a94e07e7c5 100644
--- a/drivers/net/phy/phy_led_triggers.c
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -48,8 +48,9 @@ void phy_led_trigger_change_speed(struct phy_device *phy)
if (!phy->last_triggered)
led_trigger_event(&phy->led_link_trigger->trigger,
LED_FULL);
+ else
+ led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
- led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
led_trigger_event(&plt->trigger, LED_FULL);
phy->last_triggered = plt;
}
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 5d0af041b8f9..a5a57ca94c1a 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -216,6 +216,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
pl->supported, true);
linkmode_zero(pl->supported);
phylink_set(pl->supported, MII);
+ phylink_set(pl->supported, Pause);
+ phylink_set(pl->supported, Asym_Pause);
if (s) {
__set_bit(s->bit, pl->supported);
} else {
@@ -374,8 +376,8 @@ static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_stat
* Local device Link partner
* Pause AsymDir Pause AsymDir Result
* 1 X 1 X TX+RX
- * 0 1 1 1 RX
- * 1 1 0 1 TX
+ * 0 1 1 1 TX
+ * 1 1 0 1 RX
*/
static void phylink_resolve_flow(struct phylink *pl,
struct phylink_link_state *state)
@@ -396,7 +398,7 @@ static void phylink_resolve_flow(struct phylink *pl,
new_pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
else if (pause & MLO_PAUSE_ASYM)
new_pause = state->pause & MLO_PAUSE_SYM ?
- MLO_PAUSE_RX : MLO_PAUSE_TX;
+ MLO_PAUSE_TX : MLO_PAUSE_RX;
} else {
new_pause = pl->link_config.pause & MLO_PAUSE_TXRX_MASK;
}
@@ -990,10 +992,10 @@ void phylink_start(struct phylink *pl)
}
if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
mod_timer(&pl->link_poll, jiffies + HZ);
- if (pl->sfp_bus)
- sfp_upstream_start(pl->sfp_bus);
if (pl->phydev)
phy_start(pl->phydev);
+ if (pl->sfp_bus)
+ sfp_upstream_start(pl->sfp_bus);
}
EXPORT_SYMBOL_GPL(phylink_start);
@@ -1010,10 +1012,10 @@ void phylink_stop(struct phylink *pl)
{
ASSERT_RTNL();
- if (pl->phydev)
- phy_stop(pl->phydev);
if (pl->sfp_bus)
sfp_upstream_stop(pl->sfp_bus);
+ if (pl->phydev)
+ phy_stop(pl->phydev);
del_timer_sync(&pl->link_poll);
if (pl->link_irq) {
free_irq(pl->link_irq, pl);
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 1d902ecb4aa8..a44dd3c8af63 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -1115,6 +1115,9 @@ static const struct proto_ops pppoe_ops = {
.recvmsg = pppoe_recvmsg,
.mmap = sock_no_mmap,
.ioctl = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = pppox_compat_ioctl,
+#endif
};
static const struct pppox_proto pppoe_proto = {
diff --git a/drivers/net/ppp/pppox.c b/drivers/net/ppp/pppox.c
index 5ef422a43d70..08364f10a43f 100644
--- a/drivers/net/ppp/pppox.c
+++ b/drivers/net/ppp/pppox.c
@@ -17,6 +17,7 @@
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/compat.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/net.h>
@@ -98,6 +99,18 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
EXPORT_SYMBOL(pppox_ioctl);
+#ifdef CONFIG_COMPAT
+int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == PPPOEIOCSFWD32)
+ cmd = PPPOEIOCSFWD;
+
+ return pppox_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
+}
+
+EXPORT_SYMBOL(pppox_compat_ioctl);
+#endif
+
static int pppox_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index a8e52c8e4128..734de7de03f7 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -623,6 +623,9 @@ static const struct proto_ops pptp_ops = {
.recvmsg = sock_no_recvmsg,
.mmap = sock_no_mmap,
.ioctl = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = pppox_compat_ioctl,
+#endif
};
static const struct pppox_proto pppox_pptp_proto = {
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index abfa0da9bbd2..e8089def5a46 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1004,6 +1004,8 @@ static void __team_compute_features(struct team *team)
team->dev->vlan_features = vlan_features;
team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX |
NETIF_F_GSO_UDP_L4;
team->dev->hard_header_len = max_hard_header_len;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 3d443597bd04..aab0be40d443 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -787,7 +787,8 @@ static void tun_detach_all(struct net_device *dev)
}
static int tun_attach(struct tun_struct *tun, struct file *file,
- bool skip_filter, bool napi, bool napi_frags)
+ bool skip_filter, bool napi, bool napi_frags,
+ bool publish_tun)
{
struct tun_file *tfile = file->private_data;
struct net_device *dev = tun->dev;
@@ -870,7 +871,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
* initialized tfile; otherwise we risk using half-initialized
* object.
*/
- rcu_assign_pointer(tfile->tun, tun);
+ if (publish_tun)
+ rcu_assign_pointer(tfile->tun, tun);
rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
tun->numqueues++;
tun_set_real_num_queues(tun);
@@ -1599,7 +1601,8 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
return true;
}
-static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
+static struct sk_buff *__tun_build_skb(struct tun_file *tfile,
+ struct page_frag *alloc_frag, char *buf,
int buflen, int len, int pad)
{
struct sk_buff *skb = build_skb(buf, buflen);
@@ -1609,6 +1612,7 @@ static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
skb_reserve(skb, pad);
skb_put(skb, len);
+ skb_set_owner_w(skb, tfile->socket.sk);
get_page(alloc_frag->page);
alloc_frag->offset += buflen;
@@ -1686,7 +1690,8 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
*/
if (hdr->gso_type || !xdp_prog) {
*skb_xdp = 1;
- return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+ return __tun_build_skb(tfile, alloc_frag, buf, buflen, len,
+ pad);
}
*skb_xdp = 0;
@@ -1723,7 +1728,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
rcu_read_unlock();
local_bh_enable();
- return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+ return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
err_xdp:
put_page(alloc_frag->page);
@@ -2727,7 +2732,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER,
ifr->ifr_flags & IFF_NAPI,
- ifr->ifr_flags & IFF_NAPI_FRAGS);
+ ifr->ifr_flags & IFF_NAPI_FRAGS, true);
if (err < 0)
return err;
@@ -2826,13 +2831,17 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
INIT_LIST_HEAD(&tun->disabled);
err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
- ifr->ifr_flags & IFF_NAPI_FRAGS);
+ ifr->ifr_flags & IFF_NAPI_FRAGS, false);
if (err < 0)
goto err_free_flow;
err = register_netdevice(tun->dev);
if (err < 0)
goto err_detach;
+ /* free_netdev() won't check refcnt, to aovid race
+ * with dev_put() we need publish tun after registration.
+ */
+ rcu_assign_pointer(tfile->tun, tun);
}
netif_carrier_on(tun->dev);
@@ -2975,7 +2984,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
if (ret < 0)
goto unlock;
ret = tun_attach(tun, file, false, tun->flags & IFF_NAPI,
- tun->flags & IFF_NAPI_FRAGS);
+ tun->flags & IFF_NAPI_FRAGS, true);
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
tun = rtnl_dereference(tfile->tun);
if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached)
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 8458e88c18e9..32f53de5b1fe 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -206,7 +206,15 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
goto bad_desc;
}
skip:
- if (rndis && header.usb_cdc_acm_descriptor &&
+ /* Communcation class functions with bmCapabilities are not
+ * RNDIS. But some Wireless class RNDIS functions use
+ * bmCapabilities for their own purpose. The failsafe is
+ * therefore applied only to Communication class RNDIS
+ * functions. The rndis test is redundant, but a cheap
+ * optimization.
+ */
+ if (rndis && is_rndis(&intf->cur_altsetting->desc) &&
+ header.usb_cdc_acm_descriptor &&
header.usb_cdc_acm_descriptor->bmCapabilities) {
dev_dbg(&intf->dev,
"ACM capabilities %02x, not really RNDIS?\n",
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
index 5519248a791e..32b08b18e120 100644
--- a/drivers/net/usb/cx82310_eth.c
+++ b/drivers/net/usb/cx82310_eth.c
@@ -163,7 +163,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
}
if (!timeout) {
dev_err(&udev->dev, "firmware not ready in time\n");
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+ goto err;
}
/* enable ethernet mode (?) */
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index d62b6706a537..fc5895f85cee 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -113,16 +113,16 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_1),
usb_buf, 24);
if (status != 0)
- return status;
+ goto out;
memcpy(usb_buf, init_msg_2, 12);
status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_2),
usb_buf, 28);
if (status != 0)
- return status;
+ goto out;
memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
-
+out:
kfree(usb_buf);
return status;
}
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 3d92ea6fcc02..f033fee225a1 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3792,7 +3792,7 @@ static int lan78xx_probe(struct usb_interface *intf,
ret = register_netdev(netdev);
if (ret != 0) {
netif_err(dev, probe, netdev, "couldn't register the device\n");
- goto out3;
+ goto out4;
}
usb_set_intfdata(intf, dev);
@@ -3807,12 +3807,14 @@ static int lan78xx_probe(struct usb_interface *intf,
ret = lan78xx_phy_init(dev);
if (ret < 0)
- goto out4;
+ goto out5;
return 0;
-out4:
+out5:
unregister_netdev(netdev);
+out4:
+ usb_free_urb(dev->urb_intr);
out3:
lan78xx_unbind(dev, intf);
out2:
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 6d25dea5ad4b..f7d117d80cfb 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -282,7 +282,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
{
int i;
- __u8 tmp;
+ __u8 tmp = 0;
__le16 retdatai;
int ret;
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 69e0a2acfcb0..b6dc5d714b5e 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1295,6 +1295,7 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x2001, 0x7e3d, 4)}, /* D-Link DWM-222 A2 */
{QMI_FIXED_INTF(0x2020, 0x2031, 4)}, /* Olicard 600 */
{QMI_FIXED_INTF(0x2020, 0x2033, 4)}, /* BroadMobi BM806U */
+ {QMI_FIXED_INTF(0x2020, 0x2060, 4)}, /* BroadMobi BM818 */
{QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */
{QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */
{QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 39e0768d734d..04137ac373b0 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -50,7 +50,7 @@
#define PLA_TEREDO_WAKE_BASE 0xc0c4
#define PLA_MAR 0xcd00
#define PLA_BACKUP 0xd000
-#define PAL_BDC_CR 0xd1a0
+#define PLA_BDC_CR 0xd1a0
#define PLA_TEREDO_TIMER 0xd2cc
#define PLA_REALWOW_TIMER 0xd2e8
#define PLA_SUSPEND_FLAG 0xd38a
@@ -274,7 +274,7 @@
#define TEREDO_RS_EVENT_MASK 0x00fe
#define OOB_TEREDO_EN 0x0001
-/* PAL_BDC_CR */
+/* PLA_BDC_CR */
#define ALDPS_PROXY_MODE 0x0001
/* PLA_EFUSE_CMD */
@@ -799,8 +799,11 @@ int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
value, index, tmp, size, 500);
+ if (ret < 0)
+ memset(data, 0xff, size);
+ else
+ memcpy(data, tmp, size);
- memcpy(data, tmp, size);
kfree(tmp);
return ret;
@@ -3191,9 +3194,9 @@ static void r8152b_enter_oob(struct r8152 *tp)
rtl_rx_vlan_en(tp, true);
- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
ocp_data |= ALDPS_PROXY_MODE;
- ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
@@ -3577,9 +3580,9 @@ static void r8153_enter_oob(struct r8152 *tp)
rtl_rx_vlan_en(tp, true);
- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
ocp_data |= ALDPS_PROXY_MODE;
- ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
@@ -4018,8 +4021,7 @@ static int rtl8152_close(struct net_device *netdev)
#ifdef CONFIG_PM_SLEEP
unregister_pm_notifier(&tp->pm_notifier);
#endif
- if (!test_bit(RTL8152_UNPLUG, &tp->flags))
- napi_disable(&tp->napi);
+ napi_disable(&tp->napi);
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
cancel_delayed_work_sync(&tp->schedule);
@@ -5350,7 +5352,6 @@ static int rtl8152_probe(struct usb_interface *intf,
return 0;
out1:
- netif_napi_del(&tp->napi);
usb_set_intfdata(intf, NULL);
out:
free_netdev(netdev);
@@ -5365,7 +5366,6 @@ static void rtl8152_disconnect(struct usb_interface *intf)
if (tp) {
rtl_set_unplug(tp);
- netif_napi_del(&tp->napi);
unregister_netdev(tp->netdev);
cancel_delayed_work_sync(&tp->hw_phy_work);
tp->rtl_ops.unload(tp);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4f3de0ac8b0b..ba98e0971b84 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1331,7 +1331,7 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
}
}
- if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) {
+ if (rq->vq->num_free > min((unsigned int)budget, virtqueue_get_vring_size(rq->vq)) / 2) {
if (!try_fill_recv(vi, rq, GFP_ATOMIC))
schedule_delayed_work(&vi->refill, 0);
}
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index d74349628db2..0e6a51525d91 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1115,7 +1115,7 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/
sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
- lmc_trace(dev, "lmc_runnin_reset_out");
+ lmc_trace(dev, "lmc_running_reset_out");
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index a9ac3f37b904..e2e679a01b65 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -413,6 +413,7 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
case SDLA_RET_NO_BUFS:
if (cmd == SDLA_INFORMATION_WRITE)
break;
+ /* Else, fall through */
default:
netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index e9fc168bb734..489cba9b284d 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -351,13 +351,15 @@ int i2400m_barker_db_init(const char *_options)
}
result = i2400m_barker_db_add(barker);
if (result < 0)
- goto error_add;
+ goto error_parse_add;
}
kfree(options_orig);
}
return 0;
+error_parse_add:
error_parse:
+ kfree(options_orig);
error_add:
kfree(i2400m_barker_db);
return result;
diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c
index 6642bcb27761..8efb493ceec2 100644
--- a/drivers/net/wimax/i2400m/op-rfkill.c
+++ b/drivers/net/wimax/i2400m/op-rfkill.c
@@ -127,6 +127,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
"%d\n", result);
result = 0;
error_cmd:
+ kfree(cmd);
kfree_skb(ack_skb);
error_msg_to_dev:
error_alloc:
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 1f500cddb3a7..55b713255b8e 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -556,6 +556,30 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
+const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
+ .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
+ .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
+const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
+ .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
+ .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
const struct iwl_cfg iwl22000_2ax_cfg_jf = {
.name = "Intel(R) Dual Band Wireless AX 22000",
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index d55312ef58c9..9b0bb89599fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -776,7 +776,6 @@ struct iwl_rss_config_cmd {
u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */
-#define IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE 128
#define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0
#define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf
@@ -812,10 +811,12 @@ struct iwl_rxq_sync_notification {
*
* @IWL_MVM_RXQ_EMPTY: empty sync notification
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
+ * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
*/
enum iwl_mvm_rxq_notif_type {
IWL_MVM_RXQ_EMPTY,
IWL_MVM_RXQ_NOTIF_DEL_BA,
+ IWL_MVM_RXQ_NSSN_SYNC,
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index e411ac98290d..4d81776f576d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2438,17 +2438,19 @@ static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
{
u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
- const char err_str[] =
- "WRT: ext=%d. Invalid %s name length %d, expected %d\n";
if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
- IWL_WARN(fwrt, err_str, ext, "image", img_name_len,
+ IWL_WARN(fwrt,
+ "WRT: ext=%d. Invalid image name length %d, expected %d\n",
+ ext, img_name_len,
IWL_FW_INI_MAX_IMG_NAME_LEN);
return;
}
if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
- IWL_WARN(fwrt, err_str, ext, "debug cfg", dbg_cfg_name_len,
+ IWL_WARN(fwrt,
+ "WRT: ext=%d. Invalid debug cfg name length %d, expected %d\n",
+ ext, dbg_cfg_name_len,
IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
return;
}
@@ -2775,8 +2777,6 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
struct iwl_ucode_tlv *tlv = iter;
void *ini_tlv = (void *)tlv->data;
u32 type = le32_to_cpu(tlv->type);
- const char invalid_ap_str[] =
- "WRT: ext=%d. Invalid apply point %d for %s\n";
switch (type) {
case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
@@ -2786,8 +2786,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
if (pnt != IWL_FW_INI_APPLY_EARLY) {
- IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
- "buffer allocation");
+ IWL_ERR(fwrt,
+ "WRT: ext=%d. Invalid apply point %d for buffer allocation\n",
+ ext, pnt);
goto next;
}
@@ -2797,8 +2798,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
}
case IWL_UCODE_TLV_TYPE_HCMD:
if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
- IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
- "host command");
+ IWL_ERR(fwrt,
+ "WRT: ext=%d. Invalid apply point %d for host command\n",
+ ext, pnt);
goto next;
}
iwl_fw_dbg_send_hcmd(fwrt, tlv, ext);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 1c1bf1b281cd..6c04f8223aff 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -577,6 +577,8 @@ extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
+extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
+extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650x_2ax_cfg;
extern const struct iwl_cfg killer1650w_2ax_cfg;
extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 57d09049e615..38672dd5aae9 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1640,6 +1640,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
init_completion(&drv->request_firmware_complete);
INIT_LIST_HEAD(&drv->list);
+ iwl_load_fw_dbg_tlv(drv->trans->dev, drv->trans);
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* Create the device debugfs entries. */
drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
@@ -1660,8 +1662,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
err_fw:
#ifdef CONFIG_IWLWIFI_DEBUGFS
debugfs_remove_recursive(drv->dbgfs_drv);
- iwl_fw_dbg_free(drv->trans);
#endif
+ iwl_fw_dbg_free(drv->trans);
kfree(drv);
err:
return ERR_PTR(ret);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 1d608e9e9101..5de54d1559dd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -755,7 +755,7 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
for (i = 0; i < n_profiles; i++) {
/* the tables start at element 3 */
- static int pos = 3;
+ int pos = 3;
/* The EWRD profiles officially go from 2 to 4, but we
* save them in sar_profiles[1-3] (because we don't
@@ -880,6 +880,22 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}
+static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
+{
+ /*
+ * The GEO_TX_POWER_LIMIT command is not supported on earlier
+ * firmware versions. Unfortunately, we don't have a TLV API
+ * flag to rely on, so rely on the major version which is in
+ * the first byte of ucode_ver. This was implemented
+ * initially on version 38 and then backported to 36, 29 and
+ * 17.
+ */
+ return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
+ IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 36 ||
+ IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 ||
+ IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17;
+}
+
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{
struct iwl_geo_tx_power_profiles_resp *resp;
@@ -909,6 +925,9 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
.data = { data },
};
+ if (!iwl_mvm_sar_geo_support(mvm))
+ return -EOPNOTSUPP;
+
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) {
IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
@@ -934,13 +953,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
int ret, i, j;
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
- /*
- * This command is not supported on earlier firmware versions.
- * Unfortunately, we don't have a TLV API flag to rely on, so
- * rely on the major version which is in the first byte of
- * ucode_ver.
- */
- if (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) < 41)
+ if (!iwl_mvm_sar_geo_support(mvm))
return 0;
ret = iwl_mvm_sar_get_wgds_table(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index cb22d447fcb8..fe776e35b9d0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -554,7 +554,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
cpu_to_le32(vif->bss_conf.use_short_slot ?
MAC_FLG_SHORT_SLOT : 0);
- cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+ cmd->filter_flags = 0;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
@@ -623,6 +623,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
/* We need the dtim_period to set the MAC as associated */
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
!force_assoc_off) {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ u8 ap_sta_id = mvmvif->ap_sta_id;
u32 dtim_offs;
/*
@@ -658,6 +660,29 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
dtim_offs);
ctxt_sta->is_assoc = cpu_to_le32(1);
+
+ /*
+ * allow multicast data frames only as long as the station is
+ * authorized, i.e., GTK keys are already installed (if needed)
+ */
+ if (ap_sta_id < IWL_MVM_STATION_COUNT) {
+ struct ieee80211_sta *sta;
+
+ rcu_read_lock();
+
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
+ if (!IS_ERR_OR_NULL(sta)) {
+ struct iwl_mvm_sta *mvmsta =
+ iwl_mvm_sta_from_mac80211(sta);
+
+ if (mvmsta->sta_state ==
+ IEEE80211_STA_AUTHORIZED)
+ cmd.filter_flags |=
+ cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+ }
+
+ rcu_read_unlock();
+ }
} else {
ctxt_sta->is_assoc = cpu_to_le32(0);
@@ -703,7 +728,8 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
MAC_FILTER_IN_CONTROL_AND_MGMT |
MAC_FILTER_IN_BEACON |
MAC_FILTER_IN_PROBE_REQUEST |
- MAC_FILTER_IN_CRC32);
+ MAC_FILTER_IN_CRC32 |
+ MAC_FILTER_ACCEPT_GRP);
ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
/* Allocate sniffer station */
@@ -727,7 +753,8 @@ static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
- MAC_FILTER_IN_PROBE_REQUEST);
+ MAC_FILTER_IN_PROBE_REQUEST |
+ MAC_FILTER_ACCEPT_GRP);
/* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 55cd49ccbf0b..a7bc00d1296f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -207,11 +207,11 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
},
};
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key);
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
@@ -474,7 +474,19 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
ieee80211_hw_set(hw, STA_MMPDU_TXQ);
- ieee80211_hw_set(hw, TX_AMSDU);
+ /*
+ * On older devices, enabling TX A-MSDU occasionally leads to
+ * something getting messed up, the command read from the FIFO
+ * gets out of sync and isn't a TX command, so that we have an
+ * assert EDC.
+ *
+ * It's not clear where the bug is, but since we didn't used to
+ * support A-MSDU until moving the mac80211 iTXQs, just leave it
+ * for older devices. We also don't see this issue on any newer
+ * devices.
+ */
+ if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+ ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
if (iwl_mvm_has_tlc_offload(mvm)) {
@@ -2726,7 +2738,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
mvmvif->ap_early_keys[i] = NULL;
- ret = iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
+ ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
if (ret)
goto out_quota_failed;
}
@@ -3315,10 +3327,20 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
/* enable beacon filtering */
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+ /*
+ * Now that the station is authorized, i.e., keys were already
+ * installed, need to indicate to the FW that
+ * multicast data frames can be forwarded to the driver
+ */
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
true);
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
+ /* Multicast data frames are no longer allowed */
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
/* disable beacon filtering */
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
WARN_ON(ret &&
@@ -3494,11 +3516,11 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
return ret;
}
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -3553,8 +3575,6 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}
- mutex_lock(&mvm->mutex);
-
switch (cmd) {
case SET_KEY:
if ((vif->type == NL80211_IFTYPE_ADHOC ||
@@ -3700,7 +3720,22 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
ret = -EINVAL;
}
+ return ret;
+}
+
+static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+ ret = __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
mutex_unlock(&mvm->mutex);
+
return ret;
}
@@ -5041,7 +5076,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
int ret;
- lockdep_assert_held(&mvm->mutex);
if (!iwl_mvm_has_new_rx_api(mvm))
return;
@@ -5052,13 +5086,15 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
atomic_set(&mvm->queue_sync_counter,
mvm->trans->num_rx_queues);
- ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
+ ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
+ size, !notif->sync);
if (ret) {
IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
goto out;
}
if (notif->sync) {
+ lockdep_assert_held(&mvm->mutex);
ret = wait_event_timeout(mvm->rx_sync_waitq,
atomic_read(&mvm->queue_sync_counter) == 0 ||
iwl_mvm_is_radio_killed(mvm),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 48c77af54e99..a263cc629d75 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1664,9 +1664,9 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
- const u8 *data, u32 count);
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
- int queue);
+ const u8 *data, u32 count, bool async);
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
@@ -1813,7 +1813,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
#endif /* CONFIG_IWLWIFI_DEBUGFS */
/* rate scaling */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync);
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg);
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
void rs_update_last_rssi(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index 719f793b3487..a9bb43a2f27b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -620,7 +620,7 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
enum iwl_mcc_source src;
char mcc[3];
struct ieee80211_regdomain *regd;
- u32 wgds_tbl_idx;
+ int wgds_tbl_idx;
lockdep_assert_held(&mvm->mutex);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index d7d6f3398f86..4888054dc3d8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1088,7 +1088,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
RX_QUEUES_NOTIFICATION)))
- iwl_mvm_rx_queue_notif(mvm, rxb, 0);
+ iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
@@ -1812,7 +1812,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
RX_QUEUES_NOTIFICATION)))
- iwl_mvm_rx_queue_notif(mvm, rxb, queue);
+ iwl_mvm_rx_queue_notif(mvm, napi, rxb, queue);
else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 8c9069f28a58..d3f04acfbacb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -1197,239 +1197,6 @@ static u8 rs_get_tid(struct ieee80211_hdr *hdr)
return tid;
}
-void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- int tid, struct ieee80211_tx_info *info, bool ndp)
-{
- int legacy_success;
- int retries;
- int i;
- struct iwl_lq_cmd *table;
- u32 lq_hwrate;
- struct rs_rate lq_rate, tx_resp_rate;
- struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
- u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
- u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
- u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
- u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
-
- /* Treat uninitialized rate scaling data same as non-existing. */
- if (!lq_sta) {
- IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
- return;
- } else if (!lq_sta->pers.drv) {
- IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
- return;
- }
-
- /* This packet was aggregated but doesn't carry status info */
- if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
- !(info->flags & IEEE80211_TX_STAT_AMPDU))
- return;
-
- if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
- &tx_resp_rate)) {
- WARN_ON_ONCE(1);
- return;
- }
-
-#ifdef CONFIG_MAC80211_DEBUGFS
- /* Disable last tx check if we are debugging with fixed rate but
- * update tx stats */
- if (lq_sta->pers.dbg_fixed_rate) {
- int index = tx_resp_rate.index;
- enum rs_column column;
- int attempts, success;
-
- column = rs_get_column_from_rate(&tx_resp_rate);
- if (WARN_ONCE(column == RS_COLUMN_INVALID,
- "Can't map rate 0x%x to column",
- tx_resp_hwrate))
- return;
-
- if (info->flags & IEEE80211_TX_STAT_AMPDU) {
- attempts = info->status.ampdu_len;
- success = info->status.ampdu_ack_len;
- } else {
- attempts = info->status.rates[0].count;
- success = !!(info->flags & IEEE80211_TX_STAT_ACK);
- }
-
- lq_sta->pers.tx_stats[column][index].total += attempts;
- lq_sta->pers.tx_stats[column][index].success += success;
-
- IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
- tx_resp_hwrate, success, attempts);
- return;
- }
-#endif
-
- if (time_after(jiffies,
- (unsigned long)(lq_sta->last_tx +
- (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
- IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
- iwl_mvm_rs_rate_init(mvm, sta, info->band, true);
- return;
- }
- lq_sta->last_tx = jiffies;
-
- /* Ignore this Tx frame response if its initial rate doesn't match
- * that of latest Link Quality command. There may be stragglers
- * from a previous Link Quality command, but we're no longer interested
- * in those; they're either from the "active" mode while we're trying
- * to check "search" mode, or a prior "search" mode after we've moved
- * to a new "search" mode (which might become the new "active" mode).
- */
- table = &lq_sta->lq;
- lq_hwrate = le32_to_cpu(table->rs_table[0]);
- if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
- WARN_ON_ONCE(1);
- return;
- }
-
- /* Here we actually compare this rate to the latest LQ command */
- if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
- IWL_DEBUG_RATE(mvm,
- "tx resp color 0x%x does not match 0x%x\n",
- lq_color, LQ_FLAG_COLOR_GET(table->flags));
-
- /*
- * Since rates mis-match, the last LQ command may have failed.
- * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
- * ... driver.
- */
- lq_sta->missed_rate_counter++;
- if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
- lq_sta->missed_rate_counter = 0;
- IWL_DEBUG_RATE(mvm,
- "Too many rates mismatch. Send sync LQ. rs_state %d\n",
- lq_sta->rs_state);
- iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
- }
- /* Regardless, ignore this status info for outdated rate */
- return;
- } else
- /* Rate did match, so reset the missed_rate_counter */
- lq_sta->missed_rate_counter = 0;
-
- if (!lq_sta->search_better_tbl) {
- curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
- other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
- } else {
- curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
- other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
- }
-
- if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
- IWL_DEBUG_RATE(mvm,
- "Neither active nor search matches tx rate\n");
- tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
- rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
- tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
- rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
- rs_dump_rate(mvm, &lq_rate, "ACTUAL");
-
- /*
- * no matching table found, let's by-pass the data collection
- * and continue to perform rate scale to find the rate table
- */
- rs_stay_in_table(lq_sta, true);
- goto done;
- }
-
- /*
- * Updating the frame history depends on whether packets were
- * aggregated.
- *
- * For aggregation, all packets were transmitted at the same rate, the
- * first index into rate scale table.
- */
- if (info->flags & IEEE80211_TX_STAT_AMPDU) {
- rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
- info->status.ampdu_len,
- info->status.ampdu_ack_len,
- reduced_txp);
-
- /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
- * it as a single frame loss as we don't want the success ratio
- * to dip too quickly because a BA wasn't received.
- * For TPC, there's no need for this optimisation since we want
- * to recover very quickly from a bad power reduction and,
- * therefore we'd like the success ratio to get an immediate hit
- * when failing to get a BA, so we'd switch back to a lower or
- * zero power reduction. When FW transmits agg with a rate
- * different from the initial rate, it will not use reduced txp
- * and will send BA notification twice (one empty with reduced
- * txp equal to the value from LQ and one with reduced txp 0).
- * We need to update counters for each txp level accordingly.
- */
- if (info->status.ampdu_ack_len == 0)
- info->status.ampdu_len = 1;
-
- rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl, tx_resp_rate.index,
- info->status.ampdu_len,
- info->status.ampdu_ack_len);
-
- /* Update success/fail counts if not searching for new mode */
- if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
- lq_sta->total_success += info->status.ampdu_ack_len;
- lq_sta->total_failed += (info->status.ampdu_len -
- info->status.ampdu_ack_len);
- }
- } else {
- /* For legacy, update frame history with for each Tx retry. */
- retries = info->status.rates[0].count - 1;
- /* HW doesn't send more than 15 retries */
- retries = min(retries, 15);
-
- /* The last transmission may have been successful */
- legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
- /* Collect data for each rate used during failed TX attempts */
- for (i = 0; i <= retries; ++i) {
- lq_hwrate = le32_to_cpu(table->rs_table[i]);
- if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
- &lq_rate)) {
- WARN_ON_ONCE(1);
- return;
- }
-
- /*
- * Only collect stats if retried rate is in the same RS
- * table as active/search.
- */
- if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
- tmp_tbl = curr_tbl;
- else if (rs_rate_column_match(&lq_rate,
- &other_tbl->rate))
- tmp_tbl = other_tbl;
- else
- continue;
-
- rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
- tx_resp_rate.index, 1,
- i < retries ? 0 : legacy_success,
- reduced_txp);
- rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
- tx_resp_rate.index, 1,
- i < retries ? 0 : legacy_success);
- }
-
- /* Update success/fail counts if not searching for new mode */
- if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
- lq_sta->total_success += legacy_success;
- lq_sta->total_failed += retries + (1 - legacy_success);
- }
- }
- /* The last TX rate is cached in lq_sta; it's set in if/else above */
- lq_sta->last_rate_n_flags = lq_hwrate;
- IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
-done:
- /* See if there's a better rate or modulation mode to try. */
- if (sta->supp_rates[info->band])
- rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
-}
-
/*
* mac80211 sends us Tx status
*/
@@ -1442,8 +1209,9 @@ static void rs_drv_mac80211_tx_status(void *mvm_r,
struct iwl_op_mode *op_mode = mvm_r;
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (!iwl_mvm_sta_from_mac80211(sta)->vif)
+ if (!mvmsta->vif)
return;
if (!ieee80211_is_data(hdr->frame_control) ||
@@ -1584,6 +1352,18 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
}
+/* rs uses two tables, one is active and the second is for searching better
+ * configuration. This function, according to the index of the currently
+ * active table returns the search table, which is located at the
+ * index complementary to 1 according to the active table (active = 1,
+ * search = 0 or active = 0, search = 1).
+ * Since lq_info is an arary of size 2, make sure index cannot be out of bounds.
+ */
+static inline u8 rs_search_tbl(u8 active_tbl)
+{
+ return (active_tbl ^ 1) & 1;
+}
+
static s32 rs_get_best_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, /* "search" */
@@ -1794,7 +1574,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl)
{
rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
- iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
+ iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
}
static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
@@ -1931,9 +1711,9 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum rs_column col_id)
{
- struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
struct iwl_scale_tbl_info *search_tbl =
- &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
struct rs_rate *rate = &search_tbl->rate;
const struct rs_tx_column *column = &rs_tx_columns[col_id];
const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
@@ -2341,7 +2121,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
else
- active_tbl = 1 - lq_sta->active_tbl;
+ active_tbl = rs_search_tbl(lq_sta->active_tbl);
tbl = &(lq_sta->lq_info[active_tbl]);
rate = &tbl->rate;
@@ -2565,7 +2345,7 @@ lq_update:
/* If new "search" mode was selected, set up in uCode table */
if (lq_sta->search_better_tbl) {
/* Access the "search" table, clear its history. */
- tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
rs_rate_scale_clear_tbl_windows(mvm, tbl);
/* Use new "search" start rate */
@@ -2896,7 +2676,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
static void rs_initialize_lq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
- enum nl80211_band band, bool update)
+ enum nl80211_band band)
{
struct iwl_scale_tbl_info *tbl;
struct rs_rate *rate;
@@ -2908,7 +2688,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
else
- active_tbl = 1 - lq_sta->active_tbl;
+ active_tbl = rs_search_tbl(lq_sta->active_tbl);
tbl = &(lq_sta->lq_info[active_tbl]);
rate = &tbl->rate;
@@ -2926,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
rs_set_expected_tpt_table(lq_sta, tbl);
rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
/* TODO restore station should remember the lq cmd */
- iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, !update);
+ iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
}
static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
@@ -3175,7 +2955,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
* Called after adding a new station to initialize rate scaling
*/
static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- enum nl80211_band band, bool update)
+ enum nl80211_band band)
{
int i, j;
struct ieee80211_hw *hw = mvm->hw;
@@ -3186,6 +2966,8 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct ieee80211_supported_band *sband;
unsigned long supp; /* must be unsigned long for for_each_set_bit */
+ lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);
+
/* clear all non-persistent lq data */
memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
@@ -3255,7 +3037,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- rs_initialize_lq(mvm, sta, lq_sta, band, update);
+ rs_initialize_lq(mvm, sta, lq_sta, band);
}
static void rs_drv_rate_update(void *mvm_r,
@@ -3278,6 +3060,258 @@ static void rs_drv_rate_update(void *mvm_r,
iwl_mvm_rs_rate_init(mvm, sta, sband->band, true);
}
+static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ int tid, struct ieee80211_tx_info *info,
+ bool ndp)
+{
+ int legacy_success;
+ int retries;
+ int i;
+ struct iwl_lq_cmd *table;
+ u32 lq_hwrate;
+ struct rs_rate lq_rate, tx_resp_rate;
+ struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+ u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
+ u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
+ u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
+ u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+
+ /* Treat uninitialized rate scaling data same as non-existing. */
+ if (!lq_sta) {
+ IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
+ return;
+ } else if (!lq_sta->pers.drv) {
+ IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
+ return;
+ }
+
+ /* This packet was aggregated but doesn't carry status info */
+ if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+ !(info->flags & IEEE80211_TX_STAT_AMPDU))
+ return;
+
+ if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
+ &tx_resp_rate)) {
+ WARN_ON_ONCE(1);
+ return;
+ }
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ /* Disable last tx check if we are debugging with fixed rate but
+ * update tx stats
+ */
+ if (lq_sta->pers.dbg_fixed_rate) {
+ int index = tx_resp_rate.index;
+ enum rs_column column;
+ int attempts, success;
+
+ column = rs_get_column_from_rate(&tx_resp_rate);
+ if (WARN_ONCE(column == RS_COLUMN_INVALID,
+ "Can't map rate 0x%x to column",
+ tx_resp_hwrate))
+ return;
+
+ if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+ attempts = info->status.ampdu_len;
+ success = info->status.ampdu_ack_len;
+ } else {
+ attempts = info->status.rates[0].count;
+ success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ }
+
+ lq_sta->pers.tx_stats[column][index].total += attempts;
+ lq_sta->pers.tx_stats[column][index].success += success;
+
+ IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
+ tx_resp_hwrate, success, attempts);
+ return;
+ }
+#endif
+
+ if (time_after(jiffies,
+ (unsigned long)(lq_sta->last_tx +
+ (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
+ IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
+ /* reach here only in case of driver RS, call directly
+ * the unlocked version
+ */
+ rs_drv_rate_init(mvm, sta, info->band);
+ return;
+ }
+ lq_sta->last_tx = jiffies;
+
+ /* Ignore this Tx frame response if its initial rate doesn't match
+ * that of latest Link Quality command. There may be stragglers
+ * from a previous Link Quality command, but we're no longer interested
+ * in those; they're either from the "active" mode while we're trying
+ * to check "search" mode, or a prior "search" mode after we've moved
+ * to a new "search" mode (which might become the new "active" mode).
+ */
+ table = &lq_sta->lq;
+ lq_hwrate = le32_to_cpu(table->rs_table[0]);
+ if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
+ WARN_ON_ONCE(1);
+ return;
+ }
+
+ /* Here we actually compare this rate to the latest LQ command */
+ if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
+ IWL_DEBUG_RATE(mvm,
+ "tx resp color 0x%x does not match 0x%x\n",
+ lq_color, LQ_FLAG_COLOR_GET(table->flags));
+
+ /* Since rates mis-match, the last LQ command may have failed.
+ * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
+ * ... driver.
+ */
+ lq_sta->missed_rate_counter++;
+ if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
+ lq_sta->missed_rate_counter = 0;
+ IWL_DEBUG_RATE(mvm,
+ "Too many rates mismatch. Send sync LQ. rs_state %d\n",
+ lq_sta->rs_state);
+ iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
+ }
+ /* Regardless, ignore this status info for outdated rate */
+ return;
+ }
+
+ /* Rate did match, so reset the missed_rate_counter */
+ lq_sta->missed_rate_counter = 0;
+
+ if (!lq_sta->search_better_tbl) {
+ curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+ other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+ } else {
+ curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+ other_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+ }
+
+ if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
+ IWL_DEBUG_RATE(mvm,
+ "Neither active nor search matches tx rate\n");
+ tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+ rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
+ tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+ rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
+ rs_dump_rate(mvm, &lq_rate, "ACTUAL");
+
+ /* no matching table found, let's by-pass the data collection
+ * and continue to perform rate scale to find the rate table
+ */
+ rs_stay_in_table(lq_sta, true);
+ goto done;
+ }
+
+ /* Updating the frame history depends on whether packets were
+ * aggregated.
+ *
+ * For aggregation, all packets were transmitted at the same rate, the
+ * first index into rate scale table.
+ */
+ if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+ rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
+ info->status.ampdu_len,
+ info->status.ampdu_ack_len,
+ reduced_txp);
+
+ /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
+ * it as a single frame loss as we don't want the success ratio
+ * to dip too quickly because a BA wasn't received.
+ * For TPC, there's no need for this optimisation since we want
+ * to recover very quickly from a bad power reduction and,
+ * therefore we'd like the success ratio to get an immediate hit
+ * when failing to get a BA, so we'd switch back to a lower or
+ * zero power reduction. When FW transmits agg with a rate
+ * different from the initial rate, it will not use reduced txp
+ * and will send BA notification twice (one empty with reduced
+ * txp equal to the value from LQ and one with reduced txp 0).
+ * We need to update counters for each txp level accordingly.
+ */
+ if (info->status.ampdu_ack_len == 0)
+ info->status.ampdu_len = 1;
+
+ rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl,
+ tx_resp_rate.index,
+ info->status.ampdu_len,
+ info->status.ampdu_ack_len);
+
+ /* Update success/fail counts if not searching for new mode */
+ if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+ lq_sta->total_success += info->status.ampdu_ack_len;
+ lq_sta->total_failed += (info->status.ampdu_len -
+ info->status.ampdu_ack_len);
+ }
+ } else {
+ /* For legacy, update frame history with for each Tx retry. */
+ retries = info->status.rates[0].count - 1;
+ /* HW doesn't send more than 15 retries */
+ retries = min(retries, 15);
+
+ /* The last transmission may have been successful */
+ legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ /* Collect data for each rate used during failed TX attempts */
+ for (i = 0; i <= retries; ++i) {
+ lq_hwrate = le32_to_cpu(table->rs_table[i]);
+ if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
+ &lq_rate)) {
+ WARN_ON_ONCE(1);
+ return;
+ }
+
+ /* Only collect stats if retried rate is in the same RS
+ * table as active/search.
+ */
+ if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
+ tmp_tbl = curr_tbl;
+ else if (rs_rate_column_match(&lq_rate,
+ &other_tbl->rate))
+ tmp_tbl = other_tbl;
+ else
+ continue;
+
+ rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
+ tx_resp_rate.index, 1,
+ i < retries ? 0 : legacy_success,
+ reduced_txp);
+ rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
+ tx_resp_rate.index, 1,
+ i < retries ? 0 : legacy_success);
+ }
+
+ /* Update success/fail counts if not searching for new mode */
+ if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+ lq_sta->total_success += legacy_success;
+ lq_sta->total_failed += retries + (1 - legacy_success);
+ }
+ }
+ /* The last TX rate is cached in lq_sta; it's set in if/else above */
+ lq_sta->last_rate_n_flags = lq_hwrate;
+ IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
+done:
+ /* See if there's a better rate or modulation mode to try. */
+ if (sta->supp_rates[info->band])
+ rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
+}
+
+void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int tid, struct ieee80211_tx_info *info, bool ndp)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ /* If it's locked we are in middle of init flow
+ * just wait for next tx status to update the lq_sta data
+ */
+ if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock))
+ return;
+
+ __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);
+ spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+}
+
#ifdef CONFIG_MAC80211_DEBUGFS
static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
struct iwl_lq_cmd *lq_cmd,
@@ -3569,7 +3603,7 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;
bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params);
- iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false);
+ iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd);
ss_params |= LQ_SS_BFER_ALLOWED;
IWL_DEBUG_RATE(mvm,
@@ -3735,7 +3769,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
if (lq_sta->pers.dbg_fixed_rate) {
rs_fill_lq_cmd(mvm, NULL, lq_sta, NULL);
- iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
+ iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq);
}
}
@@ -4132,10 +4166,15 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool update)
{
- if (iwl_mvm_has_tlc_offload(mvm))
+ if (iwl_mvm_has_tlc_offload(mvm)) {
rs_fw_rate_init(mvm, sta, band, update);
- else
- rs_drv_rate_init(mvm, sta, band, update);
+ } else {
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock);
+ rs_drv_rate_init(mvm, sta, band);
+ spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+ }
}
int iwl_mvm_rate_control_register(void)
@@ -4165,7 +4204,7 @@ static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
lq->flags &= ~LQ_FLAG_USE_RTS_MSK;
}
- return iwl_mvm_send_lq_cmd(mvm, lq, false);
+ return iwl_mvm_send_lq_cmd(mvm, lq);
}
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index f7eb60dbaf20..428642e66658 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -4,7 +4,7 @@
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
@@ -390,6 +390,7 @@ struct iwl_lq_sta {
s8 last_rssi;
struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
struct iwl_mvm *drv;
+ spinlock_t lock; /* for races in reinit/update table */
} pers;
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 64f950501287..854edd7d7103 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -463,20 +463,22 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
}
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
- const u8 *data, u32 count)
+ const u8 *data, u32 count, bool async)
{
- struct iwl_rxq_sync_cmd *cmd;
+ u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
+ sizeof(struct iwl_mvm_rss_sync_notif)];
+ struct iwl_rxq_sync_cmd *cmd = (void *)buf;
u32 data_size = sizeof(*cmd) + count;
int ret;
- /* should be DWORD aligned */
- if (WARN_ON(count & 3 || count > IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE))
+ /*
+ * size must be a multiple of DWORD
+ * Ensure we don't overflow buf
+ */
+ if (WARN_ON(count & 3 ||
+ count > sizeof(struct iwl_mvm_rss_sync_notif)))
return -EINVAL;
- cmd = kzalloc(data_size, GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
cmd->rxq_mask = cpu_to_le32(rxq_mask);
cmd->count = cpu_to_le32(count);
cmd->flags = 0;
@@ -485,9 +487,8 @@ int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
ret = iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(DATA_PATH_GROUP,
TRIGGER_RX_QUEUES_NOTIF_CMD),
- 0, data_size, cmd);
+ async ? CMD_ASYNC : 0, data_size, cmd);
- kfree(cmd);
return ret;
}
@@ -503,14 +504,31 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
!ieee80211_sn_less(sn1, sn2 - buffer_size);
}
+static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
+{
+ struct iwl_mvm_rss_sync_notif notif = {
+ .metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
+ .metadata.sync = 0,
+ .nssn_sync.baid = baid,
+ .nssn_sync.nssn = nssn,
+ };
+
+ iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+}
+
#define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
+enum iwl_mvm_release_flags {
+ IWL_MVM_RELEASE_SEND_RSS_SYNC = BIT(0),
+ IWL_MVM_RELEASE_FROM_RSS_SYNC = BIT(1),
+};
+
static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct napi_struct *napi,
struct iwl_mvm_baid_data *baid_data,
struct iwl_mvm_reorder_buffer *reorder_buf,
- u16 nssn)
+ u16 nssn, u32 flags)
{
struct iwl_mvm_reorder_buf_entry *entries =
&baid_data->entries[reorder_buf->queue *
@@ -519,6 +537,18 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
lockdep_assert_held(&reorder_buf->lock);
+ /*
+ * We keep the NSSN not too far behind, if we are sync'ing it and it
+ * is more than 2048 ahead of us, it must be behind us. Discard it.
+ * This can happen if the queue that hit the 0 / 2048 seqno was lagging
+ * behind and this queue already processed packets. The next if
+ * would have caught cases where this queue would have processed less
+ * than 64 packets, but it may have processed more than 64 packets.
+ */
+ if ((flags & IWL_MVM_RELEASE_FROM_RSS_SYNC) &&
+ ieee80211_sn_less(nssn, ssn))
+ goto set_timer;
+
/* ignore nssn smaller than head sn - this can happen due to timeout */
if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
goto set_timer;
@@ -529,6 +559,9 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
struct sk_buff *skb;
ssn = ieee80211_sn_inc(ssn);
+ if ((flags & IWL_MVM_RELEASE_SEND_RSS_SYNC) &&
+ (ssn == 2048 || ssn == 0))
+ iwl_mvm_sync_nssn(mvm, baid_data->baid, ssn);
/*
* Empty the list. Will have more than one frame for A-MSDU.
@@ -615,7 +648,8 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
sta_id, sn);
iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
sta, baid_data->tid);
- iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data, buf, sn);
+ iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data,
+ buf, sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
rcu_read_unlock();
} else {
/*
@@ -657,7 +691,8 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
spin_lock_bh(&reorder_buf->lock);
iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
ieee80211_sn_add(reorder_buf->head_sn,
- reorder_buf->buf_size));
+ reorder_buf->buf_size),
+ 0);
spin_unlock_bh(&reorder_buf->lock);
del_timer_sync(&reorder_buf->reorder_timer);
@@ -665,8 +700,54 @@ out:
rcu_read_unlock();
}
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
- int queue)
+static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
+ struct napi_struct *napi,
+ u8 baid, u16 nssn, int queue,
+ u32 flags)
+{
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_reorder_buffer *reorder_buf;
+ struct iwl_mvm_baid_data *ba_data;
+
+ IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
+ baid, nssn);
+
+ if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
+ baid >= ARRAY_SIZE(mvm->baid_map)))
+ return;
+
+ rcu_read_lock();
+
+ ba_data = rcu_dereference(mvm->baid_map[baid]);
+ if (WARN_ON_ONCE(!ba_data))
+ goto out;
+
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
+ goto out;
+
+ reorder_buf = &ba_data->reorder_buf[queue];
+
+ spin_lock_bh(&reorder_buf->lock);
+ iwl_mvm_release_frames(mvm, sta, napi, ba_data,
+ reorder_buf, nssn, flags);
+ spin_unlock_bh(&reorder_buf->lock);
+
+out:
+ rcu_read_unlock();
+}
+
+static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm,
+ struct napi_struct *napi, int queue,
+ const struct iwl_mvm_nssn_sync_data *data)
+{
+ iwl_mvm_release_frames_from_notif(mvm, napi, data->baid,
+ data->nssn, queue,
+ IWL_MVM_RELEASE_FROM_RSS_SYNC);
+}
+
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rxq_sync_notification *notif;
@@ -687,6 +768,10 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
case IWL_MVM_RXQ_NOTIF_DEL_BA:
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
break;
+ case IWL_MVM_RXQ_NSSN_SYNC:
+ iwl_mvm_nssn_sync(mvm, napi, queue,
+ (void *)internal_notif->data);
+ break;
default:
WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
}
@@ -785,7 +870,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
}
if (ieee80211_is_back_req(hdr->frame_control)) {
- iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+ iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+ buffer, nssn, 0);
goto drop;
}
@@ -794,7 +880,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* If the SN is smaller than the NSSN it might need to first go into
* the reorder buffer, in which case we just release up to it and the
* rest of the function will take care of storing it and releasing up to
- * the nssn
+ * the nssn.
+ * This should not happen. This queue has been lagging and it should
+ * have been updated by a IWL_MVM_RXQ_NSSN_SYNC notification. Be nice
+ * and update the other queues.
*/
if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
buffer->buf_size) ||
@@ -802,7 +891,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer,
- min_sn);
+ min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
}
/* drop any oudated packets */
@@ -813,8 +902,23 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
buffer->buf_size) &&
- (!amsdu || last_subframe))
+ (!amsdu || last_subframe)) {
+ /*
+ * If we crossed the 2048 or 0 SN, notify all the
+ * queues. This is done in order to avoid having a
+ * head_sn that lags behind for too long. When that
+ * happens, we can get to a situation where the head_sn
+ * is within the interval [nssn - buf_size : nssn]
+ * which will make us think that the nssn is a packet
+ * that we already freed because of the reordering
+ * buffer and we will ignore it. So maintain the
+ * head_sn somewhat updated across all the queues:
+ * when it crosses 0 and 2048.
+ */
+ if (sn == 2048 || sn == 0)
+ iwl_mvm_sync_nssn(mvm, baid, sn);
buffer->head_sn = nssn;
+ }
/* No need to update AMSDU last SN - we are moving the head */
spin_unlock_bh(&buffer->lock);
return false;
@@ -829,8 +933,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* while technically there is no hole and we can move forward.
*/
if (!buffer->num_stored && sn == buffer->head_sn) {
- if (!amsdu || last_subframe)
+ if (!amsdu || last_subframe) {
+ if (sn == 2048 || sn == 0)
+ iwl_mvm_sync_nssn(mvm, baid, sn);
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
+ }
/* No need to update AMSDU last SN - we are moving the head */
spin_unlock_bh(&buffer->lock);
return false;
@@ -875,7 +982,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* release notification with up to date NSSN.
*/
if (!amsdu || last_subframe)
- iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+ iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+ buffer, nssn,
+ IWL_MVM_RELEASE_SEND_RSS_SYNC);
spin_unlock_bh(&buffer->lock);
return true;
@@ -1840,40 +1949,14 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
out:
rcu_read_unlock();
}
+
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_frame_release *release = (void *)pkt->data;
- struct ieee80211_sta *sta;
- struct iwl_mvm_reorder_buffer *reorder_buf;
- struct iwl_mvm_baid_data *ba_data;
-
- int baid = release->baid;
-
- IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
- release->baid, le16_to_cpu(release->nssn));
- if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID))
- return;
-
- rcu_read_lock();
-
- ba_data = rcu_dereference(mvm->baid_map[baid]);
- if (WARN_ON_ONCE(!ba_data))
- goto out;
-
- sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
- if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
- goto out;
-
- reorder_buf = &ba_data->reorder_buf[queue];
-
- spin_lock_bh(&reorder_buf->lock);
- iwl_mvm_release_frames(mvm, sta, napi, ba_data, reorder_buf,
- le16_to_cpu(release->nssn));
- spin_unlock_bh(&reorder_buf->lock);
-
-out:
- rcu_read_unlock();
+ iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
+ le16_to_cpu(release->nssn),
+ queue, 0);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index f545a737a92d..10f18536dd0d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1684,6 +1684,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
*/
if (iwl_mvm_has_tlc_offload(mvm))
iwl_mvm_rs_add_sta(mvm, mvm_sta);
+ else
+ spin_lock_init(&mvm_sta->lq_sta.rs_drv.pers.lock);
iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
@@ -2421,7 +2423,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
{
- struct iwl_mvm_delba_notif notif = {
+ struct iwl_mvm_rss_sync_notif notif = {
.metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
.metadata.sync = 1,
.delba.baid = baid,
@@ -2972,7 +2974,7 @@ out:
IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
sta->addr, tid);
- return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq, false);
+ return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq);
}
static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 4487cc3e07c1..8d70093847cb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -343,9 +343,17 @@ struct iwl_mvm_delba_data {
u32 baid;
} __packed;
-struct iwl_mvm_delba_notif {
+struct iwl_mvm_nssn_sync_data {
+ u32 baid;
+ u32 nssn;
+} __packed;
+
+struct iwl_mvm_rss_sync_notif {
struct iwl_mvm_internal_rxq_notif metadata;
- struct iwl_mvm_delba_data delba;
+ union {
+ struct iwl_mvm_delba_data delba;
+ struct iwl_mvm_nssn_sync_data nssn_sync;
+ };
} __packed;
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index a3e5d88f1c07..6ac114a393cc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -831,6 +831,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
unsigned int tcp_payload_len;
unsigned int mss = skb_shinfo(skb)->gso_size;
bool ipv4 = (skb->protocol == htons(ETH_P_IP));
+ bool qos = ieee80211_is_data_qos(hdr->frame_control);
u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
skb_shinfo(skb)->gso_size = num_subframes * mss;
@@ -864,7 +865,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
if (tcp_payload_len > mss) {
skb_shinfo(tmp)->gso_size = mss;
} else {
- if (ieee80211_is_data_qos(hdr->frame_control)) {
+ if (qos) {
u8 *qc;
if (ipv4)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 9ecd5f09615a..b8e20a01c192 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -653,12 +653,12 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
* this case to clear the state indicating that station creation is in
* progress.
*/
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync)
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
{
struct iwl_host_cmd cmd = {
.id = LQ_CMD,
.len = { sizeof(struct iwl_lq_cmd), },
- .flags = sync ? 0 : CMD_ASYNC,
+ .flags = CMD_ASYNC,
.data = { lq, },
};
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index ea2a03d4bf55..3b12e7ad35e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -604,10 +604,13 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x6014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0xE010, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0xE014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},
@@ -1059,7 +1062,28 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
+ else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
+ iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
+ else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
+ iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
}
+
+ /* same thing for QuZ... */
+ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
+ if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
+ iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
+ else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
+ iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
+ else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
+ else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
+ else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
+ else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+ }
+
#endif
pci_set_drvdata(pdev, iwl_trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index f5df5b370d78..db62c8314603 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -3602,11 +3602,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
- ((trans->cfg != &iwl_ax200_cfg_cc &&
- trans->cfg != &killer1650x_2ax_cfg &&
- trans->cfg != &killer1650w_2ax_cfg &&
- trans->cfg != &iwl_ax201_cfg_quz_hr) ||
- trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
+ trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
u32 hw_status;
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 38d110338987..9ef6b8fe03c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -99,10 +99,7 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
u16 len = byte_cnt;
__le16 bc_ent;
- if (trans_pcie->bc_table_dword)
- len = DIV_ROUND_UP(len, 4);
-
- if (WARN_ON(len > 0xFFF || idx >= txq->n_window))
+ if (WARN(idx >= txq->n_window, "%d >= %d\n", idx, txq->n_window))
return;
filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
@@ -117,11 +114,20 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
*/
num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
- bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+ /* Starting from 22560, the HW expects bytes */
+ WARN_ON(trans_pcie->bc_table_dword);
+ WARN_ON(len > 0x3FFF);
+ bc_ent = cpu_to_le16(len | (num_fetch_chunks << 14));
scd_bc_tbl_gen3->tfd_offset[idx] = bc_ent;
- else
+ } else {
+ /* Until 22560, the HW expects DW */
+ WARN_ON(!trans_pcie->bc_table_dword);
+ len = DIV_ROUND_UP(len, 4);
+ WARN_ON(len > 0xFFF);
+ bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
scd_bc_tbl->tfd_offset[idx] = bc_ent;
+ }
}
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index fa4245d0d4a8..2f0ba7ef53b8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -435,6 +435,8 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
DMA_TO_DEVICE);
}
+ meta->tbs = 0;
+
if (trans->cfg->use_tfh) {
struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 519b4ee88c5c..772e54f0696f 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3617,10 +3617,12 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, &hwsim_genl_family,
NLM_F_MULTI, HWSIM_CMD_GET_RADIO);
- if (!hdr)
+ if (hdr) {
+ genl_dump_check_consistent(cb, hdr);
+ genlmsg_end(skb, hdr);
+ } else {
res = -EMSGSIZE;
- genl_dump_check_consistent(cb, hdr);
- genlmsg_end(skb, hdr);
+ }
}
done:
diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c
index 653d347a9a19..580387f9f12a 100644
--- a/drivers/net/wireless/marvell/mwifiex/ie.c
+++ b/drivers/net/wireless/marvell/mwifiex/ie.c
@@ -241,6 +241,9 @@ static int mwifiex_update_vs_ie(const u8 *ies, int ies_len,
}
vs_ie = (struct ieee_types_header *)vendor_ie;
+ if (le16_to_cpu(ie->ie_length) + vs_ie->len + 2 >
+ IEEE_MAX_IE_SIZE)
+ return -EINVAL;
memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length),
vs_ie, vs_ie->len + 2);
le16_unaligned_add_cpu(&ie->ie_length, vs_ie->len + 2);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 3e442c7f7882..095837fba300 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -124,6 +124,7 @@ enum {
#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
+#define WPA_GTK_OUI_OFFSET 2
#define RSN_GTK_OUI_OFFSET 2
#define MWIFIEX_OUI_NOT_PRESENT 0
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 0d6d41727037..21dda385f6c6 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -181,7 +181,8 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
u8 ret = MWIFIEX_OUI_NOT_PRESENT;
if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
- iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
+ iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
+ WPA_GTK_OUI_OFFSET);
oui = &mwifiex_wpa_oui[cipher][0];
ret = mwifiex_search_oui_in_ie(iebody, oui);
if (ret)
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index 18f7d9bf30b2..0939a8c8f3ab 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -265,6 +265,8 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
if (rate_ie) {
+ if (rate_ie->len > MWIFIEX_SUPPORTED_RATES)
+ return;
memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
rate_len = rate_ie->len;
}
@@ -272,8 +274,11 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
params->beacon.tail,
params->beacon.tail_len);
- if (rate_ie)
+ if (rate_ie) {
+ if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len)
+ return;
memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
+ }
return;
}
@@ -391,6 +396,8 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
params->beacon.tail_len);
if (vendor_ie) {
wmm_ie = vendor_ie;
+ if (*(wmm_ie + 1) > sizeof(struct mwifiex_types_wmm_info))
+ return;
memcpy(&bss_cfg->wmm_info, wmm_ie +
sizeof(struct ieee_types_header), *(wmm_ie + 1));
priv->wmm_enabled = 1;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 40c0d536e20d..9d4426f6905f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -59,6 +59,11 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
}
+ if (is_mt7630(dev)) {
+ dev->mt76.cap.has_5ghz = false;
+ dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");
+ }
+
if (!mt76x02_field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index 4585e1b756c2..6117e6ca08cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -62,6 +62,19 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
mt76x0e_stop_hw(dev);
}
+static int
+mt76x0e_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct mt76x02_dev *dev = hw->priv;
+
+ if (is_mt7630(dev))
+ return -EOPNOTSUPP;
+
+ return mt76x02_set_key(hw, cmd, vif, sta, key);
+}
+
static void
mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
@@ -78,7 +91,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
.configure_filter = mt76x02_configure_filter,
.bss_info_changed = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
- .set_key = mt76x02_set_key,
+ .set_key = mt76x0e_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 627ed1fc7b15..645f4d15fb61 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -136,11 +136,11 @@ static const struct ieee80211_ops mt76x0u_ops = {
.release_buffered_frames = mt76_release_buffered_frames,
};
-static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)
{
int err;
- mt76x0_chip_onoff(dev, true, true);
+ mt76x0_chip_onoff(dev, true, reset);
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
@@ -173,7 +173,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
if (err < 0)
goto out_err;
- err = mt76x0u_init_hardware(dev);
+ err = mt76x0u_init_hardware(dev, true);
if (err < 0)
goto out_err;
@@ -309,7 +309,7 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
if (ret < 0)
goto err;
- ret = mt76x0u_init_hardware(dev);
+ ret = mt76x0u_init_hardware(dev, false);
if (ret)
goto err;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index c9b957ac5733..f1cdcd61c54a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1654,13 +1654,18 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
- rt2800_register_multiread(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
- if ((crypto->cipher == CIPHER_TKIP) ||
- (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
- (crypto->cipher == CIPHER_AES))
- iveiv_entry.iv[3] |= 0x20;
- iveiv_entry.iv[3] |= key->keyidx << 6;
+ if (crypto->cmd == SET_KEY) {
+ rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
+ if ((crypto->cipher == CIPHER_TKIP) ||
+ (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+ (crypto->cipher == CIPHER_AES))
+ iveiv_entry.iv[3] |= 0x20;
+ iveiv_entry.iv[3] |= key->keyidx << 6;
+ } else {
+ memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+ }
+
rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));
}
@@ -4237,24 +4242,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
switch (rt2x00dev->default_ant.rx_chain_num) {
case 3:
/* Turn on tertiary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
- rf->channel > 14);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
- rf->channel <= 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
/* fall-through */
case 2:
/* Turn on secondary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
- rf->channel > 14);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
- rf->channel <= 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
/* fall-through */
case 1:
/* Turn on primary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
- rf->channel > 14);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
- rf->channel <= 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
break;
}
@@ -6095,6 +6094,15 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
}
/*
+ * Clear encryption initialization vectors on start, but keep them
+ * for watchdog reset. Otherwise we will have wrong IVs and not be
+ * able to keep connections after reset.
+ */
+ if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
+ for (i = 0; i < 256; i++)
+ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+
+ /*
* Clear all beacons
*/
for (i = 0; i < 8; i++)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 7e43690a861c..2b216edd0c7d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -658,6 +658,7 @@ enum rt2x00_state_flags {
DEVICE_STATE_ENABLED_RADIO,
DEVICE_STATE_SCANNING,
DEVICE_STATE_FLUSHING,
+ DEVICE_STATE_RESET,
/*
* Driver configuration
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 35414f97a978..9d158237ac67 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -1256,13 +1256,14 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
{
- int retval;
+ int retval = 0;
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
/*
* This is special case for ieee80211_restart_hw(), otherwise
* mac80211 never call start() two times in row without stop();
*/
+ set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
rt2x00lib_stop(rt2x00dev);
}
@@ -1273,14 +1274,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
*/
retval = rt2x00lib_load_firmware(rt2x00dev);
if (retval)
- return retval;
+ goto out;
/*
* Initialize the device.
*/
retval = rt2x00lib_initialize(rt2x00dev);
if (retval)
- return retval;
+ goto out;
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
@@ -1289,11 +1290,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
/* Enable the radio */
retval = rt2x00lib_enable_radio(rt2x00dev);
if (retval)
- return retval;
+ goto out;
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
- return 0;
+out:
+ clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+ return retval;
}
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index f5048d4b8cb6..760eaffeebd6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -645,7 +645,6 @@ fail_rx:
kfree(rsi_dev->tx_buffer);
fail_eps:
- kfree(rsi_dev);
return status;
}
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 1d9940d4e8c7..c9262ffeefe4 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -925,6 +925,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
nskb = xenvif_alloc_skb(0);
if (unlikely(nskb == NULL)) {
+ skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
xenvif_tx_err(queue, &txreq, extra_count, idx);
if (net_ratelimit())
@@ -940,6 +941,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
/* Failure in xenvif_set_skb_gso is fatal. */
+ skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
kfree_skb(nskb);
break;
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
index e65d027b91fa..529be35ac178 100644
--- a/drivers/nfc/nfcmrvl/main.c
+++ b/drivers/nfc/nfcmrvl/main.c
@@ -244,7 +244,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
/* Reset possible fault of previous session */
clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
- if (priv->config.reset_n_io) {
+ if (gpio_is_valid(priv->config.reset_n_io)) {
nfc_info(priv->dev, "reset the chip\n");
gpio_set_value(priv->config.reset_n_io, 0);
usleep_range(5000, 10000);
@@ -255,7 +255,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
void nfcmrvl_chip_halt(struct nfcmrvl_private *priv)
{
- if (priv->config.reset_n_io)
+ if (gpio_is_valid(priv->config.reset_n_io))
gpio_set_value(priv->config.reset_n_io, 0);
}
diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
index 9a22056e8d9e..e5a622ce4b95 100644
--- a/drivers/nfc/nfcmrvl/uart.c
+++ b/drivers/nfc/nfcmrvl/uart.c
@@ -26,7 +26,7 @@
static unsigned int hci_muxed;
static unsigned int flow_control;
static unsigned int break_control;
-static unsigned int reset_n_io;
+static int reset_n_io = -EINVAL;
/*
** NFCMRVL NCI OPS
@@ -231,5 +231,5 @@ MODULE_PARM_DESC(break_control, "Tell if UART driver must drive break signal.");
module_param(hci_muxed, uint, 0);
MODULE_PARM_DESC(hci_muxed, "Tell if transport is muxed in HCI one.");
-module_param(reset_n_io, uint, 0);
+module_param(reset_n_io, int, 0);
MODULE_PARM_DESC(reset_n_io, "GPIO that is wired to RESET_N signal.");
diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c
index 945cc903d8f1..888e298f610b 100644
--- a/drivers/nfc/nfcmrvl/usb.c
+++ b/drivers/nfc/nfcmrvl/usb.c
@@ -305,6 +305,7 @@ static int nfcmrvl_probe(struct usb_interface *intf,
/* No configuration for USB */
memset(&config, 0, sizeof(config));
+ config.reset_n_io = -EINVAL;
nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index c3e10b6ab3a4..f25f1ec5f9e9 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -333,6 +333,8 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
skb->len - 2, GFP_KERNEL);
+ if (!transaction)
+ return -ENOMEM;
transaction->aid_len = skb->data[1];
memcpy(transaction->aid, &skb->data[2], transaction->aid_len);
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index 06fc542fd198..6586378cacb0 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -317,6 +317,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
skb->len - 2, GFP_KERNEL);
+ if (!transaction)
+ return -ENOMEM;
transaction->aid_len = skb->data[1];
memcpy(transaction->aid, &skb->data[2],
diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c
index e42850095892..7eda62a9e0df 100644
--- a/drivers/nfc/st95hf/core.c
+++ b/drivers/nfc/st95hf/core.c
@@ -316,7 +316,7 @@ static int st95hf_echo_command(struct st95hf_context *st95context)
&echo_response);
if (result) {
dev_err(&st95context->spicontext.spidev->dev,
- "err: echo response receieve error = 0x%x\n", result);
+ "err: echo response receive error = 0x%x\n", result);
return result;
}
diff --git a/drivers/ntb/msi.c b/drivers/ntb/msi.c
index 9dddf133658f..0a5e884a920c 100644
--- a/drivers/ntb/msi.c
+++ b/drivers/ntb/msi.c
@@ -6,11 +6,6 @@
#include <linux/msi.h>
#include <linux/pci.h>
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.1");
-MODULE_AUTHOR("Logan Gunthorpe <logang@deltatee.com>");
-MODULE_DESCRIPTION("NTB MSI Interrupt Library");
-
struct ntb_msi {
u64 base_addr;
u64 end_addr;
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index 62d00fffa4af..3508a79110c7 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -62,14 +62,14 @@ static ssize_t sector_size_store(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_size_select_store(dev, buf, &nd_btt->lbasize,
btt_lbasize_supported);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -91,11 +91,11 @@ static ssize_t uuid_store(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
rc = nd_uuid_store(dev, &nd_btt->uuid, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -120,13 +120,13 @@ static ssize_t namespace_store(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -138,14 +138,14 @@ static ssize_t size_show(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
if (dev->driver)
rc = sprintf(buf, "%llu\n", nd_btt->size);
else {
/* no size to convey if the btt instance is disabled */
rc = -ENXIO;
}
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 2dca3034fee0..798c5c4aea9c 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -26,7 +26,7 @@
int nvdimm_major;
static int nvdimm_bus_major;
-static struct class *nd_class;
+struct class *nd_class;
static DEFINE_IDA(nd_ida);
static int to_nd_device_type(struct device *dev)
@@ -73,7 +73,7 @@ static void nvdimm_bus_probe_end(struct nvdimm_bus *nvdimm_bus)
{
nvdimm_bus_lock(&nvdimm_bus->dev);
if (--nvdimm_bus->probe_active == 0)
- wake_up(&nvdimm_bus->probe_wait);
+ wake_up(&nvdimm_bus->wait);
nvdimm_bus_unlock(&nvdimm_bus->dev);
}
@@ -91,7 +91,10 @@ static int nvdimm_bus_probe(struct device *dev)
dev->driver->name, dev_name(dev));
nvdimm_bus_probe_start(nvdimm_bus);
+ debug_nvdimm_lock(dev);
rc = nd_drv->probe(dev);
+ debug_nvdimm_unlock(dev);
+
if (rc == 0)
nd_region_probe_success(nvdimm_bus, dev);
else
@@ -113,8 +116,11 @@ static int nvdimm_bus_remove(struct device *dev)
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
int rc = 0;
- if (nd_drv->remove)
+ if (nd_drv->remove) {
+ debug_nvdimm_lock(dev);
rc = nd_drv->remove(dev);
+ debug_nvdimm_unlock(dev);
+ }
nd_region_disable(nvdimm_bus, dev);
dev_dbg(&nvdimm_bus->dev, "%s.remove(%s) = %d\n", dev->driver->name,
@@ -140,7 +146,7 @@ static void nvdimm_bus_shutdown(struct device *dev)
void nd_device_notify(struct device *dev, enum nvdimm_event event)
{
- device_lock(dev);
+ nd_device_lock(dev);
if (dev->driver) {
struct nd_device_driver *nd_drv;
@@ -148,7 +154,7 @@ void nd_device_notify(struct device *dev, enum nvdimm_event event)
if (nd_drv->notify)
nd_drv->notify(dev, event);
}
- device_unlock(dev);
+ nd_device_unlock(dev);
}
EXPORT_SYMBOL(nd_device_notify);
@@ -296,7 +302,7 @@ static void nvdimm_bus_release(struct device *dev)
kfree(nvdimm_bus);
}
-static bool is_nvdimm_bus(struct device *dev)
+bool is_nvdimm_bus(struct device *dev)
{
return dev->release == nvdimm_bus_release;
}
@@ -341,7 +347,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
return NULL;
INIT_LIST_HEAD(&nvdimm_bus->list);
INIT_LIST_HEAD(&nvdimm_bus->mapping_list);
- init_waitqueue_head(&nvdimm_bus->probe_wait);
+ init_waitqueue_head(&nvdimm_bus->wait);
nvdimm_bus->id = ida_simple_get(&nd_ida, 0, 0, GFP_KERNEL);
if (nvdimm_bus->id < 0) {
kfree(nvdimm_bus);
@@ -426,6 +432,9 @@ static int nd_bus_remove(struct device *dev)
list_del_init(&nvdimm_bus->list);
mutex_unlock(&nvdimm_bus_list_mutex);
+ wait_event(nvdimm_bus->wait,
+ atomic_read(&nvdimm_bus->ioctl_active) == 0);
+
nd_synchronize();
device_for_each_child(&nvdimm_bus->dev, NULL, child_unregister);
@@ -547,13 +556,38 @@ EXPORT_SYMBOL(nd_device_register);
void nd_device_unregister(struct device *dev, enum nd_async_mode mode)
{
+ bool killed;
+
switch (mode) {
case ND_ASYNC:
+ /*
+ * In the async case this is being triggered with the
+ * device lock held and the unregistration work needs to
+ * be moved out of line iff this is thread has won the
+ * race to schedule the deletion.
+ */
+ if (!kill_device(dev))
+ return;
+
get_device(dev);
async_schedule_domain(nd_async_device_unregister, dev,
&nd_async_domain);
break;
case ND_SYNC:
+ /*
+ * In the sync case the device is being unregistered due
+ * to a state change of the parent. Claim the kill state
+ * to synchronize against other unregistration requests,
+ * or otherwise let the async path handle it if the
+ * unregistration was already queued.
+ */
+ nd_device_lock(dev);
+ killed = kill_device(dev);
+ nd_device_unlock(dev);
+
+ if (!killed)
+ return;
+
nd_synchronize();
device_unregister(dev);
break;
@@ -859,10 +893,12 @@ void wait_nvdimm_bus_probe_idle(struct device *dev)
do {
if (nvdimm_bus->probe_active == 0)
break;
- nvdimm_bus_unlock(&nvdimm_bus->dev);
- wait_event(nvdimm_bus->probe_wait,
+ nvdimm_bus_unlock(dev);
+ nd_device_unlock(dev);
+ wait_event(nvdimm_bus->wait,
nvdimm_bus->probe_active == 0);
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ nd_device_lock(dev);
+ nvdimm_bus_lock(dev);
} while (true);
}
@@ -945,20 +981,19 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
int read_only, unsigned int ioctl_cmd, unsigned long arg)
{
struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
- static char out_env[ND_CMD_MAX_ENVELOPE];
- static char in_env[ND_CMD_MAX_ENVELOPE];
const struct nd_cmd_desc *desc = NULL;
unsigned int cmd = _IOC_NR(ioctl_cmd);
struct device *dev = &nvdimm_bus->dev;
void __user *p = (void __user *) arg;
+ char *out_env = NULL, *in_env = NULL;
const char *cmd_name, *dimm_name;
u32 in_len = 0, out_len = 0;
unsigned int func = cmd;
unsigned long cmd_mask;
struct nd_cmd_pkg pkg;
int rc, i, cmd_rc;
+ void *buf = NULL;
u64 buf_len = 0;
- void *buf;
if (nvdimm) {
desc = nd_cmd_dimm_desc(cmd);
@@ -989,7 +1024,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
case ND_CMD_ARS_START:
case ND_CMD_CLEAR_ERROR:
case ND_CMD_CALL:
- dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
+ dev_dbg(dev, "'%s' command while read-only.\n",
nvdimm ? nvdimm_cmd_name(cmd)
: nvdimm_bus_cmd_name(cmd));
return -EPERM;
@@ -998,6 +1033,9 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
}
/* process an input envelope */
+ in_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
+ if (!in_env)
+ return -ENOMEM;
for (i = 0; i < desc->in_num; i++) {
u32 in_size, copy;
@@ -1005,14 +1043,17 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
if (in_size == UINT_MAX) {
dev_err(dev, "%s:%s unknown input size cmd: %s field: %d\n",
__func__, dimm_name, cmd_name, i);
- return -ENXIO;
+ rc = -ENXIO;
+ goto out;
}
- if (in_len < sizeof(in_env))
- copy = min_t(u32, sizeof(in_env) - in_len, in_size);
+ if (in_len < ND_CMD_MAX_ENVELOPE)
+ copy = min_t(u32, ND_CMD_MAX_ENVELOPE - in_len, in_size);
else
copy = 0;
- if (copy && copy_from_user(&in_env[in_len], p + in_len, copy))
- return -EFAULT;
+ if (copy && copy_from_user(&in_env[in_len], p + in_len, copy)) {
+ rc = -EFAULT;
+ goto out;
+ }
in_len += in_size;
}
@@ -1024,6 +1065,12 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
}
/* process an output envelope */
+ out_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
+ if (!out_env) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
for (i = 0; i < desc->out_num; i++) {
u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
(u32 *) in_env, (u32 *) out_env, 0);
@@ -1032,15 +1079,18 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
if (out_size == UINT_MAX) {
dev_dbg(dev, "%s unknown output size cmd: %s field: %d\n",
dimm_name, cmd_name, i);
- return -EFAULT;
+ rc = -EFAULT;
+ goto out;
}
- if (out_len < sizeof(out_env))
- copy = min_t(u32, sizeof(out_env) - out_len, out_size);
+ if (out_len < ND_CMD_MAX_ENVELOPE)
+ copy = min_t(u32, ND_CMD_MAX_ENVELOPE - out_len, out_size);
else
copy = 0;
if (copy && copy_from_user(&out_env[out_len],
- p + in_len + out_len, copy))
- return -EFAULT;
+ p + in_len + out_len, copy)) {
+ rc = -EFAULT;
+ goto out;
+ }
out_len += out_size;
}
@@ -1048,19 +1098,23 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
if (buf_len > ND_IOCTL_MAX_BUFLEN) {
dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name,
cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
buf = vmalloc(buf_len);
- if (!buf)
- return -ENOMEM;
+ if (!buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
if (copy_from_user(buf, p, buf_len)) {
rc = -EFAULT;
goto out;
}
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ nd_device_lock(dev);
+ nvdimm_bus_lock(dev);
rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
if (rc)
goto out_unlock;
@@ -1075,39 +1129,24 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
nvdimm_account_cleared_poison(nvdimm_bus, clear_err->address,
clear_err->cleared);
}
- nvdimm_bus_unlock(&nvdimm_bus->dev);
if (copy_to_user(p, buf, buf_len))
rc = -EFAULT;
- vfree(buf);
- return rc;
-
- out_unlock:
- nvdimm_bus_unlock(&nvdimm_bus->dev);
- out:
+out_unlock:
+ nvdimm_bus_unlock(dev);
+ nd_device_unlock(dev);
+out:
+ kfree(in_env);
+ kfree(out_env);
vfree(buf);
return rc;
}
-static long nd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- long id = (long) file->private_data;
- int rc = -ENXIO, ro;
- struct nvdimm_bus *nvdimm_bus;
-
- ro = ((file->f_flags & O_ACCMODE) == O_RDONLY);
- mutex_lock(&nvdimm_bus_list_mutex);
- list_for_each_entry(nvdimm_bus, &nvdimm_bus_list, list) {
- if (nvdimm_bus->id == id) {
- rc = __nd_ioctl(nvdimm_bus, NULL, ro, cmd, arg);
- break;
- }
- }
- mutex_unlock(&nvdimm_bus_list_mutex);
-
- return rc;
-}
+enum nd_ioctl_mode {
+ BUS_IOCTL,
+ DIMM_IOCTL,
+};
static int match_dimm(struct device *dev, void *data)
{
@@ -1122,31 +1161,62 @@ static int match_dimm(struct device *dev, void *data)
return 0;
}
-static long nvdimm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long nd_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+ enum nd_ioctl_mode mode)
+
{
- int rc = -ENXIO, ro;
- struct nvdimm_bus *nvdimm_bus;
+ struct nvdimm_bus *nvdimm_bus, *found = NULL;
+ long id = (long) file->private_data;
+ struct nvdimm *nvdimm = NULL;
+ int rc, ro;
ro = ((file->f_flags & O_ACCMODE) == O_RDONLY);
mutex_lock(&nvdimm_bus_list_mutex);
list_for_each_entry(nvdimm_bus, &nvdimm_bus_list, list) {
- struct device *dev = device_find_child(&nvdimm_bus->dev,
- file->private_data, match_dimm);
- struct nvdimm *nvdimm;
-
- if (!dev)
- continue;
+ if (mode == DIMM_IOCTL) {
+ struct device *dev;
+
+ dev = device_find_child(&nvdimm_bus->dev,
+ file->private_data, match_dimm);
+ if (!dev)
+ continue;
+ nvdimm = to_nvdimm(dev);
+ found = nvdimm_bus;
+ } else if (nvdimm_bus->id == id) {
+ found = nvdimm_bus;
+ }
- nvdimm = to_nvdimm(dev);
- rc = __nd_ioctl(nvdimm_bus, nvdimm, ro, cmd, arg);
- put_device(dev);
- break;
+ if (found) {
+ atomic_inc(&nvdimm_bus->ioctl_active);
+ break;
+ }
}
mutex_unlock(&nvdimm_bus_list_mutex);
+ if (!found)
+ return -ENXIO;
+
+ nvdimm_bus = found;
+ rc = __nd_ioctl(nvdimm_bus, nvdimm, ro, cmd, arg);
+
+ if (nvdimm)
+ put_device(&nvdimm->dev);
+ if (atomic_dec_and_test(&nvdimm_bus->ioctl_active))
+ wake_up(&nvdimm_bus->wait);
+
return rc;
}
+static long bus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return nd_ioctl(file, cmd, arg, BUS_IOCTL);
+}
+
+static long dimm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return nd_ioctl(file, cmd, arg, DIMM_IOCTL);
+}
+
static int nd_open(struct inode *inode, struct file *file)
{
long minor = iminor(inode);
@@ -1158,16 +1228,16 @@ static int nd_open(struct inode *inode, struct file *file)
static const struct file_operations nvdimm_bus_fops = {
.owner = THIS_MODULE,
.open = nd_open,
- .unlocked_ioctl = nd_ioctl,
- .compat_ioctl = nd_ioctl,
+ .unlocked_ioctl = bus_ioctl,
+ .compat_ioctl = bus_ioctl,
.llseek = noop_llseek,
};
static const struct file_operations nvdimm_fops = {
.owner = THIS_MODULE,
.open = nd_open,
- .unlocked_ioctl = nvdimm_ioctl,
- .compat_ioctl = nvdimm_ioctl,
+ .unlocked_ioctl = dimm_ioctl,
+ .compat_ioctl = dimm_ioctl,
.llseek = noop_llseek,
};
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 5e1f060547bf..9204f1e9fd14 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -246,7 +246,7 @@ static int nd_uuid_parse(struct device *dev, u8 *uuid_out, const char *buf,
*
* Enforce that uuids can only be changed while the device is disabled
* (driver detached)
- * LOCKING: expects device_lock() is held on entry
+ * LOCKING: expects nd_device_lock() is held on entry
*/
int nd_uuid_store(struct device *dev, u8 **uuid_out, const char *buf,
size_t len)
@@ -347,15 +347,15 @@ static DEVICE_ATTR_RO(provider);
static int flush_namespaces(struct device *dev, void *data)
{
- device_lock(dev);
- device_unlock(dev);
+ nd_device_lock(dev);
+ nd_device_unlock(dev);
return 0;
}
static int flush_regions_dimms(struct device *dev, void *data)
{
- device_lock(dev);
- device_unlock(dev);
+ nd_device_lock(dev);
+ nd_device_unlock(dev);
device_for_each_child(dev, NULL, flush_namespaces);
return 0;
}
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index dfecd6e17043..29a065e769ea 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -484,12 +484,12 @@ static ssize_t security_store(struct device *dev,
* done while probing is idle and the DIMM is not in active use
* in any region.
*/
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __security_store(dev, buf, len);
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 2d8d7e554877..a16e52251a30 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -410,7 +410,7 @@ static ssize_t alt_name_store(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev->parent);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __alt_name_store(dev, buf, len);
@@ -418,7 +418,7 @@ static ssize_t alt_name_store(struct device *dev,
rc = nd_namespace_label_update(nd_region, dev);
dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -1077,7 +1077,7 @@ static ssize_t size_store(struct device *dev,
if (rc)
return rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __size_store(dev, val);
@@ -1103,7 +1103,7 @@ static ssize_t size_store(struct device *dev,
dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc);
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -1286,7 +1286,7 @@ static ssize_t uuid_store(struct device *dev,
} else
return -ENXIO;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
if (to_ndns(dev)->claim)
@@ -1302,7 +1302,7 @@ static ssize_t uuid_store(struct device *dev,
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -1376,7 +1376,7 @@ static ssize_t sector_size_store(struct device *dev,
} else
return -ENXIO;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
if (to_ndns(dev)->claim)
rc = -EBUSY;
@@ -1387,7 +1387,7 @@ static ssize_t sector_size_store(struct device *dev,
dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote",
buf, buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -1502,9 +1502,9 @@ static ssize_t holder_show(struct device *dev,
struct nd_namespace_common *ndns = to_ndns(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
rc = sprintf(buf, "%s\n", ndns->claim ? dev_name(ndns->claim) : "");
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -1541,7 +1541,7 @@ static ssize_t holder_class_store(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev->parent);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __holder_class_store(dev, buf);
@@ -1549,7 +1549,7 @@ static ssize_t holder_class_store(struct device *dev,
rc = nd_namespace_label_update(nd_region, dev);
dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -1560,7 +1560,7 @@ static ssize_t holder_class_show(struct device *dev,
struct nd_namespace_common *ndns = to_ndns(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
if (ndns->claim_class == NVDIMM_CCLASS_NONE)
rc = sprintf(buf, "\n");
else if ((ndns->claim_class == NVDIMM_CCLASS_BTT) ||
@@ -1572,7 +1572,7 @@ static ssize_t holder_class_show(struct device *dev,
rc = sprintf(buf, "dax\n");
else
rc = sprintf(buf, "<unknown>\n");
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -1586,7 +1586,7 @@ static ssize_t mode_show(struct device *dev,
char *mode;
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
claim = ndns->claim;
if (claim && is_nd_btt(claim))
mode = "safe";
@@ -1599,7 +1599,7 @@ static ssize_t mode_show(struct device *dev,
else
mode = "raw";
rc = sprintf(buf, "%s\n", mode);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -1703,8 +1703,8 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
* Flush any in-progess probes / removals in the driver
* for the raw personality of this namespace.
*/
- device_lock(&ndns->dev);
- device_unlock(&ndns->dev);
+ nd_device_lock(&ndns->dev);
+ nd_device_unlock(&ndns->dev);
if (ndns->dev.driver) {
dev_dbg(&ndns->dev, "is active, can't bind %s\n",
dev_name(dev));
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 391e88de3a29..0ac52b6eb00e 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -9,6 +9,7 @@
#include <linux/sizes.h>
#include <linux/mutex.h>
#include <linux/nd.h>
+#include "nd.h"
extern struct list_head nvdimm_bus_list;
extern struct mutex nvdimm_bus_list_mutex;
@@ -17,10 +18,11 @@ extern struct workqueue_struct *nvdimm_wq;
struct nvdimm_bus {
struct nvdimm_bus_descriptor *nd_desc;
- wait_queue_head_t probe_wait;
+ wait_queue_head_t wait;
struct list_head list;
struct device dev;
int id, probe_active;
+ atomic_t ioctl_active;
struct list_head mapping_list;
struct mutex reconfig_mutex;
struct badrange badrange;
@@ -181,4 +183,71 @@ ssize_t nd_namespace_store(struct device *dev,
struct nd_namespace_common **_ndns, const char *buf,
size_t len);
struct nd_pfn *to_nd_pfn_safe(struct device *dev);
+bool is_nvdimm_bus(struct device *dev);
+
+#ifdef CONFIG_PROVE_LOCKING
+extern struct class *nd_class;
+
+enum {
+ LOCK_BUS,
+ LOCK_NDCTL,
+ LOCK_REGION,
+ LOCK_DIMM = LOCK_REGION,
+ LOCK_NAMESPACE,
+ LOCK_CLAIM,
+};
+
+static inline void debug_nvdimm_lock(struct device *dev)
+{
+ if (is_nd_region(dev))
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_REGION);
+ else if (is_nvdimm(dev))
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_DIMM);
+ else if (is_nd_btt(dev) || is_nd_pfn(dev) || is_nd_dax(dev))
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_CLAIM);
+ else if (dev->parent && (is_nd_region(dev->parent)))
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_NAMESPACE);
+ else if (is_nvdimm_bus(dev))
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_BUS);
+ else if (dev->class && dev->class == nd_class)
+ mutex_lock_nested(&dev->lockdep_mutex, LOCK_NDCTL);
+ else
+ dev_WARN(dev, "unknown lock level\n");
+}
+
+static inline void debug_nvdimm_unlock(struct device *dev)
+{
+ mutex_unlock(&dev->lockdep_mutex);
+}
+
+static inline void nd_device_lock(struct device *dev)
+{
+ device_lock(dev);
+ debug_nvdimm_lock(dev);
+}
+
+static inline void nd_device_unlock(struct device *dev)
+{
+ debug_nvdimm_unlock(dev);
+ device_unlock(dev);
+}
+#else
+static inline void nd_device_lock(struct device *dev)
+{
+ device_lock(dev);
+}
+
+static inline void nd_device_unlock(struct device *dev)
+{
+ device_unlock(dev);
+}
+
+static inline void debug_nvdimm_lock(struct device *dev)
+{
+}
+
+static inline void debug_nvdimm_unlock(struct device *dev)
+{
+}
+#endif
#endif /* __ND_CORE_H__ */
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index df2bdbd22450..cb98b8fe786e 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -67,7 +67,7 @@ static ssize_t mode_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc = 0;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
if (dev->driver)
rc = -EBUSY;
@@ -89,7 +89,7 @@ static ssize_t mode_store(struct device *dev,
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -132,14 +132,14 @@ static ssize_t align_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_size_select_store(dev, buf, &nd_pfn->align,
nd_pfn_supported_alignments());
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -161,11 +161,11 @@ static ssize_t uuid_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc ? rc : len;
}
@@ -190,13 +190,13 @@ static ssize_t namespace_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -208,7 +208,7 @@ static ssize_t resource_show(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
if (dev->driver) {
struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
u64 offset = __le64_to_cpu(pfn_sb->dataoff);
@@ -222,7 +222,7 @@ static ssize_t resource_show(struct device *dev,
/* no address to convey if the pfn instance is disabled */
rc = -ENXIO;
}
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -234,7 +234,7 @@ static ssize_t size_show(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
if (dev->driver) {
struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
u64 offset = __le64_to_cpu(pfn_sb->dataoff);
@@ -250,7 +250,7 @@ static ssize_t size_show(struct device *dev,
/* no size to convey if the pfn instance is disabled */
rc = -ENXIO;
}
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
@@ -655,6 +655,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
resource_size_t start, size;
struct nd_region *nd_region;
unsigned long npfns, align;
+ u32 end_trunc;
struct nd_pfn_sb *pfn_sb;
phys_addr_t offset;
const char *sig;
@@ -696,6 +697,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
size = resource_size(&nsio->res);
npfns = PHYS_PFN(size - SZ_8K);
align = max(nd_pfn->align, (1UL << SUBSECTION_SHIFT));
+ end_trunc = start + size - ALIGN_DOWN(start + size, align);
if (nd_pfn->mode == PFN_MODE_PMEM) {
/*
* The altmap should be padded out to the block size used
@@ -714,7 +716,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
return -ENXIO;
}
- npfns = PHYS_PFN(size - offset);
+ npfns = PHYS_PFN(size - offset - end_trunc);
pfn_sb->mode = cpu_to_le32(nd_pfn->mode);
pfn_sb->dataoff = cpu_to_le64(offset);
pfn_sb->npfns = cpu_to_le64(npfns);
@@ -723,6 +725,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
pfn_sb->version_major = cpu_to_le16(1);
pfn_sb->version_minor = cpu_to_le16(3);
+ pfn_sb->end_trunc = cpu_to_le32(end_trunc);
pfn_sb->align = cpu_to_le32(nd_pfn->align);
checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
pfn_sb->checksum = cpu_to_le64(checksum);
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 2bf3acd69613..4c121dd03dd9 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -522,8 +522,8 @@ static int nd_pmem_remove(struct device *dev)
nvdimm_namespace_detach_btt(to_nd_btt(dev));
else {
/*
- * Note, this assumes device_lock() context to not race
- * nd_pmem_notify()
+ * Note, this assumes nd_device_lock() context to not
+ * race nd_pmem_notify()
*/
sysfs_put(pmem->bb_state);
pmem->bb_state = NULL;
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c
index ef46cc3a71ae..37bf8719a2a4 100644
--- a/drivers/nvdimm/region.c
+++ b/drivers/nvdimm/region.c
@@ -34,17 +34,6 @@ static int nd_region_probe(struct device *dev)
if (rc)
return rc;
- rc = nd_region_register_namespaces(nd_region, &err);
- if (rc < 0)
- return rc;
-
- ndrd = dev_get_drvdata(dev);
- ndrd->ns_active = rc;
- ndrd->ns_count = rc + err;
-
- if (rc && err && rc == err)
- return -ENODEV;
-
if (is_nd_pmem(&nd_region->dev)) {
struct resource ndr_res;
@@ -60,6 +49,17 @@ static int nd_region_probe(struct device *dev)
nvdimm_badblocks_populate(nd_region, &nd_region->bb, &ndr_res);
}
+ rc = nd_region_register_namespaces(nd_region, &err);
+ if (rc < 0)
+ return rc;
+
+ ndrd = dev_get_drvdata(dev);
+ ndrd->ns_active = rc;
+ ndrd->ns_count = rc + err;
+
+ if (rc && err && rc == err)
+ return -ENODEV;
+
nd_region->btt_seed = nd_btt_create(nd_region);
nd_region->pfn_seed = nd_pfn_create(nd_region);
nd_region->dax_seed = nd_dax_create(nd_region);
@@ -102,7 +102,7 @@ static int nd_region_remove(struct device *dev)
nvdimm_bus_unlock(dev);
/*
- * Note, this assumes device_lock() context to not race
+ * Note, this assumes nd_device_lock() context to not race
* nd_region_notify()
*/
sysfs_put(nd_region->bb_state);
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 56f2227f192a..af30cbe7a8ea 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -331,7 +331,7 @@ static ssize_t set_cookie_show(struct device *dev,
* the v1.1 namespace label cookie definition. To read all this
* data we need to wait for probing to settle.
*/
- device_lock(dev);
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
if (nd_region->ndr_mappings) {
@@ -348,7 +348,7 @@ static ssize_t set_cookie_show(struct device *dev,
}
}
nvdimm_bus_unlock(dev);
- device_unlock(dev);
+ nd_device_unlock(dev);
if (rc)
return rc;
@@ -424,10 +424,12 @@ static ssize_t available_size_show(struct device *dev,
* memory nvdimm_bus_lock() is dropped, but that's userspace's
* problem to not race itself.
*/
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
available = nd_region_available_dpa(nd_region);
nvdimm_bus_unlock(dev);
+ nd_device_unlock(dev);
return sprintf(buf, "%llu\n", available);
}
@@ -439,10 +441,12 @@ static ssize_t max_available_extent_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
unsigned long long available = 0;
+ nd_device_lock(dev);
nvdimm_bus_lock(dev);
wait_nvdimm_bus_probe_idle(dev);
available = nd_region_allocatable_dpa(nd_region);
nvdimm_bus_unlock(dev);
+ nd_device_unlock(dev);
return sprintf(buf, "%llu\n", available);
}
@@ -561,12 +565,12 @@ static ssize_t region_badblocks_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
ssize_t rc;
- device_lock(dev);
+ nd_device_lock(dev);
if (dev->driver)
rc = badblocks_show(&nd_region->bb, buf, 0);
else
rc = -ENXIO;
- device_unlock(dev);
+ nd_device_unlock(dev);
return rc;
}
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index cc09b81fc7f4..d3d6b7bd6903 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1286,6 +1286,9 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
*/
if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
mutex_lock(&ctrl->scan_lock);
+ mutex_lock(&ctrl->subsys->lock);
+ nvme_mpath_start_freeze(ctrl->subsys);
+ nvme_mpath_wait_freeze(ctrl->subsys);
nvme_start_freeze(ctrl);
nvme_wait_freeze(ctrl);
}
@@ -1316,6 +1319,8 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
nvme_update_formats(ctrl);
if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
nvme_unfreeze(ctrl);
+ nvme_mpath_unfreeze(ctrl->subsys);
+ mutex_unlock(&ctrl->subsys->lock);
mutex_unlock(&ctrl->scan_lock);
}
if (effects & NVME_CMD_EFFECTS_CCC)
@@ -1715,6 +1720,7 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
if (ns->head->disk) {
nvme_update_disk_info(ns->head->disk, ns, id);
blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
+ revalidate_disk(ns->head->disk);
}
#endif
}
@@ -2251,6 +2257,16 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
.vid = 0x1179,
.mn = "THNSF5256GPUK TOSHIBA",
.quirks = NVME_QUIRK_NO_APST,
+ },
+ {
+ /*
+ * This LiteON CL1-3D*-Q11 firmware version has a race
+ * condition associated with actions related to suspend to idle
+ * LiteON has resolved the problem in future firmware
+ */
+ .vid = 0x14a4,
+ .fr = "22301111",
+ .quirks = NVME_QUIRK_SIMPLE_SUSPEND,
}
};
@@ -2311,17 +2327,15 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct
memset(subsys->subnqn + off, 0, sizeof(subsys->subnqn) - off);
}
-static void __nvme_release_subsystem(struct nvme_subsystem *subsys)
+static void nvme_release_subsystem(struct device *dev)
{
+ struct nvme_subsystem *subsys =
+ container_of(dev, struct nvme_subsystem, dev);
+
ida_simple_remove(&nvme_subsystems_ida, subsys->instance);
kfree(subsys);
}
-static void nvme_release_subsystem(struct device *dev)
-{
- __nvme_release_subsystem(container_of(dev, struct nvme_subsystem, dev));
-}
-
static void nvme_destroy_subsystem(struct kref *ref)
{
struct nvme_subsystem *subsys =
@@ -2477,7 +2491,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
mutex_lock(&nvme_subsystems_lock);
found = __nvme_find_get_subsystem(subsys->subnqn);
if (found) {
- __nvme_release_subsystem(subsys);
+ put_device(&subsys->dev);
subsys = found;
if (!nvme_validate_cntlid(subsys, ctrl, id)) {
@@ -2489,6 +2503,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
if (ret) {
dev_err(ctrl->device,
"failed to register subsystem device.\n");
+ put_device(&subsys->dev);
goto out_unlock;
}
ida_init(&subsys->ns_ida);
@@ -2511,7 +2526,6 @@ out_put_subsystem:
nvme_put_subsystem(subsys);
out_unlock:
mutex_unlock(&nvme_subsystems_lock);
- put_device(&subsys->dev);
return ret;
}
@@ -2593,6 +2607,9 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
goto out_free;
}
+ if (!(ctrl->ops->flags & NVME_F_FABRICS))
+ ctrl->cntlid = le16_to_cpu(id->cntlid);
+
if (!ctrl->identified) {
int i;
@@ -2693,7 +2710,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
goto out_free;
}
} else {
- ctrl->cntlid = le16_to_cpu(id->cntlid);
ctrl->hmpre = le32_to_cpu(id->hmpre);
ctrl->hmmin = le32_to_cpu(id->hmmin);
ctrl->hmminds = le32_to_cpu(id->hmminds);
@@ -3573,6 +3589,13 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
struct nvme_ns *ns, *next;
LIST_HEAD(ns_list);
+ /*
+ * make sure to requeue I/O to all namespaces as these
+ * might result from the scan itself and must complete
+ * for the scan_work to make progress
+ */
+ nvme_mpath_clear_ctrl_paths(ctrl);
+
/* prevent racing with ns scanning */
flush_work(&ctrl->scan_work);
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index a9a927677970..af831d3d15d0 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -12,9 +12,34 @@ module_param(multipath, bool, 0444);
MODULE_PARM_DESC(multipath,
"turn on native support for multiple controllers per subsystem");
-inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
{
- return multipath && ctrl->subsys && (ctrl->subsys->cmic & (1 << 3));
+ struct nvme_ns_head *h;
+
+ lockdep_assert_held(&subsys->lock);
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (h->disk)
+ blk_mq_unfreeze_queue(h->disk->queue);
+}
+
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+ struct nvme_ns_head *h;
+
+ lockdep_assert_held(&subsys->lock);
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (h->disk)
+ blk_mq_freeze_queue_wait(h->disk->queue);
+}
+
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+ struct nvme_ns_head *h;
+
+ lockdep_assert_held(&subsys->lock);
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (h->disk)
+ blk_freeze_queue_start(h->disk->queue);
}
/*
@@ -109,18 +134,34 @@ static const char *nvme_ana_state_names[] = {
[NVME_ANA_CHANGE] = "change",
};
-void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
{
struct nvme_ns_head *head = ns->head;
+ bool changed = false;
int node;
if (!head)
- return;
+ goto out;
for_each_node(node) {
- if (ns == rcu_access_pointer(head->current_path[node]))
+ if (ns == rcu_access_pointer(head->current_path[node])) {
rcu_assign_pointer(head->current_path[node], NULL);
+ changed = true;
+ }
}
+out:
+ return changed;
+}
+
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
+{
+ struct nvme_ns *ns;
+
+ mutex_lock(&ctrl->scan_lock);
+ list_for_each_entry(ns, &ctrl->namespaces, list)
+ if (nvme_mpath_clear_current_path(ns))
+ kblockd_schedule_work(&ns->head->requeue_work);
+ mutex_unlock(&ctrl->scan_lock);
}
static bool nvme_path_is_disabled(struct nvme_ns *ns)
@@ -231,6 +272,24 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
return ns;
}
+static bool nvme_available_path(struct nvme_ns_head *head)
+{
+ struct nvme_ns *ns;
+
+ list_for_each_entry_rcu(ns, &head->list, siblings) {
+ switch (ns->ctrl->state) {
+ case NVME_CTRL_LIVE:
+ case NVME_CTRL_RESETTING:
+ case NVME_CTRL_CONNECTING:
+ /* fallthru */
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
struct bio *bio)
{
@@ -257,14 +316,14 @@ static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
disk_devt(ns->head->disk),
bio->bi_iter.bi_sector);
ret = direct_make_request(bio);
- } else if (!list_empty_careful(&head->list)) {
- dev_warn_ratelimited(dev, "no path available - requeuing I/O\n");
+ } else if (nvme_available_path(head)) {
+ dev_warn_ratelimited(dev, "no usable path - requeuing I/O\n");
spin_lock_irq(&head->requeue_lock);
bio_list_add(&head->requeue_list, bio);
spin_unlock_irq(&head->requeue_lock);
} else {
- dev_warn_ratelimited(dev, "no path - failing I/O\n");
+ dev_warn_ratelimited(dev, "no available path - failing I/O\n");
bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
@@ -369,6 +428,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
srcu_read_unlock(&head->srcu, srcu_idx);
}
+ synchronize_srcu(&ns->head->srcu);
kblockd_schedule_work(&ns->head->requeue_work);
}
@@ -622,7 +682,8 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
{
int error;
- if (!nvme_ctrl_use_ana(ctrl))
+ /* check if multipath is enabled and we have the capability */
+ if (!multipath || !ctrl->subsys || !(ctrl->subsys->cmic & (1 << 3)))
return 0;
ctrl->anacap = id->anacap;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 716a876119c8..2d678fb968c7 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -92,6 +92,11 @@ enum nvme_quirks {
* Broken Write Zeroes.
*/
NVME_QUIRK_DISABLE_WRITE_ZEROES = (1 << 9),
+
+ /*
+ * Force simple suspend/resume path.
+ */
+ NVME_QUIRK_SIMPLE_SUSPEND = (1 << 10),
};
/*
@@ -485,7 +490,14 @@ extern const struct attribute_group *nvme_ns_id_attr_groups[];
extern const struct block_device_operations nvme_ns_head_ops;
#ifdef CONFIG_NVME_MULTIPATH
-bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl);
+static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
+{
+ return ctrl->ana_log_buf != NULL;
+}
+
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys);
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
struct nvme_ctrl *ctrl, int *flags);
void nvme_failover_req(struct request *req);
@@ -496,7 +508,8 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head);
int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
void nvme_mpath_stop(struct nvme_ctrl *ctrl);
-void nvme_mpath_clear_current_path(struct nvme_ns *ns);
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl);
struct nvme_ns *nvme_find_path(struct nvme_ns_head *head);
static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -544,7 +557,11 @@ static inline void nvme_mpath_add_disk(struct nvme_ns *ns,
static inline void nvme_mpath_remove_disk(struct nvme_ns_head *head)
{
}
-static inline void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+static inline bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
+{
+ return false;
+}
+static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
{
}
static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -564,6 +581,15 @@ static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
static inline void nvme_mpath_stop(struct nvme_ctrl *ctrl)
{
}
+static inline void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+}
#endif /* CONFIG_NVME_MULTIPATH */
#ifdef CONFIG_NVM
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index bb970ca82517..732d5b63ec05 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2254,9 +2254,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
if (!dev->ctrl.tagset) {
dev->tagset.ops = &nvme_mq_ops;
dev->tagset.nr_hw_queues = dev->online_queues - 1;
- dev->tagset.nr_maps = 1; /* default */
- if (dev->io_queues[HCTX_TYPE_READ])
- dev->tagset.nr_maps++;
+ dev->tagset.nr_maps = 2; /* default + read */
if (dev->io_queues[HCTX_TYPE_POLL])
dev->tagset.nr_maps++;
dev->tagset.timeout = NVME_IO_TIMEOUT;
@@ -2697,7 +2695,7 @@ static void nvme_async_probe(void *data, async_cookie_t cookie)
{
struct nvme_dev *dev = data;
- nvme_reset_ctrl_sync(&dev->ctrl);
+ flush_work(&dev->ctrl.reset_work);
flush_work(&dev->ctrl.scan_work);
nvme_put_ctrl(&dev->ctrl);
}
@@ -2763,6 +2761,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
+ nvme_reset_ctrl(&dev->ctrl);
nvme_get_ctrl(&dev->ctrl);
async_schedule(nvme_async_probe, dev);
@@ -2848,7 +2847,7 @@ static int nvme_resume(struct device *dev)
struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
struct nvme_ctrl *ctrl = &ndev->ctrl;
- if (pm_resume_via_firmware() || !ctrl->npss ||
+ if (ndev->last_ps == U32_MAX ||
nvme_set_power_state(ctrl, ndev->last_ps) != 0)
nvme_reset_ctrl(ctrl);
return 0;
@@ -2861,6 +2860,8 @@ static int nvme_suspend(struct device *dev)
struct nvme_ctrl *ctrl = &ndev->ctrl;
int ret = -EBUSY;
+ ndev->last_ps = U32_MAX;
+
/*
* The platform does not remove power for a kernel managed suspend so
* use host managed nvme power settings for lowest idle power if
@@ -2868,8 +2869,15 @@ static int nvme_suspend(struct device *dev)
* shutdown. But if the firmware is involved after the suspend or the
* device does not support any non-default power states, shut down the
* device fully.
+ *
+ * If ASPM is not enabled for the device, shut down the device and allow
+ * the PCI bus layer to put it into D3 in order to take the PCIe link
+ * down, so as to allow the platform to achieve its minimum low-power
+ * state (which may not be possible if the link is up).
*/
- if (pm_suspend_via_firmware() || !ctrl->npss) {
+ if (pm_suspend_via_firmware() || !ctrl->npss ||
+ !pcie_aspm_enabled(pdev) ||
+ (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) {
nvme_dev_disable(ndev, true);
return 0;
}
@@ -2882,7 +2890,6 @@ static int nvme_suspend(struct device *dev)
ctrl->state != NVME_CTRL_ADMIN_ONLY)
goto unfreeze;
- ndev->last_ps = 0;
ret = nvme_get_power_state(ctrl, &ndev->last_ps);
if (ret < 0)
goto unfreeze;
@@ -3029,6 +3036,8 @@ static const struct pci_device_id nvme_id_table[] = {
.driver_data = NVME_QUIRK_LIGHTNVM, },
{ PCI_DEVICE(0x1d1d, 0x2601), /* CNEX Granby */
.driver_data = NVME_QUIRK_LIGHTNVM, },
+ { PCI_DEVICE(0x10ec, 0x5762), /* ADATA SX6000LNP */
+ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index a249db528d54..1a6449bc547b 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -562,13 +562,17 @@ out_destroy_cm_id:
return ret;
}
+static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
+{
+ rdma_disconnect(queue->cm_id);
+ ib_drain_qp(queue->qp);
+}
+
static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
{
if (!test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags))
return;
-
- rdma_disconnect(queue->cm_id);
- ib_drain_qp(queue->qp);
+ __nvme_rdma_stop_queue(queue);
}
static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
@@ -607,11 +611,13 @@ static int nvme_rdma_start_queue(struct nvme_rdma_ctrl *ctrl, int idx)
else
ret = nvmf_connect_admin_queue(&ctrl->ctrl);
- if (!ret)
+ if (!ret) {
set_bit(NVME_RDMA_Q_LIVE, &queue->flags);
- else
+ } else {
+ __nvme_rdma_stop_queue(queue);
dev_info(ctrl->ctrl.device,
"failed to connect queue: %d ret=%d\n", idx, ret);
+ }
return ret;
}
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index cd52b9f15376..98613a45bd3b 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -675,6 +675,7 @@ static void nvmet_port_subsys_drop_link(struct config_item *parent,
found:
list_del(&p->entry);
+ nvmet_port_del_ctrls(port, subsys);
nvmet_port_disc_changed(port, subsys);
if (list_empty(&port->subsystems))
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index dad0243c7c96..3a67e244e568 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -46,6 +46,9 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno)
u16 status;
switch (errno) {
+ case 0:
+ status = NVME_SC_SUCCESS;
+ break;
case -ENOSPC:
req->error_loc = offsetof(struct nvme_rw_command, length);
status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
@@ -280,6 +283,18 @@ void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops)
}
EXPORT_SYMBOL_GPL(nvmet_unregister_transport);
+void nvmet_port_del_ctrls(struct nvmet_port *port, struct nvmet_subsys *subsys)
+{
+ struct nvmet_ctrl *ctrl;
+
+ mutex_lock(&subsys->lock);
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+ if (ctrl->port == port)
+ ctrl->ops->delete_ctrl(ctrl);
+ }
+ mutex_unlock(&subsys->lock);
+}
+
int nvmet_enable_port(struct nvmet_port *port)
{
const struct nvmet_fabrics_ops *ops;
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index b16dc3981c69..0940c5024a34 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -654,6 +654,14 @@ static void nvme_loop_remove_port(struct nvmet_port *port)
mutex_lock(&nvme_loop_ports_mutex);
list_del_init(&port->entry);
mutex_unlock(&nvme_loop_ports_mutex);
+
+ /*
+ * Ensure any ctrls that are in the process of being
+ * deleted are in fact deleted before we return
+ * and free the port. This is to prevent active
+ * ctrls from using a port after it's freed.
+ */
+ flush_workqueue(nvme_delete_wq);
}
static const struct nvmet_fabrics_ops nvme_loop_ops = {
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 6ee66c610739..c51f8dd01dc4 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -418,6 +418,9 @@ void nvmet_port_send_ana_event(struct nvmet_port *port);
int nvmet_register_transport(const struct nvmet_fabrics_ops *ops);
void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops);
+void nvmet_port_del_ctrls(struct nvmet_port *port,
+ struct nvmet_subsys *subsys);
+
int nvmet_enable_port(struct nvmet_port *port);
void nvmet_disable_port(struct nvmet_port *port);
diff --git a/drivers/nvmem/nvmem-sysfs.c b/drivers/nvmem/nvmem-sysfs.c
index 6f303b91f6e7..9e0c429cd08a 100644
--- a/drivers/nvmem/nvmem-sysfs.c
+++ b/drivers/nvmem/nvmem-sysfs.c
@@ -224,10 +224,17 @@ int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
if (!config->base_dev)
return -EINVAL;
- if (nvmem->read_only)
- nvmem->eeprom = bin_attr_ro_root_nvmem;
- else
- nvmem->eeprom = bin_attr_rw_root_nvmem;
+ if (nvmem->read_only) {
+ if (config->root_only)
+ nvmem->eeprom = bin_attr_ro_root_nvmem;
+ else
+ nvmem->eeprom = bin_attr_ro_nvmem;
+ } else {
+ if (config->root_only)
+ nvmem->eeprom = bin_attr_rw_root_nvmem;
+ else
+ nvmem->eeprom = bin_attr_rw_nvmem;
+ }
nvmem->eeprom.attr.name = "eeprom";
nvmem->eeprom.size = nvmem->size;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 9cdf14b9aaab..223d617ecfe1 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -24,6 +24,7 @@
#include <linux/debugfs.h>
#include <linux/serial_core.h>
#include <linux/sysfs.h>
+#include <linux/random.h>
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#include <asm/page.h>
@@ -1044,6 +1045,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
{
int l;
const char *p;
+ const void *rng_seed;
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
@@ -1078,6 +1080,18 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
pr_debug("Command line is: %s\n", (char*)data);
+ rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l);
+ if (rng_seed && l > 0) {
+ add_bootloader_randomness(rng_seed, l);
+
+ /* try to clear seed so it won't be found. */
+ fdt_nop_property(initial_boot_params, node, "rng-seed");
+
+ /* update CRC check value */
+ of_fdt_crc32 = crc32_be(~0, initial_boot_params,
+ fdt_totalsize(initial_boot_params));
+ }
+
/* break now */
return 1;
}
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 7f84bb4903ca..a296eaf52a5b 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
* of_irq_parse_one - Resolve an interrupt for a device
* @device: the device whose interrupt is to be resolved
* @index: index of the interrupt to resolve
- * @out_irq: structure of_irq filled by this function
+ * @out_irq: structure of_phandle_args filled by this function
*
* This function resolves an interrupt for a node by walking the interrupt tree,
* finding which interrupt controller node it is attached to, and returning the
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index c1b67dd7cd6e..83c766233181 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -206,16 +206,22 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
for_each_child_of_node(local_fixups, child) {
for_each_child_of_node(overlay, overlay_child)
- if (!node_name_cmp(child, overlay_child))
+ if (!node_name_cmp(child, overlay_child)) {
+ of_node_put(overlay_child);
break;
+ }
- if (!overlay_child)
+ if (!overlay_child) {
+ of_node_put(child);
return -EINVAL;
+ }
err = adjust_local_phandle_references(child, overlay_child,
phandle_delta);
- if (err)
+ if (err) {
+ of_node_put(child);
return err;
+ }
}
return 0;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 3c730103e637..2f1cac89ddf5 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -6,7 +6,7 @@
** (c) Copyright 1999 SuSE GmbH
** (c) Copyright 1999,2000 Hewlett-Packard Company
** (c) Copyright 2000 Grant Grundler
-** (c) Copyright 2006 Helge Deller
+** (c) Copyright 2006-2019 Helge Deller
**
**
** This module provides access to Dino PCI bus (config/IOport spaces)
@@ -156,6 +156,15 @@ static inline struct dino_device *DINO_DEV(struct pci_hba_data *hba)
return container_of(hba, struct dino_device, hba);
}
+/* Check if PCI device is behind a Card-mode Dino. */
+static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
+{
+ struct dino_device *dino_dev;
+
+ dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
+ return is_card_dino(&dino_dev->hba.dev->id);
+}
+
/*
* Dino Configuration Space Accessor Functions
*/
@@ -437,6 +446,21 @@ static void quirk_cirrus_cardbus(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+#ifdef CONFIG_TULIP
+static void pci_fixup_tulip(struct pci_dev *dev)
+{
+ if (!pci_dev_is_behind_card_dino(dev))
+ return;
+ if (!(pci_resource_flags(dev, 1) & IORESOURCE_MEM))
+ return;
+ pr_warn("%s: HP HSC-PCI Cards with card-mode Dino not yet supported.\n",
+ pci_name(dev));
+ /* Disable this card by zeroing the PCI resources */
+ memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+ memset(&dev->resource[1], 0, sizeof(dev->resource[1]));
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_DEC, PCI_ANY_ID, pci_fixup_tulip);
+#endif /* CONFIG_TULIP */
static void __init
dino_bios_init(void)
@@ -863,14 +887,14 @@ static int __init dino_common_init(struct parisc_device *dev,
#define CUJO_RAVEN_BADPAGE 0x01003000UL
#define CUJO_FIREHAWK_BADPAGE 0x01607000UL
-static const char *dino_vers[] = {
+static const char dino_vers[][4] = {
"2.0",
"2.1",
"3.0",
"3.1"
};
-static const char *cujo_vers[] = {
+static const char cujo_vers[][4] = {
"1.0",
"2.0"
};
diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c
index 9c08222c0cc6..f54a6f450391 100644
--- a/drivers/parisc/eisa_enumerator.c
+++ b/drivers/parisc/eisa_enumerator.c
@@ -93,7 +93,7 @@ static int configure_memory(const unsigned char *buf,
res->start = mem_parent->start + get_24(buf+len+2);
res->end = res->start + get_16(buf+len+5)*1024;
res->flags = IORESOURCE_MEM;
- printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end);
+ pr_cont("memory %pR ", res);
result = request_resource(mem_parent, res);
if (result < 0) {
printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
@@ -123,7 +123,7 @@ static int configure_irq(const unsigned char *buf)
for (i=0;i<HPEE_IRQ_MAX_ENT;i++) {
c = get_8(buf+len);
- printk("IRQ %d ", c & HPEE_IRQ_CHANNEL_MASK);
+ pr_cont("IRQ %d ", c & HPEE_IRQ_CHANNEL_MASK);
if (c & HPEE_IRQ_TRIG_LEVEL) {
eisa_make_irq_level(c & HPEE_IRQ_CHANNEL_MASK);
} else {
@@ -153,7 +153,7 @@ static int configure_dma(const unsigned char *buf)
for (i=0;i<HPEE_DMA_MAX_ENT;i++) {
c = get_8(buf+len);
- printk("DMA %d ", c&HPEE_DMA_CHANNEL_MASK);
+ pr_cont("DMA %d ", c&HPEE_DMA_CHANNEL_MASK);
/* fixme: maybe initialize the dma channel withthe timing ? */
len+=2;
if (!(c & HPEE_DMA_MORE)) {
@@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent,
res->start = get_16(buf+len+1);
res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1;
res->flags = IORESOURCE_IO;
- printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end);
+ pr_cont("ioports %pR ", res);
result = request_resource(io_parent, res);
if (result < 0) {
printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
@@ -401,7 +401,7 @@ static int parse_slot_config(int slot,
}
pos = p0 + function_len;
}
- printk("\n");
+ pr_cont("\n");
if (!id_string_used) {
kfree(board);
}
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 44e12c83cfa8..e60e68664654 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -61,8 +61,6 @@ static int __init hppb_probe(struct parisc_device *dev)
}
card = card->next;
}
- printk(KERN_INFO "Found GeckoBoa at 0x%llx\n",
- (unsigned long long) dev->hpa.start);
card->hpa = dev->hpa.start;
card->mmio_region.name = "HP-PB Bus";
@@ -72,10 +70,11 @@ static int __init hppb_probe(struct parisc_device *dev)
card->mmio_region.end = gsc_readl(dev->hpa.start + IO_IO_HIGH) - 1;
status = ccio_request_resource(dev, &card->mmio_region);
- if(status < 0) {
- printk(KERN_ERR "%s: failed to claim HP-PB bus space (%pR)\n",
- __FILE__, &card->mmio_region);
- }
+
+ pr_info("Found GeckoBoa at %pap, bus space %pR,%s claimed.\n",
+ &dev->hpa.start,
+ &card->mmio_region,
+ (status < 0) ? " not":"" );
return 0;
}
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 40b625458afa..97056f3dd317 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev,
const struct hv_vmbus_device_id *dev_id)
{
struct hv_pcibus_device *hbus;
+ char *name;
int ret;
/*
@@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev,
goto free_config;
}
- hbus->sysdata.fwnode = irq_domain_alloc_fwnode(hbus);
+ name = kasprintf(GFP_KERNEL, "%pUL", &hdev->dev_instance);
+ if (!name) {
+ ret = -ENOMEM;
+ goto unmap;
+ }
+
+ hbus->sysdata.fwnode = irq_domain_alloc_named_fwnode(name);
+ kfree(name);
if (!hbus->sysdata.fwnode) {
ret = -ENOMEM;
goto unmap;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index e9f78eb390d2..e7b493c22bf3 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -147,15 +147,6 @@ config HOTPLUG_PCI_RPA_DLPAR
When in doubt, say N.
-config HOTPLUG_PCI_SGI
- tristate "SGI PCI Hotplug Support"
- depends on IA64_SGI_SN2 || IA64_GENERIC
- help
- Say Y here if you want to use the SGI Altix Hotplug
- Driver for PCI devices.
-
- When in doubt, say N.
-
config HOTPLUG_PCI_S390
bool "System z PCI Hotplug Support"
depends on S390 && 64BIT
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 7e3331603714..5196983220df 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -18,7 +18,6 @@ obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
obj-$(CONFIG_HOTPLUG_PCI_POWERNV) += pnv-php.o
obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
-obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
deleted file mode 100644
index 231f5bdd3d2d..000000000000
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ /dev/null
@@ -1,700 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved.
- *
- * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
- * Work to add BIOS PROM support was completed by Mike Habeck.
- */
-
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/pci_hotplug.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-
-#include <asm/sn/addrs.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/l1.h>
-#include <asm/sn/module.h>
-#include <asm/sn/pcibr_provider.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/sn_feature_sets.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/types.h>
-#include <asm/sn/acpi.h>
-
-#include "../pci.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
-MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
-
-
-/* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */
-#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
-#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
-#define PCI_L1_ERR 7 /* L1 console command error */
-#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
-
-
-#define PCIIO_ASIC_TYPE_TIOCA 4
-#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
-#define SN_MAX_HP_SLOTS 32 /* max hotplug slots */
-#define SN_SLOT_NAME_SIZE 33 /* size of name string */
-
-/* internal list head */
-static struct list_head sn_hp_list;
-
-/* hotplug_slot struct's private pointer */
-struct slot {
- int device_num;
- struct pci_bus *pci_bus;
- /* this struct for glue internal only */
- struct hotplug_slot hotplug_slot;
- struct list_head hp_list;
- char physical_path[SN_SLOT_NAME_SIZE];
-};
-
-struct pcibr_slot_enable_resp {
- int resp_sub_errno;
- char resp_l1_msg[PCI_L1_QSIZE + 1];
-};
-
-struct pcibr_slot_disable_resp {
- int resp_sub_errno;
- char resp_l1_msg[PCI_L1_QSIZE + 1];
-};
-
-enum sn_pci_req_e {
- PCI_REQ_SLOT_ELIGIBLE,
- PCI_REQ_SLOT_DISABLE
-};
-
-static int enable_slot(struct hotplug_slot *slot);
-static int disable_slot(struct hotplug_slot *slot);
-static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
-
-static const struct hotplug_slot_ops sn_hotplug_slot_ops = {
- .enable_slot = enable_slot,
- .disable_slot = disable_slot,
- .get_power_status = get_power_status,
-};
-
-static DEFINE_MUTEX(sn_hotplug_mutex);
-
-static struct slot *to_slot(struct hotplug_slot *bss_hotplug_slot)
-{
- return container_of(bss_hotplug_slot, struct slot, hotplug_slot);
-}
-
-static ssize_t path_show(struct pci_slot *pci_slot, char *buf)
-{
- int retval = -ENOENT;
- struct slot *slot = to_slot(pci_slot->hotplug);
-
- if (!slot)
- return retval;
-
- retval = sprintf(buf, "%s\n", slot->physical_path);
- return retval;
-}
-
-static struct pci_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
-
-static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
-{
- struct pcibus_info *pcibus_info;
- u16 busnum, segment, ioboard_type;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
-
- /* Check to see if this is a valid slot on 'pci_bus' */
- if (!(pcibus_info->pbi_valid_devices & (1 << device)))
- return -EPERM;
-
- ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
- busnum = pcibus_info->pbi_buscommon.bs_persist_busnum;
- segment = pci_domain_nr(pci_bus) & 0xf;
-
- /* Do not allow hotplug operations on base I/O cards */
- if ((ioboard_type == L1_BRICKTYPE_IX ||
- ioboard_type == L1_BRICKTYPE_IA) &&
- (segment == 1 && busnum == 0 && device != 1))
- return -EPERM;
-
- return 1;
-}
-
-static int sn_pci_bus_valid(struct pci_bus *pci_bus)
-{
- struct pcibus_info *pcibus_info;
- u32 asic_type;
- u16 ioboard_type;
-
- /* Don't register slots hanging off the TIOCA bus */
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
- asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
- if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
- return -EPERM;
-
- /* Only register slots in I/O Bricks that support hotplug */
- ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
- switch (ioboard_type) {
- case L1_BRICKTYPE_IX:
- case L1_BRICKTYPE_PX:
- case L1_BRICKTYPE_IA:
- case L1_BRICKTYPE_PA:
- case L1_BOARDTYPE_PCIX3SLOT:
- return 1;
- break;
- default:
- return -EPERM;
- break;
- }
-
- return -EIO;
-}
-
-static int sn_hp_slot_private_alloc(struct hotplug_slot **bss_hotplug_slot,
- struct pci_bus *pci_bus, int device,
- char *name)
-{
- struct pcibus_info *pcibus_info;
- struct slot *slot;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
-
- slot = kzalloc(sizeof(*slot), GFP_KERNEL);
- if (!slot)
- return -ENOMEM;
-
- slot->device_num = device;
- slot->pci_bus = pci_bus;
- sprintf(name, "%04x:%02x:%02x",
- pci_domain_nr(pci_bus),
- ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
- device + 1);
-
- sn_generate_path(pci_bus, slot->physical_path);
-
- list_add(&slot->hp_list, &sn_hp_list);
- *bss_hotplug_slot = &slot->hotplug_slot;
-
- return 0;
-}
-
-static struct hotplug_slot *sn_hp_destroy(void)
-{
- struct slot *slot;
- struct pci_slot *pci_slot;
- struct hotplug_slot *bss_hotplug_slot = NULL;
-
- list_for_each_entry(slot, &sn_hp_list, hp_list) {
- bss_hotplug_slot = &slot->hotplug_slot;
- pci_slot = bss_hotplug_slot->pci_slot;
- list_del(&slot->hp_list);
- sysfs_remove_file(&pci_slot->kobj,
- &sn_slot_path_attr.attr);
- break;
- }
- return bss_hotplug_slot;
-}
-
-static void sn_bus_free_data(struct pci_dev *dev)
-{
- struct pci_bus *subordinate_bus;
- struct pci_dev *child;
-
- /* Recursively clean up sn_irq_info structs */
- if (dev->subordinate) {
- subordinate_bus = dev->subordinate;
- list_for_each_entry(child, &subordinate_bus->devices, bus_list)
- sn_bus_free_data(child);
- }
- /*
- * Some drivers may use dma accesses during the
- * driver remove function. We release the sysdata
- * areas after the driver remove functions have
- * been called.
- */
- sn_bus_store_sysdata(dev);
- sn_pci_unfixup_slot(dev);
-}
-
-static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
- int device_num, char **ssdt)
-{
- struct slot *slot = to_slot(bss_hotplug_slot);
- struct pcibus_info *pcibus_info;
- struct pcibr_slot_enable_resp resp;
- int rc;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
-
- /*
- * Power-on and initialize the slot in the SN
- * PCI infrastructure.
- */
- rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp, ssdt);
-
-
- if (rc == PCI_SLOT_ALREADY_UP) {
- pci_dbg(slot->pci_bus->self, "is already active\n");
- return 1; /* return 1 to user */
- }
-
- if (rc == PCI_L1_ERR) {
- pci_dbg(slot->pci_bus->self, "L1 failure %d with message: %s",
- resp.resp_sub_errno, resp.resp_l1_msg);
- return -EPERM;
- }
-
- if (rc) {
- pci_dbg(slot->pci_bus->self, "insert failed with error %d sub-error %d\n",
- rc, resp.resp_sub_errno);
- return -EIO;
- }
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices |= (1 << device_num);
-
- return 0;
-}
-
-static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
- int device_num, int action)
-{
- struct slot *slot = to_slot(bss_hotplug_slot);
- struct pcibus_info *pcibus_info;
- struct pcibr_slot_disable_resp resp;
- int rc;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
-
- rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
-
- if ((action == PCI_REQ_SLOT_ELIGIBLE) &&
- (rc == PCI_SLOT_ALREADY_DOWN)) {
- pci_dbg(slot->pci_bus->self, "Slot %s already inactive\n", slot->physical_path);
- return 1; /* return 1 to user */
- }
-
- if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) {
- pci_dbg(slot->pci_bus->self, "Cannot remove last 33MHz card\n");
- return -EPERM;
- }
-
- if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) {
- pci_dbg(slot->pci_bus->self, "L1 failure %d with message \n%s\n",
- resp.resp_sub_errno, resp.resp_l1_msg);
- return -EPERM;
- }
-
- if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) {
- pci_dbg(slot->pci_bus->self, "remove failed with error %d sub-error %d\n",
- rc, resp.resp_sub_errno);
- return -EIO;
- }
-
- if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc)
- return 0;
-
- if ((action == PCI_REQ_SLOT_DISABLE) && !rc) {
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
- pci_dbg(slot->pci_bus->self, "remove successful\n");
- return 0;
- }
-
- if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
- pci_dbg(slot->pci_bus->self, "remove failed rc = %d\n", rc);
- }
-
- return rc;
-}
-
-/*
- * Power up and configure the slot via a SAL call to PROM.
- * Scan slot (and any children), do any platform specific fixup,
- * and find device driver.
- */
-static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
-{
- struct slot *slot = to_slot(bss_hotplug_slot);
- struct pci_bus *new_bus = NULL;
- struct pci_dev *dev;
- int num_funcs;
- int new_ppb = 0;
- int rc;
- char *ssdt = NULL;
- void pcibios_fixup_device_resources(struct pci_dev *);
-
- /* Serialize the Linux PCI infrastructure */
- mutex_lock(&sn_hotplug_mutex);
-
- /*
- * Power-on and initialize the slot in the SN
- * PCI infrastructure. Also, retrieve the ACPI SSDT
- * table for the slot (if ACPI capable PROM).
- */
- rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt);
- if (rc) {
- mutex_unlock(&sn_hotplug_mutex);
- return rc;
- }
-
- if (ssdt)
- ssdt = __va(ssdt);
- /* Add the new SSDT for the slot to the ACPI namespace */
- if (SN_ACPI_BASE_SUPPORT() && ssdt) {
- acpi_status ret;
-
- ret = acpi_load_table((struct acpi_table_header *)ssdt);
- if (ACPI_FAILURE(ret)) {
- printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
- __func__, ret);
- /* try to continue on */
- }
- }
-
- num_funcs = pci_scan_slot(slot->pci_bus,
- PCI_DEVFN(slot->device_num + 1, 0));
- if (!num_funcs) {
- pci_dbg(slot->pci_bus->self, "no device in slot\n");
- mutex_unlock(&sn_hotplug_mutex);
- return -ENODEV;
- }
-
- /*
- * Map SN resources for all functions on the card
- * to the Linux PCI interface and tell the drivers
- * about them.
- */
- list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
- if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
- continue;
-
- /* Need to do slot fixup on PPB before fixup of children
- * (PPB's pcidev_info needs to be in pcidev_info list
- * before child's SN_PCIDEV_INFO() call to setup
- * pdi_host_pcidev_info).
- */
- pcibios_fixup_device_resources(dev);
- if (SN_ACPI_BASE_SUPPORT())
- sn_acpi_slot_fixup(dev);
- else
- sn_io_slot_fixup(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_hp_add_bridge(dev);
- if (dev->subordinate) {
- new_bus = dev->subordinate;
- new_ppb = 1;
- }
- }
- }
-
- /*
- * Add the slot's devices to the ACPI infrastructure */
- if (SN_ACPI_BASE_SUPPORT() && ssdt) {
- unsigned long long adr;
- struct acpi_device *pdevice;
- acpi_handle phandle;
- acpi_handle chandle = NULL;
- acpi_handle rethandle;
- acpi_status ret;
-
- phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion);
-
- if (acpi_bus_get_device(phandle, &pdevice)) {
- pci_dbg(slot->pci_bus->self, "no parent device, assuming NULL\n");
- pdevice = NULL;
- }
-
- acpi_scan_lock_acquire();
- /*
- * Walk the rootbus node's immediate children looking for
- * the slot's device node(s). There can be more than
- * one for multifunction devices.
- */
- for (;;) {
- rethandle = NULL;
- ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
- phandle, chandle,
- &rethandle);
-
- if (ret == AE_NOT_FOUND || rethandle == NULL)
- break;
-
- chandle = rethandle;
-
- ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR,
- NULL, &adr);
-
- if (ACPI_SUCCESS(ret) &&
- (adr>>16) == (slot->device_num + 1)) {
-
- ret = acpi_bus_scan(chandle);
- if (ACPI_FAILURE(ret)) {
- printk(KERN_ERR "%s: acpi_bus_scan failed (0x%x) for slot %d func %d\n",
- __func__, ret, (int)(adr>>16),
- (int)(adr&0xffff));
- /* try to continue on */
- }
- }
- }
- acpi_scan_lock_release();
- }
-
- pci_lock_rescan_remove();
-
- /* Call the driver for the new device */
- pci_bus_add_devices(slot->pci_bus);
- /* Call the drivers for the new devices subordinate to PPB */
- if (new_ppb)
- pci_bus_add_devices(new_bus);
-
- pci_unlock_rescan_remove();
- mutex_unlock(&sn_hotplug_mutex);
-
- if (rc == 0)
- pci_dbg(slot->pci_bus->self, "insert operation successful\n");
- else
- pci_dbg(slot->pci_bus->self, "insert operation failed rc = %d\n", rc);
-
- return rc;
-}
-
-static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
-{
- struct slot *slot = to_slot(bss_hotplug_slot);
- struct pci_dev *dev, *temp;
- int rc;
- acpi_handle ssdt_hdl = NULL;
-
- /* Acquire update access to the bus */
- mutex_lock(&sn_hotplug_mutex);
-
- /* is it okay to bring this slot down? */
- rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
- PCI_REQ_SLOT_ELIGIBLE);
- if (rc)
- goto leaving;
-
- /* free the ACPI resources for the slot */
- if (SN_ACPI_BASE_SUPPORT() &&
- PCI_CONTROLLER(slot->pci_bus)->companion) {
- unsigned long long adr;
- struct acpi_device *device;
- acpi_handle phandle;
- acpi_handle chandle = NULL;
- acpi_handle rethandle;
- acpi_status ret;
-
- /* Get the rootbus node pointer */
- phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion);
-
- acpi_scan_lock_acquire();
- /*
- * Walk the rootbus node's immediate children looking for
- * the slot's device node(s). There can be more than
- * one for multifunction devices.
- */
- for (;;) {
- rethandle = NULL;
- ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
- phandle, chandle,
- &rethandle);
-
- if (ret == AE_NOT_FOUND || rethandle == NULL)
- break;
-
- chandle = rethandle;
-
- ret = acpi_evaluate_integer(chandle,
- METHOD_NAME__ADR,
- NULL, &adr);
- if (ACPI_SUCCESS(ret) &&
- (adr>>16) == (slot->device_num + 1)) {
- /* retain the owner id */
- ssdt_hdl = chandle;
-
- ret = acpi_bus_get_device(chandle,
- &device);
- if (ACPI_SUCCESS(ret))
- acpi_bus_trim(device);
- }
- }
- acpi_scan_lock_release();
- }
-
- pci_lock_rescan_remove();
- /* Free the SN resources assigned to the Linux device.*/
- list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
- if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
- continue;
-
- pci_dev_get(dev);
- sn_bus_free_data(dev);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- }
- pci_unlock_rescan_remove();
-
- /* Remove the SSDT for the slot from the ACPI namespace */
- if (SN_ACPI_BASE_SUPPORT() && ssdt_hdl) {
- acpi_status ret;
- ret = acpi_unload_parent_table(ssdt_hdl);
- if (ACPI_FAILURE(ret)) {
- acpi_handle_err(ssdt_hdl,
- "%s: acpi_unload_parent_table failed (0x%x)\n",
- __func__, ret);
- /* try to continue on */
- }
- }
-
- /* free the collected sysdata pointers */
- sn_bus_free_sysdata();
-
- /* Deactivate slot */
- rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
- PCI_REQ_SLOT_DISABLE);
- leaving:
- /* Release the bus lock */
- mutex_unlock(&sn_hotplug_mutex);
-
- return rc;
-}
-
-static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
- u8 *value)
-{
- struct slot *slot = to_slot(bss_hotplug_slot);
- struct pcibus_info *pcibus_info;
- u32 power;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- mutex_lock(&sn_hotplug_mutex);
- power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
- *value = power ? 1 : 0;
- mutex_unlock(&sn_hotplug_mutex);
- return 0;
-}
-
-static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
-{
- kfree(to_slot(bss_hotplug_slot));
-}
-
-static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
-{
- int device;
- struct pci_slot *pci_slot;
- struct hotplug_slot *bss_hotplug_slot;
- char name[SN_SLOT_NAME_SIZE];
- int rc = 0;
-
- /*
- * Currently only four devices are supported,
- * in the future there maybe more -- up to 32.
- */
-
- for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
- if (sn_pci_slot_valid(pci_bus, device) != 1)
- continue;
-
- if (sn_hp_slot_private_alloc(&bss_hotplug_slot,
- pci_bus, device, name)) {
- rc = -ENOMEM;
- goto alloc_err;
- }
- bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
-
- rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name);
- if (rc)
- goto register_err;
-
- pci_slot = bss_hotplug_slot->pci_slot;
- rc = sysfs_create_file(&pci_slot->kobj,
- &sn_slot_path_attr.attr);
- if (rc)
- goto alloc_err;
- }
- pci_dbg(pci_bus->self, "Registered bus with hotplug\n");
- return rc;
-
-register_err:
- pci_dbg(pci_bus->self, "bus failed to register with err = %d\n",
- rc);
-
- /* destroy THIS element */
- sn_hp_destroy();
- sn_release_slot(bss_hotplug_slot);
-
-alloc_err:
- /* destroy anything else on the list */
- while ((bss_hotplug_slot = sn_hp_destroy())) {
- pci_hp_deregister(bss_hotplug_slot);
- sn_release_slot(bss_hotplug_slot);
- }
-
- return rc;
-}
-
-static int __init sn_pci_hotplug_init(void)
-{
- struct pci_bus *pci_bus = NULL;
- int rc;
- int registered = 0;
-
- if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
- printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
- __func__);
- return -EPERM;
- }
-
- INIT_LIST_HEAD(&sn_hp_list);
-
- while ((pci_bus = pci_find_next_bus(pci_bus))) {
- if (!pci_bus->sysdata)
- continue;
-
- rc = sn_pci_bus_valid(pci_bus);
- if (rc != 1) {
- pci_dbg(pci_bus->self, "not a valid hotplug bus\n");
- continue;
- }
- pci_dbg(pci_bus->self, "valid hotplug bus\n");
-
- rc = sn_hotplug_slot_register(pci_bus);
- if (!rc) {
- registered = 1;
- } else {
- registered = 0;
- break;
- }
- }
-
- return registered == 1 ? 0 : -ENODEV;
-}
-
-static void __exit sn_pci_hotplug_exit(void)
-{
- struct hotplug_slot *bss_hotplug_slot;
-
- while ((bss_hotplug_slot = sn_hp_destroy())) {
- pci_hp_deregister(bss_hotplug_slot);
- sn_release_slot(bss_hotplug_slot);
- }
-
- if (!list_empty(&sn_hp_list))
- printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
-}
-
-module_init(sn_pci_hotplug_init);
-module_exit(sn_pci_hotplug_exit);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 29ed5ec1ac27..1b27b5af3d55 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1025,10 +1025,15 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
if (state == PCI_D0) {
pci_platform_power_transition(dev, PCI_D0);
/*
- * Mandatory power management transition delays are
- * handled in the PCIe portdrv resume hooks.
+ * Mandatory power management transition delays, see
+ * PCI Express Base Specification Revision 2.0 Section
+ * 6.6.1: Conventional Reset. Do not delay for
+ * devices powered on/off by corresponding bridge,
+ * because have already delayed for the bridge.
*/
if (dev->runtime_d3cold) {
+ if (dev->d3cold_delay && !dev->imm_ready)
+ msleep(dev->d3cold_delay);
/*
* When powering on a bridge from D3cold, the
* whole hierarchy may be powered on into
@@ -4602,16 +4607,14 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
}
-
/**
- * pcie_wait_for_link_delay - Wait until link is active or inactive
+ * pcie_wait_for_link - Wait until link is active or inactive
* @pdev: Bridge device
* @active: waiting for active or inactive?
- * @delay: Delay to wait after link has become active (in ms)
*
* Use this to wait till link becomes active or inactive.
*/
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
+bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
{
int timeout = 1000;
bool ret;
@@ -4648,25 +4651,13 @@ bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
timeout -= 10;
}
if (active && ret)
- msleep(delay);
+ msleep(100);
else if (ret != active)
pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
active ? "set" : "cleared");
return ret == active;
}
-/**
- * pcie_wait_for_link - Wait until link is active or inactive
- * @pdev: Bridge device
- * @active: waiting for active or inactive?
- *
- * Use this to wait till link becomes active or inactive.
- */
-bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
-{
- return pcie_wait_for_link_delay(pdev, active, 100);
-}
-
void pci_reset_secondary_bus(struct pci_dev *dev)
{
u16 ctrl;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 1be03a97cb92..d22d1b807701 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -497,7 +497,6 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state,
u32 service);
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay);
bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
#ifdef CONFIG_PCIEASPM
void pcie_aspm_init_link_state(struct pci_dev *pdev);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index e44af7f4d37f..464f8f92653f 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1170,6 +1170,26 @@ static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
NULL, 0644);
+/**
+ * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
+ * @pdev: Target device.
+ */
+bool pcie_aspm_enabled(struct pci_dev *pdev)
+{
+ struct pci_dev *bridge = pci_upstream_bridge(pdev);
+ bool ret;
+
+ if (!bridge)
+ return false;
+
+ mutex_lock(&aspm_lock);
+ ret = bridge->link_state ? !!bridge->link_state->aspm_enabled : false;
+ mutex_unlock(&aspm_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
+
#ifdef CONFIG_PCIEASPM_DEBUG
static ssize_t link_state_show(struct device *dev,
struct device_attribute *attr,
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 308c3e0c4a34..1b330129089f 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -379,67 +378,6 @@ static int pm_iter(struct device *dev, void *data)
return 0;
}
-static int get_downstream_delay(struct pci_bus *bus)
-{
- struct pci_dev *pdev;
- int min_delay = 100;
- int max_delay = 0;
-
- list_for_each_entry(pdev, &bus->devices, bus_list) {
- if (!pdev->imm_ready)
- min_delay = 0;
- else if (pdev->d3cold_delay < min_delay)
- min_delay = pdev->d3cold_delay;
- if (pdev->d3cold_delay > max_delay)
- max_delay = pdev->d3cold_delay;
- }
-
- return max(min_delay, max_delay);
-}
-
-/*
- * wait_for_downstream_link - Wait for downstream link to establish
- * @pdev: PCIe port whose downstream link is waited
- *
- * Handle delays according to PCIe 4.0 section 6.6.1 before configuration
- * access to the downstream component is permitted.
- *
- * This blocks PCI core resume of the hierarchy below this port until the
- * link is trained. Should be called before resuming port services to
- * prevent pciehp from starting to tear-down the hierarchy too soon.
- */
-static void wait_for_downstream_link(struct pci_dev *pdev)
-{
- int delay;
-
- if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
- pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
- return;
-
- if (pci_dev_is_disconnected(pdev))
- return;
-
- if (!pdev->subordinate || list_empty(&pdev->subordinate->devices) ||
- !pdev->bridge_d3)
- return;
-
- delay = get_downstream_delay(pdev->subordinate);
- if (!delay)
- return;
-
- dev_dbg(&pdev->dev, "waiting downstream link for %d ms\n", delay);
-
- /*
- * If downstream port does not support speeds greater than 5 GT/s
- * need to wait 100ms. For higher speeds (gen3) we need to wait
- * first for the data link layer to become active.
- */
- if (pcie_get_speed_cap(pdev) <= PCIE_SPEED_5_0GT)
- msleep(delay);
- else
- pcie_wait_for_link_delay(pdev, true, delay);
-}
-
/**
* pcie_port_device_suspend - suspend port services associated with a PCIe port
* @dev: PCI Express port to handle
@@ -453,8 +391,6 @@ int pcie_port_device_suspend(struct device *dev)
int pcie_port_device_resume_noirq(struct device *dev)
{
size_t off = offsetof(struct pcie_port_service_driver, resume_noirq);
-
- wait_for_downstream_link(to_pci_dev(dev));
return device_for_each_child(dev, &off, pm_iter);
}
@@ -485,8 +421,6 @@ int pcie_port_device_runtime_suspend(struct device *dev)
int pcie_port_device_runtime_resume(struct device *dev)
{
size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
-
- wait_for_downstream_link(to_pci_dev(dev));
return device_for_each_child(dev, &off, pm_iter);
}
#endif /* PM */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 208aacf39329..44c4ae1abd00 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -5256,7 +5256,7 @@ static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
*/
if (ioread32(map + 0x2240c) & 0x2) {
pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
- ret = pci_reset_function(pdev);
+ ret = pci_reset_bus(pdev);
if (ret < 0)
pci_err(pdev, "Failed to reset GPU: %d\n", ret);
}
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index eb6168e6ac43..590e594092f2 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -255,8 +255,10 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
switch (state->Vcc) {
case 50:
++v;
+ /* fall through */
case 33:
++v;
+ /* fall through */
case 0:
break;
default:
@@ -267,9 +269,11 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
switch (state->Vpp) {
case 12:
++p;
+ /* fall through */
case 33:
case 50:
++p;
+ /* fall through */
case 0:
break;
default:
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 2d06b8095a19..df352b334ea7 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -723,8 +723,8 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
cpu_pm_pmu_setup(armpmu, cmd);
break;
case CPU_PM_EXIT:
- cpu_pm_pmu_setup(armpmu, cmd);
case CPU_PM_ENTER_FAILED:
+ cpu_pm_pmu_setup(armpmu, cmd);
armpmu->start(armpmu);
break;
default:
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index da71c741cb46..abcf54f7d19c 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -113,8 +113,6 @@ struct smmu_pmu {
u64 counter_mask;
u32 options;
bool global_filter;
- u32 global_filter_span;
- u32 global_filter_sid;
};
#define to_smmu_pmu(p) (container_of(p, struct smmu_pmu, pmu))
@@ -260,6 +258,19 @@ static void smmu_pmu_set_event_filter(struct perf_event *event,
smmu_pmu_set_smr(smmu_pmu, idx, sid);
}
+static bool smmu_pmu_check_global_filter(struct perf_event *curr,
+ struct perf_event *new)
+{
+ if (get_filter_enable(new) != get_filter_enable(curr))
+ return false;
+
+ if (!get_filter_enable(new))
+ return true;
+
+ return get_filter_span(new) == get_filter_span(curr) &&
+ get_filter_stream_id(new) == get_filter_stream_id(curr);
+}
+
static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
struct perf_event *event, int idx)
{
@@ -279,17 +290,14 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
}
/* Requested settings same as current global settings*/
- if (span == smmu_pmu->global_filter_span &&
- sid == smmu_pmu->global_filter_sid)
+ idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
+ if (idx == num_ctrs ||
+ smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) {
+ smmu_pmu_set_event_filter(event, 0, span, sid);
return 0;
+ }
- if (!bitmap_empty(smmu_pmu->used_counters, num_ctrs))
- return -EAGAIN;
-
- smmu_pmu_set_event_filter(event, 0, span, sid);
- smmu_pmu->global_filter_span = span;
- smmu_pmu->global_filter_sid = sid;
- return 0;
+ return -EAGAIN;
}
static int smmu_pmu_get_event_idx(struct smmu_pmu *smmu_pmu,
@@ -312,6 +320,19 @@ static int smmu_pmu_get_event_idx(struct smmu_pmu *smmu_pmu,
return idx;
}
+static bool smmu_pmu_events_compatible(struct perf_event *curr,
+ struct perf_event *new)
+{
+ if (new->pmu != curr->pmu)
+ return false;
+
+ if (to_smmu_pmu(new->pmu)->global_filter &&
+ !smmu_pmu_check_global_filter(curr, new))
+ return false;
+
+ return true;
+}
+
/*
* Implementation of abstract pmu functionality required by
* the core perf events code.
@@ -323,6 +344,7 @@ static int smmu_pmu_event_init(struct perf_event *event)
struct smmu_pmu *smmu_pmu = to_smmu_pmu(event->pmu);
struct device *dev = smmu_pmu->dev;
struct perf_event *sibling;
+ int group_num_events = 1;
u16 event_id;
if (event->attr.type != event->pmu->type)
@@ -347,18 +369,23 @@ static int smmu_pmu_event_init(struct perf_event *event)
}
/* Don't allow groups with mixed PMUs, except for s/w events */
- if (event->group_leader->pmu != event->pmu &&
- !is_software_event(event->group_leader)) {
- dev_dbg(dev, "Can't create mixed PMU group\n");
- return -EINVAL;
+ if (!is_software_event(event->group_leader)) {
+ if (!smmu_pmu_events_compatible(event->group_leader, event))
+ return -EINVAL;
+
+ if (++group_num_events > smmu_pmu->num_counters)
+ return -EINVAL;
}
for_each_sibling_event(sibling, event->group_leader) {
- if (sibling->pmu != event->pmu &&
- !is_software_event(sibling)) {
- dev_dbg(dev, "Can't create mixed PMU group\n");
+ if (is_software_event(sibling))
+ continue;
+
+ if (!smmu_pmu_events_compatible(sibling, event))
+ return -EINVAL;
+
+ if (++group_num_events > smmu_pmu->num_counters)
return -EINVAL;
- }
}
hwc->idx = -1;
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
index 63fe21600072..ce7345745b42 100644
--- a/drivers/perf/fsl_imx8_ddr_perf.c
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
@@ -35,6 +35,8 @@
#define EVENT_CYCLES_COUNTER 0
#define NUM_COUNTERS 4
+#define AXI_MASKING_REVERT 0xffff0000 /* AXI_MASKING(MSB 16bits) + AXI_ID(LSB 16bits) */
+
#define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu)
#define DDR_PERF_DEV_NAME "imx8_ddr"
@@ -42,11 +44,25 @@
static DEFINE_IDA(ddr_ida);
+/* DDR Perf hardware feature */
+#define DDR_CAP_AXI_ID_FILTER 0x1 /* support AXI ID filter */
+
+struct fsl_ddr_devtype_data {
+ unsigned int quirks; /* quirks needed for different DDR Perf core */
+};
+
+static const struct fsl_ddr_devtype_data imx8_devtype_data;
+
+static const struct fsl_ddr_devtype_data imx8m_devtype_data = {
+ .quirks = DDR_CAP_AXI_ID_FILTER,
+};
+
static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
- { .compatible = "fsl,imx8-ddr-pmu",},
- { .compatible = "fsl,imx8m-ddr-pmu",},
+ { .compatible = "fsl,imx8-ddr-pmu", .data = &imx8_devtype_data},
+ { .compatible = "fsl,imx8m-ddr-pmu", .data = &imx8m_devtype_data},
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids);
struct ddr_pmu {
struct pmu pmu;
@@ -57,6 +73,7 @@ struct ddr_pmu {
struct perf_event *events[NUM_COUNTERS];
int active_events;
enum cpuhp_state cpuhp_state;
+ const struct fsl_ddr_devtype_data *devtype_data;
int irq;
int id;
};
@@ -128,6 +145,8 @@ static struct attribute *ddr_perf_events_attrs[] = {
IMX8_DDR_PMU_EVENT_ATTR(refresh, 0x37),
IMX8_DDR_PMU_EVENT_ATTR(write, 0x38),
IMX8_DDR_PMU_EVENT_ATTR(raw-hazard, 0x39),
+ IMX8_DDR_PMU_EVENT_ATTR(axid-read, 0x41),
+ IMX8_DDR_PMU_EVENT_ATTR(axid-write, 0x42),
NULL,
};
@@ -137,9 +156,13 @@ static struct attribute_group ddr_perf_events_attr_group = {
};
PMU_FORMAT_ATTR(event, "config:0-7");
+PMU_FORMAT_ATTR(axi_id, "config1:0-15");
+PMU_FORMAT_ATTR(axi_mask, "config1:16-31");
static struct attribute *ddr_perf_format_attrs[] = {
&format_attr_event.attr,
+ &format_attr_axi_id.attr,
+ &format_attr_axi_mask.attr,
NULL,
};
@@ -189,6 +212,26 @@ static u32 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter)
return readl_relaxed(pmu->base + COUNTER_READ + counter * 4);
}
+static bool ddr_perf_is_filtered(struct perf_event *event)
+{
+ return event->attr.config == 0x41 || event->attr.config == 0x42;
+}
+
+static u32 ddr_perf_filter_val(struct perf_event *event)
+{
+ return event->attr.config1;
+}
+
+static bool ddr_perf_filters_compatible(struct perf_event *a,
+ struct perf_event *b)
+{
+ if (!ddr_perf_is_filtered(a))
+ return true;
+ if (!ddr_perf_is_filtered(b))
+ return true;
+ return ddr_perf_filter_val(a) == ddr_perf_filter_val(b);
+}
+
static int ddr_perf_event_init(struct perf_event *event)
{
struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
@@ -215,6 +258,15 @@ static int ddr_perf_event_init(struct perf_event *event)
!is_software_event(event->group_leader))
return -EINVAL;
+ if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER) {
+ if (!ddr_perf_filters_compatible(event, event->group_leader))
+ return -EINVAL;
+ for_each_sibling_event(sibling, event->group_leader) {
+ if (!ddr_perf_filters_compatible(event, sibling))
+ return -EINVAL;
+ }
+ }
+
for_each_sibling_event(sibling, event->group_leader) {
if (sibling->pmu != event->pmu &&
!is_software_event(sibling))
@@ -287,6 +339,23 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
struct hw_perf_event *hwc = &event->hw;
int counter;
int cfg = event->attr.config;
+ int cfg1 = event->attr.config1;
+
+ if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER) {
+ int i;
+
+ for (i = 1; i < NUM_COUNTERS; i++) {
+ if (pmu->events[i] &&
+ !ddr_perf_filters_compatible(event, pmu->events[i]))
+ return -EINVAL;
+ }
+
+ if (ddr_perf_is_filtered(event)) {
+ /* revert axi id masking(axi_mask) value */
+ cfg1 ^= AXI_MASKING_REVERT;
+ writel(cfg1, pmu->base + COUNTER_DPCR1);
+ }
+ }
counter = ddr_perf_alloc_counter(pmu, cfg);
if (counter < 0) {
@@ -472,6 +541,8 @@ static int ddr_perf_probe(struct platform_device *pdev)
if (!name)
return -ENOMEM;
+ pmu->devtype_data = of_device_get_match_data(&pdev->dev);
+
pmu->cpu = raw_smp_processor_id();
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
DDR_CPUHP_CB_NAME,
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 6ad0823bcf23..e42d4464c2cf 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -217,10 +217,8 @@ static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu,
/* Read and init IRQ */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "DDRC PMU get irq fail; irq:%d\n", irq);
+ if (irq < 0)
return irq;
- }
ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr,
IRQF_NOBALANCING | IRQF_NO_THREAD,
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 4f2917f3e25e..f28063873e11 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -207,10 +207,8 @@ static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu,
/* Read and init IRQ */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "HHA PMU get irq fail; irq:%d\n", irq);
+ if (irq < 0)
return irq;
- }
ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr,
IRQF_NOBALANCING | IRQF_NO_THREAD,
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 9153e093f9df..078b8dc57250 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -206,10 +206,8 @@ static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu,
/* Read and init IRQ */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "L3C PMU get irq fail; irq:%d\n", irq);
+ if (irq < 0)
return irq;
- }
ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr,
IRQF_NOBALANCING | IRQF_NO_THREAD,
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index d06182fe14b8..21d6991dbe0b 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -909,12 +909,8 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data)
cluster->cluster_id = fw_cluster_id;
irq = platform_get_irq(sdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev,
- "Failed to get valid irq for cluster %ld\n",
- fw_cluster_id);
+ if (irq < 0)
return irq;
- }
irq_set_status_flags(irq, IRQ_NOAUTOEN);
cluster->irq = irq;
diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
index 3259e2ebeb39..7e328d6385c3 100644
--- a/drivers/perf/xgene_pmu.c
+++ b/drivers/perf/xgene_pmu.c
@@ -1901,10 +1901,8 @@ static int xgene_pmu_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "No IRQ resource\n");
+ if (irq < 0)
return -EINVAL;
- }
rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr,
IRQF_NOBALANCING | IRQF_NO_THREAD,
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
index 384396cbb22d..22256576b69a 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
@@ -2412,7 +2412,7 @@ static const struct aspeed_pin_config aspeed_g4_configs[] = {
{ PIN_CONFIG_INPUT_DEBOUNCE, { C14, B14 }, SCUA8, 27 },
};
-static int aspeed_g4_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g4_sig_expr_set(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr,
bool enable)
{
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index 053101f795a2..ff84d1afd229 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -2507,6 +2507,88 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
{ PIN_CONFIG_INPUT_DEBOUNCE, { A20, B19 }, SCUA8, 27 },
};
+static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx,
+ int ip)
+{
+ if (ip == ASPEED_IP_SCU) {
+ WARN(!ctx->maps[ip], "Missing SCU syscon!");
+ return ctx->maps[ip];
+ }
+
+ if (ip >= ASPEED_NR_PINMUX_IPS)
+ return ERR_PTR(-EINVAL);
+
+ if (likely(ctx->maps[ip]))
+ return ctx->maps[ip];
+
+ if (ip == ASPEED_IP_GFX) {
+ struct device_node *node;
+ struct regmap *map;
+
+ node = of_parse_phandle(ctx->dev->of_node,
+ "aspeed,external-nodes", 0);
+ if (node) {
+ map = syscon_node_to_regmap(node);
+ of_node_put(node);
+ if (IS_ERR(map))
+ return map;
+ } else
+ return ERR_PTR(-ENODEV);
+
+ ctx->maps[ASPEED_IP_GFX] = map;
+ dev_dbg(ctx->dev, "Acquired GFX regmap");
+ return map;
+ }
+
+ if (ip == ASPEED_IP_LPC) {
+ struct device_node *node;
+ struct regmap *map;
+
+ node = of_parse_phandle(ctx->dev->of_node,
+ "aspeed,external-nodes", 1);
+ if (node) {
+ map = syscon_node_to_regmap(node->parent);
+ of_node_put(node);
+ if (IS_ERR(map))
+ return map;
+ } else
+ return ERR_PTR(-ENODEV);
+
+ ctx->maps[ASPEED_IP_LPC] = map;
+ dev_dbg(ctx->dev, "Acquired LPC regmap");
+ return map;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int aspeed_g5_sig_expr_eval(struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr,
+ bool enabled)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < expr->ndescs; i++) {
+ const struct aspeed_sig_desc *desc = &expr->descs[i];
+ struct regmap *map;
+
+ map = aspeed_g5_acquire_regmap(ctx, desc->ip);
+ if (IS_ERR(map)) {
+ dev_err(ctx->dev,
+ "Failed to acquire regmap for IP block %d\n",
+ desc->ip);
+ return PTR_ERR(map);
+ }
+
+ ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
+ if (ret <= 0)
+ return ret;
+ }
+
+ return 1;
+}
+
/**
* Configure a pin's signal by applying an expression's descriptor state for
* all descriptors in the expression.
@@ -2520,7 +2602,7 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
* Return: 0 if the expression is configured as requested and a negative error
* code otherwise
*/
-static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr,
bool enable)
{
@@ -2531,9 +2613,15 @@ static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_desc *desc = &expr->descs[i];
u32 pattern = enable ? desc->enable : desc->disable;
u32 val = (pattern << __ffs(desc->mask));
+ struct regmap *map;
- if (!ctx->maps[desc->ip])
- return -ENODEV;
+ map = aspeed_g5_acquire_regmap(ctx, desc->ip);
+ if (IS_ERR(map)) {
+ dev_err(ctx->dev,
+ "Failed to acquire regmap for IP block %d\n",
+ desc->ip);
+ return PTR_ERR(map);
+ }
/*
* Strap registers are configured in hardware or by early-boot
@@ -2586,6 +2674,7 @@ static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
}
static const struct aspeed_pinmux_ops aspeed_g5_ops = {
+ .eval = aspeed_g5_sig_expr_eval,
.set = aspeed_g5_sig_expr_set,
};
@@ -2641,34 +2730,11 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
{
int i;
- struct regmap *map;
- struct device_node *node;
for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
aspeed_g5_pins[i].number = i;
- node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
- map = syscon_node_to_regmap(node);
- of_node_put(node);
- if (IS_ERR(map)) {
- dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
- map = NULL;
- }
- aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_GFX] = map;
-
- node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
- if (node) {
- map = syscon_node_to_regmap(node->parent);
- if (IS_ERR(map)) {
- dev_warn(&pdev->dev, "LHC parent is not a syscon, some mux configurations may fail\n");
- map = NULL;
- }
- } else {
- dev_warn(&pdev->dev, "No LHC phandle found, some mux configurations may fail\n");
- map = NULL;
- }
- of_node_put(node);
- aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_LPC] = map;
+ aspeed_g5_pinctrl_data.pinmux.dev = &pdev->dev;
return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
&aspeed_g5_pinctrl_data);
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 535db3de490b..54933665b5f8 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -71,7 +71,7 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_enable(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr)
{
int ret;
@@ -86,7 +86,7 @@ static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
return 0;
}
-static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_disable(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr)
{
int ret;
@@ -109,7 +109,7 @@ static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
*
* Return: 0 if all expressions are disabled, otherwise a negative error code
*/
-static int aspeed_disable_sig(const struct aspeed_pinmux_data *ctx,
+static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr **exprs)
{
int ret = 0;
@@ -217,8 +217,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
{
int i;
int ret;
- const struct aspeed_pinctrl_data *pdata =
- pinctrl_dev_get_drvdata(pctldev);
+ struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
const struct aspeed_pin_function *pfunc =
&pdata->pinmux.functions[function];
@@ -306,8 +305,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
unsigned int offset)
{
int ret;
- const struct aspeed_pinctrl_data *pdata =
- pinctrl_dev_get_drvdata(pctldev);
+ struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
const struct aspeed_sig_expr ***prios, **funcs, *expr;
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.c b/drivers/pinctrl/aspeed/pinmux-aspeed.c
index 5b0fe178ccf2..57305ca838a7 100644
--- a/drivers/pinctrl/aspeed/pinmux-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.c
@@ -5,7 +5,7 @@
#include "pinmux-aspeed.h"
-const char *const aspeed_pinmux_ips[] = {
+static const char *const aspeed_pinmux_ips[] = {
[ASPEED_IP_SCU] = "SCU",
[ASPEED_IP_GFX] = "GFX",
[ASPEED_IP_LPC] = "LPC",
@@ -78,11 +78,14 @@ int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
* neither the enabled nor disabled state. Thus we must explicitly test for
* either condition as required.
*/
-int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
+int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr, bool enabled)
{
- int i;
int ret;
+ int i;
+
+ if (ctx->ops->eval)
+ return ctx->ops->eval(ctx, expr, enabled);
for (i = 0; i < expr->ndescs; i++) {
const struct aspeed_sig_desc *desc = &expr->descs[i];
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h
index 329d54d48667..db3457c86f48 100644
--- a/drivers/pinctrl/aspeed/pinmux-aspeed.h
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h
@@ -702,11 +702,14 @@ struct aspeed_pin_function {
struct aspeed_pinmux_data;
struct aspeed_pinmux_ops {
- int (*set)(const struct aspeed_pinmux_data *ctx,
+ int (*eval)(struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr, bool enabled);
+ int (*set)(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr, bool enabled);
};
struct aspeed_pinmux_data {
+ struct device *dev;
struct regmap *maps[ASPEED_NR_PINMUX_IPS];
const struct aspeed_pinmux_ops *ops;
@@ -721,11 +724,10 @@ struct aspeed_pinmux_data {
int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, bool enabled,
struct regmap *map);
-int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
- const struct aspeed_sig_expr *expr,
- bool enabled);
+int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr, bool enabled);
-static inline int aspeed_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static inline int aspeed_sig_expr_set(struct aspeed_pinmux_data *ctx,
const struct aspeed_sig_expr *expr,
bool enabled)
{
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index e5a112a8e067..297b7b5fcb28 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
chip->irq_eoi(data);
}
+static void byt_init_irq_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ /*
+ * FIXME: currently the valid_mask is filled in as part of
+ * initializing the irq_chip below in byt_gpio_irq_init_hw().
+ * when converting this driver to the new way of passing the
+ * gpio_irq_chip along when adding the gpio_chip, move the
+ * mask initialization into this callback instead. Right now
+ * this callback is here to make sure the mask gets allocated.
+ */
+}
+
static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
{
struct gpio_chip *gc = &vg->chip;
@@ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
gc->can_sleep = false;
gc->parent = &vg->pdev->dev;
gc->ngpio = vg->soc_data->npins;
- gc->irq.need_valid_mask = true;
+ gc->irq.init_valid_mask = byt_init_irq_valid_mask;
#ifdef CONFIG_PM_SLEEP
vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 03ec7a5d9d0b..ab681d1a3a74 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1543,6 +1543,30 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
{}
};
+static void chv_init_irq_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
+ const struct chv_community *community = pctrl->community;
+ int i;
+
+ /* Do not add GPIOs that can only generate GPEs to the IRQ domain */
+ for (i = 0; i < community->npins; i++) {
+ const struct pinctrl_pin_desc *desc;
+ u32 intsel;
+
+ desc = &community->pins[i];
+
+ intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
+ intsel &= CHV_PADCTRL0_INTSEL_MASK;
+ intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
+
+ if (intsel >= community->nirqs)
+ clear_bit(i, valid_mask);
+ }
+}
+
static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
{
const struct chv_gpio_pinrange *range;
@@ -1557,7 +1581,8 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
chip->label = dev_name(pctrl->dev);
chip->parent = pctrl->dev;
chip->base = -1;
- chip->irq.need_valid_mask = need_valid_mask;
+ if (need_valid_mask)
+ chip->irq.init_valid_mask = chv_init_irq_valid_mask;
ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
if (ret) {
@@ -1576,21 +1601,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
}
}
- /* Do not add GPIOs that can only generate GPEs to the IRQ domain */
- for (i = 0; i < community->npins; i++) {
- const struct pinctrl_pin_desc *desc;
- u32 intsel;
-
- desc = &community->pins[i];
-
- intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
- intsel &= CHV_PADCTRL0_INTSEL_MASK;
- intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
-
- if (need_valid_mask && intsel >= community->nirqs)
- clear_bit(i, chip->irq.valid_mask);
- }
-
/*
* The same set of machines in chv_no_valid_mask[] have incorrectly
* configured GPIOs that generate spurious interrupts so we use
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index d3332da35637..dd5aa9a2dfe5 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -585,12 +585,24 @@ static int stmfx_pinctrl_gpio_function_enable(struct stmfx_pinctrl *pctl)
return stmfx_function_enable(pctl->stmfx, func);
}
+static int stmfx_pinctrl_gpio_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+ u32 n;
+
+ for_each_clear_bit(n, &pctl->gpio_valid_mask, ngpios)
+ clear_bit(n, valid_mask);
+
+ return 0;
+}
+
static int stmfx_pinctrl_probe(struct platform_device *pdev)
{
struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node;
struct stmfx_pinctrl *pctl;
- u32 n;
int irq, ret;
pctl = devm_kzalloc(stmfx->dev, sizeof(*pctl), GFP_KERNEL);
@@ -650,7 +662,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
pctl->gpio_chip.ngpio = pctl->pctl_desc.npins;
pctl->gpio_chip.can_sleep = true;
pctl->gpio_chip.of_node = np;
- pctl->gpio_chip.need_valid_mask = true;
+ pctl->gpio_chip.init_valid_mask = stmfx_pinctrl_gpio_init_valid_mask;
ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl);
if (ret) {
@@ -668,8 +680,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
pctl->irq_chip.irq_set_type = stmfx_pinctrl_irq_set_type;
pctl->irq_chip.irq_bus_lock = stmfx_pinctrl_irq_bus_lock;
pctl->irq_chip.irq_bus_sync_unlock = stmfx_pinctrl_irq_bus_sync_unlock;
- for_each_clear_bit(n, &pctl->gpio_valid_mask, pctl->gpio_chip.ngpio)
- clear_bit(n, pctl->gpio_chip.valid_mask);
ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip,
0, handle_bad_irq, IRQ_TYPE_NONE);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 8e14a5f2e970..fa2c87821401 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -138,6 +138,7 @@ config PINCTRL_QCOM_SPMI_PMIC
select PINMUX
select PINCONF
select GENERIC_PINCONF
+ select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 7f35c196bb3e..b8a1c43222f8 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -593,24 +593,25 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define msm_gpio_dbg_show NULL
#endif
-static int msm_gpio_init_valid_mask(struct gpio_chip *chip)
+static int msm_gpio_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
{
- struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
int ret;
unsigned int len, i;
- unsigned int max_gpios = pctrl->soc->ngpios;
const int *reserved = pctrl->soc->reserved_gpios;
u16 *tmp;
/* Driver provided reserved list overrides DT and ACPI */
if (reserved) {
- bitmap_fill(chip->valid_mask, max_gpios);
+ bitmap_fill(valid_mask, ngpios);
for (i = 0; reserved[i] >= 0; i++) {
- if (i >= max_gpios || reserved[i] >= max_gpios) {
+ if (i >= ngpios || reserved[i] >= ngpios) {
dev_err(pctrl->dev, "invalid list of reserved GPIOs\n");
return -EINVAL;
}
- clear_bit(reserved[i], chip->valid_mask);
+ clear_bit(reserved[i], valid_mask);
}
return 0;
@@ -622,7 +623,7 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip)
if (ret < 0)
return 0;
- if (ret > max_gpios)
+ if (ret > ngpios)
return -EINVAL;
tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL);
@@ -635,9 +636,9 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip)
goto out;
}
- bitmap_zero(chip->valid_mask, max_gpios);
+ bitmap_zero(valid_mask, ngpios);
for (i = 0; i < len; i++)
- set_bit(tmp[i], chip->valid_mask);
+ set_bit(tmp[i], valid_mask);
out:
kfree(tmp);
@@ -653,7 +654,6 @@ static const struct gpio_chip msm_gpio_template = {
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.dbg_show = msm_gpio_dbg_show,
- .init_valid_mask = msm_gpio_init_valid_mask,
};
/* For dual-edge interrupts in software, since some hardware has no
@@ -1015,7 +1015,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
chip->parent = pctrl->dev;
chip->owner = THIS_MODULE;
chip->of_node = pctrl->dev->of_node;
- chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
+ if (msm_gpio_needs_valid_mask(pctrl))
+ chip->init_valid_mask = msm_gpio_init_valid_mask;
pctrl->irq_chip.name = "msmgpio";
pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index f39da87ea185..442db15e0729 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -170,8 +170,6 @@ struct pmic_gpio_state {
struct regmap *map;
struct pinctrl_dev *ctrl;
struct gpio_chip chip;
- struct fwnode_handle *fwnode;
- struct irq_domain *domain;
};
static const struct pinconf_generic_params pmic_gpio_bindings[] = {
@@ -751,23 +749,6 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip,
return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
}
-static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
-{
- struct pmic_gpio_state *state = gpiochip_get_data(chip);
- struct irq_fwspec fwspec;
-
- fwspec.fwnode = state->fwnode;
- fwspec.param_count = 2;
- fwspec.param[0] = pin + PMIC_GPIO_PHYSICAL_OFFSET;
- /*
- * Set the type to a safe value temporarily. This will be overwritten
- * later with the proper value by irq_set_type.
- */
- fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
-
- return irq_create_fwspec_mapping(&fwspec);
-}
-
static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct pmic_gpio_state *state = gpiochip_get_data(chip);
@@ -787,7 +768,6 @@ static const struct gpio_chip pmic_gpio_gpio_template = {
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.of_xlate = pmic_gpio_of_xlate,
- .to_irq = pmic_gpio_to_irq,
.dbg_show = pmic_gpio_dbg_show,
};
@@ -964,46 +944,24 @@ static int pmic_gpio_domain_translate(struct irq_domain *domain,
return 0;
}
-static int pmic_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs, void *data)
+static unsigned int pmic_gpio_child_offset_to_irq(struct gpio_chip *chip,
+ unsigned int offset)
{
- struct pmic_gpio_state *state = container_of(domain->host_data,
- struct pmic_gpio_state,
- chip);
- struct irq_fwspec *fwspec = data;
- struct irq_fwspec parent_fwspec;
- irq_hw_number_t hwirq;
- unsigned int type;
- int ret, i;
-
- ret = pmic_gpio_domain_translate(domain, fwspec, &hwirq, &type);
- if (ret)
- return ret;
-
- for (i = 0; i < nr_irqs; i++)
- irq_domain_set_info(domain, virq + i, hwirq + i,
- &pmic_gpio_irq_chip, state,
- handle_level_irq, NULL, NULL);
+ return offset + PMIC_GPIO_PHYSICAL_OFFSET;
+}
- parent_fwspec.fwnode = domain->parent->fwnode;
- parent_fwspec.param_count = 4;
- parent_fwspec.param[0] = 0;
- parent_fwspec.param[1] = hwirq + 0xc0;
- parent_fwspec.param[2] = 0;
- parent_fwspec.param[3] = fwspec->param[1];
+static int pmic_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
+ unsigned int child_hwirq,
+ unsigned int child_type,
+ unsigned int *parent_hwirq,
+ unsigned int *parent_type)
+{
+ *parent_hwirq = child_hwirq + 0xc0;
+ *parent_type = child_type;
- return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
- &parent_fwspec);
+ return 0;
}
-static const struct irq_domain_ops pmic_gpio_domain_ops = {
- .activate = gpiochip_irq_domain_activate,
- .alloc = pmic_gpio_domain_alloc,
- .deactivate = gpiochip_irq_domain_deactivate,
- .free = irq_domain_free_irqs_common,
- .translate = pmic_gpio_domain_translate,
-};
-
static int pmic_gpio_probe(struct platform_device *pdev)
{
struct irq_domain *parent_domain;
@@ -1013,6 +971,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
struct pinctrl_desc *pctrldesc;
struct pmic_gpio_pad *pad, *pads;
struct pmic_gpio_state *state;
+ struct gpio_irq_chip *girq;
int ret, npins, i;
u32 reg;
@@ -1092,19 +1051,21 @@ static int pmic_gpio_probe(struct platform_device *pdev)
if (!parent_domain)
return -ENXIO;
- state->fwnode = of_node_to_fwnode(state->dev->of_node);
- state->domain = irq_domain_create_hierarchy(parent_domain, 0,
- state->chip.ngpio,
- state->fwnode,
- &pmic_gpio_domain_ops,
- &state->chip);
- if (!state->domain)
- return -ENODEV;
+ girq = &state->chip.irq;
+ girq->chip = &pmic_gpio_irq_chip;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
+ girq->fwnode = of_node_to_fwnode(state->dev->of_node);
+ girq->parent_domain = parent_domain;
+ girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq;
+ girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell;
+ girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq;
+ girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate;
ret = gpiochip_add_data(&state->chip, state);
if (ret) {
dev_err(state->dev, "can't add gpio chip\n");
- goto err_chip_add_data;
+ return ret;
}
/*
@@ -1130,8 +1091,6 @@ static int pmic_gpio_probe(struct platform_device *pdev)
err_range:
gpiochip_remove(&state->chip);
-err_chip_add_data:
- irq_domain_remove(state->domain);
return ret;
}
@@ -1140,7 +1099,6 @@ static int pmic_gpio_remove(struct platform_device *pdev)
struct pmic_gpio_state *state = platform_get_drvdata(pdev);
gpiochip_remove(&state->chip);
- irq_domain_remove(state->domain);
return 0;
}
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c
index e504d255d5ce..430731cdf827 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -707,7 +707,7 @@ static int cros_ec_ishtp_reset(struct ishtp_cl_device *cl_device)
*/
static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
{
- struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+ struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
@@ -722,7 +722,7 @@ static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
*/
static int __maybe_unused cros_ec_ishtp_resume(struct device *device)
{
- struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+ struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c
index 006a8ff64057..714306bc3f79 100644
--- a/drivers/platform/chrome/cros_ec_spi.c
+++ b/drivers/platform/chrome/cros_ec_spi.c
@@ -706,7 +706,7 @@ static int cros_ec_spi_devm_high_pri_alloc(struct device *dev,
struct cros_ec_spi *ec_spi)
{
struct sched_param sched_priority = {
- .sched_priority = MAX_RT_PRIO - 1,
+ .sched_priority = MAX_RT_PRIO / 2,
};
int err;
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index f85a1b9d129b..706207d192ae 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -642,11 +642,8 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
priv->irq = pdata->irq;
} else {
priv->irq = platform_get_irq(pdev, 0);
- if (priv->irq < 0) {
- dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
- priv->irq);
+ if (priv->irq < 0)
return priv->irq;
- }
}
priv->regmap = pdata->regmap;
diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c
index 48d6f0d87583..83ed1fbf73cf 100644
--- a/drivers/platform/olpc/olpc-xo175-ec.c
+++ b/drivers/platform/olpc/olpc-xo175-ec.c
@@ -736,6 +736,12 @@ static const struct of_device_id olpc_xo175_ec_of_match[] = {
};
MODULE_DEVICE_TABLE(of, olpc_xo175_ec_of_match);
+static const struct spi_device_id olpc_xo175_ec_id_table[] = {
+ { "xo1.75-ec", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, olpc_xo175_ec_id_table);
+
static struct spi_driver olpc_xo175_ec_spi_driver = {
.driver = {
.name = "olpc-xo175-ec",
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 62b54e137231..60c18f21588d 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1881,52 +1881,17 @@ static int __init acer_wmi_enable_rf_button(void)
return status;
}
-#define ACER_WMID_ACCEL_HID "BST0001"
-
-static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
- void *ctx, void **retval)
-{
- struct acpi_device *dev;
-
- if (!strcmp(ctx, "SENR")) {
- if (acpi_bus_get_device(ah, &dev))
- return AE_OK;
- if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
- return AE_OK;
- } else
- return AE_OK;
-
- *(acpi_handle *)retval = ah;
-
- return AE_CTRL_TERMINATE;
-}
-
-static int __init acer_wmi_get_handle(const char *name, const char *prop,
- acpi_handle *ah)
-{
- acpi_status status;
- acpi_handle handle;
-
- BUG_ON(!name || !ah);
-
- handle = NULL;
- status = acpi_get_devices(prop, acer_wmi_get_handle_cb,
- (void *)name, &handle);
- if (ACPI_SUCCESS(status) && handle) {
- *ah = handle;
- return 0;
- } else {
- return -ENODEV;
- }
-}
-
static int __init acer_wmi_accel_setup(void)
{
+ struct acpi_device *adev;
int err;
- err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle);
- if (err)
- return err;
+ adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1);
+ if (!adev)
+ return -ENODEV;
+
+ gsensor_handle = acpi_device_handle(adev);
+ acpi_dev_put(adev);
interface->capability |= ACER_CAP_ACCEL;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 2ebde0174937..b361c73636a4 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -402,6 +402,15 @@ static const struct dmi_system_id asus_quirks[] = {
},
.driver_data = &quirk_asus_forceals,
},
+ {
+ .callback = dmi_matched,
+ .ident = "ASUSTeK COMPUTER INC. UX430UNR",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UX430UNR"),
+ },
+ .driver_data = &quirk_asus_forceals,
+ },
{},
};
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index ca28d27dae63..821b08e01635 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -26,6 +26,7 @@
#include <linux/rfkill.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
+#include <linux/power_supply.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/debugfs.h>
@@ -35,6 +36,8 @@
#include <linux/thermal.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
+
+#include <acpi/battery.h>
#include <acpi/video.h>
#include "asus-wmi.h"
@@ -65,6 +68,9 @@ MODULE_LICENSE("GPL");
#define ASUS_FAN_MFUN 0x13
#define ASUS_FAN_SFUN_READ 0x06
#define ASUS_FAN_SFUN_WRITE 0x07
+
+/* Based on standard hwmon pwmX_enable values */
+#define ASUS_FAN_CTRL_FULLSPEED 0
#define ASUS_FAN_CTRL_MANUAL 1
#define ASUS_FAN_CTRL_AUTO 2
@@ -120,7 +126,7 @@ struct agfn_args {
} __packed;
/* struct used for calling fan read and write methods */
-struct fan_args {
+struct agfn_fan_args {
struct agfn_args agfn; /* common fields */
u8 fan; /* fan number: 0: set auto mode 1: 1st fan */
u32 speed; /* read: RPM/100 - write: 0-255 */
@@ -148,6 +154,12 @@ struct asus_rfkill {
u32 dev_id;
};
+enum fan_type {
+ FAN_TYPE_NONE = 0,
+ FAN_TYPE_AGFN, /* deprecated on newer platforms */
+ FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */
+};
+
struct asus_wmi {
int dsts_id;
int spec;
@@ -178,14 +190,17 @@ struct asus_wmi {
struct asus_rfkill gps;
struct asus_rfkill uwb;
- bool asus_hwmon_fan_manual_mode;
- int asus_hwmon_num_fans;
- int asus_hwmon_pwm;
+ enum fan_type fan_type;
+ int fan_pwm_mode;
+ int agfn_pwm;
bool fan_boost_mode_available;
u8 fan_boost_mode_mask;
u8 fan_boost_mode;
+ // The RSOC controls the maximum charging percentage.
+ bool battery_rsoc_available;
+
struct hotplug_slot hotplug_slot;
struct mutex hotplug_lock;
struct mutex wmi_lock;
@@ -292,12 +307,11 @@ static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)
* Copy to dma capable address otherwise memory corruption occurs as
* bios has to be able to access it.
*/
- input.pointer = kzalloc(args.length, GFP_DMA | GFP_KERNEL);
+ input.pointer = kmemdup(args.pointer, args.length, GFP_DMA | GFP_KERNEL);
input.length = args.length;
if (!input.pointer)
return -ENOMEM;
phys_addr = virt_to_phys(input.pointer);
- memcpy(input.pointer, args.pointer, args.length);
status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_AGFN,
phys_addr, 0, &retval);
@@ -331,7 +345,6 @@ static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
int err;
err = asus_wmi_get_devstate(asus, dev_id, &retval);
-
if (err < 0)
return err;
@@ -352,6 +365,105 @@ static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
ASUS_WMI_DSTS_STATUS_BIT);
}
+static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
+{
+ u32 retval;
+ int status = asus_wmi_get_devstate(asus, dev_id, &retval);
+
+ return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT);
+}
+
+/* Battery ********************************************************************/
+
+/* The battery maximum charging percentage */
+static int charge_end_threshold;
+
+static ssize_t charge_control_end_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value, ret, rv;
+
+ ret = kstrtouint(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ if (value < 0 || value > 100)
+ return -EINVAL;
+
+ ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, value, &rv);
+ if (ret)
+ return ret;
+
+ if (rv != 1)
+ return -EIO;
+
+ /* There isn't any method in the DSDT to read the threshold, so we
+ * save the threshold.
+ */
+ charge_end_threshold = value;
+ return count;
+}
+
+static ssize_t charge_control_end_threshold_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", charge_end_threshold);
+}
+
+static DEVICE_ATTR_RW(charge_control_end_threshold);
+
+static int asus_wmi_battery_add(struct power_supply *battery)
+{
+ /* The WMI method does not provide a way to specific a battery, so we
+ * just assume it is the first battery.
+ */
+ if (strcmp(battery->desc->name, "BAT0") != 0)
+ return -ENODEV;
+
+ if (device_create_file(&battery->dev,
+ &dev_attr_charge_control_end_threshold))
+ return -ENODEV;
+
+ /* The charge threshold is only reset when the system is power cycled,
+ * and we can't get the current threshold so let set it to 100% when
+ * a battery is added.
+ */
+ asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, 100, NULL);
+ charge_end_threshold = 100;
+
+ return 0;
+}
+
+static int asus_wmi_battery_remove(struct power_supply *battery)
+{
+ device_remove_file(&battery->dev,
+ &dev_attr_charge_control_end_threshold);
+ return 0;
+}
+
+static struct acpi_battery_hook battery_hook = {
+ .add_battery = asus_wmi_battery_add,
+ .remove_battery = asus_wmi_battery_remove,
+ .name = "ASUS Battery Extension",
+};
+
+static void asus_wmi_battery_init(struct asus_wmi *asus)
+{
+ asus->battery_rsoc_available = false;
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_RSOC)) {
+ asus->battery_rsoc_available = true;
+ battery_hook_register(&battery_hook);
+ }
+}
+
+static void asus_wmi_battery_exit(struct asus_wmi *asus)
+{
+ if (asus->battery_rsoc_available)
+ battery_hook_unregister(&battery_hook);
+}
+
/* LEDs ***********************************************************************/
/*
@@ -427,15 +539,14 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
if (retval == 0x8000)
retval = 0;
- if (retval >= 0) {
- if (level)
- *level = retval & 0x7F;
- if (env)
- *env = (retval >> 8) & 0x7F;
- retval = 0;
- }
+ if (retval < 0)
+ return retval;
- return retval;
+ if (level)
+ *level = retval & 0x7F;
+ if (env)
+ *env = (retval >> 8) & 0x7F;
+ return 0;
}
static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
@@ -446,12 +557,7 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
max_level = asus->kbd_led.max_brightness;
- if (value > max_level)
- value = max_level;
- else if (value < 0)
- value = 0;
-
- asus->kbd_led_wk = value;
+ asus->kbd_led_wk = clamp_val(value, 0, max_level);
kbd_led_update(asus);
}
@@ -481,7 +587,6 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
retval = kbd_led_read(asus, &value, NULL);
-
if (retval < 0)
return retval;
@@ -497,15 +602,6 @@ static int wlan_led_unknown_state(struct asus_wmi *asus)
return result & ASUS_WMI_DSTS_UNKNOWN_BIT;
}
-static int wlan_led_presence(struct asus_wmi *asus)
-{
- u32 result;
-
- asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
-
- return result & ASUS_WMI_DSTS_PRESENCE_BIT;
-}
-
static void wlan_led_update(struct work_struct *work)
{
int ctrl_param;
@@ -572,15 +668,6 @@ static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev)
return result & ASUS_WMI_DSTS_LIGHTBAR_MASK;
}
-static int lightbar_led_presence(struct asus_wmi *asus)
-{
- u32 result;
-
- asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result);
-
- return result & ASUS_WMI_DSTS_PRESENCE_BIT;
-}
-
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
@@ -631,7 +718,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
- if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) {
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_WIRELESS_LED)
+ && (asus->driver->quirks->wapf > 0)) {
INIT_WORK(&asus->wlan_led_work, wlan_led_update);
asus->wlan_led.name = "asus::wlan";
@@ -648,7 +736,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
- if (lightbar_led_presence(asus)) {
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_LIGHTBAR)) {
INIT_WORK(&asus->lightbar_led_work, lightbar_led_update);
asus->lightbar_led.name = "asus::lightbar";
@@ -771,16 +859,14 @@ static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
acpi_handle handle;
status = acpi_get_handle(NULL, node, &handle);
-
- if (ACPI_SUCCESS(status)) {
- status = acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- asus_rfkill_notify, asus);
- if (ACPI_FAILURE(status))
- pr_warn("Failed to register notify on %s\n", node);
- } else
+ if (ACPI_FAILURE(status))
return -ENODEV;
+ status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ asus_rfkill_notify, asus);
+ if (ACPI_FAILURE(status))
+ pr_warn("Failed to register notify on %s\n", node);
+
return 0;
}
@@ -790,15 +876,13 @@ static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
acpi_handle handle;
status = acpi_get_handle(NULL, node, &handle);
+ if (ACPI_FAILURE(status))
+ return;
- if (ACPI_SUCCESS(status)) {
- status = acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- asus_rfkill_notify);
- if (ACPI_FAILURE(status))
- pr_err("Error removing rfkill notify handler %s\n",
- node);
- }
+ status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ asus_rfkill_notify);
+ if (ACPI_FAILURE(status))
+ pr_err("Error removing rfkill notify handler %s\n", node);
}
static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
@@ -1126,10 +1210,10 @@ static void asus_wmi_set_als(void)
/* Hwmon device ***************************************************************/
-static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan,
+static int asus_agfn_fan_speed_read(struct asus_wmi *asus, int fan,
int *speed)
{
- struct fan_args args = {
+ struct agfn_fan_args args = {
.agfn.len = sizeof(args),
.agfn.mfun = ASUS_FAN_MFUN,
.agfn.sfun = ASUS_FAN_SFUN_READ,
@@ -1153,10 +1237,10 @@ static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan,
return 0;
}
-static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan,
+static int asus_agfn_fan_speed_write(struct asus_wmi *asus, int fan,
int *speed)
{
- struct fan_args args = {
+ struct agfn_fan_args args = {
.agfn.len = sizeof(args),
.agfn.mfun = ASUS_FAN_MFUN,
.agfn.sfun = ASUS_FAN_SFUN_WRITE,
@@ -1176,7 +1260,7 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan,
return -ENXIO;
if (speed && fan == 1)
- asus->asus_hwmon_pwm = *speed;
+ asus->agfn_pwm = *speed;
return 0;
}
@@ -1185,77 +1269,60 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan,
* Check if we can read the speed of one fan. If true we assume we can also
* control it.
*/
-static int asus_hwmon_get_fan_number(struct asus_wmi *asus, int *num_fans)
+static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus)
{
int status;
- int speed = 0;
+ int speed;
+ u32 value;
- *num_fans = 0;
+ status = asus_agfn_fan_speed_read(asus, 1, &speed);
+ if (status != 0)
+ return false;
- status = asus_hwmon_agfn_fan_speed_read(asus, 1, &speed);
- if (!status)
- *num_fans = 1;
+ status = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
+ if (status != 0)
+ return false;
- return 0;
+ /*
+ * We need to find a better way, probably using sfun,
+ * bits or spec ...
+ * Currently we disable it if:
+ * - ASUS_WMI_UNSUPPORTED_METHOD is returned
+ * - reverved bits are non-zero
+ * - sfun and presence bit are not set
+ */
+ return !(value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
+ || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)));
}
-static int asus_hwmon_fan_set_auto(struct asus_wmi *asus)
+static int asus_fan_set_auto(struct asus_wmi *asus)
{
int status;
+ u32 retval;
- status = asus_hwmon_agfn_fan_speed_write(asus, 0, NULL);
- if (status)
- return -ENXIO;
-
- asus->asus_hwmon_fan_manual_mode = false;
-
- return 0;
-}
+ switch (asus->fan_type) {
+ case FAN_TYPE_SPEC83:
+ status = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,
+ 0, &retval);
+ if (status)
+ return status;
-static int asus_hwmon_fan_rpm_show(struct device *dev, int fan)
-{
- struct asus_wmi *asus = dev_get_drvdata(dev);
- int value;
- int ret;
+ if (retval != 1)
+ return -EIO;
+ break;
- /* no speed readable on manual mode */
- if (asus->asus_hwmon_fan_manual_mode)
- return -ENXIO;
+ case FAN_TYPE_AGFN:
+ status = asus_agfn_fan_speed_write(asus, 0, NULL);
+ if (status)
+ return -ENXIO;
+ break;
- ret = asus_hwmon_agfn_fan_speed_read(asus, fan+1, &value);
- if (ret) {
- pr_warn("reading fan speed failed: %d\n", ret);
+ default:
return -ENXIO;
}
- return value;
-}
-static void asus_hwmon_pwm_show(struct asus_wmi *asus, int fan, int *value)
-{
- int err;
-
- if (asus->asus_hwmon_pwm >= 0) {
- *value = asus->asus_hwmon_pwm;
- return;
- }
-
- err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, value);
- if (err < 0)
- return;
-
- *value &= 0xFF;
-
- if (*value == 1) /* Low Speed */
- *value = 85;
- else if (*value == 2)
- *value = 170;
- else if (*value == 3)
- *value = 255;
- else if (*value) {
- pr_err("Unknown fan speed %#x\n", *value);
- *value = -1;
- }
+ return 0;
}
static ssize_t pwm1_show(struct device *dev,
@@ -1263,9 +1330,33 @@ static ssize_t pwm1_show(struct device *dev,
char *buf)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
+ int err;
int value;
- asus_hwmon_pwm_show(asus, 0, &value);
+ /* If we already set a value then just return it */
+ if (asus->agfn_pwm >= 0)
+ return sprintf(buf, "%d\n", asus->agfn_pwm);
+
+ /*
+ * If we haven't set already set a value through the AGFN interface,
+ * we read a current value through the (now-deprecated) FAN_CTRL device.
+ */
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
+ if (err < 0)
+ return err;
+
+ value &= 0xFF;
+
+ if (value == 1) /* Low Speed */
+ value = 85;
+ else if (value == 2)
+ value = 170;
+ else if (value == 3)
+ value = 255;
+ else if (value) {
+ pr_err("Unknown fan speed %#x\n", value);
+ value = -1;
+ }
return sprintf(buf, "%d\n", value);
}
@@ -1279,17 +1370,16 @@ static ssize_t pwm1_store(struct device *dev,
int ret;
ret = kstrtouint(buf, 10, &value);
-
if (ret)
return ret;
value = clamp(value, 0, 255);
- state = asus_hwmon_agfn_fan_speed_write(asus, 1, &value);
+ state = asus_agfn_fan_speed_write(asus, 1, &value);
if (state)
pr_warn("Setting fan speed failed: %d\n", state);
else
- asus->asus_hwmon_fan_manual_mode = true;
+ asus->fan_pwm_mode = ASUS_FAN_CTRL_MANUAL;
return count;
}
@@ -1298,10 +1388,37 @@ static ssize_t fan1_input_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- int value = asus_hwmon_fan_rpm_show(dev, 0);
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+ int value;
+ int ret;
- return sprintf(buf, "%d\n", value < 0 ? -1 : value*100);
+ switch (asus->fan_type) {
+ case FAN_TYPE_SPEC83:
+ ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL,
+ &value);
+ if (ret < 0)
+ return ret;
+
+ value &= 0xffff;
+ break;
+
+ case FAN_TYPE_AGFN:
+ /* no speed readable on manual mode */
+ if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL)
+ return -ENXIO;
+
+ ret = asus_agfn_fan_speed_read(asus, 1, &value);
+ if (ret) {
+ pr_warn("reading fan speed failed: %d\n", ret);
+ return -ENXIO;
+ }
+ break;
+
+ default:
+ return -ENXIO;
+ }
+ return sprintf(buf, "%d\n", value < 0 ? -1 : value*100);
}
static ssize_t pwm1_enable_show(struct device *dev,
@@ -1310,10 +1427,16 @@ static ssize_t pwm1_enable_show(struct device *dev,
{
struct asus_wmi *asus = dev_get_drvdata(dev);
- if (asus->asus_hwmon_fan_manual_mode)
- return sprintf(buf, "%d\n", ASUS_FAN_CTRL_MANUAL);
-
- return sprintf(buf, "%d\n", ASUS_FAN_CTRL_AUTO);
+ /*
+ * Just read back the cached pwm mode.
+ *
+ * For the CPU_FAN device, the spec indicates that we should be
+ * able to read the device status and consult bit 19 to see if we
+ * are in Full On or Automatic mode. However, this does not work
+ * in practice on X532FL at least (the bit is always 0) and there's
+ * also nothing in the DSDT to indicate that this behaviour exists.
+ */
+ return sprintf(buf, "%d\n", asus->fan_pwm_mode);
}
static ssize_t pwm1_enable_store(struct device *dev,
@@ -1323,21 +1446,50 @@ static ssize_t pwm1_enable_store(struct device *dev,
struct asus_wmi *asus = dev_get_drvdata(dev);
int status = 0;
int state;
+ int value;
int ret;
+ u32 retval;
ret = kstrtouint(buf, 10, &state);
-
if (ret)
return ret;
- if (state == ASUS_FAN_CTRL_MANUAL)
- asus->asus_hwmon_fan_manual_mode = true;
- else
- status = asus_hwmon_fan_set_auto(asus);
+ if (asus->fan_type == FAN_TYPE_SPEC83) {
+ switch (state) { /* standard documented hwmon values */
+ case ASUS_FAN_CTRL_FULLSPEED:
+ value = 1;
+ break;
+ case ASUS_FAN_CTRL_AUTO:
+ value = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
- if (status)
- return status;
+ ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,
+ value, &retval);
+ if (ret)
+ return ret;
+
+ if (retval != 1)
+ return -EIO;
+ } else if (asus->fan_type == FAN_TYPE_AGFN) {
+ switch (state) {
+ case ASUS_FAN_CTRL_MANUAL:
+ break;
+
+ case ASUS_FAN_CTRL_AUTO:
+ status = asus_fan_set_auto(asus);
+ if (status)
+ return status;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ asus->fan_pwm_mode = state;
return count;
}
@@ -1357,7 +1509,6 @@ static ssize_t asus_hwmon_temp1(struct device *dev,
int err;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
-
if (err < 0)
return err;
@@ -1390,59 +1541,33 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
{
struct device *dev = container_of(kobj, struct device, kobj);
struct asus_wmi *asus = dev_get_drvdata(dev->parent);
- int dev_id = -1;
- int fan_attr = -1;
u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
- bool ok = true;
- if (attr == &dev_attr_pwm1.attr)
- dev_id = ASUS_WMI_DEVID_FAN_CTRL;
- else if (attr == &dev_attr_temp1_input.attr)
- dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
-
-
- if (attr == &dev_attr_fan1_input.attr
+ if (attr == &dev_attr_pwm1.attr) {
+ if (asus->fan_type != FAN_TYPE_AGFN)
+ return 0;
+ } else if (attr == &dev_attr_fan1_input.attr
|| attr == &dev_attr_fan1_label.attr
- || attr == &dev_attr_pwm1.attr
|| attr == &dev_attr_pwm1_enable.attr) {
- fan_attr = 1;
- }
-
- if (dev_id != -1) {
- int err = asus_wmi_get_devstate(asus, dev_id, &value);
+ if (asus->fan_type == FAN_TYPE_NONE)
+ return 0;
+ } else if (attr == &dev_attr_temp1_input.attr) {
+ int err = asus_wmi_get_devstate(asus,
+ ASUS_WMI_DEVID_THERMAL_CTRL,
+ &value);
- if (err < 0 && fan_attr == -1)
+ if (err < 0)
return 0; /* can't return negative here */
- }
- if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
- /*
- * We need to find a better way, probably using sfun,
- * bits or spec ...
- * Currently we disable it if:
- * - ASUS_WMI_UNSUPPORTED_METHOD is returned
- * - reverved bits are non-zero
- * - sfun and presence bit are not set
- */
- if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
- || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
- ok = false;
- else
- ok = fan_attr <= asus->asus_hwmon_num_fans;
- } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
/*
* If the temperature value in deci-Kelvin is near the absolute
* zero temperature, something is clearly wrong
*/
if (value == 0 || value == 1)
- ok = false;
- } else if (fan_attr <= asus->asus_hwmon_num_fans && fan_attr != -1) {
- ok = true;
- } else {
- ok = false;
+ return 0;
}
- return ok ? attr->mode : 0;
+ return attr->mode;
}
static const struct attribute_group hwmon_attribute_group = {
@@ -1468,20 +1593,19 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
static int asus_wmi_fan_init(struct asus_wmi *asus)
{
- int status;
+ asus->fan_type = FAN_TYPE_NONE;
+ asus->agfn_pwm = -1;
- asus->asus_hwmon_pwm = -1;
- asus->asus_hwmon_num_fans = -1;
- asus->asus_hwmon_fan_manual_mode = false;
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL))
+ asus->fan_type = FAN_TYPE_SPEC83;
+ else if (asus_wmi_has_agfn_fan(asus))
+ asus->fan_type = FAN_TYPE_AGFN;
- status = asus_hwmon_get_fan_number(asus, &asus->asus_hwmon_num_fans);
- if (status) {
- asus->asus_hwmon_num_fans = 0;
- pr_warn("Could not determine number of fans: %d\n", status);
- return -ENXIO;
- }
+ if (asus->fan_type == FAN_TYPE_NONE)
+ return -ENODEV;
- pr_info("Number of fans: %d\n", asus->asus_hwmon_num_fans);
+ asus_fan_set_auto(asus);
+ asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO;
return 0;
}
@@ -1523,7 +1647,6 @@ static int fan_boost_mode_write(struct asus_wmi *asus)
pr_info("Set fan boost mode: %u\n", value);
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_FAN_BOOST_MODE, value,
&retval);
-
if (err) {
pr_warn("Failed to set fan boost mode: %d\n", err);
return err;
@@ -1606,6 +1729,7 @@ static DEVICE_ATTR_RW(fan_boost_mode);
static int read_backlight_power(struct asus_wmi *asus)
{
int ret;
+
if (asus->driver->quirks->store_backlight_power)
ret = !asus->driver->panel_power;
else
@@ -1624,7 +1748,6 @@ static int read_brightness_max(struct asus_wmi *asus)
int err;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
-
if (err < 0)
return err;
@@ -1644,7 +1767,6 @@ static int read_brightness(struct backlight_device *bd)
int err;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
-
if (err < 0)
return err;
@@ -1734,7 +1856,6 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
return max;
power = read_backlight_power(asus);
-
if (power == -ENODEV)
power = FB_BLANK_UNBLANK;
else if (power < 0)
@@ -1900,7 +2021,6 @@ static void asus_wmi_notify(u32 value, void *context)
for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) {
code = asus_wmi_get_event_code(value);
-
if (code < 0) {
pr_warn("Failed to get notify code: %d\n", code);
return;
@@ -1929,7 +2049,6 @@ static int asus_wmi_notify_queue_flush(struct asus_wmi *asus)
for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) {
code = asus_wmi_get_event_code(WMI_EVENT_VALUE_ATK);
-
if (code < 0) {
pr_warn("Failed to get event during flush: %d\n", code);
return code;
@@ -1945,32 +2064,25 @@ static int asus_wmi_notify_queue_flush(struct asus_wmi *asus)
/* Sysfs **********************************************************************/
-static int parse_arg(const char *buf, unsigned long count, int *val)
-{
- if (!count)
- return 0;
- if (sscanf(buf, "%i", val) != 1)
- return -EINVAL;
- return count;
-}
-
static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
const char *buf, size_t count)
{
u32 retval;
- int rv, err, value;
+ int err, value;
value = asus_wmi_get_devstate_simple(asus, devid);
if (value < 0)
return value;
- rv = parse_arg(buf, count, &value);
- err = asus_wmi_set_devstate(devid, value, &retval);
+ err = kstrtoint(buf, 0, &value);
+ if (err)
+ return err;
+ err = asus_wmi_set_devstate(devid, value, &retval);
if (err < 0)
return err;
- return rv;
+ return count;
}
static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
@@ -2019,8 +2131,10 @@ static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr,
{
int value, rv;
- if (!count || sscanf(buf, "%i", &value) != 1)
- return -EINVAL;
+ rv = kstrtoint(buf, 0, &value);
+ if (rv)
+ return rv;
+
if (value < 0 || value > 2)
return -EINVAL;
@@ -2181,7 +2295,6 @@ static int show_dsts(struct seq_file *m, void *data)
u32 retval = -1;
err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
-
if (err < 0)
return err;
@@ -2198,7 +2311,6 @@ static int show_devs(struct seq_file *m, void *data)
err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
&retval);
-
if (err < 0)
return err;
@@ -2334,7 +2446,6 @@ static int asus_wmi_add(struct platform_device *pdev)
goto fail_input;
err = asus_wmi_fan_init(asus); /* probably no problems on error */
- asus_hwmon_fan_set_auto(asus);
err = asus_wmi_hwmon_init(asus);
if (err)
@@ -2392,6 +2503,8 @@ static int asus_wmi_add(struct platform_device *pdev)
goto fail_wmi_handler;
}
+ asus_wmi_battery_init(asus);
+
asus_wmi_debugfs_init(asus);
return 0;
@@ -2426,7 +2539,8 @@ static int asus_wmi_remove(struct platform_device *device)
asus_wmi_rfkill_exit(asus);
asus_wmi_debugfs_exit(asus);
asus_wmi_sysfs_exit(asus->platform_device);
- asus_hwmon_fan_set_auto(asus);
+ asus_fan_set_auto(asus);
+ asus_wmi_battery_exit(asus);
kfree(asus);
return 0;
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 09dfa6f48a1a..ab610376fdad 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -226,7 +226,7 @@ static const unsigned char pwm_lookup_table[256] = {
/* General access */
static u8 ec_read_u8(u8 addr)
{
- u8 value;
+ u8 value = 0;
ec_read(addr, &value);
return value;
}
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index acc653f9c16f..6669db2555fb 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -311,11 +311,13 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = {
{ KE_IGNORE, 0xfff1, { KEY_RESERVED } },
/* Keyboard backlight level changed */
- { KE_IGNORE, 0x01e1, { KEY_RESERVED } },
- { KE_IGNORE, 0x02ea, { KEY_RESERVED } },
- { KE_IGNORE, 0x02eb, { KEY_RESERVED } },
- { KE_IGNORE, 0x02ec, { KEY_RESERVED } },
- { KE_IGNORE, 0x02f6, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_OFF_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_ON_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_AUTO_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_AUTO_25_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_AUTO_50_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_AUTO_75_TOKEN, { KEY_RESERVED } },
+ { KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } },
};
static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 7a2747455237..799cbe2ffcf3 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -240,6 +240,7 @@ static const struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted),
+ AXIS_DMI_MATCH("HPZBook17G5", "HP ZBook 17 G5", x_inverted),
AXIS_DMI_MATCH("HPZBook17", "HP ZBook 17", xy_swap_yz_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
index 197d8a192721..61fe341a85aa 100644
--- a/drivers/platform/x86/i2c-multi-instantiate.c
+++ b/drivers/platform/x86/i2c-multi-instantiate.c
@@ -81,9 +81,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- multi = devm_kmalloc(dev,
- offsetof(struct i2c_multi_inst_data, clients[ret]),
- GFP_KERNEL);
+ multi = devm_kmalloc(dev, struct_size(multi, clients, ret), GFP_KERNEL);
if (!multi)
return -ENOMEM;
diff --git a/drivers/platform/x86/intel_bxtwc_tmu.c b/drivers/platform/x86/intel_bxtwc_tmu.c
index 951c105bafc1..7ccf583649e6 100644
--- a/drivers/platform/x86/intel_bxtwc_tmu.c
+++ b/drivers/platform/x86/intel_bxtwc_tmu.c
@@ -60,11 +60,8 @@ static int bxt_wcove_tmu_probe(struct platform_device *pdev)
wctmu->regmap = pmic->regmap;
irq = platform_get_irq(pdev, 0);
-
- if (irq < 0) {
- dev_err(&pdev->dev, "invalid irq %d\n", irq);
+ if (irq < 0)
return irq;
- }
regmap_irq_chip = pmic->irq_chip_data_tmu;
virq = regmap_irq_get_virq(regmap_irq_chip, irq);
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c
index d9542c661ddc..af233b7b77f2 100644
--- a/drivers/platform/x86/intel_int0002_vgpio.c
+++ b/drivers/platform/x86/intel_int0002_vgpio.c
@@ -122,7 +122,7 @@ static irqreturn_t int0002_irq(int irq, void *data)
generic_handle_irq(irq_find_mapping(chip->irq.domain,
GPE0A_PME_B0_VIRT_GPIO_PIN));
- pm_system_wakeup();
+ pm_wakeup_hard_event(chip->parent);
return IRQ_HANDLED;
}
@@ -144,6 +144,7 @@ static struct irq_chip int0002_cht_irqchip = {
* No set_wake, on CHT the IRQ is typically shared with the ACPI SCI
* and we don't want to mess with the ACPI SCI irq settings.
*/
+ .flags = IRQCHIP_SKIP_SET_WAKE,
};
static const struct x86_cpu_id int0002_cpu_ids[] = {
@@ -152,6 +153,13 @@ static const struct x86_cpu_id int0002_cpu_ids[] = {
{}
};
+static void int0002_init_irq_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ bitmap_clear(valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
+}
+
static int int0002_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -166,10 +174,8 @@ static int int0002_probe(struct platform_device *pdev)
return -ENODEV;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "Error getting IRQ: %d\n", irq);
+ if (irq < 0)
return irq;
- }
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -184,7 +190,7 @@ static int int0002_probe(struct platform_device *pdev)
chip->direction_output = int0002_gpio_direction_output;
chip->base = -1;
chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
- chip->irq.need_valid_mask = true;
+ chip->irq.init_valid_mask = int0002_init_irq_valid_mask;
ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
if (ret) {
@@ -192,8 +198,6 @@ static int int0002_probe(struct platform_device *pdev)
return ret;
}
- bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
-
/*
* We manually request the irq here instead of passing a flow-handler
* to gpiochip_set_chained_irqchip, because the irq is shared.
@@ -216,6 +220,13 @@ static int int0002_probe(struct platform_device *pdev)
gpiochip_set_chained_irqchip(chip, irq_chip, irq, NULL);
+ device_init_wakeup(dev, true);
+ return 0;
+}
+
+static int int0002_remove(struct platform_device *pdev)
+{
+ device_init_wakeup(&pdev->dev, false);
return 0;
}
@@ -231,6 +242,7 @@ static struct platform_driver int0002_driver = {
.acpi_match_table = int0002_acpi_ids,
},
.probe = int0002_probe,
+ .remove = int0002_remove,
};
module_platform_driver(int0002_driver);
diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c
index 235c0b89f824..94a008efb09b 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -806,12 +806,13 @@ static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
#endif /* CONFIG_DEBUG_FS */
static const struct x86_cpu_id intel_pmc_core_ids[] = {
- INTEL_CPU_FAM6(SKYLAKE_MOBILE, spt_reg_map),
- INTEL_CPU_FAM6(SKYLAKE_DESKTOP, spt_reg_map),
- INTEL_CPU_FAM6(KABYLAKE_MOBILE, spt_reg_map),
- INTEL_CPU_FAM6(KABYLAKE_DESKTOP, spt_reg_map),
- INTEL_CPU_FAM6(CANNONLAKE_MOBILE, cnp_reg_map),
- INTEL_CPU_FAM6(ICELAKE_MOBILE, icl_reg_map),
+ INTEL_CPU_FAM6(SKYLAKE_L, spt_reg_map),
+ INTEL_CPU_FAM6(SKYLAKE, spt_reg_map),
+ INTEL_CPU_FAM6(KABYLAKE_L, spt_reg_map),
+ INTEL_CPU_FAM6(KABYLAKE, spt_reg_map),
+ INTEL_CPU_FAM6(CANNONLAKE_L, cnp_reg_map),
+ INTEL_CPU_FAM6(ICELAKE_L, icl_reg_map),
+ INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map),
{}
};
@@ -877,10 +878,14 @@ static int pmc_core_probe(struct platform_device *pdev)
if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids))
pmcdev->map = &cnp_reg_map;
- if (lpit_read_residency_count_address(&slp_s0_addr))
+ if (lpit_read_residency_count_address(&slp_s0_addr)) {
pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT;
- else
+
+ if (page_is_ram(PHYS_PFN(pmcdev->base_addr)))
+ return -ENODEV;
+ } else {
pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset;
+ }
pmcdev->regbase = ioremap(pmcdev->base_addr,
pmcdev->map->regmap_length);
diff --git a/drivers/platform/x86/intel_pmc_core_pltdrv.c b/drivers/platform/x86/intel_pmc_core_pltdrv.c
index a8754a6db1b8..6fe829f30997 100644
--- a/drivers/platform/x86/intel_pmc_core_pltdrv.c
+++ b/drivers/platform/x86/intel_pmc_core_pltdrv.c
@@ -18,8 +18,16 @@
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
+static void intel_pmc_core_release(struct device *dev)
+{
+ /* Nothing to do. */
+}
+
static struct platform_device pmc_core_device = {
.name = "intel_pmc_core",
+ .dev = {
+ .release = intel_pmc_core_release,
+ },
};
/*
@@ -30,12 +38,12 @@ static struct platform_device pmc_core_device = {
* other list may grow, but this list should not.
*/
static const struct x86_cpu_id intel_pmc_core_platform_ids[] = {
- INTEL_CPU_FAM6(SKYLAKE_MOBILE, pmc_core_device),
- INTEL_CPU_FAM6(SKYLAKE_DESKTOP, pmc_core_device),
- INTEL_CPU_FAM6(KABYLAKE_MOBILE, pmc_core_device),
- INTEL_CPU_FAM6(KABYLAKE_DESKTOP, pmc_core_device),
- INTEL_CPU_FAM6(CANNONLAKE_MOBILE, pmc_core_device),
- INTEL_CPU_FAM6(ICELAKE_MOBILE, pmc_core_device),
+ INTEL_CPU_FAM6(SKYLAKE_L, pmc_core_device),
+ INTEL_CPU_FAM6(SKYLAKE, pmc_core_device),
+ INTEL_CPU_FAM6(KABYLAKE_L, pmc_core_device),
+ INTEL_CPU_FAM6(KABYLAKE, pmc_core_device),
+ INTEL_CPU_FAM6(CANNONLAKE_L, pmc_core_device),
+ INTEL_CPU_FAM6(ICELAKE_L, pmc_core_device),
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_platform_ids);
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index 55037ff258f8..5c1da2bb1435 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -936,10 +936,8 @@ static int ipc_plat_probe(struct platform_device *pdev)
spin_lock_init(&ipcdev.gcr_lock);
ipcdev.irq = platform_get_irq(pdev, 0);
- if (ipcdev.irq < 0) {
- dev_err(&pdev->dev, "Failed to get irq\n");
+ if (ipcdev.irq < 0)
return -EINVAL;
- }
ret = ipc_plat_get_res(pdev);
if (ret) {
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c b/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
index 68d75391db57..3de5a3c66529 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
+++ b/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
@@ -29,6 +29,8 @@ static struct isst_if_cmd_cb punit_callbacks[ISST_IF_DEV_MAX];
static int punit_msr_white_list[] = {
MSR_TURBO_RATIO_LIMIT,
MSR_CONFIG_TDP_CONTROL,
+ MSR_TURBO_RATIO_LIMIT1,
+ MSR_TURBO_RATIO_LIMIT2,
};
struct isst_valid_cmd_ranges {
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
index f7266a115a08..ad8c7c0df4d9 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
+++ b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
@@ -132,11 +132,9 @@ static void isst_if_remove(struct pci_dev *pdev)
static int __maybe_unused isst_if_suspend(struct device *device)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct isst_if_device *punit_dev;
+ struct isst_if_device *punit_dev = dev_get_drvdata(device);
int i;
- punit_dev = pci_get_drvdata(pdev);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
punit_dev->range_0[i] = readl(punit_dev->punit_mmio +
mmio_range[0].beg + 4 * i);
@@ -149,11 +147,9 @@ static int __maybe_unused isst_if_suspend(struct device *device)
static int __maybe_unused isst_if_resume(struct device *device)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct isst_if_device *punit_dev;
+ struct isst_if_device *punit_dev = dev_get_drvdata(device);
int i;
- punit_dev = pci_get_drvdata(pdev);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
writel(punit_dev->range_0[i], punit_dev->punit_mmio +
mmio_range[0].beg + 4 * i);
diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c
index b0d3110ae378..48b112b4f0b0 100644
--- a/drivers/platform/x86/pcengines-apuv2.c
+++ b/drivers/platform/x86/pcengines-apuv2.c
@@ -32,6 +32,8 @@
#define APU2_GPIO_REG_LED3 AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
#define APU2_GPIO_REG_MODESW AMD_FCH_GPIO_REG_GPIO32_GE1
#define APU2_GPIO_REG_SIMSWAP AMD_FCH_GPIO_REG_GPIO33_GE2
+#define APU2_GPIO_REG_MPCIE2 AMD_FCH_GPIO_REG_GPIO59_DEVSLP0
+#define APU2_GPIO_REG_MPCIE3 AMD_FCH_GPIO_REG_GPIO51
/* order in which the gpio lines are defined in the register list */
#define APU2_GPIO_LINE_LED1 0
@@ -39,6 +41,8 @@
#define APU2_GPIO_LINE_LED3 2
#define APU2_GPIO_LINE_MODESW 3
#define APU2_GPIO_LINE_SIMSWAP 4
+#define APU2_GPIO_LINE_MPCIE2 5
+#define APU2_GPIO_LINE_MPCIE3 6
/* gpio device */
@@ -48,6 +52,8 @@ static int apu2_gpio_regs[] = {
[APU2_GPIO_LINE_LED3] = APU2_GPIO_REG_LED3,
[APU2_GPIO_LINE_MODESW] = APU2_GPIO_REG_MODESW,
[APU2_GPIO_LINE_SIMSWAP] = APU2_GPIO_REG_SIMSWAP,
+ [APU2_GPIO_LINE_MPCIE2] = APU2_GPIO_REG_MPCIE2,
+ [APU2_GPIO_LINE_MPCIE3] = APU2_GPIO_REG_MPCIE3,
};
static const char * const apu2_gpio_names[] = {
@@ -56,6 +62,8 @@ static const char * const apu2_gpio_names[] = {
[APU2_GPIO_LINE_LED3] = "front-led3",
[APU2_GPIO_LINE_MODESW] = "front-button",
[APU2_GPIO_LINE_SIMSWAP] = "simswap",
+ [APU2_GPIO_LINE_MPCIE2] = "mpcie2_reset",
+ [APU2_GPIO_LINE_MPCIE3] = "mpcie3_reset",
};
static const struct amd_fch_gpio_pdata board_apu2 = {
@@ -69,7 +77,8 @@ static const struct amd_fch_gpio_pdata board_apu2 = {
static const struct gpio_led apu2_leds[] = {
{ .name = "apu:green:1" },
{ .name = "apu:green:2" },
- { .name = "apu:green:3" }
+ { .name = "apu:green:3" },
+ { .name = "apu:simswap" },
};
static const struct gpio_led_platform_data apu2_leds_pdata = {
@@ -86,6 +95,8 @@ static struct gpiod_lookup_table gpios_led_table = {
NULL, 1, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
NULL, 2, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_REG_SIMSWAP,
+ NULL, 3, GPIO_ACTIVE_LOW),
}
};
@@ -93,7 +104,7 @@ static struct gpiod_lookup_table gpios_led_table = {
static struct gpio_keys_button apu2_keys_buttons[] = {
{
- .code = KEY_SETUP,
+ .code = KEY_RESTART,
.active_low = 1,
.desc = "front button",
.type = EV_KEY,
@@ -255,6 +266,4 @@ MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LED/keys driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
MODULE_ALIAS("platform:pcengines-apuv2");
-MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME);
-MODULE_SOFTDEP("pre: platform:leds-gpio");
-MODULE_SOFTDEP("pre: platform:gpio_keys_polled");
+MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME " platform:leds-gpio platform:gpio_keys_polled");
diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c
index aa53648a2214..9aca5e7ce6d0 100644
--- a/drivers/platform/x86/pmc_atom.c
+++ b/drivers/platform/x86/pmc_atom.c
@@ -415,6 +415,13 @@ static const struct dmi_system_id critclk_systems[] = {
DMI_MATCH(DMI_BOARD_NAME, "CB6363"),
},
},
+ {
+ .ident = "SIMATIC IPC227E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "6ES7647-8B"),
+ },
+ },
{ /*sentinel*/ }
};
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 7bde4640ef34..da794dcfdd92 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3647,22 +3647,19 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
goto err_exit;
/* Set up key map */
- hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
- GFP_KERNEL);
- if (!hotkey_keycode_map) {
- pr_err("failed to allocate memory for key map\n");
- res = -ENOMEM;
- goto err_exit;
- }
-
keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable,
ARRAY_SIZE(tpacpi_keymap_qtable));
BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps));
dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
"using keymap number %lu\n", keymap_id);
- memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id],
- TPACPI_HOTKEY_MAP_SIZE);
+ hotkey_keycode_map = kmemdup(&tpacpi_keymaps[keymap_id],
+ TPACPI_HOTKEY_MAP_SIZE, GFP_KERNEL);
+ if (!hotkey_keycode_map) {
+ pr_err("failed to allocate memory for key map\n");
+ res = -ENOMEM;
+ goto err_exit;
+ }
input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
@@ -9714,6 +9711,107 @@ static struct ibm_struct battery_driver_data = {
.exit = tpacpi_battery_exit,
};
+/*************************************************************************
+ * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature
+ */
+
+static int lcdshadow_state;
+
+static int lcdshadow_on_off(bool state)
+{
+ acpi_handle set_shadow_handle;
+ int output;
+
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "SSSS", &set_shadow_handle))) {
+ pr_warn("Thinkpad ACPI has no %s interface.\n", "SSSS");
+ return -EIO;
+ }
+
+ if (!acpi_evalf(set_shadow_handle, &output, NULL, "dd", (int)state))
+ return -EIO;
+
+ lcdshadow_state = state;
+ return 0;
+}
+
+static int lcdshadow_set(bool on)
+{
+ if (lcdshadow_state < 0)
+ return lcdshadow_state;
+ if (lcdshadow_state == on)
+ return 0;
+ return lcdshadow_on_off(on);
+}
+
+static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm)
+{
+ acpi_handle get_shadow_handle;
+ int output;
+
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GSSS", &get_shadow_handle))) {
+ lcdshadow_state = -ENODEV;
+ return 0;
+ }
+
+ if (!acpi_evalf(get_shadow_handle, &output, NULL, "dd", 0)) {
+ lcdshadow_state = -EIO;
+ return -EIO;
+ }
+ if (!(output & 0x10000)) {
+ lcdshadow_state = -ENODEV;
+ return 0;
+ }
+ lcdshadow_state = output & 0x1;
+
+ return 0;
+}
+
+static void lcdshadow_resume(void)
+{
+ if (lcdshadow_state >= 0)
+ lcdshadow_on_off(lcdshadow_state);
+}
+
+static int lcdshadow_read(struct seq_file *m)
+{
+ if (lcdshadow_state < 0) {
+ seq_puts(m, "status:\t\tnot supported\n");
+ } else {
+ seq_printf(m, "status:\t\t%d\n", lcdshadow_state);
+ seq_puts(m, "commands:\t0, 1\n");
+ }
+
+ return 0;
+}
+
+static int lcdshadow_write(char *buf)
+{
+ char *cmd;
+ int state = -1;
+
+ if (lcdshadow_state < 0)
+ return -ENODEV;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (strlencmp(cmd, "0") == 0)
+ state = 0;
+ else if (strlencmp(cmd, "1") == 0)
+ state = 1;
+ }
+
+ if (state == -1)
+ return -EINVAL;
+
+ return lcdshadow_set(state);
+}
+
+static struct ibm_struct lcdshadow_driver_data = {
+ .name = "lcdshadow",
+ .resume = lcdshadow_resume,
+ .read = lcdshadow_read,
+ .write = lcdshadow_write,
+};
+
/****************************************************************************
****************************************************************************
*
@@ -10195,6 +10293,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
.init = tpacpi_battery_init,
.data = &battery_driver_data,
},
+ {
+ .init = tpacpi_lcdshadow_init,
+ .data = &lcdshadow_driver_data,
+ },
};
static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
index 4370e4add83a..1c7d8324ff5c 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -136,6 +136,22 @@ static const struct ts_dmi_data chuwi_vi10_data = {
.properties = chuwi_vi10_props,
};
+static const struct property_entry chuwi_surbook_mini_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 88),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 13),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 2040),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1524),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-surbook-mini.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ { }
+};
+
+static const struct ts_dmi_data chuwi_surbook_mini_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = chuwi_surbook_mini_props,
+};
+
static const struct property_entry connect_tablet9_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
PROPERTY_ENTRY_U32("touchscreen-min-y", 10),
@@ -230,6 +246,24 @@ static const struct ts_dmi_data gp_electronic_t701_data = {
.properties = gp_electronic_t701_props,
};
+static const struct property_entry irbis_tw90_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1720),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1138),
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 8),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 14),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-irbis_tw90.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct ts_dmi_data irbis_tw90_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = irbis_tw90_props,
+};
+
static const struct property_entry itworks_tw891_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
@@ -647,6 +681,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
},
},
{
+ /* Chuwi Surbook Mini (CWI540) */
+ .driver_data = (void *)&chuwi_surbook_mini_data,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "C3W6_AP108_4G"),
+ },
+ },
+ {
/* Connect Tablet 9 */
.driver_data = (void *)&connect_tablet9_data,
.matches = {
@@ -709,6 +751,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
},
},
{
+ /* Irbis TW90 */
+ .driver_data = (void *)&irbis_tw90_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW90"),
+ },
+ },
+ {
/* I.T.Works TW891 */
.driver_data = (void *)&itworks_tw891_data,
.matches = {
@@ -884,6 +934,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
},
},
{
+ /* Trekstor Primebook C11B (same touchscreen as the C11) */
+ .driver_data = (void *)&trekstor_primebook_c11_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PRIMEBOOK C11B"),
+ },
+ },
+ {
/* Trekstor Primebook C13 */
.driver_data = (void *)&trekstor_primebook_c13_data,
.matches = {
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 784cea8572c2..59e9aa0f9643 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -340,9 +340,7 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
* expensive, but have no corresponding WCxx method. So we
* should not fail if this happens.
*/
- if (acpi_has_method(handle, wc_method))
- wc_status = acpi_execute_simple_method(handle,
- wc_method, 1);
+ wc_status = acpi_execute_simple_method(handle, wc_method, 1);
}
strcpy(method, "WQ");
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 30de448de802..86d88aec94a1 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -742,6 +742,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
USB_CH_IP_CUR_LVL_1P5;
break;
}
+ /* Else, fall through */
case USB_STAT_HM_IDGND:
dev_err(di->dev, "USB Type - Charging not allowed\n");
di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c
index 9fd6dd342169..94ddd7d659c8 100644
--- a/drivers/powercap/intel_rapl_common.c
+++ b/drivers/powercap/intel_rapl_common.c
@@ -957,27 +957,27 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
INTEL_CPU_FAM6(IVYBRIDGE, rapl_defaults_core),
INTEL_CPU_FAM6(IVYBRIDGE_X, rapl_defaults_core),
- INTEL_CPU_FAM6(HASWELL_CORE, rapl_defaults_core),
- INTEL_CPU_FAM6(HASWELL_ULT, rapl_defaults_core),
- INTEL_CPU_FAM6(HASWELL_GT3E, rapl_defaults_core),
+ INTEL_CPU_FAM6(HASWELL, rapl_defaults_core),
+ INTEL_CPU_FAM6(HASWELL_L, rapl_defaults_core),
+ INTEL_CPU_FAM6(HASWELL_G, rapl_defaults_core),
INTEL_CPU_FAM6(HASWELL_X, rapl_defaults_hsw_server),
- INTEL_CPU_FAM6(BROADWELL_CORE, rapl_defaults_core),
- INTEL_CPU_FAM6(BROADWELL_GT3E, rapl_defaults_core),
- INTEL_CPU_FAM6(BROADWELL_XEON_D, rapl_defaults_core),
+ INTEL_CPU_FAM6(BROADWELL, rapl_defaults_core),
+ INTEL_CPU_FAM6(BROADWELL_G, rapl_defaults_core),
+ INTEL_CPU_FAM6(BROADWELL_D, rapl_defaults_core),
INTEL_CPU_FAM6(BROADWELL_X, rapl_defaults_hsw_server),
- INTEL_CPU_FAM6(SKYLAKE_DESKTOP, rapl_defaults_core),
- INTEL_CPU_FAM6(SKYLAKE_MOBILE, rapl_defaults_core),
+ INTEL_CPU_FAM6(SKYLAKE, rapl_defaults_core),
+ INTEL_CPU_FAM6(SKYLAKE_L, rapl_defaults_core),
INTEL_CPU_FAM6(SKYLAKE_X, rapl_defaults_hsw_server),
- INTEL_CPU_FAM6(KABYLAKE_MOBILE, rapl_defaults_core),
- INTEL_CPU_FAM6(KABYLAKE_DESKTOP, rapl_defaults_core),
- INTEL_CPU_FAM6(CANNONLAKE_MOBILE, rapl_defaults_core),
- INTEL_CPU_FAM6(ICELAKE_MOBILE, rapl_defaults_core),
- INTEL_CPU_FAM6(ICELAKE_DESKTOP, rapl_defaults_core),
+ INTEL_CPU_FAM6(KABYLAKE_L, rapl_defaults_core),
+ INTEL_CPU_FAM6(KABYLAKE, rapl_defaults_core),
+ INTEL_CPU_FAM6(CANNONLAKE_L, rapl_defaults_core),
+ INTEL_CPU_FAM6(ICELAKE_L, rapl_defaults_core),
+ INTEL_CPU_FAM6(ICELAKE, rapl_defaults_core),
INTEL_CPU_FAM6(ICELAKE_NNPI, rapl_defaults_core),
INTEL_CPU_FAM6(ICELAKE_X, rapl_defaults_hsw_server),
- INTEL_CPU_FAM6(ICELAKE_XEON_D, rapl_defaults_hsw_server),
+ INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server),
INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt),
INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
@@ -985,8 +985,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
INTEL_CPU_FAM6(ATOM_AIRMONT_MID, rapl_defaults_ann),
INTEL_CPU_FAM6(ATOM_GOLDMONT, rapl_defaults_core),
INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, rapl_defaults_core),
- INTEL_CPU_FAM6(ATOM_GOLDMONT_X, rapl_defaults_core),
- INTEL_CPU_FAM6(ATOM_TREMONT_X, rapl_defaults_core),
+ INTEL_CPU_FAM6(ATOM_GOLDMONT_D, rapl_defaults_core),
+ INTEL_CPU_FAM6(ATOM_TREMONT_D, rapl_defaults_core),
INTEL_CPU_FAM6(XEON_PHI_KNL, rapl_defaults_hsw_server),
INTEL_CPU_FAM6(XEON_PHI_KNM, rapl_defaults_hsw_server),
@@ -1454,7 +1454,7 @@ static void __exit rapl_exit(void)
unregister_pm_notifier(&rapl_pm_notifier);
}
-module_init(rapl_init);
+fs_initcall(rapl_init);
module_exit(rapl_exit);
MODULE_DESCRIPTION("Intel Runtime Average Power Limit (RAPL) common code");
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index 540e8aafc990..f808c5fa9838 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -671,7 +671,7 @@ static int __init powercap_init(void)
return class_register(&powercap_class);
}
-device_initcall(powercap_init);
+fs_initcall(powercap_init);
MODULE_DESCRIPTION("PowerCap sysfs Driver");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c3ab07ab31a9..8edfac17364e 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -882,8 +882,11 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
return of_pwm_get(dev, dev->of_node, con_id);
/* then lookup via ACPI */
- if (dev && is_acpi_node(dev->fwnode))
- return acpi_pwm_get(dev->fwnode);
+ if (dev && is_acpi_node(dev->fwnode)) {
+ pwm = acpi_pwm_get(dev->fwnode);
+ if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT)
+ return pwm;
+ }
/*
* We look up the provider in the static table typically provided by
diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile
index ef6777e14d3d..6f0404f50107 100644
--- a/drivers/ras/Makefile
+++ b/drivers/ras/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_RAS) += ras.o debugfs.o
+obj-$(CONFIG_RAS) += ras.o
+obj-$(CONFIG_DEBUG_FS) += debugfs.o
obj-$(CONFIG_RAS_CEC) += cec.o
diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c
index 5d545806d930..c09cf55e2d20 100644
--- a/drivers/ras/cec.c
+++ b/drivers/ras/cec.c
@@ -4,6 +4,7 @@
*/
#include <linux/mm.h>
#include <linux/gfp.h>
+#include <linux/ras.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c
index 9c1b717efad8..0d4f985afbf3 100644
--- a/drivers/ras/debugfs.c
+++ b/drivers/ras/debugfs.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/debugfs.h>
+#include <linux/ras.h>
+#include "debugfs.h"
struct dentry *ras_debugfs_dir;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index b57093d7c01f..3ee63531f6d5 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -83,6 +83,7 @@ config REGULATOR_88PM8607
config REGULATOR_ACT8865
tristate "Active-semi act8865 voltage regulator"
depends on I2C
+ depends on POWER_SUPPLY
select REGMAP_I2C
help
This driver controls a active-semi act8865 voltage output
@@ -618,6 +619,15 @@ config REGULATOR_MT6323
This driver supports the control of different power rails of device
through regulator interface.
+config REGULATOR_MT6358
+ tristate "MediaTek MT6358 PMIC"
+ depends on MFD_MT6397 && BROKEN
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6358 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP
@@ -906,6 +916,13 @@ config REGULATOR_SY8106A
help
This driver supports SY8106A single output regulator.
+config REGULATOR_SY8824X
+ tristate "Silergy SY8824C/SY8824E regulator"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver supports SY8824C single output regulator.
+
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index eef73b5a35a4..2210ba56f9bd 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
+obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
@@ -111,6 +112,7 @@ obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
+obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index cf72d7c6b8c9..0fa97f934df4 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -16,8 +16,10 @@
#include <linux/regulator/act8865.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/power_supply.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regmap.h>
+#include <dt-bindings/regulator/active-semi,8865-regulator.h>
/*
* ACT8600 Global Register Map.
@@ -89,35 +91,50 @@
*/
#define ACT8865_SYS_MODE 0x00
#define ACT8865_SYS_CTRL 0x01
+#define ACT8865_SYS_UNLK_REGS 0x0b
#define ACT8865_DCDC1_VSET1 0x20
#define ACT8865_DCDC1_VSET2 0x21
#define ACT8865_DCDC1_CTRL 0x22
+#define ACT8865_DCDC1_SUS 0x24
#define ACT8865_DCDC2_VSET1 0x30
#define ACT8865_DCDC2_VSET2 0x31
#define ACT8865_DCDC2_CTRL 0x32
+#define ACT8865_DCDC2_SUS 0x34
#define ACT8865_DCDC3_VSET1 0x40
#define ACT8865_DCDC3_VSET2 0x41
#define ACT8865_DCDC3_CTRL 0x42
+#define ACT8865_DCDC3_SUS 0x44
#define ACT8865_LDO1_VSET 0x50
#define ACT8865_LDO1_CTRL 0x51
+#define ACT8865_LDO1_SUS 0x52
#define ACT8865_LDO2_VSET 0x54
#define ACT8865_LDO2_CTRL 0x55
+#define ACT8865_LDO2_SUS 0x56
#define ACT8865_LDO3_VSET 0x60
#define ACT8865_LDO3_CTRL 0x61
+#define ACT8865_LDO3_SUS 0x62
#define ACT8865_LDO4_VSET 0x64
#define ACT8865_LDO4_CTRL 0x65
+#define ACT8865_LDO4_SUS 0x66
#define ACT8865_MSTROFF 0x20
/*
* Field Definitions.
*/
#define ACT8865_ENA 0x80 /* ON - [7] */
+#define ACT8865_DIS 0x40 /* DIS - [6] */
+
#define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */
#define ACT8600_LDO10_ENA 0x40 /* ON - [6] */
#define ACT8600_SUDCDC_VSEL_MASK 0xFF /* SUDCDC VSET - [7:0] */
+#define ACT8600_APCH_CHG_ACIN BIT(7)
+#define ACT8600_APCH_CHG_USB BIT(6)
+#define ACT8600_APCH_CSTATE0 BIT(5)
+#define ACT8600_APCH_CSTATE1 BIT(4)
+
/*
* ACT8865 voltage number
*/
@@ -217,6 +234,171 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0),
};
+static int act8865_set_suspend_state(struct regulator_dev *rdev, bool enable)
+{
+ struct regmap *regmap = rdev->regmap;
+ int id = rdev->desc->id, reg, val;
+
+ switch (id) {
+ case ACT8865_ID_DCDC1:
+ reg = ACT8865_DCDC1_SUS;
+ val = 0xa8;
+ break;
+ case ACT8865_ID_DCDC2:
+ reg = ACT8865_DCDC2_SUS;
+ val = 0xa8;
+ break;
+ case ACT8865_ID_DCDC3:
+ reg = ACT8865_DCDC3_SUS;
+ val = 0xa8;
+ break;
+ case ACT8865_ID_LDO1:
+ reg = ACT8865_LDO1_SUS;
+ val = 0xe8;
+ break;
+ case ACT8865_ID_LDO2:
+ reg = ACT8865_LDO2_SUS;
+ val = 0xe8;
+ break;
+ case ACT8865_ID_LDO3:
+ reg = ACT8865_LDO3_SUS;
+ val = 0xe8;
+ break;
+ case ACT8865_ID_LDO4:
+ reg = ACT8865_LDO4_SUS;
+ val = 0xe8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (enable)
+ val |= BIT(4);
+
+ /*
+ * Ask the PMIC to enable/disable this output when entering hibernate
+ * mode.
+ */
+ return regmap_write(regmap, reg, val);
+}
+
+static int act8865_set_suspend_enable(struct regulator_dev *rdev)
+{
+ return act8865_set_suspend_state(rdev, true);
+}
+
+static int act8865_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return act8865_set_suspend_state(rdev, false);
+}
+
+static unsigned int act8865_of_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case ACT8865_REGULATOR_MODE_FIXED:
+ return REGULATOR_MODE_FAST;
+ case ACT8865_REGULATOR_MODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case ACT8865_REGULATOR_MODE_LOWPOWER:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static int act8865_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct regmap *regmap = rdev->regmap;
+ int id = rdev_get_id(rdev);
+ int reg, val = 0;
+
+ switch (id) {
+ case ACT8865_ID_DCDC1:
+ reg = ACT8865_DCDC1_CTRL;
+ break;
+ case ACT8865_ID_DCDC2:
+ reg = ACT8865_DCDC2_CTRL;
+ break;
+ case ACT8865_ID_DCDC3:
+ reg = ACT8865_DCDC3_CTRL;
+ break;
+ case ACT8865_ID_LDO1:
+ reg = ACT8865_LDO1_CTRL;
+ break;
+ case ACT8865_ID_LDO2:
+ reg = ACT8865_LDO2_CTRL;
+ break;
+ case ACT8865_ID_LDO3:
+ reg = ACT8865_LDO3_CTRL;
+ break;
+ case ACT8865_ID_LDO4:
+ reg = ACT8865_LDO4_CTRL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ case REGULATOR_MODE_NORMAL:
+ if (id <= ACT8865_ID_DCDC3)
+ val = BIT(5);
+ break;
+ case REGULATOR_MODE_STANDBY:
+ if (id > ACT8865_ID_DCDC3)
+ val = BIT(5);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(regmap, reg, BIT(5), val);
+}
+
+static unsigned int act8865_get_mode(struct regulator_dev *rdev)
+{
+ struct regmap *regmap = rdev->regmap;
+ int id = rdev_get_id(rdev);
+ int reg, ret, val = 0;
+
+ switch (id) {
+ case ACT8865_ID_DCDC1:
+ reg = ACT8865_DCDC1_CTRL;
+ break;
+ case ACT8865_ID_DCDC2:
+ reg = ACT8865_DCDC2_CTRL;
+ break;
+ case ACT8865_ID_DCDC3:
+ reg = ACT8865_DCDC3_CTRL;
+ break;
+ case ACT8865_ID_LDO1:
+ reg = ACT8865_LDO1_CTRL;
+ break;
+ case ACT8865_ID_LDO2:
+ reg = ACT8865_LDO2_CTRL;
+ break;
+ case ACT8865_ID_LDO3:
+ reg = ACT8865_LDO3_CTRL;
+ break;
+ case ACT8865_ID_LDO4:
+ reg = ACT8865_LDO4_CTRL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ if (id <= ACT8865_ID_DCDC3 && (val & BIT(5)))
+ return REGULATOR_MODE_FAST;
+ else if (id > ACT8865_ID_DCDC3 && !(val & BIT(5)))
+ return REGULATOR_MODE_NORMAL;
+ else
+ return REGULATOR_MODE_STANDBY;
+}
+
static const struct regulator_ops act8865_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
@@ -224,24 +406,44 @@ static const struct regulator_ops act8865_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
+ .set_mode = act8865_set_mode,
+ .get_mode = act8865_get_mode,
.is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = act8865_set_suspend_enable,
+ .set_suspend_disable = act8865_set_suspend_disable,
};
static const struct regulator_ops act8865_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_mode = act8865_set_mode,
+ .get_mode = act8865_get_mode,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = act8865_set_suspend_enable,
+ .set_suspend_disable = act8865_set_suspend_disable,
+ .set_pull_down = regulator_set_pull_down_regmap,
+};
+
+static const struct regulator_ops act8865_fixed_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
-#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \
+#define ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, _ops) \
[_family##_ID_##_id] = { \
.name = _name, \
.of_match = of_match_ptr(_name), \
+ .of_map_mode = act8865_of_map_mode, \
.regulators_node = of_match_ptr("regulators"), \
.supply_name = _supply, \
.id = _family##_ID_##_id, \
.type = REGULATOR_VOLTAGE, \
- .ops = &act8865_ops, \
+ .ops = _ops, \
.n_voltages = ACT8865_VOLTAGE_NUM, \
.linear_ranges = act8865_voltage_ranges, \
.n_linear_ranges = ARRAY_SIZE(act8865_voltage_ranges), \
@@ -249,9 +451,17 @@ static const struct regulator_ops act8865_ldo_ops = {
.vsel_mask = ACT8865_VSEL_MASK, \
.enable_reg = _family##_##_id##_CTRL, \
.enable_mask = ACT8865_ENA, \
+ .pull_down_reg = _family##_##_id##_CTRL, \
+ .pull_down_mask = ACT8865_DIS, \
.owner = THIS_MODULE, \
}
+#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \
+ ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ops)
+
+#define ACT88xx_LDO(_name, _family, _id, _vsel_reg, _supply) \
+ ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ldo_ops)
+
static const struct regulator_desc act8600_regulators[] = {
ACT88xx_REG("DCDC1", ACT8600, DCDC1, VSET, "vp1"),
ACT88xx_REG("DCDC2", ACT8600, DCDC2, VSET, "vp2"),
@@ -281,7 +491,7 @@ static const struct regulator_desc act8600_regulators[] = {
.of_match = of_match_ptr("LDO_REG9"),
.regulators_node = of_match_ptr("regulators"),
.id = ACT8600_ID_LDO9,
- .ops = &act8865_ldo_ops,
+ .ops = &act8865_fixed_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
.fixed_uV = 3300000,
@@ -294,7 +504,7 @@ static const struct regulator_desc act8600_regulators[] = {
.of_match = of_match_ptr("LDO_REG10"),
.regulators_node = of_match_ptr("regulators"),
.id = ACT8600_ID_LDO10,
- .ops = &act8865_ldo_ops,
+ .ops = &act8865_fixed_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
.fixed_uV = 1200000,
@@ -323,20 +533,20 @@ static const struct regulator_desc act8865_regulators[] = {
ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"),
ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"),
ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"),
- ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
- ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
- ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
- ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
+ ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
+ ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
+ ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
+ ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
};
static const struct regulator_desc act8865_alt_regulators[] = {
ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET2, "vp1"),
ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET2, "vp2"),
ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET2, "vp3"),
- ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
- ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
- ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
- ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
+ ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
+ ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
+ ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
+ ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
};
#ifdef CONFIG_OF
@@ -372,6 +582,75 @@ static void act8865_power_off(void)
while (1);
}
+static int act8600_charger_get_status(struct regmap *map)
+{
+ unsigned int val;
+ int ret;
+ u8 state0, state1;
+
+ ret = regmap_read(map, ACT8600_APCH_STAT, &val);
+ if (ret < 0)
+ return ret;
+
+ state0 = val & ACT8600_APCH_CSTATE0;
+ state1 = val & ACT8600_APCH_CSTATE1;
+
+ if (state0 && !state1)
+ return POWER_SUPPLY_STATUS_CHARGING;
+ if (!state0 && state1)
+ return POWER_SUPPLY_STATUS_NOT_CHARGING;
+ if (!state0 && !state1)
+ return POWER_SUPPLY_STATUS_DISCHARGING;
+
+ return POWER_SUPPLY_STATUS_UNKNOWN;
+}
+
+static int act8600_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp, union power_supply_propval *val)
+{
+ struct regmap *map = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = act8600_charger_get_status(map);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property act8600_charger_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+};
+
+static const struct power_supply_desc act8600_charger_desc = {
+ .name = "act8600-charger",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = act8600_charger_properties,
+ .num_properties = ARRAY_SIZE(act8600_charger_properties),
+ .get_property = act8600_charger_get_property,
+};
+
+static int act8600_charger_probe(struct device *dev, struct regmap *regmap)
+{
+ struct power_supply *charger;
+ struct power_supply_config cfg = {
+ .drv_data = regmap,
+ .of_node = dev->of_node,
+ };
+
+ charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg);
+
+ return PTR_ERR_OR_ZERO(charger);
+}
+
static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
@@ -483,9 +762,20 @@ static int act8865_pmic_probe(struct i2c_client *client,
}
}
+ if (type == ACT8600) {
+ ret = act8600_charger_probe(dev, act8865->regmap);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to probe charger");
+ return ret;
+ }
+ }
+
i2c_set_clientdata(client, act8865);
- return 0;
+ /* Unlock expert registers for ACT8865. */
+ return type != ACT8865 ? 0 : regmap_write(act8865->regmap,
+ ACT8865_SYS_UNLK_REGS, 0xef);
}
static const struct i2c_device_id act8865_ids[] = {
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
index 584284938ac9..d2f804dbc785 100644
--- a/drivers/regulator/act8945a-regulator.c
+++ b/drivers/regulator/act8945a-regulator.c
@@ -169,16 +169,16 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
reg = ACT8945A_DCDC3_CTRL;
break;
case ACT8945A_ID_LDO1:
- reg = ACT8945A_LDO1_SUS;
+ reg = ACT8945A_LDO1_CTRL;
break;
case ACT8945A_ID_LDO2:
- reg = ACT8945A_LDO2_SUS;
+ reg = ACT8945A_LDO2_CTRL;
break;
case ACT8945A_ID_LDO3:
- reg = ACT8945A_LDO3_SUS;
+ reg = ACT8945A_LDO3_CTRL;
break;
case ACT8945A_ID_LDO4:
- reg = ACT8945A_LDO4_SUS;
+ reg = ACT8945A_LDO4_CTRL;
break;
default:
return -EINVAL;
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 152053361862..989506bd90b1 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -174,14 +174,14 @@
#define AXP803_DCDC5_1140mV_STEPS 35
#define AXP803_DCDC5_1140mV_END \
(AXP803_DCDC5_1140mV_START + AXP803_DCDC5_1140mV_STEPS)
-#define AXP803_DCDC5_NUM_VOLTAGES 68
+#define AXP803_DCDC5_NUM_VOLTAGES 69
#define AXP803_DCDC6_600mV_START 0x00
#define AXP803_DCDC6_600mV_STEPS 50
#define AXP803_DCDC6_600mV_END \
(AXP803_DCDC6_600mV_START + AXP803_DCDC6_600mV_STEPS)
#define AXP803_DCDC6_1120mV_START 0x33
-#define AXP803_DCDC6_1120mV_STEPS 14
+#define AXP803_DCDC6_1120mV_STEPS 20
#define AXP803_DCDC6_1120mV_END \
(AXP803_DCDC6_1120mV_START + AXP803_DCDC6_1120mV_STEPS)
#define AXP803_DCDC6_NUM_VOLTAGES 72
@@ -240,7 +240,7 @@
#define AXP806_DCDCA_600mV_END \
(AXP806_DCDCA_600mV_START + AXP806_DCDCA_600mV_STEPS)
#define AXP806_DCDCA_1120mV_START 0x33
-#define AXP806_DCDCA_1120mV_STEPS 14
+#define AXP806_DCDCA_1120mV_STEPS 20
#define AXP806_DCDCA_1120mV_END \
(AXP806_DCDCA_1120mV_START + AXP806_DCDCA_1120mV_STEPS)
#define AXP806_DCDCA_NUM_VOLTAGES 72
@@ -774,8 +774,8 @@ static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
AXP806_DCDCD_600mV_END,
20000),
REGULATOR_LINEAR_RANGE(1600000,
- AXP806_DCDCD_600mV_START,
- AXP806_DCDCD_600mV_END,
+ AXP806_DCDCD_1600mV_START,
+ AXP806_DCDCD_1600mV_END,
100000),
};
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e0c0cf462004..afe94470b67f 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -381,12 +381,16 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,
if (!regnode) {
regnode = of_get_child_regulator(child, prop_name);
if (regnode)
- return regnode;
+ goto err_node_put;
} else {
- return regnode;
+ goto err_node_put;
}
}
return NULL;
+
+err_node_put:
+ of_node_put(child);
+ return regnode;
}
/**
@@ -564,13 +568,15 @@ static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- ssize_t ret;
+ int uV;
regulator_lock(rdev);
- ret = sprintf(buf, "%d\n", regulator_get_voltage_rdev(rdev));
+ uV = regulator_get_voltage_rdev(rdev);
regulator_unlock(rdev);
- return ret;
+ if (uV < 0)
+ return uV;
+ return sprintf(buf, "%d\n", uV);
}
static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
@@ -5640,7 +5646,7 @@ static int __init regulator_init(void)
/* init early to allow our consumers to complete system booting */
core_initcall(regulator_init);
-static int __init regulator_late_cleanup(struct device *dev, void *data)
+static int regulator_late_cleanup(struct device *dev, void *data)
{
struct regulator_dev *rdev = dev_to_rdev(dev);
const struct regulator_ops *ops = rdev->desc->ops;
@@ -5689,18 +5695,9 @@ unlock:
return 0;
}
-static int __init regulator_init_complete(void)
+static void regulator_init_complete_work_function(struct work_struct *work)
{
/*
- * Since DT doesn't provide an idiomatic mechanism for
- * enabling full constraints and since it's much more natural
- * with DT to provide them just assume that a DT enabled
- * system has full constraints.
- */
- if (of_have_populated_dt())
- has_full_constraints = true;
-
- /*
* Regulators may had failed to resolve their input supplies
* when were registered, either because the input supply was
* not registered yet or because its parent device was not
@@ -5717,6 +5714,35 @@ static int __init regulator_init_complete(void)
*/
class_for_each_device(&regulator_class, NULL, NULL,
regulator_late_cleanup);
+}
+
+static DECLARE_DELAYED_WORK(regulator_init_complete_work,
+ regulator_init_complete_work_function);
+
+static int __init regulator_init_complete(void)
+{
+ /*
+ * Since DT doesn't provide an idiomatic mechanism for
+ * enabling full constraints and since it's much more natural
+ * with DT to provide them just assume that a DT enabled
+ * system has full constraints.
+ */
+ if (of_have_populated_dt())
+ has_full_constraints = true;
+
+ /*
+ * We punt completion for an arbitrary amount of time since
+ * systems like distros will load many drivers from userspace
+ * so consumers might not always be ready yet, this is
+ * particularly an issue with laptops where this might bounce
+ * the display off then on. Ideally we'd get a notification
+ * from userspace when this happens but we don't so just wait
+ * a bit and hope we waited long enough. It'd be better if
+ * we'd only do this on systems that need it, and a kernel
+ * command line option might be useful.
+ */
+ schedule_delayed_work(&regulator_init_complete_work,
+ msecs_to_jiffies(30000));
return 0;
}
diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index 2ffc64622451..56f3f72d7707 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -1032,10 +1032,8 @@ static int da9062_regulator_probe(struct platform_device *pdev)
/* LDOs overcurrent event support */
irq = platform_get_irq_byname(pdev, "LDO_LIM");
- if (irq < 0) {
- dev_err(&pdev->dev, "Failed to get IRQ.\n");
+ if (irq < 0)
return irq;
- }
regulators->irq_ldo_lim = irq;
ret = devm_request_threaded_irq(&pdev->dev, irq,
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 02f816318fba..28b1b20f45bd 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -863,10 +863,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
/* LDOs overcurrent event support */
irq = platform_get_irq_byname(pdev, "LDO_LIM");
- if (irq < 0) {
- dev_err(&pdev->dev, "Failed to get IRQ.\n");
+ if (irq < 0)
return irq;
- }
ret = devm_request_threaded_irq(&pdev->dev, irq,
NULL, da9063_ldo_lim_event,
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index 0309823d2c72..bf80748f1ccc 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -285,7 +285,7 @@ static struct da9211_pdata *da9211_parse_regulators_dt(
pdata->reg_node[n] = da9211_matches[i].of_node;
pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev,
da9211_matches[i].of_node,
- "enable",
+ "enable-gpios",
0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"da9211-enable");
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 999547dde99d..d90a6fd8cbc7 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -23,14 +23,63 @@
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
+#include <linux/clk.h>
+
struct fixed_voltage_data {
struct regulator_desc desc;
struct regulator_dev *dev;
+
+ struct clk *enable_clock;
+ unsigned int clk_enable_counter;
};
+struct fixed_dev_type {
+ bool has_enable_clock;
+};
+
+static const struct fixed_dev_type fixed_voltage_data = {
+ .has_enable_clock = false,
+};
+
+static const struct fixed_dev_type fixed_clkenable_data = {
+ .has_enable_clock = true,
+};
+
+static int reg_clock_enable(struct regulator_dev *rdev)
+{
+ struct fixed_voltage_data *priv = rdev_get_drvdata(rdev);
+ int ret = 0;
+
+ ret = clk_prepare_enable(priv->enable_clock);
+ if (ret)
+ return ret;
+
+ priv->clk_enable_counter++;
+
+ return ret;
+}
+
+static int reg_clock_disable(struct regulator_dev *rdev)
+{
+ struct fixed_voltage_data *priv = rdev_get_drvdata(rdev);
+
+ clk_disable_unprepare(priv->enable_clock);
+ priv->clk_enable_counter--;
+
+ return 0;
+}
+
+static int reg_clock_is_enabled(struct regulator_dev *rdev)
+{
+ struct fixed_voltage_data *priv = rdev_get_drvdata(rdev);
+
+ return priv->clk_enable_counter > 0;
+}
+
/**
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info
@@ -84,10 +133,19 @@ of_get_fixed_voltage_config(struct device *dev,
static struct regulator_ops fixed_voltage_ops = {
};
+static struct regulator_ops fixed_voltage_clkenabled_ops = {
+ .enable = reg_clock_enable,
+ .disable = reg_clock_disable,
+ .is_enabled = reg_clock_is_enabled,
+};
+
static int reg_fixed_voltage_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct fixed_voltage_config *config;
struct fixed_voltage_data *drvdata;
+ const struct fixed_dev_type *drvtype =
+ of_match_device(dev->driver->of_match_table, dev)->data;
struct regulator_config cfg = { };
enum gpiod_flags gflags;
int ret;
@@ -118,7 +176,18 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
}
drvdata->desc.type = REGULATOR_VOLTAGE;
drvdata->desc.owner = THIS_MODULE;
- drvdata->desc.ops = &fixed_voltage_ops;
+
+ if (drvtype->has_enable_clock) {
+ drvdata->desc.ops = &fixed_voltage_clkenabled_ops;
+
+ drvdata->enable_clock = devm_clk_get(dev, NULL);
+ if (IS_ERR(drvdata->enable_clock)) {
+ dev_err(dev, "Cant get enable-clock from devicetree\n");
+ return -ENOENT;
+ }
+ } else {
+ drvdata->desc.ops = &fixed_voltage_ops;
+ }
drvdata->desc.enable_time = config->startup_delay;
@@ -191,8 +260,16 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
#if defined(CONFIG_OF)
static const struct of_device_id fixed_of_match[] = {
- { .compatible = "regulator-fixed", },
- {},
+ {
+ .compatible = "regulator-fixed",
+ .data = &fixed_voltage_data,
+ },
+ {
+ .compatible = "regulator-fixed-clock",
+ .data = &fixed_clkenable_data,
+ },
+ {
+ },
};
MODULE_DEVICE_TABLE(of, fixed_of_match);
#endif
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 4986cc5064a1..ca3dc3f3bb29 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -860,3 +860,24 @@ int regulator_get_current_limit_regmap(struct regulator_dev *rdev)
return -EINVAL;
}
EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap);
+
+/**
+ * regulator_bulk_set_supply_names - initialize the 'supply' fields in an array
+ * of regulator_bulk_data structs
+ *
+ * @consumers: array of regulator_bulk_data entries to initialize
+ * @supply_names: array of supply name strings
+ * @num_supplies: number of supply names to initialize
+ *
+ * Note: the 'consumers' array must be the size of 'num_supplies'.
+ */
+void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers,
+ const char *const *supply_names,
+ unsigned int num_supplies)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_supplies; i++)
+ consumers[i].supply = supply_names[i];
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_set_supply_names);
diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c
index 5647e2f97ff8..4b9f618b07e9 100644
--- a/drivers/regulator/lm363x-regulator.c
+++ b/drivers/regulator/lm363x-regulator.c
@@ -30,13 +30,13 @@
/* LM3632 */
#define LM3632_BOOST_VSEL_MAX 0x26
-#define LM3632_LDO_VSEL_MAX 0x29
+#define LM3632_LDO_VSEL_MAX 0x28
#define LM3632_VBOOST_MIN 4500000
#define LM3632_VLDO_MIN 4000000
/* LM36274 */
#define LM36274_BOOST_VSEL_MAX 0x3f
-#define LM36274_LDO_VSEL_MAX 0x34
+#define LM36274_LDO_VSEL_MAX 0x32
#define LM36274_VOLTAGE_MIN 4000000
/* Common */
@@ -226,7 +226,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = {
.of_match = "vboost",
.id = LM36274_BOOST,
.ops = &lm363x_boost_voltage_table_ops,
- .n_voltages = LM36274_BOOST_VSEL_MAX,
+ .n_voltages = LM36274_BOOST_VSEL_MAX + 1,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
@@ -239,7 +239,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = {
.of_match = "vpos",
.id = LM36274_LDO_POS,
.ops = &lm363x_regulator_voltage_table_ops,
- .n_voltages = LM36274_LDO_VSEL_MAX,
+ .n_voltages = LM36274_LDO_VSEL_MAX + 1,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
@@ -254,7 +254,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = {
.of_match = "vneg",
.id = LM36274_LDO_NEG,
.ops = &lm363x_regulator_voltage_table_ops,
- .n_voltages = LM36274_LDO_VSEL_MAX,
+ .n_voltages = LM36274_LDO_VSEL_MAX + 1,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c
index 5d067f7c2116..4ae12ac1f4c6 100644
--- a/drivers/regulator/lp87565-regulator.c
+++ b/drivers/regulator/lp87565-regulator.c
@@ -65,7 +65,6 @@ static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay)
{
int id = rdev_get_id(rdev);
- struct lp87565 *lp87565 = rdev_get_drvdata(rdev);
unsigned int reg;
int ret;
@@ -86,11 +85,11 @@ static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev,
else
reg = 0;
- ret = regmap_update_bits(lp87565->regmap, regulators[id].ctrl2_reg,
+ ret = regmap_update_bits(rdev->regmap, regulators[id].ctrl2_reg,
LP87565_BUCK_CTRL_2_SLEW_RATE,
reg << __ffs(LP87565_BUCK_CTRL_2_SLEW_RATE));
if (ret) {
- dev_err(lp87565->dev, "SLEW RATE write failed: %d\n", ret);
+ dev_err(&rdev->dev, "SLEW RATE write failed: %d\n", ret);
return ret;
}
@@ -163,7 +162,7 @@ static int lp87565_regulator_probe(struct platform_device *pdev)
struct lp87565 *lp87565 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
- int i, min_idx = LP87565_BUCK_0, max_idx = LP87565_BUCK_3;
+ int i, min_idx, max_idx;
platform_set_drvdata(pdev, lp87565);
@@ -182,9 +181,9 @@ static int lp87565_regulator_probe(struct platform_device *pdev)
max_idx = LP87565_BUCK_3210;
break;
default:
- dev_err(lp87565->dev, "Invalid lp config %d\n",
- lp87565->dev_type);
- return -EINVAL;
+ min_idx = LP87565_BUCK_0;
+ max_idx = LP87565_BUCK_3;
+ break;
}
for (i = min_idx; i <= max_idx; i++) {
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 1b00f3638996..00e9bb92c326 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -464,7 +464,7 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
{
struct lp8788 *lp = ldo->lp;
enum lp8788_ext_ldo_en_id enable_id;
- u8 en_mask[] = {
+ static const u8 en_mask[] = {
[EN_ALDO1] = LP8788_EN_SEL_ALDO1_M,
[EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
[EN_ALDO5] = LP8788_EN_SEL_ALDO5_M,
diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c
index 8020eb57374a..c8e579e99316 100644
--- a/drivers/regulator/max77686-regulator.c
+++ b/drivers/regulator/max77686-regulator.c
@@ -257,7 +257,7 @@ static int max77686_of_parse_cb(struct device_node *np,
case MAX77686_BUCK9:
case MAX77686_LDO20 ... MAX77686_LDO22:
config->ena_gpiod = gpiod_get_from_of_node(np,
- "maxim,ena",
+ "maxim,ena-gpios",
0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"max77686-regulator");
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 4bca54446287..347043a5a9a7 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -485,7 +485,6 @@ static int max8660_probe(struct i2c_client *client,
rdev = devm_regulator_register(&client->dev,
&max8660_reg[id], &config);
if (IS_ERR(rdev)) {
- ret = PTR_ERR(rdev);
dev_err(&client->dev, "failed to register %s\n",
max8660_reg[id].name);
return PTR_ERR(rdev);
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
new file mode 100644
index 000000000000..ba42682e06f3
--- /dev/null
+++ b/drivers/regulator/mt6358-regulator.c
@@ -0,0 +1,549 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/mfd/mt6358/registers.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/mt6358-regulator.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MT6358_BUCK_MODE_AUTO 0
+#define MT6358_BUCK_MODE_FORCE_PWM 1
+
+/*
+ * MT6358 regulators' information
+ *
+ * @desc: standard fields of regulator description.
+ * @qi: Mask for query enable signal status of regulators
+ */
+struct mt6358_regulator_info {
+ struct regulator_desc desc;
+ u32 status_reg;
+ u32 qi;
+ const u32 *index_table;
+ unsigned int n_table;
+ u32 vsel_shift;
+ u32 da_vsel_reg;
+ u32 da_vsel_mask;
+ u32 da_vsel_shift;
+ u32 modeset_reg;
+ u32 modeset_mask;
+ u32 modeset_shift;
+};
+
+#define MT6358_BUCK(match, vreg, min, max, step, \
+ volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \
+ _da_vsel_shift, _modeset_reg, _modeset_shift) \
+[MT6358_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6358_volt_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6358_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = MT6358_BUCK_##vreg##_CON0, \
+ .enable_mask = BIT(0), \
+ .of_map_mode = mt6358_map_mode, \
+ }, \
+ .status_reg = MT6358_BUCK_##vreg##_DBG1, \
+ .qi = BIT(0), \
+ .da_vsel_reg = _da_vsel_reg, \
+ .da_vsel_mask = _da_vsel_mask, \
+ .da_vsel_shift = _da_vsel_shift, \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = BIT(_modeset_shift), \
+ .modeset_shift = _modeset_shift \
+}
+
+#define MT6358_LDO(match, vreg, ldo_volt_table, \
+ ldo_index_table, enreg, enbit, vosel, \
+ vosel_mask, vosel_shift) \
+[MT6358_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6358_volt_table_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6358_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
+ .volt_table = ldo_volt_table, \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ }, \
+ .status_reg = MT6358_LDO_##vreg##_CON1, \
+ .qi = BIT(15), \
+ .index_table = ldo_index_table, \
+ .n_table = ARRAY_SIZE(ldo_index_table), \
+ .vsel_shift = vosel_shift, \
+}
+
+#define MT6358_LDO1(match, vreg, min, max, step, \
+ volt_ranges, _da_vsel_reg, _da_vsel_mask, \
+ _da_vsel_shift, vosel, vosel_mask) \
+[MT6358_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6358_volt_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6358_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = MT6358_LDO_##vreg##_CON0, \
+ .enable_mask = BIT(0), \
+ }, \
+ .da_vsel_reg = _da_vsel_reg, \
+ .da_vsel_mask = _da_vsel_mask, \
+ .da_vsel_shift = _da_vsel_shift, \
+ .status_reg = MT6358_LDO_##vreg##_DBG1, \
+ .qi = BIT(0), \
+}
+
+#define MT6358_REG_FIXED(match, vreg, \
+ enreg, enbit, volt) \
+[MT6358_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6358_volt_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6358_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = 1, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .min_uV = volt, \
+ }, \
+ .status_reg = MT6358_LDO_##vreg##_CON1, \
+ .qi = BIT(15), \
+}
+
+static const struct regulator_linear_range buck_volt_range1[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
+};
+
+static const struct regulator_linear_range buck_volt_range2[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500),
+};
+
+static const struct regulator_linear_range buck_volt_range3[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
+};
+
+static const struct regulator_linear_range buck_volt_range4[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500),
+};
+
+static const u32 vdram2_voltages[] = {
+ 600000, 1800000,
+};
+
+static const u32 vsim_voltages[] = {
+ 1700000, 1800000, 2700000, 3000000, 3100000,
+};
+
+static const u32 vibr_voltages[] = {
+ 1200000, 1300000, 1500000, 1800000,
+ 2000000, 2800000, 3000000, 3300000,
+};
+
+static const u32 vusb_voltages[] = {
+ 3000000, 3100000,
+};
+
+static const u32 vcamd_voltages[] = {
+ 900000, 1000000, 1100000, 1200000,
+ 1300000, 1500000, 1800000,
+};
+
+static const u32 vefuse_voltages[] = {
+ 1700000, 1800000, 1900000,
+};
+
+static const u32 vmch_vemc_voltages[] = {
+ 2900000, 3000000, 3300000,
+};
+
+static const u32 vcama_voltages[] = {
+ 1800000, 2500000, 2700000,
+ 2800000, 2900000, 3000000,
+};
+
+static const u32 vcn33_bt_wifi_voltages[] = {
+ 3300000, 3400000, 3500000,
+};
+
+static const u32 vmc_voltages[] = {
+ 1800000, 2900000, 3000000, 3300000,
+};
+
+static const u32 vldo28_voltages[] = {
+ 2800000, 3000000,
+};
+
+static const u32 vdram2_idx[] = {
+ 0, 12,
+};
+
+static const u32 vsim_idx[] = {
+ 3, 4, 8, 11, 12,
+};
+
+static const u32 vibr_idx[] = {
+ 0, 1, 2, 4, 5, 9, 11, 13,
+};
+
+static const u32 vusb_idx[] = {
+ 3, 4,
+};
+
+static const u32 vcamd_idx[] = {
+ 3, 4, 5, 6, 7, 9, 12,
+};
+
+static const u32 vefuse_idx[] = {
+ 11, 12, 13,
+};
+
+static const u32 vmch_vemc_idx[] = {
+ 2, 3, 5,
+};
+
+static const u32 vcama_idx[] = {
+ 0, 7, 9, 10, 11, 12,
+};
+
+static const u32 vcn33_bt_wifi_idx[] = {
+ 1, 2, 3,
+};
+
+static const u32 vmc_idx[] = {
+ 4, 10, 11, 13,
+};
+
+static const u32 vldo28_idx[] = {
+ 1, 3,
+};
+
+static unsigned int mt6358_map_mode(unsigned int mode)
+{
+ return mode == MT6358_BUCK_MODE_AUTO ?
+ REGULATOR_MODE_NORMAL : REGULATOR_MODE_FAST;
+}
+
+static int mt6358_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ int idx, ret;
+ const u32 *pvol;
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+
+ pvol = info->index_table;
+
+ idx = pvol[selector];
+ ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg,
+ info->desc.vsel_mask,
+ idx << info->vsel_shift);
+
+ return ret;
+}
+
+static int mt6358_get_voltage_sel(struct regulator_dev *rdev)
+{
+ int idx, ret;
+ u32 selector;
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+ const u32 *pvol;
+
+ ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector);
+ if (ret != 0) {
+ dev_info(&rdev->dev,
+ "Failed to get mt6358 %s vsel reg: %d\n",
+ info->desc.name, ret);
+ return ret;
+ }
+
+ selector = (selector & info->desc.vsel_mask) >> info->vsel_shift;
+ pvol = info->index_table;
+ for (idx = 0; idx < info->desc.n_voltages; idx++) {
+ if (pvol[idx] == selector)
+ return idx;
+ }
+
+ return -EINVAL;
+}
+
+static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev)
+{
+ int ret, regval;
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->da_vsel_reg, &regval);
+ if (ret != 0) {
+ dev_err(&rdev->dev,
+ "Failed to get mt6358 Buck %s vsel reg: %d\n",
+ info->desc.name, ret);
+ return ret;
+ }
+
+ ret = (regval >> info->da_vsel_shift) & info->da_vsel_mask;
+
+ return ret;
+}
+
+static int mt6358_get_status(struct regulator_dev *rdev)
+{
+ int ret;
+ u32 regval;
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->status_reg, &regval);
+ if (ret != 0) {
+ dev_info(&rdev->dev, "Failed to get enable reg: %d\n", ret);
+ return ret;
+ }
+
+ return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
+}
+
+static int mt6358_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+ int val;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = MT6358_BUCK_MODE_FORCE_PWM;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = MT6358_BUCK_MODE_AUTO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x, %#x\n",
+ info->modeset_reg, info->modeset_mask,
+ info->modeset_shift, val);
+
+ val <<= info->modeset_shift;
+
+ return regmap_update_bits(rdev->regmap, info->modeset_reg,
+ info->modeset_mask, val);
+}
+
+static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+ int ret, regval;
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
+ if (ret != 0) {
+ dev_err(&rdev->dev,
+ "Failed to get mt6358 buck mode: %d\n", ret);
+ return ret;
+ }
+
+ switch ((regval & info->modeset_mask) >> info->modeset_shift) {
+ case MT6358_BUCK_MODE_AUTO:
+ return REGULATOR_MODE_NORMAL;
+ case MT6358_BUCK_MODE_FORCE_PWM:
+ return REGULATOR_MODE_FAST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct regulator_ops mt6358_volt_range_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = mt6358_get_buck_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6358_get_status,
+ .set_mode = mt6358_regulator_set_mode,
+ .get_mode = mt6358_regulator_get_mode,
+};
+
+static const struct regulator_ops mt6358_volt_table_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = mt6358_set_voltage_sel,
+ .get_voltage_sel = mt6358_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6358_get_status,
+};
+
+static const struct regulator_ops mt6358_volt_fixed_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6358_get_status,
+};
+
+/* The array is indexed by id(MT6358_ID_XXX) */
+static struct mt6358_regulator_info mt6358_regulators[] = {
+ MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
+ buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f,
+ 0, MT6358_VDRAM1_ANA_CON0, 8),
+ MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
+ buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
+ 0, MT6358_VCORE_VGPU_ANA_CON0, 1),
+ MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
+ buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, 0,
+ MT6358_VPA_ANA_CON0, 3),
+ MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
+ buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f,
+ 0, MT6358_VPROC_ANA_CON0, 1),
+ MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
+ buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f,
+ 0, MT6358_VPROC_ANA_CON0, 2),
+ MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
+ buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, 0,
+ MT6358_VCORE_VGPU_ANA_CON0, 2),
+ MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
+ buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, 0,
+ MT6358_VS2_ANA_CON0, 8),
+ MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
+ buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f,
+ 0, MT6358_VMODEM_ANA_CON0, 8),
+ MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
+ buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, 0,
+ MT6358_VS1_ANA_CON0, 8),
+ MT6358_REG_FIXED("ldo_vrf12", VRF12,
+ MT6358_LDO_VRF12_CON0, 0, 1200000),
+ MT6358_REG_FIXED("ldo_vio18", VIO18,
+ MT6358_LDO_VIO18_CON0, 0, 1800000),
+ MT6358_REG_FIXED("ldo_vcamio", VCAMIO,
+ MT6358_LDO_VCAMIO_CON0, 0, 1800000),
+ MT6358_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000),
+ MT6358_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000),
+ MT6358_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000),
+ MT6358_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000),
+ MT6358_REG_FIXED("ldo_vaux18", VAUX18,
+ MT6358_LDO_VAUX18_CON0, 0, 1800000),
+ MT6358_REG_FIXED("ldo_vbif28", VBIF28,
+ MT6358_LDO_VBIF28_CON0, 0, 2800000),
+ MT6358_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000),
+ MT6358_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000),
+ MT6358_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000),
+ MT6358_REG_FIXED("ldo_vaud28", VAUD28,
+ MT6358_LDO_VAUD28_CON0, 0, 2800000),
+ MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
+ MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0),
+ MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx,
+ MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
+ MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx,
+ MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700, 8),
+ MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx,
+ MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx,
+ MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx,
+ MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700, 8),
+ MT6358_LDO("ldo_vcama1", VCAMA1, vcama_voltages, vcama_idx,
+ MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx,
+ MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700, 8),
+ MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages,
+ vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0,
+ 0, MT6358_VCN33_ANA_CON0, 0x300, 8),
+ MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages,
+ vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1,
+ 0, MT6358_VCN33_ANA_CON0, 0x300, 8),
+ MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx,
+ MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
+ MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00, 8),
+ MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx,
+ MT6358_LDO_VLDO28_CON0_0, 0,
+ MT6358_VLDO28_ANA_CON0, 0x300, 8),
+ MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx,
+ MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00, 8),
+ MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
+ buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f, 8,
+ MT6358_LDO_VSRAM_CON0, 0x7f),
+ MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
+ buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f, 8,
+ MT6358_LDO_VSRAM_CON2, 0x7f),
+ MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
+ buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f, 8,
+ MT6358_LDO_VSRAM_CON3, 0x7f),
+ MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
+ buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f, 8,
+ MT6358_LDO_VSRAM_CON1, 0x7f),
+};
+
+static int mt6358_regulator_probe(struct platform_device *pdev)
+{
+ struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ int i;
+
+ for (i = 0; i < MT6358_MAX_REGULATOR; i++) {
+ config.dev = &pdev->dev;
+ config.driver_data = &mt6358_regulators[i];
+ config.regmap = mt6397->regmap;
+
+ rdev = devm_regulator_register(&pdev->dev,
+ &mt6358_regulators[i].desc,
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ mt6358_regulators[i].desc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id mt6358_platform_ids[] = {
+ {"mt6358-regulator", 0},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, mt6358_platform_ids);
+
+static struct platform_driver mt6358_regulator_driver = {
+ .driver = {
+ .name = "mt6358-regulator",
+ },
+ .probe = mt6358_regulator_probe,
+ .id_table = mt6358_platform_ids,
+};
+
+module_platform_driver(mt6358_regulator_driver);
+
+MODULE_AUTHOR("Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6358 PMIC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 397918ebba55..9112faa6a9a0 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -416,8 +416,10 @@ device_node *regulator_of_get_init_node(struct device *dev,
if (!name)
name = child->name;
- if (!strcmp(desc->of_match, name))
+ if (!strcmp(desc->of_match, name)) {
+ of_node_put(search);
return of_node_get(child);
+ }
}
of_node_put(search);
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index b2c2d01d1637..db6c085da65e 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -50,6 +50,20 @@ enum rpmh_regulator_type {
#define PMIC4_BOB_MODE_AUTO 2
#define PMIC4_BOB_MODE_PWM 3
+#define PMIC5_LDO_MODE_RETENTION 3
+#define PMIC5_LDO_MODE_LPM 4
+#define PMIC5_LDO_MODE_HPM 7
+
+#define PMIC5_SMPS_MODE_RETENTION 3
+#define PMIC5_SMPS_MODE_PFM 4
+#define PMIC5_SMPS_MODE_AUTO 6
+#define PMIC5_SMPS_MODE_PWM 7
+
+#define PMIC5_BOB_MODE_PASS 2
+#define PMIC5_BOB_MODE_PFM 4
+#define PMIC5_BOB_MODE_AUTO 6
+#define PMIC5_BOB_MODE_PWM 7
+
/**
* struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
* @regulator_type: RPMh accelerator type used to manage this
@@ -488,6 +502,14 @@ static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = {
[REGULATOR_MODE_FAST] = -EINVAL,
};
+static const int pmic_mode_map_pmic5_ldo[REGULATOR_MODE_STANDBY + 1] = {
+ [REGULATOR_MODE_INVALID] = -EINVAL,
+ [REGULATOR_MODE_STANDBY] = PMIC5_LDO_MODE_RETENTION,
+ [REGULATOR_MODE_IDLE] = PMIC5_LDO_MODE_LPM,
+ [REGULATOR_MODE_NORMAL] = PMIC5_LDO_MODE_HPM,
+ [REGULATOR_MODE_FAST] = -EINVAL,
+};
+
static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode)
{
unsigned int mode;
@@ -518,6 +540,14 @@ static const int pmic_mode_map_pmic4_smps[REGULATOR_MODE_STANDBY + 1] = {
[REGULATOR_MODE_FAST] = PMIC4_SMPS_MODE_PWM,
};
+static const int pmic_mode_map_pmic5_smps[REGULATOR_MODE_STANDBY + 1] = {
+ [REGULATOR_MODE_INVALID] = -EINVAL,
+ [REGULATOR_MODE_STANDBY] = PMIC5_SMPS_MODE_RETENTION,
+ [REGULATOR_MODE_IDLE] = PMIC5_SMPS_MODE_PFM,
+ [REGULATOR_MODE_NORMAL] = PMIC5_SMPS_MODE_AUTO,
+ [REGULATOR_MODE_FAST] = PMIC5_SMPS_MODE_PWM,
+};
+
static unsigned int
rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode)
{
@@ -552,6 +582,14 @@ static const int pmic_mode_map_pmic4_bob[REGULATOR_MODE_STANDBY + 1] = {
[REGULATOR_MODE_FAST] = PMIC4_BOB_MODE_PWM,
};
+static const int pmic_mode_map_pmic5_bob[REGULATOR_MODE_STANDBY + 1] = {
+ [REGULATOR_MODE_INVALID] = -EINVAL,
+ [REGULATOR_MODE_STANDBY] = -EINVAL,
+ [REGULATOR_MODE_IDLE] = PMIC5_BOB_MODE_PFM,
+ [REGULATOR_MODE_NORMAL] = PMIC5_BOB_MODE_AUTO,
+ [REGULATOR_MODE_FAST] = PMIC5_BOB_MODE_PWM,
+};
+
static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode)
{
unsigned int mode;
@@ -637,6 +675,72 @@ static const struct rpmh_vreg_hw_data pmic4_lvs = {
/* LVS hardware does not support voltage or mode configuration. */
};
+static const struct rpmh_vreg_hw_data pmic5_pldo = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_drms_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000),
+ .n_voltages = 256,
+ .hpm_min_load_uA = 10000,
+ .pmic_mode_map = pmic_mode_map_pmic5_ldo,
+ .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_pldo_lv = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_drms_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000),
+ .n_voltages = 63,
+ .hpm_min_load_uA = 10000,
+ .pmic_mode_map = pmic_mode_map_pmic5_ldo,
+ .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_nldo = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_drms_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000),
+ .n_voltages = 124,
+ .hpm_min_load_uA = 30000,
+ .pmic_mode_map = pmic_mode_map_pmic5_ldo,
+ .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
+ .n_voltages = 216,
+ .pmic_mode_map = pmic_mode_map_pmic5_smps,
+ .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000),
+ .n_voltages = 264,
+ .pmic_mode_map = pmic_mode_map_pmic5_smps,
+ .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600),
+ .n_voltages = 5,
+ .pmic_mode_map = pmic_mode_map_pmic5_smps,
+ .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_bob = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_bypass_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000),
+ .n_voltages = 136,
+ .pmic_mode_map = pmic_mode_map_pmic5_bob,
+ .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode,
+};
+
#define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \
{ \
.name = _name, \
@@ -705,6 +809,75 @@ static const struct rpmh_vreg_init_data pm8005_vreg_data[] = {
{},
};
+static const struct rpmh_vreg_init_data pm8150_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps510, "vdd-s8"),
+ RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps510, "vdd-s9"),
+ RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l8-l11"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l10"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3-l4-l5-l18"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l3-l4-l5-l18"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l3-l4-l5-l18"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l12-l14-l15"),
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l1-l8-l11"),
+ RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9"),
+ RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l2-l10"),
+ RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l1-l8-l11"),
+ RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
+ RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l6-l17"),
+ RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
+ RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
+ RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l6-l17"),
+ RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l6-l17"),
+ RPMH_VREG("ldo18", "ldo%s18", &pmic5_nldo, "vdd-l3-l4-l5-l18"),
+ {},
+};
+
+static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"),
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8-l11"),
+ RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"),
+ RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"),
+ RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"),
+ RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"),
+ {},
+};
+
+static const struct rpmh_vreg_init_data pm8009_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"),
+ RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"),
+ {},
+};
+
static int rpmh_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -744,6 +917,22 @@ static int rpmh_regulator_probe(struct platform_device *pdev)
static const struct of_device_id rpmh_regulator_match_table[] = {
{
+ .compatible = "qcom,pm8005-rpmh-regulators",
+ .data = pm8005_vreg_data,
+ },
+ {
+ .compatible = "qcom,pm8009-rpmh-regulators",
+ .data = pm8009_vreg_data,
+ },
+ {
+ .compatible = "qcom,pm8150-rpmh-regulators",
+ .data = pm8150_vreg_data,
+ },
+ {
+ .compatible = "qcom,pm8150l-rpmh-regulators",
+ .data = pm8150l_vreg_data,
+ },
+ {
.compatible = "qcom,pm8998-rpmh-regulators",
.data = pm8998_vreg_data,
},
@@ -751,10 +940,6 @@ static const struct of_device_id rpmh_regulator_match_table[] = {
.compatible = "qcom,pmi8998-rpmh-regulators",
.data = pmi8998_vreg_data,
},
- {
- .compatible = "qcom,pm8005-rpmh-regulators",
- .data = pm8005_vreg_data,
- },
{}
};
MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table);
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index e7af0c53d449..61bd5ef0806c 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -606,7 +606,7 @@ static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode)
case 2:
return REGULATOR_MODE_NORMAL;
default:
- return -EINVAL;
+ return REGULATOR_MODE_INVALID;
}
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 054baaadfdfd..5bc00884cf51 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1226,7 +1226,7 @@ common_reg:
goto out;
}
- if (s2mps11->ext_control_gpiod[i]) {
+ if (config.ena_gpiod) {
ret = s2mps14_pmic_enable_ext_control(s2mps11,
regulator);
if (ret < 0) {
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index 04b732991d69..a0565daecace 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -205,7 +205,7 @@ static int slg51000_of_parse_cb(struct device_node *np,
ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np,
"enable-gpios", 0,
gflags, "gpio-en-ldo");
- if (ena_gpiod) {
+ if (!IS_ERR(ena_gpiod)) {
config->ena_gpiod = ena_gpiod;
devm_gpiod_unhinge(chip->dev, config->ena_gpiod);
}
@@ -447,18 +447,19 @@ static int slg51000_i2c_probe(struct i2c_client *client,
{
struct device *dev = &client->dev;
struct slg51000 *chip;
- struct gpio_desc *cs_gpiod = NULL;
+ struct gpio_desc *cs_gpiod;
int error, ret;
chip = devm_kzalloc(dev, sizeof(struct slg51000), GFP_KERNEL);
if (!chip)
return -ENOMEM;
- cs_gpiod = devm_gpiod_get_from_of_node(dev, dev->of_node,
- "dlg,cs-gpios", 0,
- GPIOD_OUT_HIGH
- | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
- "slg51000-cs");
+ cs_gpiod = devm_gpiod_get_optional(dev, "dlg,cs",
+ GPIOD_OUT_HIGH |
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE);
+ if (IS_ERR(cs_gpiod))
+ return PTR_ERR(cs_gpiod);
+
if (cs_gpiod) {
dev_info(dev, "Found chip selector property\n");
chip->cs_gpiod = cs_gpiod;
diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c
index 2a897666c650..03f162ffd144 100644
--- a/drivers/regulator/stm32-booster.c
+++ b/drivers/regulator/stm32-booster.c
@@ -20,7 +20,6 @@
#define STM32MP1_SYSCFG_EN_BOOSTER_MASK BIT(8)
static const struct regulator_ops stm32h7_booster_ops = {
- .list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -31,7 +30,6 @@ static const struct regulator_desc stm32h7_booster_desc = {
.supply_name = "vdda",
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
- .min_uV = 3300000,
.fixed_uV = 3300000,
.ramp_delay = 66000, /* up to 50us to stabilize */
.ops = &stm32h7_booster_ops,
@@ -53,7 +51,6 @@ static int stm32mp1_booster_disable(struct regulator_dev *rdev)
}
static const struct regulator_ops stm32mp1_booster_ops = {
- .list_voltage = regulator_list_voltage_linear,
.enable = stm32mp1_booster_enable,
.disable = stm32mp1_booster_disable,
.is_enabled = regulator_is_enabled_regmap,
@@ -64,7 +61,6 @@ static const struct regulator_desc stm32mp1_booster_desc = {
.supply_name = "vdda",
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
- .min_uV = 3300000,
.fixed_uV = 3300000,
.ramp_delay = 66000,
.ops = &stm32mp1_booster_ops,
diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c
new file mode 100644
index 000000000000..92adb4f3ee19
--- /dev/null
+++ b/drivers/regulator/sy8824x.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// SY8824C/SY8824E regulator driver
+//
+// Copyright (C) 2019 Synaptics Incorporated
+//
+// Author: Jisheng Zhang <jszhang@kernel.org>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define SY8824C_BUCK_EN (1 << 7)
+#define SY8824C_MODE (1 << 6)
+
+struct sy8824_config {
+ /* registers */
+ unsigned int vol_reg;
+ unsigned int mode_reg;
+ unsigned int enable_reg;
+ /* Voltage range and step(linear) */
+ unsigned int vsel_min;
+ unsigned int vsel_step;
+ unsigned int vsel_count;
+};
+
+struct sy8824_device_info {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_init_data *regulator;
+ const struct sy8824_config *cfg;
+};
+
+static int sy8824_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct sy8824_device_info *di = rdev_get_drvdata(rdev);
+ const struct sy8824_config *cfg = di->cfg;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ regmap_update_bits(rdev->regmap, cfg->mode_reg,
+ SY8824C_MODE, SY8824C_MODE);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ regmap_update_bits(rdev->regmap, cfg->mode_reg,
+ SY8824C_MODE, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static unsigned int sy8824_get_mode(struct regulator_dev *rdev)
+{
+ struct sy8824_device_info *di = rdev_get_drvdata(rdev);
+ const struct sy8824_config *cfg = di->cfg;
+ u32 val;
+ int ret = 0;
+
+ ret = regmap_read(rdev->regmap, cfg->mode_reg, &val);
+ if (ret < 0)
+ return ret;
+ if (val & SY8824C_MODE)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static const struct regulator_ops sy8824_regulator_ops = {
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = sy8824_set_mode,
+ .get_mode = sy8824_get_mode,
+};
+
+static int sy8824_regulator_register(struct sy8824_device_info *di,
+ struct regulator_config *config)
+{
+ struct regulator_desc *rdesc = &di->desc;
+ const struct sy8824_config *cfg = di->cfg;
+ struct regulator_dev *rdev;
+
+ rdesc->name = "sy8824-reg";
+ rdesc->supply_name = "vin";
+ rdesc->ops = &sy8824_regulator_ops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->n_voltages = cfg->vsel_count;
+ rdesc->enable_reg = cfg->enable_reg;
+ rdesc->enable_mask = SY8824C_BUCK_EN;
+ rdesc->min_uV = cfg->vsel_min;
+ rdesc->uV_step = cfg->vsel_step;
+ rdesc->vsel_reg = cfg->vol_reg;
+ rdesc->vsel_mask = cfg->vsel_count - 1;
+ rdesc->owner = THIS_MODULE;
+
+ rdev = devm_regulator_register(di->dev, &di->desc, config);
+ return PTR_ERR_OR_ZERO(rdev);
+}
+
+static const struct regmap_config sy8824_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int sy8824_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
+ struct sy8824_device_info *di;
+ struct regulator_config config = { };
+ struct regmap *regmap;
+ int ret;
+
+ di = devm_kzalloc(dev, sizeof(struct sy8824_device_info), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
+ if (!di->regulator) {
+ dev_err(dev, "Platform data not found!\n");
+ return -EINVAL;
+ }
+
+ di->dev = dev;
+ di->cfg = of_device_get_match_data(dev);
+
+ regmap = devm_regmap_init_i2c(client, &sy8824_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+ i2c_set_clientdata(client, di);
+
+ config.dev = di->dev;
+ config.init_data = di->regulator;
+ config.regmap = regmap;
+ config.driver_data = di;
+ config.of_node = np;
+
+ ret = sy8824_regulator_register(di, &config);
+ if (ret < 0)
+ dev_err(dev, "Failed to register regulator!\n");
+ return ret;
+}
+
+static const struct sy8824_config sy8824c_cfg = {
+ .vol_reg = 0x00,
+ .mode_reg = 0x00,
+ .enable_reg = 0x00,
+ .vsel_min = 762500,
+ .vsel_step = 12500,
+ .vsel_count = 64,
+};
+
+static const struct sy8824_config sy8824e_cfg = {
+ .vol_reg = 0x00,
+ .mode_reg = 0x00,
+ .enable_reg = 0x00,
+ .vsel_min = 700000,
+ .vsel_step = 12500,
+ .vsel_count = 64,
+};
+
+static const struct sy8824_config sy20276_cfg = {
+ .vol_reg = 0x00,
+ .mode_reg = 0x01,
+ .enable_reg = 0x01,
+ .vsel_min = 600000,
+ .vsel_step = 10000,
+ .vsel_count = 128,
+};
+
+static const struct sy8824_config sy20278_cfg = {
+ .vol_reg = 0x00,
+ .mode_reg = 0x01,
+ .enable_reg = 0x01,
+ .vsel_min = 762500,
+ .vsel_step = 12500,
+ .vsel_count = 64,
+};
+
+static const struct of_device_id sy8824_dt_ids[] = {
+ {
+ .compatible = "silergy,sy8824c",
+ .data = &sy8824c_cfg
+ },
+ {
+ .compatible = "silergy,sy8824e",
+ .data = &sy8824e_cfg
+ },
+ {
+ .compatible = "silergy,sy20276",
+ .data = &sy20276_cfg
+ },
+ {
+ .compatible = "silergy,sy20278",
+ .data = &sy20278_cfg
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sy8824_dt_ids);
+
+static const struct i2c_device_id sy8824_id[] = {
+ { "sy8824", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, sy8824_id);
+
+static struct i2c_driver sy8824_regulator_driver = {
+ .driver = {
+ .name = "sy8824-regulator",
+ .of_match_table = of_match_ptr(sy8824_dt_ids),
+ },
+ .probe = sy8824_i2c_probe,
+ .id_table = sy8824_id,
+};
+module_i2c_driver(sy8824_regulator_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("SY8824C/SY8824E regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c
index 6e22f5ebba2e..e302bd01a084 100644
--- a/drivers/regulator/tps65132-regulator.c
+++ b/drivers/regulator/tps65132-regulator.c
@@ -138,7 +138,7 @@ static int tps65132_of_parse_cb(struct device_node *np,
rpdata->en_gpiod = devm_fwnode_get_index_gpiod_from_child(tps->dev,
"enable", 0, &np->fwnode, 0, "enable");
- if (IS_ERR(rpdata->en_gpiod)) {
+ if (IS_ERR_OR_NULL(rpdata->en_gpiod)) {
ret = PTR_ERR(rpdata->en_gpiod);
/* Ignore the error other than probe defer */
@@ -150,7 +150,7 @@ static int tps65132_of_parse_cb(struct device_node *np,
rpdata->act_dis_gpiod = devm_fwnode_get_index_gpiod_from_child(
tps->dev, "active-discharge", 0,
&np->fwnode, 0, "active-discharge");
- if (IS_ERR(rpdata->act_dis_gpiod)) {
+ if (IS_ERR_OR_NULL(rpdata->act_dis_gpiod)) {
ret = PTR_ERR(rpdata->act_dis_gpiod);
/* Ignore the error other than probe defer */
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 6fa15b2d6fb3..866b4dd01da9 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -359,6 +359,17 @@ static const u16 VINTANA2_VSEL_table[] = {
2500, 2750,
};
+/* 600mV to 1450mV in 12.5 mV steps */
+static const struct regulator_linear_range VDD1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500)
+};
+
+/* 600mV to 1450mV in 12.5 mV steps, everything above = 1500mV */
+static const struct regulator_linear_range VDD2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500),
+ REGULATOR_LINEAR_RANGE(1500000, 69, 69, 12500)
+};
+
static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
@@ -427,6 +438,8 @@ static int twl4030smps_get_voltage(struct regulator_dev *rdev)
}
static const struct regulator_ops twl4030smps_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+
.set_voltage = twl4030smps_set_voltage,
.get_voltage = twl4030smps_get_voltage,
};
@@ -466,7 +479,8 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
}, \
}
-#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
+#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf, \
+ n_volt) \
static const struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \
.id = num, \
@@ -479,6 +493,9 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
.owner = THIS_MODULE, \
.enable_time = turnon_delay, \
.of_map_mode = twl4030reg_map_mode, \
+ .n_voltages = n_volt, \
+ .n_linear_ranges = ARRAY_SIZE(label ## _ranges), \
+ .linear_ranges = label ## _ranges, \
}, \
}
@@ -518,8 +535,8 @@ TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00);
TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08);
-TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08);
-TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08);
+TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08, 68);
+TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08, 69);
/* VUSBCP is managed *only* by the USB subchip */
TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
index 5fe208b381eb..b8100c3cedad 100644
--- a/drivers/regulator/twl6030-regulator.c
+++ b/drivers/regulator/twl6030-regulator.c
@@ -57,6 +57,9 @@ struct twlreg_info {
#define VREG_BC_PROC 3
#define VREG_BC_CLK_RST 4
+/* TWL6030 LDO register values for VREG_VOLTAGE */
+#define TWL6030_VREG_VOLTAGE_WR_S BIT(7)
+
/* TWL6030 LDO register values for CFG_STATE */
#define TWL6030_CFG_STATE_OFF 0x00
#define TWL6030_CFG_STATE_ON 0x01
@@ -68,9 +71,10 @@ struct twlreg_info {
#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
TWL6030_CFG_STATE_APP_SHIFT)
-/* Flags for SMPS Voltage reading */
+/* Flags for SMPS Voltage reading and LDO reading*/
#define SMPS_OFFSET_EN BIT(0)
#define SMPS_EXTENDED_EN BIT(1)
+#define TWL_6030_WARM_RESET BIT(3)
/* twl6032 SMPS EPROM values */
#define TWL6030_SMPS_OFFSET 0xB0
@@ -250,6 +254,9 @@ twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
+ if (info->flags & TWL_6030_WARM_RESET)
+ selector |= TWL6030_VREG_VOLTAGE_WR_S;
+
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
selector);
}
@@ -259,6 +266,9 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
+ if (info->flags & TWL_6030_WARM_RESET)
+ vsel &= ~TWL6030_VREG_VOLTAGE_WR_S;
+
return vsel;
}
@@ -665,14 +675,14 @@ static int twlreg_probe(struct platform_device *pdev)
struct regulation_constraints *c;
struct regulator_dev *rdev;
struct regulator_config config = { };
+ struct device_node *np = pdev->dev.of_node;
template = of_device_get_match_data(&pdev->dev);
if (!template)
return -ENODEV;
id = template->desc.id;
- initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
- &template->desc);
+ initdata = of_get_regulator_init_data(&pdev->dev, np, &template->desc);
if (!initdata)
return -EINVAL;
@@ -710,10 +720,13 @@ static int twlreg_probe(struct platform_device *pdev)
break;
}
+ if (of_get_property(np, "ti,retain-on-reset", NULL))
+ info->flags |= TWL_6030_WARM_RESET;
+
config.dev = &pdev->dev;
config.init_data = initdata;
config.driver_data = info;
- config.of_node = pdev->dev.of_node;
+ config.of_node = np;
rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c
index 9026d5a3e964..2311924c3103 100644
--- a/drivers/regulator/uniphier-regulator.c
+++ b/drivers/regulator/uniphier-regulator.c
@@ -186,6 +186,10 @@ static const struct of_device_id uniphier_regulator_match[] = {
.data = &uniphier_pro4_usb3_data,
},
{
+ .compatible = "socionext,uniphier-pro5-usb3-regulator",
+ .data = &uniphier_pro4_usb3_data,
+ },
+ {
.compatible = "socionext,uniphier-pxs2-usb3-regulator",
.data = &uniphier_pxs2_usb3_data,
},
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 21efb7d39d62..7b07281aa0ae 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -116,9 +116,20 @@ config RESET_QCOM_PDC
to control reset signals provided by PDC for Modem, Compute,
Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS.
+config RESET_SCMI
+ tristate "Reset driver controlled via ARM SCMI interface"
+ depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+ default ARM_SCMI_PROTOCOL
+ help
+ This driver provides support for reset signal/domains that are
+ controlled by firmware that implements the SCMI interface.
+
+ This driver uses SCMI Message Protocol to interact with the
+ firmware controlling all the reset signals.
+
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
- default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN
+ default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN || ARC
help
This enables a simple reset controller driver for reset lines that
that can be asserted and deasserted by toggling bits in a contiguous,
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 61456b8f659c..cf60ce526064 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
+obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
index 3ecd770f910b..1443a55a0c29 100644
--- a/drivers/reset/reset-imx7.c
+++ b/drivers/reset/reset-imx7.c
@@ -169,9 +169,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
[IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
[IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
[IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) },
- [IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
- [IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
- [IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
+ [IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
+ [IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
+ [IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
[IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR,
BIT(2) | BIT(1) },
[IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
@@ -220,9 +220,9 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */
- case IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N: /* fallthrough */
- case IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N: /* fallthrough */
- case IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */
value = assert ? 0 : bit;
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 5242e0679df7..7d05d766e1ea 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -1,58 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Amlogic Meson Reset Controller driver
*
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright (c) 2016 BayLibre, SAS.
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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. 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, see <http://www.gnu.org/licenses/>.
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * BSD LICENSE
- *
* Copyright (c) 2016 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/err.h>
#include <linux/init.h>
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
new file mode 100644
index 000000000000..c6d3c8427f14
--- /dev/null
+++ b/drivers/reset/reset-scmi.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM System Control and Management Interface (ARM SCMI) reset driver
+ *
+ * Copyright (C) 2019 ARM Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/reset-controller.h>
+#include <linux/scmi_protocol.h>
+
+/**
+ * struct scmi_reset_data - reset controller information structure
+ * @rcdev: reset controller entity
+ * @handle: ARM SCMI handle used for communication with system controller
+ */
+struct scmi_reset_data {
+ struct reset_controller_dev rcdev;
+ const struct scmi_handle *handle;
+};
+
+#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev)
+#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle)
+
+/**
+ * scmi_reset_assert() - assert device reset
+ * @rcdev: reset controller entity
+ * @id: ID of the reset to be asserted
+ *
+ * This function implements the reset driver op to assert a device's reset
+ * using the ARM SCMI protocol.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int
+scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ const struct scmi_handle *handle = to_scmi_handle(rcdev);
+
+ return handle->reset_ops->assert(handle, id);
+}
+
+/**
+ * scmi_reset_deassert() - deassert device reset
+ * @rcdev: reset controller entity
+ * @id: ID of the reset to be deasserted
+ *
+ * This function implements the reset driver op to deassert a device's reset
+ * using the ARM SCMI protocol.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int
+scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ const struct scmi_handle *handle = to_scmi_handle(rcdev);
+
+ return handle->reset_ops->deassert(handle, id);
+}
+
+/**
+ * scmi_reset_reset() - reset the device
+ * @rcdev: reset controller entity
+ * @id: ID of the reset signal to be reset(assert + deassert)
+ *
+ * This function implements the reset driver op to trigger a device's
+ * reset signal using the ARM SCMI protocol.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int
+scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ const struct scmi_handle *handle = to_scmi_handle(rcdev);
+
+ return handle->reset_ops->reset(handle, id);
+}
+
+static const struct reset_control_ops scmi_reset_ops = {
+ .assert = scmi_reset_assert,
+ .deassert = scmi_reset_deassert,
+ .reset = scmi_reset_reset,
+};
+
+static int scmi_reset_probe(struct scmi_device *sdev)
+{
+ struct scmi_reset_data *data;
+ struct device *dev = &sdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct scmi_handle *handle = sdev->handle;
+
+ if (!handle || !handle->reset_ops)
+ return -ENODEV;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->rcdev.ops = &scmi_reset_ops;
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.of_node = np;
+ data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle);
+
+ return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+ { SCMI_PROTOCOL_RESET },
+ { },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_reset_driver = {
+ .name = "scmi-reset",
+ .probe = scmi_reset_probe,
+ .id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_reset_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI reset controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index 1154f7b1f4dd..067e7e7b34f1 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -127,6 +127,9 @@ static const struct of_device_id reset_simple_dt_ids[] = {
{ .compatible = "aspeed,ast2500-lpc-reset" },
{ .compatible = "bitmain,bm1880-reset",
.data = &reset_simple_active_low },
+ { .compatible = "snps,dw-high-reset" },
+ { .compatible = "snps,dw-low-reset",
+ .data = &reset_simple_active_low },
{ /* sentinel */ },
};
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index b9ce93e9df89..99f86612f775 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -383,6 +383,20 @@ suborder_not_supported(struct dasd_ccw_req *cqr)
char msg_format;
char msg_no;
+ /*
+ * intrc values ENODEV, ENOLINK and EPERM
+ * will be optained from sleep_on to indicate that no
+ * IO operation can be started
+ */
+ if (cqr->intrc == -ENODEV)
+ return 1;
+
+ if (cqr->intrc == -ENOLINK)
+ return 1;
+
+ if (cqr->intrc == -EPERM)
+ return 1;
+
sense = dasd_get_sense(&cqr->irb);
if (!sense)
return 0;
@@ -447,12 +461,8 @@ static int read_unit_address_configuration(struct dasd_device *device,
lcu->flags &= ~NEED_UAC_UPDATE;
spin_unlock_irqrestore(&lcu->lock, flags);
- do {
- rc = dasd_sleep_on(cqr);
- if (rc && suborder_not_supported(cqr))
- return -EOPNOTSUPP;
- } while (rc && (cqr->retries > 0));
- if (rc) {
+ rc = dasd_sleep_on(cqr);
+ if (rc && !suborder_not_supported(cqr)) {
spin_lock_irqsave(&lcu->lock, flags);
lcu->flags |= NEED_UAC_UPDATE;
spin_unlock_irqrestore(&lcu->lock, flags);
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 8c9d412b6d33..e7cf0a1d4f71 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -398,6 +398,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
}
if (dstat == 0x08)
break;
+ /* else, fall through */
case 0x04:
/* Device end interrupt. */
if ((raw = req->info) == NULL)
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 8d3370da2dfc..3e0b2f63a9d2 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -677,6 +677,7 @@ tape_generic_remove(struct ccw_device *cdev)
switch (device->tape_state) {
case TS_INIT:
tape_state_set(device, TS_NOT_OPER);
+ /* fallthrough */
case TS_NOT_OPER:
/*
* Nothing to do.
@@ -949,6 +950,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
break;
if (device->tape_state == TS_UNUSED)
break;
+ /* fallthrough */
default:
if (device->tape_state == TS_BLKUSE)
break;
@@ -1116,6 +1118,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
case -ETIMEDOUT:
DBF_LH(1, "(%08x): Request timed out\n",
device->cdev_id);
+ /* fallthrough */
case -EIO:
__tape_end_request(device, request, -EIO);
break;
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 730c4e68094b..4142c85e77d8 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -319,9 +319,7 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
int retries = 0, cc;
unsigned long laob = 0;
- WARN_ON_ONCE(aob && ((queue_type(q) != QDIO_IQDIO_QFMT) ||
- !q->u.out.use_cq));
- if (q->u.out.use_cq && aob != 0) {
+ if (aob) {
fc = QDIO_SIGA_WRITEQ;
laob = aob;
}
@@ -621,9 +619,6 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
{
unsigned long phys_aob = 0;
- if (!q->use_cq)
- return 0;
-
if (!q->aobs[bufnr]) {
struct qaob *aob = qdio_allocate_aob();
q->aobs[bufnr] = aob;
@@ -1308,6 +1303,8 @@ static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
for_each_output_queue(irq_ptr, q, i) {
if (use_cq) {
+ if (multicast_outbound(q))
+ continue;
if (qdio_enable_async_operation(&q->u.out) < 0) {
use_cq = 0;
continue;
@@ -1553,18 +1550,19 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
/* One SIGA-W per buffer required for unicast HSI */
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
- phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
+ if (q->u.out.use_cq)
+ phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
rc = qdio_kick_outbound_q(q, phys_aob);
} else if (need_siga_sync(q)) {
rc = qdio_siga_sync_q(q);
+ } else if (count < QDIO_MAX_BUFFERS_PER_Q &&
+ get_buf_state(q, prev_buf(bufnr), &state, 0) > 0 &&
+ state == SLSB_CU_OUTPUT_PRIMED) {
+ /* The previous buffer is not processed yet, tack on. */
+ qperf_inc(q, fast_requeue);
} else {
- /* try to fast requeue buffers */
- get_buf_state(q, prev_buf(bufnr), &state, 0);
- if (state != SLSB_CU_OUTPUT_PRIMED)
- rc = qdio_kick_outbound_q(q, 0);
- else
- qperf_inc(q, fast_requeue);
+ rc = qdio_kick_outbound_q(q, 0);
}
/* in case of SIGA errors we must process the error immediately */
diff --git a/drivers/s390/cio/vfio_ccw_async.c b/drivers/s390/cio/vfio_ccw_async.c
index 8c1d2357ef5b..7a838e3d7c0f 100644
--- a/drivers/s390/cio/vfio_ccw_async.c
+++ b/drivers/s390/cio/vfio_ccw_async.c
@@ -70,7 +70,7 @@ static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,
}
-const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
+static const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
.read = vfio_ccw_async_region_read,
.write = vfio_ccw_async_region_write,
.release = vfio_ccw_async_region_release,
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 1d4c893ead23..3645d1720c4b 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -72,8 +72,10 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 iova, unsigned int len)
sizeof(*pa->pa_iova_pfn) +
sizeof(*pa->pa_pfn),
GFP_KERNEL);
- if (unlikely(!pa->pa_iova_pfn))
+ if (unlikely(!pa->pa_iova_pfn)) {
+ pa->pa_nr = 0;
return -ENOMEM;
+ }
pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
@@ -421,7 +423,7 @@ static int ccwchain_loop_tic(struct ccwchain *chain,
static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
{
struct ccwchain *chain;
- int len;
+ int len, ret;
/* Copy 2K (the most we support today) of possible CCWs */
len = copy_from_iova(cp->mdev, cp->guest_cp, cda,
@@ -448,7 +450,12 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
memcpy(chain->ch_ccw, cp->guest_cp, len * sizeof(struct ccw1));
/* Loop for tics on this new chain. */
- return ccwchain_loop_tic(chain, cp);
+ ret = ccwchain_loop_tic(chain, cp);
+
+ if (ret)
+ ccwchain_free(chain);
+
+ return ret;
}
/* Loop for TICs. */
@@ -642,17 +649,16 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
/* Build a ccwchain for the first CCW segment */
ret = ccwchain_handle_ccw(orb->cmd.cpa, cp);
- if (ret)
- cp_free(cp);
-
- /* It is safe to force: if not set but idals used
- * ccwchain_calc_length returns an error.
- */
- cp->orb.cmd.c64 = 1;
- if (!ret)
+ if (!ret) {
cp->initialized = true;
+ /* It is safe to force: if it was not set but idals used
+ * ccwchain_calc_length would have returned an error.
+ */
+ cp->orb.cmd.c64 = 1;
+ }
+
return ret;
}
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 2b90a5ecaeb9..9208c0e56c33 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -88,7 +88,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
(SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
if (scsw_is_solicited(&irb->scsw)) {
cp_update_scsw(&private->cp, &irb->scsw);
- if (is_final)
+ if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
cp_free(&private->cp);
}
mutex_lock(&private->io_mutex);
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 5ea83dc4f1d7..dad2be333d82 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -152,6 +152,7 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq)
ap_msg->receive(aq, ap_msg, aq->reply);
break;
}
+ /* fall through */
case AP_RESPONSE_NO_PENDING_REPLY:
if (!status.queue_empty || aq->queue_count <= 0)
break;
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 12fe9deb265e..a36251d138fb 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -801,10 +801,7 @@ static int convert_response_ica(struct zcrypt_queue *zq,
if (msg->cprbx.cprb_ver_id == 0x02)
return convert_type86_ica(zq, reply,
outputdata, outputdatalength);
- /*
- * Fall through, no break, incorrect cprb version is an unknown
- * response
- */
+ /* fall through - wrong cprb version is an unknown response */
default: /* Unknown response type, this should NEVER EVER happen */
zq->online = 0;
pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -837,10 +834,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq,
}
if (msg->cprbx.cprb_ver_id == 0x02)
return convert_type86_xcrb(zq, reply, xcRB);
- /*
- * Fall through, no break, incorrect cprb version is an unknown
- * response
- */
+ /* fall through - wrong cprb version is an unknown response */
default: /* Unknown response type, this should NEVER EVER happen */
xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
zq->online = 0;
@@ -870,7 +864,7 @@ static int convert_response_ep11_xcrb(struct zcrypt_queue *zq,
return convert_error(zq, reply);
if (msg->cprbx.cprb_ver_id == 0x04)
return convert_type86_ep11_xcrb(zq, reply, xcRB);
- /* Fall through, no break, incorrect cprb version is an unknown resp.*/
+ /* fall through - wrong cprb version is an unknown resp */
default: /* Unknown response type, this should NEVER EVER happen */
zq->online = 0;
pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -900,10 +894,7 @@ static int convert_response_rng(struct zcrypt_queue *zq,
return -EINVAL;
if (msg->cprbx.cprb_ver_id == 0x02)
return convert_type86_rng(zq, reply, data);
- /*
- * Fall through, no break, incorrect cprb version is an unknown
- * response
- */
+ /* fall through - wrong cprb version is an unknown response */
default: /* Unknown response type, this should NEVER EVER happen */
zq->online = 0;
pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
index 1b4ee570b712..4a8a5373cb35 100644
--- a/drivers/s390/net/ctcm_fsms.c
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -1704,6 +1704,7 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
grp->changed_side = 2;
break;
}
+ /* Else, fall through */
case MPCG_STATE_XID0IOWAIX:
case MPCG_STATE_XID7INITW:
case MPCG_STATE_XID7INITX:
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index e02f295d38a9..1534420a0243 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -357,6 +357,7 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
/*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
if (callback)
grp->send_qllc_disc = 1;
+ /* Else, fall through */
case MPCG_STATE_XID0IOWAIT:
fsm_deltimer(&grp->timer);
grp->outstanding_xid2 = 0;
@@ -1469,6 +1470,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
break;
+ /* Else, fall through */
default:
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
@@ -2089,6 +2091,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
grp->estconnfunc = NULL;
break;
}
+ /* Else, fall through */
case MPCG_STATE_FLOWC:
case MPCG_STATE_READY:
grp->send_qllc_disc = 2;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index c7ee07ce3615..28db887d38ed 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -629,6 +629,7 @@ struct qeth_seqno {
struct qeth_reply {
struct list_head list;
struct completion received;
+ spinlock_t lock;
int (*callback)(struct qeth_card *, struct qeth_reply *,
unsigned long);
u32 seqno;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 4d0caeebc802..6502b148541e 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -544,6 +544,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
if (reply) {
refcount_set(&reply->refcnt, 1);
init_completion(&reply->received);
+ spin_lock_init(&reply->lock);
}
return reply;
}
@@ -799,6 +800,13 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
if (!reply->callback) {
rc = 0;
+ goto no_callback;
+ }
+
+ spin_lock_irqsave(&reply->lock, flags);
+ if (reply->rc) {
+ /* Bail out when the requestor has already left: */
+ rc = reply->rc;
} else {
if (cmd) {
reply->offset = (u16)((char *)cmd - (char *)iob->data);
@@ -807,7 +815,9 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
rc = reply->callback(card, reply, (unsigned long)iob);
}
}
+ spin_unlock_irqrestore(&reply->lock, flags);
+no_callback:
if (rc <= 0)
qeth_notify_reply(reply, rc);
qeth_put_reply(reply);
@@ -1749,6 +1759,16 @@ static int qeth_send_control_data(struct qeth_card *card,
rc = (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
qeth_dequeue_reply(card, reply);
+
+ if (reply_cb) {
+ /* Wait until the callback for a late reply has completed: */
+ spin_lock_irq(&reply->lock);
+ if (rc)
+ /* Zap any callback that's still pending: */
+ reply->rc = rc;
+ spin_unlock_irq(&reply->lock);
+ }
+
if (!rc)
rc = reply->rc;
qeth_put_reply(reply);
@@ -4354,6 +4374,10 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
get_user(req_len, &ureq->hdr.req_len))
return -EFAULT;
+ /* Sanitize user input, to avoid overflows in iob size calculation: */
+ if (req_len > QETH_BUFSIZE)
+ return -EINVAL;
+
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, req_len);
if (!iob)
return -ENOMEM;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index fd64bc3f4062..cbead3d1b2fd 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -333,7 +333,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
card->osn_info.data_cb(skb);
break;
}
- /* else unknown */
+ /* Else, fall through */
default:
dev_kfree_skb_any(skb);
QETH_CARD_TEXT(card, 3, "inbunkno");
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index 1a55e5942d36..957889a42d2e 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -145,6 +145,8 @@ struct airq_info {
struct airq_iv *aiv;
};
static struct airq_info *airq_areas[MAX_AIRQ_AREAS];
+static DEFINE_MUTEX(airq_areas_lock);
+
static u8 *summary_indicators;
static inline u8 *get_summary_indicator(struct airq_info *info)
@@ -265,9 +267,11 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
unsigned long bit, flags;
for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
+ mutex_lock(&airq_areas_lock);
if (!airq_areas[i])
airq_areas[i] = new_airq_info(i);
info = airq_areas[i];
+ mutex_unlock(&airq_areas_lock);
if (!info)
return 0;
write_lock_irqsave(&info->lock, flags);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 75f66f8ad3ea..1b92f3c19ff3 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1523,10 +1523,10 @@ config SCSI_VIRTIO
source "drivers/scsi/csiostor/Kconfig"
-endif # SCSI_LOWLEVEL
-
source "drivers/scsi/pcmcia/Kconfig"
+endif # SCSI_LOWLEVEL
+
source "drivers/scsi/device_handler/Kconfig"
endmenu
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index aea4fd73c862..6c68c2303638 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -603,6 +603,7 @@ static void fas216_handlesync(FAS216_Info *info, char *msg)
msgqueue_flush(&info->scsi.msgs);
msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
info->scsi.phase = PHASE_MSGOUT_EXPECT;
+ /* fall through */
case async:
dev->period = info->ifcfg.asyncperiod / 4;
@@ -915,6 +916,7 @@ static void fas216_disconnect_intr(FAS216_Info *info)
fas216_done(info, DID_ABORT);
break;
}
+ /* else, fall through */
default: /* huh? */
printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
@@ -1411,6 +1413,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */
case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
fas216_stoptransfer(info);
+ /* fall through */
+
case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */
case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */
case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */
@@ -1422,6 +1426,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */
case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */
fas216_stoptransfer(info);
+ /* fall through */
+
case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */
case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */
case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */
@@ -1575,6 +1581,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned
fas216_message(info);
break;
}
+ /* else, fall through */
default:
fas216_log(info, 0, "internal phase %s for function done?"
@@ -1957,6 +1964,7 @@ static void fas216_kick(FAS216_Info *info)
switch (where_from) {
case TYPE_QUEUE:
fas216_allocate_tag(info, SCpnt);
+ /* fall through */
case TYPE_OTHER:
fas216_start_command(info, SCpnt);
break;
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index f0066f8a1786..4971104b1817 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -40,6 +40,7 @@
#define ALUA_FAILOVER_TIMEOUT 60
#define ALUA_FAILOVER_RETRIES 5
#define ALUA_RTPG_DELAY_MSECS 5
+#define ALUA_RTPG_RETRY_DELAY 2
/* device handler flags */
#define ALUA_OPTIMIZE_STPG 0x01
@@ -682,7 +683,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
case SCSI_ACCESS_STATE_TRANSITIONING:
if (time_before(jiffies, pg->expiry)) {
/* State transition, retry */
- pg->interval = 2;
+ pg->interval = ALUA_RTPG_RETRY_DELAY;
err = SCSI_DH_RETRY;
} else {
struct alua_dh_data *h;
@@ -807,6 +808,8 @@ static void alua_rtpg_work(struct work_struct *work)
spin_lock_irqsave(&pg->lock, flags);
pg->flags &= ~ALUA_PG_RUNNING;
pg->flags |= ALUA_PG_RUN_RTPG;
+ if (!pg->interval)
+ pg->interval = ALUA_RTPG_RETRY_DELAY;
spin_unlock_irqrestore(&pg->lock, flags);
queue_delayed_work(kaluad_wq, &pg->rtpg_work,
pg->interval * HZ);
@@ -818,6 +821,8 @@ static void alua_rtpg_work(struct work_struct *work)
spin_lock_irqsave(&pg->lock, flags);
if (err == SCSI_DH_RETRY || pg->flags & ALUA_PG_RUN_RTPG) {
pg->flags &= ~ALUA_PG_RUNNING;
+ if (!pg->interval && !(pg->flags & ALUA_PG_RUN_RTPG))
+ pg->interval = ALUA_RTPG_RETRY_DELAY;
pg->flags |= ALUA_PG_RUN_RTPG;
spin_unlock_irqrestore(&pg->lock, flags);
queue_delayed_work(kaluad_wq, &pg->rtpg_work,
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 590ec8009f52..1791a393795d 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -1019,7 +1019,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
struct fcoe_fcf *fcf;
struct fcoe_fcf new;
- unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
+ unsigned long sol_tov = msecs_to_jiffies(FCOE_CTLR_SOL_TOV);
int first = 0;
int mtu_valid;
int found = 0;
@@ -2005,7 +2005,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
*/
static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
{
- return (struct fcoe_rport *)(rdata + 1);
+ return container_of(rdata, struct fcoe_rport, rdata);
}
/**
@@ -2269,7 +2269,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
*/
static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
struct sk_buff *skb,
- struct fc_rport_priv *rdata)
+ struct fcoe_rport *frport)
{
struct fip_header *fiph;
struct fip_desc *desc = NULL;
@@ -2277,16 +2277,12 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
struct fip_wwn_desc *wwn = NULL;
struct fip_vn_desc *vn = NULL;
struct fip_size_desc *size = NULL;
- struct fcoe_rport *frport;
size_t rlen;
size_t dlen;
u32 desc_mask = 0;
u32 dtype;
u8 sub;
- memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
- frport = fcoe_ctlr_rport(rdata);
-
fiph = (struct fip_header *)skb->data;
frport->flags = ntohs(fiph->fip_flags);
@@ -2349,15 +2345,17 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
if (dlen != sizeof(struct fip_wwn_desc))
goto len_err;
wwn = (struct fip_wwn_desc *)desc;
- rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+ frport->rdata.ids.node_name =
+ get_unaligned_be64(&wwn->fd_wwn);
break;
case FIP_DT_VN_ID:
if (dlen != sizeof(struct fip_vn_desc))
goto len_err;
vn = (struct fip_vn_desc *)desc;
memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
- rdata->ids.port_id = ntoh24(vn->fd_fc_id);
- rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
+ frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id);
+ frport->rdata.ids.port_name =
+ get_unaligned_be64(&vn->fd_wwpn);
break;
case FIP_DT_FC4F:
if (dlen != sizeof(struct fip_fc4_feat))
@@ -2403,16 +2401,14 @@ static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
/**
* fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
* @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
+ * @frport: parsed FCoE rport from the probe request
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
- struct fc_rport_priv *rdata)
+ struct fcoe_rport *frport)
{
- struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
- if (rdata->ids.port_id != fip->port_id)
+ if (frport->rdata.ids.port_id != fip->port_id)
return;
switch (fip->state) {
@@ -2432,7 +2428,7 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
* Probe's REC bit is not set.
* If we don't reply, we will change our address.
*/
- if (fip->lp->wwpn > rdata->ids.port_name &&
+ if (fip->lp->wwpn > frport->rdata.ids.port_name &&
!(frport->flags & FIP_FL_REC_OR_P2P)) {
LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
"port_id collision\n");
@@ -2456,14 +2452,14 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
* @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
+ * @frport: parsed FCoE rport from the probe request
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
- struct fc_rport_priv *rdata)
+ struct fcoe_rport *frport)
{
- if (rdata->ids.port_id != fip->port_id)
+ if (frport->rdata.ids.port_id != fip->port_id)
return;
switch (fip->state) {
case FIP_ST_VNMP_START:
@@ -2486,11 +2482,11 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
* @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
+ * @new: newly-parsed FCoE rport as a template for new rdata
*
* Called with ctlr_mutex held.
*/
-static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
+static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fcoe_rport *new)
{
struct fc_lport *lport = fip->lp;
struct fc_rport_priv *rdata;
@@ -2498,7 +2494,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
struct fcoe_rport *frport;
u32 port_id;
- port_id = new->ids.port_id;
+ port_id = new->rdata.ids.port_id;
if (port_id == fip->port_id)
return;
@@ -2515,22 +2511,28 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
rdata->disc_id = lport->disc.disc_id;
ids = &rdata->ids;
- if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
- (ids->node_name != -1 && ids->node_name != new->ids.node_name)) {
+ if ((ids->port_name != -1 &&
+ ids->port_name != new->rdata.ids.port_name) ||
+ (ids->node_name != -1 &&
+ ids->node_name != new->rdata.ids.node_name)) {
mutex_unlock(&rdata->rp_mutex);
LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id);
fc_rport_logoff(rdata);
mutex_lock(&rdata->rp_mutex);
}
- ids->port_name = new->ids.port_name;
- ids->node_name = new->ids.node_name;
+ ids->port_name = new->rdata.ids.port_name;
+ ids->node_name = new->rdata.ids.node_name;
mutex_unlock(&rdata->rp_mutex);
frport = fcoe_ctlr_rport(rdata);
LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n",
port_id, frport->fcoe_len ? "old" : "new",
rdata->rp_state);
- *frport = *fcoe_ctlr_rport(new);
+ frport->fcoe_len = new->fcoe_len;
+ frport->flags = new->flags;
+ frport->login_count = new->login_count;
+ memcpy(frport->enode_mac, new->enode_mac, ETH_ALEN);
+ memcpy(frport->vn_mac, new->vn_mac, ETH_ALEN);
frport->time = 0;
}
@@ -2562,16 +2564,14 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
/**
* fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
* @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
+ * @new: newly-parsed FCoE rport as a template for new rdata
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
- struct fc_rport_priv *new)
+ struct fcoe_rport *new)
{
- struct fcoe_rport *frport = fcoe_ctlr_rport(new);
-
- if (frport->flags & FIP_FL_REC_OR_P2P) {
+ if (new->flags & FIP_FL_REC_OR_P2P) {
LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
return;
@@ -2580,7 +2580,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
case FIP_ST_VNMP_START:
case FIP_ST_VNMP_PROBE1:
case FIP_ST_VNMP_PROBE2:
- if (new->ids.port_id == fip->port_id) {
+ if (new->rdata.ids.port_id == fip->port_id) {
LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
"restart, state %d\n",
fip->state);
@@ -2589,8 +2589,8 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
break;
case FIP_ST_VNMP_CLAIM:
case FIP_ST_VNMP_UP:
- if (new->ids.port_id == fip->port_id) {
- if (new->ids.port_name > fip->lp->wwpn) {
+ if (new->rdata.ids.port_id == fip->port_id) {
+ if (new->rdata.ids.port_name > fip->lp->wwpn) {
LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
"restart, port_id collision\n");
fcoe_ctlr_vn_restart(fip);
@@ -2602,15 +2602,16 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
break;
}
LIBFCOE_FIP_DBG(fip, "vn_claim_notify: send reply to %x\n",
- new->ids.port_id);
- fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
- min((u32)frport->fcoe_len,
+ new->rdata.ids.port_id);
+ fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, new->enode_mac,
+ min((u32)new->fcoe_len,
fcoe_ctlr_fcoe_size(fip)));
fcoe_ctlr_vn_add(fip, new);
break;
default:
LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
- "ignoring claim from %x\n", new->ids.port_id);
+ "ignoring claim from %x\n",
+ new->rdata.ids.port_id);
break;
}
}
@@ -2618,15 +2619,15 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_vn_claim_resp() - handle received Claim Response
* @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Claim Response
+ * @new: newly-parsed FCoE rport from the Claim Response
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
- struct fc_rport_priv *new)
+ struct fcoe_rport *new)
{
LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
- new->ids.port_id, fcoe_ctlr_state(fip->state));
+ new->rdata.ids.port_id, fcoe_ctlr_state(fip->state));
if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
fcoe_ctlr_vn_add(fip, new);
}
@@ -2634,28 +2635,28 @@ static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_vn_beacon() - handle received beacon.
* @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Beacon
+ * @new: newly-parsed FCoE rport from the Beacon
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
- struct fc_rport_priv *new)
+ struct fcoe_rport *new)
{
struct fc_lport *lport = fip->lp;
struct fc_rport_priv *rdata;
struct fcoe_rport *frport;
- frport = fcoe_ctlr_rport(new);
- if (frport->flags & FIP_FL_REC_OR_P2P) {
+ if (new->flags & FIP_FL_REC_OR_P2P) {
LIBFCOE_FIP_DBG(fip, "p2p beacon while in vn2vn mode\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
return;
}
- rdata = fc_rport_lookup(lport, new->ids.port_id);
+ rdata = fc_rport_lookup(lport, new->rdata.ids.port_id);
if (rdata) {
- if (rdata->ids.node_name == new->ids.node_name &&
- rdata->ids.port_name == new->ids.port_name) {
+ if (rdata->ids.node_name == new->rdata.ids.node_name &&
+ rdata->ids.port_name == new->rdata.ids.port_name) {
frport = fcoe_ctlr_rport(rdata);
+
LIBFCOE_FIP_DBG(fip, "beacon from rport %x\n",
rdata->ids.port_id);
if (!frport->time && fip->state == FIP_ST_VNMP_UP) {
@@ -2678,7 +2679,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
* Don't add the neighbor yet.
*/
LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
- new->ids.port_id);
+ new->rdata.ids.port_id);
if (time_after(jiffies,
fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
fcoe_ctlr_vn_send_claim(fip);
@@ -2738,10 +2739,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
struct fip_header *fiph;
enum fip_vn2vn_subcode sub;
- struct {
- struct fc_rport_priv rdata;
- struct fcoe_rport frport;
- } buf;
+ struct fcoe_rport frport = { };
int rc, vlan_id = 0;
fiph = (struct fip_header *)skb->data;
@@ -2757,7 +2755,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
goto drop;
}
- rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
+ rc = fcoe_ctlr_vn_parse(fip, skb, &frport);
if (rc) {
LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
goto drop;
@@ -2766,19 +2764,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
mutex_lock(&fip->ctlr_mutex);
switch (sub) {
case FIP_SC_VN_PROBE_REQ:
- fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
+ fcoe_ctlr_vn_probe_req(fip, &frport);
break;
case FIP_SC_VN_PROBE_REP:
- fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
+ fcoe_ctlr_vn_probe_reply(fip, &frport);
break;
case FIP_SC_VN_CLAIM_NOTIFY:
- fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
+ fcoe_ctlr_vn_claim_notify(fip, &frport);
break;
case FIP_SC_VN_CLAIM_REP:
- fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
+ fcoe_ctlr_vn_claim_resp(fip, &frport);
break;
case FIP_SC_VN_BEACON:
- fcoe_ctlr_vn_beacon(fip, &buf.rdata);
+ fcoe_ctlr_vn_beacon(fip, &frport);
break;
default:
LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
@@ -2802,22 +2800,18 @@ drop:
*/
static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
struct sk_buff *skb,
- struct fc_rport_priv *rdata)
+ struct fcoe_rport *frport)
{
struct fip_header *fiph;
struct fip_desc *desc = NULL;
struct fip_mac_desc *macd = NULL;
struct fip_wwn_desc *wwn = NULL;
- struct fcoe_rport *frport;
size_t rlen;
size_t dlen;
u32 desc_mask = 0;
u32 dtype;
u8 sub;
- memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
- frport = fcoe_ctlr_rport(rdata);
-
fiph = (struct fip_header *)skb->data;
frport->flags = ntohs(fiph->fip_flags);
@@ -2871,7 +2865,8 @@ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
if (dlen != sizeof(struct fip_wwn_desc))
goto len_err;
wwn = (struct fip_wwn_desc *)desc;
- rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+ frport->rdata.ids.node_name =
+ get_unaligned_be64(&wwn->fd_wwn);
break;
default:
LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
@@ -2957,13 +2952,13 @@ static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_vlan_disk_reply() - send FIP VLAN Discovery Notification.
* @fip: The FCoE controller
+ * @frport: The newly-parsed FCoE rport from the Discovery Request
*
* Called with ctlr_mutex held.
*/
static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip,
- struct fc_rport_priv *rdata)
+ struct fcoe_rport *frport)
{
- struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
enum fip_vlan_subcode sub = FIP_SC_VL_NOTE;
if (fip->mode == FIP_MODE_VN2VN)
@@ -2982,22 +2977,19 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
struct fip_header *fiph;
enum fip_vlan_subcode sub;
- struct {
- struct fc_rport_priv rdata;
- struct fcoe_rport frport;
- } buf;
+ struct fcoe_rport frport = { };
int rc;
fiph = (struct fip_header *)skb->data;
sub = fiph->fip_subcode;
- rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
+ rc = fcoe_ctlr_vlan_parse(fip, skb, &frport);
if (rc) {
LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
goto drop;
}
mutex_lock(&fip->ctlr_mutex);
if (sub == FIP_SC_VL_REQ)
- fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
+ fcoe_ctlr_vlan_disc_reply(fip, &frport);
mutex_unlock(&fip->ctlr_mutex);
drop:
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 43a6b5350775..1bb6aada93fa 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2334,6 +2334,8 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h,
case IOACCEL2_SERV_RESPONSE_COMPLETE:
switch (c2->error_data.status) {
case IOACCEL2_STATUS_SR_TASK_COMP_GOOD:
+ if (cmd)
+ cmd->result = 0;
break;
case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND:
cmd->result |= SAM_STAT_CHECK_CONDITION;
@@ -2483,8 +2485,10 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
/* check for good status */
if (likely(c2->error_data.serv_response == 0 &&
- c2->error_data.status == 0))
+ c2->error_data.status == 0)) {
+ cmd->result = 0;
return hpsa_cmd_free_and_done(h, c, cmd);
+ }
/*
* Any RAID offload error results in retry which will use
@@ -5654,6 +5658,12 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
return SCSI_MLQUEUE_DEVICE_BUSY;
/*
+ * This is necessary because the SML doesn't zero out this field during
+ * error recovery.
+ */
+ cmd->result = 0;
+
+ /*
* Call alternate submit routine for I/O accelerated commands.
* Retries always go down the normal I/O path.
*/
@@ -6081,8 +6091,6 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h,
if (idx != h->last_collision_tag) { /* Print once per tag */
dev_warn(&h->pdev->dev,
"%s: tag collision (tag=%d)\n", __func__, idx);
- if (c->scsi_cmd != NULL)
- scsi_print_command(c->scsi_cmd);
if (scmd)
scsi_print_command(scmd);
h->last_collision_tag = idx;
@@ -7798,7 +7806,7 @@ static void hpsa_free_pci_init(struct ctlr_info *h)
hpsa_disable_interrupt_mode(h); /* pci_init 2 */
/*
* call pci_disable_device before pci_release_regions per
- * Documentation/PCI/pci.rst
+ * Documentation/driver-api/pci/pci.rst
*/
pci_disable_device(h->pdev); /* pci_init 1 */
pci_release_regions(h->pdev); /* pci_init 2 */
@@ -7881,7 +7889,7 @@ clean2: /* intmode+region, pci */
clean1:
/*
* call pci_disable_device before pci_release_regions per
- * Documentation/PCI/pci.rst
+ * Documentation/driver-api/pci/pci.rst
*/
pci_disable_device(h->pdev);
pci_release_regions(h->pdev);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index acd16e0d52cf..8cdbac076a1b 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -4864,8 +4864,8 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);
- ibmvfc_free_event_pool(vhost);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_free_event_pool(vhost);
ibmvfc_free_mem(vhost);
spin_lock(&ibmvfc_driver_lock);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index e0f3852fdad1..da6e97d8dc3b 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -128,6 +128,7 @@ EXPORT_SYMBOL(fc_rport_lookup);
struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
{
struct fc_rport_priv *rdata;
+ size_t rport_priv_size = sizeof(*rdata);
lockdep_assert_held(&lport->disc.disc_mutex);
@@ -135,7 +136,9 @@ struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
if (rdata)
return rdata;
- rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL);
+ if (lport->rport_priv_size > 0)
+ rport_priv_size = lport->rport_priv_size;
+ rdata = kzalloc(rport_priv_size, GFP_KERNEL);
if (!rdata)
return NULL;
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index abcad097ff2f..f47b4b281b14 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -459,6 +459,7 @@ static void sas_discover_domain(struct work_struct *work)
pr_notice("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n");
/* Fall through */
#endif
+ /* Fall through - only for the #else condition above. */
default:
error = -ENXIO;
pr_err("unhandled device %d\n", dev->dev_type);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 2c3bb8a966e5..bade2e025ecf 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -824,6 +824,7 @@ struct lpfc_hba {
uint32_t cfg_cq_poll_threshold;
uint32_t cfg_cq_max_proc_limit;
uint32_t cfg_fcp_cpu_map;
+ uint32_t cfg_fcp_mq_threshold;
uint32_t cfg_hdw_queue;
uint32_t cfg_irq_chann;
uint32_t cfg_suppress_rsp;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index ea62322ffe2b..d65558619ab0 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5709,6 +5709,19 @@ LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
"Embed NVME Command in WQE");
/*
+ * lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
+ * the driver will advertise it supports to the SCSI layer.
+ *
+ * 0 = Set nr_hw_queues by the number of CPUs or HW queues.
+ * 1,128 = Manually specify the maximum nr_hw_queue value to be set,
+ *
+ * Value range is [0,256]. Default value is 8.
+ */
+LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
+ LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX,
+ "Set the number of SCSI Queues advertised");
+
+/*
* lpfc_hdw_queue: Set the number of Hardware Queues the driver
* will advertise it supports to the NVME and SCSI layers. This also
* will map to the number of CQ/WQ pairs the driver will create.
@@ -6030,6 +6043,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_cq_poll_threshold,
&dev_attr_lpfc_cq_max_proc_limit,
&dev_attr_lpfc_fcp_cpu_map,
+ &dev_attr_lpfc_fcp_mq_threshold,
&dev_attr_lpfc_hdw_queue,
&dev_attr_lpfc_irq_chann,
&dev_attr_lpfc_suppress_rsp,
@@ -7112,6 +7126,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
/* Initialize first burst. Target vs Initiator are different. */
lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
+ lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold);
lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
lpfc_irq_chann_init(phba, lpfc_irq_chann);
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index faf43b1d3dbe..1ac98becb5ba 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4309,10 +4309,12 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
shost->max_cmd_len = 16;
if (phba->sli_rev == LPFC_SLI_REV4) {
- if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
- shost->nr_hw_queues = phba->cfg_hdw_queue;
- else
- shost->nr_hw_queues = phba->sli4_hba.num_present_cpu;
+ if (!phba->cfg_fcp_mq_threshold ||
+ phba->cfg_fcp_mq_threshold > phba->cfg_hdw_queue)
+ phba->cfg_fcp_mq_threshold = phba->cfg_hdw_queue;
+
+ shost->nr_hw_queues = min_t(int, 2 * num_possible_nodes(),
+ phba->cfg_fcp_mq_threshold);
shost->dma_boundary =
phba->sli4_hba.pc_sli4_params.sge_supp_len-1;
@@ -10776,12 +10778,31 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
/* This loop sets up all CPUs that are affinitized with a
* irq vector assigned to the driver. All affinitized CPUs
* will get a link to that vectors IRQ and EQ.
+ *
+ * NULL affinity mask handling:
+ * If irq count is greater than one, log an error message.
+ * If the null mask is received for the first irq, find the
+ * first present cpu, and assign the eq index to ensure at
+ * least one EQ is assigned.
*/
for (idx = 0; idx < phba->cfg_irq_chann; idx++) {
/* Get a CPU mask for all CPUs affinitized to this vector */
maskp = pci_irq_get_affinity(phba->pcidev, idx);
- if (!maskp)
- continue;
+ if (!maskp) {
+ if (phba->cfg_irq_chann > 1)
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3329 No affinity mask found "
+ "for vector %d (%d)\n",
+ idx, phba->cfg_irq_chann);
+ if (!idx) {
+ cpu = cpumask_first(cpu_present_mask);
+ cpup = &phba->sli4_hba.cpu_map[cpu];
+ cpup->eq = idx;
+ cpup->irq = pci_irq_vector(phba->pcidev, idx);
+ cpup->flag |= LPFC_CPU_FIRST_IRQ;
+ }
+ break;
+ }
i = 0;
/* Loop through all CPUs associated with vector idx */
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 3aeca387b22a..a81ef0293696 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -44,6 +44,11 @@
#define LPFC_HBA_HDWQ_MAX 128
#define LPFC_HBA_HDWQ_DEF 0
+/* FCP MQ queue count limiting */
+#define LPFC_FCP_MQ_THRESHOLD_MIN 0
+#define LPFC_FCP_MQ_THRESHOLD_MAX 256
+#define LPFC_FCP_MQ_THRESHOLD_DEF 8
+
/* Common buffer size to accomidate SCSI and NVME IO buffers */
#define LPFC_COMMON_IO_BUF_SZ 768
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index b2339d04a700..f9f07935556e 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3163,6 +3163,7 @@ fw_crash_buffer_show(struct device *cdev,
(struct megasas_instance *) shost->hostdata;
u32 size;
unsigned long dmachunk = CRASH_DMA_BUF_SIZE;
+ unsigned long chunk_left_bytes;
unsigned long src_addr;
unsigned long flags;
u32 buff_offset;
@@ -3186,6 +3187,8 @@ fw_crash_buffer_show(struct device *cdev,
}
size = (instance->fw_crash_buffer_size * dmachunk) - buff_offset;
+ chunk_left_bytes = dmachunk - (buff_offset % dmachunk);
+ size = (size > chunk_left_bytes) ? chunk_left_bytes : size;
size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
src_addr = (unsigned long)instance->crash_buf[buff_offset / dmachunk] +
@@ -8763,7 +8766,7 @@ static int __init megasas_init(void)
if ((event_log_level < MFI_EVT_CLASS_DEBUG) ||
(event_log_level > MFI_EVT_CLASS_DEAD)) {
- printk(KERN_WARNING "megarid_sas: provided event log level is out of range, setting it to default 2(CLASS_CRITICAL), permissible range is: -2 to 4\n");
+ pr_warn("megaraid_sas: provided event log level is out of range, setting it to default 2(CLASS_CRITICAL), permissible range is: -2 to 4\n");
event_log_level = MFI_EVT_CLASS_CRITICAL;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index a32b3f0fcd15..120e3c4de8c2 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -537,7 +537,7 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
return 0;
}
-int
+static int
megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
{
u32 max_mpt_cmd, i, j;
@@ -576,7 +576,8 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
return 0;
}
-int
+
+static int
megasas_alloc_request_fusion(struct megasas_instance *instance)
{
struct fusion_context *fusion;
@@ -657,7 +658,7 @@ retry_alloc:
return 0;
}
-int
+static int
megasas_alloc_reply_fusion(struct megasas_instance *instance)
{
int i, count;
@@ -734,7 +735,7 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance)
return 0;
}
-int
+static int
megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
{
int i, j, k, msix_count;
@@ -916,7 +917,7 @@ megasas_free_reply_fusion(struct megasas_instance *instance) {
* and is used as SMID of the cmd.
* SMID value range is from 1 to max_fw_cmds.
*/
-int
+static int
megasas_alloc_cmds_fusion(struct megasas_instance *instance)
{
int i;
@@ -1736,7 +1737,7 @@ static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance)
*
* This is the main function for initializing firmware.
*/
-u32
+static u32
megasas_init_adapter_fusion(struct megasas_instance *instance)
{
struct fusion_context *fusion;
@@ -1962,7 +1963,7 @@ megasas_fusion_stop_watchdog(struct megasas_instance *instance)
* @ext_status : ext status of cmd returned by FW
*/
-void
+static void
map_cmd_status(struct fusion_context *fusion,
struct scsi_cmnd *scmd, u8 status, u8 ext_status,
u32 data_length, u8 *sense)
@@ -2375,7 +2376,7 @@ int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp,
*
* Used to set the PD LBA in CDB for FP IOs
*/
-void
+static void
megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
@@ -2714,7 +2715,7 @@ megasas_set_raidflag_cpu_affinity(struct fusion_context *fusion,
* Prepares the io_request and chain elements (sg_frame) for IO
* The IO can be for PD (Fast Path) or LD
*/
-void
+static void
megasas_build_ldio_fusion(struct megasas_instance *instance,
struct scsi_cmnd *scp,
struct megasas_cmd_fusion *cmd)
@@ -3211,7 +3212,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
* Invokes helper functions to prepare request frames
* and sets flags appropriate for IO/Non-IO cmd
*/
-int
+static int
megasas_build_io_fusion(struct megasas_instance *instance,
struct scsi_cmnd *scp,
struct megasas_cmd_fusion *cmd)
@@ -3325,9 +3326,9 @@ megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
/* megasas_prepate_secondRaid1_IO
* It prepares the raid 1 second IO
*/
-void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
- struct megasas_cmd_fusion *cmd,
- struct megasas_cmd_fusion *r1_cmd)
+static void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
+ struct megasas_cmd_fusion *cmd,
+ struct megasas_cmd_fusion *r1_cmd)
{
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc, *req_desc2 = NULL;
struct fusion_context *fusion;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 684662888792..050c0f029ef9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2703,6 +2703,8 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
{
u64 required_mask, coherent_mask;
struct sysinfo s;
+ /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
+ int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64;
if (ioc->is_mcpu_endpoint)
goto try_32bit;
@@ -2712,17 +2714,17 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
goto try_32bit;
if (ioc->dma_mask)
- coherent_mask = DMA_BIT_MASK(64);
+ coherent_mask = DMA_BIT_MASK(dma_mask);
else
coherent_mask = DMA_BIT_MASK(32);
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) ||
+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) ||
dma_set_coherent_mask(&pdev->dev, coherent_mask))
goto try_32bit;
ioc->base_add_sg_single = &_base_add_sg_single_64;
ioc->sge_size = sizeof(Mpi2SGESimple64_t);
- ioc->dma_mask = 64;
+ ioc->dma_mask = dma_mask;
goto out;
try_32bit:
@@ -2744,7 +2746,7 @@ static int
_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
struct pci_dev *pdev)
{
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) {
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
return -ENODEV;
}
@@ -4989,7 +4991,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
total_sz += sz;
} while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
- if (ioc->dma_mask == 64) {
+ if (ioc->dma_mask > 32) {
if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
pci_name(ioc->pdev));
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index e5760c4a27f0..832af4213046 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -357,10 +357,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
-#include <asm/sn/io.h>
-#endif
-
/*
* Compile time Options:
@@ -380,11 +376,6 @@
#define NVRAM_DELAY() udelay(500) /* 2 microseconds */
-#if defined(__ia64__) && !defined(ia64_platform_is)
-#define ia64_platform_is(foo) (!strcmp(x, platform_name))
-#endif
-
-
#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020)
#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \
ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240)
@@ -1427,15 +1418,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
ha->flags.reset_active = 0;
ha->flags.abort_isp_active = 0;
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
- if (ia64_platform_is("sn2")) {
- printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
- "dual channel lockup workaround\n", ha->host_no);
- ha->flags.use_pci_vchannel = 1;
- driver_setup.no_nvram = 1;
- }
-#endif
-
/* TODO: implement support for the 1040 nvram format */
if (IS_ISP1040(ha))
driver_setup.no_nvram = 1;
@@ -2251,13 +2233,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
mb[1] = nv->firmware_feature.f.enable_fast_posting;
mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1;
mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5;
-#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2)
- if (ia64_platform_is("sn2")) {
- printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
- "workaround\n", ha->host_no);
- mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */
- }
-#endif
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* Retry count and delay. */
@@ -2888,12 +2863,6 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
break;
dma_handle = sg_dma_address(s);
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
- if (ha->flags.use_pci_vchannel)
- sn_pci_set_vchan(ha->pdev,
- (unsigned long *)&dma_handle,
- SCSI_BUS_32(cmd));
-#endif
*dword_ptr++ =
cpu_to_le32(lower_32_bits(dma_handle));
*dword_ptr++ =
@@ -2950,12 +2919,6 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
if (cnt == 5)
break;
dma_handle = sg_dma_address(s);
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
- if (ha->flags.use_pci_vchannel)
- sn_pci_set_vchan(ha->pdev,
- (unsigned long *)&dma_handle,
- SCSI_BUS_32(cmd));
-#endif
*dword_ptr++ =
cpu_to_le32(lower_32_bits(dma_handle));
*dword_ptr++ =
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index b496206362a9..a1a8aefc7cc3 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -1055,9 +1055,6 @@ struct scsi_qla_host {
uint32_t reset_active:1; /* 3 */
uint32_t abort_isp_active:1; /* 4 */
uint32_t disable_risc_code_load:1; /* 5 */
-#ifdef __ia64__
- uint32_t use_pci_vchannel:1;
-#endif
} flags;
struct nvram nvram;
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 8d560c562e9c..6b7b390b2e52 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2956,6 +2956,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma);
+ vha->gnl.l = NULL;
+
vfree(vha->scan.l);
if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4059655639d9..d4c3baec9172 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -4575,20 +4575,6 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
rval = 1;
}
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
- /*
- * The SN2 does not provide BIOS emulation which means you can't change
- * potentially bogus BIOS settings. Force the use of default settings
- * for link rate and frame size. Hope that the rest of the settings
- * are valid.
- */
- if (ia64_platform_is("sn2")) {
- nv->frame_payload_size = 2048;
- if (IS_QLA23XX(ha))
- nv->special_options[1] = BIT_7;
- }
-#endif
-
/* Reset Initialization control block */
memset(icb, 0, ha->init_cb_size);
@@ -4877,7 +4863,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
ql_log(ql_log_warn, vha, 0xd049,
"Failed to allocate ct_sns request.\n");
kfree(fcport);
- fcport = NULL;
+ return NULL;
}
INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2e58cff9d200..98e60a34afd9 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3440,6 +3440,12 @@ skip_dpc:
return 0;
probe_failed:
+ if (base_vha->gnl.l) {
+ dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
+ base_vha->gnl.l, base_vha->gnl.ldma);
+ base_vha->gnl.l = NULL;
+ }
+
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
base_vha->flags.online = 0;
@@ -3673,7 +3679,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
if (!atomic_read(&pdev->enable_cnt)) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
-
+ base_vha->gnl.l = NULL;
scsi_host_put(base_vha->host);
kfree(ha);
pci_set_drvdata(pdev, NULL);
@@ -3713,6 +3719,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
dma_free_coherent(&ha->pdev->dev,
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
+ base_vha->gnl.l = NULL;
+
vfree(base_vha->scan.l);
if (IS_QLAFX00(ha))
@@ -4816,6 +4824,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
"Alloc failed for scan database.\n");
dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
vha->gnl.l, vha->gnl.ldma);
+ vha->gnl.l = NULL;
scsi_remove_host(vha->host);
return NULL;
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9381171c2fc0..11e64b50497f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1784,8 +1784,10 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
blk_queue_max_integrity_segments(q, shost->sg_prot_tablesize);
}
- shost->max_sectors = min_t(unsigned int, shost->max_sectors,
- dma_max_mapping_size(dev) << SECTOR_SHIFT);
+ if (dev->dma_mask) {
+ shost->max_sectors = min_t(unsigned int, shost->max_sectors,
+ dma_max_mapping_size(dev) >> SECTOR_SHIFT);
+ }
blk_queue_max_hw_sectors(q, shost->max_sectors);
if (shost->unchecked_isa_dma)
blk_queue_bounce_limit(q, BLK_BOUNCE_ISA);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e274053109d0..029da74bb2f5 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7062,6 +7062,9 @@ static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
struct ufs_vreg *vreg)
{
+ if (!vreg)
+ return 0;
+
return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
}
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
deleted file mode 100644
index a6c443d31a3c..000000000000
--- a/drivers/sn/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Miscellaneous SN-specific devices
-#
-
-menu "SN Devices"
- depends on SGI_SN
-
-config SGI_IOC3
- tristate "SGI IOC3 Base IO support"
- default m
- ---help---
- This option enables basic support for the SGI IOC3-based Base IO
- controller card. This option does not enable any specific
- functions on such a card, but provides necessary infrastructure
- for other drivers to utilize.
-
- If you have an SGI Altix with an IOC3-based
- I/O controller or a PCI IOC3 serial card say Y.
- Otherwise say N.
-
-endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
deleted file mode 100644
index f0e809a38b2d..000000000000
--- a/drivers/sn/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the Altix device drivers.
-#
-#
-
-obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
deleted file mode 100644
index 358025af4918..000000000000
--- a/drivers/sn/ioc3.c
+++ /dev/null
@@ -1,844 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * SGI IOC3 master driver and IRQ demuxer
- *
- * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
- * Heavily based on similar work by:
- * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
- * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/ioc3.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-
-#define IOC3_PCI_SIZE 0x100000
-
-static LIST_HEAD(ioc3_devices);
-static int ioc3_counter;
-static DECLARE_RWSEM(ioc3_devices_rwsem);
-
-static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
-static struct ioc3_submodule *ioc3_ethernet;
-static DEFINE_RWLOCK(ioc3_submodules_lock);
-
-/* NIC probing code */
-
-#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
-
-static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
-{
- return (pulse << 10) | (sample << 2);
-}
-
-static int nic_wait(struct ioc3_driver_data *idd)
-{
- unsigned mcr;
-
- do {
- mcr = readl(&idd->vma->mcr);
- } while (!(mcr & 2));
-
- return mcr & 1;
-}
-
-static int nic_reset(struct ioc3_driver_data *idd)
-{
- int presence;
- unsigned long flags;
-
- local_irq_save(flags);
- writel(mcr_pack(500, 65), &idd->vma->mcr);
- presence = nic_wait(idd);
- local_irq_restore(flags);
-
- udelay(500);
-
- return presence;
-}
-
-static int nic_read_bit(struct ioc3_driver_data *idd)
-{
- int result;
- unsigned long flags;
-
- local_irq_save(flags);
- writel(mcr_pack(6, 13), &idd->vma->mcr);
- result = nic_wait(idd);
- local_irq_restore(flags);
-
- udelay(500);
-
- return result;
-}
-
-static void nic_write_bit(struct ioc3_driver_data *idd, int bit)
-{
- if (bit)
- writel(mcr_pack(6, 110), &idd->vma->mcr);
- else
- writel(mcr_pack(80, 30), &idd->vma->mcr);
-
- nic_wait(idd);
-}
-
-static unsigned nic_read_byte(struct ioc3_driver_data *idd)
-{
- unsigned result = 0;
- int i;
-
- for (i = 0; i < 8; i++)
- result = (result >> 1) | (nic_read_bit(idd) << 7);
-
- return result;
-}
-
-static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
-{
- int i, bit;
-
- for (i = 8; i; i--) {
- bit = byte & 1;
- byte >>= 1;
-
- nic_write_bit(idd, bit);
- }
-}
-
-static unsigned long
-nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
-{
- int a, b, index, disc;
-
- nic_reset(idd);
-
- /* Search ROM. */
- nic_write_byte(idd, 0xF0);
-
- /* Algorithm from ``Book of iButton Standards''. */
- for (index = 0, disc = 0; index < 64; index++) {
- a = nic_read_bit(idd);
- b = nic_read_bit(idd);
-
- if (a && b) {
- printk(KERN_WARNING "IOC3 NIC search failed.\n");
- *last = 0;
- return 0;
- }
-
- if (!a && !b) {
- if (index == *last) {
- addr |= 1UL << index;
- } else if (index > *last) {
- addr &= ~(1UL << index);
- disc = index;
- } else if ((addr & (1UL << index)) == 0)
- disc = index;
- nic_write_bit(idd, (addr>>index)&1);
- continue;
- } else {
- if (a)
- addr |= 1UL << index;
- else
- addr &= ~(1UL << index);
- nic_write_bit(idd, a);
- continue;
- }
- }
- *last = disc;
- return addr;
-}
-
-static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
-{
- int index;
-
- nic_reset(idd);
- nic_write_byte(idd, 0xF0);
- for (index = 0; index < 64; index++) {
- nic_read_bit(idd);
- nic_read_bit(idd);
- nic_write_bit(idd, (addr>>index)&1);
- }
-}
-
-static void crc16_byte(unsigned int *crc, unsigned char db)
-{
- int i;
-
- for(i=0;i<8;i++) {
- *crc <<= 1;
- if((db^(*crc>>16)) & 1)
- *crc ^= 0x8005;
- db >>= 1;
- }
- *crc &= 0xFFFF;
-}
-
-static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc)
-{
- while(size--)
- crc16_byte(&crc, *(dbs++));
- return crc;
-}
-
-static void crc8_byte(unsigned int *crc, unsigned char db)
-{
- int i,f;
-
- for(i=0;i<8;i++) {
- f = (*crc ^ db) & 1;
- *crc >>= 1;
- db >>= 1;
- if(f)
- *crc ^= 0x8c;
- }
- *crc &= 0xff;
-}
-
-static unsigned int crc8_addr(unsigned long addr)
-{
- int i;
- unsigned int crc = 0x00;
-
- for(i=0;i<8;i++)
- crc8_byte(&crc, addr>>(i<<3));
- return crc;
-}
-
-static void
-read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page,
- unsigned char *redir, unsigned char *data)
-{
- int loops = 16, i;
-
- while(redir[page] != 0xFF) {
- page = redir[page]^0xFF;
- loops--;
- if(loops<0) {
- printk(KERN_ERR "IOC3: NIC circular redirection\n");
- return;
- }
- }
- loops = 3;
- while(loops>0) {
- nic_addr(idd, addr);
- nic_write_byte(idd, 0xF0);
- nic_write_byte(idd, (page << 5) & 0xE0);
- nic_write_byte(idd, (page >> 3) & 0x1F);
- for(i=0;i<0x20;i++)
- data[i] = nic_read_byte(idd);
- if(crc16_area(data, 0x20, 0x0000) == 0x800d)
- return;
- loops--;
- }
- printk(KERN_ERR "IOC3: CRC error in data page\n");
- for(i=0;i<0x20;i++)
- data[i] = 0x00;
-}
-
-static void
-read_redir_map(struct ioc3_driver_data *idd, unsigned long addr,
- unsigned char *redir)
-{
- int i,j,loops = 3,crc_ok;
- unsigned int crc;
-
- while(loops>0) {
- crc_ok = 1;
- nic_addr(idd, addr);
- nic_write_byte(idd, 0xAA);
- nic_write_byte(idd, 0x00);
- nic_write_byte(idd, 0x01);
- for(i=0;i<64;i+=8) {
- for(j=0;j<8;j++)
- redir[i+j] = nic_read_byte(idd);
- crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000);
- crc16_byte(&crc, nic_read_byte(idd));
- crc16_byte(&crc, nic_read_byte(idd));
- if(crc != 0x800d)
- crc_ok = 0;
- }
- if(crc_ok)
- return;
- loops--;
- }
- printk(KERN_ERR "IOC3: CRC error in redirection page\n");
- for(i=0;i<64;i++)
- redir[i] = 0xFF;
-}
-
-static void read_nic(struct ioc3_driver_data *idd, unsigned long addr)
-{
- unsigned char redir[64];
- unsigned char data[64],part[32];
- int i,j;
-
- /* read redirections */
- read_redir_map(idd, addr, redir);
- /* read data pages */
- read_redir_page(idd, addr, 0, redir, data);
- read_redir_page(idd, addr, 1, redir, data+32);
- /* assemble the part # */
- j=0;
- for(i=0;i<19;i++)
- if(data[i+11] != ' ')
- part[j++] = data[i+11];
- for(i=0;i<6;i++)
- if(data[i+32] != ' ')
- part[j++] = data[i+32];
- part[j] = 0;
- /* skip Octane power supplies */
- if(!strncmp(part, "060-0035-", 9))
- return;
- if(!strncmp(part, "060-0038-", 9))
- return;
- strcpy(idd->nic_part, part);
- /* assemble the serial # */
- j=0;
- for(i=0;i<10;i++)
- if(data[i+1] != ' ')
- idd->nic_serial[j++] = data[i+1];
- idd->nic_serial[j] = 0;
-}
-
-static void read_mac(struct ioc3_driver_data *idd, unsigned long addr)
-{
- int i, loops = 3;
- unsigned char data[13];
-
- while(loops>0) {
- nic_addr(idd, addr);
- nic_write_byte(idd, 0xF0);
- nic_write_byte(idd, 0x00);
- nic_write_byte(idd, 0x00);
- nic_read_byte(idd);
- for(i=0;i<13;i++)
- data[i] = nic_read_byte(idd);
- if(crc16_area(data, 13, 0x0000) == 0x800d) {
- for(i=10;i>4;i--)
- idd->nic_mac[10-i] = data[i];
- return;
- }
- loops--;
- }
- printk(KERN_ERR "IOC3: CRC error in MAC address\n");
- for(i=0;i<6;i++)
- idd->nic_mac[i] = 0x00;
-}
-
-static void probe_nic(struct ioc3_driver_data *idd)
-{
- int save = 0, loops = 3;
- unsigned long first, addr;
-
- writel(GPCR_MLAN_EN, &idd->vma->gpcr_s);
-
- while(loops>0) {
- idd->nic_part[0] = 0;
- idd->nic_serial[0] = 0;
- addr = first = nic_find(idd, &save, 0);
- if(!first)
- return;
- while(1) {
- if(crc8_addr(addr))
- break;
- else {
- switch(addr & 0xFF) {
- case 0x0B:
- read_nic(idd, addr);
- break;
- case 0x09:
- case 0x89:
- case 0x91:
- read_mac(idd, addr);
- break;
- }
- }
- addr = nic_find(idd, &save, addr);
- if(addr == first)
- return;
- }
- loops--;
- }
- printk(KERN_ERR "IOC3: CRC error in NIC address\n");
-}
-
-/* Interrupts */
-
-static void write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&idd->ir_lock, flags);
- switch (which) {
- case IOC3_W_IES:
- writel(val, &idd->vma->sio_ies);
- break;
- case IOC3_W_IEC:
- writel(val, &idd->vma->sio_iec);
- break;
- }
- spin_unlock_irqrestore(&idd->ir_lock, flags);
-}
-static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd)
-{
- unsigned long flag;
- uint32_t intrs = 0;
-
- spin_lock_irqsave(&idd->ir_lock, flag);
- intrs = readl(&idd->vma->sio_ir);
- intrs &= readl(&idd->vma->sio_ies);
- spin_unlock_irqrestore(&idd->ir_lock, flag);
- return intrs;
-}
-
-static irqreturn_t ioc3_intr_io(int irq, void *arg)
-{
- unsigned long flags;
- struct ioc3_driver_data *idd = arg;
- int handled = 1, id;
- unsigned int pending;
-
- read_lock_irqsave(&ioc3_submodules_lock, flags);
-
- if(idd->dual_irq && readb(&idd->vma->eisr)) {
- /* send Ethernet IRQ to the driver */
- if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
- ioc3_ethernet->intr) {
- handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
- idd, 0);
- }
- }
- pending = get_pending_intrs(idd); /* look at the IO IRQs */
-
- for(id=0;id<IOC3_MAX_SUBMODULES;id++) {
- if(idd->active[id] && ioc3_submodules[id]
- && (pending & ioc3_submodules[id]->irq_mask)
- && ioc3_submodules[id]->intr) {
- write_ireg(idd, ioc3_submodules[id]->irq_mask,
- IOC3_W_IEC);
- if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
- idd, pending & ioc3_submodules[id]->irq_mask))
- pending &= ~ioc3_submodules[id]->irq_mask;
- if (ioc3_submodules[id]->reset_mask)
- write_ireg(idd, ioc3_submodules[id]->irq_mask,
- IOC3_W_IES);
- }
- }
- read_unlock_irqrestore(&ioc3_submodules_lock, flags);
- if(pending) {
- printk(KERN_WARNING
- "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending);
- write_ireg(idd, pending, IOC3_W_IEC);
- handled = 1;
- }
- return handled?IRQ_HANDLED:IRQ_NONE;
-}
-
-static irqreturn_t ioc3_intr_eth(int irq, void *arg)
-{
- unsigned long flags;
- struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
- int handled = 1;
-
- if(!idd->dual_irq)
- return IRQ_NONE;
- read_lock_irqsave(&ioc3_submodules_lock, flags);
- if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
- && ioc3_ethernet->intr)
- handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0);
- read_unlock_irqrestore(&ioc3_submodules_lock, flags);
- return handled?IRQ_HANDLED:IRQ_NONE;
-}
-
-void ioc3_enable(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd, unsigned int irqs)
-{
- write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES);
-}
-
-void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd,
- unsigned int irqs)
-{
- writel(irqs & is->irq_mask, &idd->vma->sio_ir);
-}
-
-void ioc3_disable(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd, unsigned int irqs)
-{
- write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC);
-}
-
-void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val)
-{
- unsigned long flags;
- spin_lock_irqsave(&idd->gpio_lock, flags);
- writel(val, &idd->vma->gpcr_s);
- spin_unlock_irqrestore(&idd->gpio_lock, flags);
-}
-
-/* Keep it simple, stupid! */
-static int find_slot(void **tab, int max)
-{
- int i;
- for(i=0;i<max;i++)
- if(!(tab[i]))
- return i;
- return -1;
-}
-
-/* Register an IOC3 submodule */
-int ioc3_register_submodule(struct ioc3_submodule *is)
-{
- struct ioc3_driver_data *idd;
- int alloc_id;
- unsigned long flags;
-
- write_lock_irqsave(&ioc3_submodules_lock, flags);
- alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
- if(alloc_id != -1) {
- ioc3_submodules[alloc_id] = is;
- if(is->ethernet) {
- if(ioc3_ethernet==NULL)
- ioc3_ethernet=is;
- else
- printk(KERN_WARNING
- "IOC3 Ethernet module already registered!\n");
- }
- }
- write_unlock_irqrestore(&ioc3_submodules_lock, flags);
-
- if(alloc_id == -1) {
- printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
- return -ENOMEM;
- }
-
- is->id=alloc_id;
-
- /* Initialize submodule for each IOC3 */
- if (!is->probe)
- return 0;
-
- down_read(&ioc3_devices_rwsem);
- list_for_each_entry(idd, &ioc3_devices, list) {
- /* set to 1 for IRQs in probe */
- idd->active[alloc_id] = 1;
- idd->active[alloc_id] = !is->probe(is, idd);
- }
- up_read(&ioc3_devices_rwsem);
-
- return 0;
-}
-
-/* Unregister an IOC3 submodule */
-void ioc3_unregister_submodule(struct ioc3_submodule *is)
-{
- struct ioc3_driver_data *idd;
- unsigned long flags;
-
- write_lock_irqsave(&ioc3_submodules_lock, flags);
- if(ioc3_submodules[is->id]==is)
- ioc3_submodules[is->id]=NULL;
- else
- printk(KERN_WARNING
- "IOC3 submodule %s has wrong ID.\n",is->name);
- if(ioc3_ethernet==is)
- ioc3_ethernet = NULL;
- write_unlock_irqrestore(&ioc3_submodules_lock, flags);
-
- /* Remove submodule for each IOC3 */
- down_read(&ioc3_devices_rwsem);
- list_for_each_entry(idd, &ioc3_devices, list)
- if(idd->active[is->id]) {
- if(is->remove)
- if(is->remove(is, idd))
- printk(KERN_WARNING
- "%s: IOC3 submodule %s remove failed "
- "for pci_dev %s.\n",
- __func__, module_name(is->owner),
- pci_name(idd->pdev));
- idd->active[is->id] = 0;
- if(is->irq_mask)
- write_ireg(idd, is->irq_mask, IOC3_W_IEC);
- }
- up_read(&ioc3_devices_rwsem);
-}
-
-/*********************
- * Device management *
- *********************/
-
-static char *ioc3_class_names[] = { "unknown", "IP27 BaseIO", "IP30 system",
- "MENET 1/2/3", "MENET 4", "CADduo", "Altix Serial" };
-
-static int ioc3_class(struct ioc3_driver_data *idd)
-{
- int res = IOC3_CLASS_NONE;
- /* NIC-based logic */
- if(!strncmp(idd->nic_part, "030-0891-", 9))
- res = IOC3_CLASS_BASE_IP30;
- if(!strncmp(idd->nic_part, "030-1155-", 9))
- res = IOC3_CLASS_CADDUO;
- if(!strncmp(idd->nic_part, "030-1657-", 9))
- res = IOC3_CLASS_SERIAL;
- if(!strncmp(idd->nic_part, "030-1664-", 9))
- res = IOC3_CLASS_SERIAL;
- /* total random heuristics */
-#ifdef CONFIG_SGI_IP27
- if(!idd->nic_part[0])
- res = IOC3_CLASS_BASE_IP27;
-#endif
- /* print educational message */
- printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n",
- idd->nic_part, idd->nic_serial, ioc3_class_names[res]);
- return res;
-}
-/* Adds a new instance of an IOC3 card */
-static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
- struct ioc3_driver_data *idd;
- uint32_t pcmd;
- int ret, id;
-
- /* Enable IOC3 and take ownership of it */
- if ((ret = pci_enable_device(pdev))) {
- printk(KERN_WARNING
- "%s: Failed to enable IOC3 device for pci_dev %s.\n",
- __func__, pci_name(pdev));
- goto out;
- }
- pci_set_master(pdev);
-
-#ifdef USE_64BIT_DMA
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
- if (!ret) {
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (ret < 0) {
- printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
- "for consistent allocations\n",
- __func__);
- }
- }
-#endif
-
- /* Set up per-IOC3 data */
- idd = kzalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
- if (!idd) {
- printk(KERN_WARNING
- "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
- __func__, pci_name(pdev));
- ret = -ENODEV;
- goto out_idd;
- }
- spin_lock_init(&idd->ir_lock);
- spin_lock_init(&idd->gpio_lock);
- idd->pdev = pdev;
-
- /* Map all IOC3 registers. These are shared between subdevices
- * so the main IOC3 module manages them.
- */
- idd->pma = pci_resource_start(pdev, 0);
- if (!idd->pma) {
- printk(KERN_WARNING
- "%s: Unable to find IOC3 resource "
- "for pci_dev %s.\n",
- __func__, pci_name(pdev));
- ret = -ENODEV;
- goto out_pci;
- }
- if (!request_mem_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
- printk(KERN_WARNING
- "%s: Unable to request IOC3 region "
- "for pci_dev %s.\n",
- __func__, pci_name(pdev));
- ret = -ENODEV;
- goto out_pci;
- }
- idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE);
- if (!idd->vma) {
- printk(KERN_WARNING
- "%s: Unable to remap IOC3 region "
- "for pci_dev %s.\n",
- __func__, pci_name(pdev));
- ret = -ENODEV;
- goto out_misc_region;
- }
-
- /* Track PCI-device specific data */
- pci_set_drvdata(pdev, idd);
- down_write(&ioc3_devices_rwsem);
- list_add_tail(&idd->list, &ioc3_devices);
- idd->id = ioc3_counter++;
- up_write(&ioc3_devices_rwsem);
-
- idd->gpdr_shadow = readl(&idd->vma->gpdr);
-
- /* Read IOC3 NIC contents */
- probe_nic(idd);
-
- /* Detect IOC3 class */
- idd->class = ioc3_class(idd);
-
- /* Initialize IOC3 */
- pci_read_config_dword(pdev, PCI_COMMAND, &pcmd);
- pci_write_config_dword(pdev, PCI_COMMAND,
- pcmd | PCI_COMMAND_MEMORY |
- PCI_COMMAND_PARITY | PCI_COMMAND_SERR |
- PCI_SCR_DROP_MODE_EN);
-
- write_ireg(idd, ~0, IOC3_W_IEC);
- writel(~0, &idd->vma->sio_ir);
-
- /* Set up IRQs */
- if(idd->class == IOC3_CLASS_BASE_IP30
- || idd->class == IOC3_CLASS_BASE_IP27) {
- writel(0, &idd->vma->eier);
- writel(~0, &idd->vma->eisr);
-
- idd->dual_irq = 1;
- if (!request_irq(pdev->irq, ioc3_intr_eth, IRQF_SHARED,
- "ioc3-eth", (void *)idd)) {
- idd->irq_eth = pdev->irq;
- } else {
- printk(KERN_WARNING
- "%s : request_irq fails for IRQ 0x%x\n ",
- __func__, pdev->irq);
- }
- if (!request_irq(pdev->irq+2, ioc3_intr_io, IRQF_SHARED,
- "ioc3-io", (void *)idd)) {
- idd->irq_io = pdev->irq+2;
- } else {
- printk(KERN_WARNING
- "%s : request_irq fails for IRQ 0x%x\n ",
- __func__, pdev->irq+2);
- }
- } else {
- if (!request_irq(pdev->irq, ioc3_intr_io, IRQF_SHARED,
- "ioc3", (void *)idd)) {
- idd->irq_io = pdev->irq;
- } else {
- printk(KERN_WARNING
- "%s : request_irq fails for IRQ 0x%x\n ",
- __func__, pdev->irq);
- }
- }
-
- /* Add this IOC3 to all submodules */
- for(id=0;id<IOC3_MAX_SUBMODULES;id++)
- if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
- idd->active[id] = 1;
- idd->active[id] = !ioc3_submodules[id]->probe
- (ioc3_submodules[id], idd);
- }
-
- printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
-
- return 0;
-
-out_misc_region:
- release_mem_region(idd->pma, IOC3_PCI_SIZE);
-out_pci:
- kfree(idd);
-out_idd:
- pci_disable_device(pdev);
-out:
- return ret;
-}
-
-/* Removes a particular instance of an IOC3 card. */
-static void ioc3_remove(struct pci_dev *pdev)
-{
- int id;
- struct ioc3_driver_data *idd;
-
- idd = pci_get_drvdata(pdev);
-
- /* Remove this IOC3 from all submodules */
- for(id=0;id<IOC3_MAX_SUBMODULES;id++)
- if(idd->active[id]) {
- if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
- if(ioc3_submodules[id]->remove(ioc3_submodules[id],
- idd))
- printk(KERN_WARNING
- "%s: IOC3 submodule 0x%s remove failed "
- "for pci_dev %s.\n",
- __func__,
- module_name(ioc3_submodules[id]->owner),
- pci_name(pdev));
- idd->active[id] = 0;
- }
-
- /* Clear and disable all IRQs */
- write_ireg(idd, ~0, IOC3_W_IEC);
- writel(~0, &idd->vma->sio_ir);
-
- /* Release resources */
- free_irq(idd->irq_io, (void *)idd);
- if(idd->dual_irq)
- free_irq(idd->irq_eth, (void *)idd);
- iounmap(idd->vma);
- release_mem_region(idd->pma, IOC3_PCI_SIZE);
-
- /* Disable IOC3 and relinquish */
- pci_disable_device(pdev);
-
- /* Remove and free driver data */
- down_write(&ioc3_devices_rwsem);
- list_del(&idd->list);
- up_write(&ioc3_devices_rwsem);
- kfree(idd);
-}
-
-static struct pci_device_id ioc3_id_table[] = {
- {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID},
- {0}
-};
-
-static struct pci_driver ioc3_driver = {
- .name = "IOC3",
- .id_table = ioc3_id_table,
- .probe = ioc3_probe,
- .remove = ioc3_remove,
-};
-
-MODULE_DEVICE_TABLE(pci, ioc3_id_table);
-
-/*********************
- * Module management *
- *********************/
-
-/* Module load */
-static int __init ioc3_init(void)
-{
- if (ia64_platform_is("sn2"))
- return pci_register_driver(&ioc3_driver);
- return -ENODEV;
-}
-
-/* Module unload */
-static void __exit ioc3_exit(void)
-{
- pci_unregister_driver(&ioc3_driver);
-}
-
-module_init(ioc3_init);
-module_exit(ioc3_exit);
-
-MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
-MODULE_DESCRIPTION("PCI driver for SGI IOC3");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL_GPL(ioc3_register_submodule);
-EXPORT_SYMBOL_GPL(ioc3_unregister_submodule);
-EXPORT_SYMBOL_GPL(ioc3_ack);
-EXPORT_SYMBOL_GPL(ioc3_gpcr_set);
-EXPORT_SYMBOL_GPL(ioc3_disable);
-EXPORT_SYMBOL_GPL(ioc3_enable);
diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
index 23bfb8ef4fdb..bc2c912949bd 100644
--- a/drivers/soc/amlogic/Kconfig
+++ b/drivers/soc/amlogic/Kconfig
@@ -37,6 +37,17 @@ config MESON_GX_PM_DOMAINS
Say yes to expose Amlogic Meson GX Power Domains as
Generic Power Domains.
+config MESON_EE_PM_DOMAINS
+ bool "Amlogic Meson Everything-Else Power Domains driver"
+ depends on ARCH_MESON || COMPILE_TEST
+ depends on PM && OF
+ default ARCH_MESON
+ select PM_GENERIC_DOMAINS
+ select PM_GENERIC_DOMAINS_OF
+ help
+ Say yes to expose Amlogic Meson Everything-Else Power Domains as
+ Generic Power Domains.
+
config MESON_MX_SOCINFO
bool "Amlogic Meson MX SoC Information driver"
depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
index f2e4ed171297..de79d044b545 100644
--- a/drivers/soc/amlogic/Makefile
+++ b/drivers/soc/amlogic/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o
obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
+obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
index 19d4cbc93a17..0fa47d77577d 100644
--- a/drivers/soc/amlogic/meson-clk-measure.c
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -11,6 +11,8 @@
#include <linux/debugfs.h>
#include <linux/regmap.h>
+static DEFINE_MUTEX(measure_lock);
+
#define MSR_CLK_DUTY 0x0
#define MSR_CLK_REG0 0x4
#define MSR_CLK_REG1 0x8
@@ -322,6 +324,8 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
CLK_MSR_ID(84, "co_tx"),
CLK_MSR_ID(89, "hdmi_todig"),
CLK_MSR_ID(90, "hdmitx_sys"),
+ CLK_MSR_ID(91, "sys_cpub_div16"),
+ CLK_MSR_ID(92, "sys_pll_cpub_div16"),
CLK_MSR_ID(94, "eth_phy_rx"),
CLK_MSR_ID(95, "eth_phy_pll"),
CLK_MSR_ID(96, "vpu_b"),
@@ -353,6 +357,136 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
CLK_MSR_ID(122, "audio_pdm_dclk"),
};
+static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
+ CLK_MSR_ID(0, "ring_osc_out_ee_0"),
+ CLK_MSR_ID(1, "ring_osc_out_ee_1"),
+ CLK_MSR_ID(2, "ring_osc_out_ee_2"),
+ CLK_MSR_ID(3, "ring_osc_out_ee_3"),
+ CLK_MSR_ID(4, "gp0_pll"),
+ CLK_MSR_ID(5, "gp1_pll"),
+ CLK_MSR_ID(6, "enci"),
+ CLK_MSR_ID(7, "clk81"),
+ CLK_MSR_ID(8, "encp"),
+ CLK_MSR_ID(9, "encl"),
+ CLK_MSR_ID(10, "vdac"),
+ CLK_MSR_ID(11, "eth_tx"),
+ CLK_MSR_ID(12, "hifi_pll"),
+ CLK_MSR_ID(13, "mod_tcon"),
+ CLK_MSR_ID(14, "fec_0"),
+ CLK_MSR_ID(15, "fec_1"),
+ CLK_MSR_ID(16, "fec_2"),
+ CLK_MSR_ID(17, "sys_pll_div16"),
+ CLK_MSR_ID(18, "sys_cpu_div16"),
+ CLK_MSR_ID(19, "lcd_an_ph2"),
+ CLK_MSR_ID(20, "rtc_osc_out"),
+ CLK_MSR_ID(21, "lcd_an_ph3"),
+ CLK_MSR_ID(22, "eth_phy_ref"),
+ CLK_MSR_ID(23, "mpll_50m"),
+ CLK_MSR_ID(24, "eth_125m"),
+ CLK_MSR_ID(25, "eth_rmii"),
+ CLK_MSR_ID(26, "sc_int"),
+ CLK_MSR_ID(27, "in_mac"),
+ CLK_MSR_ID(28, "sar_adc"),
+ CLK_MSR_ID(29, "pcie_inp"),
+ CLK_MSR_ID(30, "pcie_inn"),
+ CLK_MSR_ID(31, "mpll_test_out"),
+ CLK_MSR_ID(32, "vdec"),
+ CLK_MSR_ID(34, "eth_mpll_50m"),
+ CLK_MSR_ID(35, "mali"),
+ CLK_MSR_ID(36, "hdmi_tx_pixel"),
+ CLK_MSR_ID(37, "cdac"),
+ CLK_MSR_ID(38, "vdin_meas"),
+ CLK_MSR_ID(39, "bt656"),
+ CLK_MSR_ID(40, "arm_ring_osc_out_4"),
+ CLK_MSR_ID(41, "eth_rx_or_rmii"),
+ CLK_MSR_ID(42, "mp0_out"),
+ CLK_MSR_ID(43, "fclk_div5"),
+ CLK_MSR_ID(44, "pwm_b"),
+ CLK_MSR_ID(45, "pwm_a"),
+ CLK_MSR_ID(46, "vpu"),
+ CLK_MSR_ID(47, "ddr_dpll_pt"),
+ CLK_MSR_ID(48, "mp1_out"),
+ CLK_MSR_ID(49, "mp2_out"),
+ CLK_MSR_ID(50, "mp3_out"),
+ CLK_MSR_ID(51, "sd_emmc_c"),
+ CLK_MSR_ID(52, "sd_emmc_b"),
+ CLK_MSR_ID(53, "sd_emmc_a"),
+ CLK_MSR_ID(54, "vpu_clkc"),
+ CLK_MSR_ID(55, "vid_pll_div_out"),
+ CLK_MSR_ID(56, "wave420l_a"),
+ CLK_MSR_ID(57, "wave420l_c"),
+ CLK_MSR_ID(58, "wave420l_b"),
+ CLK_MSR_ID(59, "hcodec"),
+ CLK_MSR_ID(60, "arm_ring_osc_out_5"),
+ CLK_MSR_ID(61, "gpio_msr"),
+ CLK_MSR_ID(62, "hevcb"),
+ CLK_MSR_ID(63, "dsi_meas"),
+ CLK_MSR_ID(64, "spicc_1"),
+ CLK_MSR_ID(65, "spicc_0"),
+ CLK_MSR_ID(66, "vid_lock"),
+ CLK_MSR_ID(67, "dsi_phy"),
+ CLK_MSR_ID(68, "hdcp22_esm"),
+ CLK_MSR_ID(69, "hdcp22_skp"),
+ CLK_MSR_ID(70, "pwm_f"),
+ CLK_MSR_ID(71, "pwm_e"),
+ CLK_MSR_ID(72, "pwm_d"),
+ CLK_MSR_ID(73, "pwm_c"),
+ CLK_MSR_ID(74, "arm_ring_osc_out_6"),
+ CLK_MSR_ID(75, "hevcf"),
+ CLK_MSR_ID(76, "arm_ring_osc_out_7"),
+ CLK_MSR_ID(77, "rng_ring_osc_0"),
+ CLK_MSR_ID(78, "rng_ring_osc_1"),
+ CLK_MSR_ID(79, "rng_ring_osc_2"),
+ CLK_MSR_ID(80, "rng_ring_osc_3"),
+ CLK_MSR_ID(81, "vapb"),
+ CLK_MSR_ID(82, "ge2d"),
+ CLK_MSR_ID(83, "co_rx"),
+ CLK_MSR_ID(84, "co_tx"),
+ CLK_MSR_ID(85, "arm_ring_osc_out_8"),
+ CLK_MSR_ID(86, "arm_ring_osc_out_9"),
+ CLK_MSR_ID(87, "mipi_dsi_phy"),
+ CLK_MSR_ID(88, "cis2_adapt"),
+ CLK_MSR_ID(89, "hdmi_todig"),
+ CLK_MSR_ID(90, "hdmitx_sys"),
+ CLK_MSR_ID(91, "nna_core"),
+ CLK_MSR_ID(92, "nna_axi"),
+ CLK_MSR_ID(93, "vad"),
+ CLK_MSR_ID(94, "eth_phy_rx"),
+ CLK_MSR_ID(95, "eth_phy_pll"),
+ CLK_MSR_ID(96, "vpu_b"),
+ CLK_MSR_ID(97, "cpu_b_tmp"),
+ CLK_MSR_ID(98, "ts"),
+ CLK_MSR_ID(99, "arm_ring_osc_out_10"),
+ CLK_MSR_ID(100, "arm_ring_osc_out_11"),
+ CLK_MSR_ID(101, "arm_ring_osc_out_12"),
+ CLK_MSR_ID(102, "arm_ring_osc_out_13"),
+ CLK_MSR_ID(103, "arm_ring_osc_out_14"),
+ CLK_MSR_ID(104, "arm_ring_osc_out_15"),
+ CLK_MSR_ID(105, "arm_ring_osc_out_16"),
+ CLK_MSR_ID(106, "ephy_test"),
+ CLK_MSR_ID(107, "au_dac_g128x"),
+ CLK_MSR_ID(108, "audio_locker_out"),
+ CLK_MSR_ID(109, "audio_locker_in"),
+ CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
+ CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
+ CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
+ CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
+ CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
+ CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
+ CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
+ CLK_MSR_ID(117, "audio_resample"),
+ CLK_MSR_ID(118, "audio_pdm_sys"),
+ CLK_MSR_ID(119, "audio_spdifout_b"),
+ CLK_MSR_ID(120, "audio_spdifout"),
+ CLK_MSR_ID(121, "audio_spdifin"),
+ CLK_MSR_ID(122, "audio_pdm_dclk"),
+ CLK_MSR_ID(123, "audio_resampled"),
+ CLK_MSR_ID(124, "earcrx_pll"),
+ CLK_MSR_ID(125, "earcrx_pll_test"),
+ CLK_MSR_ID(126, "csi_phy0"),
+ CLK_MSR_ID(127, "csi2_data"),
+};
+
static int meson_measure_id(struct meson_msr_id *clk_msr_id,
unsigned int duration)
{
@@ -360,6 +494,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
unsigned int val;
int ret;
+ ret = mutex_lock_interruptible(&measure_lock);
+ if (ret)
+ return ret;
+
regmap_write(priv->regmap, MSR_CLK_REG0, 0);
/* Set measurement duration */
@@ -377,8 +515,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
val, !(val & MSR_BUSY), 10, 10000);
- if (ret)
+ if (ret) {
+ mutex_unlock(&measure_lock);
return ret;
+ }
/* Disable */
regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
@@ -386,6 +526,8 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
/* Get the value in multiple of gate time counts */
regmap_read(priv->regmap, MSR_CLK_REG2, &val);
+ mutex_unlock(&measure_lock);
+
if (val >= MSR_VAL_MASK)
return -EINVAL;
@@ -533,6 +675,10 @@ static const struct of_device_id meson_msr_match_table[] = {
.compatible = "amlogic,meson-g12a-clk-measure",
.data = (void *)clk_msr_g12a,
},
+ {
+ .compatible = "amlogic,meson-sm1-clk-measure",
+ .data = (void *)clk_msr_sm1,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c
new file mode 100644
index 000000000000..5823f5b67d16
--- /dev/null
+++ b/drivers/soc/amlogic/meson-ee-pwrc.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/reset-controller.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <dt-bindings/power/meson-g12a-power.h>
+#include <dt-bindings/power/meson-sm1-power.h>
+
+/* AO Offsets */
+
+#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2)
+#define AO_RTI_GEN_PWR_ISO0 (0x3b << 2)
+
+/* HHI Offsets */
+
+#define HHI_MEM_PD_REG0 (0x40 << 2)
+#define HHI_VPU_MEM_PD_REG0 (0x41 << 2)
+#define HHI_VPU_MEM_PD_REG1 (0x42 << 2)
+#define HHI_VPU_MEM_PD_REG3 (0x43 << 2)
+#define HHI_VPU_MEM_PD_REG4 (0x44 << 2)
+#define HHI_AUDIO_MEM_PD_REG0 (0x45 << 2)
+#define HHI_NANOQ_MEM_PD_REG0 (0x46 << 2)
+#define HHI_NANOQ_MEM_PD_REG1 (0x47 << 2)
+#define HHI_VPU_MEM_PD_REG2 (0x4d << 2)
+
+struct meson_ee_pwrc;
+struct meson_ee_pwrc_domain;
+
+struct meson_ee_pwrc_mem_domain {
+ unsigned int reg;
+ unsigned int mask;
+};
+
+struct meson_ee_pwrc_top_domain {
+ unsigned int sleep_reg;
+ unsigned int sleep_mask;
+ unsigned int iso_reg;
+ unsigned int iso_mask;
+};
+
+struct meson_ee_pwrc_domain_desc {
+ char *name;
+ unsigned int reset_names_count;
+ unsigned int clk_names_count;
+ struct meson_ee_pwrc_top_domain *top_pd;
+ unsigned int mem_pd_count;
+ struct meson_ee_pwrc_mem_domain *mem_pd;
+ bool (*get_power)(struct meson_ee_pwrc_domain *pwrc_domain);
+};
+
+struct meson_ee_pwrc_domain_data {
+ unsigned int count;
+ struct meson_ee_pwrc_domain_desc *domains;
+};
+
+/* TOP Power Domains */
+
+static struct meson_ee_pwrc_top_domain g12a_pwrc_vpu = {
+ .sleep_reg = AO_RTI_GEN_PWR_SLEEP0,
+ .sleep_mask = BIT(8),
+ .iso_reg = AO_RTI_GEN_PWR_SLEEP0,
+ .iso_mask = BIT(9),
+};
+
+#define SM1_EE_PD(__bit) \
+ { \
+ .sleep_reg = AO_RTI_GEN_PWR_SLEEP0, \
+ .sleep_mask = BIT(__bit), \
+ .iso_reg = AO_RTI_GEN_PWR_ISO0, \
+ .iso_mask = BIT(__bit), \
+ }
+
+static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
+
+/* Memory PD Domains */
+
+#define VPU_MEMPD(__reg) \
+ { __reg, GENMASK(1, 0) }, \
+ { __reg, GENMASK(3, 2) }, \
+ { __reg, GENMASK(5, 4) }, \
+ { __reg, GENMASK(7, 6) }, \
+ { __reg, GENMASK(9, 8) }, \
+ { __reg, GENMASK(11, 10) }, \
+ { __reg, GENMASK(13, 12) }, \
+ { __reg, GENMASK(15, 14) }, \
+ { __reg, GENMASK(17, 16) }, \
+ { __reg, GENMASK(19, 18) }, \
+ { __reg, GENMASK(21, 20) }, \
+ { __reg, GENMASK(23, 22) }, \
+ { __reg, GENMASK(25, 24) }, \
+ { __reg, GENMASK(27, 26) }, \
+ { __reg, GENMASK(29, 28) }, \
+ { __reg, GENMASK(31, 30) }
+
+#define VPU_HHI_MEMPD(__reg) \
+ { __reg, BIT(8) }, \
+ { __reg, BIT(9) }, \
+ { __reg, BIT(10) }, \
+ { __reg, BIT(11) }, \
+ { __reg, BIT(12) }, \
+ { __reg, BIT(13) }, \
+ { __reg, BIT(14) }, \
+ { __reg, BIT(15) }
+
+static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
+ VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_eth[] = {
+ { HHI_MEM_PD_REG0, GENMASK(3, 2) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
+ { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
+ { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
+ { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
+ { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
+ VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
+ { HHI_NANOQ_MEM_PD_REG0, 0xff },
+ { HHI_NANOQ_MEM_PD_REG1, 0xff },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
+ { HHI_MEM_PD_REG0, GENMASK(31, 30) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
+ { HHI_MEM_PD_REG0, GENMASK(29, 26) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
+ { HHI_MEM_PD_REG0, GENMASK(25, 18) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
+ { HHI_MEM_PD_REG0, GENMASK(5, 4) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
+ { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
+};
+
+#define VPU_PD(__name, __top_pd, __mem, __get_power, __resets, __clks) \
+ { \
+ .name = __name, \
+ .reset_names_count = __resets, \
+ .clk_names_count = __clks, \
+ .top_pd = __top_pd, \
+ .mem_pd_count = ARRAY_SIZE(__mem), \
+ .mem_pd = __mem, \
+ .get_power = __get_power, \
+ }
+
+#define TOP_PD(__name, __top_pd, __mem, __get_power) \
+ { \
+ .name = __name, \
+ .top_pd = __top_pd, \
+ .mem_pd_count = ARRAY_SIZE(__mem), \
+ .mem_pd = __mem, \
+ .get_power = __get_power, \
+ }
+
+#define MEM_PD(__name, __mem) \
+ TOP_PD(__name, NULL, __mem, NULL)
+
+static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain);
+
+static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
+ [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu,
+ pwrc_ee_get_power, 11, 2),
+ [PWRC_G12A_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
+};
+
+static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
+ [PWRC_SM1_VPU_ID] = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
+ pwrc_ee_get_power, 11, 2),
+ [PWRC_SM1_NNA_ID] = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
+ pwrc_ee_get_power),
+ [PWRC_SM1_USB_ID] = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
+ pwrc_ee_get_power),
+ [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
+ pwrc_ee_get_power),
+ [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
+ pwrc_ee_get_power),
+ [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
+ [PWRC_SM1_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
+};
+
+struct meson_ee_pwrc_domain {
+ struct generic_pm_domain base;
+ bool enabled;
+ struct meson_ee_pwrc *pwrc;
+ struct meson_ee_pwrc_domain_desc desc;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct reset_control *rstc;
+ int num_rstc;
+};
+
+struct meson_ee_pwrc {
+ struct regmap *regmap_ao;
+ struct regmap *regmap_hhi;
+ struct meson_ee_pwrc_domain *domains;
+ struct genpd_onecell_data xlate;
+};
+
+static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain)
+{
+ u32 reg;
+
+ regmap_read(pwrc_domain->pwrc->regmap_ao,
+ pwrc_domain->desc.top_pd->sleep_reg, &reg);
+
+ return (reg & pwrc_domain->desc.top_pd->sleep_mask);
+}
+
+static int meson_ee_pwrc_off(struct generic_pm_domain *domain)
+{
+ struct meson_ee_pwrc_domain *pwrc_domain =
+ container_of(domain, struct meson_ee_pwrc_domain, base);
+ int i;
+
+ if (pwrc_domain->desc.top_pd)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+ pwrc_domain->desc.top_pd->sleep_reg,
+ pwrc_domain->desc.top_pd->sleep_mask,
+ pwrc_domain->desc.top_pd->sleep_mask);
+ udelay(20);
+
+ for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
+ pwrc_domain->desc.mem_pd[i].reg,
+ pwrc_domain->desc.mem_pd[i].mask,
+ pwrc_domain->desc.mem_pd[i].mask);
+
+ udelay(20);
+
+ if (pwrc_domain->desc.top_pd)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+ pwrc_domain->desc.top_pd->iso_reg,
+ pwrc_domain->desc.top_pd->iso_mask,
+ pwrc_domain->desc.top_pd->iso_mask);
+
+ if (pwrc_domain->num_clks) {
+ msleep(20);
+ clk_bulk_disable_unprepare(pwrc_domain->num_clks,
+ pwrc_domain->clks);
+ }
+
+ return 0;
+}
+
+static int meson_ee_pwrc_on(struct generic_pm_domain *domain)
+{
+ struct meson_ee_pwrc_domain *pwrc_domain =
+ container_of(domain, struct meson_ee_pwrc_domain, base);
+ int i, ret;
+
+ if (pwrc_domain->desc.top_pd)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+ pwrc_domain->desc.top_pd->sleep_reg,
+ pwrc_domain->desc.top_pd->sleep_mask, 0);
+ udelay(20);
+
+ for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
+ pwrc_domain->desc.mem_pd[i].reg,
+ pwrc_domain->desc.mem_pd[i].mask, 0);
+
+ udelay(20);
+
+ ret = reset_control_assert(pwrc_domain->rstc);
+ if (ret)
+ return ret;
+
+ if (pwrc_domain->desc.top_pd)
+ regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+ pwrc_domain->desc.top_pd->iso_reg,
+ pwrc_domain->desc.top_pd->iso_mask, 0);
+
+ ret = reset_control_deassert(pwrc_domain->rstc);
+ if (ret)
+ return ret;
+
+ return clk_bulk_prepare_enable(pwrc_domain->num_clks,
+ pwrc_domain->clks);
+}
+
+static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
+ struct meson_ee_pwrc *pwrc,
+ struct meson_ee_pwrc_domain *dom)
+{
+ dom->pwrc = pwrc;
+ dom->num_rstc = dom->desc.reset_names_count;
+ dom->num_clks = dom->desc.clk_names_count;
+
+ if (dom->num_rstc) {
+ int count = reset_control_get_count(&pdev->dev);
+
+ if (count != dom->num_rstc)
+ dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n",
+ count, dom->desc.name);
+
+ dom->rstc = devm_reset_control_array_get(&pdev->dev, false,
+ false);
+ if (IS_ERR(dom->rstc))
+ return PTR_ERR(dom->rstc);
+ }
+
+ if (dom->num_clks) {
+ int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks);
+ if (ret < 0)
+ return ret;
+
+ if (dom->num_clks != ret) {
+ dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n",
+ ret, dom->desc.name);
+ dom->num_clks = ret;
+ }
+ }
+
+ dom->base.name = dom->desc.name;
+ dom->base.power_on = meson_ee_pwrc_on;
+ dom->base.power_off = meson_ee_pwrc_off;
+
+ /*
+ * TOFIX: This is a special case for the VPU power domain, which can
+ * be enabled previously by the bootloader. In this case the VPU
+ * pipeline may be functional but no driver maybe never attach
+ * to this power domain, and if the domain is disabled it could
+ * cause system errors. This is why the pm_domain_always_on_gov
+ * is used here.
+ * For the same reason, the clocks should be enabled in case
+ * we need to power the domain off, otherwise the internal clocks
+ * prepare/enable counters won't be in sync.
+ */
+ if (dom->num_clks && dom->desc.get_power && !dom->desc.get_power(dom)) {
+ int ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
+ if (ret)
+ return ret;
+
+ pm_genpd_init(&dom->base, &pm_domain_always_on_gov, false);
+ } else
+ pm_genpd_init(&dom->base, NULL,
+ (dom->desc.get_power ?
+ dom->desc.get_power(dom) : true));
+
+ return 0;
+}
+
+static int meson_ee_pwrc_probe(struct platform_device *pdev)
+{
+ const struct meson_ee_pwrc_domain_data *match;
+ struct regmap *regmap_ao, *regmap_hhi;
+ struct meson_ee_pwrc *pwrc;
+ int i, ret;
+
+ match = of_device_get_match_data(&pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "failed to get match data\n");
+ return -ENODEV;
+ }
+
+ pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
+ if (!pwrc)
+ return -ENOMEM;
+
+ pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
+ sizeof(*pwrc->xlate.domains),
+ GFP_KERNEL);
+ if (!pwrc->xlate.domains)
+ return -ENOMEM;
+
+ pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
+ sizeof(*pwrc->domains), GFP_KERNEL);
+ if (!pwrc->domains)
+ return -ENOMEM;
+
+ pwrc->xlate.num_domains = match->count;
+
+ regmap_hhi = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
+ if (IS_ERR(regmap_hhi)) {
+ dev_err(&pdev->dev, "failed to get HHI regmap\n");
+ return PTR_ERR(regmap_hhi);
+ }
+
+ regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "amlogic,ao-sysctrl");
+ if (IS_ERR(regmap_ao)) {
+ dev_err(&pdev->dev, "failed to get AO regmap\n");
+ return PTR_ERR(regmap_ao);
+ }
+
+ pwrc->regmap_ao = regmap_ao;
+ pwrc->regmap_hhi = regmap_hhi;
+
+ platform_set_drvdata(pdev, pwrc);
+
+ for (i = 0 ; i < match->count ; ++i) {
+ struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
+
+ memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc));
+
+ ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom);
+ if (ret)
+ return ret;
+
+ pwrc->xlate.domains[i] = &dom->base;
+ }
+
+ of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
+
+ return 0;
+}
+
+static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
+{
+ struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
+ struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
+
+ if (dom->desc.get_power && !dom->desc.get_power(dom))
+ meson_ee_pwrc_off(&dom->base);
+ }
+}
+
+static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
+ .count = ARRAY_SIZE(g12a_pwrc_domains),
+ .domains = g12a_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
+ .count = ARRAY_SIZE(sm1_pwrc_domains),
+ .domains = sm1_pwrc_domains,
+};
+
+static const struct of_device_id meson_ee_pwrc_match_table[] = {
+ {
+ .compatible = "amlogic,meson-g12a-pwrc",
+ .data = &meson_ee_g12a_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,meson-sm1-pwrc",
+ .data = &meson_ee_sm1_pwrc_data,
+ },
+ { /* sentinel */ }
+};
+
+static struct platform_driver meson_ee_pwrc_driver = {
+ .probe = meson_ee_pwrc_probe,
+ .shutdown = meson_ee_pwrc_shutdown,
+ .driver = {
+ .name = "meson_ee_pwrc",
+ .of_match_table = meson_ee_pwrc_match_table,
+ },
+};
+builtin_platform_driver(meson_ee_pwrc_driver);
diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index bca34954518e..6d0d04f163cb 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -39,6 +39,7 @@ static const struct meson_gx_soc_id {
{ "TXHD", 0x27 },
{ "G12A", 0x28 },
{ "G12B", 0x29 },
+ { "SM1", 0x2b },
};
static const struct meson_gx_package_id {
@@ -65,6 +66,8 @@ static const struct meson_gx_package_id {
{ "S905D2", 0x28, 0x10, 0xf0 },
{ "S905X2", 0x28, 0x40, 0xf0 },
{ "S922X", 0x29, 0x40, 0xf0 },
+ { "A311D", 0x29, 0x10, 0xf0 },
+ { "S905X3", 0x2b, 0x5, 0xf },
};
static inline unsigned int socinfo_to_major(u32 socinfo)
@@ -138,8 +141,10 @@ static int __init meson_gx_socinfo_init(void)
}
/* check if chip-id is available */
- if (!of_property_read_bool(np, "amlogic,has-chip-id"))
+ if (!of_property_read_bool(np, "amlogic,has-chip-id")) {
+ of_node_put(np);
return -ENODEV;
+ }
/* node should be a syscon */
regmap = syscon_node_to_regmap(np);
diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c
index 9168d8ddc932..27243f706f37 100644
--- a/drivers/soc/fsl/dpaa2-console.c
+++ b/drivers/soc/fsl/dpaa2-console.c
@@ -73,7 +73,7 @@ static u64 get_mc_fw_base_address(void)
mcfbaregs = ioremap(mc_base_addr.start, resource_size(&mc_base_addr));
if (!mcfbaregs) {
- pr_err("could not map MC Firmaware Base registers\n");
+ pr_err("could not map MC Firmware Base registers\n");
return 0;
}
diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index b9539ef2c3cd..518a8e081b49 100644
--- a/drivers/soc/fsl/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -305,8 +305,6 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
list_del(&ctx->node);
spin_unlock_irqrestore(&d->lock_notifications, irqflags);
- if (dev)
- device_link_remove(dev, d->dev);
}
EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 1ef8068c8dd3..34810f9bb2ee 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -102,6 +102,11 @@ static const struct fsl_soc_die_attr fsl_soc_die[] = {
.svr = 0x87360000,
.mask = 0xff3f0000,
},
+ /* Die: LS1028A, SoC: LS1028A */
+ { .die = "LS1028A",
+ .svr = 0x870b0000,
+ .mask = 0xff3f0000,
+ },
{ },
};
@@ -224,6 +229,7 @@ static const struct of_device_id fsl_guts_of_match[] = {
{ .compatible = "fsl,ls1012a-dcfg", },
{ .compatible = "fsl,ls1046a-dcfg", },
{ .compatible = "fsl,lx2160a-dcfg", },
+ { .compatible = "fsl,ls1028a-dcfg", },
{}
};
MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
diff --git a/drivers/soc/fsl/qbman/bman.c b/drivers/soc/fsl/qbman/bman.c
index f84ab596bde8..f4fb527d8301 100644
--- a/drivers/soc/fsl/qbman/bman.c
+++ b/drivers/soc/fsl/qbman/bman.c
@@ -635,30 +635,31 @@ int bman_p_irqsource_add(struct bman_portal *p, u32 bits)
return 0;
}
-static int bm_shutdown_pool(u32 bpid)
+int bm_shutdown_pool(u32 bpid)
{
+ int err = 0;
struct bm_mc_command *bm_cmd;
union bm_mc_result *bm_res;
+
+ struct bman_portal *p = get_affine_portal();
while (1) {
- struct bman_portal *p = get_affine_portal();
/* Acquire buffers until empty */
bm_cmd = bm_mc_start(&p->p);
bm_cmd->bpid = bpid;
bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1);
if (!bm_mc_result_timeout(&p->p, &bm_res)) {
- put_affine_portal();
pr_crit("BMan Acquire Command timedout\n");
- return -ETIMEDOUT;
+ err = -ETIMEDOUT;
+ goto done;
}
if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) {
- put_affine_portal();
/* Pool is empty */
- return 0;
+ goto done;
}
- put_affine_portal();
}
-
+done:
+ put_affine_portal();
return 0;
}
diff --git a/drivers/soc/fsl/qbman/bman_ccsr.c b/drivers/soc/fsl/qbman/bman_ccsr.c
index 7c3cc968053c..cb24a08be084 100644
--- a/drivers/soc/fsl/qbman/bman_ccsr.c
+++ b/drivers/soc/fsl/qbman/bman_ccsr.c
@@ -97,17 +97,40 @@ static void bm_get_version(u16 *id, u8 *major, u8 *minor)
/* signal transactions for FBPRs with higher priority */
#define FBPR_AR_RPRIO_HI BIT(30)
-static void bm_set_memory(u64 ba, u32 size)
+/* Track if probe has occurred and if cleanup is required */
+static int __bman_probed;
+static int __bman_requires_cleanup;
+
+
+static int bm_set_memory(u64 ba, u32 size)
{
+ u32 bar, bare;
u32 exp = ilog2(size);
/* choke if size isn't within range */
DPAA_ASSERT(size >= 4096 && size <= 1024*1024*1024 &&
is_power_of_2(size));
/* choke if '[e]ba' has lower-alignment than 'size' */
DPAA_ASSERT(!(ba & (size - 1)));
+
+ /* Check to see if BMan has already been initialized */
+ bar = bm_ccsr_in(REG_FBPR_BAR);
+ if (bar) {
+ /* Maker sure ba == what was programmed) */
+ bare = bm_ccsr_in(REG_FBPR_BARE);
+ if (bare != upper_32_bits(ba) || bar != lower_32_bits(ba)) {
+ pr_err("Attempted to reinitialize BMan with different BAR, got 0x%llx read BARE=0x%x BAR=0x%x\n",
+ ba, bare, bar);
+ return -ENOMEM;
+ }
+ pr_info("BMan BAR already configured\n");
+ __bman_requires_cleanup = 1;
+ return 1;
+ }
+
bm_ccsr_out(REG_FBPR_BARE, upper_32_bits(ba));
bm_ccsr_out(REG_FBPR_BAR, lower_32_bits(ba));
bm_ccsr_out(REG_FBPR_AR, exp - 1);
+ return 0;
}
/*
@@ -120,7 +143,6 @@ static void bm_set_memory(u64 ba, u32 size)
*/
static dma_addr_t fbpr_a;
static size_t fbpr_sz;
-static int __bman_probed;
static int bman_fbpr(struct reserved_mem *rmem)
{
@@ -173,6 +195,16 @@ int bman_is_probed(void)
}
EXPORT_SYMBOL_GPL(bman_is_probed);
+int bman_requires_cleanup(void)
+{
+ return __bman_requires_cleanup;
+}
+
+void bman_done_cleanup(void)
+{
+ __bman_requires_cleanup = 0;
+}
+
static int fsl_bman_probe(struct platform_device *pdev)
{
int ret, err_irq;
diff --git a/drivers/soc/fsl/qbman/bman_portal.c b/drivers/soc/fsl/qbman/bman_portal.c
index cf4f10d6f590..923c44063a9a 100644
--- a/drivers/soc/fsl/qbman/bman_portal.c
+++ b/drivers/soc/fsl/qbman/bman_portal.c
@@ -100,7 +100,7 @@ static int bman_portal_probe(struct platform_device *pdev)
struct device_node *node = dev->of_node;
struct bm_portal_config *pcfg;
struct resource *addr_phys[2];
- int irq, cpu, err;
+ int irq, cpu, err, i;
err = bman_is_probed();
if (!err)
@@ -135,10 +135,8 @@ static int bman_portal_probe(struct platform_device *pdev)
pcfg->cpu = -1;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(dev, "Can't get %pOF IRQ'\n", node);
+ if (irq <= 0)
goto err_ioremap1;
- }
pcfg->irq = irq;
pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
@@ -178,6 +176,22 @@ static int bman_portal_probe(struct platform_device *pdev)
if (!cpu_online(cpu))
bman_offline_cpu(cpu);
+ if (__bman_portals_probed == 1 && bman_requires_cleanup()) {
+ /*
+ * BMan wasn't reset prior to boot (Kexec for example)
+ * Empty all the buffer pools so they are in reset state
+ */
+ for (i = 0; i < BM_POOL_MAX; i++) {
+ err = bm_shutdown_pool(i);
+ if (err) {
+ dev_err(dev, "Failed to shutdown bpool %d\n",
+ i);
+ goto err_portal_init;
+ }
+ }
+ bman_done_cleanup();
+ }
+
return 0;
err_portal_init:
diff --git a/drivers/soc/fsl/qbman/bman_priv.h b/drivers/soc/fsl/qbman/bman_priv.h
index 751ce90383b7..aa3981e04965 100644
--- a/drivers/soc/fsl/qbman/bman_priv.h
+++ b/drivers/soc/fsl/qbman/bman_priv.h
@@ -76,3 +76,8 @@ int bman_p_irqsource_add(struct bman_portal *p, u32 bits);
const struct bm_portal_config *
bman_get_bm_portal_config(const struct bman_portal *portal);
+
+int bman_requires_cleanup(void);
+void bman_done_cleanup(void);
+
+int bm_shutdown_pool(u32 bpid);
diff --git a/drivers/soc/fsl/qbman/dpaa_sys.c b/drivers/soc/fsl/qbman/dpaa_sys.c
index e6d48dccb8d5..9dd8bb571dbc 100644
--- a/drivers/soc/fsl/qbman/dpaa_sys.c
+++ b/drivers/soc/fsl/qbman/dpaa_sys.c
@@ -37,42 +37,53 @@
int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
size_t *size)
{
- int ret;
struct device_node *mem_node;
- u64 size64;
+ struct reserved_mem *rmem;
+ struct property *prop;
+ int len, err;
+ __be32 *res_array;
- ret = of_reserved_mem_device_init_by_idx(dev, dev->of_node, idx);
- if (ret) {
- dev_err(dev,
- "of_reserved_mem_device_init_by_idx(%d) failed 0x%x\n",
- idx, ret);
- return -ENODEV;
- }
- mem_node = of_parse_phandle(dev->of_node, "memory-region", 0);
- if (mem_node) {
- ret = of_property_read_u64(mem_node, "size", &size64);
- if (ret) {
- dev_err(dev, "of_address_to_resource fails 0x%x\n",
- ret);
- return -ENODEV;
- }
- *size = size64;
- } else {
+ mem_node = of_parse_phandle(dev->of_node, "memory-region", idx);
+ if (!mem_node) {
dev_err(dev, "No memory-region found for index %d\n", idx);
return -ENODEV;
}
- if (!dma_alloc_coherent(dev, *size, addr, 0)) {
- dev_err(dev, "DMA Alloc memory failed\n");
+ rmem = of_reserved_mem_lookup(mem_node);
+ if (!rmem) {
+ dev_err(dev, "of_reserved_mem_lookup() returned NULL\n");
return -ENODEV;
}
+ *addr = rmem->base;
+ *size = rmem->size;
/*
- * Disassociate the reserved memory area from the device
- * because a device can only have one DMA memory area. This
- * should be fine since the memory is allocated and initialized
- * and only ever accessed by the QBMan device from now on
+ * Check if the reg property exists - if not insert the node
+ * so upon kexec() the same memory region address will be preserved.
+ * This is needed because QBMan HW does not allow the base address/
+ * size to be modified once set.
*/
- of_reserved_mem_device_release(dev);
+ prop = of_find_property(mem_node, "reg", &len);
+ if (!prop) {
+ prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+ prop->value = res_array = devm_kzalloc(dev, sizeof(__be32) * 4,
+ GFP_KERNEL);
+ if (!prop->value)
+ return -ENOMEM;
+ res_array[0] = cpu_to_be32(upper_32_bits(*addr));
+ res_array[1] = cpu_to_be32(lower_32_bits(*addr));
+ res_array[2] = cpu_to_be32(upper_32_bits(*size));
+ res_array[3] = cpu_to_be32(lower_32_bits(*size));
+ prop->length = sizeof(__be32) * 4;
+ prop->name = devm_kstrdup(dev, "reg", GFP_KERNEL);
+ if (!prop->name)
+ return -ENOMEM;
+ err = of_add_property(mem_node, prop);
+ if (err)
+ return err;
+ }
+
return 0;
}
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index 636f83f781f5..bf68d86d80ee 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -1018,6 +1018,20 @@ static inline void put_affine_portal(void)
put_cpu_var(qman_affine_portal);
}
+
+static inline struct qman_portal *get_portal_for_channel(u16 channel)
+{
+ int i;
+
+ for (i = 0; i < num_possible_cpus(); i++) {
+ if (affine_portals[i] &&
+ affine_portals[i]->config->channel == channel)
+ return affine_portals[i];
+ }
+
+ return NULL;
+}
+
static struct workqueue_struct *qm_portal_wq;
int qman_dqrr_set_ithresh(struct qman_portal *portal, u8 ithresh)
@@ -1070,6 +1084,20 @@ int qman_wq_alloc(void)
return 0;
}
+
+void qman_enable_irqs(void)
+{
+ int i;
+
+ for (i = 0; i < num_possible_cpus(); i++) {
+ if (affine_portals[i]) {
+ qm_out(&affine_portals[i]->p, QM_REG_ISR, 0xffffffff);
+ qm_out(&affine_portals[i]->p, QM_REG_IIR, 0);
+ }
+
+ }
+}
+
/*
* This is what everything can wait on, even if it migrates to a different cpu
* to the one whose affine portal it is waiting on.
@@ -1164,6 +1192,7 @@ static int drain_mr_fqrni(struct qm_portal *p)
{
const union qm_mr_entry *msg;
loop:
+ qm_mr_pvb_update(p);
msg = qm_mr_current(p);
if (!msg) {
/*
@@ -1180,7 +1209,8 @@ loop:
* entries well before the ring has been fully consumed, so
* we're being *really* paranoid here.
*/
- msleep(1);
+ mdelay(1);
+ qm_mr_pvb_update(p);
msg = qm_mr_current(p);
if (!msg)
return 0;
@@ -1267,8 +1297,8 @@ static int qman_create_portal(struct qman_portal *portal,
qm_out(p, QM_REG_ISDR, isdr);
portal->irq_sources = 0;
qm_out(p, QM_REG_IER, 0);
- qm_out(p, QM_REG_ISR, 0xffffffff);
snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu);
+ qm_out(p, QM_REG_IIR, 1);
if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) {
dev_err(c->dev, "request_irq() failed\n");
goto fail_irq;
@@ -1288,7 +1318,7 @@ static int qman_create_portal(struct qman_portal *portal,
isdr &= ~(QM_PIRQ_DQRI | QM_PIRQ_MRI);
qm_out(p, QM_REG_ISDR, isdr);
if (qm_dqrr_current(p)) {
- dev_err(c->dev, "DQRR unclean\n");
+ dev_dbg(c->dev, "DQRR unclean\n");
qm_dqrr_cdc_consume_n(p, 0xffff);
}
if (qm_mr_current(p) && drain_mr_fqrni(p)) {
@@ -1301,8 +1331,10 @@ static int qman_create_portal(struct qman_portal *portal,
}
/* Success */
portal->config = c;
+ qm_out(p, QM_REG_ISR, 0xffffffff);
qm_out(p, QM_REG_ISDR, 0);
- qm_out(p, QM_REG_IIR, 0);
+ if (!qman_requires_cleanup())
+ qm_out(p, QM_REG_IIR, 0);
/* Write a sane SDQCR */
qm_dqrr_sdqcr_set(p, portal->sdqcr);
return 0;
@@ -2581,9 +2613,9 @@ static int _qm_dqrr_consume_and_match(struct qm_portal *p, u32 fqid, int s,
#define qm_dqrr_drain_nomatch(p) \
_qm_dqrr_consume_and_match(p, 0, 0, false)
-static int qman_shutdown_fq(u32 fqid)
+int qman_shutdown_fq(u32 fqid)
{
- struct qman_portal *p;
+ struct qman_portal *p, *channel_portal;
struct device *dev;
union qm_mc_command *mcc;
union qm_mc_result *mcr;
@@ -2623,17 +2655,28 @@ static int qman_shutdown_fq(u32 fqid)
channel = qm_fqd_get_chan(&mcr->queryfq.fqd);
wq = qm_fqd_get_wq(&mcr->queryfq.fqd);
+ if (channel < qm_channel_pool1) {
+ channel_portal = get_portal_for_channel(channel);
+ if (channel_portal == NULL) {
+ dev_err(dev, "Can't find portal for dedicated channel 0x%x\n",
+ channel);
+ ret = -EIO;
+ goto out;
+ }
+ } else
+ channel_portal = p;
+
switch (state) {
case QM_MCR_NP_STATE_TEN_SCHED:
case QM_MCR_NP_STATE_TRU_SCHED:
case QM_MCR_NP_STATE_ACTIVE:
case QM_MCR_NP_STATE_PARKED:
orl_empty = 0;
- mcc = qm_mc_start(&p->p);
+ mcc = qm_mc_start(&channel_portal->p);
qm_fqid_set(&mcc->fq, fqid);
- qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE);
- if (!qm_mc_result_timeout(&p->p, &mcr)) {
- dev_err(dev, "QUERYFQ_NP timeout\n");
+ qm_mc_commit(&channel_portal->p, QM_MCC_VERB_ALTER_RETIRE);
+ if (!qm_mc_result_timeout(&channel_portal->p, &mcr)) {
+ dev_err(dev, "ALTER_RETIRE timeout\n");
ret = -ETIMEDOUT;
goto out;
}
@@ -2641,6 +2684,9 @@ static int qman_shutdown_fq(u32 fqid)
QM_MCR_VERB_ALTER_RETIRE);
res = mcr->result; /* Make a copy as we reuse MCR below */
+ if (res == QM_MCR_RESULT_OK)
+ drain_mr_fqrni(&channel_portal->p);
+
if (res == QM_MCR_RESULT_PENDING) {
/*
* Need to wait for the FQRN in the message ring, which
@@ -2670,21 +2716,25 @@ static int qman_shutdown_fq(u32 fqid)
}
/* Set the sdqcr to drain this channel */
if (channel < qm_channel_pool1)
- qm_dqrr_sdqcr_set(&p->p,
+ qm_dqrr_sdqcr_set(&channel_portal->p,
QM_SDQCR_TYPE_ACTIVE |
QM_SDQCR_CHANNELS_DEDICATED);
else
- qm_dqrr_sdqcr_set(&p->p,
+ qm_dqrr_sdqcr_set(&channel_portal->p,
QM_SDQCR_TYPE_ACTIVE |
QM_SDQCR_CHANNELS_POOL_CONV
(channel));
do {
/* Keep draining DQRR while checking the MR*/
- qm_dqrr_drain_nomatch(&p->p);
+ qm_dqrr_drain_nomatch(&channel_portal->p);
/* Process message ring too */
- found_fqrn = qm_mr_drain(&p->p, FQRN);
+ found_fqrn = qm_mr_drain(&channel_portal->p,
+ FQRN);
cpu_relax();
} while (!found_fqrn);
+ /* Restore SDQCR */
+ qm_dqrr_sdqcr_set(&channel_portal->p,
+ channel_portal->sdqcr);
}
if (res != QM_MCR_RESULT_OK &&
@@ -2715,9 +2765,8 @@ static int qman_shutdown_fq(u32 fqid)
* Wait for a dequeue and process the dequeues,
* making sure to empty the ring completely
*/
- } while (qm_dqrr_drain_wait(&p->p, fqid, FQ_EMPTY));
+ } while (!qm_dqrr_drain_wait(&p->p, fqid, FQ_EMPTY));
}
- qm_dqrr_sdqcr_set(&p->p, 0);
while (!orl_empty) {
/* Wait for the ORL to have been completely drained */
@@ -2754,7 +2803,7 @@ static int qman_shutdown_fq(u32 fqid)
DPAA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
QM_MCR_VERB_ALTER_OOS);
- if (mcr->result) {
+ if (mcr->result != QM_MCR_RESULT_OK) {
dev_err(dev, "OOS fail: FQ 0x%x (0x%x)\n",
fqid, mcr->result);
ret = -EIO;
diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c b/drivers/soc/fsl/qbman/qman_ccsr.c
index a6bb43007d03..157659fd033a 100644
--- a/drivers/soc/fsl/qbman/qman_ccsr.c
+++ b/drivers/soc/fsl/qbman/qman_ccsr.c
@@ -274,6 +274,7 @@ static u32 __iomem *qm_ccsr_start;
/* A SDQCR mask comprising all the available/visible pool channels */
static u32 qm_pools_sdqcr;
static int __qman_probed;
+static int __qman_requires_cleanup;
static inline u32 qm_ccsr_in(u32 offset)
{
@@ -340,19 +341,55 @@ static void qm_get_version(u16 *id, u8 *major, u8 *minor)
}
#define PFDR_AR_EN BIT(31)
-static void qm_set_memory(enum qm_memory memory, u64 ba, u32 size)
+static int qm_set_memory(enum qm_memory memory, u64 ba, u32 size)
{
+ void *ptr;
u32 offset = (memory == qm_memory_fqd) ? REG_FQD_BARE : REG_PFDR_BARE;
u32 exp = ilog2(size);
+ u32 bar, bare;
/* choke if size isn't within range */
DPAA_ASSERT((size >= 4096) && (size <= 1024*1024*1024) &&
is_power_of_2(size));
/* choke if 'ba' has lower-alignment than 'size' */
DPAA_ASSERT(!(ba & (size - 1)));
+
+ /* Check to see if QMan has already been initialized */
+ bar = qm_ccsr_in(offset + REG_offset_BAR);
+ if (bar) {
+ /* Maker sure ba == what was programmed) */
+ bare = qm_ccsr_in(offset);
+ if (bare != upper_32_bits(ba) || bar != lower_32_bits(ba)) {
+ pr_err("Attempted to reinitialize QMan with different BAR, got 0x%llx read BARE=0x%x BAR=0x%x\n",
+ ba, bare, bar);
+ return -ENOMEM;
+ }
+ __qman_requires_cleanup = 1;
+ /* Return 1 to indicate memory was previously programmed */
+ return 1;
+ }
+ /* Need to temporarily map the area to make sure it is zeroed */
+ ptr = memremap(ba, size, MEMREMAP_WB);
+ if (!ptr) {
+ pr_crit("memremap() of QMan private memory failed\n");
+ return -ENOMEM;
+ }
+ memset(ptr, 0, size);
+
+#ifdef CONFIG_PPC
+ /*
+ * PPC doesn't appear to flush the cache on memunmap() but the
+ * cache must be flushed since QMan does non coherent accesses
+ * to this memory
+ */
+ flush_dcache_range((unsigned long) ptr, (unsigned long) ptr+size);
+#endif
+ memunmap(ptr);
+
qm_ccsr_out(offset, upper_32_bits(ba));
qm_ccsr_out(offset + REG_offset_BAR, lower_32_bits(ba));
qm_ccsr_out(offset + REG_offset_AR, PFDR_AR_EN | (exp - 1));
+ return 0;
}
static void qm_set_pfdr_threshold(u32 th, u8 k)
@@ -455,7 +492,7 @@ RESERVEDMEM_OF_DECLARE(qman_pfdr, "fsl,qman-pfdr", qman_pfdr);
#endif
-static unsigned int qm_get_fqid_maxcnt(void)
+unsigned int qm_get_fqid_maxcnt(void)
{
return fqd_sz / 64;
}
@@ -571,12 +608,19 @@ static int qman_init_ccsr(struct device *dev)
int i, err;
/* FQD memory */
- qm_set_memory(qm_memory_fqd, fqd_a, fqd_sz);
+ err = qm_set_memory(qm_memory_fqd, fqd_a, fqd_sz);
+ if (err < 0)
+ return err;
/* PFDR memory */
- qm_set_memory(qm_memory_pfdr, pfdr_a, pfdr_sz);
- err = qm_init_pfdr(dev, 8, pfdr_sz / 64 - 8);
- if (err)
+ err = qm_set_memory(qm_memory_pfdr, pfdr_a, pfdr_sz);
+ if (err < 0)
return err;
+ /* Only initialize PFDRs if the QMan was not initialized before */
+ if (err == 0) {
+ err = qm_init_pfdr(dev, 8, pfdr_sz / 64 - 8);
+ if (err)
+ return err;
+ }
/* thresholds */
qm_set_pfdr_threshold(512, 64);
qm_set_sfdr_threshold(128);
@@ -693,6 +737,18 @@ int qman_is_probed(void)
}
EXPORT_SYMBOL_GPL(qman_is_probed);
+int qman_requires_cleanup(void)
+{
+ return __qman_requires_cleanup;
+}
+
+void qman_done_cleanup(void)
+{
+ qman_enable_irqs();
+ __qman_requires_cleanup = 0;
+}
+
+
static int fsl_qman_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c
index e2186b681d87..5685b6706893 100644
--- a/drivers/soc/fsl/qbman/qman_portal.c
+++ b/drivers/soc/fsl/qbman/qman_portal.c
@@ -233,7 +233,7 @@ static int qman_portal_probe(struct platform_device *pdev)
struct device_node *node = dev->of_node;
struct qm_portal_config *pcfg;
struct resource *addr_phys[2];
- int irq, cpu, err;
+ int irq, cpu, err, i;
u32 val;
err = qman_is_probed();
@@ -275,10 +275,8 @@ static int qman_portal_probe(struct platform_device *pdev)
pcfg->channel = val;
pcfg->cpu = -1;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(dev, "Can't get %pOF IRQ\n", node);
+ if (irq <= 0)
goto err_ioremap1;
- }
pcfg->irq = irq;
pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
@@ -325,6 +323,22 @@ static int qman_portal_probe(struct platform_device *pdev)
if (!cpu_online(cpu))
qman_offline_cpu(cpu);
+ if (__qman_portals_probed == 1 && qman_requires_cleanup()) {
+ /*
+ * QMan wasn't reset prior to boot (Kexec for example)
+ * Empty all the frame queues so they are in reset state
+ */
+ for (i = 0; i < qm_get_fqid_maxcnt(); i++) {
+ err = qman_shutdown_fq(i);
+ if (err) {
+ dev_err(dev, "Failed to shutdown frame queue %d\n",
+ i);
+ goto err_portal_init;
+ }
+ }
+ qman_done_cleanup();
+ }
+
return 0;
err_portal_init:
diff --git a/drivers/soc/fsl/qbman/qman_priv.h b/drivers/soc/fsl/qbman/qman_priv.h
index 04515718cfd9..fd1cf543fb81 100644
--- a/drivers/soc/fsl/qbman/qman_priv.h
+++ b/drivers/soc/fsl/qbman/qman_priv.h
@@ -272,3 +272,11 @@ extern struct qman_portal *affine_portals[NR_CPUS];
extern struct qman_portal *qman_dma_portal;
const struct qm_portal_config *qman_get_qm_portal_config(
struct qman_portal *portal);
+
+unsigned int qm_get_fqid_maxcnt(void);
+
+int qman_shutdown_fq(u32 fqid);
+
+int qman_requires_cleanup(void);
+void qman_done_cleanup(void);
+void qman_enable_irqs(void);
diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c
index 62c6ba17991a..417df7e19281 100644
--- a/drivers/soc/fsl/qe/qe.c
+++ b/drivers/soc/fsl/qe/qe.c
@@ -10,6 +10,7 @@
* General Purpose functions for the global management of the
* QUICC Engine (QE).
*/
+#include <linux/bitmap.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -39,29 +40,32 @@ static DEFINE_SPINLOCK(qe_lock);
DEFINE_SPINLOCK(cmxgcr_lock);
EXPORT_SYMBOL(cmxgcr_lock);
-/* QE snum state */
-enum qe_snum_state {
- QE_SNUM_STATE_USED,
- QE_SNUM_STATE_FREE
-};
-
-/* QE snum */
-struct qe_snum {
- u8 num;
- enum qe_snum_state state;
-};
-
/* We allocate this here because it is used almost exclusively for
* the communication processor devices.
*/
struct qe_immap __iomem *qe_immr;
EXPORT_SYMBOL(qe_immr);
-static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
+static u8 snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
+static DECLARE_BITMAP(snum_state, QE_NUM_OF_SNUM);
static unsigned int qe_num_of_snum;
static phys_addr_t qebase = -1;
+static struct device_node *qe_get_device_node(void)
+{
+ struct device_node *qe;
+
+ /*
+ * Newer device trees have an "fsl,qe" compatible property for the QE
+ * node, but we still need to support older device trees.
+ */
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (qe)
+ return qe;
+ return of_find_node_by_type(NULL, "qe");
+}
+
static phys_addr_t get_qe_base(void)
{
struct device_node *qe;
@@ -71,12 +75,9 @@ static phys_addr_t get_qe_base(void)
if (qebase != -1)
return qebase;
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return qebase;
- }
+ qe = qe_get_device_node();
+ if (!qe)
+ return qebase;
ret = of_address_to_resource(qe, 0, &res);
if (!ret)
@@ -170,12 +171,9 @@ unsigned int qe_get_brg_clk(void)
if (brg_clk)
return brg_clk;
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return brg_clk;
- }
+ qe = qe_get_device_node();
+ if (!qe)
+ return brg_clk;
prop = of_get_property(qe, "brg-frequency", &size);
if (prop && size == sizeof(*prop))
@@ -281,7 +279,6 @@ EXPORT_SYMBOL(qe_clock_source);
*/
static void qe_snums_init(void)
{
- int i;
static const u8 snum_init_76[] = {
0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
@@ -302,19 +299,39 @@ static void qe_snums_init(void)
0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
};
- static const u8 *snum_init;
+ struct device_node *qe;
+ const u8 *snum_init;
+ int i;
- qe_num_of_snum = qe_get_num_of_snums();
+ bitmap_zero(snum_state, QE_NUM_OF_SNUM);
+ qe_num_of_snum = 28; /* The default number of snum for threads is 28 */
+ qe = qe_get_device_node();
+ if (qe) {
+ i = of_property_read_variable_u8_array(qe, "fsl,qe-snums",
+ snums, 1, QE_NUM_OF_SNUM);
+ if (i > 0) {
+ of_node_put(qe);
+ qe_num_of_snum = i;
+ return;
+ }
+ /*
+ * Fall back to legacy binding of using the value of
+ * fsl,qe-num-snums to choose one of the static arrays
+ * above.
+ */
+ of_property_read_u32(qe, "fsl,qe-num-snums", &qe_num_of_snum);
+ of_node_put(qe);
+ }
- if (qe_num_of_snum == 76)
+ if (qe_num_of_snum == 76) {
snum_init = snum_init_76;
- else
+ } else if (qe_num_of_snum == 28 || qe_num_of_snum == 46) {
snum_init = snum_init_46;
-
- for (i = 0; i < qe_num_of_snum; i++) {
- snums[i].num = snum_init[i];
- snums[i].state = QE_SNUM_STATE_FREE;
+ } else {
+ pr_err("QE: unsupported value of fsl,qe-num-snums: %u\n", qe_num_of_snum);
+ return;
}
+ memcpy(snums, snum_init, qe_num_of_snum);
}
int qe_get_snum(void)
@@ -324,12 +341,10 @@ int qe_get_snum(void)
int i;
spin_lock_irqsave(&qe_lock, flags);
- for (i = 0; i < qe_num_of_snum; i++) {
- if (snums[i].state == QE_SNUM_STATE_FREE) {
- snums[i].state = QE_SNUM_STATE_USED;
- snum = snums[i].num;
- break;
- }
+ i = find_first_zero_bit(snum_state, qe_num_of_snum);
+ if (i < qe_num_of_snum) {
+ set_bit(i, snum_state);
+ snum = snums[i];
}
spin_unlock_irqrestore(&qe_lock, flags);
@@ -339,14 +354,10 @@ EXPORT_SYMBOL(qe_get_snum);
void qe_put_snum(u8 snum)
{
- int i;
+ const u8 *p = memchr(snums, snum, qe_num_of_snum);
- for (i = 0; i < qe_num_of_snum; i++) {
- if (snums[i].num == snum) {
- snums[i].state = QE_SNUM_STATE_FREE;
- break;
- }
- }
+ if (p)
+ clear_bit(p - snums, snum_state);
}
EXPORT_SYMBOL(qe_put_snum);
@@ -419,7 +430,7 @@ static void qe_upload_microcode(const void *base,
/*
* Upload a microcode to the I-RAM at a specific address.
*
- * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
+ * See Documentation/powerpc/qe_firmware.rst for information on QE microcode
* uploading.
*
* Currently, only version 1 is supported, so the 'version' field must be
@@ -572,16 +583,9 @@ struct qe_firmware_info *qe_get_firmware_info(void)
initialized = 1;
- /*
- * Newer device trees have an "fsl,qe" compatible property for the QE
- * node, but we still need to support older device trees.
- */
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return NULL;
- }
+ qe = qe_get_device_node();
+ if (!qe)
+ return NULL;
/* Find the 'firmware' child node */
fw = of_get_child_by_name(qe, "firmware");
@@ -627,16 +631,9 @@ unsigned int qe_get_num_of_risc(void)
unsigned int num_of_risc = 0;
const u32 *prop;
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- /* Older devices trees did not have an "fsl,qe"
- * compatible property, so we need to look for
- * the QE node by name.
- */
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return num_of_risc;
- }
+ qe = qe_get_device_node();
+ if (!qe)
+ return num_of_risc;
prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
if (prop && size == sizeof(*prop))
@@ -650,37 +647,7 @@ EXPORT_SYMBOL(qe_get_num_of_risc);
unsigned int qe_get_num_of_snums(void)
{
- struct device_node *qe;
- int size;
- unsigned int num_of_snums;
- const u32 *prop;
-
- num_of_snums = 28; /* The default number of snum for threads is 28 */
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- /* Older devices trees did not have an "fsl,qe"
- * compatible property, so we need to look for
- * the QE node by name.
- */
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return num_of_snums;
- }
-
- prop = of_get_property(qe, "fsl,qe-num-snums", &size);
- if (prop && size == sizeof(*prop)) {
- num_of_snums = *prop;
- if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
- /* No QE ever has fewer than 28 SNUMs */
- pr_err("QE: number of snum is invalid\n");
- of_node_put(qe);
- return -EINVAL;
- }
- }
-
- of_node_put(qe);
-
- return num_of_snums;
+ return qe_num_of_snum;
}
EXPORT_SYMBOL(qe_get_num_of_snums);
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 31b8d002d855..b0dffb06c05d 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -198,7 +198,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
err = regulator_disable(domain->regulator);
if (err)
dev_err(domain->dev,
- "failed to disable regulator: %d\n", ret);
+ "failed to disable regulator: %d\n", err);
/* Preserve earlier error code */
ret = ret ?: err;
}
diff --git a/drivers/soc/imx/soc-imx-scu.c b/drivers/soc/imx/soc-imx-scu.c
index 676f612f6488..50831ebf126a 100644
--- a/drivers/soc/imx/soc-imx-scu.c
+++ b/drivers/soc/imx/soc-imx-scu.c
@@ -27,6 +27,40 @@ struct imx_sc_msg_misc_get_soc_id {
} data;
} __packed;
+struct imx_sc_msg_misc_get_soc_uid {
+ struct imx_sc_rpc_msg hdr;
+ u32 uid_low;
+ u32 uid_high;
+} __packed;
+
+static ssize_t soc_uid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct imx_sc_msg_misc_get_soc_uid msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ u64 soc_uid;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_MISC;
+ hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID;
+ hdr->size = 1;
+
+ ret = imx_scu_call_rpc(soc_ipc_handle, &msg, false);
+ if (ret) {
+ pr_err("%s: get soc uid failed, ret %d\n", __func__, ret);
+ return ret;
+ }
+
+ soc_uid = msg.uid_high;
+ soc_uid <<= 32;
+ soc_uid |= msg.uid_low;
+
+ return sprintf(buf, "%016llX\n", soc_uid);
+}
+
+static DEVICE_ATTR_RO(soc_uid);
+
static int imx_scu_soc_id(void)
{
struct imx_sc_msg_misc_get_soc_id msg;
@@ -102,6 +136,11 @@ static int imx_scu_soc_probe(struct platform_device *pdev)
goto free_revision;
}
+ ret = device_create_file(soc_device_to_device(soc_dev),
+ &dev_attr_soc_uid);
+ if (ret)
+ goto free_revision;
+
return 0;
free_revision:
diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c
index f924ae8c6514..b9831576dd25 100644
--- a/drivers/soc/imx/soc-imx8.c
+++ b/drivers/soc/imx/soc-imx8.c
@@ -16,6 +16,9 @@
#define IMX8MQ_SW_INFO_B1 0x40
#define IMX8MQ_SW_MAGIC_B1 0xff0055aa
+#define OCOTP_UID_LOW 0x410
+#define OCOTP_UID_HIGH 0x420
+
/* Same as ANADIG_DIGPROG_IMX7D */
#define ANADIG_DIGPROG_IMX8MM 0x800
@@ -24,6 +27,16 @@ struct imx8_soc_data {
u32 (*soc_revision)(void);
};
+static u64 soc_uid;
+
+static ssize_t soc_uid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%016llX\n", soc_uid);
+}
+
+static DEVICE_ATTR_RO(soc_uid);
+
static u32 __init imx8mq_soc_revision(void)
{
struct device_node *np;
@@ -42,6 +55,10 @@ static u32 __init imx8mq_soc_revision(void)
if (magic == IMX8MQ_SW_MAGIC_B1)
rev = REV_B1;
+ soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+ soc_uid <<= 32;
+ soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
+
iounmap(ocotp_base);
out:
@@ -49,6 +66,26 @@ out:
return rev;
}
+static void __init imx8mm_soc_uid(void)
+{
+ void __iomem *ocotp_base;
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
+ if (!np)
+ return;
+
+ ocotp_base = of_iomap(np, 0);
+ WARN_ON(!ocotp_base);
+
+ soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+ soc_uid <<= 32;
+ soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
+
+ iounmap(ocotp_base);
+ of_node_put(np);
+}
+
static u32 __init imx8mm_soc_revision(void)
{
struct device_node *np;
@@ -66,6 +103,9 @@ static u32 __init imx8mm_soc_revision(void)
iounmap(anatop_base);
of_node_put(np);
+
+ imx8mm_soc_uid();
+
return rev;
}
@@ -140,6 +180,11 @@ static int __init imx8_soc_init(void)
goto free_rev;
}
+ ret = device_create_file(soc_device_to_device(soc_dev),
+ &dev_attr_soc_uid);
+ if (ret)
+ goto free_rev;
+
if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
diff --git a/drivers/soc/ixp4xx/Kconfig b/drivers/soc/ixp4xx/Kconfig
index de2e62c3310a..e3eb19b85fa4 100644
--- a/drivers/soc/ixp4xx/Kconfig
+++ b/drivers/soc/ixp4xx/Kconfig
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
+if ARCH_IXP4XX || COMPILE_TEST
+
menu "IXP4xx SoC drivers"
config IXP4XX_QMGR
@@ -15,3 +17,5 @@ config IXP4XX_NPE
and is automatically selected by Ethernet and HSS drivers.
endmenu
+
+endif
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
index ff9fef5a032b..7aa0517ff2f3 100644
--- a/drivers/soc/mediatek/mtk-cmdq-helper.c
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -136,7 +136,7 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
return 0;
}
-int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset)
+int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
{
u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) |
(subsys << CMDQ_SUBSYS_SHIFT);
@@ -145,8 +145,8 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset)
}
EXPORT_SYMBOL(cmdq_pkt_write);
-int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
- u32 subsys, u32 offset, u32 mask)
+int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
+ u16 offset, u32 value, u32 mask)
{
u32 offset_mask = offset;
int err = 0;
@@ -161,7 +161,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
}
EXPORT_SYMBOL(cmdq_pkt_write_mask);
-int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event)
+int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
{
u32 arg_b;
@@ -181,7 +181,7 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event)
}
EXPORT_SYMBOL(cmdq_pkt_wfe);
-int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event)
+int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
{
if (event >= CMDQ_MAX_EVENT)
return -EINVAL;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index a6d1bfb17279..661e47acc354 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -175,6 +175,14 @@ config QCOM_SMSM
Say yes here to support the Qualcomm Shared Memory State Machine.
The state machine is represented by bits in shared memory.
+config QCOM_SOCINFO
+ tristate "Qualcomm socinfo driver"
+ depends on QCOM_SMEM
+ select SOC_BUS
+ help
+ Say yes here to support the Qualcomm socinfo driver, providing
+ information about the SoC to user space.
+
config QCOM_WCNSS_CTRL
tristate "Qualcomm WCNSS control driver"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index eeb088beb15f..162788701a77 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_QCOM_SMEM) += smem.o
obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
+obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index d5cf953b4337..7d622ea1274e 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -630,6 +630,9 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
struct geni_wrapper *wrapper = se->wrapper;
u32 val;
+ if (!wrapper)
+ return -EINVAL;
+
*iova = dma_map_single(wrapper->dev, buf, len, DMA_TO_DEVICE);
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
@@ -663,6 +666,9 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
struct geni_wrapper *wrapper = se->wrapper;
u32 val;
+ if (!wrapper)
+ return -EINVAL;
+
*iova = dma_map_single(wrapper->dev, buf, len, DMA_FROM_DEVICE);
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 5f885196f4d0..33a27e6c6d67 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -10,6 +10,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
+#include <linux/thermal.h>
+#include <linux/slab.h>
#define QMP_DESC_MAGIC 0x0
#define QMP_DESC_VERSION 0x4
@@ -40,6 +42,17 @@
/* 64 bytes is enough to store the requests and provides padding to 4 bytes */
#define QMP_MSG_LEN 64
+#define QMP_NUM_COOLING_RESOURCES 2
+
+static bool qmp_cdev_init_state = 1;
+
+struct qmp_cooling_device {
+ struct thermal_cooling_device *cdev;
+ struct qmp *qmp;
+ char *name;
+ bool state;
+};
+
/**
* struct qmp - driver state for QMP implementation
* @msgram: iomem referencing the message RAM used for communication
@@ -69,6 +82,7 @@ struct qmp {
struct clk_hw qdss_clk;
struct genpd_onecell_data pd_data;
+ struct qmp_cooling_device *cooling_devs;
};
struct qmp_pd {
@@ -385,6 +399,118 @@ static void qmp_pd_remove(struct qmp *qmp)
pm_genpd_remove(data->domains[i]);
}
+static int qmp_cdev_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ *state = qmp_cdev_init_state;
+ return 0;
+}
+
+static int qmp_cdev_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct qmp_cooling_device *qmp_cdev = cdev->devdata;
+
+ *state = qmp_cdev->state;
+ return 0;
+}
+
+static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct qmp_cooling_device *qmp_cdev = cdev->devdata;
+ char buf[QMP_MSG_LEN] = {};
+ bool cdev_state;
+ int ret;
+
+ /* Normalize state */
+ cdev_state = !!state;
+
+ if (qmp_cdev->state == state)
+ return 0;
+
+ snprintf(buf, sizeof(buf),
+ "{class: volt_flr, event:zero_temp, res:%s, value:%s}",
+ qmp_cdev->name,
+ cdev_state ? "off" : "on");
+
+ ret = qmp_send(qmp_cdev->qmp, buf, sizeof(buf));
+
+ if (!ret)
+ qmp_cdev->state = cdev_state;
+
+ return ret;
+}
+
+static struct thermal_cooling_device_ops qmp_cooling_device_ops = {
+ .get_max_state = qmp_cdev_get_max_state,
+ .get_cur_state = qmp_cdev_get_cur_state,
+ .set_cur_state = qmp_cdev_set_cur_state,
+};
+
+static int qmp_cooling_device_add(struct qmp *qmp,
+ struct qmp_cooling_device *qmp_cdev,
+ struct device_node *node)
+{
+ char *cdev_name = (char *)node->name;
+
+ qmp_cdev->qmp = qmp;
+ qmp_cdev->state = qmp_cdev_init_state;
+ qmp_cdev->name = cdev_name;
+ qmp_cdev->cdev = devm_thermal_of_cooling_device_register
+ (qmp->dev, node,
+ cdev_name,
+ qmp_cdev, &qmp_cooling_device_ops);
+
+ if (IS_ERR(qmp_cdev->cdev))
+ dev_err(qmp->dev, "unable to register %s cooling device\n",
+ cdev_name);
+
+ return PTR_ERR_OR_ZERO(qmp_cdev->cdev);
+}
+
+static int qmp_cooling_devices_register(struct qmp *qmp)
+{
+ struct device_node *np, *child;
+ int count = QMP_NUM_COOLING_RESOURCES;
+ int ret;
+
+ np = qmp->dev->of_node;
+
+ qmp->cooling_devs = devm_kcalloc(qmp->dev, count,
+ sizeof(*qmp->cooling_devs),
+ GFP_KERNEL);
+
+ if (!qmp->cooling_devs)
+ return -ENOMEM;
+
+ for_each_available_child_of_node(np, child) {
+ if (!of_find_property(child, "#cooling-cells", NULL))
+ continue;
+ ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
+ child);
+ if (ret)
+ goto unroll;
+ }
+
+ return 0;
+
+unroll:
+ while (--count >= 0)
+ thermal_cooling_device_unregister
+ (qmp->cooling_devs[count].cdev);
+
+ return ret;
+}
+
+static void qmp_cooling_devices_remove(struct qmp *qmp)
+{
+ int i;
+
+ for (i = 0; i < QMP_NUM_COOLING_RESOURCES; i++)
+ thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
+}
+
static int qmp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -433,6 +559,10 @@ static int qmp_probe(struct platform_device *pdev)
if (ret)
goto err_remove_qdss_clk;
+ ret = qmp_cooling_devices_register(qmp);
+ if (ret)
+ dev_err(&pdev->dev, "failed to register aoss cooling devices\n");
+
platform_set_drvdata(pdev, qmp);
return 0;
@@ -453,6 +583,7 @@ static int qmp_remove(struct platform_device *pdev)
qmp_qdss_clk_remove(qmp);
qmp_pd_remove(qmp);
+ qmp_cooling_devices_remove(qmp);
qmp_close(qmp);
mbox_free_channel(qmp->mbox_chan);
@@ -461,7 +592,9 @@ static int qmp_remove(struct platform_device *pdev)
}
static const struct of_device_id qmp_dt_match[] = {
+ { .compatible = "qcom,sc7180-aoss-qmp", },
{ .compatible = "qcom,sdm845-aoss-qmp", },
+ { .compatible = "qcom,sm8150-aoss-qmp", },
{}
};
MODULE_DEVICE_TABLE(of, qmp_dt_match);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index f27c00d82ae4..28c19bcb2f20 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -84,7 +84,7 @@
#define SMEM_GLOBAL_HOST 0xfffe
/* Max number of processors/hosts in a system */
-#define SMEM_HOST_COUNT 10
+#define SMEM_HOST_COUNT 11
/**
* struct smem_proc_comm - proc_comm communication struct (legacy)
@@ -268,6 +268,7 @@ struct qcom_smem {
struct smem_partition_header *partitions[SMEM_HOST_COUNT];
size_t cacheline[SMEM_HOST_COUNT];
u32 item_count;
+ struct platform_device *socinfo;
unsigned num_regions;
struct smem_region regions[];
@@ -963,11 +964,19 @@ static int qcom_smem_probe(struct platform_device *pdev)
__smem = smem;
+ smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
+ PLATFORM_DEVID_NONE, NULL,
+ 0);
+ if (IS_ERR(smem->socinfo))
+ dev_dbg(&pdev->dev, "failed to register socinfo device\n");
+
return 0;
}
static int qcom_smem_remove(struct platform_device *pdev)
{
+ platform_device_unregister(__smem->socinfo);
+
hwspin_lock_free(__smem->hwlock);
__smem = NULL;
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
new file mode 100644
index 000000000000..a39ea5061dc5
--- /dev/null
+++ b/drivers/soc/qcom/socinfo.c
@@ -0,0 +1,476 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, Linaro Ltd.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/string.h>
+#include <linux/sys_soc.h>
+#include <linux/types.h>
+
+/*
+ * SoC version type with major number in the upper 16 bits and minor
+ * number in the lower 16 bits.
+ */
+#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
+#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
+#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
+
+#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
+
+/*
+ * SMEM item id, used to acquire handles to respective
+ * SMEM region.
+ */
+#define SMEM_HW_SW_BUILD_ID 137
+
+#ifdef CONFIG_DEBUG_FS
+#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
+#define SMEM_IMAGE_VERSION_SIZE 4096
+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
+#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
+#define SMEM_IMAGE_VERSION_OEM_SIZE 32
+
+/*
+ * SMEM Image table indices
+ */
+#define SMEM_IMAGE_TABLE_BOOT_INDEX 0
+#define SMEM_IMAGE_TABLE_TZ_INDEX 1
+#define SMEM_IMAGE_TABLE_RPM_INDEX 3
+#define SMEM_IMAGE_TABLE_APPS_INDEX 10
+#define SMEM_IMAGE_TABLE_MPSS_INDEX 11
+#define SMEM_IMAGE_TABLE_ADSP_INDEX 12
+#define SMEM_IMAGE_TABLE_CNSS_INDEX 13
+#define SMEM_IMAGE_TABLE_VIDEO_INDEX 14
+#define SMEM_IMAGE_VERSION_TABLE 469
+
+/*
+ * SMEM Image table names
+ */
+static const char *const socinfo_image_names[] = {
+ [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp",
+ [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps",
+ [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot",
+ [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss",
+ [SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss",
+ [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm",
+ [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz",
+ [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video",
+};
+
+static const char *const pmic_models[] = {
+ [0] = "Unknown PMIC model",
+ [9] = "PM8994",
+ [11] = "PM8916",
+ [13] = "PM8058",
+ [14] = "PM8028",
+ [15] = "PM8901",
+ [16] = "PM8027",
+ [17] = "ISL9519",
+ [18] = "PM8921",
+ [19] = "PM8018",
+ [20] = "PM8015",
+ [21] = "PM8014",
+ [22] = "PM8821",
+ [23] = "PM8038",
+ [24] = "PM8922",
+ [25] = "PM8917",
+};
+#endif /* CONFIG_DEBUG_FS */
+
+/* Socinfo SMEM item structure */
+struct socinfo {
+ __le32 fmt;
+ __le32 id;
+ __le32 ver;
+ char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
+ /* Version 2 */
+ __le32 raw_id;
+ __le32 raw_ver;
+ /* Version 3 */
+ __le32 hw_plat;
+ /* Version 4 */
+ __le32 plat_ver;
+ /* Version 5 */
+ __le32 accessory_chip;
+ /* Version 6 */
+ __le32 hw_plat_subtype;
+ /* Version 7 */
+ __le32 pmic_model;
+ __le32 pmic_die_rev;
+ /* Version 8 */
+ __le32 pmic_model_1;
+ __le32 pmic_die_rev_1;
+ __le32 pmic_model_2;
+ __le32 pmic_die_rev_2;
+ /* Version 9 */
+ __le32 foundry_id;
+ /* Version 10 */
+ __le32 serial_num;
+ /* Version 11 */
+ __le32 num_pmics;
+ __le32 pmic_array_offset;
+ /* Version 12 */
+ __le32 chip_family;
+ __le32 raw_device_family;
+ __le32 raw_device_num;
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct socinfo_params {
+ u32 raw_device_family;
+ u32 hw_plat_subtype;
+ u32 accessory_chip;
+ u32 raw_device_num;
+ u32 chip_family;
+ u32 foundry_id;
+ u32 plat_ver;
+ u32 raw_ver;
+ u32 hw_plat;
+ u32 fmt;
+};
+
+struct smem_image_version {
+ char name[SMEM_IMAGE_VERSION_NAME_SIZE];
+ char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE];
+ char pad;
+ char oem[SMEM_IMAGE_VERSION_OEM_SIZE];
+};
+#endif /* CONFIG_DEBUG_FS */
+
+struct qcom_socinfo {
+ struct soc_device *soc_dev;
+ struct soc_device_attribute attr;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dbg_root;
+ struct socinfo_params info;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+struct soc_id {
+ unsigned int id;
+ const char *name;
+};
+
+static const struct soc_id soc_id[] = {
+ { 87, "MSM8960" },
+ { 109, "APQ8064" },
+ { 122, "MSM8660A" },
+ { 123, "MSM8260A" },
+ { 124, "APQ8060A" },
+ { 126, "MSM8974" },
+ { 130, "MPQ8064" },
+ { 138, "MSM8960AB" },
+ { 139, "APQ8060AB" },
+ { 140, "MSM8260AB" },
+ { 141, "MSM8660AB" },
+ { 178, "APQ8084" },
+ { 184, "APQ8074" },
+ { 185, "MSM8274" },
+ { 186, "MSM8674" },
+ { 194, "MSM8974PRO" },
+ { 206, "MSM8916" },
+ { 208, "APQ8074-AA" },
+ { 209, "APQ8074-AB" },
+ { 210, "APQ8074PRO" },
+ { 211, "MSM8274-AA" },
+ { 212, "MSM8274-AB" },
+ { 213, "MSM8274PRO" },
+ { 214, "MSM8674-AA" },
+ { 215, "MSM8674-AB" },
+ { 216, "MSM8674PRO" },
+ { 217, "MSM8974-AA" },
+ { 218, "MSM8974-AB" },
+ { 246, "MSM8996" },
+ { 247, "APQ8016" },
+ { 248, "MSM8216" },
+ { 249, "MSM8116" },
+ { 250, "MSM8616" },
+ { 291, "APQ8096" },
+ { 305, "MSM8996SG" },
+ { 310, "MSM8996AU" },
+ { 311, "APQ8096AU" },
+ { 312, "APQ8096SG" },
+};
+
+static const char *socinfo_machine(struct device *dev, unsigned int id)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) {
+ if (soc_id[idx].id == id)
+ return soc_id[idx].name;
+ }
+
+ return NULL;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#define QCOM_OPEN(name, _func) \
+static int qcom_open_##name(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, _func, inode->i_private); \
+} \
+ \
+static const struct file_operations qcom_ ##name## _ops = { \
+ .open = qcom_open_##name, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+#define DEBUGFS_ADD(info, name) \
+ debugfs_create_file(__stringify(name), 0400, \
+ qcom_socinfo->dbg_root, \
+ info, &qcom_ ##name## _ops)
+
+
+static int qcom_show_build_id(struct seq_file *seq, void *p)
+{
+ struct socinfo *socinfo = seq->private;
+
+ seq_printf(seq, "%s\n", socinfo->build_id);
+
+ return 0;
+}
+
+static int qcom_show_pmic_model(struct seq_file *seq, void *p)
+{
+ struct socinfo *socinfo = seq->private;
+ int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model));
+
+ if (model < 0)
+ return -EINVAL;
+
+ seq_printf(seq, "%s\n", pmic_models[model]);
+
+ return 0;
+}
+
+static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
+{
+ struct socinfo *socinfo = seq->private;
+
+ seq_printf(seq, "%u.%u\n",
+ SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)),
+ SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev)));
+
+ return 0;
+}
+
+QCOM_OPEN(build_id, qcom_show_build_id);
+QCOM_OPEN(pmic_model, qcom_show_pmic_model);
+QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
+
+#define DEFINE_IMAGE_OPS(type) \
+static int show_image_##type(struct seq_file *seq, void *p) \
+{ \
+ struct smem_image_version *image_version = seq->private; \
+ seq_puts(seq, image_version->type); \
+ seq_puts(seq, "\n"); \
+ return 0; \
+} \
+static int open_image_##type(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, show_image_##type, inode->i_private); \
+} \
+ \
+static const struct file_operations qcom_image_##type##_ops = { \
+ .open = open_image_##type, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+DEFINE_IMAGE_OPS(name);
+DEFINE_IMAGE_OPS(variant);
+DEFINE_IMAGE_OPS(oem);
+
+static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
+ struct socinfo *info)
+{
+ struct smem_image_version *versions;
+ struct dentry *dentry;
+ size_t size;
+ int i;
+
+ qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
+
+ qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
+
+ switch (qcom_socinfo->info.fmt) {
+ case SOCINFO_VERSION(0, 12):
+ qcom_socinfo->info.chip_family =
+ __le32_to_cpu(info->chip_family);
+ qcom_socinfo->info.raw_device_family =
+ __le32_to_cpu(info->raw_device_family);
+ qcom_socinfo->info.raw_device_num =
+ __le32_to_cpu(info->raw_device_num);
+
+ debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.chip_family);
+ debugfs_create_x32("raw_device_family", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.raw_device_family);
+ debugfs_create_x32("raw_device_number", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.raw_device_num);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 11):
+ case SOCINFO_VERSION(0, 10):
+ case SOCINFO_VERSION(0, 9):
+ qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
+
+ debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.foundry_id);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 8):
+ case SOCINFO_VERSION(0, 7):
+ DEBUGFS_ADD(info, pmic_model);
+ DEBUGFS_ADD(info, pmic_die_rev);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 6):
+ qcom_socinfo->info.hw_plat_subtype =
+ __le32_to_cpu(info->hw_plat_subtype);
+
+ debugfs_create_u32("hardware_platform_subtype", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.hw_plat_subtype);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 5):
+ qcom_socinfo->info.accessory_chip =
+ __le32_to_cpu(info->accessory_chip);
+
+ debugfs_create_u32("accessory_chip", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.accessory_chip);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 4):
+ qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver);
+
+ debugfs_create_u32("platform_version", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.plat_ver);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 3):
+ qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat);
+
+ debugfs_create_u32("hardware_platform", 0400,
+ qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.hw_plat);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 2):
+ qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver);
+
+ debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.raw_ver);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 1):
+ DEBUGFS_ADD(info, build_id);
+ break;
+ }
+
+ versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
+ &size);
+
+ for (i = 0; i < ARRAY_SIZE(socinfo_image_names); i++) {
+ if (!socinfo_image_names[i])
+ continue;
+
+ dentry = debugfs_create_dir(socinfo_image_names[i],
+ qcom_socinfo->dbg_root);
+ debugfs_create_file("name", 0400, dentry, &versions[i],
+ &qcom_image_name_ops);
+ debugfs_create_file("variant", 0400, dentry, &versions[i],
+ &qcom_image_variant_ops);
+ debugfs_create_file("oem", 0400, dentry, &versions[i],
+ &qcom_image_oem_ops);
+ }
+}
+
+static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
+{
+ debugfs_remove_recursive(qcom_socinfo->dbg_root);
+}
+#else
+static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
+ struct socinfo *info)
+{
+}
+static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { }
+#endif /* CONFIG_DEBUG_FS */
+
+static int qcom_socinfo_probe(struct platform_device *pdev)
+{
+ struct qcom_socinfo *qs;
+ struct socinfo *info;
+ size_t item_size;
+
+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
+ &item_size);
+ if (IS_ERR(info)) {
+ dev_err(&pdev->dev, "Couldn't find socinfo\n");
+ return PTR_ERR(info);
+ }
+
+ qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL);
+ if (!qs)
+ return -ENOMEM;
+
+ qs->attr.family = "Snapdragon";
+ qs->attr.machine = socinfo_machine(&pdev->dev,
+ le32_to_cpu(info->id));
+ qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
+ SOCINFO_MAJOR(le32_to_cpu(info->ver)),
+ SOCINFO_MINOR(le32_to_cpu(info->ver)));
+ if (offsetof(struct socinfo, serial_num) <= item_size)
+ qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "%u",
+ le32_to_cpu(info->serial_num));
+
+ qs->soc_dev = soc_device_register(&qs->attr);
+ if (IS_ERR(qs->soc_dev))
+ return PTR_ERR(qs->soc_dev);
+
+ socinfo_debugfs_init(qs, info);
+
+ /* Feed the soc specific unique data into entropy pool */
+ add_device_randomness(info, item_size);
+
+ platform_set_drvdata(pdev, qs->soc_dev);
+
+ return 0;
+}
+
+static int qcom_socinfo_remove(struct platform_device *pdev)
+{
+ struct qcom_socinfo *qs = platform_get_drvdata(pdev);
+
+ soc_device_unregister(qs->soc_dev);
+
+ socinfo_debugfs_exit(qs);
+
+ return 0;
+}
+
+static struct platform_driver qcom_socinfo_driver = {
+ .probe = qcom_socinfo_probe,
+ .remove = qcom_socinfo_remove,
+ .driver = {
+ .name = "qcom-socinfo",
+ },
+};
+
+module_platform_driver(qcom_socinfo_driver);
+
+MODULE_DESCRIPTION("Qualcomm SoCinfo driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-socinfo");
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 2bbf49e5d441..3c5e017bacba 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -55,6 +55,7 @@ config ARCH_EMEV2
config ARCH_R7S72100
bool "RZ/A1H (R7S72100)"
+ select ARM_ERRATA_754322
select PM
select PM_GENERIC_DOMAINS
select RENESAS_OSTM
@@ -72,12 +73,14 @@ config ARCH_R8A73A4
bool "R-Mobile APE6 (R8A73A40)"
select ARCH_RMOBILE
select ARM_ERRATA_798181 if SMP
+ select ARM_ERRATA_814220
select HAVE_ARM_ARCH_TIMER
select RENESAS_IRQC
config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
select ARCH_RMOBILE
+ select ARM_ERRATA_754322
select RENESAS_INTC_IRQPIN
config ARCH_R8A7743
@@ -95,20 +98,24 @@ config ARCH_R8A7744
config ARCH_R8A7745
bool "RZ/G1E (R8A77450)"
select ARCH_RCAR_GEN2
+ select ARM_ERRATA_814220
select SYSC_R8A7745
config ARCH_R8A77470
bool "RZ/G1C (R8A77470)"
select ARCH_RCAR_GEN2
+ select ARM_ERRATA_814220
select SYSC_R8A77470
config ARCH_R8A7778
bool "R-Car M1A (R8A77781)"
select ARCH_RCAR_GEN1
+ select ARM_ERRATA_754322
config ARCH_R8A7779
bool "R-Car H1 (R8A77790)"
select ARCH_RCAR_GEN1
+ select ARM_ERRATA_754322
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select SYSC_R8A7779
@@ -117,6 +124,7 @@ config ARCH_R8A7790
bool "R-Car H2 (R8A77900)"
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
+ select ARM_ERRATA_814220
select I2C
select SYSC_R8A7790
@@ -143,15 +151,18 @@ config ARCH_R8A7793
config ARCH_R8A7794
bool "R-Car E2 (R8A77940)"
select ARCH_RCAR_GEN2
+ select ARM_ERRATA_814220
select SYSC_R8A7794
config ARCH_R9A06G032
bool "RZ/N1D (R9A06G032)"
select ARCH_RZN1
+ select ARM_ERRATA_814220
config ARCH_SH73A0
bool "SH-Mobile AG5 (R8A73A00)"
select ARCH_RMOBILE
+ select ARM_ERRATA_754322
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select RENESAS_INTC_IRQPIN
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 0c80fab4f8de..59b5e6b10272 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -170,7 +170,7 @@ struct rcar_sysc_pd {
struct generic_pm_domain genpd;
struct rcar_sysc_ch ch;
unsigned int flags;
- char name[0];
+ char name[];
};
static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
@@ -200,7 +200,6 @@ static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
{
struct generic_pm_domain *genpd = &pd->genpd;
const char *name = pd->genpd.name;
- struct dev_power_governor *gov = &simple_qos_governor;
int error;
if (pd->flags & PD_CPU) {
@@ -254,7 +253,7 @@ static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
rcar_sysc_power(&pd->ch, true);
finalize:
- error = pm_genpd_init(genpd, gov, false);
+ error = pm_genpd_init(genpd, &simple_qos_governor, false);
if (error)
pr_err("Failed to init PM domain %s: %d\n", name, error);
@@ -346,7 +345,7 @@ static int __init rcar_sysc_pd_init(void)
if (info->init) {
error = info->init();
if (error)
- return error;
+ goto out_put;
}
has_cpg_mstp = of_find_compatible_node(NULL, NULL,
diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c
index 421ae1c887d8..54b616ad4a62 100644
--- a/drivers/soc/renesas/rmobile-sysc.c
+++ b/drivers/soc/renesas/rmobile-sysc.c
@@ -48,12 +48,8 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
{
struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
- unsigned int mask;
+ unsigned int mask = BIT(rmobile_pd->bit_shift);
- if (rmobile_pd->bit_shift == ~0)
- return -EBUSY;
-
- mask = BIT(rmobile_pd->bit_shift);
if (rmobile_pd->suspend) {
int ret = rmobile_pd->suspend();
@@ -80,14 +76,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
{
- unsigned int mask;
+ unsigned int mask = BIT(rmobile_pd->bit_shift);
unsigned int retry_count;
int ret = 0;
- if (rmobile_pd->bit_shift == ~0)
- return 0;
-
- mask = BIT(rmobile_pd->bit_shift);
if (__raw_readl(rmobile_pd->base + PSTR) & mask)
return ret;
@@ -122,11 +114,15 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
struct dev_power_governor *gov = rmobile_pd->gov;
genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
- genpd->power_off = rmobile_pd_power_down;
- genpd->power_on = rmobile_pd_power_up;
- genpd->attach_dev = cpg_mstp_attach_dev;
- genpd->detach_dev = cpg_mstp_detach_dev;
- __rmobile_pd_power_up(rmobile_pd);
+ genpd->attach_dev = cpg_mstp_attach_dev;
+ genpd->detach_dev = cpg_mstp_detach_dev;
+
+ if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
+ genpd->power_off = rmobile_pd_power_down;
+ genpd->power_on = rmobile_pd_power_up;
+ __rmobile_pd_power_up(rmobile_pd);
+ }
+
pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
}
@@ -270,6 +266,11 @@ static void __init rmobile_setup_pm_domain(struct device_node *np,
break;
case PD_NORMAL:
+ if (pd->bit_shift == ~0) {
+ /* Top-level always-on domain */
+ pr_debug("PM domain %s is always-on domain\n", name);
+ pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+ }
break;
}
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 2186285fda92..33ad0de2de3c 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -7,6 +7,12 @@ menuconfig SOC_SAMSUNG
if SOC_SAMSUNG
+config EXYNOS_CHIPID
+ bool "Exynos Chipid controller driver" if COMPILE_TEST
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ select MFD_SYSCON
+ select SOC_BUS
+
config EXYNOS_PMU
bool "Exynos PMU controller driver" if COMPILE_TEST
depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 29f294baac6e..3b6a8797416c 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
new file mode 100644
index 000000000000..c55a47cfe617
--- /dev/null
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS - CHIP ID support
+ * Author: Pankaj Dubey <pankaj.dubey@samsung.com>
+ * Author: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+ */
+
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/soc/samsung/exynos-chipid.h>
+#include <linux/sys_soc.h>
+
+static const struct exynos_soc_id {
+ const char *name;
+ unsigned int id;
+} soc_ids[] = {
+ { "EXYNOS3250", 0xE3472000 },
+ { "EXYNOS4210", 0x43200000 }, /* EVT0 revision */
+ { "EXYNOS4210", 0x43210000 },
+ { "EXYNOS4212", 0x43220000 },
+ { "EXYNOS4412", 0xE4412000 },
+ { "EXYNOS5250", 0x43520000 },
+ { "EXYNOS5260", 0xE5260000 },
+ { "EXYNOS5410", 0xE5410000 },
+ { "EXYNOS5420", 0xE5420000 },
+ { "EXYNOS5440", 0xE5440000 },
+ { "EXYNOS5800", 0xE5422000 },
+ { "EXYNOS7420", 0xE7420000 },
+ { "EXYNOS5433", 0xE5433000 },
+};
+
+static const char * __init product_id_to_soc_id(unsigned int product_id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
+ if ((product_id & EXYNOS_MASK) == soc_ids[i].id)
+ return soc_ids[i].name;
+ return NULL;
+}
+
+int __init exynos_chipid_early_init(void)
+{
+ struct soc_device_attribute *soc_dev_attr;
+ struct soc_device *soc_dev;
+ struct device_node *root;
+ struct regmap *regmap;
+ u32 product_id;
+ u32 revision;
+ int ret;
+
+ regmap = syscon_regmap_lookup_by_compatible("samsung,exynos4210-chipid");
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id);
+ if (ret < 0)
+ return ret;
+
+ revision = product_id & EXYNOS_REV_MASK;
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return -ENOMEM;
+
+ soc_dev_attr->family = "Samsung Exynos";
+
+ root = of_find_node_by_path("/");
+ of_property_read_string(root, "model", &soc_dev_attr->machine);
+ of_node_put(root);
+
+ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision);
+ soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
+ if (!soc_dev_attr->soc_id) {
+ pr_err("Unknown SoC\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ /* please note that the actual registration will be deferred */
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+ ret = PTR_ERR(soc_dev);
+ goto err;
+ }
+
+ /* it is too early to use dev_info() here (soc_dev is NULL) */
+ pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
+ soc_dev_attr->soc_id, product_id, revision);
+
+ return 0;
+
+err:
+ kfree(soc_dev_attr->revision);
+ kfree(soc_dev_attr);
+ return ret;
+}
+
+early_initcall(exynos_chipid_early_init);
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index bb77c220b6f8..ccc6d53fe788 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -141,7 +141,7 @@ static int __init am43xx_map_gic(void)
}
#ifdef CONFIG_SUSPEND
-struct wkup_m3_wakeup_src rtc_wake_src(void)
+static struct wkup_m3_wakeup_src rtc_wake_src(void)
{
u32 i;
@@ -157,7 +157,7 @@ struct wkup_m3_wakeup_src rtc_wake_src(void)
return rtc_ext_wakeup;
}
-int am33xx_rtc_only_idle(unsigned long wfi_flags)
+static int am33xx_rtc_only_idle(unsigned long wfi_flags)
{
omap_rtc_power_off_program(&omap_rtc->dev);
am33xx_do_wfi_sram(wfi_flags);
@@ -252,7 +252,7 @@ static int am33xx_pm_begin(suspend_state_t state)
if (state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable()) {
nvmem = devm_nvmem_device_get(&omap_rtc->dev,
"omap_rtc_scratch0");
- if (nvmem)
+ if (!IS_ERR(nvmem))
nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
(void *)&rtc_magic_val);
rtc_only_idle = 1;
@@ -278,9 +278,12 @@ static void am33xx_pm_end(void)
struct nvmem_device *nvmem;
nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0");
+ if (IS_ERR(nvmem))
+ return;
+
m3_ipc->ops->finish_low_power(m3_ipc);
if (rtc_only_idle) {
- if (retrigger_irq)
+ if (retrigger_irq) {
/*
* 32 bits of Interrupt Set-Pending correspond to 32
* 32 interrupts. Compute the bit offset of the
@@ -291,8 +294,10 @@ static void am33xx_pm_end(void)
writel_relaxed(1 << (retrigger_irq & 31),
gic_dist_base + GIC_INT_SET_PENDING_BASE
+ retrigger_irq / 32 * 4);
- nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
- (void *)&val);
+ }
+
+ nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+ (void *)&val);
}
rtc_only_idle = 0;
@@ -415,7 +420,7 @@ static int am33xx_pm_rtc_setup(void)
nvmem = devm_nvmem_device_get(&omap_rtc->dev,
"omap_rtc_scratch0");
- if (nvmem) {
+ if (!IS_ERR(nvmem)) {
nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
4, (void *)&rtc_magic_val);
if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c
index 97817dd7ba24..8c2a2f23982c 100644
--- a/drivers/soc/ti/ti_sci_pm_domains.c
+++ b/drivers/soc/ti/ti_sci_pm_domains.c
@@ -15,15 +15,19 @@
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
/**
* struct ti_sci_genpd_dev_data: holds data needed for every device attached
* to this genpd
* @idx: index of the device that identifies it with the system
* control processor.
+ * @exclusive: Permissions for exclusive request or shared request of the
+ * device.
*/
struct ti_sci_genpd_dev_data {
int idx;
+ u8 exclusive;
};
/**
@@ -55,6 +59,14 @@ static int ti_sci_dev_id(struct device *dev)
return sci_dev_data->idx;
}
+static u8 is_ti_sci_dev_exclusive(struct device *dev)
+{
+ struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+ struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+ return sci_dev_data->exclusive;
+}
+
/**
* ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
* @dev: pointer to device associated with this genpd
@@ -79,7 +91,10 @@ static int ti_sci_dev_start(struct device *dev)
const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
int idx = ti_sci_dev_id(dev);
- return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
+ if (is_ti_sci_dev_exclusive(dev))
+ return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, idx);
+ else
+ return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
}
/**
@@ -110,7 +125,7 @@ static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
if (ret < 0)
return ret;
- if (pd_args.args_count != 1)
+ if (pd_args.args_count != 1 && pd_args.args_count != 2)
return -EINVAL;
idx = pd_args.args[0];
@@ -128,6 +143,10 @@ static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
return -ENOMEM;
sci_dev_data->idx = idx;
+ /* Enable the exclusive permissions by default */
+ sci_dev_data->exclusive = TI_SCI_PD_EXCLUSIVE;
+ if (pd_args.args_count == 2)
+ sci_dev_data->exclusive = pd_args.args[1] & 0x1;
genpd_data = dev_gpd_data(dev);
genpd_data->data = sci_dev_data;
diff --git a/drivers/soc/ux500/ux500-soc-id.c b/drivers/soc/ux500/ux500-soc-id.c
index ea5fd2e5e340..d64feeb51a40 100644
--- a/drivers/soc/ux500/ux500-soc-id.c
+++ b/drivers/soc/ux500/ux500-soc-id.c
@@ -203,10 +203,13 @@ static int __init ux500_soc_device_init(void)
ux500_setup_id();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
- if (!soc_dev_attr)
+ if (!soc_dev_attr) {
+ of_node_put(backupram);
return -ENOMEM;
+ }
soc_info_populate(soc_dev_attr, backupram);
+ of_node_put(backupram);
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig
index 3a01cfd70fdc..f518273cfbe3 100644
--- a/drivers/soundwire/Kconfig
+++ b/drivers/soundwire/Kconfig
@@ -4,7 +4,7 @@
#
menuconfig SOUNDWIRE
- bool "SoundWire support"
+ tristate "SoundWire support"
help
SoundWire is a 2-Pin interface with data and clock line ratified
by the MIPI Alliance. SoundWire is used for transporting data
@@ -17,17 +17,12 @@ if SOUNDWIRE
comment "SoundWire Devices"
-config SOUNDWIRE_BUS
- tristate
- select REGMAP_SOUNDWIRE
-
config SOUNDWIRE_CADENCE
tristate
config SOUNDWIRE_INTEL
tristate "Intel SoundWire Master driver"
select SOUNDWIRE_CADENCE
- select SOUNDWIRE_BUS
depends on X86 && ACPI && SND_SOC
help
SoundWire Intel Master driver.
diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile
index fd99a831b92a..45b7e5001653 100644
--- a/drivers/soundwire/Makefile
+++ b/drivers/soundwire/Makefile
@@ -5,7 +5,7 @@
#Bus Objs
soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
-obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
+obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
#Cadence Objs
soundwire-cadence-objs := cadence_master.o
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index ff4badc9b3de..60e8bdee5c75 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -81,8 +81,8 @@
#define CDNS_MCP_INTSET 0x4C
-#define CDNS_SDW_SLAVE_STAT 0x50
-#define CDNS_MCP_SLAVE_STAT_MASK BIT(1, 0)
+#define CDNS_MCP_SLAVE_STAT 0x50
+#define CDNS_MCP_SLAVE_STAT_MASK GENMASK(1, 0)
#define CDNS_MCP_SLAVE_INTSTAT0 0x54
#define CDNS_MCP_SLAVE_INTSTAT1 0x58
@@ -96,8 +96,8 @@
#define CDNS_MCP_SLAVE_INTMASK0 0x5C
#define CDNS_MCP_SLAVE_INTMASK1 0x60
-#define CDNS_MCP_SLAVE_INTMASK0_MASK GENMASK(30, 0)
-#define CDNS_MCP_SLAVE_INTMASK1_MASK GENMASK(16, 0)
+#define CDNS_MCP_SLAVE_INTMASK0_MASK GENMASK(31, 0)
+#define CDNS_MCP_SLAVE_INTMASK1_MASK GENMASK(15, 0)
#define CDNS_MCP_PORT_INTSTAT 0x64
#define CDNS_MCP_PDI_STAT 0x6C
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3a1d8f1170de..0f0fdb57198f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -433,6 +433,16 @@ config SPI_MT7621
help
This selects a driver for the MediaTek MT7621 SPI Controller.
+config SPI_NPCM_FIU
+ tristate "Nuvoton NPCM FLASH Interface Unit"
+ depends on ARCH_NPCM || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ help
+ This enables support for the Flash Interface Unit SPI controller
+ in master mode.
+ This driver does not support generic SPI. The implementation only
+ supports spi-mem interface.
+
config SPI_NPCM_PSPI
tristate "Nuvoton NPCM PSPI Controller"
depends on ARCH_NPCM || COMPILE_TEST
@@ -440,13 +450,6 @@ config SPI_NPCM_PSPI
This driver provides support for Nuvoton NPCM BMC
Peripheral SPI controller in master mode.
-config SPI_NUC900
- tristate "Nuvoton NUC900 series SPI"
- depends on ARCH_W90X900
- select SPI_BITBANG
- help
- SPI driver for Nuvoton NUC900 series ARM SoCs
-
config SPI_LANTIQ_SSC
tristate "Lantiq SSC SPI controller"
depends on LANTIQ || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 63dcab552bcb..bb49c9e6d0a0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -63,8 +63,8 @@ obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o
obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o
+obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o
obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o
-obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 6a7d7b553d95..fd8007ebb145 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -526,7 +526,6 @@ static int atmel_qspi_probe(struct platform_device *pdev)
/* Request the IRQ */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "missing IRQ\n");
err = irq;
goto disable_qspick;
}
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index ea160f117f88..41d71ba7fd32 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -170,7 +170,6 @@ static int altera_spi_probe(struct platform_device *pdev)
{
struct altera_spi *hw;
struct spi_master *master;
- struct resource *res;
int err = -ENODEV;
master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
@@ -189,8 +188,7 @@ static int altera_spi_probe(struct platform_device *pdev)
hw = spi_master_get_devdata(master);
/* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hw->base = devm_ioremap_resource(&pdev->dev, res);
+ hw->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->base)) {
err = PTR_ERR(hw->base);
goto exit;
diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 032888344822..e450ee17787f 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -817,7 +817,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *of_node = dev->of_node;
- struct resource *res;
struct spi_master *master;
struct a3700_spi *spi;
u32 num_cs = 0;
@@ -855,8 +854,7 @@ static int a3700_spi_probe(struct platform_device *pdev)
spi->master = master;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spi->base = devm_ioremap_resource(dev, res);
+ spi->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spi->base)) {
ret = PTR_ERR(spi->base);
goto error;
@@ -864,7 +862,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(dev, "could not get irq: %d\n", irq);
ret = -ENXIO;
goto error;
}
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 032a615e4ccd..eb9a243e9526 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -139,7 +139,6 @@ static int ath79_spi_probe(struct platform_device *pdev)
struct spi_master *master;
struct ath79_spi *sp;
struct ath79_spi_platform_data *pdata;
- struct resource *r;
unsigned long rate;
int ret;
@@ -169,8 +168,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
sp->bitbang.flags = SPI_CS_HIGH;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sp->base = devm_ioremap_resource(&pdev->dev, r);
+ sp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sp->base)) {
ret = PTR_ERR(sp->base);
goto err_put_master;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index f00b367523cd..acf318e7330c 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -23,6 +23,7 @@
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
+#include <trace/events/spi.h>
/* SPI register offsets */
#define SPI_CR 0x0000
@@ -1409,9 +1410,13 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
msg->actual_length = 0;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+ trace_spi_transfer_start(msg, xfer);
+
ret = atmel_spi_one_transfer(master, msg, xfer);
if (ret)
goto msg_done;
+
+ trace_spi_transfer_stop(msg, xfer);
}
if (as->use_pdc)
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index 3b1833e6c7ad..74842f6019ed 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -460,7 +460,6 @@ static int spi_engine_probe(struct platform_device *pdev)
struct spi_engine *spi_engine;
struct spi_master *master;
unsigned int version;
- struct resource *res;
int irq;
int ret;
@@ -480,8 +479,7 @@ static int spi_engine_probe(struct platform_device *pdev)
spin_lock_init(&spi_engine->lock);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spi_engine->base = devm_ioremap_resource(&pdev->dev, res);
+ spi_engine->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spi_engine->base)) {
ret = PTR_ERR(spi_engine->base);
goto err_put_master;
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 902bdbfedea8..7a3531856491 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -343,7 +343,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
{
int bpc = 0, bpp = 0;
u8 command = op->cmd.opcode;
- int width = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE;
+ int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE;
int addrlen = op->addr.nbytes;
int flex_mode = 1;
@@ -897,6 +897,7 @@ static int bcm_qspi_transfer_one(struct spi_master *master,
read_from_hw(qspi, slots);
}
+ bcm_qspi_enable_bspi(qspi);
return 0;
}
@@ -981,7 +982,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem,
if (mspi_read)
return bcm_qspi_mspi_exec_mem_op(spi, op);
- ret = bcm_qspi_bspi_set_mode(qspi, op, -1);
+ ret = bcm_qspi_bspi_set_mode(qspi, op, 0);
if (!ret)
ret = bcm_qspi_bspi_exec_mem_op(spi, op);
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 6f243a90c844..b4070c0de3df 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -25,7 +25,9 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h> /* FIXME: using chip internals */
+#include <linux/gpio/driver.h> /* FIXME: using chip internals */
#include <linux/of_irq.h>
#include <linux/spi/spi.h>
@@ -66,6 +68,7 @@
#define BCM2835_SPI_FIFO_SIZE 64
#define BCM2835_SPI_FIFO_SIZE_3_4 48
#define BCM2835_SPI_DMA_MIN_LENGTH 96
+#define BCM2835_SPI_NUM_CS 3 /* raise as necessary */
#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
| SPI_NO_CS | SPI_3WIRE)
@@ -92,7 +95,8 @@ MODULE_PARM_DESC(polling_limit_us,
* @rx_prologue: bytes received without DMA if first RX sglist entry's
* length is not a multiple of 4 (to overcome hardware limitation)
* @tx_spillover: whether @tx_prologue spills over to second TX sglist entry
- * @dma_pending: whether a DMA transfer is in progress
+ * @prepare_cs: precalculated CS register value for ->prepare_message()
+ * (uses slave-specific clock polarity and phase settings)
* @debugfs_dir: the debugfs directory - neede to remove debugfs when
* unloading the module
* @count_transfer_polling: count of how often polling mode is used
@@ -102,6 +106,19 @@ MODULE_PARM_DESC(polling_limit_us,
* These are counted as well in @count_transfer_polling and
* @count_transfer_irq
* @count_transfer_dma: count how often dma mode is used
+ * @chip_select: SPI slave currently selected
+ * (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs)
+ * @tx_dma_active: whether a TX DMA descriptor is in progress
+ * @rx_dma_active: whether a RX DMA descriptor is in progress
+ * (used by bcm2835_spi_dma_tx_done() to handle a race)
+ * @fill_tx_desc: preallocated TX DMA descriptor used for RX-only transfers
+ * (cyclically copies from zero page to TX FIFO)
+ * @fill_tx_addr: bus address of zero page
+ * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers
+ * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register)
+ * @clear_rx_addr: bus address of @clear_rx_cs
+ * @clear_rx_cs: precalculated CS register value to clear RX FIFO
+ * (uses slave-specific clock polarity and phase settings)
*/
struct bcm2835_spi {
void __iomem *regs;
@@ -115,13 +132,22 @@ struct bcm2835_spi {
int tx_prologue;
int rx_prologue;
unsigned int tx_spillover;
- unsigned int dma_pending;
+ u32 prepare_cs[BCM2835_SPI_NUM_CS];
struct dentry *debugfs_dir;
u64 count_transfer_polling;
u64 count_transfer_irq;
u64 count_transfer_irq_after_polling;
u64 count_transfer_dma;
+
+ u8 chip_select;
+ unsigned int tx_dma_active;
+ unsigned int rx_dma_active;
+ struct dma_async_tx_descriptor *fill_tx_desc;
+ dma_addr_t fill_tx_addr;
+ struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS];
+ dma_addr_t clear_rx_addr;
+ u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned;
};
#if defined(CONFIG_DEBUG_FS)
@@ -319,6 +345,13 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr)
BCM2835_SPI_CS_INTD |
BCM2835_SPI_CS_DMAEN |
BCM2835_SPI_CS_TA);
+ /*
+ * Transmission sometimes breaks unless the DONE bit is written at the
+ * end of every transfer. The spec says it's a RO bit. Either the
+ * spec is wrong and the bit is actually of type RW1C, or it's a
+ * hardware erratum.
+ */
+ cs |= BCM2835_SPI_CS_DONE;
/* and reset RX/TX FIFOS */
cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX;
@@ -448,14 +481,14 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr,
bs->rx_prologue = 0;
bs->tx_spillover = false;
- if (!sg_is_last(&tfr->tx_sg.sgl[0]))
+ if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0]))
bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3;
- if (!sg_is_last(&tfr->rx_sg.sgl[0])) {
+ if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) {
bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3;
if (bs->rx_prologue > bs->tx_prologue) {
- if (sg_is_last(&tfr->tx_sg.sgl[0])) {
+ if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) {
bs->tx_prologue = bs->rx_prologue;
} else {
bs->tx_prologue += 4;
@@ -477,7 +510,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr,
bcm2835_wr_fifo_count(bs, bs->rx_prologue);
bcm2835_wait_tx_fifo_empty(bs);
bcm2835_rd_fifo_count(bs, bs->rx_prologue);
- bcm2835_spi_reset_hw(ctlr);
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX
+ | BCM2835_SPI_CS_CLEAR_TX
+ | BCM2835_SPI_CS_DONE);
dma_sync_single_for_device(ctlr->dma_rx->device->dev,
sg_dma_address(&tfr->rx_sg.sgl[0]),
@@ -487,6 +522,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr,
sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue;
}
+ if (!bs->tx_buf)
+ return;
+
/*
* Write remaining TX prologue. Adjust first entry in TX sglist.
* Also adjust second entry if prologue spills over to it.
@@ -498,7 +536,8 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr,
| BCM2835_SPI_CS_DMAEN);
bcm2835_wr_fifo_count(bs, tx_remaining);
bcm2835_wait_tx_fifo_empty(bs);
- bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX);
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX
+ | BCM2835_SPI_CS_DONE);
}
if (likely(!bs->tx_spillover)) {
@@ -531,6 +570,9 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs)
sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue;
}
+ if (!bs->tx_buf)
+ goto out;
+
if (likely(!bs->tx_spillover)) {
sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue;
sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue;
@@ -539,32 +581,85 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs)
sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4;
sg_dma_len(&tfr->tx_sg.sgl[1]) += 4;
}
+out:
+ bs->tx_prologue = 0;
}
-static void bcm2835_spi_dma_done(void *data)
+/**
+ * bcm2835_spi_dma_rx_done() - callback for DMA RX channel
+ * @data: SPI master controller
+ *
+ * Used for bidirectional and RX-only transfers.
+ */
+static void bcm2835_spi_dma_rx_done(void *data)
{
struct spi_controller *ctlr = data;
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
- /* reset fifo and HW */
- bcm2835_spi_reset_hw(ctlr);
-
- /* and terminate tx-dma as we do not have an irq for it
+ /* terminate tx-dma as we do not have an irq for it
* because when the rx dma will terminate and this callback
* is called the tx-dma must have finished - can't get to this
* situation otherwise...
*/
- if (cmpxchg(&bs->dma_pending, true, false)) {
- dmaengine_terminate_async(ctlr->dma_tx);
- bcm2835_spi_undo_prologue(bs);
- }
+ dmaengine_terminate_async(ctlr->dma_tx);
+ bs->tx_dma_active = false;
+ bs->rx_dma_active = false;
+ bcm2835_spi_undo_prologue(bs);
+
+ /* reset fifo and HW */
+ bcm2835_spi_reset_hw(ctlr);
/* and mark as completed */;
complete(&ctlr->xfer_completion);
}
+/**
+ * bcm2835_spi_dma_tx_done() - callback for DMA TX channel
+ * @data: SPI master controller
+ *
+ * Used for TX-only transfers.
+ */
+static void bcm2835_spi_dma_tx_done(void *data)
+{
+ struct spi_controller *ctlr = data;
+ struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+
+ /* busy-wait for TX FIFO to empty */
+ while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE))
+ bcm2835_wr(bs, BCM2835_SPI_CS,
+ bs->clear_rx_cs[bs->chip_select]);
+
+ bs->tx_dma_active = false;
+ smp_wmb();
+
+ /*
+ * In case of a very short transfer, RX DMA may not have been
+ * issued yet. The onus is then on bcm2835_spi_transfer_one_dma()
+ * to terminate it immediately after issuing.
+ */
+ if (cmpxchg(&bs->rx_dma_active, true, false))
+ dmaengine_terminate_async(ctlr->dma_rx);
+
+ bcm2835_spi_undo_prologue(bs);
+ bcm2835_spi_reset_hw(ctlr);
+ complete(&ctlr->xfer_completion);
+}
+
+/**
+ * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist
+ * @ctlr: SPI master controller
+ * @spi: SPI slave
+ * @tfr: SPI transfer
+ * @bs: BCM2835 SPI controller
+ * @is_tx: whether to submit DMA descriptor for TX or RX sglist
+ *
+ * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr.
+ * Return 0 on success or a negative error number.
+ */
static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
+ struct spi_device *spi,
struct spi_transfer *tfr,
+ struct bcm2835_spi *bs,
bool is_tx)
{
struct dma_chan *chan;
@@ -581,8 +676,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
chan = ctlr->dma_tx;
nents = tfr->tx_sg.nents;
sgl = tfr->tx_sg.sgl;
- flags = 0 /* no tx interrupt */;
-
+ flags = tfr->rx_buf ? 0 : DMA_PREP_INTERRUPT;
} else {
dir = DMA_DEV_TO_MEM;
chan = ctlr->dma_rx;
@@ -595,10 +689,17 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
if (!desc)
return -EINVAL;
- /* set callback for rx */
+ /*
+ * Completion is signaled by the RX channel for bidirectional and
+ * RX-only transfers; else by the TX channel for TX-only transfers.
+ */
if (!is_tx) {
- desc->callback = bcm2835_spi_dma_done;
+ desc->callback = bcm2835_spi_dma_rx_done;
+ desc->callback_param = ctlr;
+ } else if (!tfr->rx_buf) {
+ desc->callback = bcm2835_spi_dma_tx_done;
desc->callback_param = ctlr;
+ bs->chip_select = spi->chip_select;
}
/* submit it to DMA-engine */
@@ -607,12 +708,60 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
return dma_submit_error(cookie);
}
+/**
+ * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine
+ * @ctlr: SPI master controller
+ * @spi: SPI slave
+ * @tfr: SPI transfer
+ * @cs: CS register
+ *
+ * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up
+ * the TX and RX DMA channel to copy between memory and FIFO register.
+ *
+ * For *TX-only* transfers (rx_buf is %NULL), copying the RX FIFO's contents to
+ * memory is pointless. However not reading the RX FIFO isn't an option either
+ * because transmission is halted once it's full. As a workaround, cyclically
+ * clear the RX FIFO by setting the CLEAR_RX bit in the CS register.
+ *
+ * The CS register value is precalculated in bcm2835_spi_setup(). Normally
+ * this is called only once, on slave registration. A DMA descriptor to write
+ * this value is preallocated in bcm2835_dma_init(). All that's left to do
+ * when performing a TX-only transfer is to submit this descriptor to the RX
+ * DMA channel. Latency is thereby minimized. The descriptor does not
+ * generate any interrupts while running. It must be terminated once the
+ * TX DMA channel is done.
+ *
+ * Clearing the RX FIFO is paced by the DREQ signal. The signal is asserted
+ * when the RX FIFO becomes half full, i.e. 32 bytes. (Tuneable with the DC
+ * register.) Reading 32 bytes from the RX FIFO would normally require 8 bus
+ * accesses, whereas clearing it requires only 1 bus access. So an 8-fold
+ * reduction in bus traffic and thus energy consumption is achieved.
+ *
+ * For *RX-only* transfers (tx_buf is %NULL), fill the TX FIFO by cyclically
+ * copying from the zero page. The DMA descriptor to do this is preallocated
+ * in bcm2835_dma_init(). It must be terminated once the RX DMA channel is
+ * done and can then be reused.
+ *
+ * The BCM2835 DMA driver autodetects when a transaction copies from the zero
+ * page and utilizes the DMA controller's ability to synthesize zeroes instead
+ * of copying them from memory. This reduces traffic on the memory bus. The
+ * feature is not available on so-called "lite" channels, but normally TX DMA
+ * is backed by a full-featured channel.
+ *
+ * Zero-filling the TX FIFO is paced by the DREQ signal. Unfortunately the
+ * BCM2835 SPI controller continues to assert DREQ even after the DLEN register
+ * has been counted down to zero (hardware erratum). Thus, when the transfer
+ * has finished, the DMA engine zero-fills the TX FIFO until it is half full.
+ * (Tuneable with the DC register.) So up to 9 gratuitous bus accesses are
+ * performed at the end of an RX-only transfer.
+ */
static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
struct spi_device *spi,
struct spi_transfer *tfr,
u32 cs)
{
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+ dma_cookie_t cookie;
int ret;
/* update usage statistics */
@@ -625,16 +774,15 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs);
/* setup tx-DMA */
- ret = bcm2835_spi_prepare_sg(ctlr, tfr, true);
+ if (bs->tx_buf) {
+ ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true);
+ } else {
+ cookie = dmaengine_submit(bs->fill_tx_desc);
+ ret = dma_submit_error(cookie);
+ }
if (ret)
goto err_reset_hw;
- /* start TX early */
- dma_async_issue_pending(ctlr->dma_tx);
-
- /* mark as dma pending */
- bs->dma_pending = 1;
-
/* set the DMA length */
bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len);
@@ -642,20 +790,43 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
bcm2835_wr(bs, BCM2835_SPI_CS,
cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN);
+ bs->tx_dma_active = true;
+ smp_wmb();
+
+ /* start TX early */
+ dma_async_issue_pending(ctlr->dma_tx);
+
/* setup rx-DMA late - to run transfers while
* mapping of the rx buffers still takes place
* this saves 10us or more.
*/
- ret = bcm2835_spi_prepare_sg(ctlr, tfr, false);
+ if (bs->rx_buf) {
+ ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, false);
+ } else {
+ cookie = dmaengine_submit(bs->clear_rx_desc[spi->chip_select]);
+ ret = dma_submit_error(cookie);
+ }
if (ret) {
/* need to reset on errors */
dmaengine_terminate_sync(ctlr->dma_tx);
- bs->dma_pending = false;
+ bs->tx_dma_active = false;
goto err_reset_hw;
}
/* start rx dma late */
dma_async_issue_pending(ctlr->dma_rx);
+ bs->rx_dma_active = true;
+ smp_mb();
+
+ /*
+ * In case of a very short TX-only transfer, bcm2835_spi_dma_tx_done()
+ * may run before RX DMA is issued. Terminate RX DMA if so.
+ */
+ if (!bs->rx_buf && !bs->tx_dma_active &&
+ cmpxchg(&bs->rx_dma_active, true, false)) {
+ dmaengine_terminate_async(ctlr->dma_rx);
+ bcm2835_spi_reset_hw(ctlr);
+ }
/* wait for wakeup in framework */
return 1;
@@ -678,26 +849,52 @@ static bool bcm2835_spi_can_dma(struct spi_controller *ctlr,
return true;
}
-static void bcm2835_dma_release(struct spi_controller *ctlr)
+static void bcm2835_dma_release(struct spi_controller *ctlr,
+ struct bcm2835_spi *bs)
{
+ int i;
+
if (ctlr->dma_tx) {
dmaengine_terminate_sync(ctlr->dma_tx);
+
+ if (bs->fill_tx_desc)
+ dmaengine_desc_free(bs->fill_tx_desc);
+
+ if (bs->fill_tx_addr)
+ dma_unmap_page_attrs(ctlr->dma_tx->device->dev,
+ bs->fill_tx_addr, sizeof(u32),
+ DMA_TO_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+
dma_release_channel(ctlr->dma_tx);
ctlr->dma_tx = NULL;
}
+
if (ctlr->dma_rx) {
dmaengine_terminate_sync(ctlr->dma_rx);
+
+ for (i = 0; i < BCM2835_SPI_NUM_CS; i++)
+ if (bs->clear_rx_desc[i])
+ dmaengine_desc_free(bs->clear_rx_desc[i]);
+
+ if (bs->clear_rx_addr)
+ dma_unmap_single(ctlr->dma_rx->device->dev,
+ bs->clear_rx_addr,
+ sizeof(bs->clear_rx_cs),
+ DMA_TO_DEVICE);
+
dma_release_channel(ctlr->dma_rx);
ctlr->dma_rx = NULL;
}
}
-static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev)
+static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
+ struct bcm2835_spi *bs)
{
struct dma_slave_config slave_config;
const __be32 *addr;
dma_addr_t dma_reg_base;
- int ret;
+ int ret, i;
/* base address in dma-space */
addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL);
@@ -719,7 +916,11 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev)
goto err_release;
}
- /* configure DMAs */
+ /*
+ * The TX DMA channel either copies a transfer's TX buffer to the FIFO
+ * or, in case of an RX-only transfer, cyclically copies from the zero
+ * page to the FIFO using a preallocated, reusable descriptor.
+ */
slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO);
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -727,17 +928,74 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev)
if (ret)
goto err_config;
+ bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev,
+ ZERO_PAGE(0), 0, sizeof(u32),
+ DMA_TO_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) {
+ dev_err(dev, "cannot map zero page - not using DMA mode\n");
+ bs->fill_tx_addr = 0;
+ goto err_release;
+ }
+
+ bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx,
+ bs->fill_tx_addr,
+ sizeof(u32), 0,
+ DMA_MEM_TO_DEV, 0);
+ if (!bs->fill_tx_desc) {
+ dev_err(dev, "cannot prepare fill_tx_desc - not using DMA mode\n");
+ goto err_release;
+ }
+
+ ret = dmaengine_desc_set_reuse(bs->fill_tx_desc);
+ if (ret) {
+ dev_err(dev, "cannot reuse fill_tx_desc - not using DMA mode\n");
+ goto err_release;
+ }
+
+ /*
+ * The RX DMA channel is used bidirectionally: It either reads the
+ * RX FIFO or, in case of a TX-only transfer, cyclically writes a
+ * precalculated value to the CS register to clear the RX FIFO.
+ */
slave_config.src_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO);
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_CS);
+ slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ret = dmaengine_slave_config(ctlr->dma_rx, &slave_config);
if (ret)
goto err_config;
+ bs->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev,
+ bs->clear_rx_cs,
+ sizeof(bs->clear_rx_cs),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(ctlr->dma_rx->device->dev, bs->clear_rx_addr)) {
+ dev_err(dev, "cannot map clear_rx_cs - not using DMA mode\n");
+ bs->clear_rx_addr = 0;
+ goto err_release;
+ }
+
+ for (i = 0; i < BCM2835_SPI_NUM_CS; i++) {
+ bs->clear_rx_desc[i] = dmaengine_prep_dma_cyclic(ctlr->dma_rx,
+ bs->clear_rx_addr + i * sizeof(u32),
+ sizeof(u32), 0,
+ DMA_MEM_TO_DEV, 0);
+ if (!bs->clear_rx_desc[i]) {
+ dev_err(dev, "cannot prepare clear_rx_desc - not using DMA mode\n");
+ goto err_release;
+ }
+
+ ret = dmaengine_desc_set_reuse(bs->clear_rx_desc[i]);
+ if (ret) {
+ dev_err(dev, "cannot reuse clear_rx_desc - not using DMA mode\n");
+ goto err_release;
+ }
+ }
+
/* all went well, so set can_dma */
ctlr->can_dma = bcm2835_spi_can_dma;
- /* need to do TX AND RX DMA, so we need dummy buffers */
- ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
return;
@@ -745,7 +1003,7 @@ err_config:
dev_err(dev, "issue configuring dma: %d - not using DMA mode\n",
ret);
err_release:
- bcm2835_dma_release(ctlr);
+ bcm2835_dma_release(ctlr, bs);
err:
return;
}
@@ -812,7 +1070,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
unsigned long spi_hz, clk_hz, cdiv, spi_used_hz;
unsigned long hz_per_byte, byte_limit;
- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+ u32 cs = bs->prepare_cs[spi->chip_select];
/* set clock */
spi_hz = tfr->speed_hz;
@@ -834,17 +1092,8 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
/* handle all the 3-wire mode */
- if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
+ if (spi->mode & SPI_3WIRE && tfr->rx_buf)
cs |= BCM2835_SPI_CS_REN;
- else
- cs &= ~BCM2835_SPI_CS_REN;
-
- /*
- * The driver always uses software-controlled GPIO Chip Select.
- * Set the hardware-controlled native Chip Select to an invalid
- * value to prevent it from interfering.
- */
- cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
/* set transmit buffers and length */
bs->tx_buf = tfr->tx_buf;
@@ -881,7 +1130,6 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
{
struct spi_device *spi = msg->spi;
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
int ret;
if (ctlr->can_dma) {
@@ -896,14 +1144,11 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
return ret;
}
- cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
-
- if (spi->mode & SPI_CPOL)
- cs |= BCM2835_SPI_CS_CPOL;
- if (spi->mode & SPI_CPHA)
- cs |= BCM2835_SPI_CS_CPHA;
-
- bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+ /*
+ * Set up clock polarity before spi_transfer_one_message() asserts
+ * chip select to avoid a gratuitous clock signal edge.
+ */
+ bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]);
return 0;
}
@@ -914,11 +1159,12 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr,
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
/* if an error occurred and we have an active dma, then terminate */
- if (cmpxchg(&bs->dma_pending, true, false)) {
- dmaengine_terminate_sync(ctlr->dma_tx);
- dmaengine_terminate_sync(ctlr->dma_rx);
- bcm2835_spi_undo_prologue(bs);
- }
+ dmaengine_terminate_sync(ctlr->dma_tx);
+ bs->tx_dma_active = false;
+ dmaengine_terminate_sync(ctlr->dma_rx);
+ bs->rx_dma_active = false;
+ bcm2835_spi_undo_prologue(bs);
+
/* and reset */
bcm2835_spi_reset_hw(ctlr);
}
@@ -930,14 +1176,50 @@ static int chip_match_name(struct gpio_chip *chip, void *data)
static int bcm2835_spi_setup(struct spi_device *spi)
{
- int err;
+ struct spi_controller *ctlr = spi->controller;
+ struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
struct gpio_chip *chip;
+ enum gpio_lookup_flags lflags;
+ u32 cs;
+
+ /*
+ * Precalculate SPI slave's CS register value for ->prepare_message():
+ * The driver always uses software-controlled GPIO chip select, hence
+ * set the hardware-controlled native chip select to an invalid value
+ * to prevent it from interfering.
+ */
+ cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
+ if (spi->mode & SPI_CPOL)
+ cs |= BCM2835_SPI_CS_CPOL;
+ if (spi->mode & SPI_CPHA)
+ cs |= BCM2835_SPI_CS_CPHA;
+ bs->prepare_cs[spi->chip_select] = cs;
+
+ /*
+ * Precalculate SPI slave's CS register value to clear RX FIFO
+ * in case of a TX-only DMA transfer.
+ */
+ if (ctlr->dma_rx) {
+ bs->clear_rx_cs[spi->chip_select] = cs |
+ BCM2835_SPI_CS_TA |
+ BCM2835_SPI_CS_DMAEN |
+ BCM2835_SPI_CS_CLEAR_RX;
+ dma_sync_single_for_device(ctlr->dma_rx->device->dev,
+ bs->clear_rx_addr,
+ sizeof(bs->clear_rx_cs),
+ DMA_TO_DEVICE);
+ }
+
/*
* sanity checking the native-chipselects
*/
if (spi->mode & SPI_NO_CS)
return 0;
- if (gpio_is_valid(spi->cs_gpio))
+ /*
+ * The SPI core has successfully requested the CS GPIO line from the
+ * device tree, so we are done.
+ */
+ if (spi->cs_gpiod)
return 0;
if (spi->chip_select > 1) {
/* error in the case of native CS requested with CS > 1
@@ -948,29 +1230,43 @@ static int bcm2835_spi_setup(struct spi_device *spi)
"setup: only two native chip-selects are supported\n");
return -EINVAL;
}
- /* now translate native cs to GPIO */
+
+ /*
+ * Translate native CS to GPIO
+ *
+ * FIXME: poking around in the gpiolib internals like this is
+ * not very good practice. Find a way to locate the real problem
+ * and fix it. Why is the GPIO descriptor in spi->cs_gpiod
+ * sometimes not assigned correctly? Erroneous device trees?
+ */
/* get the gpio chip for the base */
chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
if (!chip)
return 0;
- /* and calculate the real CS */
- spi->cs_gpio = chip->base + 8 - spi->chip_select;
+ /*
+ * Retrieve the corresponding GPIO line used for CS.
+ * The inversion semantics will be handled by the GPIO core
+ * code, so we pass GPIOS_OUT_LOW for "unasserted" and
+ * the correct flag for inversion semantics. The SPI_CS_HIGH
+ * on spi->mode cannot be checked for polarity in this case
+ * as the flag use_gpio_descriptors enforces SPI_CS_HIGH.
+ */
+ if (of_property_read_bool(spi->dev.of_node, "spi-cs-high"))
+ lflags = GPIO_ACTIVE_HIGH;
+ else
+ lflags = GPIO_ACTIVE_LOW;
+ spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select,
+ DRV_NAME,
+ lflags,
+ GPIOD_OUT_LOW);
+ if (IS_ERR(spi->cs_gpiod))
+ return PTR_ERR(spi->cs_gpiod);
/* and set up the "mode" and level */
- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",
- spi->chip_select, spi->cs_gpio);
-
- /* set up GPIO as output and pull to the correct level */
- err = gpio_direction_output(spi->cs_gpio,
- (spi->mode & SPI_CS_HIGH) ? 0 : 1);
- if (err) {
- dev_err(&spi->dev,
- "could not set CS%i gpio %i as output: %i",
- spi->chip_select, spi->cs_gpio, err);
- return err;
- }
+ dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n",
+ spi->chip_select);
return 0;
}
@@ -979,18 +1275,19 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
{
struct spi_controller *ctlr;
struct bcm2835_spi *bs;
- struct resource *res;
int err;
- ctlr = spi_alloc_master(&pdev->dev, sizeof(*bs));
+ ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
+ dma_get_cache_alignment()));
if (!ctlr)
return -ENOMEM;
platform_set_drvdata(pdev, ctlr);
+ ctlr->use_gpio_descriptors = true;
ctlr->mode_bits = BCM2835_SPI_MODE_BITS;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
- ctlr->num_chipselect = 3;
+ ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
ctlr->setup = bcm2835_spi_setup;
ctlr->transfer_one = bcm2835_spi_transfer_one;
ctlr->handle_err = bcm2835_spi_handle_err;
@@ -999,8 +1296,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
bs = spi_controller_get_devdata(ctlr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- bs->regs = devm_ioremap_resource(&pdev->dev, res);
+ bs->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bs->regs)) {
err = PTR_ERR(bs->regs);
goto out_controller_put;
@@ -1015,14 +1311,13 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
bs->irq = platform_get_irq(pdev, 0);
if (bs->irq <= 0) {
- dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
err = bs->irq ? bs->irq : -ENODEV;
goto out_controller_put;
}
clk_prepare_enable(bs->clk);
- bcm2835_dma_init(ctlr, &pdev->dev);
+ bcm2835_dma_init(ctlr, &pdev->dev, bs);
/* initialise the hardware with the default polarities */
bcm2835_wr(bs, BCM2835_SPI_CS,
@@ -1066,7 +1361,7 @@ static int bcm2835_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(bs->clk);
- bcm2835_dma_release(ctlr);
+ bcm2835_dma_release(ctlr, bs);
return 0;
}
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index bb57035c5770..a2162ff56a12 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -491,7 +491,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct bcm2835aux_spi *bs;
- struct resource *res;
unsigned long clk_hz;
int err;
@@ -524,8 +523,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
bs = spi_master_get_devdata(master);
/* the main area */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- bs->regs = devm_ioremap_resource(&pdev->dev, res);
+ bs->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bs->regs)) {
err = PTR_ERR(bs->regs);
goto out_master_put;
@@ -540,7 +538,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
bs->irq = platform_get_irq(pdev, 0);
if (bs->irq <= 0) {
- dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
err = bs->irq ? bs->irq : -ENODEV;
goto out_master_put;
}
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 9a06ffdb73b8..c6836a931dbf 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -330,7 +330,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct bcm63xx_hsspi *bs;
- struct resource *res_mem;
void __iomem *regs;
struct device *dev = &pdev->dev;
struct clk *clk, *pll_clk = NULL;
@@ -338,13 +337,10 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "no irq: %d\n", irq);
+ if (irq < 0)
return irq;
- }
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(dev, res_mem);
+ regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index df1c94a131e6..fdd7eaa0b8ed 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -520,10 +520,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "no irq: %d\n", irq);
+ if (irq < 0)
return irq;
- }
clk = devm_clk_get(dev, "spi");
if (IS_ERR(clk)) {
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 7c41e4e82849..c36587b42e95 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -474,7 +474,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
int ret = 0, irq;
struct spi_master *master;
struct cdns_spi *xspi;
- struct resource *res;
u32 num_cs;
master = spi_alloc_master(&pdev->dev, sizeof(*xspi));
@@ -485,8 +484,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
master->dev.of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xspi->regs = devm_ioremap_resource(&pdev->dev, res);
+ xspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xspi->regs)) {
ret = PTR_ERR(xspi->regs);
goto remove_master;
@@ -540,7 +538,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
ret = -ENXIO;
- dev_err(&pdev->dev, "irq number is invalid\n");
goto clk_dis_all;
}
diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c
index ee4703e84622..1a2de6ce9064 100644
--- a/drivers/spi/spi-cavium-octeon.c
+++ b/drivers/spi/spi-cavium-octeon.c
@@ -18,7 +18,6 @@
static int octeon_spi_probe(struct platform_device *pdev)
{
- struct resource *res_mem;
void __iomem *reg_base;
struct spi_master *master;
struct octeon_spi *p;
@@ -30,8 +29,7 @@ static int octeon_spi_probe(struct platform_device *pdev)
p = spi_master_get_devdata(master);
platform_set_drvdata(pdev, master);
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg_base)) {
err = PTR_ERR(reg_base);
goto fail;
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 4daba12ec843..5e900f228919 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -91,7 +91,6 @@ static int spi_clps711x_probe(struct platform_device *pdev)
{
struct spi_clps711x_data *hw;
struct spi_master *master;
- struct resource *res;
int irq, ret;
irq = platform_get_irq(pdev, 0);
@@ -125,8 +124,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
goto err_out;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hw->syncio = devm_ioremap_resource(&pdev->dev, res);
+ hw->syncio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->syncio)) {
ret = PTR_ERR(hw->syncio);
goto err_out;
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index 5ff48ab2f534..f80e06c87fbe 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -339,7 +339,6 @@ static int mcfqspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct mcfqspi *mcfqspi;
- struct resource *res;
struct mcfqspi_platform_data *pdata;
int status;
@@ -362,8 +361,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
mcfqspi = spi_master_get_devdata(master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res);
+ mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mcfqspi->iobase)) {
status = PTR_ERR(mcfqspi->iobase);
goto fail0;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 18c06568805e..bd46fca3f094 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -79,14 +79,12 @@ static int dw_spi_mscc_init(struct platform_device *pdev,
const char *cpu_syscon, u32 if_si_owner_offset)
{
struct dw_spi_mscc *dwsmscc;
- struct resource *res;
dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL);
if (!dwsmscc)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- dwsmscc->spi_mst = devm_ioremap_resource(&pdev->dev, res);
+ dwsmscc->spi_mst = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(dwsmscc->spi_mst)) {
dev_err(&pdev->dev, "SPI_MST region map failed\n");
return PTR_ERR(dwsmscc->spi_mst);
@@ -138,7 +136,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
struct dw_spi_mmio *dwsmmio);
struct dw_spi_mmio *dwsmmio;
struct dw_spi *dws;
- struct resource *mem;
int ret;
int num_cs;
@@ -150,18 +147,15 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws = &dwsmmio->dws;
/* Get basic io resource and map it */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dws->regs = devm_ioremap_resource(&pdev->dev, mem);
+ dws->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dws->regs)) {
dev_err(&pdev->dev, "SPI region map failed\n");
return PTR_ERR(dws->regs);
}
dws->irq = platform_get_irq(pdev, 0);
- if (dws->irq < 0) {
- dev_err(&pdev->dev, "no irq resource?\n");
+ if (dws->irq < 0)
return dws->irq; /* -ENXIO */
- }
dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dwsmmio->clk))
@@ -172,8 +166,10 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
/* Optional clock needed to access the registers */
dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk");
- if (IS_ERR(dwsmmio->pclk))
- return PTR_ERR(dwsmmio->pclk);
+ if (IS_ERR(dwsmmio->pclk)) {
+ ret = PTR_ERR(dwsmmio->pclk);
+ goto out_clk;
+ }
ret = clk_prepare_enable(dwsmmio->pclk);
if (ret)
goto out_clk;
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 9651679ee7f7..140644913e6c 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -19,6 +19,7 @@ struct spi_pci_desc {
int (*setup)(struct dw_spi *);
u16 num_cs;
u16 bus_num;
+ u32 max_freq;
};
static struct spi_pci_desc spi_pci_mid_desc_1 = {
@@ -33,6 +34,12 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = {
.bus_num = 1,
};
+static struct spi_pci_desc spi_pci_ehl_desc = {
+ .num_cs = 1,
+ .bus_num = -1,
+ .max_freq = 100000000,
+};
+
static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct dw_spi *dws;
@@ -65,6 +72,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (desc) {
dws->num_cs = desc->num_cs;
dws->bus_num = desc->bus_num;
+ dws->max_freq = desc->max_freq;
if (desc->setup) {
ret = desc->setup(dws);
@@ -98,16 +106,14 @@ static void spi_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM_SLEEP
static int spi_suspend(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_spi *dws = pci_get_drvdata(pdev);
+ struct dw_spi *dws = dev_get_drvdata(dev);
return dw_spi_suspend_host(dws);
}
static int spi_resume(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_spi *dws = pci_get_drvdata(pdev);
+ struct dw_spi *dws = dev_get_drvdata(dev);
return dw_spi_resume_host(dws);
}
@@ -125,8 +131,14 @@ static const struct pci_device_id pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc_1},
/* Intel MID platform SPI controller 2 */
{ PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&spi_pci_mid_desc_2},
+ /* Intel Elkhart Lake PSE SPI controllers */
+ { PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&spi_pci_ehl_desc},
+ { PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&spi_pci_ehl_desc},
+ { PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&spi_pci_ehl_desc},
+ { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc},
{},
};
+MODULE_DEVICE_TABLE(pci, pci_ids);
static struct pci_driver dw_spi_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c
index eb1f2142a335..64d4c441b641 100644
--- a/drivers/spi/spi-efm32.c
+++ b/drivers/spi/spi-efm32.c
@@ -400,10 +400,8 @@ static int efm32_spi_probe(struct platform_device *pdev)
}
ret = platform_get_irq(pdev, 0);
- if (ret <= 0) {
- dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret);
+ if (ret <= 0)
goto err;
- }
ddata->rxirq = ret;
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 4034e3ec0ba2..4e1ccd4e52b6 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -656,10 +656,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get irq resources\n");
+ if (irq < 0)
return -EBUSY;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
index e967ac564761..858f0544289e 100644
--- a/drivers/spi/spi-fsl-cpm.c
+++ b/drivers/spi/spi-fsl-cpm.c
@@ -305,12 +305,10 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
}
if (mspi->flags & SPI_CPM1) {
- struct resource *res;
void *pram;
- res = platform_get_resource(to_platform_device(dev),
- IORESOURCE_MEM, 1);
- pram = devm_ioremap_resource(dev, res);
+ pram = devm_platform_ioremap_resource(to_platform_device(dev),
+ 1);
if (IS_ERR(pram))
mspi->pram = NULL;
else
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 53335ccc98f6..bec758e978fb 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -9,26 +9,16 @@
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/math64.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/pm_runtime.h>
#include <linux/regmap.h>
-#include <linux/sched.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-fsl-dspi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/time.h>
-#define DRIVER_NAME "fsl-dspi"
+#define DRIVER_NAME "fsl-dspi"
#ifdef CONFIG_M5441x
#define DSPI_FIFO_SIZE 16
@@ -37,101 +27,97 @@
#endif
#define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024)
-#define SPI_MCR 0x00
-#define SPI_MCR_MASTER (1 << 31)
-#define SPI_MCR_PCSIS (0x3F << 16)
-#define SPI_MCR_CLR_TXF (1 << 11)
-#define SPI_MCR_CLR_RXF (1 << 10)
-#define SPI_MCR_XSPI (1 << 3)
-
-#define SPI_TCR 0x08
-#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16)
-
-#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4))
-#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27)
-#define SPI_CTAR_CPOL(x) ((x) << 26)
-#define SPI_CTAR_CPHA(x) ((x) << 25)
-#define SPI_CTAR_LSBFE(x) ((x) << 24)
-#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22)
-#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20)
-#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18)
-#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16)
-#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12)
-#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8)
-#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4)
-#define SPI_CTAR_BR(x) ((x) & 0x0000000f)
-#define SPI_CTAR_SCALE_BITS 0xf
-
-#define SPI_CTAR0_SLAVE 0x0c
-
-#define SPI_SR 0x2c
-#define SPI_SR_EOQF 0x10000000
-#define SPI_SR_TCFQF 0x80000000
-#define SPI_SR_CLEAR 0x9aaf0000
-
-#define SPI_RSER_TFFFE BIT(25)
-#define SPI_RSER_TFFFD BIT(24)
-#define SPI_RSER_RFDFE BIT(17)
-#define SPI_RSER_RFDFD BIT(16)
-
-#define SPI_RSER 0x30
-#define SPI_RSER_EOQFE 0x10000000
-#define SPI_RSER_TCFQE 0x80000000
-
-#define SPI_PUSHR 0x34
-#define SPI_PUSHR_CMD_CONT (1 << 15)
-#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16)
-#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12)
-#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16)
-#define SPI_PUSHR_CMD_EOQ (1 << 11)
-#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16)
-#define SPI_PUSHR_CMD_CTCNT (1 << 10)
-#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16)
-#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f)
-#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16)
-#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff)
-
-#define SPI_PUSHR_SLAVE 0x34
-
-#define SPI_POPR 0x38
-#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff)
-
-#define SPI_TXFR0 0x3c
-#define SPI_TXFR1 0x40
-#define SPI_TXFR2 0x44
-#define SPI_TXFR3 0x48
-#define SPI_RXFR0 0x7c
-#define SPI_RXFR1 0x80
-#define SPI_RXFR2 0x84
-#define SPI_RXFR3 0x88
-
-#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4))
-#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16)
-#define SPI_CTARE_DTCP(x) ((x) & 0x7ff)
-
-#define SPI_SREX 0x13c
-
-#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1)
-#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf)
-#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf)
-#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7)
-
-#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4)
-#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1)
+#define SPI_MCR 0x00
+#define SPI_MCR_MASTER BIT(31)
+#define SPI_MCR_PCSIS (0x3F << 16)
+#define SPI_MCR_CLR_TXF BIT(11)
+#define SPI_MCR_CLR_RXF BIT(10)
+#define SPI_MCR_XSPI BIT(3)
+
+#define SPI_TCR 0x08
+#define SPI_TCR_GET_TCNT(x) (((x) & GENMASK(31, 16)) >> 16)
+
+#define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4))
+#define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27))
+#define SPI_CTAR_CPOL BIT(26)
+#define SPI_CTAR_CPHA BIT(25)
+#define SPI_CTAR_LSBFE BIT(24)
+#define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22))
+#define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20))
+#define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18))
+#define SPI_CTAR_PBR(x) (((x) << 16) & GENMASK(17, 16))
+#define SPI_CTAR_CSSCK(x) (((x) << 12) & GENMASK(15, 12))
+#define SPI_CTAR_ASC(x) (((x) << 8) & GENMASK(11, 8))
+#define SPI_CTAR_DT(x) (((x) << 4) & GENMASK(7, 4))
+#define SPI_CTAR_BR(x) ((x) & GENMASK(3, 0))
+#define SPI_CTAR_SCALE_BITS 0xf
+
+#define SPI_CTAR0_SLAVE 0x0c
+
+#define SPI_SR 0x2c
+#define SPI_SR_TCFQF BIT(31)
+#define SPI_SR_EOQF BIT(28)
+#define SPI_SR_TFUF BIT(27)
+#define SPI_SR_TFFF BIT(25)
+#define SPI_SR_CMDTCF BIT(23)
+#define SPI_SR_SPEF BIT(21)
+#define SPI_SR_RFOF BIT(19)
+#define SPI_SR_TFIWF BIT(18)
+#define SPI_SR_RFDF BIT(17)
+#define SPI_SR_CMDFFF BIT(16)
+#define SPI_SR_CLEAR (SPI_SR_TCFQF | SPI_SR_EOQF | \
+ SPI_SR_TFUF | SPI_SR_TFFF | \
+ SPI_SR_CMDTCF | SPI_SR_SPEF | \
+ SPI_SR_RFOF | SPI_SR_TFIWF | \
+ SPI_SR_RFDF | SPI_SR_CMDFFF)
+
+#define SPI_RSER_TFFFE BIT(25)
+#define SPI_RSER_TFFFD BIT(24)
+#define SPI_RSER_RFDFE BIT(17)
+#define SPI_RSER_RFDFD BIT(16)
+
+#define SPI_RSER 0x30
+#define SPI_RSER_TCFQE BIT(31)
+#define SPI_RSER_EOQFE BIT(28)
+
+#define SPI_PUSHR 0x34
+#define SPI_PUSHR_CMD_CONT BIT(15)
+#define SPI_PUSHR_CMD_CTAS(x) (((x) << 12 & GENMASK(14, 12)))
+#define SPI_PUSHR_CMD_EOQ BIT(11)
+#define SPI_PUSHR_CMD_CTCNT BIT(10)
+#define SPI_PUSHR_CMD_PCS(x) (BIT(x) & GENMASK(5, 0))
+
+#define SPI_PUSHR_SLAVE 0x34
+
+#define SPI_POPR 0x38
+
+#define SPI_TXFR0 0x3c
+#define SPI_TXFR1 0x40
+#define SPI_TXFR2 0x44
+#define SPI_TXFR3 0x48
+#define SPI_RXFR0 0x7c
+#define SPI_RXFR1 0x80
+#define SPI_RXFR2 0x84
+#define SPI_RXFR3 0x88
+
+#define SPI_CTARE(x) (0x11c + (((x) & GENMASK(1, 0)) * 4))
+#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16)
+#define SPI_CTARE_DTCP(x) ((x) & 0x7ff)
+
+#define SPI_SREX 0x13c
+
+#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1)
+#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4)
/* Register offsets for regmap_pushr */
-#define PUSHR_CMD 0x0
-#define PUSHR_TX 0x2
+#define PUSHR_CMD 0x0
+#define PUSHR_TX 0x2
-#define SPI_CS_INIT 0x01
-#define SPI_CS_ASSERT 0x02
-#define SPI_CS_DROP 0x04
-
-#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000)
+#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000)
struct chip_data {
- u32 ctar_val;
- u16 void_write_data;
+ u32 ctar_val;
+ u16 void_write_data;
};
enum dspi_trans_mode {
@@ -141,75 +127,75 @@ enum dspi_trans_mode {
};
struct fsl_dspi_devtype_data {
- enum dspi_trans_mode trans_mode;
- u8 max_clock_factor;
- bool xspi_mode;
+ enum dspi_trans_mode trans_mode;
+ u8 max_clock_factor;
+ bool xspi_mode;
};
static const struct fsl_dspi_devtype_data vf610_data = {
- .trans_mode = DSPI_DMA_MODE,
- .max_clock_factor = 2,
+ .trans_mode = DSPI_DMA_MODE,
+ .max_clock_factor = 2,
};
static const struct fsl_dspi_devtype_data ls1021a_v1_data = {
- .trans_mode = DSPI_TCFQ_MODE,
- .max_clock_factor = 8,
- .xspi_mode = true,
+ .trans_mode = DSPI_TCFQ_MODE,
+ .max_clock_factor = 8,
+ .xspi_mode = true,
};
static const struct fsl_dspi_devtype_data ls2085a_data = {
- .trans_mode = DSPI_TCFQ_MODE,
- .max_clock_factor = 8,
+ .trans_mode = DSPI_TCFQ_MODE,
+ .max_clock_factor = 8,
};
static const struct fsl_dspi_devtype_data coldfire_data = {
- .trans_mode = DSPI_EOQ_MODE,
- .max_clock_factor = 8,
+ .trans_mode = DSPI_EOQ_MODE,
+ .max_clock_factor = 8,
};
struct fsl_dspi_dma {
/* Length of transfer in words of DSPI_FIFO_SIZE */
- u32 curr_xfer_len;
-
- u32 *tx_dma_buf;
- struct dma_chan *chan_tx;
- dma_addr_t tx_dma_phys;
- struct completion cmd_tx_complete;
- struct dma_async_tx_descriptor *tx_desc;
-
- u32 *rx_dma_buf;
- struct dma_chan *chan_rx;
- dma_addr_t rx_dma_phys;
- struct completion cmd_rx_complete;
- struct dma_async_tx_descriptor *rx_desc;
+ u32 curr_xfer_len;
+
+ u32 *tx_dma_buf;
+ struct dma_chan *chan_tx;
+ dma_addr_t tx_dma_phys;
+ struct completion cmd_tx_complete;
+ struct dma_async_tx_descriptor *tx_desc;
+
+ u32 *rx_dma_buf;
+ struct dma_chan *chan_rx;
+ dma_addr_t rx_dma_phys;
+ struct completion cmd_rx_complete;
+ struct dma_async_tx_descriptor *rx_desc;
};
struct fsl_dspi {
- struct spi_master *master;
- struct platform_device *pdev;
-
- struct regmap *regmap;
- struct regmap *regmap_pushr;
- int irq;
- struct clk *clk;
-
- struct spi_transfer *cur_transfer;
- struct spi_message *cur_msg;
- struct chip_data *cur_chip;
- size_t len;
- const void *tx;
- void *rx;
- void *rx_end;
- u16 void_write_data;
- u16 tx_cmd;
- u8 bits_per_word;
- u8 bytes_per_word;
- const struct fsl_dspi_devtype_data *devtype_data;
-
- wait_queue_head_t waitq;
- u32 waitflags;
-
- struct fsl_dspi_dma *dma;
+ struct spi_controller *ctlr;
+ struct platform_device *pdev;
+
+ struct regmap *regmap;
+ struct regmap *regmap_pushr;
+ int irq;
+ struct clk *clk;
+
+ struct spi_transfer *cur_transfer;
+ struct spi_message *cur_msg;
+ struct chip_data *cur_chip;
+ size_t len;
+ const void *tx;
+ void *rx;
+ void *rx_end;
+ u16 void_write_data;
+ u16 tx_cmd;
+ u8 bits_per_word;
+ u8 bytes_per_word;
+ const struct fsl_dspi_devtype_data *devtype_data;
+
+ wait_queue_head_t waitq;
+ u32 waitflags;
+
+ struct fsl_dspi_dma *dma;
};
static u32 dspi_pop_tx(struct fsl_dspi *dspi)
@@ -233,7 +219,7 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
{
u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
- if (spi_controller_is_slave(dspi->master))
+ if (spi_controller_is_slave(dspi->ctlr))
return data;
if (dspi->len > 0)
@@ -246,7 +232,7 @@ static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata)
if (!dspi->rx)
return;
- /* Mask of undefined bits */
+ /* Mask off undefined bits */
rxdata &= (1 << dspi->bits_per_word) - 1;
if (dspi->bytes_per_word == 1)
@@ -282,8 +268,8 @@ static void dspi_rx_dma_callback(void *arg)
static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
{
- struct fsl_dspi_dma *dma = dspi->dma;
struct device *dev = &dspi->pdev->dev;
+ struct fsl_dspi_dma *dma = dspi->dma;
int time_left;
int i;
@@ -332,13 +318,13 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
dma_async_issue_pending(dma->chan_rx);
dma_async_issue_pending(dma->chan_tx);
- if (spi_controller_is_slave(dspi->master)) {
+ if (spi_controller_is_slave(dspi->ctlr)) {
wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete);
return 0;
}
time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
- DMA_COMPLETION_TIMEOUT);
+ DMA_COMPLETION_TIMEOUT);
if (time_left == 0) {
dev_err(dev, "DMA tx timeout\n");
dmaengine_terminate_all(dma->chan_tx);
@@ -347,7 +333,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
}
time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete,
- DMA_COMPLETION_TIMEOUT);
+ DMA_COMPLETION_TIMEOUT);
if (time_left == 0) {
dev_err(dev, "DMA rx timeout\n");
dmaengine_terminate_all(dma->chan_tx);
@@ -360,9 +346,9 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
static int dspi_dma_xfer(struct fsl_dspi *dspi)
{
- struct fsl_dspi_dma *dma = dspi->dma;
- struct device *dev = &dspi->pdev->dev;
struct spi_message *message = dspi->cur_msg;
+ struct device *dev = &dspi->pdev->dev;
+ struct fsl_dspi_dma *dma = dspi->dma;
int curr_remaining_bytes;
int bytes_per_buffer;
int ret = 0;
@@ -397,9 +383,9 @@ exit:
static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
{
- struct fsl_dspi_dma *dma;
- struct dma_slave_config cfg;
struct device *dev = &dspi->pdev->dev;
+ struct dma_slave_config cfg;
+ struct fsl_dspi_dma *dma;
int ret;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
@@ -421,14 +407,14 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
}
dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
- &dma->tx_dma_phys, GFP_KERNEL);
+ &dma->tx_dma_phys, GFP_KERNEL);
if (!dma->tx_dma_buf) {
ret = -ENOMEM;
goto err_tx_dma_buf;
}
dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
- &dma->rx_dma_phys, GFP_KERNEL);
+ &dma->rx_dma_phys, GFP_KERNEL);
if (!dma->rx_dma_buf) {
ret = -ENOMEM;
goto err_rx_dma_buf;
@@ -485,30 +471,31 @@ static void dspi_release_dma(struct fsl_dspi *dspi)
struct fsl_dspi_dma *dma = dspi->dma;
struct device *dev = &dspi->pdev->dev;
- if (dma) {
- if (dma->chan_tx) {
- dma_unmap_single(dev, dma->tx_dma_phys,
- DSPI_DMA_BUFSIZE, DMA_TO_DEVICE);
- dma_release_channel(dma->chan_tx);
- }
+ if (!dma)
+ return;
- if (dma->chan_rx) {
- dma_unmap_single(dev, dma->rx_dma_phys,
- DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE);
- dma_release_channel(dma->chan_rx);
- }
+ if (dma->chan_tx) {
+ dma_unmap_single(dev, dma->tx_dma_phys,
+ DSPI_DMA_BUFSIZE, DMA_TO_DEVICE);
+ dma_release_channel(dma->chan_tx);
+ }
+
+ if (dma->chan_rx) {
+ dma_unmap_single(dev, dma->rx_dma_phys,
+ DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE);
+ dma_release_channel(dma->chan_rx);
}
}
static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
- unsigned long clkrate)
+ unsigned long clkrate)
{
/* Valid baud rate pre-scaler values */
int pbr_tbl[4] = {2, 3, 5, 7};
int brs[16] = { 2, 4, 6, 8,
- 16, 32, 64, 128,
- 256, 512, 1024, 2048,
- 4096, 8192, 16384, 32768 };
+ 16, 32, 64, 128,
+ 256, 512, 1024, 2048,
+ 4096, 8192, 16384, 32768 };
int scale_needed, scale, minscale = INT_MAX;
int i, j;
@@ -538,15 +525,15 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
}
static void ns_delay_scale(char *psc, char *sc, int delay_ns,
- unsigned long clkrate)
+ unsigned long clkrate)
{
- int pscale_tbl[4] = {1, 3, 5, 7};
int scale_needed, scale, minscale = INT_MAX;
- int i, j;
+ int pscale_tbl[4] = {1, 3, 5, 7};
u32 remainder;
+ int i, j;
scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
- &remainder);
+ &remainder);
if (remainder)
scale_needed++;
@@ -601,7 +588,7 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi)
*/
u32 data = dspi_pop_tx(dspi);
- if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE(1)) {
+ if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE) {
/* LSB */
tx_fifo_write(dspi, data & 0xFFFF);
tx_fifo_write(dspi, data >> 16);
@@ -655,19 +642,90 @@ static void dspi_eoq_read(struct fsl_dspi *dspi)
{
int fifo_size = DSPI_FIFO_SIZE;
- /* Read one FIFO entry at and push to rx buffer */
+ /* Read one FIFO entry and push to rx buffer */
while ((dspi->rx < dspi->rx_end) && fifo_size--)
dspi_push_rx(dspi, fifo_read(dspi));
}
-static int dspi_transfer_one_message(struct spi_master *master,
- struct spi_message *message)
+static int dspi_rxtx(struct fsl_dspi *dspi)
{
- struct fsl_dspi *dspi = spi_master_get_devdata(master);
+ struct spi_message *msg = dspi->cur_msg;
+ enum dspi_trans_mode trans_mode;
+ u16 spi_tcnt;
+ u32 spi_tcr;
+
+ /* Get transfer counter (in number of SPI transfers). It was
+ * reset to 0 when transfer(s) were started.
+ */
+ regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
+ spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
+ /* Update total number of bytes that were transferred */
+ msg->actual_length += spi_tcnt * dspi->bytes_per_word;
+
+ trans_mode = dspi->devtype_data->trans_mode;
+ if (trans_mode == DSPI_EOQ_MODE)
+ dspi_eoq_read(dspi);
+ else if (trans_mode == DSPI_TCFQ_MODE)
+ dspi_tcfq_read(dspi);
+
+ if (!dspi->len)
+ /* Success! */
+ return 0;
+
+ if (trans_mode == DSPI_EOQ_MODE)
+ dspi_eoq_write(dspi);
+ else if (trans_mode == DSPI_TCFQ_MODE)
+ dspi_tcfq_write(dspi);
+
+ return -EINPROGRESS;
+}
+
+static int dspi_poll(struct fsl_dspi *dspi)
+{
+ int tries = 1000;
+ u32 spi_sr;
+
+ do {
+ regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+ regmap_write(dspi->regmap, SPI_SR, spi_sr);
+
+ if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))
+ break;
+ } while (--tries);
+
+ if (!tries)
+ return -ETIMEDOUT;
+
+ return dspi_rxtx(dspi);
+}
+
+static irqreturn_t dspi_interrupt(int irq, void *dev_id)
+{
+ struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
+ u32 spi_sr;
+
+ regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+ regmap_write(dspi->regmap, SPI_SR, spi_sr);
+
+ if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)))
+ return IRQ_NONE;
+
+ if (dspi_rxtx(dspi) == 0) {
+ dspi->waitflags = 1;
+ wake_up_interruptible(&dspi->waitq);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int dspi_transfer_one_message(struct spi_controller *ctlr,
+ struct spi_message *message)
+{
+ struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
struct spi_device *spi = message->spi;
+ enum dspi_trans_mode trans_mode;
struct spi_transfer *transfer;
int status = 0;
- enum dspi_trans_mode trans_mode;
message->actual_length = 0;
@@ -677,7 +735,7 @@ static int dspi_transfer_one_message(struct spi_master *master,
dspi->cur_chip = spi_get_ctldata(spi);
/* Prepare command word for CMD FIFO */
dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) |
- SPI_PUSHR_CMD_PCS(spi->chip_select);
+ SPI_PUSHR_CMD_PCS(spi->chip_select);
if (list_is_last(&dspi->cur_transfer->transfer_list,
&dspi->cur_msg->transfers)) {
/* Leave PCS activated after last transfer when
@@ -718,8 +776,8 @@ static int dspi_transfer_one_message(struct spi_master *master,
SPI_FRAME_BITS(transfer->bits_per_word));
if (dspi->devtype_data->xspi_mode)
regmap_write(dspi->regmap, SPI_CTARE(0),
- SPI_FRAME_EBITS(transfer->bits_per_word)
- | SPI_CTARE_DTCP(1));
+ SPI_FRAME_EBITS(transfer->bits_per_word) |
+ SPI_CTARE_DTCP(1));
trans_mode = dspi->devtype_data->trans_mode;
switch (trans_mode) {
@@ -733,8 +791,8 @@ static int dspi_transfer_one_message(struct spi_master *master,
break;
case DSPI_DMA_MODE:
regmap_write(dspi->regmap, SPI_RSER,
- SPI_RSER_TFFFE | SPI_RSER_TFFFD |
- SPI_RSER_RFDFE | SPI_RSER_RFDFD);
+ SPI_RSER_TFFFE | SPI_RSER_TFFFD |
+ SPI_RSER_RFDFE | SPI_RSER_RFDFD);
status = dspi_dma_xfer(dspi);
break;
default:
@@ -744,13 +802,18 @@ static int dspi_transfer_one_message(struct spi_master *master,
goto out;
}
- if (trans_mode != DSPI_DMA_MODE) {
- if (wait_event_interruptible(dspi->waitq,
- dspi->waitflags))
- dev_err(&dspi->pdev->dev,
- "wait transfer complete fail!\n");
+ if (!dspi->irq) {
+ do {
+ status = dspi_poll(dspi);
+ } while (status == -EINPROGRESS);
+ } else if (trans_mode != DSPI_DMA_MODE) {
+ status = wait_event_interruptible(dspi->waitq,
+ dspi->waitflags);
dspi->waitflags = 0;
}
+ if (status)
+ dev_err(&dspi->pdev->dev,
+ "Waiting for transfer to complete failed!\n");
if (transfer->delay_usecs)
udelay(transfer->delay_usecs);
@@ -758,19 +821,19 @@ static int dspi_transfer_one_message(struct spi_master *master,
out:
message->status = status;
- spi_finalize_current_message(master);
+ spi_finalize_current_message(ctlr);
return status;
}
static int dspi_setup(struct spi_device *spi)
{
- struct chip_data *chip;
- struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
- struct fsl_dspi_platform_data *pdata;
- u32 cs_sck_delay = 0, sck_cs_delay = 0;
+ struct fsl_dspi *dspi = spi_controller_get_devdata(spi->controller);
unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
+ u32 cs_sck_delay = 0, sck_cs_delay = 0;
+ struct fsl_dspi_platform_data *pdata;
unsigned char pasc = 0, asc = 0;
+ struct chip_data *chip;
unsigned long clkrate;
/* Only alloc on first setup */
@@ -785,10 +848,10 @@ static int dspi_setup(struct spi_device *spi)
if (!pdata) {
of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
- &cs_sck_delay);
+ &cs_sck_delay);
of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
- &sck_cs_delay);
+ &sck_cs_delay);
} else {
cs_sck_delay = pdata->cs_sck_delay;
sck_cs_delay = pdata->sck_cs_delay;
@@ -805,18 +868,22 @@ static int dspi_setup(struct spi_device *spi)
/* Set After SCK delay scale values */
ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
- chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
- | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0);
-
- if (!spi_controller_is_slave(dspi->master)) {
- chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode &
- SPI_LSB_FIRST ? 1 : 0)
- | SPI_CTAR_PCSSCK(pcssck)
- | SPI_CTAR_CSSCK(cssck)
- | SPI_CTAR_PASC(pasc)
- | SPI_CTAR_ASC(asc)
- | SPI_CTAR_PBR(pbr)
- | SPI_CTAR_BR(br);
+ chip->ctar_val = 0;
+ if (spi->mode & SPI_CPOL)
+ chip->ctar_val |= SPI_CTAR_CPOL;
+ if (spi->mode & SPI_CPHA)
+ chip->ctar_val |= SPI_CTAR_CPHA;
+
+ if (!spi_controller_is_slave(dspi->ctlr)) {
+ chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) |
+ SPI_CTAR_CSSCK(cssck) |
+ SPI_CTAR_PASC(pasc) |
+ SPI_CTAR_ASC(asc) |
+ SPI_CTAR_PBR(pbr) |
+ SPI_CTAR_BR(br);
+
+ if (spi->mode & SPI_LSB_FIRST)
+ chip->ctar_val |= SPI_CTAR_LSBFE;
}
spi_set_ctldata(spi, chip);
@@ -829,68 +896,11 @@ static void dspi_cleanup(struct spi_device *spi)
struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n",
- spi->master->bus_num, spi->chip_select);
+ spi->controller->bus_num, spi->chip_select);
kfree(chip);
}
-static irqreturn_t dspi_interrupt(int irq, void *dev_id)
-{
- struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
- struct spi_message *msg = dspi->cur_msg;
- enum dspi_trans_mode trans_mode;
- u32 spi_sr, spi_tcr;
- u16 spi_tcnt;
-
- regmap_read(dspi->regmap, SPI_SR, &spi_sr);
- regmap_write(dspi->regmap, SPI_SR, spi_sr);
-
-
- if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) {
- /* Get transfer counter (in number of SPI transfers). It was
- * reset to 0 when transfer(s) were started.
- */
- regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
- spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
- /* Update total number of bytes that were transferred */
- msg->actual_length += spi_tcnt * dspi->bytes_per_word;
-
- trans_mode = dspi->devtype_data->trans_mode;
- switch (trans_mode) {
- case DSPI_EOQ_MODE:
- dspi_eoq_read(dspi);
- break;
- case DSPI_TCFQ_MODE:
- dspi_tcfq_read(dspi);
- break;
- default:
- dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
- trans_mode);
- return IRQ_HANDLED;
- }
-
- if (!dspi->len) {
- dspi->waitflags = 1;
- wake_up_interruptible(&dspi->waitq);
- } else {
- switch (trans_mode) {
- case DSPI_EOQ_MODE:
- dspi_eoq_write(dspi);
- break;
- case DSPI_TCFQ_MODE:
- dspi_tcfq_write(dspi);
- break;
- default:
- dev_err(&dspi->pdev->dev,
- "unsupported trans_mode %u\n",
- trans_mode);
- }
- }
- }
-
- return IRQ_HANDLED;
-}
-
static const struct of_device_id fsl_dspi_dt_ids[] = {
{ .compatible = "fsl,vf610-dspi", .data = &vf610_data, },
{ .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, },
@@ -902,10 +912,10 @@ MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int dspi_suspend(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
- struct fsl_dspi *dspi = spi_master_get_devdata(master);
+ struct spi_controller *ctlr = dev_get_drvdata(dev);
+ struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
- spi_master_suspend(master);
+ spi_controller_suspend(ctlr);
clk_disable_unprepare(dspi->clk);
pinctrl_pm_select_sleep_state(dev);
@@ -915,8 +925,8 @@ static int dspi_suspend(struct device *dev)
static int dspi_resume(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
- struct fsl_dspi *dspi = spi_master_get_devdata(master);
+ struct spi_controller *ctlr = dev_get_drvdata(dev);
+ struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
int ret;
pinctrl_pm_select_default_state(dev);
@@ -924,7 +934,7 @@ static int dspi_resume(struct device *dev)
ret = clk_prepare_enable(dspi->clk);
if (ret)
return ret;
- spi_master_resume(master);
+ spi_controller_resume(ctlr);
return 0;
}
@@ -939,16 +949,16 @@ static const struct regmap_range dspi_volatile_ranges[] = {
};
static const struct regmap_access_table dspi_volatile_table = {
- .yes_ranges = dspi_volatile_ranges,
- .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges),
+ .yes_ranges = dspi_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges),
};
static const struct regmap_config dspi_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .max_register = 0x88,
- .volatile_table = &dspi_volatile_table,
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x88,
+ .volatile_table = &dspi_volatile_table,
};
static const struct regmap_range dspi_xspi_volatile_ranges[] = {
@@ -959,33 +969,34 @@ static const struct regmap_range dspi_xspi_volatile_ranges[] = {
};
static const struct regmap_access_table dspi_xspi_volatile_table = {
- .yes_ranges = dspi_xspi_volatile_ranges,
- .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges),
+ .yes_ranges = dspi_xspi_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges),
};
static const struct regmap_config dspi_xspi_regmap_config[] = {
{
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .max_register = 0x13c,
- .volatile_table = &dspi_xspi_volatile_table,
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x13c,
+ .volatile_table = &dspi_xspi_volatile_table,
},
{
- .name = "pushr",
- .reg_bits = 16,
- .val_bits = 16,
- .reg_stride = 2,
- .max_register = 0x2,
+ .name = "pushr",
+ .reg_bits = 16,
+ .val_bits = 16,
+ .reg_stride = 2,
+ .max_register = 0x2,
},
};
static void dspi_init(struct fsl_dspi *dspi)
{
- unsigned int mcr = SPI_MCR_PCSIS |
- (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0);
+ unsigned int mcr = SPI_MCR_PCSIS;
- if (!spi_controller_is_slave(dspi->master))
+ if (dspi->devtype_data->xspi_mode)
+ mcr |= SPI_MCR_XSPI;
+ if (!spi_controller_is_slave(dspi->ctlr))
mcr |= SPI_MCR_MASTER;
regmap_write(dspi->regmap, SPI_MCR, mcr);
@@ -998,34 +1009,33 @@ static void dspi_init(struct fsl_dspi *dspi)
static int dspi_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct spi_master *master;
+ const struct regmap_config *regmap_config;
+ struct fsl_dspi_platform_data *pdata;
+ struct spi_controller *ctlr;
+ int ret, cs_num, bus_num;
struct fsl_dspi *dspi;
struct resource *res;
- const struct regmap_config *regmap_config;
void __iomem *base;
- struct fsl_dspi_platform_data *pdata;
- int ret = 0, cs_num, bus_num;
- master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
- if (!master)
+ ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
+ if (!ctlr)
return -ENOMEM;
- dspi = spi_master_get_devdata(master);
+ dspi = spi_controller_get_devdata(ctlr);
dspi->pdev = pdev;
- dspi->master = master;
+ dspi->ctlr = ctlr;
- master->transfer = NULL;
- master->setup = dspi_setup;
- master->transfer_one_message = dspi_transfer_one_message;
- master->dev.of_node = pdev->dev.of_node;
+ ctlr->setup = dspi_setup;
+ ctlr->transfer_one_message = dspi_transfer_one_message;
+ ctlr->dev.of_node = pdev->dev.of_node;
- master->cleanup = dspi_cleanup;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+ ctlr->cleanup = dspi_cleanup;
+ ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
- master->num_chipselect = pdata->cs_num;
- master->bus_num = pdata->bus_num;
+ ctlr->num_chipselect = pdata->cs_num;
+ ctlr->bus_num = pdata->bus_num;
dspi->devtype_data = &coldfire_data;
} else {
@@ -1033,38 +1043,38 @@ static int dspi_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num);
if (ret < 0) {
dev_err(&pdev->dev, "can't get spi-num-chipselects\n");
- goto out_master_put;
+ goto out_ctlr_put;
}
- master->num_chipselect = cs_num;
+ ctlr->num_chipselect = cs_num;
ret = of_property_read_u32(np, "bus-num", &bus_num);
if (ret < 0) {
dev_err(&pdev->dev, "can't get bus-num\n");
- goto out_master_put;
+ goto out_ctlr_put;
}
- master->bus_num = bus_num;
+ ctlr->bus_num = bus_num;
if (of_property_read_bool(np, "spi-slave"))
- master->slave = true;
+ ctlr->slave = true;
dspi->devtype_data = of_device_get_match_data(&pdev->dev);
if (!dspi->devtype_data) {
dev_err(&pdev->dev, "can't get devtype_data\n");
ret = -EFAULT;
- goto out_master_put;
+ goto out_ctlr_put;
}
}
if (dspi->devtype_data->xspi_mode)
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+ ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
else
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+ ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
- goto out_master_put;
+ goto out_ctlr_put;
}
if (dspi->devtype_data->xspi_mode)
@@ -1076,7 +1086,7 @@ static int dspi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to init regmap: %ld\n",
PTR_ERR(dspi->regmap));
ret = PTR_ERR(dspi->regmap);
- goto out_master_put;
+ goto out_ctlr_put;
}
if (dspi->devtype_data->xspi_mode) {
@@ -1088,7 +1098,7 @@ static int dspi_probe(struct platform_device *pdev)
"failed to init pushr regmap: %ld\n",
PTR_ERR(dspi->regmap_pushr));
ret = PTR_ERR(dspi->regmap_pushr);
- goto out_master_put;
+ goto out_ctlr_put;
}
}
@@ -1096,18 +1106,20 @@ static int dspi_probe(struct platform_device *pdev)
if (IS_ERR(dspi->clk)) {
ret = PTR_ERR(dspi->clk);
dev_err(&pdev->dev, "unable to get clock\n");
- goto out_master_put;
+ goto out_ctlr_put;
}
ret = clk_prepare_enable(dspi->clk);
if (ret)
- goto out_master_put;
+ goto out_ctlr_put;
dspi_init(dspi);
+
dspi->irq = platform_get_irq(pdev, 0);
- if (dspi->irq < 0) {
- dev_err(&pdev->dev, "can't get platform irq\n");
- ret = dspi->irq;
- goto out_clk_put;
+ if (dspi->irq <= 0) {
+ dev_info(&pdev->dev,
+ "can't get platform irq, using poll mode\n");
+ dspi->irq = 0;
+ goto poll_mode;
}
ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt,
@@ -1117,6 +1129,9 @@ static int dspi_probe(struct platform_device *pdev)
goto out_clk_put;
}
+ init_waitqueue_head(&dspi->waitq);
+
+poll_mode:
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
ret = dspi_request_dma(dspi, res->start);
if (ret < 0) {
@@ -1125,15 +1140,14 @@ static int dspi_probe(struct platform_device *pdev)
}
}
- master->max_speed_hz =
+ ctlr->max_speed_hz =
clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor;
- init_waitqueue_head(&dspi->waitq);
- platform_set_drvdata(pdev, master);
+ platform_set_drvdata(pdev, ctlr);
- ret = spi_register_master(master);
+ ret = spi_register_controller(ctlr);
if (ret != 0) {
- dev_err(&pdev->dev, "Problem registering DSPI master\n");
+ dev_err(&pdev->dev, "Problem registering DSPI ctlr\n");
goto out_clk_put;
}
@@ -1141,32 +1155,32 @@ static int dspi_probe(struct platform_device *pdev)
out_clk_put:
clk_disable_unprepare(dspi->clk);
-out_master_put:
- spi_master_put(master);
+out_ctlr_put:
+ spi_controller_put(ctlr);
return ret;
}
static int dspi_remove(struct platform_device *pdev)
{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct fsl_dspi *dspi = spi_master_get_devdata(master);
+ struct spi_controller *ctlr = platform_get_drvdata(pdev);
+ struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
/* Disconnect from the SPI framework */
dspi_release_dma(dspi);
clk_disable_unprepare(dspi->clk);
- spi_unregister_master(dspi->master);
+ spi_unregister_controller(dspi->ctlr);
return 0;
}
static struct platform_driver fsl_dspi_driver = {
- .driver.name = DRIVER_NAME,
- .driver.of_match_table = fsl_dspi_dt_ids,
- .driver.owner = THIS_MODULE,
- .driver.pm = &dspi_pm,
- .probe = dspi_probe,
- .remove = dspi_remove,
+ .driver.name = DRIVER_NAME,
+ .driver.of_match_table = fsl_dspi_dt_ids,
+ .driver.owner = THIS_MODULE,
+ .driver.pm = &dspi_pm,
+ .probe = dspi_probe,
+ .remove = dspi_remove,
};
module_platform_driver(fsl_dspi_driver);
diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
index 3576167283dc..015a1abb6a84 100644
--- a/drivers/spi/spi-fsl-lib.h
+++ b/drivers/spi/spi-fsl-lib.h
@@ -91,9 +91,6 @@ static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
struct mpc8xxx_spi_probe_info {
struct fsl_spi_platform_data pdata;
- int ngpios;
- int *gpios;
- bool *alow_flags;
__be32 __iomem *immr_spi_cs;
};
diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
index 41a49b93ca60..c02e24c01136 100644
--- a/drivers/spi/spi-fsl-qspi.c
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -206,7 +206,7 @@ static const struct fsl_qspi_devtype_data imx6sx_data = {
};
static const struct fsl_qspi_devtype_data imx7d_data = {
- .rxfifo = SZ_512,
+ .rxfifo = SZ_128,
.txfifo = SZ_512,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
@@ -860,10 +860,8 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* find the irq */
ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "failed to get the irq: %d\n", ret);
+ if (ret < 0)
goto err_disable_clk;
- }
ret = devm_request_irq(dev, ret,
fsl_qspi_irq_handler, 0, pdev->name, q);
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 1d9b33aa1a3b..4b80ace1d137 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
@@ -28,7 +28,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
@@ -481,32 +480,6 @@ static int fsl_spi_setup(struct spi_device *spi)
return retval;
}
- if (mpc8xxx_spi->type == TYPE_GRLIB) {
- if (gpio_is_valid(spi->cs_gpio)) {
- int desel;
-
- retval = gpio_request(spi->cs_gpio,
- dev_name(&spi->dev));
- if (retval)
- return retval;
-
- desel = !(spi->mode & SPI_CS_HIGH);
- retval = gpio_direction_output(spi->cs_gpio, desel);
- if (retval) {
- gpio_free(spi->cs_gpio);
- return retval;
- }
- } else if (spi->cs_gpio != -ENOENT) {
- if (spi->cs_gpio < 0)
- return spi->cs_gpio;
- return -EINVAL;
- }
- /* When spi->cs_gpio == -ENOENT, a hole in the phandle list
- * indicates to use native chipselect if present, or allow for
- * an always selected chip
- */
- }
-
/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
@@ -515,12 +488,8 @@ static int fsl_spi_setup(struct spi_device *spi)
static void fsl_spi_cleanup(struct spi_device *spi)
{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
- if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio))
- gpio_free(spi->cs_gpio);
-
kfree(cs);
spi_set_ctldata(spi, NULL);
}
@@ -586,8 +555,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
u32 slvsel;
u16 cs = spi->chip_select;
- if (gpio_is_valid(spi->cs_gpio)) {
- gpio_set_value(spi->cs_gpio, on);
+ if (spi->cs_gpiod) {
+ gpiod_set_value(spi->cs_gpiod, on);
} else if (cs < mpc8xxx_spi->native_chipselects) {
slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
@@ -718,139 +687,19 @@ err:
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
- struct device *dev = spi->dev.parent->parent;
- struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- u16 cs = spi->chip_select;
-
- if (cs < pinfo->ngpios) {
- int gpio = pinfo->gpios[cs];
- bool alow = pinfo->alow_flags[cs];
-
- gpio_set_value(gpio, on ^ alow);
+ if (spi->cs_gpiod) {
+ gpiod_set_value(spi->cs_gpiod, on);
} else {
- if (WARN_ON_ONCE(cs > pinfo->ngpios || !pinfo->immr_spi_cs))
+ struct device *dev = spi->dev.parent->parent;
+ struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+ struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+
+ if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
return;
iowrite32be(on ? SPI_BOOT_SEL_BIT : 0, pinfo->immr_spi_cs);
}
}
-static int of_fsl_spi_get_chipselects(struct device *dev)
-{
- struct device_node *np = dev->of_node;
- struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- bool spisel_boot = IS_ENABLED(CONFIG_FSL_SOC) &&
- of_property_read_bool(np, "fsl,spisel_boot");
- int ngpios;
- int i = 0;
- int ret;
-
- ngpios = of_gpio_count(np);
- ngpios = max(ngpios, 0);
- if (ngpios == 0 && !spisel_boot) {
- /*
- * SPI w/o chip-select line. One SPI device is still permitted
- * though.
- */
- pdata->max_chipselect = 1;
- return 0;
- }
-
- pinfo->ngpios = ngpios;
- pinfo->gpios = kmalloc_array(ngpios, sizeof(*pinfo->gpios),
- GFP_KERNEL);
- if (!pinfo->gpios)
- return -ENOMEM;
- memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
-
- pinfo->alow_flags = kcalloc(ngpios, sizeof(*pinfo->alow_flags),
- GFP_KERNEL);
- if (!pinfo->alow_flags) {
- ret = -ENOMEM;
- goto err_alloc_flags;
- }
-
- for (; i < ngpios; i++) {
- int gpio;
- enum of_gpio_flags flags;
-
- gpio = of_get_gpio_flags(np, i, &flags);
- if (!gpio_is_valid(gpio)) {
- dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
- ret = gpio;
- goto err_loop;
- }
-
- ret = gpio_request(gpio, dev_name(dev));
- if (ret) {
- dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
- goto err_loop;
- }
-
- pinfo->gpios[i] = gpio;
- pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
-
- ret = gpio_direction_output(pinfo->gpios[i],
- pinfo->alow_flags[i]);
- if (ret) {
- dev_err(dev,
- "can't set output direction for gpio #%d: %d\n",
- i, ret);
- goto err_loop;
- }
- }
-
-#if IS_ENABLED(CONFIG_FSL_SOC)
- if (spisel_boot) {
- pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4);
- if (!pinfo->immr_spi_cs) {
- ret = -ENOMEM;
- i = ngpios - 1;
- goto err_loop;
- }
- }
-#endif
-
- pdata->max_chipselect = ngpios + spisel_boot;
- pdata->cs_control = fsl_spi_cs_control;
-
- return 0;
-
-err_loop:
- while (i >= 0) {
- if (gpio_is_valid(pinfo->gpios[i]))
- gpio_free(pinfo->gpios[i]);
- i--;
- }
-
- kfree(pinfo->alow_flags);
- pinfo->alow_flags = NULL;
-err_alloc_flags:
- kfree(pinfo->gpios);
- pinfo->gpios = NULL;
- return ret;
-}
-
-static int of_fsl_spi_free_chipselects(struct device *dev)
-{
- struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- int i;
-
- if (!pinfo->gpios)
- return 0;
-
- for (i = 0; i < pdata->max_chipselect; i++) {
- if (gpio_is_valid(pinfo->gpios[i]))
- gpio_free(pinfo->gpios[i]);
- }
-
- kfree(pinfo->gpios);
- kfree(pinfo->alow_flags);
- return 0;
-}
-
static int of_fsl_spi_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
@@ -866,9 +715,21 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
type = fsl_spi_get_type(&ofdev->dev);
if (type == TYPE_FSL) {
- ret = of_fsl_spi_get_chipselects(dev);
- if (ret)
- goto err;
+ struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+#if IS_ENABLED(CONFIG_FSL_SOC)
+ struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+ bool spisel_boot = of_property_read_bool(np, "fsl,spisel_boot");
+
+ if (spisel_boot) {
+ pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4);
+ if (!pinfo->immr_spi_cs) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+#endif
+
+ pdata->cs_control = fsl_spi_cs_control;
}
ret = of_address_to_resource(np, 0, &mem);
@@ -891,8 +752,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
err:
irq_dispose_mapping(irq);
- if (type == TYPE_FSL)
- of_fsl_spi_free_chipselects(dev);
return ret;
}
@@ -902,8 +761,6 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
fsl_spi_cpm_free(mpc8xxx_spi);
- if (mpc8xxx_spi->type == TYPE_FSL)
- of_fsl_spi_free_chipselects(&ofdev->dev);
return 0;
}
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 5f0b0d5bfef4..6f3d64a1a2b3 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -534,18 +534,14 @@ static int spi_geni_probe(struct platform_device *pdev)
int ret, irq;
struct spi_master *spi;
struct spi_geni_master *mas;
- struct resource *res;
void __iomem *base;
struct clk *clk;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "Err getting IRQ %d\n", irq);
+ if (irq < 0)
return irq;
- }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index eca9d52ecf65..1d3e23ec20a6 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -290,10 +290,7 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio)
return PTR_ERR(spi_gpio->miso);
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
- if (IS_ERR(spi_gpio->sck))
- return PTR_ERR(spi_gpio->sck);
-
- return 0;
+ return PTR_ERR_OR_ZERO(spi_gpio->sck);
}
#ifdef CONFIG_OF
@@ -410,6 +407,12 @@ static int spi_gpio_probe(struct platform_device *pdev)
bb = &spi_gpio->bitbang;
bb->master = master;
+ /*
+ * There is some additional business, apart from driving the CS GPIO
+ * line, that we need to do on selection. This makes the local
+ * callback for chipselect always get called.
+ */
+ master->flags |= SPI_MASTER_GPIO_SS;
bb->chipselect = spi_gpio_chipselect;
bb->set_line_direction = spi_gpio_set_direction;
diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c
index 8f01858c0ae6..9dfe8b04e688 100644
--- a/drivers/spi/spi-lantiq-ssc.c
+++ b/drivers/spi/spi-lantiq-ssc.c
@@ -819,22 +819,16 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
}
rx_irq = platform_get_irq_byname(pdev, LTQ_SPI_RX_IRQ_NAME);
- if (rx_irq < 0) {
- dev_err(dev, "failed to get %s\n", LTQ_SPI_RX_IRQ_NAME);
+ if (rx_irq < 0)
return -ENXIO;
- }
tx_irq = platform_get_irq_byname(pdev, LTQ_SPI_TX_IRQ_NAME);
- if (tx_irq < 0) {
- dev_err(dev, "failed to get %s\n", LTQ_SPI_TX_IRQ_NAME);
+ if (tx_irq < 0)
return -ENXIO;
- }
err_irq = platform_get_irq_byname(pdev, LTQ_SPI_ERR_IRQ_NAME);
- if (err_irq < 0) {
- dev_err(dev, "failed to get %s\n", LTQ_SPI_ERR_IRQ_NAME);
+ if (err_irq < 0)
return -ENXIO;
- }
master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));
if (!master)
diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c
index f50779fd329c..2d436541d6c2 100644
--- a/drivers/spi/spi-lp8841-rtc.c
+++ b/drivers/spi/spi-lp8841-rtc.c
@@ -185,7 +185,6 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
int ret;
struct spi_master *master;
struct spi_lp8841_rtc *data;
- void *iomem;
master = spi_alloc_master(&pdev->dev, sizeof(*data));
if (!master)
@@ -207,8 +206,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
data = spi_master_get_devdata(master);
- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->iomem = devm_ioremap_resource(&pdev->dev, iomem);
+ data->iomem = devm_platform_ioremap_resource(pdev, 0);
ret = PTR_ERR_OR_ZERO(data->iomem);
if (ret) {
dev_err(&pdev->dev, "failed to get IO address\n");
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index 7fe4488ace57..f3f10443f9e2 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -503,7 +503,6 @@ static int meson_spicc_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct meson_spicc_device *spicc;
- struct resource *res;
int ret, irq, rate;
master = spi_alloc_master(&pdev->dev, sizeof(*spicc));
@@ -517,8 +516,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
spicc->pdev = pdev;
platform_set_drvdata(pdev, spicc);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spicc->base = devm_ioremap_resource(&pdev->dev, res);
+ spicc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spicc->base)) {
dev_err(&pdev->dev, "io resource mapping failed\n");
ret = PTR_ERR(spicc->base);
diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c
index f7fe9b13d122..c7b039980291 100644
--- a/drivers/spi/spi-meson-spifc.c
+++ b/drivers/spi/spi-meson-spifc.c
@@ -286,7 +286,6 @@ static int meson_spifc_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct meson_spifc *spifc;
- struct resource *res;
void __iomem *base;
unsigned int rate;
int ret = 0;
@@ -300,8 +299,7 @@ static int meson_spifc_probe(struct platform_device *pdev)
spifc = spi_master_get_devdata(master);
spifc->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(spifc->dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
goto out_err;
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 45d8a7048b6c..6888a4dcff6d 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -17,6 +17,7 @@
#include <linux/platform_data/spi-mt65xx.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
+#include <linux/dma-mapping.h>
#define SPI_CFG0_REG 0x0000
#define SPI_CFG1_REG 0x0004
@@ -28,6 +29,8 @@
#define SPI_STATUS0_REG 0x001c
#define SPI_PAD_SEL_REG 0x0024
#define SPI_CFG2_REG 0x0028
+#define SPI_TX_SRC_REG_64 0x002c
+#define SPI_RX_DST_REG_64 0x0030
#define SPI_CFG0_SCK_HIGH_OFFSET 0
#define SPI_CFG0_SCK_LOW_OFFSET 8
@@ -73,6 +76,10 @@
#define MTK_SPI_MAX_FIFO_SIZE 32U
#define MTK_SPI_PACKET_SIZE 1024
+#define MTK_SPI_32BITS_MASK (0xffffffff)
+
+#define DMA_ADDR_EXT_BITS (36)
+#define DMA_ADDR_DEF_BITS (32)
struct mtk_spi_compatible {
bool need_pad_sel;
@@ -80,6 +87,8 @@ struct mtk_spi_compatible {
bool must_tx;
/* some IC design adjust cfg register to enhance time accuracy */
bool enhance_timing;
+ /* some IC support DMA addr extension */
+ bool dma_ext;
};
struct mtk_spi {
@@ -102,6 +111,13 @@ static const struct mtk_spi_compatible mt2712_compat = {
.must_tx = true,
};
+static const struct mtk_spi_compatible mt6765_compat = {
+ .need_pad_sel = true,
+ .must_tx = true,
+ .enhance_timing = true,
+ .dma_ext = true,
+};
+
static const struct mtk_spi_compatible mt7622_compat = {
.must_tx = true,
.enhance_timing = true,
@@ -137,6 +153,9 @@ static const struct of_device_id mtk_spi_of_match[] = {
{ .compatible = "mediatek,mt6589-spi",
.data = (void *)&mtk_common_compat,
},
+ { .compatible = "mediatek,mt6765-spi",
+ .data = (void *)&mt6765_compat,
+ },
{ .compatible = "mediatek,mt7622-spi",
.data = (void *)&mt7622_compat,
},
@@ -371,10 +390,25 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master,
{
struct mtk_spi *mdata = spi_master_get_devdata(master);
- if (mdata->tx_sgl)
- writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG);
- if (mdata->rx_sgl)
- writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG);
+ if (mdata->tx_sgl) {
+ writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK),
+ mdata->base + SPI_TX_SRC_REG);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (mdata->dev_comp->dma_ext)
+ writel((u32)(xfer->tx_dma >> 32),
+ mdata->base + SPI_TX_SRC_REG_64);
+#endif
+ }
+
+ if (mdata->rx_sgl) {
+ writel((u32)(xfer->rx_dma & MTK_SPI_32BITS_MASK),
+ mdata->base + SPI_RX_DST_REG);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (mdata->dev_comp->dma_ext)
+ writel((u32)(xfer->rx_dma >> 32),
+ mdata->base + SPI_RX_DST_REG_64);
+#endif
+ }
}
static int mtk_spi_fifo_transfer(struct spi_master *master,
@@ -586,7 +620,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
struct mtk_spi *mdata;
const struct of_device_id *of_id;
struct resource *res;
- int i, irq, ret;
+ int i, irq, ret, addr_bits;
master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
if (!master) {
@@ -664,7 +698,6 @@ static int mtk_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to get irq (%d)\n", irq);
ret = irq;
goto err_put_master;
}
@@ -753,6 +786,15 @@ static int mtk_spi_probe(struct platform_device *pdev)
}
}
+ if (mdata->dev_comp->dma_ext)
+ addr_bits = DMA_ADDR_EXT_BITS;
+ else
+ addr_bits = DMA_ADDR_DEF_BITS;
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(addr_bits));
+ if (ret)
+ dev_notice(&pdev->dev, "SPI dma_set_mask(%d) failed, ret:%d\n",
+ addr_bits, ret);
+
return 0;
err_disable_runtime_pm:
diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
index ff85982464d2..2c3b7a2a1ec7 100644
--- a/drivers/spi/spi-mt7621.c
+++ b/drivers/spi/spi-mt7621.c
@@ -327,7 +327,6 @@ static int mt7621_spi_probe(struct platform_device *pdev)
struct spi_controller *master;
struct mt7621_spi *rs;
void __iomem *base;
- struct resource *r;
int status = 0;
struct clk *clk;
int ret;
@@ -336,8 +335,7 @@ static int mt7621_spi_probe(struct platform_device *pdev)
if (!match)
return -EINVAL;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, r);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 7bf53cfc25d6..996c1c8a9c71 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -532,7 +532,6 @@ static int mxs_spi_probe(struct platform_device *pdev)
struct spi_master *master;
struct mxs_spi *spi;
struct mxs_ssp *ssp;
- struct resource *iores;
struct clk *clk;
void __iomem *base;
int devid, clk_freq;
@@ -545,12 +544,11 @@ static int mxs_spi_probe(struct platform_device *pdev)
*/
const int clk_freq_default = 160000000;
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq_err = platform_get_irq(pdev, 0);
if (irq_err < 0)
return irq_err;
- base = devm_ioremap_resource(&pdev->dev, iores);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c
new file mode 100644
index 000000000000..cb52fd8008d0
--- /dev/null
+++ b/drivers/spi/spi-npcm-fiu.c
@@ -0,0 +1,769 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 Nuvoton Technology corporation.
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi-mem.h>
+#include <linux/mfd/syscon.h>
+
+/* NPCM7xx GCR module */
+#define NPCM7XX_INTCR3_OFFSET 0x9C
+#define NPCM7XX_INTCR3_FIU_FIX BIT(6)
+
+/* Flash Interface Unit (FIU) Registers */
+#define NPCM_FIU_DRD_CFG 0x00
+#define NPCM_FIU_DWR_CFG 0x04
+#define NPCM_FIU_UMA_CFG 0x08
+#define NPCM_FIU_UMA_CTS 0x0C
+#define NPCM_FIU_UMA_CMD 0x10
+#define NPCM_FIU_UMA_ADDR 0x14
+#define NPCM_FIU_PRT_CFG 0x18
+#define NPCM_FIU_UMA_DW0 0x20
+#define NPCM_FIU_UMA_DW1 0x24
+#define NPCM_FIU_UMA_DW2 0x28
+#define NPCM_FIU_UMA_DW3 0x2C
+#define NPCM_FIU_UMA_DR0 0x30
+#define NPCM_FIU_UMA_DR1 0x34
+#define NPCM_FIU_UMA_DR2 0x38
+#define NPCM_FIU_UMA_DR3 0x3C
+#define NPCM_FIU_MAX_REG_LIMIT 0x80
+
+/* FIU Direct Read Configuration Register */
+#define NPCM_FIU_DRD_CFG_LCK BIT(31)
+#define NPCM_FIU_DRD_CFG_R_BURST GENMASK(25, 24)
+#define NPCM_FIU_DRD_CFG_ADDSIZ GENMASK(17, 16)
+#define NPCM_FIU_DRD_CFG_DBW GENMASK(13, 12)
+#define NPCM_FIU_DRD_CFG_ACCTYPE GENMASK(9, 8)
+#define NPCM_FIU_DRD_CFG_RDCMD GENMASK(7, 0)
+#define NPCM_FIU_DRD_ADDSIZ_SHIFT 16
+#define NPCM_FIU_DRD_DBW_SHIFT 12
+#define NPCM_FIU_DRD_ACCTYPE_SHIFT 8
+
+/* FIU Direct Write Configuration Register */
+#define NPCM_FIU_DWR_CFG_LCK BIT(31)
+#define NPCM_FIU_DWR_CFG_W_BURST GENMASK(25, 24)
+#define NPCM_FIU_DWR_CFG_ADDSIZ GENMASK(17, 16)
+#define NPCM_FIU_DWR_CFG_ABPCK GENMASK(11, 10)
+#define NPCM_FIU_DWR_CFG_DBPCK GENMASK(9, 8)
+#define NPCM_FIU_DWR_CFG_WRCMD GENMASK(7, 0)
+#define NPCM_FIU_DWR_ADDSIZ_SHIFT 16
+#define NPCM_FIU_DWR_ABPCK_SHIFT 10
+#define NPCM_FIU_DWR_DBPCK_SHIFT 8
+
+/* FIU UMA Configuration Register */
+#define NPCM_FIU_UMA_CFG_LCK BIT(31)
+#define NPCM_FIU_UMA_CFG_CMMLCK BIT(30)
+#define NPCM_FIU_UMA_CFG_RDATSIZ GENMASK(28, 24)
+#define NPCM_FIU_UMA_CFG_DBSIZ GENMASK(23, 21)
+#define NPCM_FIU_UMA_CFG_WDATSIZ GENMASK(20, 16)
+#define NPCM_FIU_UMA_CFG_ADDSIZ GENMASK(13, 11)
+#define NPCM_FIU_UMA_CFG_CMDSIZ BIT(10)
+#define NPCM_FIU_UMA_CFG_RDBPCK GENMASK(9, 8)
+#define NPCM_FIU_UMA_CFG_DBPCK GENMASK(7, 6)
+#define NPCM_FIU_UMA_CFG_WDBPCK GENMASK(5, 4)
+#define NPCM_FIU_UMA_CFG_ADBPCK GENMASK(3, 2)
+#define NPCM_FIU_UMA_CFG_CMBPCK GENMASK(1, 0)
+#define NPCM_FIU_UMA_CFG_ADBPCK_SHIFT 2
+#define NPCM_FIU_UMA_CFG_WDBPCK_SHIFT 4
+#define NPCM_FIU_UMA_CFG_DBPCK_SHIFT 6
+#define NPCM_FIU_UMA_CFG_RDBPCK_SHIFT 8
+#define NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT 11
+#define NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT 16
+#define NPCM_FIU_UMA_CFG_DBSIZ_SHIFT 21
+#define NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT 24
+
+/* FIU UMA Control and Status Register */
+#define NPCM_FIU_UMA_CTS_RDYIE BIT(25)
+#define NPCM_FIU_UMA_CTS_RDYST BIT(24)
+#define NPCM_FIU_UMA_CTS_SW_CS BIT(16)
+#define NPCM_FIU_UMA_CTS_DEV_NUM GENMASK(9, 8)
+#define NPCM_FIU_UMA_CTS_EXEC_DONE BIT(0)
+#define NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT 8
+
+/* FIU UMA Command Register */
+#define NPCM_FIU_UMA_CMD_DUM3 GENMASK(31, 24)
+#define NPCM_FIU_UMA_CMD_DUM2 GENMASK(23, 16)
+#define NPCM_FIU_UMA_CMD_DUM1 GENMASK(15, 8)
+#define NPCM_FIU_UMA_CMD_CMD GENMASK(7, 0)
+
+/* FIU UMA Address Register */
+#define NPCM_FIU_UMA_ADDR_UMA_ADDR GENMASK(31, 0)
+#define NPCM_FIU_UMA_ADDR_AB3 GENMASK(31, 24)
+#define NPCM_FIU_UMA_ADDR_AB2 GENMASK(23, 16)
+#define NPCM_FIU_UMA_ADDR_AB1 GENMASK(15, 8)
+#define NPCM_FIU_UMA_ADDR_AB0 GENMASK(7, 0)
+
+/* FIU UMA Write Data Bytes 0-3 Register */
+#define NPCM_FIU_UMA_DW0_WB3 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DW0_WB2 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DW0_WB1 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DW0_WB0 GENMASK(7, 0)
+
+/* FIU UMA Write Data Bytes 4-7 Register */
+#define NPCM_FIU_UMA_DW1_WB7 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DW1_WB6 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DW1_WB5 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DW1_WB4 GENMASK(7, 0)
+
+/* FIU UMA Write Data Bytes 8-11 Register */
+#define NPCM_FIU_UMA_DW2_WB11 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DW2_WB10 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DW2_WB9 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DW2_WB8 GENMASK(7, 0)
+
+/* FIU UMA Write Data Bytes 12-15 Register */
+#define NPCM_FIU_UMA_DW3_WB15 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DW3_WB14 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DW3_WB13 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DW3_WB12 GENMASK(7, 0)
+
+/* FIU UMA Read Data Bytes 0-3 Register */
+#define NPCM_FIU_UMA_DR0_RB3 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DR0_RB2 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DR0_RB1 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DR0_RB0 GENMASK(7, 0)
+
+/* FIU UMA Read Data Bytes 4-7 Register */
+#define NPCM_FIU_UMA_DR1_RB15 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DR1_RB14 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DR1_RB13 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DR1_RB12 GENMASK(7, 0)
+
+/* FIU UMA Read Data Bytes 8-11 Register */
+#define NPCM_FIU_UMA_DR2_RB15 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DR2_RB14 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DR2_RB13 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DR2_RB12 GENMASK(7, 0)
+
+/* FIU UMA Read Data Bytes 12-15 Register */
+#define NPCM_FIU_UMA_DR3_RB15 GENMASK(31, 24)
+#define NPCM_FIU_UMA_DR3_RB14 GENMASK(23, 16)
+#define NPCM_FIU_UMA_DR3_RB13 GENMASK(15, 8)
+#define NPCM_FIU_UMA_DR3_RB12 GENMASK(7, 0)
+
+/* FIU Read Mode */
+enum {
+ DRD_SINGLE_WIRE_MODE = 0,
+ DRD_DUAL_IO_MODE = 1,
+ DRD_QUAD_IO_MODE = 2,
+ DRD_SPI_X_MODE = 3,
+};
+
+enum {
+ DWR_ABPCK_BIT_PER_CLK = 0,
+ DWR_ABPCK_2_BIT_PER_CLK = 1,
+ DWR_ABPCK_4_BIT_PER_CLK = 2,
+};
+
+enum {
+ DWR_DBPCK_BIT_PER_CLK = 0,
+ DWR_DBPCK_2_BIT_PER_CLK = 1,
+ DWR_DBPCK_4_BIT_PER_CLK = 2,
+};
+
+#define NPCM_FIU_DRD_16_BYTE_BURST 0x3000000
+#define NPCM_FIU_DWR_16_BYTE_BURST 0x3000000
+
+#define MAP_SIZE_128MB 0x8000000
+#define MAP_SIZE_16MB 0x1000000
+#define MAP_SIZE_8MB 0x800000
+
+#define NUM_BITS_IN_BYTE 8
+#define FIU_DRD_MAX_DUMMY_NUMBER 3
+#define NPCM_MAX_CHIP_NUM 4
+#define CHUNK_SIZE 16
+#define UMA_MICRO_SEC_TIMEOUT 150
+
+enum {
+ FIU0 = 0,
+ FIU3,
+ FIUX,
+};
+
+struct npcm_fiu_info {
+ char *name;
+ u32 fiu_id;
+ u32 max_map_size;
+ u32 max_cs;
+};
+
+struct fiu_data {
+ const struct npcm_fiu_info *npcm_fiu_data_info;
+ int fiu_max;
+};
+
+static const struct npcm_fiu_info npxm7xx_fiu_info[] = {
+ {.name = "FIU0", .fiu_id = FIU0,
+ .max_map_size = MAP_SIZE_128MB, .max_cs = 2},
+ {.name = "FIU3", .fiu_id = FIU3,
+ .max_map_size = MAP_SIZE_128MB, .max_cs = 4},
+ {.name = "FIUX", .fiu_id = FIUX,
+ .max_map_size = MAP_SIZE_16MB, .max_cs = 2} };
+
+static const struct fiu_data npxm7xx_fiu_data = {
+ .npcm_fiu_data_info = npxm7xx_fiu_info,
+ .fiu_max = 3,
+};
+
+struct npcm_fiu_spi;
+
+struct npcm_fiu_chip {
+ void __iomem *flash_region_mapped_ptr;
+ struct npcm_fiu_spi *fiu;
+ unsigned long clkrate;
+ u32 chipselect;
+};
+
+struct npcm_fiu_spi {
+ struct npcm_fiu_chip chip[NPCM_MAX_CHIP_NUM];
+ const struct npcm_fiu_info *info;
+ struct spi_mem_op drd_op;
+ struct resource *res_mem;
+ struct regmap *regmap;
+ unsigned long clkrate;
+ struct device *dev;
+ struct clk *clk;
+ bool spix_mode;
+};
+
+static const struct regmap_config npcm_mtd_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = NPCM_FIU_MAX_REG_LIMIT,
+};
+
+static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu,
+ const struct spi_mem_op *op)
+{
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_ACCTYPE,
+ ilog2(op->addr.buswidth) <<
+ NPCM_FIU_DRD_ACCTYPE_SHIFT);
+ fiu->drd_op.addr.buswidth = op->addr.buswidth;
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_DBW,
+ ((op->dummy.nbytes * ilog2(op->addr.buswidth))
+ / NUM_BITS_IN_BYTE) << NPCM_FIU_DRD_DBW_SHIFT);
+ fiu->drd_op.dummy.nbytes = op->dummy.nbytes;
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode);
+ fiu->drd_op.cmd.opcode = op->cmd.opcode;
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_ADDSIZ,
+ (op->addr.nbytes - 3) << NPCM_FIU_DRD_ADDSIZ_SHIFT);
+ fiu->drd_op.addr.nbytes = op->addr.nbytes;
+}
+
+static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc,
+ u64 offs, size_t len, void *buf)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(desc->mem->spi->master);
+ struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
+ void __iomem *src = (void __iomem *)(chip->flash_region_mapped_ptr +
+ offs);
+ u8 *buf_rx = buf;
+ u32 i;
+
+ if (fiu->spix_mode) {
+ for (i = 0 ; i < len ; i++)
+ *(buf_rx + i) = ioread8(src + i);
+ } else {
+ if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth ||
+ desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes ||
+ desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode ||
+ desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes)
+ npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
+
+ memcpy_fromio(buf_rx, src, len);
+ }
+
+ return len;
+}
+
+static ssize_t npcm_fiu_direct_write(struct spi_mem_dirmap_desc *desc,
+ u64 offs, size_t len, const void *buf)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(desc->mem->spi->master);
+ struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
+ void __iomem *dst = (void __iomem *)(chip->flash_region_mapped_ptr +
+ offs);
+ const u8 *buf_tx = buf;
+ u32 i;
+
+ if (fiu->spix_mode)
+ for (i = 0 ; i < len ; i++)
+ iowrite8(*(buf_tx + i), dst + i);
+ else
+ memcpy_toio(dst, buf_tx, len);
+
+ return len;
+}
+
+static int npcm_fiu_uma_read(struct spi_mem *mem,
+ const struct spi_mem_op *op, u32 addr,
+ bool is_address_size, u8 *data, u32 data_size)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(mem->spi->master);
+ u32 uma_cfg = BIT(10);
+ u32 data_reg[4];
+ int ret;
+ u32 val;
+ u32 i;
+
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_DEV_NUM,
+ (mem->spi->chip_select <<
+ NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
+ NPCM_FIU_UMA_CMD_CMD, op->cmd.opcode);
+
+ if (is_address_size) {
+ uma_cfg |= ilog2(op->cmd.buswidth);
+ uma_cfg |= ilog2(op->addr.buswidth)
+ << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT;
+ uma_cfg |= ilog2(op->dummy.buswidth)
+ << NPCM_FIU_UMA_CFG_DBPCK_SHIFT;
+ uma_cfg |= ilog2(op->data.buswidth)
+ << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT;
+ uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT;
+ uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT;
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr);
+ } else {
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0);
+ }
+
+ uma_cfg |= data_size << NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT;
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg);
+ regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_EXEC_DONE,
+ NPCM_FIU_UMA_CTS_EXEC_DONE);
+ ret = regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val,
+ (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0,
+ UMA_MICRO_SEC_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (data_size) {
+ for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++)
+ regmap_read(fiu->regmap, NPCM_FIU_UMA_DR0 + (i * 4),
+ &data_reg[i]);
+ memcpy(data, data_reg, data_size);
+ }
+
+ return 0;
+}
+
+static int npcm_fiu_uma_write(struct spi_mem *mem,
+ const struct spi_mem_op *op, u8 cmd,
+ bool is_address_size, u8 *data, u32 data_size)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(mem->spi->master);
+ u32 uma_cfg = BIT(10);
+ u32 data_reg[4] = {0};
+ u32 val;
+ u32 i;
+
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_DEV_NUM,
+ (mem->spi->chip_select <<
+ NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
+
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
+ NPCM_FIU_UMA_CMD_CMD, cmd);
+
+ if (data_size) {
+ memcpy(data_reg, data, data_size);
+ for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++)
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_DW0 + (i * 4),
+ data_reg[i]);
+ }
+
+ if (is_address_size) {
+ uma_cfg |= ilog2(op->cmd.buswidth);
+ uma_cfg |= ilog2(op->addr.buswidth) <<
+ NPCM_FIU_UMA_CFG_ADBPCK_SHIFT;
+ uma_cfg |= ilog2(op->data.buswidth) <<
+ NPCM_FIU_UMA_CFG_WDBPCK_SHIFT;
+ uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT;
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, op->addr.val);
+ } else {
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0);
+ }
+
+ uma_cfg |= (data_size << NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT);
+ regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg);
+
+ regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_EXEC_DONE,
+ NPCM_FIU_UMA_CTS_EXEC_DONE);
+
+ return regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val,
+ (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0,
+ UMA_MICRO_SEC_TIMEOUT);
+}
+
+static int npcm_fiu_manualwrite(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(mem->spi->master);
+ u8 *data = (u8 *)op->data.buf.out;
+ u32 num_data_chunks;
+ u32 remain_data;
+ u32 idx = 0;
+ int ret;
+
+ num_data_chunks = op->data.nbytes / CHUNK_SIZE;
+ remain_data = op->data.nbytes % CHUNK_SIZE;
+
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_DEV_NUM,
+ (mem->spi->chip_select <<
+ NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_SW_CS, 0);
+
+ ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, true, NULL, 0);
+ if (ret)
+ return ret;
+
+ /* Starting the data writing loop in multiples of 8 */
+ for (idx = 0; idx < num_data_chunks; ++idx) {
+ ret = npcm_fiu_uma_write(mem, op, data[0], false,
+ &data[1], CHUNK_SIZE - 1);
+ if (ret)
+ return ret;
+
+ data += CHUNK_SIZE;
+ }
+
+ /* Handling chunk remains */
+ if (remain_data > 0) {
+ ret = npcm_fiu_uma_write(mem, op, data[0], false,
+ &data[1], remain_data - 1);
+ if (ret)
+ return ret;
+ }
+
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
+ NPCM_FIU_UMA_CTS_SW_CS, NPCM_FIU_UMA_CTS_SW_CS);
+
+ return 0;
+}
+
+static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ u8 *data = op->data.buf.in;
+ int i, readlen, currlen;
+ u8 *buf_ptr;
+ u32 addr;
+ int ret;
+
+ i = 0;
+ currlen = op->data.nbytes;
+
+ do {
+ addr = ((u32)op->addr.val + i);
+ if (currlen < 16)
+ readlen = currlen;
+ else
+ readlen = 16;
+
+ buf_ptr = data + i;
+ ret = npcm_fiu_uma_read(mem, op, addr, true, buf_ptr,
+ readlen);
+ if (ret)
+ return ret;
+
+ i += readlen;
+ currlen -= 16;
+ } while (currlen > 0);
+
+ return 0;
+}
+
+static void npcm_fiux_set_direct_wr(struct npcm_fiu_spi *fiu)
+{
+ regmap_write(fiu->regmap, NPCM_FIU_DWR_CFG,
+ NPCM_FIU_DWR_16_BYTE_BURST);
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG,
+ NPCM_FIU_DWR_CFG_ABPCK,
+ DWR_ABPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_ABPCK_SHIFT);
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG,
+ NPCM_FIU_DWR_CFG_DBPCK,
+ DWR_DBPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_DBPCK_SHIFT);
+}
+
+static void npcm_fiux_set_direct_rd(struct npcm_fiu_spi *fiu)
+{
+ u32 rx_dummy = 0;
+
+ regmap_write(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_16_BYTE_BURST);
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_ACCTYPE,
+ DRD_SPI_X_MODE << NPCM_FIU_DRD_ACCTYPE_SHIFT);
+ regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
+ NPCM_FIU_DRD_CFG_DBW,
+ rx_dummy << NPCM_FIU_DRD_DBW_SHIFT);
+}
+
+static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(mem->spi->master);
+ struct npcm_fiu_chip *chip = &fiu->chip[mem->spi->chip_select];
+ int ret = 0;
+ u8 *buf;
+
+ dev_dbg(fiu->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
+ op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
+ op->dummy.buswidth, op->data.buswidth, op->addr.val,
+ op->data.nbytes);
+
+ if (fiu->spix_mode || op->addr.nbytes > 4)
+ return -ENOTSUPP;
+
+ if (fiu->clkrate != chip->clkrate) {
+ ret = clk_set_rate(fiu->clk, chip->clkrate);
+ if (ret < 0)
+ dev_warn(fiu->dev, "Failed setting %lu frequency, stay at %lu frequency\n",
+ chip->clkrate, fiu->clkrate);
+ else
+ fiu->clkrate = chip->clkrate;
+ }
+
+ if (op->data.dir == SPI_MEM_DATA_IN) {
+ if (!op->addr.nbytes) {
+ buf = op->data.buf.in;
+ ret = npcm_fiu_uma_read(mem, op, op->addr.val, false,
+ buf, op->data.nbytes);
+ } else {
+ ret = npcm_fiu_read(mem, op);
+ }
+ } else {
+ if (!op->addr.nbytes && !op->data.nbytes)
+ ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
+ NULL, 0);
+ if (op->addr.nbytes && !op->data.nbytes) {
+ int i;
+ u8 buf_addr[4];
+ u32 addr = op->addr.val;
+
+ for (i = op->addr.nbytes - 1; i >= 0; i--) {
+ buf_addr[i] = addr & 0xff;
+ addr >>= 8;
+ }
+ ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
+ buf_addr, op->addr.nbytes);
+ }
+ if (!op->addr.nbytes && op->data.nbytes)
+ ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
+ (u8 *)op->data.buf.out,
+ op->data.nbytes);
+ if (op->addr.nbytes && op->data.nbytes)
+ ret = npcm_fiu_manualwrite(mem, op);
+ }
+
+ return ret;
+}
+
+static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+ struct npcm_fiu_spi *fiu =
+ spi_controller_get_devdata(desc->mem->spi->master);
+ struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
+ struct regmap *gcr_regmap;
+
+ if (!fiu->res_mem) {
+ dev_warn(fiu->dev, "Reserved memory not defined, direct read disabled\n");
+ desc->nodirmap = true;
+ return 0;
+ }
+
+ if (!fiu->spix_mode &&
+ desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) {
+ desc->nodirmap = true;
+ return 0;
+ }
+
+ if (!chip->flash_region_mapped_ptr) {
+ chip->flash_region_mapped_ptr =
+ devm_ioremap_nocache(fiu->dev, (fiu->res_mem->start +
+ (fiu->info->max_map_size *
+ desc->mem->spi->chip_select)),
+ (u32)desc->info.length);
+ if (!chip->flash_region_mapped_ptr) {
+ dev_warn(fiu->dev, "Error mapping memory region, direct read disabled\n");
+ desc->nodirmap = true;
+ return 0;
+ }
+ }
+
+ if (of_device_is_compatible(fiu->dev->of_node, "nuvoton,npcm750-fiu")) {
+ gcr_regmap =
+ syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
+ if (IS_ERR(gcr_regmap)) {
+ dev_warn(fiu->dev, "Didn't find nuvoton,npcm750-gcr, direct read disabled\n");
+ desc->nodirmap = true;
+ return 0;
+ }
+ regmap_update_bits(gcr_regmap, NPCM7XX_INTCR3_OFFSET,
+ NPCM7XX_INTCR3_FIU_FIX,
+ NPCM7XX_INTCR3_FIU_FIX);
+ }
+
+ if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) {
+ if (!fiu->spix_mode)
+ npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
+ else
+ npcm_fiux_set_direct_rd(fiu);
+
+ } else {
+ npcm_fiux_set_direct_wr(fiu);
+ }
+
+ return 0;
+}
+
+static int npcm_fiu_setup(struct spi_device *spi)
+{
+ struct spi_controller *ctrl = spi->master;
+ struct npcm_fiu_spi *fiu = spi_controller_get_devdata(ctrl);
+ struct npcm_fiu_chip *chip;
+
+ chip = &fiu->chip[spi->chip_select];
+ chip->fiu = fiu;
+ chip->chipselect = spi->chip_select;
+ chip->clkrate = spi->max_speed_hz;
+
+ fiu->clkrate = clk_get_rate(fiu->clk);
+
+ return 0;
+}
+
+static const struct spi_controller_mem_ops npcm_fiu_mem_ops = {
+ .exec_op = npcm_fiu_exec_op,
+ .dirmap_create = npcm_fiu_dirmap_create,
+ .dirmap_read = npcm_fiu_direct_read,
+ .dirmap_write = npcm_fiu_direct_write,
+};
+
+static const struct of_device_id npcm_fiu_dt_ids[] = {
+ { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data },
+ { /* sentinel */ }
+};
+
+static int npcm_fiu_probe(struct platform_device *pdev)
+{
+ const struct fiu_data *fiu_data_match;
+ const struct of_device_id *match;
+ struct device *dev = &pdev->dev;
+ struct spi_controller *ctrl;
+ struct npcm_fiu_spi *fiu;
+ void __iomem *regbase;
+ struct resource *res;
+ int ret;
+ int id;
+
+ ctrl = spi_alloc_master(dev, sizeof(*fiu));
+ if (!ctrl)
+ return -ENOMEM;
+
+ fiu = spi_controller_get_devdata(ctrl);
+
+ match = of_match_device(npcm_fiu_dt_ids, dev);
+ if (!match || !match->data) {
+ dev_err(dev, "No compatible OF match\n");
+ return -ENODEV;
+ }
+
+ fiu_data_match = match->data;
+ id = of_alias_get_id(dev->of_node, "fiu");
+ if (id < 0 || id >= fiu_data_match->fiu_max) {
+ dev_err(dev, "Invalid platform device id: %d\n", id);
+ return -EINVAL;
+ }
+
+ fiu->info = &fiu_data_match->npcm_fiu_data_info[id];
+
+ platform_set_drvdata(pdev, fiu);
+ fiu->dev = dev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
+ regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regbase))
+ return PTR_ERR(regbase);
+
+ fiu->regmap = devm_regmap_init_mmio(dev, regbase,
+ &npcm_mtd_regmap_config);
+ if (IS_ERR(fiu->regmap)) {
+ dev_err(dev, "Failed to create regmap\n");
+ return PTR_ERR(fiu->regmap);
+ }
+
+ fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "memory");
+ fiu->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(fiu->clk))
+ return PTR_ERR(fiu->clk);
+
+ fiu->spix_mode = of_property_read_bool(dev->of_node,
+ "nuvoton,spix-mode");
+
+ platform_set_drvdata(pdev, fiu);
+ clk_prepare_enable(fiu->clk);
+
+ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
+ | SPI_TX_DUAL | SPI_TX_QUAD;
+ ctrl->setup = npcm_fiu_setup;
+ ctrl->bus_num = -1;
+ ctrl->mem_ops = &npcm_fiu_mem_ops;
+ ctrl->num_chipselect = fiu->info->max_cs;
+ ctrl->dev.of_node = dev->of_node;
+
+ ret = devm_spi_register_master(dev, ctrl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int npcm_fiu_remove(struct platform_device *pdev)
+{
+ struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(fiu->clk);
+ return 0;
+}
+
+MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids);
+
+static struct platform_driver npcm_fiu_driver = {
+ .driver = {
+ .name = "NPCM-FIU",
+ .bus = &platform_bus_type,
+ .of_match_table = npcm_fiu_dt_ids,
+ },
+ .probe = npcm_fiu_probe,
+ .remove = npcm_fiu_remove,
+};
+module_platform_driver(npcm_fiu_driver);
+
+MODULE_DESCRIPTION("Nuvoton FLASH Interface Unit SPI Controller Driver");
+MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
index 734a2b956959..b191d57d1dc0 100644
--- a/drivers/spi/spi-npcm-pspi.c
+++ b/drivers/spi/spi-npcm-pspi.c
@@ -341,7 +341,6 @@ static int npcm_pspi_probe(struct platform_device *pdev)
{
struct npcm_pspi *priv;
struct spi_master *master;
- struct resource *res;
unsigned long clk_hz;
struct device_node *np = pdev->dev.of_node;
int num_cs, i;
@@ -368,8 +367,7 @@ static int npcm_pspi_probe(struct platform_device *pdev)
priv->is_save_param = false;
priv->id = pdev->id;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
goto out_master_put;
@@ -388,7 +386,6 @@ static int npcm_pspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to get IRQ\n");
ret = irq;
goto out_disable_clk;
}
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
deleted file mode 100644
index 37e2034ad4d5..000000000000
--- a/drivers/spi/spi-nuc900.c
+++ /dev/null
@@ -1,429 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2009 Nuvoton technology.
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <linux/platform_data/spi-nuc900.h>
-
-/* usi registers offset */
-#define USI_CNT 0x00
-#define USI_DIV 0x04
-#define USI_SSR 0x08
-#define USI_RX0 0x10
-#define USI_TX0 0x10
-
-/* usi register bit */
-#define ENINT (0x01 << 17)
-#define ENFLG (0x01 << 16)
-#define SLEEP (0x0f << 12)
-#define TXNUM (0x03 << 8)
-#define TXBITLEN (0x1f << 3)
-#define TXNEG (0x01 << 2)
-#define RXNEG (0x01 << 1)
-#define LSB (0x01 << 10)
-#define SELECTLEV (0x01 << 2)
-#define SELECTPOL (0x01 << 31)
-#define SELECTSLAVE 0x01
-#define GOBUSY 0x01
-
-struct nuc900_spi {
- struct spi_bitbang bitbang;
- struct completion done;
- void __iomem *regs;
- int irq;
- int len;
- int count;
- const unsigned char *tx;
- unsigned char *rx;
- struct clk *clk;
- struct spi_master *master;
- struct nuc900_spi_info *pdata;
- spinlock_t lock;
-};
-
-static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
-{
- return spi_master_get_devdata(sdev->master);
-}
-
-static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
-{
- struct nuc900_spi *hw = to_hw(spi);
- unsigned int val;
- unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
- unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_SSR);
-
- if (!cs)
- val &= ~SELECTLEV;
- else
- val |= SELECTLEV;
-
- if (!ssr)
- val &= ~SELECTSLAVE;
- else
- val |= SELECTSLAVE;
-
- __raw_writel(val, hw->regs + USI_SSR);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (!cpol)
- val &= ~SELECTPOL;
- else
- val |= SELECTPOL;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_chipsel(struct spi_device *spi, int value)
-{
- switch (value) {
- case BITBANG_CS_INACTIVE:
- nuc900_slave_select(spi, 0);
- break;
-
- case BITBANG_CS_ACTIVE:
- nuc900_slave_select(spi, 1);
- break;
- }
-}
-
-static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, unsigned int txnum)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT) & ~TXNUM;
-
- if (txnum)
- val |= txnum << 0x08;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-
-}
-
-static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw,
- unsigned int txbitlen)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT) & ~TXBITLEN;
-
- val |= (txbitlen << 0x03);
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_gobusy(struct nuc900_spi *hw)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- val |= GOBUSY;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
-{
- return hw->tx ? hw->tx[count] : 0;
-}
-
-static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct nuc900_spi *hw = to_hw(spi);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
- hw->count = 0;
-
- __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);
-
- nuc900_spi_gobusy(hw);
-
- wait_for_completion(&hw->done);
-
- return hw->count;
-}
-
-static irqreturn_t nuc900_spi_irq(int irq, void *dev)
-{
- struct nuc900_spi *hw = dev;
- unsigned int status;
- unsigned int count = hw->count;
-
- status = __raw_readl(hw->regs + USI_CNT);
- __raw_writel(status, hw->regs + USI_CNT);
-
- if (status & ENFLG) {
- hw->count++;
-
- if (hw->rx)
- hw->rx[count] = __raw_readl(hw->regs + USI_RX0);
- count++;
-
- if (count < hw->len) {
- __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0);
- nuc900_spi_gobusy(hw);
- } else {
- complete(&hw->done);
- }
-
- return IRQ_HANDLED;
- }
-
- complete(&hw->done);
- return IRQ_HANDLED;
-}
-
-static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (edge)
- val |= TXNEG;
- else
- val &= ~TXNEG;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (edge)
- val |= RXNEG;
- else
- val &= ~RXNEG;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (lsb)
- val |= LSB;
- else
- val &= ~LSB;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT) & ~SLEEP;
-
- if (sleep)
- val |= (sleep << 12);
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_enable_int(struct nuc900_spi *hw)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- val |= ENINT;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_divider(struct nuc900_spi *hw)
-{
- __raw_writel(hw->pdata->divider, hw->regs + USI_DIV);
-}
-
-static void nuc900_init_spi(struct nuc900_spi *hw)
-{
- clk_enable(hw->clk);
- spin_lock_init(&hw->lock);
-
- nuc900_tx_edge(hw, hw->pdata->txneg);
- nuc900_rx_edge(hw, hw->pdata->rxneg);
- nuc900_send_first(hw, hw->pdata->lsb);
- nuc900_set_sleep(hw, hw->pdata->sleep);
- nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen);
- nuc900_spi_setup_txnum(hw, hw->pdata->txnum);
- nuc900_set_divider(hw);
- nuc900_enable_int(hw);
-}
-
-static int nuc900_spi_probe(struct platform_device *pdev)
-{
- struct nuc900_spi *hw;
- struct spi_master *master;
- struct resource *res;
- int err = 0;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
- if (master == NULL) {
- dev_err(&pdev->dev, "No memory for spi_master\n");
- return -ENOMEM;
- }
-
- hw = spi_master_get_devdata(master);
- hw->master = master;
- hw->pdata = dev_get_platdata(&pdev->dev);
-
- if (hw->pdata == NULL) {
- dev_err(&pdev->dev, "No platform data supplied\n");
- err = -ENOENT;
- goto err_pdata;
- }
-
- platform_set_drvdata(pdev, hw);
- init_completion(&hw->done);
-
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- if (hw->pdata->lsb)
- master->mode_bits |= SPI_LSB_FIRST;
- master->num_chipselect = hw->pdata->num_cs;
- master->bus_num = hw->pdata->bus_num;
- hw->bitbang.master = hw->master;
- hw->bitbang.chipselect = nuc900_spi_chipsel;
- hw->bitbang.txrx_bufs = nuc900_spi_txrx;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hw->regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(hw->regs)) {
- err = PTR_ERR(hw->regs);
- goto err_pdata;
- }
-
- hw->irq = platform_get_irq(pdev, 0);
- if (hw->irq < 0) {
- dev_err(&pdev->dev, "No IRQ specified\n");
- err = -ENOENT;
- goto err_pdata;
- }
-
- err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0,
- pdev->name, hw);
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_pdata;
- }
-
- hw->clk = devm_clk_get(&pdev->dev, "spi");
- if (IS_ERR(hw->clk)) {
- dev_err(&pdev->dev, "No clock for device\n");
- err = PTR_ERR(hw->clk);
- goto err_pdata;
- }
-
- mfp_set_groupg(&pdev->dev, NULL);
- nuc900_init_spi(hw);
-
- err = spi_bitbang_start(&hw->bitbang);
- if (err) {
- dev_err(&pdev->dev, "Failed to register SPI master\n");
- goto err_register;
- }
-
- return 0;
-
-err_register:
- clk_disable(hw->clk);
-err_pdata:
- spi_master_put(hw->master);
- return err;
-}
-
-static int nuc900_spi_remove(struct platform_device *dev)
-{
- struct nuc900_spi *hw = platform_get_drvdata(dev);
-
- spi_bitbang_stop(&hw->bitbang);
- clk_disable(hw->clk);
- spi_master_put(hw->master);
- return 0;
-}
-
-static struct platform_driver nuc900_spi_driver = {
- .probe = nuc900_spi_probe,
- .remove = nuc900_spi_remove,
- .driver = {
- .name = "nuc900-spi",
- },
-};
-module_platform_driver(nuc900_spi_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("nuc900 spi driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-spi");
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 8894f98cc99c..501b923f2c27 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -1007,10 +1007,8 @@ static int nxp_fspi_probe(struct platform_device *pdev)
/* find the irq */
ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "failed to get the irq: %d\n", ret);
+ if (ret < 0)
goto err_disable_clk;
- }
ret = devm_request_irq(dev, ret,
nxp_fspi_irq_handler, 0, pdev->name, f);
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index bbc4ba66571f..e2331eb7b47a 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -240,7 +240,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
struct tiny_spi *hw;
struct spi_master *master;
- struct resource *res;
unsigned int i;
int err = -ENODEV;
@@ -264,8 +263,7 @@ static int tiny_spi_probe(struct platform_device *pdev)
hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
/* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hw->base = devm_ioremap_resource(&pdev->dev, res);
+ hw->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->base)) {
err = PTR_ERR(hw->base);
goto exit;
diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c
index b635526ad414..86ad17597f5f 100644
--- a/drivers/spi/spi-pic32-sqi.c
+++ b/drivers/spi/spi-pic32-sqi.c
@@ -570,7 +570,6 @@ static int pic32_sqi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct pic32_sqi *sqi;
- struct resource *reg;
int ret;
master = spi_alloc_master(&pdev->dev, sizeof(*sqi));
@@ -580,8 +579,7 @@ static int pic32_sqi_probe(struct platform_device *pdev)
sqi = spi_master_get_devdata(master);
sqi->master = master;
- reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sqi->regs = devm_ioremap_resource(&pdev->dev, reg);
+ sqi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sqi->regs)) {
ret = PTR_ERR(sqi->regs);
goto err_free_master;
@@ -590,7 +588,6 @@ static int pic32_sqi_probe(struct platform_device *pdev)
/* irq */
sqi->irq = platform_get_irq(pdev, 0);
if (sqi->irq < 0) {
- dev_err(&pdev->dev, "no irq found\n");
ret = sqi->irq;
goto err_free_master;
}
diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c
index 10cebeaa1e6b..69f517ec59c6 100644
--- a/drivers/spi/spi-pic32.c
+++ b/drivers/spi/spi-pic32.c
@@ -711,22 +711,16 @@ static int pic32_spi_hw_probe(struct platform_device *pdev,
/* get irq resources: err-irq, rx-irq, tx-irq */
pic32s->fault_irq = platform_get_irq_byname(pdev, "fault");
- if (pic32s->fault_irq < 0) {
- dev_err(&pdev->dev, "fault-irq not found\n");
+ if (pic32s->fault_irq < 0)
return pic32s->fault_irq;
- }
pic32s->rx_irq = platform_get_irq_byname(pdev, "rx");
- if (pic32s->rx_irq < 0) {
- dev_err(&pdev->dev, "rx-irq not found\n");
+ if (pic32s->rx_irq < 0)
return pic32s->rx_irq;
- }
pic32s->tx_irq = platform_get_irq_byname(pdev, "tx");
- if (pic32s->tx_irq < 0) {
- dev_err(&pdev->dev, "tx-irq not found\n");
+ if (pic32s->tx_irq < 0)
return pic32s->tx_irq;
- }
/* get clock */
pic32s->clk = devm_clk_get(&pdev->dev, "mck0");
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index fc7ab4b26880..bb6a14d1ab0f 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1457,6 +1457,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
{ PCI_VDEVICE(INTEL, 0x02aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x02ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x02fb), LPSS_CNL_SSP },
+ /* TGL-LP */
+ { PCI_VDEVICE(INTEL, 0xa0aa), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0ab), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0de), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0df), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0fb), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0fd), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0xa0fe), LPSS_CNL_SSP },
{ },
};
@@ -1831,14 +1839,16 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
status = devm_spi_register_controller(&pdev->dev, controller);
if (status != 0) {
dev_err(&pdev->dev, "problem registering spi controller\n");
- goto out_error_clock_enabled;
+ goto out_error_pm_runtime_enabled;
}
return status;
-out_error_clock_enabled:
+out_error_pm_runtime_enabled:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+
+out_error_clock_enabled:
clk_disable_unprepare(ssp->clk);
out_error_dma_irq_alloc:
diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index e0f061139c8f..250fd60e1678 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -424,7 +424,6 @@ static int qcom_qspi_probe(struct platform_device *pdev)
{
int ret;
struct device *dev;
- struct resource *res;
struct spi_master *master;
struct qcom_qspi *ctrl;
@@ -440,8 +439,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
spin_lock_init(&ctrl->lock);
ctrl->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ctrl->base = devm_ioremap_resource(dev, res);
+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctrl->base)) {
ret = PTR_ERR(ctrl->base);
goto exit_probe_master_put;
@@ -454,10 +452,8 @@ static int qcom_qspi_probe(struct platform_device *pdev)
goto exit_probe_master_put;
ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "Failed to get irq %d\n", ret);
+ if (ret < 0)
goto exit_probe_master_put;
- }
ret = devm_request_irq(dev, ret, qcom_qspi_irq,
IRQF_TRIGGER_HIGH, dev_name(dev), ctrl);
if (ret) {
diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c
index 51f03d977ad6..4c9620e0d18c 100644
--- a/drivers/spi/spi-rb4xx.c
+++ b/drivers/spi/spi-rb4xx.c
@@ -135,12 +135,10 @@ static int rb4xx_spi_probe(struct platform_device *pdev)
struct spi_master *master;
struct clk *ahb_clk;
struct rb4xx_spi *rbspi;
- struct resource *r;
int err;
void __iomem *spi_base;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spi_base = devm_ioremap_resource(&pdev->dev, r);
+ spi_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spi_base))
return PTR_ERR(spi_base);
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 48d8dff05a3a..2d6e37f25e2d 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -487,7 +487,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
struct s3c2410_spi_info *pdata;
struct s3c24xx_spi *hw;
struct spi_master *master;
- struct resource *res;
int err = 0;
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
@@ -536,8 +535,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
/* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hw->regs = devm_ioremap_resource(&pdev->dev, res);
+ hw->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->regs)) {
err = PTR_ERR(hw->regs);
goto err_no_pdata;
@@ -545,7 +543,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) {
- dev_err(&pdev->dev, "No IRQ specified\n");
err = -ENOENT;
goto err_no_pdata;
}
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index b50bdbc27e58..8f134735291f 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -1297,7 +1297,6 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
static int sh_msiof_spi_probe(struct platform_device *pdev)
{
- struct resource *r;
struct spi_controller *ctlr;
const struct sh_msiof_chipdata *chipdata;
struct sh_msiof_spi_info *info;
@@ -1346,13 +1345,11 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
i = platform_get_irq(pdev, 0);
if (i < 0) {
- dev_err(&pdev->dev, "cannot get IRQ\n");
ret = i;
goto err1;
}
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- p->mapbase = devm_ioremap_resource(&pdev->dev, r);
+ p->mapbase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(p->mapbase)) {
ret = PTR_ERR(p->mapbase);
goto err1;
diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c
index f1ee58208216..20bdae5fdf3b 100644
--- a/drivers/spi/spi-sh.c
+++ b/drivers/spi/spi-sh.c
@@ -437,10 +437,8 @@ static int spi_sh_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "platform_get_irq error: %d\n", irq);
+ if (irq < 0)
return irq;
- }
master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
if (master == NULL) {
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
index 93ec2c6cdbfd..35254bdc42c4 100644
--- a/drivers/spi/spi-sifive.c
+++ b/drivers/spi/spi-sifive.c
@@ -292,7 +292,6 @@ sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device,
static int sifive_spi_probe(struct platform_device *pdev)
{
struct sifive_spi *spi;
- struct resource *res;
int ret, irq, num_cs;
u32 cs_bits, max_bits_per_word;
struct spi_master *master;
@@ -307,8 +306,7 @@ static int sifive_spi_probe(struct platform_device *pdev)
init_completion(&spi->done);
platform_set_drvdata(pdev, master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spi->regs = devm_ioremap_resource(&pdev->dev, res);
+ spi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spi->regs)) {
ret = PTR_ERR(spi->regs);
goto put_master;
@@ -323,7 +321,6 @@ static int sifive_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "Unable to find interrupt\n");
ret = irq;
goto put_master;
}
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index 71b882ab31b9..e1e639191557 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -1070,7 +1070,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
{
struct sirfsoc_spi *sspi;
struct spi_master *master;
- struct resource *mem_res;
const struct sirf_spi_comp_data *spi_comp_data;
int irq;
int ret;
@@ -1097,8 +1096,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1;
sspi->dat_max_frm_len = spi_comp_data->dat_max_frm_len;
sspi->fifo_size = spi_comp_data->fifo_size;
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sspi->base = devm_ioremap_resource(&pdev->dev, mem_res);
+ sspi->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sspi->base)) {
ret = PTR_ERR(sspi->base);
goto free_master;
diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c
index d1075433f6a6..61bc43b0fe57 100644
--- a/drivers/spi/spi-slave-mt27xx.c
+++ b/drivers/spi/spi-slave-mt27xx.c
@@ -410,7 +410,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to get irq (%d)\n", irq);
ret = irq;
goto err_put_ctlr;
}
diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c
index df5960bddfe6..9a051286f120 100644
--- a/drivers/spi/spi-sprd-adi.c
+++ b/drivers/spi/spi-sprd-adi.c
@@ -86,6 +86,7 @@
#define BIT_WDG_EN BIT(2)
/* Definition of PMIC reset status register */
+#define HWRST_STATUS_SECURITY 0x02
#define HWRST_STATUS_RECOVERY 0x20
#define HWRST_STATUS_NORMAL 0x40
#define HWRST_STATUS_ALARM 0x50
@@ -97,6 +98,8 @@
#define HWRST_STATUS_AUTODLOADER 0xa0
#define HWRST_STATUS_IQMODE 0xb0
#define HWRST_STATUS_SPRDISK 0xc0
+#define HWRST_STATUS_FACTORYTEST 0xe0
+#define HWRST_STATUS_WATCHDOG 0xf0
/* Use default timeout 50 ms that converts to watchdog values */
#define WDG_LOAD_VAL ((50 * 1000) / 32768)
@@ -162,14 +165,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
int read_timeout = ADI_READ_TIMEOUT;
unsigned long flags;
u32 val, rd_addr;
- int ret;
-
- ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
- ADI_HWSPINLOCK_TIMEOUT,
- &flags);
- if (ret) {
- dev_err(sadi->dev, "get the hw lock failed\n");
- return ret;
+ int ret = 0;
+
+ if (sadi->hwlock) {
+ ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
+ ADI_HWSPINLOCK_TIMEOUT,
+ &flags);
+ if (ret) {
+ dev_err(sadi->dev, "get the hw lock failed\n");
+ return ret;
+ }
}
/*
@@ -216,7 +221,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
*read_val = val & RD_VALUE_MASK;
out:
- hwspin_unlock_irqrestore(sadi->hwlock, &flags);
+ if (sadi->hwlock)
+ hwspin_unlock_irqrestore(sadi->hwlock, &flags);
return ret;
}
@@ -227,12 +233,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
unsigned long flags;
int ret;
- ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
- ADI_HWSPINLOCK_TIMEOUT,
- &flags);
- if (ret) {
- dev_err(sadi->dev, "get the hw lock failed\n");
- return ret;
+ if (sadi->hwlock) {
+ ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
+ ADI_HWSPINLOCK_TIMEOUT,
+ &flags);
+ if (ret) {
+ dev_err(sadi->dev, "get the hw lock failed\n");
+ return ret;
+ }
}
ret = sprd_adi_drain_fifo(sadi);
@@ -258,7 +266,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
}
out:
- hwspin_unlock_irqrestore(sadi->hwlock, &flags);
+ if (sadi->hwlock)
+ hwspin_unlock_irqrestore(sadi->hwlock, &flags);
return ret;
}
@@ -307,6 +316,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr,
return 0;
}
+static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi)
+{
+#ifdef CONFIG_SPRD_WATCHDOG
+ u32 val;
+
+ /* Set default watchdog reboot mode */
+ sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
+ val |= HWRST_STATUS_WATCHDOG;
+ sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
+#endif
+}
+
static int sprd_adi_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
{
@@ -336,11 +357,16 @@ static int sprd_adi_restart_handler(struct notifier_block *this,
reboot_mode = HWRST_STATUS_IQMODE;
else if (!strncmp(cmd, "sprdisk", 7))
reboot_mode = HWRST_STATUS_SPRDISK;
+ else if (!strncmp(cmd, "tospanic", 8))
+ reboot_mode = HWRST_STATUS_SECURITY;
+ else if (!strncmp(cmd, "factorytest", 11))
+ reboot_mode = HWRST_STATUS_FACTORYTEST;
else
reboot_mode = HWRST_STATUS_NORMAL;
/* Record the reboot mode */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
+ val &= ~HWRST_STATUS_WATCHDOG;
val |= reboot_mode;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
@@ -380,9 +406,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi)
const __be32 *list;
u32 tmp;
- /* Address bits select default 12 bits */
- writel_relaxed(0, sadi->base + REG_ADI_CTRL0);
-
/* Set all channels as default priority */
writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL);
writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH);
@@ -459,19 +482,30 @@ static int sprd_adi_probe(struct platform_device *pdev)
sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET;
sadi->ctlr = ctlr;
sadi->dev = &pdev->dev;
- ret = of_hwspin_lock_get_id_byname(np, "adi");
- if (ret < 0) {
- dev_err(&pdev->dev, "can not get the hardware spinlock\n");
- goto put_ctlr;
- }
-
- sadi->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret);
- if (!sadi->hwlock) {
- ret = -ENXIO;
- goto put_ctlr;
+ ret = of_hwspin_lock_get_id(np, 0);
+ if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
+ sadi->hwlock =
+ devm_hwspin_lock_request_specific(&pdev->dev, ret);
+ if (!sadi->hwlock) {
+ ret = -ENXIO;
+ goto put_ctlr;
+ }
+ } else {
+ switch (ret) {
+ case -ENOENT:
+ dev_info(&pdev->dev, "no hardware spinlock supplied\n");
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "failed to find hwlock id, %d\n", ret);
+ /* fall-through */
+ case -EPROBE_DEFER:
+ goto put_ctlr;
+ }
}
sprd_adi_hw_init(sadi);
+ sprd_adi_set_wdt_rst_mode(sadi);
ctlr->dev.of_node = pdev->dev.of_node;
ctlr->bus_num = pdev->id;
diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c
index 1b7eebb72c07..8c9021b7f7a9 100644
--- a/drivers/spi/spi-sprd.c
+++ b/drivers/spi/spi-sprd.c
@@ -843,10 +843,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss)
int ret;
ss->irq = platform_get_irq(pdev, 0);
- if (ss->irq < 0) {
- dev_err(&pdev->dev, "failed to get irq resource\n");
+ if (ss->irq < 0)
return ss->irq;
- }
ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq,
0, pdev->name, ss);
diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c
index 840a6bf81336..0c24c494f386 100644
--- a/drivers/spi/spi-st-ssc4.c
+++ b/drivers/spi/spi-st-ssc4.c
@@ -298,7 +298,6 @@ static int spi_st_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct spi_master *master;
- struct resource *res;
struct spi_st *spi_st;
int irq, ret = 0;
u32 var;
@@ -331,8 +330,7 @@ static int spi_st_probe(struct platform_device *pdev)
init_completion(&spi_st->done);
/* Get resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spi_st->base = devm_ioremap_resource(&pdev->dev, res);
+ spi_st->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spi_st->base)) {
ret = PTR_ERR(spi_st->base);
goto clk_disable;
diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
index 655e4afbfb2a..9ac6f9fe13cf 100644
--- a/drivers/spi/spi-stm32-qspi.c
+++ b/drivers/spi/spi-stm32-qspi.c
@@ -570,11 +570,8 @@ static int stm32_qspi_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- if (irq != -EPROBE_DEFER)
- dev_err(dev, "IRQ error missing or invalid\n");
+ if (irq < 0)
return irq;
- }
ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
dev_name(dev), qspi);
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 5194bc07fd60..cbfac6596fad 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -428,7 +428,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct sun4i_spi *sspi;
- struct resource *res;
int ret = 0, irq;
master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
@@ -440,8 +439,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sspi->base_addr)) {
ret = PTR_ERR(sspi->base_addr);
goto err_free_master;
@@ -449,7 +447,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "No spi IRQ specified\n");
ret = -ENXIO;
goto err_free_master;
}
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index ee2bdaf5b856..ec7967be9e2f 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -435,7 +435,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct sun6i_spi *sspi;
- struct resource *res;
int ret = 0, irq;
master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
@@ -447,8 +446,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sspi->base_addr)) {
ret = PTR_ERR(sspi->base_addr);
goto err_free_master;
@@ -456,7 +454,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "No spi IRQ specified\n");
ret = -ENXIO;
goto err_free_master;
}
diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c
index f99abd85c50a..ae17c99cce03 100644
--- a/drivers/spi/spi-synquacer.c
+++ b/drivers/spi/spi-synquacer.c
@@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev)
rx_irq = platform_get_irq(pdev, 0);
if (rx_irq <= 0) {
- dev_err(&pdev->dev, "get rx_irq failed (%d)\n", rx_irq);
ret = rx_irq;
goto put_spi;
}
@@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev)
tx_irq = platform_get_irq(pdev, 1);
if (tx_irq <= 0) {
- dev_err(&pdev->dev, "get tx_irq failed (%d)\n", tx_irq);
ret = tx_irq;
goto put_spi;
}
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index cd714a4f52c6..a841a7250d14 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -419,7 +419,6 @@ static int tegra_sflash_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct tegra_sflash_data *tsd;
- struct resource *r;
int ret;
const struct of_device_id *match;
@@ -451,8 +450,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
&master->max_speed_hz))
master->max_speed_hz = 25000000; /* 25MHz */
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- tsd->base = devm_ioremap_resource(&pdev->dev, r);
+ tsd->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(tsd->base)) {
ret = PTR_ERR(tsd->base);
goto exit_free_master;
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 6ca600702470..3cb65371ae3b 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -717,7 +717,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "no irq resource?\n");
ret = irq;
goto free_master;
}
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index b32c77df5d49..47cde1864630 100644
--- a/drivers/spi/spi-uniphier.c
+++ b/drivers/spi/spi-uniphier.c
@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -16,6 +17,7 @@
#include <asm/unaligned.h>
#define SSI_TIMEOUT_MS 2000
+#define SSI_POLL_TIMEOUT_US 200
#define SSI_MAX_CLK_DIVIDER 254
#define SSI_MIN_CLK_DIVIDER 4
@@ -214,6 +216,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi,
if (!priv->is_save_param || priv->mode != spi->mode) {
uniphier_spi_set_mode(spi);
priv->mode = spi->mode;
+ priv->is_save_param = false;
}
if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
@@ -226,8 +229,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi,
priv->speed_hz = t->speed_hz;
}
- if (!priv->is_save_param)
- priv->is_save_param = true;
+ priv->is_save_param = true;
/* reset FIFOs */
val = SSI_FC_TXFFL | SSI_FC_RXFFL;
@@ -290,21 +292,23 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
{
- unsigned int tx_count;
+ unsigned int fifo_threshold, fill_bytes;
u32 val;
- tx_count = DIV_ROUND_UP(priv->tx_bytes,
+ fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
bytes_per_word(priv->bits_per_word));
- tx_count = min(tx_count, SSI_FIFO_DEPTH);
+ fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
+
+ fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
/* set fifo threshold */
val = readl(priv->base + SSI_FC);
val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
- val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count);
- val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count);
+ val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
+ val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
writel(val, priv->base + SSI_FC);
- while (tx_count--)
+ while (fill_bytes--)
uniphier_spi_send(priv);
}
@@ -323,20 +327,14 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable)
writel(val, priv->base + SSI_FPS);
}
-static int uniphier_spi_transfer_one(struct spi_master *master,
- struct spi_device *spi,
- struct spi_transfer *t)
+static int uniphier_spi_transfer_one_irq(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *t)
{
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
struct device *dev = master->dev.parent;
unsigned long time_left;
- /* Terminate and return success for 0 byte length transfer */
- if (!t->len)
- return 0;
-
- uniphier_spi_setup_transfer(spi, t);
-
reinit_completion(&priv->xfer_done);
uniphier_spi_fill_tx_fifo(priv);
@@ -356,6 +354,59 @@ static int uniphier_spi_transfer_one(struct spi_master *master,
return priv->error;
}
+static int uniphier_spi_transfer_one_poll(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
+ int loop = SSI_POLL_TIMEOUT_US * 10;
+
+ while (priv->tx_bytes) {
+ uniphier_spi_fill_tx_fifo(priv);
+
+ while ((priv->rx_bytes - priv->tx_bytes) > 0) {
+ while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE)
+ && loop--)
+ ndelay(100);
+
+ if (loop == -1)
+ goto irq_transfer;
+
+ uniphier_spi_recv(priv);
+ }
+ }
+
+ return 0;
+
+irq_transfer:
+ return uniphier_spi_transfer_one_irq(master, spi, t);
+}
+
+static int uniphier_spi_transfer_one(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
+ unsigned long threshold;
+
+ /* Terminate and return success for 0 byte length transfer */
+ if (!t->len)
+ return 0;
+
+ uniphier_spi_setup_transfer(spi, t);
+
+ /*
+ * If the transfer operation will take longer than
+ * SSI_POLL_TIMEOUT_US, it should use irq.
+ */
+ threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz,
+ USEC_PER_SEC * BITS_PER_BYTE);
+ if (t->len > threshold)
+ return uniphier_spi_transfer_one_irq(master, spi, t);
+ else
+ return uniphier_spi_transfer_one_poll(master, spi, t);
+}
+
static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master)
{
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
@@ -419,7 +470,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
{
struct uniphier_spi_priv *priv;
struct spi_master *master;
- struct resource *res;
unsigned long clk_rate;
int irq;
int ret;
@@ -434,8 +484,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
priv->master = master;
priv->is_save_param = false;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
goto out_master_put;
@@ -454,7 +503,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to get IRQ\n");
ret = irq;
goto out_disable_clk;
}
diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c
index 1dc479fab98c..797ac0ea8fa3 100644
--- a/drivers/spi/spi-xlp.c
+++ b/drivers/spi/spi-xlp.c
@@ -370,7 +370,6 @@ static int xlp_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct xlp_spi_priv *xspi;
- struct resource *res;
struct clk *clk;
int irq, err;
@@ -378,16 +377,13 @@ static int xlp_spi_probe(struct platform_device *pdev)
if (!xspi)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xspi->base = devm_ioremap_resource(&pdev->dev, res);
+ xspi->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xspi->base))
return PTR_ERR(xspi->base);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq);
+ if (irq < 0)
return irq;
- }
err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0,
pdev->name, xspi);
if (err) {
diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c
index c6bee67decb5..5cf6993ddce5 100644
--- a/drivers/spi/spi-zynq-qspi.c
+++ b/drivers/spi/spi-zynq-qspi.c
@@ -620,7 +620,6 @@ static int zynq_qspi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct zynq_qspi *xqspi;
- struct resource *res;
u32 num_cs;
ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
@@ -630,8 +629,7 @@ static int zynq_qspi_probe(struct platform_device *pdev)
xqspi = spi_controller_get_devdata(ctlr);
xqspi->dev = dev;
platform_set_drvdata(pdev, xqspi);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xqspi->regs = devm_ioremap_resource(&pdev->dev, res);
+ xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xqspi->regs)) {
ret = PTR_ERR(xqspi->regs);
goto remove_master;
@@ -671,7 +669,6 @@ static int zynq_qspi_probe(struct platform_device *pdev)
xqspi->irq = platform_get_irq(pdev, 0);
if (xqspi->irq <= 0) {
ret = -ENXIO;
- dev_err(&pdev->dev, "irq resource not found\n");
goto remove_master;
}
ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq,
@@ -695,7 +692,7 @@ static int zynq_qspi_probe(struct platform_device *pdev)
ctlr->setup = zynq_qspi_setup_op;
ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
ctlr->dev.of_node = np;
- ret = spi_register_controller(ctlr);
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret) {
dev_err(&pdev->dev, "spi_register_master failed\n");
goto clk_dis_all;
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 07a83ca164c2..60c4de4e4485 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -1016,7 +1016,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
int ret = 0;
struct spi_master *master;
struct zynqmp_qspi *xqspi;
- struct resource *res;
struct device *dev = &pdev->dev;
eemi_ops = zynqmp_pm_get_eemi_ops();
@@ -1031,8 +1030,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
master->dev.of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, master);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xqspi->regs = devm_ioremap_resource(&pdev->dev, res);
+ xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xqspi->regs)) {
ret = PTR_ERR(xqspi->regs);
goto remove_master;
@@ -1077,7 +1075,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
xqspi->irq = platform_get_irq(pdev, 0);
if (xqspi->irq <= 0) {
ret = -ENXIO;
- dev_err(dev, "irq resource not found\n");
goto clk_dis_all;
}
ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 75ac046cae52..f8b4654a57d3 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1265,8 +1265,9 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
*/
static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
{
- unsigned long flags;
+ struct spi_message *msg;
bool was_busy = false;
+ unsigned long flags;
int ret;
/* Lock queue */
@@ -1325,10 +1326,10 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
}
/* Extract head of queue */
- ctlr->cur_msg =
- list_first_entry(&ctlr->queue, struct spi_message, queue);
+ msg = list_first_entry(&ctlr->queue, struct spi_message, queue);
+ ctlr->cur_msg = msg;
- list_del_init(&ctlr->cur_msg->queue);
+ list_del_init(&msg->queue);
if (ctlr->busy)
was_busy = true;
else
@@ -1361,7 +1362,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
if (ctlr->auto_runtime_pm)
pm_runtime_put(ctlr->dev.parent);
- ctlr->cur_msg->status = ret;
+ msg->status = ret;
spi_finalize_current_message(ctlr);
mutex_unlock(&ctlr->io_mutex);
@@ -1369,28 +1370,28 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
}
}
- trace_spi_message_start(ctlr->cur_msg);
+ trace_spi_message_start(msg);
if (ctlr->prepare_message) {
- ret = ctlr->prepare_message(ctlr, ctlr->cur_msg);
+ ret = ctlr->prepare_message(ctlr, msg);
if (ret) {
dev_err(&ctlr->dev, "failed to prepare message: %d\n",
ret);
- ctlr->cur_msg->status = ret;
+ msg->status = ret;
spi_finalize_current_message(ctlr);
goto out;
}
ctlr->cur_msg_prepared = true;
}
- ret = spi_map_msg(ctlr, ctlr->cur_msg);
+ ret = spi_map_msg(ctlr, msg);
if (ret) {
- ctlr->cur_msg->status = ret;
+ msg->status = ret;
spi_finalize_current_message(ctlr);
goto out;
}
- ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg);
+ ret = ctlr->transfer_one_message(ctlr, msg);
if (ret) {
dev_err(&ctlr->dev,
"failed to transfer one message from queue\n");
@@ -1434,7 +1435,7 @@ static void spi_pump_messages(struct kthread_work *work)
*/
static void spi_set_thread_rt(struct spi_controller *ctlr)
{
- struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 };
dev_info(&ctlr->dev,
"will run message pump with realtime priority\n");
@@ -2105,8 +2106,8 @@ static int match_true(struct device *dev, void *data)
return 1;
}
-static ssize_t spi_slave_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t slave_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct spi_controller *ctlr = container_of(dev, struct spi_controller,
dev);
@@ -2117,9 +2118,8 @@ static ssize_t spi_slave_show(struct device *dev,
child ? to_spi_device(child)->modalias : NULL);
}
-static ssize_t spi_slave_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
+static ssize_t slave_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct spi_controller *ctlr = container_of(dev, struct spi_controller,
dev);
@@ -2157,7 +2157,7 @@ static ssize_t spi_slave_store(struct device *dev,
return count;
}
-static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store);
+static DEVICE_ATTR_RW(slave);
static struct attribute *spi_slave_attrs[] = {
&dev_attr_slave.attr,
@@ -2188,8 +2188,10 @@ extern struct class spi_slave_class; /* dummy */
* __spi_alloc_controller - allocate an SPI master or slave controller
* @dev: the controller, possibly using the platform_bus
* @size: how much zeroed driver-private data to allocate; the pointer to this
- * memory is in the driver_data field of the returned device,
- * accessible with spi_controller_get_devdata().
+ * memory is in the driver_data field of the returned device, accessible
+ * with spi_controller_get_devdata(); the memory is cacheline aligned;
+ * drivers granting DMA access to portions of their private data need to
+ * round up @size using ALIGN(size, dma_get_cache_alignment()).
* @slave: flag indicating whether to allocate an SPI master (false) or SPI
* slave (true) controller
* Context: can sleep
@@ -2211,11 +2213,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
unsigned int size, bool slave)
{
struct spi_controller *ctlr;
+ size_t ctlr_size = ALIGN(sizeof(*ctlr), dma_get_cache_alignment());
if (!dev)
return NULL;
- ctlr = kzalloc(size + sizeof(*ctlr), GFP_KERNEL);
+ ctlr = kzalloc(size + ctlr_size, GFP_KERNEL);
if (!ctlr)
return NULL;
@@ -2229,14 +2232,14 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
ctlr->dev.class = &spi_master_class;
ctlr->dev.parent = dev;
pm_suspend_ignore_children(&ctlr->dev, true);
- spi_controller_set_devdata(ctlr, &ctlr[1]);
+ spi_controller_set_devdata(ctlr, (void *)ctlr + ctlr_size);
return ctlr;
}
EXPORT_SYMBOL_GPL(__spi_alloc_controller);
#ifdef CONFIG_OF
-static int of_spi_register_master(struct spi_controller *ctlr)
+static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
{
int nb, i, *cs;
struct device_node *np = ctlr->dev.of_node;
@@ -2269,7 +2272,7 @@ static int of_spi_register_master(struct spi_controller *ctlr)
return 0;
}
#else
-static int of_spi_register_master(struct spi_controller *ctlr)
+static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
{
return 0;
}
@@ -2456,7 +2459,7 @@ int spi_register_controller(struct spi_controller *ctlr)
ctlr->mode_bits |= SPI_CS_HIGH;
} else {
/* Legacy code path for GPIOs from DT */
- status = of_spi_register_master(ctlr);
+ status = of_spi_get_gpio_numbers(ctlr);
if (status)
return status;
}
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index fd4995fb676e..f85ec5b16b65 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -8,11 +8,14 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/swap.h>
+#include <linux/sched/signal.h>
#include "ion.h"
static inline struct page *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
{
+ if (fatal_signal_pending(current))
+ return NULL;
return alloc_pages(pool->gfp_mask, pool->order);
}
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 2edf3ee91300..caf4d4df4bd3 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -342,9 +342,9 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
unsigned int flags)
{
- int divider, base, prescale;
+ unsigned int divider, base, prescale;
- /* This function needs improvment */
+ /* This function needs improvement */
/* Don't know if divider==0 works. */
for (prescale = 0; prescale < 16; prescale++) {
@@ -358,7 +358,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
divider = (*nanosec) / base;
break;
case CMDF_ROUND_UP:
- divider = (*nanosec) / base;
+ divider = DIV_ROUND_UP(*nanosec, base);
break;
}
if (divider < 65536) {
@@ -368,7 +368,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
}
prescale = 15;
- base = timer_base * (1 << prescale);
+ base = timer_base * (prescale + 1);
divider = 65535;
*nanosec = divider * base;
return (prescale << 16) | (divider);
diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c
index b6c6d66e4eb1..e2c7646588f8 100644
--- a/drivers/staging/fbtft/fb_bd663474.c
+++ b/drivers/staging/fbtft/fb_bd663474.c
@@ -24,7 +24,7 @@
static int init_display(struct fbtft_par *par)
{
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
par->fbtftops.reset(par);
diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c
index d609a2b67db9..fd32376700e2 100644
--- a/drivers/staging/fbtft/fb_ili9163.c
+++ b/drivers/staging/fbtft/fb_ili9163.c
@@ -77,7 +77,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c
index b090e7ab6fdd..85e54a10ed72 100644
--- a/drivers/staging/fbtft/fb_ili9325.c
+++ b/drivers/staging/fbtft/fb_ili9325.c
@@ -85,7 +85,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
bt &= 0x07;
diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c
index b3d0701880fe..5a129b1352cc 100644
--- a/drivers/staging/fbtft/fb_s6d1121.c
+++ b/drivers/staging/fbtft/fb_s6d1121.c
@@ -29,7 +29,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
/* Initialization sequence from Lib_UTFT */
diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c
index bbf75f795234..88a5b6925901 100644
--- a/drivers/staging/fbtft/fb_ssd1289.c
+++ b/drivers/staging/fbtft/fb_ssd1289.c
@@ -28,7 +28,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
write_reg(par, 0x00, 0x0001);
diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c
index 4cfe9f8535d0..37622c9462aa 100644
--- a/drivers/staging/fbtft/fb_ssd1331.c
+++ b/drivers/staging/fbtft/fb_ssd1331.c
@@ -81,7 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
va_start(args, len);
*buf = (u8)va_arg(args, unsigned int);
- if (!par->gpio.dc)
+ if (par->gpio.dc)
gpiod_set_value(par->gpio.dc, 0);
ret = par->fbtftops.write(par, par->buf, sizeof(u8));
if (ret < 0) {
@@ -104,7 +104,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
return;
}
}
- if (!par->gpio.dc)
+ if (par->gpio.dc)
gpiod_set_value(par->gpio.dc, 1);
va_end(args);
}
diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c
index 564a38e34440..c77832ae5e5b 100644
--- a/drivers/staging/fbtft/fb_upd161704.c
+++ b/drivers/staging/fbtft/fb_upd161704.c
@@ -26,7 +26,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
/* Initialization sequence from Lib_UTFT */
diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c
index 2ea814d0dca5..63c65dd67b17 100644
--- a/drivers/staging/fbtft/fbtft-bus.c
+++ b/drivers/staging/fbtft/fbtft-bus.c
@@ -135,7 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
remain = len / 2;
vmem16 = (u16 *)(par->info->screen_buffer + offset);
- if (!par->gpio.dc)
+ if (par->gpio.dc)
gpiod_set_value(par->gpio.dc, 1);
/* non buffered write */
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 7cbc1bdd2d8a..cf5700a2ea66 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -76,21 +76,18 @@ static int fbtft_request_one_gpio(struct fbtft_par *par,
struct gpio_desc **gpiop)
{
struct device *dev = par->info->device;
- struct device_node *node = dev->of_node;
int ret = 0;
- if (of_find_property(node, name, NULL)) {
- *gpiop = devm_gpiod_get_index(dev, dev->driver->name, index,
- GPIOD_OUT_HIGH);
- if (IS_ERR(*gpiop)) {
- ret = PTR_ERR(*gpiop);
- dev_err(dev,
- "Failed to request %s GPIO:%d\n", name, ret);
- return ret;
- }
- fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
- __func__, name);
+ *gpiop = devm_gpiod_get_index_optional(dev, name, index,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(*gpiop)) {
+ ret = PTR_ERR(*gpiop);
+ dev_err(dev,
+ "Failed to request %s GPIO: %d\n", name, ret);
+ return ret;
}
+ fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
+ __func__, name);
return ret;
}
@@ -103,34 +100,34 @@ static int fbtft_request_gpios_dt(struct fbtft_par *par)
if (!par->info->device->of_node)
return -EINVAL;
- ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
+ ret = fbtft_request_one_gpio(par, "reset", 0, &par->gpio.reset);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
+ ret = fbtft_request_one_gpio(par, "dc", 0, &par->gpio.dc);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
+ ret = fbtft_request_one_gpio(par, "rd", 0, &par->gpio.rd);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
+ ret = fbtft_request_one_gpio(par, "wr", 0, &par->gpio.wr);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
+ ret = fbtft_request_one_gpio(par, "cs", 0, &par->gpio.cs);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
+ ret = fbtft_request_one_gpio(par, "latch", 0, &par->gpio.latch);
if (ret)
return ret;
for (i = 0; i < 16; i++) {
- ret = fbtft_request_one_gpio(par, "db-gpios", i,
+ ret = fbtft_request_one_gpio(par, "db", i,
&par->gpio.db[i]);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "led-gpios", i,
+ ret = fbtft_request_one_gpio(par, "led", i,
&par->gpio.led[i]);
if (ret)
return ret;
- ret = fbtft_request_one_gpio(par, "aux-gpios", i,
+ ret = fbtft_request_one_gpio(par, "aux", i,
&par->gpio.aux[i]);
if (ret)
return ret;
@@ -234,9 +231,9 @@ static void fbtft_reset(struct fbtft_par *par)
if (!par->gpio.reset)
return;
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
- gpiod_set_value_cansleep(par->gpio.reset, 0);
- usleep_range(20, 40);
gpiod_set_value_cansleep(par->gpio.reset, 1);
+ usleep_range(20, 40);
+ gpiod_set_value_cansleep(par->gpio.reset, 0);
msleep(120);
}
@@ -921,7 +918,7 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
return -EINVAL;
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
while (p) {
@@ -1012,7 +1009,7 @@ int fbtft_init_display(struct fbtft_par *par)
}
par->fbtftops.reset(par);
- if (!par->gpio.cs)
+ if (par->gpio.cs)
gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
i = 0;
diff --git a/drivers/staging/gasket/apex_driver.c b/drivers/staging/gasket/apex_driver.c
index 2be45ee9d061..464648ee2036 100644
--- a/drivers/staging/gasket/apex_driver.c
+++ b/drivers/staging/gasket/apex_driver.c
@@ -532,7 +532,7 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr,
break;
case ATTR_KERNEL_HIB_SIMPLE_PAGE_TABLE_SIZE:
ret = scnprintf(buf, PAGE_SIZE, "%u\n",
- gasket_page_table_num_entries(
+ gasket_page_table_num_simple_entries(
gasket_dev->page_table[0]));
break;
case ATTR_KERNEL_HIB_NUM_ACTIVE_PAGES:
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 9d4f1dab0968..40dd573e73c3 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -1750,7 +1750,8 @@ static int visornic_poll(struct napi_struct *napi, int budget)
}
/* poll_for_irq - checks the status of the response queue
- * @v: Void pointer to the visronic devdata struct.
+ * @t: pointer to the 'struct timer_list' from which we can retrieve the
+ * the visornic devdata struct.
*
* Main function of the vnic_incoming thread. Periodically check the response
* queue and drain it if needed.
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index d72fdd333050..736eedef23b6 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1969,6 +1969,7 @@ void wilc_deinit_host_int(struct net_device *net)
priv->p2p_listen_state = false;
+ flush_workqueue(vif->wilc->hif_workqueue);
mutex_destroy(&priv->scan_req_lock);
ret = wilc_deinit(vif);
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
index 22dd4c457d6a..c70caf4ea490 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
@@ -875,10 +875,12 @@ static u8 cxgbit_get_iscsi_dcb_priority(struct net_device *ndev, u16 local_port)
return 0;
if (caps & DCB_CAP_DCBX_VER_IEEE) {
- iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_ANY;
-
+ iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_STREAM;
ret = dcb_ieee_getapp_mask(ndev, &iscsi_dcb_app);
-
+ if (!ret) {
+ iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_ANY;
+ ret = dcb_ieee_getapp_mask(ndev, &iscsi_dcb_app);
+ }
} else if (caps & DCB_CAP_DCBX_VER_CEE) {
iscsi_dcb_app.selector = DCB_APP_IDTYPE_PORTNUM;
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c
index 343b129c2cfa..e877b917c15f 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_main.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c
@@ -589,7 +589,8 @@ static void cxgbit_dcb_workfn(struct work_struct *work)
iscsi_app = &dcb_work->dcb_app;
if (iscsi_app->dcbx & DCB_CAP_DCBX_VER_IEEE) {
- if (iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_ANY)
+ if ((iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_STREAM) &&
+ (iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_ANY))
goto out;
priority = iscsi_app->app.priority;
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 04eda111920e..661bb9358364 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -1132,14 +1132,16 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
struct se_cmd *se_cmd = cmd->se_cmd;
struct tcmu_dev *udev = cmd->tcmu_dev;
bool read_len_valid = false;
- uint32_t read_len = se_cmd->data_length;
+ uint32_t read_len;
/*
* cmd has been completed already from timeout, just reclaim
* data area space and free cmd
*/
- if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+ if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+ WARN_ON_ONCE(se_cmd);
goto out;
+ }
list_del_init(&cmd->queue_entry);
@@ -1152,6 +1154,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
goto done;
}
+ read_len = se_cmd->data_length;
if (se_cmd->data_direction == DMA_FROM_DEVICE &&
(entry->hdr.uflags & TCMU_UFLAG_READ_LEN) && entry->rsp.read_len) {
read_len_valid = true;
@@ -1307,6 +1310,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
*/
scsi_status = SAM_STAT_CHECK_CONDITION;
list_del_init(&cmd->queue_entry);
+ cmd->se_cmd = NULL;
} else {
list_del_init(&cmd->queue_entry);
idr_remove(&udev->commands, id);
@@ -2022,6 +2026,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
idr_remove(&udev->commands, i);
if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+ WARN_ON(!cmd->se_cmd);
list_del_init(&cmd->queue_entry);
if (err_level == 1) {
/*
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index aa942703ae65..13b0269a0abc 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -148,6 +148,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
*/
optee_cq_wait_for_completion(&optee->call_queue, &w);
} else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
+ might_sleep();
param.a0 = res.a0;
param.a1 = res.a1;
param.a2 = res.a2;
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index 213ab3cc6b80..d3446acf9bbd 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -487,6 +487,7 @@ static int proc_thermal_rapl_add(struct pci_dev *pdev,
rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
if (ret < 0) {
powercap_unregister_control_type(rapl_mmio_priv.control_type);
+ rapl_mmio_priv.control_type = NULL;
return ret;
}
rapl_mmio_priv.pcap_rapl_online = ret;
@@ -496,6 +497,9 @@ static int proc_thermal_rapl_add(struct pci_dev *pdev,
static void proc_thermal_rapl_remove(void)
{
+ if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
+ return;
+
cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
powercap_unregister_control_type(rapl_mmio_priv.control_type);
}
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index cb4db1b3ca3c..5fb214e67d73 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -47,7 +47,7 @@
* using the 2.6 Linux kernel kref construct.
*
* For direction on installation and usage of this driver please reference
- * Documentation/powerpc/hvcs.txt.
+ * Documentation/powerpc/hvcs.rst.
*/
#include <linux/device.h>
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index fd385c8c53a5..514169eb1859 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -739,7 +739,8 @@ config SERIAL_PNX8XXX_CONSOLE
config SERIAL_HS_LPC32XX
tristate "LPC32XX high speed serial port support"
- depends on ARCH_LPC32XX && OF
+ depends on ARCH_LPC32XX || COMPILE_TEST
+ depends on OF
select SERIAL_CORE
help
Support for the LPC32XX high speed serial ports (up to 900kbps).
@@ -855,16 +856,6 @@ config SERIAL_CPM_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
-config SERIAL_SGI_L1_CONSOLE
- bool "SGI Altix L1 serial console support"
- depends on IA64_GENERIC || IA64_SGI_SN2
- select SERIAL_CORE
- select SERIAL_CORE_CONSOLE
- help
- If you have an SGI Altix and you would like to use the system
- controller serial port as your console (you want this!),
- say Y. Otherwise, say N.
-
config SERIAL_PIC32
tristate "Microchip PIC32 serial support"
depends on MACH_PIC32
@@ -982,23 +973,6 @@ config SERIAL_JSM
To compile this driver as a module, choose M here: the
module will be called jsm.
-config SERIAL_SGI_IOC4
- tristate "SGI IOC4 controller serial support"
- depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4
- select SERIAL_CORE
- help
- If you have an SGI Altix with an IOC4 based Base IO card
- and wish to use the serial ports on this card, say Y.
- Otherwise, say N.
-
-config SERIAL_SGI_IOC3
- tristate "SGI Altix IOC3 serial support"
- depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3
- select SERIAL_CORE
- help
- If you have an SGI Altix with an IOC3 serial card,
- say Y or M. Otherwise, say N.
-
config SERIAL_MSM
tristate "MSM on-chip serial port support"
depends on ARCH_QCOM
@@ -1035,25 +1009,6 @@ config SERIAL_VT8500_CONSOLE
depends on SERIAL_VT8500=y
select SERIAL_CORE_CONSOLE
-config SERIAL_NETX
- tristate "NetX serial port support"
- depends on ARCH_NETX
- select SERIAL_CORE
- help
- If you have a machine based on a Hilscher NetX SoC you
- can enable its onboard serial port by enabling this option.
-
- To compile this driver as a module, choose M here: the
- module will be called netx-serial.
-
-config SERIAL_NETX_CONSOLE
- bool "Console on NetX serial port"
- depends on SERIAL_NETX=y
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the Hilscher NetX SoC
- you can make it the console by answering Y to this option.
-
config SERIAL_OMAP
tristate "OMAP serial port support"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 7cd7cabfa6c4..d2f44879384e 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_ZS) += zs.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
-obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
obj-$(CONFIG_SERIAL_IMX) += imx.o
obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
@@ -53,13 +52,10 @@ obj-$(CONFIG_SERIAL_SC16IS7XX_CORE) += sc16is7xx.o
obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
-obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
-obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
obj-$(CONFIG_SERIAL_QCOM_GENI) += qcom_geni_serial.o
-obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c
deleted file mode 100644
index d8a1cdd6a53d..000000000000
--- a/drivers/tty/serial/ioc3_serial.c
+++ /dev/null
@@ -1,2195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * This file contains a module version of the ioc3 serial driver. This
- * includes all the support functions needed (support functions, etc.)
- * and the serial driver itself.
- */
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/serial_core.h>
-#include <linux/ioc3.h>
-#include <linux/slab.h>
-
-/*
- * Interesting things about the ioc3
- */
-
-#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */
-#define PORTS_PER_CARD 2
-#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS)
-#define MAX_CARDS 8
-#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS)
-
-/* determine given the sio_ir what port it applies to */
-#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1
-
-
-/*
- * we have 2 logical ports (rs232, rs422) for each physical port
- * evens are rs232, odds are rs422
- */
-#define GET_PHYSICAL_PORT(_x) ((_x) >> 1)
-#define GET_LOGICAL_PORT(_x) ((_x) & 1)
-#define IS_PHYSICAL_PORT(_x) !((_x) & 1)
-#define IS_RS232(_x) !((_x) & 1)
-
-static unsigned int Num_of_ioc3_cards;
-static unsigned int Submodule_slot;
-
-/* defining this will get you LOTS of great debug info */
-//#define DEBUG_INTERRUPTS
-#define DPRINT_CONFIG(_x...) ;
-//#define DPRINT_CONFIG(_x...) printk _x
-#define NOT_PROGRESS() ;
-//#define NOT_PROGRESS() printk("%s : fails %d\n", __func__, __LINE__)
-
-/* number of characters we want to transmit to the lower level at a time */
-#define MAX_CHARS 256
-#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */
-
-/* Device name we're using */
-#define DEVICE_NAME "ttySIOC"
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR 116
-
-/* flags for next_char_state */
-#define NCS_BREAK 0x1
-#define NCS_PARITY 0x2
-#define NCS_FRAMING 0x4
-#define NCS_OVERRUN 0x8
-
-/* cause we need SOME parameters ... */
-#define MIN_BAUD_SUPPORTED 1200
-#define MAX_BAUD_SUPPORTED 115200
-
-/* protocol types supported */
-#define PROTO_RS232 0
-#define PROTO_RS422 1
-
-/* Notification types */
-#define N_DATA_READY 0x01
-#define N_OUTPUT_LOWAT 0x02
-#define N_BREAK 0x04
-#define N_PARITY_ERROR 0x08
-#define N_FRAMING_ERROR 0x10
-#define N_OVERRUN_ERROR 0x20
-#define N_DDCD 0x40
-#define N_DCTS 0x80
-
-#define N_ALL_INPUT (N_DATA_READY | N_BREAK \
- | N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define N_ALL_OUTPUT N_OUTPUT_LOWAT
-
-#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR)
-
-#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \
- | N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv)
-#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16))
-#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
-
-/* Some masks */
-#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
- | UART_LCR_WLEN7 | UART_LCR_WLEN8)
-#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
-
-#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable)
-
-#define RING_BUF_SIZE 4096
-#define BUF_SIZE_BIT SBBR_L_SIZE
-#define PROD_CONS_MASK PROD_CONS_PTR_4K
-
-#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
-
-/* driver specific - one per card */
-struct ioc3_card {
- struct {
- /* uart ports are allocated here */
- struct uart_port icp_uart_port[LOGICAL_PORTS];
- /* the ioc3_port used for this port */
- struct ioc3_port *icp_port;
- } ic_port[PORTS_PER_CARD];
- /* currently enabled interrupts */
- uint32_t ic_enable;
-};
-
-/* Local port info for each IOC3 serial port */
-struct ioc3_port {
- /* handy reference material */
- struct uart_port *ip_port;
- struct ioc3_card *ip_card;
- struct ioc3_driver_data *ip_idd;
- struct ioc3_submodule *ip_is;
-
- /* pci mem addresses for this port */
- struct ioc3_serialregs __iomem *ip_serial_regs;
- struct ioc3_uartregs __iomem *ip_uart_regs;
-
- /* Ring buffer page for this port */
- dma_addr_t ip_dma_ringbuf;
- /* vaddr of ring buffer */
- struct ring_buffer *ip_cpu_ringbuf;
-
- /* Rings for this port */
- struct ring *ip_inring;
- struct ring *ip_outring;
-
- /* Hook to port specific values */
- struct port_hooks *ip_hooks;
-
- spinlock_t ip_lock;
-
- /* Various rx/tx parameters */
- int ip_baud;
- int ip_tx_lowat;
- int ip_rx_timeout;
-
- /* Copy of notification bits */
- int ip_notify;
-
- /* Shadow copies of various registers so we don't need to PIO
- * read them constantly
- */
- uint32_t ip_sscr;
- uint32_t ip_tx_prod;
- uint32_t ip_rx_cons;
- unsigned char ip_flags;
-};
-
-/* tx low water mark. We need to notify the driver whenever tx is getting
- * close to empty so it can refill the tx buffer and keep things going.
- * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
- * have no trouble getting in more chars in time (I certainly hope so).
- */
-#define TX_LOWAT_LATENCY 1000
-#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
-#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
-
-/* Flags per port */
-#define INPUT_HIGH 0x01
- /* used to signify that we have turned off the rx_high
- * temporarily - we need to drain the fifo and don't
- * want to get blasted with interrupts.
- */
-#define DCD_ON 0x02
- /* DCD state is on */
-#define LOWAT_WRITTEN 0x04
-#define READ_ABORTED 0x08
- /* the read was aborted - used to avaoid infinate looping
- * in the interrupt handler
- */
-#define INPUT_ENABLE 0x10
-
-/* Since each port has different register offsets and bitmasks
- * for everything, we'll store those that we need in tables so we
- * don't have to be constantly checking the port we are dealing with.
- */
-struct port_hooks {
- uint32_t intr_delta_dcd;
- uint32_t intr_delta_cts;
- uint32_t intr_tx_mt;
- uint32_t intr_rx_timer;
- uint32_t intr_rx_high;
- uint32_t intr_tx_explicit;
- uint32_t intr_clear;
- uint32_t intr_all;
- char rs422_select_pin;
-};
-
-static struct port_hooks hooks_array[PORTS_PER_CARD] = {
- /* values for port A */
- {
- .intr_delta_dcd = SIO_IR_SA_DELTA_DCD,
- .intr_delta_cts = SIO_IR_SA_DELTA_CTS,
- .intr_tx_mt = SIO_IR_SA_TX_MT,
- .intr_rx_timer = SIO_IR_SA_RX_TIMER,
- .intr_rx_high = SIO_IR_SA_RX_HIGH,
- .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT,
- .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL
- | SIO_IR_SA_RX_HIGH
- | SIO_IR_SA_RX_TIMER
- | SIO_IR_SA_DELTA_DCD
- | SIO_IR_SA_DELTA_CTS
- | SIO_IR_SA_INT
- | SIO_IR_SA_TX_EXPLICIT
- | SIO_IR_SA_MEMERR),
- .intr_all = SIO_IR_SA,
- .rs422_select_pin = GPPR_UARTA_MODESEL_PIN,
- },
-
- /* values for port B */
- {
- .intr_delta_dcd = SIO_IR_SB_DELTA_DCD,
- .intr_delta_cts = SIO_IR_SB_DELTA_CTS,
- .intr_tx_mt = SIO_IR_SB_TX_MT,
- .intr_rx_timer = SIO_IR_SB_RX_TIMER,
- .intr_rx_high = SIO_IR_SB_RX_HIGH,
- .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT,
- .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL
- | SIO_IR_SB_RX_HIGH
- | SIO_IR_SB_RX_TIMER
- | SIO_IR_SB_DELTA_DCD
- | SIO_IR_SB_DELTA_CTS
- | SIO_IR_SB_INT
- | SIO_IR_SB_TX_EXPLICIT
- | SIO_IR_SB_MEMERR),
- .intr_all = SIO_IR_SB,
- .rs422_select_pin = GPPR_UARTB_MODESEL_PIN,
- }
-};
-
-struct ring_entry {
- union {
- struct {
- uint32_t alldata;
- uint32_t allsc;
- } all;
- struct {
- char data[4]; /* data bytes */
- char sc[4]; /* status/control */
- } s;
- } u;
-};
-
-/* Test the valid bits in any of the 4 sc chars using "allsc" member */
-#define RING_ANY_VALID \
- ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101)
-
-#define ring_sc u.s.sc
-#define ring_data u.s.data
-#define ring_allsc u.all.allsc
-
-/* Number of entries per ring buffer. */
-#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
-
-/* An individual ring */
-struct ring {
- struct ring_entry entries[ENTRIES_PER_RING];
-};
-
-/* The whole enchilada */
-struct ring_buffer {
- struct ring TX_A;
- struct ring RX_A;
- struct ring TX_B;
- struct ring RX_B;
-};
-
-/* Get a ring from a port struct */
-#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
-
-/* for Infinite loop detection */
-#define MAXITER 10000000
-
-
-/**
- * set_baud - Baud rate setting code
- * @port: port to set
- * @baud: baud rate to use
- */
-static int set_baud(struct ioc3_port *port, int baud)
-{
- int divisor;
- int actual_baud;
- int diff;
- int lcr, prediv;
- struct ioc3_uartregs __iomem *uart;
-
- for (prediv = 6; prediv < 64; prediv++) {
- divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv));
- if (!divisor)
- continue; /* invalid divisor */
- actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv));
-
- diff = actual_baud - baud;
- if (diff < 0)
- diff = -diff;
-
- /* if we're within 1% we've found a match */
- if (diff * 100 <= actual_baud)
- break;
- }
-
- /* if the above loop completed, we didn't match
- * the baud rate. give up.
- */
- if (prediv == 64) {
- NOT_PROGRESS();
- return 1;
- }
-
- uart = port->ip_uart_regs;
- lcr = readb(&uart->iu_lcr);
-
- writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr);
- writeb((unsigned char)divisor, &uart->iu_dll);
- writeb((unsigned char)(divisor >> 8), &uart->iu_dlm);
- writeb((unsigned char)prediv, &uart->iu_scr);
- writeb((unsigned char)lcr, &uart->iu_lcr);
-
- return 0;
-}
-
-/**
- * get_ioc3_port - given a uart port, return the control structure
- * @the_port: uart port to find
- */
-static struct ioc3_port *get_ioc3_port(struct uart_port *the_port)
-{
- struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev);
- struct ioc3_card *card_ptr = idd->data[Submodule_slot];
- int ii, jj;
-
- if (!card_ptr) {
- NOT_PROGRESS();
- return NULL;
- }
- for (ii = 0; ii < PORTS_PER_CARD; ii++) {
- for (jj = 0; jj < LOGICAL_PORTS; jj++) {
- if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj])
- return card_ptr->ic_port[ii].icp_port;
- }
- }
- NOT_PROGRESS();
- return NULL;
-}
-
-/**
- * port_init - Initialize the sio and ioc3 hardware for a given port
- * called per port from attach...
- * @port: port to initialize
- */
-static inline int port_init(struct ioc3_port *port)
-{
- uint32_t sio_cr;
- struct port_hooks *hooks = port->ip_hooks;
- struct ioc3_uartregs __iomem *uart;
- int reset_loop_counter = 0xfffff;
- struct ioc3_driver_data *idd = port->ip_idd;
-
- /* Idle the IOC3 serial interface */
- writel(SSCR_RESET, &port->ip_serial_regs->sscr);
-
- /* Wait until any pending bus activity for this port has ceased */
- do {
- sio_cr = readl(&idd->vma->sio_cr);
- if (reset_loop_counter-- <= 0) {
- printk(KERN_WARNING
- "IOC3 unable to come out of reset"
- " scr 0x%x\n", sio_cr);
- return -1;
- }
- } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) &&
- (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA)
- || sio_cr == SIO_CR_ARB_DIAG_TXB
- || sio_cr == SIO_CR_ARB_DIAG_RXA
- || sio_cr == SIO_CR_ARB_DIAG_RXB));
-
- /* Finish reset sequence */
- writel(0, &port->ip_serial_regs->sscr);
-
- /* Once RESET is done, reload cached tx_prod and rx_cons values
- * and set rings to empty by making prod == cons
- */
- port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
- port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- /* Disable interrupts for this 16550 */
- uart = port->ip_uart_regs;
- writeb(0, &uart->iu_lcr);
- writeb(0, &uart->iu_ier);
-
- /* Set the default baud */
- set_baud(port, port->ip_baud);
-
- /* Set line control to 8 bits no parity */
- writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Enable the FIFOs */
- writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr);
- /* then reset 16550 FIFOs */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- &uart->iu_fcr);
-
- /* Clear modem control register */
- writeb(0, &uart->iu_mcr);
-
- /* Clear deltas in modem status register */
- writel(0, &port->ip_serial_regs->shadow);
-
- /* Only do this once per port pair */
- if (port->ip_hooks == &hooks_array[0]) {
- unsigned long ring_pci_addr;
- uint32_t __iomem *sbbr_l, *sbbr_h;
-
- sbbr_l = &idd->vma->sbbr_l;
- sbbr_h = &idd->vma->sbbr_h;
- ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
- DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
- __func__, (void *)ring_pci_addr));
-
- writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
- writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
- }
-
- /* Set the receive timeout value to 10 msec */
- writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr);
-
- /* Set rx threshold, enable DMA */
- /* Set high water mark at 3/4 of full ring */
- port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
-
- /* uart experiences pauses at high baud rate reducing actual
- * throughput by 10% or so unless we enable high speed polling
- * XXX when this hardware bug is resolved we should revert to
- * normal polling speed
- */
- port->ip_sscr |= SSCR_HIGH_SPD;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Disable and clear all serial related interrupt bits */
- port->ip_card->ic_enable &= ~hooks->intr_clear;
- ioc3_disable(port->ip_is, idd, hooks->intr_clear);
- ioc3_ack(port->ip_is, idd, hooks->intr_clear);
- return 0;
-}
-
-/**
- * enable_intrs - enable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void enable_intrs(struct ioc3_port *port, uint32_t mask)
-{
- if ((port->ip_card->ic_enable & mask) != mask) {
- port->ip_card->ic_enable |= mask;
- ioc3_enable(port->ip_is, port->ip_idd, mask);
- }
-}
-
-/**
- * local_open - local open a port
- * @port: port to open
- */
-static inline int local_open(struct ioc3_port *port)
-{
- int spiniter = 0;
-
- port->ip_flags = INPUT_ENABLE;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER) {
- NOT_PROGRESS();
- return -1;
- }
- }
- }
-
- /* Reset the input fifo. If the uart received chars while the port
- * was closed and DMA is not enabled, the uart may have a bunch of
- * chars hanging around in its rx fifo which will not be discarded
- * by rclr in the upper layer. We must get rid of them here.
- */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
- &port->ip_uart_regs->iu_fcr);
-
- writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Re-enable DMA, set default threshold to intr whenever there is
- * data available.
- */
- port->ip_sscr &= ~SSCR_RX_THRESHOLD;
- port->ip_sscr |= 1; /* default threshold */
-
- /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
- * flag if it was set above
- */
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- port->ip_tx_lowat = 1;
- return 0;
-}
-
-/**
- * set_rx_timeout - Set rx timeout and threshold values.
- * @port: port to use
- * @timeout: timeout value in ticks
- */
-static inline int set_rx_timeout(struct ioc3_port *port, int timeout)
-{
- int threshold;
-
- port->ip_rx_timeout = timeout;
-
- /* Timeout is in ticks. Let's figure out how many chars we
- * can receive at the current baud rate in that interval
- * and set the rx threshold to that amount. There are 4 chars
- * per ring entry, so we'll divide the number of chars that will
- * arrive in timeout by 4.
- * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
- */
- threshold = timeout * port->ip_baud / 4000;
- if (threshold == 0)
- threshold = 1; /* otherwise we'll intr all the time! */
-
- if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD)
- return 1;
-
- port->ip_sscr &= ~SSCR_RX_THRESHOLD;
- port->ip_sscr |= threshold;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Now set the rx timeout to the given value
- * again timeout * SRTR_HZ / HZ
- */
- timeout = timeout * SRTR_HZ / 100;
- if (timeout > SRTR_CNT)
- timeout = SRTR_CNT;
- writel(timeout, &port->ip_serial_regs->srtr);
- return 0;
-}
-
-/**
- * config_port - config the hardware
- * @port: port to config
- * @baud: baud rate for the port
- * @byte_size: data size
- * @stop_bits: number of stop bits
- * @parenb: parity enable ?
- * @parodd: odd parity ?
- */
-static inline int
-config_port(struct ioc3_port *port,
- int baud, int byte_size, int stop_bits, int parenb, int parodd)
-{
- char lcr, sizebits;
- int spiniter = 0;
-
- DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
- "parodd %d\n",
- __func__, ((struct uart_port *)port->ip_port)->line,
- baud, byte_size, stop_bits, parenb, parodd));
-
- if (set_baud(port, baud))
- return 1;
-
- switch (byte_size) {
- case 5:
- sizebits = UART_LCR_WLEN5;
- break;
- case 6:
- sizebits = UART_LCR_WLEN6;
- break;
- case 7:
- sizebits = UART_LCR_WLEN7;
- break;
- case 8:
- sizebits = UART_LCR_WLEN8;
- break;
- default:
- return 1;
- }
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
-
- /* Clear relevant fields in lcr */
- lcr = readb(&port->ip_uart_regs->iu_lcr);
- lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
- UART_LCR_PARITY | LCR_MASK_STOP_BITS);
-
- /* Set byte size in lcr */
- lcr |= sizebits;
-
- /* Set parity */
- if (parenb) {
- lcr |= UART_LCR_PARITY;
- if (!parodd)
- lcr |= UART_LCR_EPAR;
- }
-
- /* Set stop bits */
- if (stop_bits)
- lcr |= UART_LCR_STOP /* 2 stop bits */ ;
-
- writeb(lcr, &port->ip_uart_regs->iu_lcr);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- port->ip_baud = baud;
-
- /* When we get within this number of ring entries of filling the
- * entire ring on tx, place an EXPLICIT intr to generate a lowat
- * notification when output has drained.
- */
- port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
- if (port->ip_tx_lowat == 0)
- port->ip_tx_lowat = 1;
-
- set_rx_timeout(port, 2);
- return 0;
-}
-
-/**
- * do_write - Write bytes to the port. Returns the number of bytes
- * actually written. Called from transmit_chars
- * @port: port to use
- * @buf: the stuff to write
- * @len: how many bytes in 'buf'
- */
-static inline int do_write(struct ioc3_port *port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total = 0;
- struct ring *outring;
- struct ring_entry *entry;
- struct port_hooks *hooks = port->ip_hooks;
-
- BUG_ON(!(len >= 0));
-
- prod_ptr = port->ip_tx_prod;
- cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- outring = port->ip_outring;
-
- /* Maintain a 1-entry red-zone. The ring buffer is full when
- * (cons - prod) % ring_size is 1. Rather than do this subtraction
- * in the body of the loop, I'll do it now.
- */
- cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
-
- /* Stuff the bytes into the output */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- int xx;
-
- /* Get 4 bytes (one ring entry) at a time */
- entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
-
- /* Invalidate all entries */
- entry->ring_allsc = 0;
-
- /* Copy in some bytes */
- for (xx = 0; (xx < 4) && (len > 0); xx++) {
- entry->ring_data[xx] = *buf++;
- entry->ring_sc[xx] = TXCB_VALID;
- len--;
- total++;
- }
-
- /* If we are within some small threshold of filling up the
- * entire ring buffer, we must place an EXPLICIT intr here
- * to generate a lowat interrupt in case we subsequently
- * really do fill up the ring and the caller goes to sleep.
- * No need to place more than one though.
- */
- if (!(port->ip_flags & LOWAT_WRITTEN) &&
- ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
- <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
- port->ip_flags |= LOWAT_WRITTEN;
- entry->ring_sc[0] |= TXCB_INT_WHEN_DONE;
- }
-
- /* Go on to next entry */
- prod_ptr += sizeof(struct ring_entry);
- prod_ptr &= PROD_CONS_MASK;
- }
-
- /* If we sent something, start DMA if necessary */
- if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) {
- port->ip_sscr |= SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
-
- /* Store the new producer pointer. If tx is disabled, we stuff the
- * data into the ring buffer, but we don't actually start tx.
- */
- if (!uart_tx_stopped(port->ip_port)) {
- writel(prod_ptr, &port->ip_serial_regs->stpir);
-
- /* If we are now transmitting, enable tx_mt interrupt so we
- * can disable DMA if necessary when the tx finishes.
- */
- if (total > 0)
- enable_intrs(port, hooks->intr_tx_mt);
- }
- port->ip_tx_prod = prod_ptr;
-
- return total;
-}
-
-/**
- * disable_intrs - disable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static inline void disable_intrs(struct ioc3_port *port, uint32_t mask)
-{
- if (port->ip_card->ic_enable & mask) {
- ioc3_disable(port->ip_is, port->ip_idd, mask);
- port->ip_card->ic_enable &= ~mask;
- }
-}
-
-/**
- * set_notification - Modify event notification
- * @port: port to use
- * @mask: events mask
- * @set_on: set ?
- */
-static int set_notification(struct ioc3_port *port, int mask, int set_on)
-{
- struct port_hooks *hooks = port->ip_hooks;
- uint32_t intrbits, sscrbits;
-
- BUG_ON(!mask);
-
- intrbits = sscrbits = 0;
-
- if (mask & N_DATA_READY)
- intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
- if (mask & N_OUTPUT_LOWAT)
- intrbits |= hooks->intr_tx_explicit;
- if (mask & N_DDCD) {
- intrbits |= hooks->intr_delta_dcd;
- sscrbits |= SSCR_RX_RING_DCD;
- }
- if (mask & N_DCTS)
- intrbits |= hooks->intr_delta_cts;
-
- if (set_on) {
- enable_intrs(port, intrbits);
- port->ip_notify |= mask;
- port->ip_sscr |= sscrbits;
- } else {
- disable_intrs(port, intrbits);
- port->ip_notify &= ~mask;
- port->ip_sscr &= ~sscrbits;
- }
-
- /* We require DMA if either DATA_READY or DDCD notification is
- * currently requested. If neither of these is requested and
- * there is currently no tx in progress, DMA may be disabled.
- */
- if (port->ip_notify & (N_DATA_READY | N_DDCD))
- port->ip_sscr |= SSCR_DMA_EN;
- else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt))
- port->ip_sscr &= ~SSCR_DMA_EN;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- return 0;
-}
-
-/**
- * set_mcr - set the master control reg
- * @the_port: port to use
- * @mask1: mcr mask
- * @mask2: shadow mask
- */
-static inline int set_mcr(struct uart_port *the_port,
- int mask1, int mask2)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- uint32_t shadow;
- int spiniter = 0;
- char mcr;
-
- if (!port)
- return -1;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
- shadow = readl(&port->ip_serial_regs->shadow);
- mcr = (shadow & 0xff000000) >> 24;
-
- /* Set new value */
- mcr |= mask1;
- shadow |= mask2;
- writeb(mcr, &port->ip_uart_regs->iu_mcr);
- writel(shadow, &port->ip_serial_regs->shadow);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- return 0;
-}
-
-/**
- * ioc3_set_proto - set the protocol for the port
- * @port: port to use
- * @proto: protocol to use
- */
-static int ioc3_set_proto(struct ioc3_port *port, int proto)
-{
- struct port_hooks *hooks = port->ip_hooks;
-
- switch (proto) {
- default:
- case PROTO_RS232:
- /* Clear the appropriate GIO pin */
- DPRINT_CONFIG(("%s: rs232\n", __func__));
- writel(0, (&port->ip_idd->vma->gppr[0]
- + hooks->rs422_select_pin));
- break;
-
- case PROTO_RS422:
- /* Set the appropriate GIO pin */
- DPRINT_CONFIG(("%s: rs422\n", __func__));
- writel(1, (&port->ip_idd->vma->gppr[0]
- + hooks->rs422_select_pin));
- break;
- }
- return 0;
-}
-
-/**
- * transmit_chars - upper level write, called with the_port->lock
- * @the_port: port to write
- */
-static void transmit_chars(struct uart_port *the_port)
-{
- int xmit_count, tail, head;
- int result;
- char *start;
- struct tty_struct *tty;
- struct ioc3_port *port = get_ioc3_port(the_port);
- struct uart_state *state;
-
- if (!the_port)
- return;
- if (!port)
- return;
-
- state = the_port->state;
- tty = state->port.tty;
-
- if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) {
- /* Nothing to do or hw stopped */
- set_notification(port, N_ALL_OUTPUT, 0);
- return;
- }
-
- head = state->xmit.head;
- tail = state->xmit.tail;
- start = (char *)&state->xmit.buf[tail];
-
- /* write out all the data or until the end of the buffer */
- xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
- if (xmit_count > 0) {
- result = do_write(port, start, xmit_count);
- if (result > 0) {
- /* booking */
- xmit_count -= result;
- the_port->icount.tx += result;
- /* advance the pointers */
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- state->xmit.tail = tail;
- start = (char *)&state->xmit.buf[tail];
- }
- }
- if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS)
- uart_write_wakeup(the_port);
-
- if (uart_circ_empty(&state->xmit)) {
- set_notification(port, N_OUTPUT_LOWAT, 0);
- } else {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- }
-}
-
-/**
- * ioc3_change_speed - change the speed of the port
- * @the_port: port to change
- * @new_termios: new termios settings
- * @old_termios: old termios settings
- */
-static void
-ioc3_change_speed(struct uart_port *the_port,
- struct ktermios *new_termios, struct ktermios *old_termios)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- unsigned int cflag, iflag;
- int baud;
- int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
- struct uart_state *state = the_port->state;
-
- cflag = new_termios->c_cflag;
- iflag = new_termios->c_iflag;
-
- switch (cflag & CSIZE) {
- case CS5:
- new_data = 5;
- break;
- case CS6:
- new_data = 6;
- break;
- case CS7:
- new_data = 7;
- break;
- case CS8:
- new_data = 8;
- break;
- default:
- /* cuz we always need a default ... */
- new_data = 5;
- break;
- }
- if (cflag & CSTOPB) {
- new_stop = 1;
- }
- if (cflag & PARENB) {
- new_parity_enable = 1;
- if (cflag & PARODD)
- new_parity = 1;
- }
- baud = uart_get_baud_rate(the_port, new_termios, old_termios,
- MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
- DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __func__, baud,
- the_port->line));
-
- if (!the_port->fifosize)
- the_port->fifosize = FIFO_SIZE;
- uart_update_timeout(the_port, cflag, baud);
-
- the_port->ignore_status_mask = N_ALL_INPUT;
-
- state->port.low_latency = 1;
-
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~(N_PARITY_ERROR
- | N_FRAMING_ERROR);
- if (iflag & IGNBRK) {
- the_port->ignore_status_mask &= ~N_BREAK;
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
- }
- if (!(cflag & CREAD)) {
- /* ignore everything */
- the_port->ignore_status_mask &= ~N_DATA_READY;
- }
-
- if (cflag & CRTSCTS) {
- /* enable hardware flow control */
- port->ip_sscr |= SSCR_HFC_EN;
- }
- else {
- /* disable hardware flow control */
- port->ip_sscr &= ~SSCR_HFC_EN;
- }
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Set the configuration and proper notification call */
- DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
- "config_port(baud %d data %d stop %d penable %d "
- " parity %d), notification 0x%x\n",
- __func__, (void *)port, the_port->line, cflag, baud,
- new_data, new_stop, new_parity_enable, new_parity,
- the_port->ignore_status_mask));
-
- if ((config_port(port, baud, /* baud */
- new_data, /* byte size */
- new_stop, /* stop bits */
- new_parity_enable, /* set parity */
- new_parity)) >= 0) { /* parity 1==odd */
- set_notification(port, the_port->ignore_status_mask, 1);
- }
-}
-
-/**
- * ic3_startup_local - Start up the serial port - returns >= 0 if no errors
- * @the_port: Port to operate on
- */
-static inline int ic3_startup_local(struct uart_port *the_port)
-{
- struct ioc3_port *port;
-
- if (!the_port) {
- NOT_PROGRESS();
- return -1;
- }
-
- port = get_ioc3_port(the_port);
- if (!port) {
- NOT_PROGRESS();
- return -1;
- }
-
- local_open(port);
-
- /* set the protocol */
- ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 :
- PROTO_RS422);
- return 0;
-}
-
-/*
- * ioc3_cb_output_lowat - called when the output low water mark is hit
- * @port: port to output
- */
-static void ioc3_cb_output_lowat(struct ioc3_port *port)
-{
- unsigned long pflags;
-
- /* the_port->lock is set on the call here */
- if (port->ip_port) {
- spin_lock_irqsave(&port->ip_port->lock, pflags);
- transmit_chars(port->ip_port);
- spin_unlock_irqrestore(&port->ip_port->lock, pflags);
- }
-}
-
-/*
- * ioc3_cb_post_ncs - called for some basic errors
- * @port: port to use
- * @ncs: event
- */
-static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs)
-{
- struct uart_icount *icount;
-
- icount = &the_port->icount;
-
- if (ncs & NCS_BREAK)
- icount->brk++;
- if (ncs & NCS_FRAMING)
- icount->frame++;
- if (ncs & NCS_OVERRUN)
- icount->overrun++;
- if (ncs & NCS_PARITY)
- icount->parity++;
-}
-
-/**
- * do_read - Read in bytes from the port. Return the number of bytes
- * actually read.
- * @the_port: port to use
- * @buf: place to put the stuff we read
- * @len: how big 'buf' is
- */
-
-static inline int do_read(struct uart_port *the_port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total;
- struct ioc3_port *port = get_ioc3_port(the_port);
- struct ring *inring;
- struct ring_entry *entry;
- struct port_hooks *hooks;
- int byte_num;
- char *sc;
- int loop_counter;
-
- BUG_ON(!(len >= 0));
- BUG_ON(!port);
- hooks = port->ip_hooks;
-
- /* There is a nasty timing issue in the IOC3. When the rx_timer
- * expires or the rx_high condition arises, we take an interrupt.
- * At some point while servicing the interrupt, we read bytes from
- * the ring buffer and re-arm the rx_timer. However the rx_timer is
- * not started until the first byte is received *after* it is armed,
- * and any bytes pending in the rx construction buffers are not drained
- * to memory until either there are 4 bytes available or the rx_timer
- * expires. This leads to a potential situation where data is left
- * in the construction buffers forever - 1 to 3 bytes were received
- * after the interrupt was generated but before the rx_timer was
- * re-armed. At that point as long as no subsequent bytes are received
- * the timer will never be started and the bytes will remain in the
- * construction buffer forever. The solution is to execute a DRAIN
- * command after rearming the timer. This way any bytes received before
- * the DRAIN will be drained to memory, and any bytes received after
- * the DRAIN will start the TIMER and be drained when it expires.
- * Luckily, this only needs to be done when the DMA buffer is empty
- * since there is no requirement that this function return all
- * available data as long as it returns some.
- */
- /* Re-arm the timer */
-
- writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- cons_ptr = port->ip_rx_cons;
-
- if (prod_ptr == cons_ptr) {
- int reset_dma = 0;
-
- /* Input buffer appears empty, do a flush. */
-
- /* DMA must be enabled for this to work. */
- if (!(port->ip_sscr & SSCR_DMA_EN)) {
- port->ip_sscr |= SSCR_DMA_EN;
- reset_dma = 1;
- }
-
- /* Potential race condition: we must reload the srpir after
- * issuing the drain command, otherwise we could think the rx
- * buffer is empty, then take a very long interrupt, and when
- * we come back it's full and we wait forever for the drain to
- * complete.
- */
- writel(port->ip_sscr | SSCR_RX_DRAIN,
- &port->ip_serial_regs->sscr);
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
-
- /* We must not wait for the DRAIN to complete unless there are
- * at least 8 bytes (2 ring entries) available to receive the
- * data otherwise the DRAIN will never complete and we'll
- * deadlock here.
- * In fact, to make things easier, I'll just ignore the flush if
- * there is any data at all now available.
- */
- if (prod_ptr == cons_ptr) {
- loop_counter = 0;
- while (readl(&port->ip_serial_regs->sscr) &
- SSCR_RX_DRAIN) {
- loop_counter++;
- if (loop_counter > MAXITER)
- return -1;
- }
-
- /* SIGH. We have to reload the prod_ptr *again* since
- * the drain may have caused it to change
- */
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
- }
- if (reset_dma) {
- port->ip_sscr &= ~SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- }
- inring = port->ip_inring;
- port->ip_flags &= ~READ_ABORTED;
-
- total = 0;
- loop_counter = 0xfffff; /* to avoid hangs */
-
- /* Grab bytes from the hardware */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- entry = (struct ring_entry *)((caddr_t) inring + cons_ptr);
-
- if (loop_counter-- <= 0) {
- printk(KERN_WARNING "IOC3 serial: "
- "possible hang condition/"
- "port stuck on read (line %d).\n",
- the_port->line);
- break;
- }
-
- /* According to the producer pointer, this ring entry
- * must contain some data. But if the PIO happened faster
- * than the DMA, the data may not be available yet, so let's
- * wait until it arrives.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- /* Indicate the read is aborted so we don't disable
- * the interrupt thinking that the consumer is
- * congested.
- */
- port->ip_flags |= READ_ABORTED;
- len = 0;
- break;
- }
-
- /* Load the bytes/status out of the ring entry */
- for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
- sc = &(entry->ring_sc[byte_num]);
-
- /* Check for change in modem state or overrun */
- if ((*sc & RXSB_MODEM_VALID)
- && (port->ip_notify & N_DDCD)) {
- /* Notify upper layer if DCD dropped */
- if ((port->ip_flags & DCD_ON)
- && !(*sc & RXSB_DCD)) {
- /* If we have already copied some data,
- * return it. We'll pick up the carrier
- * drop on the next pass. That way we
- * don't throw away the data that has
- * already been copied back to
- * the caller's buffer.
- */
- if (total > 0) {
- len = 0;
- break;
- }
- port->ip_flags &= ~DCD_ON;
-
- /* Turn off this notification so the
- * carrier drop protocol won't see it
- * again when it does a read.
- */
- *sc &= ~RXSB_MODEM_VALID;
-
- /* To keep things consistent, we need
- * to update the consumer pointer so
- * the next reader won't come in and
- * try to read the same ring entries
- * again. This must be done here before
- * the dcd change.
- */
-
- if ((entry->ring_allsc & RING_ANY_VALID)
- == 0) {
- cons_ptr += (int)sizeof
- (struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- writel(cons_ptr,
- &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* Notify upper layer of carrier drop */
- if ((port->ip_notify & N_DDCD)
- && port->ip_port) {
- uart_handle_dcd_change
- (port->ip_port, 0);
- wake_up_interruptible
- (&the_port->state->
- port.delta_msr_wait);
- }
-
- /* If we had any data to return, we
- * would have returned it above.
- */
- return 0;
- }
- }
- if (*sc & RXSB_MODEM_VALID) {
- /* Notify that an input overrun occurred */
- if ((*sc & RXSB_OVERRUN)
- && (port->ip_notify & N_OVERRUN_ERROR)) {
- ioc3_cb_post_ncs(the_port, NCS_OVERRUN);
- }
- /* Don't look at this byte again */
- *sc &= ~RXSB_MODEM_VALID;
- }
-
- /* Check for valid data or RX errors */
- if ((*sc & RXSB_DATA_VALID) &&
- ((*sc & (RXSB_PAR_ERR
- | RXSB_FRAME_ERR | RXSB_BREAK))
- && (port->ip_notify & (N_PARITY_ERROR
- | N_FRAMING_ERROR
- | N_BREAK)))) {
- /* There is an error condition on the next byte.
- * If we have already transferred some bytes,
- * we'll stop here. Otherwise if this is the
- * first byte to be read, we'll just transfer
- * it alone after notifying the
- * upper layer of its status.
- */
- if (total > 0) {
- len = 0;
- break;
- } else {
- if ((*sc & RXSB_PAR_ERR) &&
- (port->
- ip_notify & N_PARITY_ERROR)) {
- ioc3_cb_post_ncs(the_port,
- NCS_PARITY);
- }
- if ((*sc & RXSB_FRAME_ERR) &&
- (port->
- ip_notify & N_FRAMING_ERROR)) {
- ioc3_cb_post_ncs(the_port,
- NCS_FRAMING);
- }
- if ((*sc & RXSB_BREAK)
- && (port->ip_notify & N_BREAK)) {
- ioc3_cb_post_ncs
- (the_port, NCS_BREAK);
- }
- len = 1;
- }
- }
- if (*sc & RXSB_DATA_VALID) {
- *sc &= ~RXSB_DATA_VALID;
- *buf = entry->ring_data[byte_num];
- buf++;
- len--;
- total++;
- }
- }
-
- /* If we used up this entry entirely, go on to the next one,
- * otherwise we must have run out of buffer space, so
- * leave the consumer pointer here for the next read in case
- * there are still unread bytes in this entry.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- cons_ptr += (int)sizeof(struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- }
-
- /* Update consumer pointer and re-arm rx timer interrupt */
- writel(cons_ptr, &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* If we have now dipped below the rx high water mark and we have
- * rx_high interrupt turned off, we can now turn it back on again.
- */
- if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
- & PROD_CONS_MASK) <
- ((port->
- ip_sscr &
- SSCR_RX_THRESHOLD)
- << PROD_CONS_PTR_OFF))) {
- port->ip_flags &= ~INPUT_HIGH;
- enable_intrs(port, hooks->intr_rx_high);
- }
- return total;
-}
-
-/**
- * receive_chars - upper level read.
- * @the_port: port to read from
- */
-static int receive_chars(struct uart_port *the_port)
-{
- unsigned char ch[MAX_CHARS];
- int read_count = 0, read_room, flip = 0;
- struct uart_state *state = the_port->state;
- struct ioc3_port *port = get_ioc3_port(the_port);
- unsigned long pflags;
-
- /* Make sure all the pointers are "good" ones */
- if (!state)
- return 0;
-
- if (!(port->ip_flags & INPUT_ENABLE))
- return 0;
-
- spin_lock_irqsave(&the_port->lock, pflags);
-
- read_count = do_read(the_port, ch, MAX_CHARS);
- if (read_count > 0) {
- flip = 1;
- read_room = tty_insert_flip_string(&state->port, ch,
- read_count);
- the_port->icount.rx += read_count;
- }
- spin_unlock_irqrestore(&the_port->lock, pflags);
-
- if (flip)
- tty_flip_buffer_push(&state->port);
-
- return read_count;
-}
-
-/**
- * ioc3uart_intr_one - lowest level (per port) interrupt handler.
- * @is : submodule
- * @idd: driver data
- * @pending: interrupts to handle
- */
-
-static inline int
-ioc3uart_intr_one(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd,
- unsigned int pending)
-{
- int port_num = GET_PORT_FROM_SIO_IR(pending);
- struct port_hooks *hooks;
- unsigned int rx_high_rd_aborted = 0;
- unsigned long flags;
- struct uart_port *the_port;
- struct ioc3_port *port;
- int loop_counter;
- struct ioc3_card *card_ptr;
- unsigned int sio_ir;
-
- card_ptr = idd->data[is->id];
- port = card_ptr->ic_port[port_num].icp_port;
- hooks = port->ip_hooks;
-
- /* Possible race condition here: The tx_mt interrupt bit may be
- * cleared without the intervention of the interrupt handler,
- * e.g. by a write. If the top level interrupt handler reads a
- * tx_mt, then some other processor does a write, starting up
- * output, then we come in here, see the tx_mt and stop DMA, the
- * output started by the other processor will hang. Thus we can
- * only rely on tx_mt being legitimate if it is read while the
- * port lock is held. Therefore this bit must be ignored in the
- * passed in interrupt mask which was read by the top level
- * interrupt handler since the port lock was not held at the time
- * it was read. We can only rely on this bit being accurate if it
- * is read while the port lock is held. So we'll clear it for now,
- * and reload it later once we have the port lock.
- */
-
- sio_ir = pending & ~(hooks->intr_tx_mt);
- spin_lock_irqsave(&port->ip_lock, flags);
-
- loop_counter = MAXITER; /* to avoid hangs */
-
- do {
- uint32_t shadow;
-
- if (loop_counter-- <= 0) {
- printk(KERN_WARNING "IOC3 serial: "
- "possible hang condition/"
- "port stuck on interrupt (line %d).\n",
- ((struct uart_port *)port->ip_port)->line);
- break;
- }
- /* Handle a DCD change */
- if (sio_ir & hooks->intr_delta_dcd) {
- ioc3_ack(is, idd, hooks->intr_delta_dcd);
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DDCD)
- && (shadow & SHADOW_DCD)
- && (port->ip_port)) {
- the_port = port->ip_port;
- uart_handle_dcd_change(the_port,
- shadow & SHADOW_DCD);
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- } else if ((port->ip_notify & N_DDCD)
- && !(shadow & SHADOW_DCD)) {
- /* Flag delta DCD/no DCD */
- uart_handle_dcd_change(port->ip_port,
- shadow & SHADOW_DCD);
- port->ip_flags |= DCD_ON;
- }
- }
-
- /* Handle a CTS change */
- if (sio_ir & hooks->intr_delta_cts) {
- ioc3_ack(is, idd, hooks->intr_delta_cts);
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DCTS) && (port->ip_port)) {
- the_port = port->ip_port;
- uart_handle_cts_change(the_port, shadow
- & SHADOW_CTS);
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- }
- }
-
- /* rx timeout interrupt. Must be some data available. Put this
- * before the check for rx_high since servicing this condition
- * may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_rx_timer) {
- ioc3_ack(is, idd, hooks->intr_rx_timer);
- if ((port->ip_notify & N_DATA_READY)
- && (port->ip_port)) {
- receive_chars(port->ip_port);
- }
- }
-
- /* rx high interrupt. Must be after rx_timer. */
- else if (sio_ir & hooks->intr_rx_high) {
- /* Data available, notify upper layer */
- if ((port->ip_notify & N_DATA_READY) && port->ip_port) {
- receive_chars(port->ip_port);
- }
-
- /* We can't ACK this interrupt. If receive_chars didn't
- * cause the condition to clear, we'll have to disable
- * the interrupt until the data is drained.
- * If the read was aborted, don't disable the interrupt
- * as this may cause us to hang indefinitely. An
- * aborted read generally means that this interrupt
- * hasn't been delivered to the cpu yet anyway, even
- * though we see it as asserted when we read the sio_ir.
- */
- if ((sio_ir = PENDING(card_ptr, idd))
- & hooks->intr_rx_high) {
- if (port->ip_flags & READ_ABORTED) {
- rx_high_rd_aborted++;
- }
- else {
- card_ptr->ic_enable &= ~hooks->intr_rx_high;
- port->ip_flags |= INPUT_HIGH;
- }
- }
- }
-
- /* We got a low water interrupt: notify upper layer to
- * send more data. Must come before tx_mt since servicing
- * this condition may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_tx_explicit) {
- port->ip_flags &= ~LOWAT_WRITTEN;
- ioc3_ack(is, idd, hooks->intr_tx_explicit);
- if (port->ip_notify & N_OUTPUT_LOWAT)
- ioc3_cb_output_lowat(port);
- }
-
- /* Handle tx_mt. Must come after tx_explicit. */
- else if (sio_ir & hooks->intr_tx_mt) {
- /* If we are expecting a lowat notification
- * and we get to this point it probably means that for
- * some reason the tx_explicit didn't work as expected
- * (that can legitimately happen if the output buffer is
- * filled up in just the right way).
- * So send the notification now.
- */
- if (port->ip_notify & N_OUTPUT_LOWAT) {
- ioc3_cb_output_lowat(port);
-
- /* We need to reload the sio_ir since the lowat
- * call may have caused another write to occur,
- * clearing the tx_mt condition.
- */
- sio_ir = PENDING(card_ptr, idd);
- }
-
- /* If the tx_mt condition still persists even after the
- * lowat call, we've got some work to do.
- */
- if (sio_ir & hooks->intr_tx_mt) {
- /* If we are not currently expecting DMA input,
- * and the transmitter has just gone idle,
- * there is no longer any reason for DMA, so
- * disable it.
- */
- if (!(port->ip_notify
- & (N_DATA_READY | N_DDCD))) {
- BUG_ON(!(port->ip_sscr
- & SSCR_DMA_EN));
- port->ip_sscr &= ~SSCR_DMA_EN;
- writel(port->ip_sscr,
- &port->ip_serial_regs->sscr);
- }
- /* Prevent infinite tx_mt interrupt */
- card_ptr->ic_enable &= ~hooks->intr_tx_mt;
- }
- }
- sio_ir = PENDING(card_ptr, idd);
-
- /* if the read was aborted and only hooks->intr_rx_high,
- * clear hooks->intr_rx_high, so we do not loop forever.
- */
-
- if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
- sio_ir &= ~hooks->intr_rx_high;
- }
- } while (sio_ir & hooks->intr_all);
-
- spin_unlock_irqrestore(&port->ip_lock, flags);
- ioc3_enable(is, idd, card_ptr->ic_enable);
- return 0;
-}
-
-/**
- * ioc3uart_intr - field all serial interrupts
- * @is : submodule
- * @idd: driver data
- * @pending: interrupts to handle
- *
- */
-
-static int ioc3uart_intr(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd,
- unsigned int pending)
-{
- int ret = 0;
-
- /*
- * The upper level interrupt handler sends interrupts for both ports
- * here. So we need to call for each port with its interrupts.
- */
-
- if (pending & SIO_IR_SA)
- ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA);
- if (pending & SIO_IR_SB)
- ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB);
-
- return ret;
-}
-
-/**
- * ic3_type
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *ic3_type(struct uart_port *the_port)
-{
- if (IS_RS232(the_port->line))
- return "SGI IOC3 Serial [rs232]";
- else
- return "SGI IOC3 Serial [rs422]";
-}
-
-/**
- * ic3_tx_empty - Is the transmitter empty?
- * @port: Port to operate on
- *
- */
-static unsigned int ic3_tx_empty(struct uart_port *the_port)
-{
- unsigned int ret = 0;
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT)
- ret = TIOCSER_TEMT;
- return ret;
-}
-
-/**
- * ic3_stop_tx - stop the transmitter
- * @port: Port to operate on
- *
- */
-static void ic3_stop_tx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port)
- set_notification(port, N_OUTPUT_LOWAT, 0);
-}
-
-/**
- * ic3_stop_rx - stop the receiver
- * @port: Port to operate on
- *
- */
-static void ic3_stop_rx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port)
- port->ip_flags &= ~INPUT_ENABLE;
-}
-
-/**
- * null_void_function
- * @port: Port to operate on
- *
- */
-static void null_void_function(struct uart_port *the_port)
-{
-}
-
-/**
- * ic3_shutdown - shut down the port - free irq and disable
- * @port: port to shut down
- *
- */
-static void ic3_shutdown(struct uart_port *the_port)
-{
- unsigned long port_flags;
- struct ioc3_port *port;
- struct uart_state *state;
-
- port = get_ioc3_port(the_port);
- if (!port)
- return;
-
- state = the_port->state;
- wake_up_interruptible(&state->port.delta_msr_wait);
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- set_notification(port, N_ALL, 0);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic3_set_mctrl - set control lines (dtr, rts, etc)
- * @port: Port to operate on
- * @mctrl: Lines to set/unset
- *
- */
-static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
-{
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- set_mcr(the_port, mcr, SHADOW_DTR);
-}
-
-/**
- * ic3_get_mctrl - get control line info
- * @port: port to operate on
- *
- */
-static unsigned int ic3_get_mctrl(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- uint32_t shadow;
- unsigned int ret = 0;
-
- if (!port)
- return 0;
-
- shadow = readl(&port->ip_serial_regs->shadow);
- if (shadow & SHADOW_DCD)
- ret |= TIOCM_CD;
- if (shadow & SHADOW_DR)
- ret |= TIOCM_DSR;
- if (shadow & SHADOW_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-/**
- * ic3_start_tx - Start transmitter. Called with the_port->lock
- * @port: Port to operate on
- *
- */
-static void ic3_start_tx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port) {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- enable_intrs(port, port->ip_hooks->intr_tx_mt);
- }
-}
-
-/**
- * ic3_break_ctl - handle breaks
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void ic3_break_ctl(struct uart_port *the_port, int break_state)
-{
-}
-
-/**
- * ic3_startup - Start up the serial port - always return 0 (We're always on)
- * @port: Port to operate on
- *
- */
-static int ic3_startup(struct uart_port *the_port)
-{
- int retval;
- struct ioc3_port *port;
- struct ioc3_card *card_ptr;
- unsigned long port_flags;
-
- if (!the_port) {
- NOT_PROGRESS();
- return -ENODEV;
- }
- port = get_ioc3_port(the_port);
- if (!port) {
- NOT_PROGRESS();
- return -ENODEV;
- }
- card_ptr = port->ip_card;
- port->ip_port = the_port;
-
- if (!card_ptr) {
- NOT_PROGRESS();
- return -ENODEV;
- }
-
- /* Start up the serial port */
- spin_lock_irqsave(&the_port->lock, port_flags);
- retval = ic3_startup_local(the_port);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
- return retval;
-}
-
-/**
- * ic3_set_termios - set termios stuff
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-ic3_set_termios(struct uart_port *the_port,
- struct ktermios *termios, struct ktermios *old_termios)
-{
- unsigned long port_flags;
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- ioc3_change_speed(the_port, termios, old_termios);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic3_request_port - allocate resources for port - no op....
- * @port: port to operate on
- *
- */
-static int ic3_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* Associate the uart functions above - given to serial core */
-static const struct uart_ops ioc3_ops = {
- .tx_empty = ic3_tx_empty,
- .set_mctrl = ic3_set_mctrl,
- .get_mctrl = ic3_get_mctrl,
- .stop_tx = ic3_stop_tx,
- .start_tx = ic3_start_tx,
- .stop_rx = ic3_stop_rx,
- .break_ctl = ic3_break_ctl,
- .startup = ic3_startup,
- .shutdown = ic3_shutdown,
- .set_termios = ic3_set_termios,
- .type = ic3_type,
- .release_port = null_void_function,
- .request_port = ic3_request_port,
-};
-
-/*
- * Boot-time initialization code
- */
-
-static struct uart_driver ioc3_uart = {
- .owner = THIS_MODULE,
- .driver_name = "ioc3_serial",
- .dev_name = DEVICE_NAME,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR,
- .nr = MAX_LOGICAL_PORTS
-};
-
-/**
- * ioc3_serial_core_attach - register with serial core
- * This is done during pci probing
- * @is: submodule struct for this
- * @idd: handle for this card
- */
-static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
- struct ioc3_driver_data *idd)
-{
- struct ioc3_port *port;
- struct uart_port *the_port;
- struct ioc3_card *card_ptr = idd->data[is->id];
- int ii, phys_port;
- struct pci_dev *pdev = idd->pdev;
-
- DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
- __func__, pdev, (void *)card_ptr));
-
- if (!card_ptr)
- return -ENODEV;
-
- /* once around for each logical port on this card */
- for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
- phys_port = GET_PHYSICAL_PORT(ii);
- the_port = &card_ptr->ic_port[phys_port].
- icp_uart_port[GET_LOGICAL_PORT(ii)];
- port = card_ptr->ic_port[phys_port].icp_port;
- port->ip_port = the_port;
-
- DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
- __func__, (void *)the_port, (void *)port,
- phys_port, ii));
-
- /* membase, iobase and mapbase just need to be non-0 */
- the_port->membase = (unsigned char __iomem *)1;
- the_port->iobase = (pdev->bus->number << 16) | ii;
- the_port->line = (Num_of_ioc3_cards << 2) | ii;
- the_port->mapbase = 1;
- the_port->type = PORT_16550A;
- the_port->fifosize = FIFO_SIZE;
- the_port->ops = &ioc3_ops;
- the_port->irq = idd->irq_io;
- the_port->dev = &pdev->dev;
-
- if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
- printk(KERN_WARNING
- "%s: unable to add port %d bus %d\n",
- __func__, the_port->line, pdev->bus->number);
- } else {
- DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
- the_port->line, the_port->irq, pdev->bus->number));
- }
-
- /* all ports are rs232 for now */
- if (IS_PHYSICAL_PORT(ii))
- ioc3_set_proto(port, PROTO_RS232);
- }
- return 0;
-}
-
-/**
- * ioc3uart_remove - register detach function
- * @is: submodule struct for this submodule
- * @idd: ioc3 driver data for this submodule
- */
-
-static int ioc3uart_remove(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd)
-{
- struct ioc3_card *card_ptr = idd->data[is->id];
- struct uart_port *the_port;
- struct ioc3_port *port;
- int ii;
-
- if (card_ptr) {
- for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
- the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
- icp_uart_port[GET_LOGICAL_PORT(ii)];
- if (the_port)
- uart_remove_one_port(&ioc3_uart, the_port);
- port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port;
- if (port && IS_PHYSICAL_PORT(ii)
- && (GET_PHYSICAL_PORT(ii) == 0)) {
- pci_free_consistent(port->ip_idd->pdev,
- TOTAL_RING_BUF_SIZE,
- (void *)port->ip_cpu_ringbuf,
- port->ip_dma_ringbuf);
- kfree(port);
- card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
- icp_port = NULL;
- }
- }
- kfree(card_ptr);
- idd->data[is->id] = NULL;
- }
- return 0;
-}
-
-/**
- * ioc3uart_probe - card probe function called from shim driver
- * @is: submodule struct for this submodule
- * @idd: ioc3 driver data for this card
- */
-
-static int
-ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
-{
- struct pci_dev *pdev = idd->pdev;
- struct ioc3_card *card_ptr;
- int ret = 0;
- struct ioc3_port *port;
- struct ioc3_port *ports[PORTS_PER_CARD];
- int phys_port;
- int cnt;
-
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
-
- card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
- if (!card_ptr) {
- printk(KERN_WARNING "ioc3_attach_one"
- ": unable to get memory for the IOC3\n");
- return -ENOMEM;
- }
- idd->data[is->id] = card_ptr;
- Submodule_slot = is->id;
-
- writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) |
- ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) |
- (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr);
-
- pci_write_config_dword(pdev, PCI_LAT, 0xff00);
-
- /* Enable serial port mode select generic PIO pins as outputs */
- ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL);
-
- /* Create port structures for each port */
- for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
- port = kzalloc(sizeof(struct ioc3_port), GFP_KERNEL);
- if (!port) {
- printk(KERN_WARNING
- "IOC3 serial memory not available for port\n");
- ret = -ENOMEM;
- goto out4;
- }
- spin_lock_init(&port->ip_lock);
-
- /* we need to remember the previous ones, to point back to
- * them farther down - setting up the ring buffers.
- */
- ports[phys_port] = port;
-
- /* init to something useful */
- card_ptr->ic_port[phys_port].icp_port = port;
- port->ip_is = is;
- port->ip_idd = idd;
- port->ip_baud = 9600;
- port->ip_card = card_ptr;
- port->ip_hooks = &hooks_array[phys_port];
-
- /* Setup each port */
- if (phys_port == 0) {
- port->ip_serial_regs = &idd->vma->port_a;
- port->ip_uart_regs = &idd->vma->sregs.uarta;
-
- DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
- "ip_uart_regs 0x%p\n",
- __func__,
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* setup ring buffers */
- port->ip_cpu_ringbuf = pci_alloc_consistent(pdev,
- TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf);
-
- BUG_ON(!((((int64_t) port->ip_dma_ringbuf) &
- (TOTAL_RING_BUF_SIZE - 1)) == 0));
- port->ip_inring = RING(port, RX_A);
- port->ip_outring = RING(port, TX_A);
- DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
- "ip_outring 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
- }
- else {
- port->ip_serial_regs = &idd->vma->port_b;
- port->ip_uart_regs = &idd->vma->sregs.uartb;
-
- DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
- "ip_uart_regs 0x%p\n",
- __func__,
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* share the ring buffers */
- port->ip_dma_ringbuf =
- ports[phys_port - 1]->ip_dma_ringbuf;
- port->ip_cpu_ringbuf =
- ports[phys_port - 1]->ip_cpu_ringbuf;
- port->ip_inring = RING(port, RX_B);
- port->ip_outring = RING(port, TX_B);
- DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
- "ip_outring 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
- }
-
- DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
- __func__,
- phys_port, (void *)port, (void *)card_ptr));
- DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* Initialize the hardware for IOC3 */
- port_init(port);
-
- DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
- "outring 0x%p\n",
- __func__,
- phys_port, (void *)port,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
-
- }
-
- /* register port with the serial core */
-
- ret = ioc3_serial_core_attach(is, idd);
- if (ret)
- goto out4;
-
- Num_of_ioc3_cards++;
-
- return ret;
-
- /* error exits that give back resources */
-out4:
- for (cnt = 0; cnt < phys_port; cnt++)
- kfree(ports[cnt]);
-
- kfree(card_ptr);
- return ret;
-}
-
-static struct ioc3_submodule ioc3uart_ops = {
- .name = "IOC3uart",
- .probe = ioc3uart_probe,
- .remove = ioc3uart_remove,
- /* call .intr for both ports initially */
- .irq_mask = SIO_IR_SA | SIO_IR_SB,
- .intr = ioc3uart_intr,
- .owner = THIS_MODULE,
-};
-
-/**
- * ioc3_detect - module init called,
- */
-static int __init ioc3uart_init(void)
-{
- int ret;
-
- /* register with serial core */
- if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register IOC3 uart serial driver\n",
- __func__);
- return ret;
- }
- ret = ioc3_register_submodule(&ioc3uart_ops);
- if (ret)
- uart_unregister_driver(&ioc3_uart);
- return ret;
-}
-
-static void __exit ioc3uart_exit(void)
-{
- ioc3_unregister_submodule(&ioc3uart_ops);
- uart_unregister_driver(&ioc3_uart);
-}
-
-module_init(ioc3uart_init);
-module_exit(ioc3uart_exit);
-
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c
deleted file mode 100644
index db5b979e5a0c..000000000000
--- a/drivers/tty/serial/ioc4_serial.c
+++ /dev/null
@@ -1,2955 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-
-/*
- * This file contains a module version of the ioc4 serial driver. This
- * includes all the support functions needed (support functions, etc.)
- * and the serial driver itself.
- */
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ioc4.h>
-#include <linux/serial_core.h>
-#include <linux/slab.h>
-
-/*
- * interesting things about the ioc4
- */
-
-#define IOC4_NUM_SERIAL_PORTS 4 /* max ports per card */
-#define IOC4_NUM_CARDS 8 /* max cards per partition */
-
-#define GET_SIO_IR(_n) (_n == 0) ? (IOC4_SIO_IR_S0) : \
- (_n == 1) ? (IOC4_SIO_IR_S1) : \
- (_n == 2) ? (IOC4_SIO_IR_S2) : \
- (IOC4_SIO_IR_S3)
-
-#define GET_OTHER_IR(_n) (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \
- (_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \
- (_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \
- (IOC4_OTHER_IR_S3_MEMERR)
-
-
-/*
- * All IOC4 registers are 32 bits wide.
- */
-
-/*
- * PCI Memory Space Map
- */
-#define IOC4_PCI_ERR_ADDR_L 0x000 /* Low Error Address */
-#define IOC4_PCI_ERR_ADDR_VLD (0x1 << 0)
-#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1)
-#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK (0xe << 1)
-#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK (0x1 << 1)
-#define IOC4_PCI_ERR_ADDR_MUL_ERR (0x1 << 5)
-#define IOC4_PCI_ERR_ADDR_ADDR_MSK (0x3ffffff << 6)
-
-/* Interrupt types */
-#define IOC4_SIO_INTR_TYPE 0
-#define IOC4_OTHER_INTR_TYPE 1
-#define IOC4_NUM_INTR_TYPES 2
-
-/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES */
-#define IOC4_SIO_IR_S0_TX_MT 0x00000001 /* Serial port 0 TX empty */
-#define IOC4_SIO_IR_S0_RX_FULL 0x00000002 /* Port 0 RX buf full */
-#define IOC4_SIO_IR_S0_RX_HIGH 0x00000004 /* Port 0 RX hiwat */
-#define IOC4_SIO_IR_S0_RX_TIMER 0x00000008 /* Port 0 RX timeout */
-#define IOC4_SIO_IR_S0_DELTA_DCD 0x00000010 /* Port 0 delta DCD */
-#define IOC4_SIO_IR_S0_DELTA_CTS 0x00000020 /* Port 0 delta CTS */
-#define IOC4_SIO_IR_S0_INT 0x00000040 /* Port 0 pass-thru intr */
-#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080 /* Port 0 explicit TX thru */
-#define IOC4_SIO_IR_S1_TX_MT 0x00000100 /* Serial port 1 */
-#define IOC4_SIO_IR_S1_RX_FULL 0x00000200 /* */
-#define IOC4_SIO_IR_S1_RX_HIGH 0x00000400 /* */
-#define IOC4_SIO_IR_S1_RX_TIMER 0x00000800 /* */
-#define IOC4_SIO_IR_S1_DELTA_DCD 0x00001000 /* */
-#define IOC4_SIO_IR_S1_DELTA_CTS 0x00002000 /* */
-#define IOC4_SIO_IR_S1_INT 0x00004000 /* */
-#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000 /* */
-#define IOC4_SIO_IR_S2_TX_MT 0x00010000 /* Serial port 2 */
-#define IOC4_SIO_IR_S2_RX_FULL 0x00020000 /* */
-#define IOC4_SIO_IR_S2_RX_HIGH 0x00040000 /* */
-#define IOC4_SIO_IR_S2_RX_TIMER 0x00080000 /* */
-#define IOC4_SIO_IR_S2_DELTA_DCD 0x00100000 /* */
-#define IOC4_SIO_IR_S2_DELTA_CTS 0x00200000 /* */
-#define IOC4_SIO_IR_S2_INT 0x00400000 /* */
-#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000 /* */
-#define IOC4_SIO_IR_S3_TX_MT 0x01000000 /* Serial port 3 */
-#define IOC4_SIO_IR_S3_RX_FULL 0x02000000 /* */
-#define IOC4_SIO_IR_S3_RX_HIGH 0x04000000 /* */
-#define IOC4_SIO_IR_S3_RX_TIMER 0x08000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_DCD 0x10000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_CTS 0x20000000 /* */
-#define IOC4_SIO_IR_S3_INT 0x40000000 /* */
-#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000 /* */
-
-/* Per device interrupt masks */
-#define IOC4_SIO_IR_S0 (IOC4_SIO_IR_S0_TX_MT | \
- IOC4_SIO_IR_S0_RX_FULL | \
- IOC4_SIO_IR_S0_RX_HIGH | \
- IOC4_SIO_IR_S0_RX_TIMER | \
- IOC4_SIO_IR_S0_DELTA_DCD | \
- IOC4_SIO_IR_S0_DELTA_CTS | \
- IOC4_SIO_IR_S0_INT | \
- IOC4_SIO_IR_S0_TX_EXPLICIT)
-#define IOC4_SIO_IR_S1 (IOC4_SIO_IR_S1_TX_MT | \
- IOC4_SIO_IR_S1_RX_FULL | \
- IOC4_SIO_IR_S1_RX_HIGH | \
- IOC4_SIO_IR_S1_RX_TIMER | \
- IOC4_SIO_IR_S1_DELTA_DCD | \
- IOC4_SIO_IR_S1_DELTA_CTS | \
- IOC4_SIO_IR_S1_INT | \
- IOC4_SIO_IR_S1_TX_EXPLICIT)
-#define IOC4_SIO_IR_S2 (IOC4_SIO_IR_S2_TX_MT | \
- IOC4_SIO_IR_S2_RX_FULL | \
- IOC4_SIO_IR_S2_RX_HIGH | \
- IOC4_SIO_IR_S2_RX_TIMER | \
- IOC4_SIO_IR_S2_DELTA_DCD | \
- IOC4_SIO_IR_S2_DELTA_CTS | \
- IOC4_SIO_IR_S2_INT | \
- IOC4_SIO_IR_S2_TX_EXPLICIT)
-#define IOC4_SIO_IR_S3 (IOC4_SIO_IR_S3_TX_MT | \
- IOC4_SIO_IR_S3_RX_FULL | \
- IOC4_SIO_IR_S3_RX_HIGH | \
- IOC4_SIO_IR_S3_RX_TIMER | \
- IOC4_SIO_IR_S3_DELTA_DCD | \
- IOC4_SIO_IR_S3_DELTA_CTS | \
- IOC4_SIO_IR_S3_INT | \
- IOC4_SIO_IR_S3_TX_EXPLICIT)
-
-/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */
-#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
-#define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */
-#define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */
-#define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */
-#define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */
-
-#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
- IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
-
-/* Bitmasks for IOC4_SIO_CR */
-#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */
-#define IOC4_SIO_CR_ARB_DIAG_TX0 0x00000000
-#define IOC4_SIO_CR_ARB_DIAG_RX0 0x00000010
-#define IOC4_SIO_CR_ARB_DIAG_TX1 0x00000020
-#define IOC4_SIO_CR_ARB_DIAG_RX1 0x00000030
-#define IOC4_SIO_CR_ARB_DIAG_TX2 0x00000040
-#define IOC4_SIO_CR_ARB_DIAG_RX2 0x00000050
-#define IOC4_SIO_CR_ARB_DIAG_TX3 0x00000060
-#define IOC4_SIO_CR_ARB_DIAG_RX3 0x00000070
-#define IOC4_SIO_CR_SIO_DIAG_IDLE 0x00000080 /* 0 -> active request among
- serial ports (ro) */
-/* Defs for some of the generic I/O pins */
-#define IOC4_GPCR_UART0_MODESEL 0x10 /* Pin is output to port 0
- mode sel */
-#define IOC4_GPCR_UART1_MODESEL 0x20 /* Pin is output to port 1
- mode sel */
-#define IOC4_GPCR_UART2_MODESEL 0x40 /* Pin is output to port 2
- mode sel */
-#define IOC4_GPCR_UART3_MODESEL 0x80 /* Pin is output to port 3
- mode sel */
-
-#define IOC4_GPPR_UART0_MODESEL_PIN 4 /* GIO pin controlling
- uart 0 mode select */
-#define IOC4_GPPR_UART1_MODESEL_PIN 5 /* GIO pin controlling
- uart 1 mode select */
-#define IOC4_GPPR_UART2_MODESEL_PIN 6 /* GIO pin controlling
- uart 2 mode select */
-#define IOC4_GPPR_UART3_MODESEL_PIN 7 /* GIO pin controlling
- uart 3 mode select */
-
-/* Bitmasks for serial RX status byte */
-#define IOC4_RXSB_OVERRUN 0x01 /* Char(s) lost */
-#define IOC4_RXSB_PAR_ERR 0x02 /* Parity error */
-#define IOC4_RXSB_FRAME_ERR 0x04 /* Framing error */
-#define IOC4_RXSB_BREAK 0x08 /* Break character */
-#define IOC4_RXSB_CTS 0x10 /* State of CTS */
-#define IOC4_RXSB_DCD 0x20 /* State of DCD */
-#define IOC4_RXSB_MODEM_VALID 0x40 /* DCD, CTS, and OVERRUN are valid */
-#define IOC4_RXSB_DATA_VALID 0x80 /* Data byte, FRAME_ERR PAR_ERR
- * & BREAK valid */
-
-/* Bitmasks for serial TX control byte */
-#define IOC4_TXCB_INT_WHEN_DONE 0x20 /* Interrupt after this byte is sent */
-#define IOC4_TXCB_INVALID 0x00 /* Byte is invalid */
-#define IOC4_TXCB_VALID 0x40 /* Byte is valid */
-#define IOC4_TXCB_MCR 0x80 /* Data<7:0> to modem control reg */
-#define IOC4_TXCB_DELAY 0xc0 /* Delay data<7:0> mSec */
-
-/* Bitmasks for IOC4_SBBR_L */
-#define IOC4_SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */
-
-/* Bitmasks for IOC4_SSCR_<3:0> */
-#define IOC4_SSCR_RX_THRESHOLD 0x000001ff /* Hiwater mark */
-#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
-#define IOC4_SSCR_HFC_EN 0x00020000 /* Hardware flow control enabled */
-#define IOC4_SSCR_RX_RING_DCD 0x00040000 /* Post RX record on delta-DCD */
-#define IOC4_SSCR_RX_RING_CTS 0x00080000 /* Post RX record on delta-CTS */
-#define IOC4_SSCR_DIAG 0x00200000 /* Bypass clock divider for sim */
-#define IOC4_SSCR_RX_DRAIN 0x08000000 /* Drain RX buffer to memory */
-#define IOC4_SSCR_DMA_EN 0x10000000 /* Enable ring buffer DMA */
-#define IOC4_SSCR_DMA_PAUSE 0x20000000 /* Pause DMA */
-#define IOC4_SSCR_PAUSE_STATE 0x40000000 /* Sets when PAUSE takes effect */
-#define IOC4_SSCR_RESET 0x80000000 /* Reset DMA channels */
-
-/* All producer/consumer pointers are the same bitfield */
-#define IOC4_PROD_CONS_PTR_4K 0x00000ff8 /* For 4K buffers */
-#define IOC4_PROD_CONS_PTR_1K 0x000003f8 /* For 1K buffers */
-#define IOC4_PROD_CONS_PTR_OFF 3
-
-/* Bitmasks for IOC4_SRCIR_<3:0> */
-#define IOC4_SRCIR_ARM 0x80000000 /* Arm RX timer */
-
-/* Bitmasks for IOC4_SHADOW_<3:0> */
-#define IOC4_SHADOW_DR 0x00000001 /* Data ready */
-#define IOC4_SHADOW_OE 0x00000002 /* Overrun error */
-#define IOC4_SHADOW_PE 0x00000004 /* Parity error */
-#define IOC4_SHADOW_FE 0x00000008 /* Framing error */
-#define IOC4_SHADOW_BI 0x00000010 /* Break interrupt */
-#define IOC4_SHADOW_THRE 0x00000020 /* Xmit holding register empty */
-#define IOC4_SHADOW_TEMT 0x00000040 /* Xmit shift register empty */
-#define IOC4_SHADOW_RFCE 0x00000080 /* Char in RX fifo has an error */
-#define IOC4_SHADOW_DCTS 0x00010000 /* Delta clear to send */
-#define IOC4_SHADOW_DDCD 0x00080000 /* Delta data carrier detect */
-#define IOC4_SHADOW_CTS 0x00100000 /* Clear to send */
-#define IOC4_SHADOW_DCD 0x00800000 /* Data carrier detect */
-#define IOC4_SHADOW_DTR 0x01000000 /* Data terminal ready */
-#define IOC4_SHADOW_RTS 0x02000000 /* Request to send */
-#define IOC4_SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
-#define IOC4_SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
-#define IOC4_SHADOW_LOOP 0x10000000 /* Loopback enabled */
-
-/* Bitmasks for IOC4_SRTR_<3:0> */
-#define IOC4_SRTR_CNT 0x00000fff /* Reload value for RX timer */
-#define IOC4_SRTR_CNT_VAL 0x0fff0000 /* Current value of RX timer */
-#define IOC4_SRTR_CNT_VAL_SHIFT 16
-#define IOC4_SRTR_HZ 16000 /* SRTR clock frequency */
-
-/* Serial port register map used for DMA and PIO serial I/O */
-struct ioc4_serialregs {
- uint32_t sscr;
- uint32_t stpir;
- uint32_t stcir;
- uint32_t srpir;
- uint32_t srcir;
- uint32_t srtr;
- uint32_t shadow;
-};
-
-/* IOC4 UART register map */
-struct ioc4_uartregs {
- char i4u_lcr;
- union {
- char iir; /* read only */
- char fcr; /* write only */
- } u3;
- union {
- char ier; /* DLAB == 0 */
- char dlm; /* DLAB == 1 */
- } u2;
- union {
- char rbr; /* read only, DLAB == 0 */
- char thr; /* write only, DLAB == 0 */
- char dll; /* DLAB == 1 */
- } u1;
- char i4u_scr;
- char i4u_msr;
- char i4u_lsr;
- char i4u_mcr;
-};
-
-/* short names */
-#define i4u_dll u1.dll
-#define i4u_ier u2.ier
-#define i4u_dlm u2.dlm
-#define i4u_fcr u3.fcr
-
-/* Serial port registers used for DMA serial I/O */
-struct ioc4_serial {
- uint32_t sbbr01_l;
- uint32_t sbbr01_h;
- uint32_t sbbr23_l;
- uint32_t sbbr23_h;
-
- struct ioc4_serialregs port_0;
- struct ioc4_serialregs port_1;
- struct ioc4_serialregs port_2;
- struct ioc4_serialregs port_3;
- struct ioc4_uartregs uart_0;
- struct ioc4_uartregs uart_1;
- struct ioc4_uartregs uart_2;
- struct ioc4_uartregs uart_3;
-};
-
-/* UART clock speed */
-#define IOC4_SER_XIN_CLK_66 66666667
-#define IOC4_SER_XIN_CLK_33 33333333
-
-#define IOC4_W_IES 0
-#define IOC4_W_IEC 1
-
-typedef void ioc4_intr_func_f(void *, uint32_t);
-typedef ioc4_intr_func_f *ioc4_intr_func_t;
-
-static unsigned int Num_of_ioc4_cards;
-
-/* defining this will get you LOTS of great debug info */
-//#define DEBUG_INTERRUPTS
-#define DPRINT_CONFIG(_x...) ;
-//#define DPRINT_CONFIG(_x...) printk _x
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* number of characters we want to transmit to the lower level at a time */
-#define IOC4_MAX_CHARS 256
-#define IOC4_FIFO_CHARS 255
-
-/* Device name we're using */
-#define DEVICE_NAME_RS232 "ttyIOC"
-#define DEVICE_NAME_RS422 "ttyAIOC"
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR_RS232 50
-#define DEVICE_MINOR_RS422 84
-
-
-/* register offsets */
-#define IOC4_SERIAL_OFFSET 0x300
-
-/* flags for next_char_state */
-#define NCS_BREAK 0x1
-#define NCS_PARITY 0x2
-#define NCS_FRAMING 0x4
-#define NCS_OVERRUN 0x8
-
-/* cause we need SOME parameters ... */
-#define MIN_BAUD_SUPPORTED 1200
-#define MAX_BAUD_SUPPORTED 115200
-
-/* protocol types supported */
-#define PROTO_RS232 3
-#define PROTO_RS422 7
-
-/* Notification types */
-#define N_DATA_READY 0x01
-#define N_OUTPUT_LOWAT 0x02
-#define N_BREAK 0x04
-#define N_PARITY_ERROR 0x08
-#define N_FRAMING_ERROR 0x10
-#define N_OVERRUN_ERROR 0x20
-#define N_DDCD 0x40
-#define N_DCTS 0x80
-
-#define N_ALL_INPUT (N_DATA_READY | N_BREAK | \
- N_PARITY_ERROR | N_FRAMING_ERROR | \
- N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define N_ALL_OUTPUT N_OUTPUT_LOWAT
-
-#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)
-
-#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK | \
- N_PARITY_ERROR | N_FRAMING_ERROR | \
- N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define SER_DIVISOR(_x, clk) (((clk) + (_x) * 8) / ((_x) * 16))
-#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
-
-/* Some masks */
-#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
- | UART_LCR_WLEN7 | UART_LCR_WLEN8)
-#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
-
-#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
-#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
-
-/* Default to 4k buffers */
-#ifdef IOC4_1K_BUFFERS
-#define RING_BUF_SIZE 1024
-#define IOC4_BUF_SIZE_BIT 0
-#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K
-#else
-#define RING_BUF_SIZE 4096
-#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE
-#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K
-#endif
-
-#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
-
-/*
- * This is the entry saved by the driver - one per card
- */
-
-#define UART_PORT_MIN 0
-#define UART_PORT_RS232 UART_PORT_MIN
-#define UART_PORT_RS422 1
-#define UART_PORT_COUNT 2 /* one for each mode */
-
-struct ioc4_control {
- int ic_irq;
- struct {
- /* uart ports are allocated here - 1 for rs232, 1 for rs422 */
- struct uart_port icp_uart_port[UART_PORT_COUNT];
- /* Handy reference material */
- struct ioc4_port *icp_port;
- } ic_port[IOC4_NUM_SERIAL_PORTS];
- struct ioc4_soft *ic_soft;
-};
-
-/*
- * per-IOC4 data structure
- */
-#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t))
-struct ioc4_soft {
- struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
- struct ioc4_serial __iomem *is_ioc4_serial_addr;
-
- /* Each interrupt type has an entry in the array */
- struct ioc4_intr_type {
-
- /*
- * Each in-use entry in this array contains at least
- * one nonzero bit in sd_bits; no two entries in this
- * array have overlapping sd_bits values.
- */
- struct ioc4_intr_info {
- uint32_t sd_bits;
- ioc4_intr_func_f *sd_intr;
- void *sd_info;
- } is_intr_info[MAX_IOC4_INTR_ENTS];
-
- /* Number of entries active in the above array */
- atomic_t is_num_intrs;
- } is_intr_type[IOC4_NUM_INTR_TYPES];
-
- /* is_ir_lock must be held while
- * modifying sio_ie values, so
- * we can be sure that sio_ie is
- * not changing when we read it
- * along with sio_ir.
- */
- spinlock_t is_ir_lock; /* SIO_IE[SC] mod lock */
-};
-
-/* Local port info for each IOC4 serial ports */
-struct ioc4_port {
- struct uart_port *ip_port; /* current active port ptr */
- /* Ptrs for all ports */
- struct uart_port *ip_all_ports[UART_PORT_COUNT];
- /* Back ptrs for this port */
- struct ioc4_control *ip_control;
- struct pci_dev *ip_pdev;
- struct ioc4_soft *ip_ioc4_soft;
-
- /* pci mem addresses */
- struct ioc4_misc_regs __iomem *ip_mem;
- struct ioc4_serial __iomem *ip_serial;
- struct ioc4_serialregs __iomem *ip_serial_regs;
- struct ioc4_uartregs __iomem *ip_uart_regs;
-
- /* Ring buffer page for this port */
- dma_addr_t ip_dma_ringbuf;
- /* vaddr of ring buffer */
- struct ring_buffer *ip_cpu_ringbuf;
-
- /* Rings for this port */
- struct ring *ip_inring;
- struct ring *ip_outring;
-
- /* Hook to port specific values */
- struct hooks *ip_hooks;
-
- spinlock_t ip_lock;
-
- /* Various rx/tx parameters */
- int ip_baud;
- int ip_tx_lowat;
- int ip_rx_timeout;
-
- /* Copy of notification bits */
- int ip_notify;
-
- /* Shadow copies of various registers so we don't need to PIO
- * read them constantly
- */
- uint32_t ip_ienb; /* Enabled interrupts */
- uint32_t ip_sscr;
- uint32_t ip_tx_prod;
- uint32_t ip_rx_cons;
- int ip_pci_bus_speed;
- unsigned char ip_flags;
-};
-
-/* tx low water mark. We need to notify the driver whenever tx is getting
- * close to empty so it can refill the tx buffer and keep things going.
- * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
- * have no trouble getting in more chars in time (I certainly hope so).
- */
-#define TX_LOWAT_LATENCY 1000
-#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
-#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
-
-/* Flags per port */
-#define INPUT_HIGH 0x01
-#define DCD_ON 0x02
-#define LOWAT_WRITTEN 0x04
-#define READ_ABORTED 0x08
-#define PORT_ACTIVE 0x10
-#define PORT_INACTIVE 0 /* This is the value when "off" */
-
-
-/* Since each port has different register offsets and bitmasks
- * for everything, we'll store those that we need in tables so we
- * don't have to be constantly checking the port we are dealing with.
- */
-struct hooks {
- uint32_t intr_delta_dcd;
- uint32_t intr_delta_cts;
- uint32_t intr_tx_mt;
- uint32_t intr_rx_timer;
- uint32_t intr_rx_high;
- uint32_t intr_tx_explicit;
- uint32_t intr_dma_error;
- uint32_t intr_clear;
- uint32_t intr_all;
- int rs422_select_pin;
-};
-
-static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
- /* Values for port 0 */
- {
- IOC4_SIO_IR_S0_DELTA_DCD, IOC4_SIO_IR_S0_DELTA_CTS,
- IOC4_SIO_IR_S0_TX_MT, IOC4_SIO_IR_S0_RX_TIMER,
- IOC4_SIO_IR_S0_RX_HIGH, IOC4_SIO_IR_S0_TX_EXPLICIT,
- IOC4_OTHER_IR_S0_MEMERR,
- (IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL |
- IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER |
- IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS |
- IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT),
- IOC4_SIO_IR_S0, IOC4_GPPR_UART0_MODESEL_PIN,
- },
-
- /* Values for port 1 */
- {
- IOC4_SIO_IR_S1_DELTA_DCD, IOC4_SIO_IR_S1_DELTA_CTS,
- IOC4_SIO_IR_S1_TX_MT, IOC4_SIO_IR_S1_RX_TIMER,
- IOC4_SIO_IR_S1_RX_HIGH, IOC4_SIO_IR_S1_TX_EXPLICIT,
- IOC4_OTHER_IR_S1_MEMERR,
- (IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL |
- IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER |
- IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS |
- IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT),
- IOC4_SIO_IR_S1, IOC4_GPPR_UART1_MODESEL_PIN,
- },
-
- /* Values for port 2 */
- {
- IOC4_SIO_IR_S2_DELTA_DCD, IOC4_SIO_IR_S2_DELTA_CTS,
- IOC4_SIO_IR_S2_TX_MT, IOC4_SIO_IR_S2_RX_TIMER,
- IOC4_SIO_IR_S2_RX_HIGH, IOC4_SIO_IR_S2_TX_EXPLICIT,
- IOC4_OTHER_IR_S2_MEMERR,
- (IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL |
- IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER |
- IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS |
- IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT),
- IOC4_SIO_IR_S2, IOC4_GPPR_UART2_MODESEL_PIN,
- },
-
- /* Values for port 3 */
- {
- IOC4_SIO_IR_S3_DELTA_DCD, IOC4_SIO_IR_S3_DELTA_CTS,
- IOC4_SIO_IR_S3_TX_MT, IOC4_SIO_IR_S3_RX_TIMER,
- IOC4_SIO_IR_S3_RX_HIGH, IOC4_SIO_IR_S3_TX_EXPLICIT,
- IOC4_OTHER_IR_S3_MEMERR,
- (IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL |
- IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER |
- IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS |
- IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT),
- IOC4_SIO_IR_S3, IOC4_GPPR_UART3_MODESEL_PIN,
- }
-};
-
-/* A ring buffer entry */
-struct ring_entry {
- union {
- struct {
- uint32_t alldata;
- uint32_t allsc;
- } all;
- struct {
- char data[4]; /* data bytes */
- char sc[4]; /* status/control */
- } s;
- } u;
-};
-
-/* Test the valid bits in any of the 4 sc chars using "allsc" member */
-#define RING_ANY_VALID \
- ((uint32_t)(IOC4_RXSB_MODEM_VALID | IOC4_RXSB_DATA_VALID) * 0x01010101)
-
-#define ring_sc u.s.sc
-#define ring_data u.s.data
-#define ring_allsc u.all.allsc
-
-/* Number of entries per ring buffer. */
-#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
-
-/* An individual ring */
-struct ring {
- struct ring_entry entries[ENTRIES_PER_RING];
-};
-
-/* The whole enchilada */
-struct ring_buffer {
- struct ring TX_0_OR_2;
- struct ring RX_0_OR_2;
- struct ring TX_1_OR_3;
- struct ring RX_1_OR_3;
-};
-
-/* Get a ring from a port struct */
-#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
-
-/* Infinite loop detection.
- */
-#define MAXITER 10000000
-
-/* Prototypes */
-static void receive_chars(struct uart_port *);
-static void handle_intr(void *arg, uint32_t sio_ir);
-
-/*
- * port_is_active - determines if this port is currently active
- * @port: ptr to soft struct for this port
- * @uart_port: uart port to test for
- */
-static inline int port_is_active(struct ioc4_port *port,
- struct uart_port *uart_port)
-{
- if (port) {
- if ((port->ip_flags & PORT_ACTIVE)
- && (port->ip_port == uart_port))
- return 1;
- }
- return 0;
-}
-
-
-/**
- * write_ireg - write the interrupt regs
- * @ioc4_soft: ptr to soft struct for this port
- * @val: value to write
- * @which: which register
- * @type: which ireg set
- */
-static inline void
-write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
-{
- struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
-
- switch (type) {
- case IOC4_SIO_INTR_TYPE:
- switch (which) {
- case IOC4_W_IES:
- writel(val, &mem->sio_ies.raw);
- break;
-
- case IOC4_W_IEC:
- writel(val, &mem->sio_iec.raw);
- break;
- }
- break;
-
- case IOC4_OTHER_INTR_TYPE:
- switch (which) {
- case IOC4_W_IES:
- writel(val, &mem->other_ies.raw);
- break;
-
- case IOC4_W_IEC:
- writel(val, &mem->other_iec.raw);
- break;
- }
- break;
-
- default:
- break;
- }
- spin_unlock_irqrestore(&ioc4_soft->is_ir_lock, flags);
-}
-
-/**
- * set_baud - Baud rate setting code
- * @port: port to set
- * @baud: baud rate to use
- */
-static int set_baud(struct ioc4_port *port, int baud)
-{
- int actual_baud;
- int diff;
- int lcr;
- unsigned short divisor;
- struct ioc4_uartregs __iomem *uart;
-
- divisor = SER_DIVISOR(baud, port->ip_pci_bus_speed);
- if (!divisor)
- return 1;
- actual_baud = DIVISOR_TO_BAUD(divisor, port->ip_pci_bus_speed);
-
- diff = actual_baud - baud;
- if (diff < 0)
- diff = -diff;
-
- /* If we're within 1%, we've found a match */
- if (diff * 100 > actual_baud)
- return 1;
-
- uart = port->ip_uart_regs;
- lcr = readb(&uart->i4u_lcr);
- writeb(lcr | UART_LCR_DLAB, &uart->i4u_lcr);
- writeb((unsigned char)divisor, &uart->i4u_dll);
- writeb((unsigned char)(divisor >> 8), &uart->i4u_dlm);
- writeb(lcr, &uart->i4u_lcr);
- return 0;
-}
-
-
-/**
- * get_ioc4_port - given a uart port, return the control structure
- * @port: uart port
- * @set: set this port as current
- */
-static struct ioc4_port *get_ioc4_port(struct uart_port *the_port, int set)
-{
- struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
- struct ioc4_control *control = idd->idd_serial_data;
- struct ioc4_port *port;
- int port_num, port_type;
-
- if (control) {
- for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS;
- port_num++ ) {
- port = control->ic_port[port_num].icp_port;
- if (!port)
- continue;
- for (port_type = UART_PORT_MIN;
- port_type < UART_PORT_COUNT;
- port_type++) {
- if (the_port == port->ip_all_ports
- [port_type]) {
- /* set local copy */
- if (set) {
- port->ip_port = the_port;
- }
- return port;
- }
- }
- }
- }
- return NULL;
-}
-
-/* The IOC4 hardware provides no atomic way to determine if interrupts
- * are pending since two reads are required to do so. The handler must
- * read the SIO_IR and the SIO_IES, and take the logical and of the
- * two. When this value is zero, all interrupts have been serviced and
- * the handler may return.
- *
- * This has the unfortunate "hole" that, if some other CPU or
- * some other thread or some higher level interrupt manages to
- * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may
- * think we have observed SIO_IR&SIO_IE==0 when in fact this
- * condition never really occurred.
- *
- * To solve this, we use a simple spinlock that must be held
- * whenever modifying SIO_IE; holding this lock while observing
- * both SIO_IR and SIO_IE guarantees that we do not falsely
- * conclude that no enabled interrupts are pending.
- */
-
-static inline uint32_t
-pending_intrs(struct ioc4_soft *soft, int type)
-{
- struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
- unsigned long flag;
- uint32_t intrs = 0;
-
- BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
- || (type == IOC4_OTHER_INTR_TYPE)));
-
- spin_lock_irqsave(&soft->is_ir_lock, flag);
-
- switch (type) {
- case IOC4_SIO_INTR_TYPE:
- intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
- break;
-
- case IOC4_OTHER_INTR_TYPE:
- intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
-
- /* Don't process any ATA interrupte */
- intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
- break;
-
- default:
- break;
- }
- spin_unlock_irqrestore(&soft->is_ir_lock, flag);
- return intrs;
-}
-
-/**
- * port_init - Initialize the sio and ioc4 hardware for a given port
- * called per port from attach...
- * @port: port to initialize
- */
-static inline int port_init(struct ioc4_port *port)
-{
- uint32_t sio_cr;
- struct hooks *hooks = port->ip_hooks;
- struct ioc4_uartregs __iomem *uart;
-
- /* Idle the IOC4 serial interface */
- writel(IOC4_SSCR_RESET, &port->ip_serial_regs->sscr);
-
- /* Wait until any pending bus activity for this port has ceased */
- do
- sio_cr = readl(&port->ip_mem->sio_cr.raw);
- while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
-
- /* Finish reset sequence */
- writel(0, &port->ip_serial_regs->sscr);
-
- /* Once RESET is done, reload cached tx_prod and rx_cons values
- * and set rings to empty by making prod == cons
- */
- port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
- port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- /* Disable interrupts for this 16550 */
- uart = port->ip_uart_regs;
- writeb(0, &uart->i4u_lcr);
- writeb(0, &uart->i4u_ier);
-
- /* Set the default baud */
- set_baud(port, port->ip_baud);
-
- /* Set line control to 8 bits no parity */
- writeb(UART_LCR_WLEN8 | 0, &uart->i4u_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Enable the FIFOs */
- writeb(UART_FCR_ENABLE_FIFO, &uart->i4u_fcr);
- /* then reset 16550 FIFOs */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- &uart->i4u_fcr);
-
- /* Clear modem control register */
- writeb(0, &uart->i4u_mcr);
-
- /* Clear deltas in modem status register */
- readb(&uart->i4u_msr);
-
- /* Only do this once per port pair */
- if (port->ip_hooks == &hooks_array[0]
- || port->ip_hooks == &hooks_array[2]) {
- unsigned long ring_pci_addr;
- uint32_t __iomem *sbbr_l;
- uint32_t __iomem *sbbr_h;
-
- if (port->ip_hooks == &hooks_array[0]) {
- sbbr_l = &port->ip_serial->sbbr01_l;
- sbbr_h = &port->ip_serial->sbbr01_h;
- } else {
- sbbr_l = &port->ip_serial->sbbr23_l;
- sbbr_h = &port->ip_serial->sbbr23_h;
- }
-
- ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
- DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
- __func__, ring_pci_addr));
-
- writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
- writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
- }
-
- /* Set the receive timeout value to 10 msec */
- writel(IOC4_SRTR_HZ / 100, &port->ip_serial_regs->srtr);
-
- /* Set rx threshold, enable DMA */
- /* Set high water mark at 3/4 of full ring */
- port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Disable and clear all serial related interrupt bits */
- write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
- IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
- port->ip_ienb &= ~hooks->intr_clear;
- writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
- return 0;
-}
-
-/**
- * handle_dma_error_intr - service any pending DMA error interrupts for the
- * given port - 2nd level called via sd_intr
- * @arg: handler arg
- * @other_ir: ioc4regs
- */
-static void handle_dma_error_intr(void *arg, uint32_t other_ir)
-{
- struct ioc4_port *port = (struct ioc4_port *)arg;
- struct hooks *hooks = port->ip_hooks;
- unsigned long flags;
-
- spin_lock_irqsave(&port->ip_lock, flags);
-
- /* ACK the interrupt */
- writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
-
- if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
- printk(KERN_ERR
- "PCI error address is 0x%llx, "
- "master is serial port %c %s\n",
- (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
- << 32)
- | readl(&port->ip_mem->pci_err_addr_l.raw))
- & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
- ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
- IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
- (readl(&port->ip_mem->pci_err_addr_l.raw)
- & IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
- ? "RX" : "TX");
-
- if (readl(&port->ip_mem->pci_err_addr_l.raw)
- & IOC4_PCI_ERR_ADDR_MUL_ERR) {
- printk(KERN_ERR
- "Multiple errors occurred\n");
- }
- }
- spin_unlock_irqrestore(&port->ip_lock, flags);
-
- /* Re-enable DMA error interrupts */
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, IOC4_W_IES,
- IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * intr_connect - interrupt connect function
- * @soft: soft struct for this card
- * @type: interrupt type
- * @intrbits: bit pattern to set
- * @intr: handler function
- * @info: handler arg
- */
-static void
-intr_connect(struct ioc4_soft *soft, int type,
- uint32_t intrbits, ioc4_intr_func_f * intr, void *info)
-{
- int i;
- struct ioc4_intr_info *intr_ptr;
-
- BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
- || (type == IOC4_OTHER_INTR_TYPE)));
-
- i = atomic_inc_return(&soft-> is_intr_type[type].is_num_intrs) - 1;
- BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0)));
-
- /* Save off the lower level interrupt handler */
- intr_ptr = &soft->is_intr_type[type].is_intr_info[i];
- intr_ptr->sd_bits = intrbits;
- intr_ptr->sd_intr = intr;
- intr_ptr->sd_info = info;
-}
-
-/**
- * ioc4_intr - Top level IOC4 interrupt handler.
- * @irq: irq value
- * @arg: handler arg
- */
-
-static irqreturn_t ioc4_intr(int irq, void *arg)
-{
- struct ioc4_soft *soft;
- uint32_t this_ir, this_mir;
- int xx, num_intrs = 0;
- int intr_type;
- int handled = 0;
- struct ioc4_intr_info *intr_info;
-
- soft = arg;
- for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) {
- num_intrs = (int)atomic_read(
- &soft->is_intr_type[intr_type].is_num_intrs);
-
- this_mir = this_ir = pending_intrs(soft, intr_type);
-
- /* Farm out the interrupt to the various drivers depending on
- * which interrupt bits are set.
- */
- for (xx = 0; xx < num_intrs; xx++) {
- intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx];
- this_mir = this_ir & intr_info->sd_bits;
- if (this_mir) {
- /* Disable owned interrupts, call handler */
- handled++;
- write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC,
- intr_type);
- intr_info->sd_intr(intr_info->sd_info, this_mir);
- this_ir &= ~this_mir;
- }
- }
- }
-#ifdef DEBUG_INTERRUPTS
- {
- struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
- unsigned long flag;
-
- spin_lock_irqsave(&soft->is_ir_lock, flag);
- printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
- "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
- __func__, __LINE__,
- (void *)mem, readl(&mem->sio_ir.raw),
- readl(&mem->sio_ies.raw),
- readl(&mem->other_ir.raw),
- readl(&mem->other_ies.raw),
- IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
- spin_unlock_irqrestore(&soft->is_ir_lock, flag);
- }
-#endif
- return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/**
- * ioc4_attach_local - Device initialization.
- * Called at *_attach() time for each
- * IOC4 with serial ports in the system.
- * @idd: Master module data for this IOC4
- */
-static inline int ioc4_attach_local(struct ioc4_driver_data *idd)
-{
- struct ioc4_port *port;
- struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
- int port_number;
- uint16_t ioc4_revid_min = 62;
- uint16_t ioc4_revid;
- struct pci_dev *pdev = idd->idd_pdev;
- struct ioc4_control* control = idd->idd_serial_data;
- struct ioc4_soft *soft = control->ic_soft;
- void __iomem *ioc4_misc = idd->idd_misc_regs;
- void __iomem *ioc4_serial = soft->is_ioc4_serial_addr;
-
- /* IOC4 firmware must be at least rev 62 */
- pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
-
- printk(KERN_INFO "IOC4 firmware revision %d\n", ioc4_revid);
- if (ioc4_revid < ioc4_revid_min) {
- printk(KERN_WARNING
- "IOC4 serial not supported on firmware rev %d, "
- "please upgrade to rev %d or higher\n",
- ioc4_revid, ioc4_revid_min);
- return -EPERM;
- }
- BUG_ON(ioc4_misc == NULL);
- BUG_ON(ioc4_serial == NULL);
-
- /* Create port structures for each port */
- for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
- port_number++) {
- port = kzalloc(sizeof(struct ioc4_port), GFP_KERNEL);
- if (!port) {
- printk(KERN_WARNING
- "IOC4 serial memory not available for port\n");
- goto free;
- }
- spin_lock_init(&port->ip_lock);
-
- /* we need to remember the previous ones, to point back to
- * them farther down - setting up the ring buffers.
- */
- ports[port_number] = port;
-
- /* Allocate buffers and jumpstart the hardware. */
- control->ic_port[port_number].icp_port = port;
- port->ip_ioc4_soft = soft;
- port->ip_pdev = pdev;
- port->ip_ienb = 0;
- /* Use baud rate calculations based on detected PCI
- * bus speed. Simply test whether the PCI clock is
- * running closer to 66MHz or 33MHz.
- */
- if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) {
- port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66;
- } else {
- port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33;
- }
- port->ip_baud = 9600;
- port->ip_control = control;
- port->ip_mem = ioc4_misc;
- port->ip_serial = ioc4_serial;
-
- /* point to the right hook */
- port->ip_hooks = &hooks_array[port_number];
-
- /* Get direct hooks to the serial regs and uart regs
- * for this port
- */
- switch (port_number) {
- case 0:
- port->ip_serial_regs = &(port->ip_serial->port_0);
- port->ip_uart_regs = &(port->ip_serial->uart_0);
- break;
- case 1:
- port->ip_serial_regs = &(port->ip_serial->port_1);
- port->ip_uart_regs = &(port->ip_serial->uart_1);
- break;
- case 2:
- port->ip_serial_regs = &(port->ip_serial->port_2);
- port->ip_uart_regs = &(port->ip_serial->uart_2);
- break;
- default:
- case 3:
- port->ip_serial_regs = &(port->ip_serial->port_3);
- port->ip_uart_regs = &(port->ip_serial->uart_3);
- break;
- }
-
- /* ring buffers are 1 to a pair of ports */
- if (port_number && (port_number & 1)) {
- /* odd use the evens buffer */
- port->ip_dma_ringbuf =
- ports[port_number - 1]->ip_dma_ringbuf;
- port->ip_cpu_ringbuf =
- ports[port_number - 1]->ip_cpu_ringbuf;
- port->ip_inring = RING(port, RX_1_OR_3);
- port->ip_outring = RING(port, TX_1_OR_3);
-
- } else {
- if (port->ip_dma_ringbuf == 0) {
- port->ip_cpu_ringbuf = pci_alloc_consistent
- (pdev, TOTAL_RING_BUF_SIZE,
- &port->ip_dma_ringbuf);
-
- }
- BUG_ON(!((((int64_t)port->ip_dma_ringbuf) &
- (TOTAL_RING_BUF_SIZE - 1)) == 0));
- DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf));
- port->ip_inring = RING(port, RX_0_OR_2);
- port->ip_outring = RING(port, TX_0_OR_2);
- }
- DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
- __func__,
- port_number, (void *)port, (void *)control));
- DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* Initialize the hardware for IOC4 */
- port_init(port);
-
- DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
- "outring 0x%p\n",
- __func__,
- port_number, (void *)port,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
-
- /* Attach interrupt handlers */
- intr_connect(soft, IOC4_SIO_INTR_TYPE,
- GET_SIO_IR(port_number),
- handle_intr, port);
-
- intr_connect(soft, IOC4_OTHER_INTR_TYPE,
- GET_OTHER_IR(port_number),
- handle_dma_error_intr, port);
- }
- return 0;
-
-free:
- while (port_number)
- kfree(ports[--port_number]);
- return -ENOMEM;
-}
-
-/**
- * enable_intrs - enable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void enable_intrs(struct ioc4_port *port, uint32_t mask)
-{
- struct hooks *hooks = port->ip_hooks;
-
- if ((port->ip_ienb & mask) != mask) {
- write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IES,
- IOC4_SIO_INTR_TYPE);
- port->ip_ienb |= mask;
- }
-
- if (port->ip_ienb)
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
- IOC4_W_IES, IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * local_open - local open a port
- * @port: port to open
- */
-static inline int local_open(struct ioc4_port *port)
-{
- int spiniter = 0;
-
- port->ip_flags = PORT_ACTIVE;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while((readl(&port->ip_serial_regs-> sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER) {
- port->ip_flags = PORT_INACTIVE;
- return -1;
- }
- }
- }
-
- /* Reset the input fifo. If the uart received chars while the port
- * was closed and DMA is not enabled, the uart may have a bunch of
- * chars hanging around in its rx fifo which will not be discarded
- * by rclr in the upper layer. We must get rid of them here.
- */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
- &port->ip_uart_regs->i4u_fcr);
-
- writeb(UART_LCR_WLEN8, &port->ip_uart_regs->i4u_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Re-enable DMA, set default threshold to intr whenever there is
- * data available.
- */
- port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
- port->ip_sscr |= 1; /* default threshold */
-
- /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
- * flag if it was set above
- */
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- port->ip_tx_lowat = 1;
- return 0;
-}
-
-/**
- * set_rx_timeout - Set rx timeout and threshold values.
- * @port: port to use
- * @timeout: timeout value in ticks
- */
-static inline int set_rx_timeout(struct ioc4_port *port, int timeout)
-{
- int threshold;
-
- port->ip_rx_timeout = timeout;
-
- /* Timeout is in ticks. Let's figure out how many chars we
- * can receive at the current baud rate in that interval
- * and set the rx threshold to that amount. There are 4 chars
- * per ring entry, so we'll divide the number of chars that will
- * arrive in timeout by 4.
- * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
- */
- threshold = timeout * port->ip_baud / 4000;
- if (threshold == 0)
- threshold = 1; /* otherwise we'll intr all the time! */
-
- if ((unsigned)threshold > (unsigned)IOC4_SSCR_RX_THRESHOLD)
- return 1;
-
- port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
- port->ip_sscr |= threshold;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Now set the rx timeout to the given value
- * again timeout * IOC4_SRTR_HZ / HZ
- */
- timeout = timeout * IOC4_SRTR_HZ / 100;
- if (timeout > IOC4_SRTR_CNT)
- timeout = IOC4_SRTR_CNT;
-
- writel(timeout, &port->ip_serial_regs->srtr);
- return 0;
-}
-
-/**
- * config_port - config the hardware
- * @port: port to config
- * @baud: baud rate for the port
- * @byte_size: data size
- * @stop_bits: number of stop bits
- * @parenb: parity enable ?
- * @parodd: odd parity ?
- */
-static inline int
-config_port(struct ioc4_port *port,
- int baud, int byte_size, int stop_bits, int parenb, int parodd)
-{
- char lcr, sizebits;
- int spiniter = 0;
-
- DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
- __func__, baud, byte_size, stop_bits, parenb, parodd));
-
- if (set_baud(port, baud))
- return 1;
-
- switch (byte_size) {
- case 5:
- sizebits = UART_LCR_WLEN5;
- break;
- case 6:
- sizebits = UART_LCR_WLEN6;
- break;
- case 7:
- sizebits = UART_LCR_WLEN7;
- break;
- case 8:
- sizebits = UART_LCR_WLEN8;
- break;
- default:
- return 1;
- }
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while((readl(&port->ip_serial_regs->sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
-
- /* Clear relevant fields in lcr */
- lcr = readb(&port->ip_uart_regs->i4u_lcr);
- lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
- UART_LCR_PARITY | LCR_MASK_STOP_BITS);
-
- /* Set byte size in lcr */
- lcr |= sizebits;
-
- /* Set parity */
- if (parenb) {
- lcr |= UART_LCR_PARITY;
- if (!parodd)
- lcr |= UART_LCR_EPAR;
- }
-
- /* Set stop bits */
- if (stop_bits)
- lcr |= UART_LCR_STOP /* 2 stop bits */ ;
-
- writeb(lcr, &port->ip_uart_regs->i4u_lcr);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- port->ip_baud = baud;
-
- /* When we get within this number of ring entries of filling the
- * entire ring on tx, place an EXPLICIT intr to generate a lowat
- * notification when output has drained.
- */
- port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
- if (port->ip_tx_lowat == 0)
- port->ip_tx_lowat = 1;
-
- set_rx_timeout(port, 2);
-
- return 0;
-}
-
-/**
- * do_write - Write bytes to the port. Returns the number of bytes
- * actually written. Called from transmit_chars
- * @port: port to use
- * @buf: the stuff to write
- * @len: how many bytes in 'buf'
- */
-static inline int do_write(struct ioc4_port *port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total = 0;
- struct ring *outring;
- struct ring_entry *entry;
- struct hooks *hooks = port->ip_hooks;
-
- BUG_ON(!(len >= 0));
-
- prod_ptr = port->ip_tx_prod;
- cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- outring = port->ip_outring;
-
- /* Maintain a 1-entry red-zone. The ring buffer is full when
- * (cons - prod) % ring_size is 1. Rather than do this subtraction
- * in the body of the loop, I'll do it now.
- */
- cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
-
- /* Stuff the bytes into the output */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- int xx;
-
- /* Get 4 bytes (one ring entry) at a time */
- entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
-
- /* Invalidate all entries */
- entry->ring_allsc = 0;
-
- /* Copy in some bytes */
- for (xx = 0; (xx < 4) && (len > 0); xx++) {
- entry->ring_data[xx] = *buf++;
- entry->ring_sc[xx] = IOC4_TXCB_VALID;
- len--;
- total++;
- }
-
- /* If we are within some small threshold of filling up the
- * entire ring buffer, we must place an EXPLICIT intr here
- * to generate a lowat interrupt in case we subsequently
- * really do fill up the ring and the caller goes to sleep.
- * No need to place more than one though.
- */
- if (!(port->ip_flags & LOWAT_WRITTEN) &&
- ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
- <= port->ip_tx_lowat
- * (int)sizeof(struct ring_entry)) {
- port->ip_flags |= LOWAT_WRITTEN;
- entry->ring_sc[0] |= IOC4_TXCB_INT_WHEN_DONE;
- }
-
- /* Go on to next entry */
- prod_ptr += sizeof(struct ring_entry);
- prod_ptr &= PROD_CONS_MASK;
- }
-
- /* If we sent something, start DMA if necessary */
- if (total > 0 && !(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
-
- /* Store the new producer pointer. If tx is disabled, we stuff the
- * data into the ring buffer, but we don't actually start tx.
- */
- if (!uart_tx_stopped(port->ip_port)) {
- writel(prod_ptr, &port->ip_serial_regs->stpir);
-
- /* If we are now transmitting, enable tx_mt interrupt so we
- * can disable DMA if necessary when the tx finishes.
- */
- if (total > 0)
- enable_intrs(port, hooks->intr_tx_mt);
- }
- port->ip_tx_prod = prod_ptr;
- return total;
-}
-
-/**
- * disable_intrs - disable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void disable_intrs(struct ioc4_port *port, uint32_t mask)
-{
- struct hooks *hooks = port->ip_hooks;
-
- if (port->ip_ienb & mask) {
- write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IEC,
- IOC4_SIO_INTR_TYPE);
- port->ip_ienb &= ~mask;
- }
-
- if (!port->ip_ienb)
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
- IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * set_notification - Modify event notification
- * @port: port to use
- * @mask: events mask
- * @set_on: set ?
- */
-static int set_notification(struct ioc4_port *port, int mask, int set_on)
-{
- struct hooks *hooks = port->ip_hooks;
- uint32_t intrbits, sscrbits;
-
- BUG_ON(!mask);
-
- intrbits = sscrbits = 0;
-
- if (mask & N_DATA_READY)
- intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
- if (mask & N_OUTPUT_LOWAT)
- intrbits |= hooks->intr_tx_explicit;
- if (mask & N_DDCD) {
- intrbits |= hooks->intr_delta_dcd;
- sscrbits |= IOC4_SSCR_RX_RING_DCD;
- }
- if (mask & N_DCTS)
- intrbits |= hooks->intr_delta_cts;
-
- if (set_on) {
- enable_intrs(port, intrbits);
- port->ip_notify |= mask;
- port->ip_sscr |= sscrbits;
- } else {
- disable_intrs(port, intrbits);
- port->ip_notify &= ~mask;
- port->ip_sscr &= ~sscrbits;
- }
-
- /* We require DMA if either DATA_READY or DDCD notification is
- * currently requested. If neither of these is requested and
- * there is currently no tx in progress, DMA may be disabled.
- */
- if (port->ip_notify & (N_DATA_READY | N_DDCD))
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- else if (!(port->ip_ienb & hooks->intr_tx_mt))
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- return 0;
-}
-
-/**
- * set_mcr - set the master control reg
- * @the_port: port to use
- * @mask1: mcr mask
- * @mask2: shadow mask
- */
-static inline int set_mcr(struct uart_port *the_port,
- int mask1, int mask2)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- uint32_t shadow;
- int spiniter = 0;
- char mcr;
-
- if (!port)
- return -1;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
- shadow = readl(&port->ip_serial_regs->shadow);
- mcr = (shadow & 0xff000000) >> 24;
-
- /* Set new value */
- mcr |= mask1;
- shadow |= mask2;
-
- writeb(mcr, &port->ip_uart_regs->i4u_mcr);
- writel(shadow, &port->ip_serial_regs->shadow);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- return 0;
-}
-
-/**
- * ioc4_set_proto - set the protocol for the port
- * @port: port to use
- * @proto: protocol to use
- */
-static int ioc4_set_proto(struct ioc4_port *port, int proto)
-{
- struct hooks *hooks = port->ip_hooks;
-
- switch (proto) {
- case PROTO_RS232:
- /* Clear the appropriate GIO pin */
- writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
- break;
-
- case PROTO_RS422:
- /* Set the appropriate GIO pin */
- writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
- break;
-
- default:
- return 1;
- }
- return 0;
-}
-
-/**
- * transmit_chars - upper level write, called with ip_lock
- * @the_port: port to write
- */
-static void transmit_chars(struct uart_port *the_port)
-{
- int xmit_count, tail, head;
- int result;
- char *start;
- struct tty_struct *tty;
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- struct uart_state *state;
-
- if (!the_port)
- return;
- if (!port)
- return;
-
- state = the_port->state;
- tty = state->port.tty;
-
- if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) {
- /* Nothing to do or hw stopped */
- set_notification(port, N_ALL_OUTPUT, 0);
- return;
- }
-
- head = state->xmit.head;
- tail = state->xmit.tail;
- start = (char *)&state->xmit.buf[tail];
-
- /* write out all the data or until the end of the buffer */
- xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
- if (xmit_count > 0) {
- result = do_write(port, start, xmit_count);
- if (result > 0) {
- /* booking */
- xmit_count -= result;
- the_port->icount.tx += result;
- /* advance the pointers */
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- state->xmit.tail = tail;
- start = (char *)&state->xmit.buf[tail];
- }
- }
- if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS)
- uart_write_wakeup(the_port);
-
- if (uart_circ_empty(&state->xmit)) {
- set_notification(port, N_OUTPUT_LOWAT, 0);
- } else {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- }
-}
-
-/**
- * ioc4_change_speed - change the speed of the port
- * @the_port: port to change
- * @new_termios: new termios settings
- * @old_termios: old termios settings
- */
-static void
-ioc4_change_speed(struct uart_port *the_port,
- struct ktermios *new_termios, struct ktermios *old_termios)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- int baud, bits;
- unsigned cflag, iflag;
- int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
- struct uart_state *state = the_port->state;
-
- cflag = new_termios->c_cflag;
- iflag = new_termios->c_iflag;
-
- switch (cflag & CSIZE) {
- case CS5:
- new_data = 5;
- bits = 7;
- break;
- case CS6:
- new_data = 6;
- bits = 8;
- break;
- case CS7:
- new_data = 7;
- bits = 9;
- break;
- case CS8:
- new_data = 8;
- bits = 10;
- break;
- default:
- /* cuz we always need a default ... */
- new_data = 5;
- bits = 7;
- break;
- }
- if (cflag & CSTOPB) {
- bits++;
- new_stop = 1;
- }
- if (cflag & PARENB) {
- bits++;
- new_parity_enable = 1;
- if (cflag & PARODD)
- new_parity = 1;
- }
- baud = uart_get_baud_rate(the_port, new_termios, old_termios,
- MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
- DPRINT_CONFIG(("%s: returned baud %d\n", __func__, baud));
-
- /* default is 9600 */
- if (!baud)
- baud = 9600;
-
- if (!the_port->fifosize)
- the_port->fifosize = IOC4_FIFO_CHARS;
- the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
- the_port->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- the_port->ignore_status_mask = N_ALL_INPUT;
-
- state->port.low_latency = 1;
-
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~(N_PARITY_ERROR
- | N_FRAMING_ERROR);
- if (iflag & IGNBRK) {
- the_port->ignore_status_mask &= ~N_BREAK;
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
- }
- if (!(cflag & CREAD)) {
- /* ignore everything */
- the_port->ignore_status_mask &= ~N_DATA_READY;
- }
-
- if (cflag & CRTSCTS) {
- port->ip_sscr |= IOC4_SSCR_HFC_EN;
- }
- else {
- port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
- }
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Set the configuration and proper notification call */
- DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
- "config_port(baud %d data %d stop %d p enable %d parity %d),"
- " notification 0x%x\n",
- __func__, (void *)port, cflag, baud, new_data, new_stop,
- new_parity_enable, new_parity, the_port->ignore_status_mask));
-
- if ((config_port(port, baud, /* baud */
- new_data, /* byte size */
- new_stop, /* stop bits */
- new_parity_enable, /* set parity */
- new_parity)) >= 0) { /* parity 1==odd */
- set_notification(port, the_port->ignore_status_mask, 1);
- }
-}
-
-/**
- * ic4_startup_local - Start up the serial port - returns >= 0 if no errors
- * @the_port: Port to operate on
- */
-static inline int ic4_startup_local(struct uart_port *the_port)
-{
- struct ioc4_port *port;
- struct uart_state *state;
-
- if (!the_port)
- return -1;
-
- port = get_ioc4_port(the_port, 0);
- if (!port)
- return -1;
-
- state = the_port->state;
-
- local_open(port);
-
- /* set the protocol - mapbase has the port type */
- ioc4_set_proto(port, the_port->mapbase);
-
- /* set the speed of the serial port */
- ioc4_change_speed(the_port, &state->port.tty->termios,
- (struct ktermios *)0);
-
- return 0;
-}
-
-/*
- * ioc4_cb_output_lowat - called when the output low water mark is hit
- * @the_port: port to output
- */
-static void ioc4_cb_output_lowat(struct uart_port *the_port)
-{
- unsigned long pflags;
-
- /* ip_lock is set on the call here */
- if (the_port) {
- spin_lock_irqsave(&the_port->lock, pflags);
- transmit_chars(the_port);
- spin_unlock_irqrestore(&the_port->lock, pflags);
- }
-}
-
-/**
- * handle_intr - service any interrupts for the given port - 2nd level
- * called via sd_intr
- * @arg: handler arg
- * @sio_ir: ioc4regs
- */
-static void handle_intr(void *arg, uint32_t sio_ir)
-{
- struct ioc4_port *port = (struct ioc4_port *)arg;
- struct hooks *hooks = port->ip_hooks;
- unsigned int rx_high_rd_aborted = 0;
- unsigned long flags;
- struct uart_port *the_port;
- int loop_counter;
-
- /* Possible race condition here: The tx_mt interrupt bit may be
- * cleared without the intervention of the interrupt handler,
- * e.g. by a write. If the top level interrupt handler reads a
- * tx_mt, then some other processor does a write, starting up
- * output, then we come in here, see the tx_mt and stop DMA, the
- * output started by the other processor will hang. Thus we can
- * only rely on tx_mt being legitimate if it is read while the
- * port lock is held. Therefore this bit must be ignored in the
- * passed in interrupt mask which was read by the top level
- * interrupt handler since the port lock was not held at the time
- * it was read. We can only rely on this bit being accurate if it
- * is read while the port lock is held. So we'll clear it for now,
- * and reload it later once we have the port lock.
- */
- sio_ir &= ~(hooks->intr_tx_mt);
-
- spin_lock_irqsave(&port->ip_lock, flags);
-
- loop_counter = MAXITER; /* to avoid hangs */
-
- do {
- uint32_t shadow;
-
- if ( loop_counter-- <= 0 ) {
- printk(KERN_WARNING "IOC4 serial: "
- "possible hang condition/"
- "port stuck on interrupt.\n");
- break;
- }
-
- /* Handle a DCD change */
- if (sio_ir & hooks->intr_delta_dcd) {
- /* ACK the interrupt */
- writel(hooks->intr_delta_dcd,
- &port->ip_mem->sio_ir.raw);
-
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DDCD)
- && (shadow & IOC4_SHADOW_DCD)
- && (port->ip_port)) {
- the_port = port->ip_port;
- the_port->icount.dcd = 1;
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- } else if ((port->ip_notify & N_DDCD)
- && !(shadow & IOC4_SHADOW_DCD)) {
- /* Flag delta DCD/no DCD */
- port->ip_flags |= DCD_ON;
- }
- }
-
- /* Handle a CTS change */
- if (sio_ir & hooks->intr_delta_cts) {
- /* ACK the interrupt */
- writel(hooks->intr_delta_cts,
- &port->ip_mem->sio_ir.raw);
-
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DCTS)
- && (port->ip_port)) {
- the_port = port->ip_port;
- the_port->icount.cts =
- (shadow & IOC4_SHADOW_CTS) ? 1 : 0;
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- }
- }
-
- /* rx timeout interrupt. Must be some data available. Put this
- * before the check for rx_high since servicing this condition
- * may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_rx_timer) {
- /* ACK the interrupt */
- writel(hooks->intr_rx_timer,
- &port->ip_mem->sio_ir.raw);
-
- if ((port->ip_notify & N_DATA_READY)
- && (port->ip_port)) {
- /* ip_lock is set on call here */
- receive_chars(port->ip_port);
- }
- }
-
- /* rx high interrupt. Must be after rx_timer. */
- else if (sio_ir & hooks->intr_rx_high) {
- /* Data available, notify upper layer */
- if ((port->ip_notify & N_DATA_READY)
- && port->ip_port) {
- /* ip_lock is set on call here */
- receive_chars(port->ip_port);
- }
-
- /* We can't ACK this interrupt. If receive_chars didn't
- * cause the condition to clear, we'll have to disable
- * the interrupt until the data is drained.
- * If the read was aborted, don't disable the interrupt
- * as this may cause us to hang indefinitely. An
- * aborted read generally means that this interrupt
- * hasn't been delivered to the cpu yet anyway, even
- * though we see it as asserted when we read the sio_ir.
- */
- if ((sio_ir = PENDING(port)) & hooks->intr_rx_high) {
- if ((port->ip_flags & READ_ABORTED) == 0) {
- port->ip_ienb &= ~hooks->intr_rx_high;
- port->ip_flags |= INPUT_HIGH;
- } else {
- rx_high_rd_aborted++;
- }
- }
- }
-
- /* We got a low water interrupt: notify upper layer to
- * send more data. Must come before tx_mt since servicing
- * this condition may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_tx_explicit) {
- port->ip_flags &= ~LOWAT_WRITTEN;
-
- /* ACK the interrupt */
- writel(hooks->intr_tx_explicit,
- &port->ip_mem->sio_ir.raw);
-
- if (port->ip_notify & N_OUTPUT_LOWAT)
- ioc4_cb_output_lowat(port->ip_port);
- }
-
- /* Handle tx_mt. Must come after tx_explicit. */
- else if (sio_ir & hooks->intr_tx_mt) {
- /* If we are expecting a lowat notification
- * and we get to this point it probably means that for
- * some reason the tx_explicit didn't work as expected
- * (that can legitimately happen if the output buffer is
- * filled up in just the right way).
- * So send the notification now.
- */
- if (port->ip_notify & N_OUTPUT_LOWAT) {
- ioc4_cb_output_lowat(port->ip_port);
-
- /* We need to reload the sio_ir since the lowat
- * call may have caused another write to occur,
- * clearing the tx_mt condition.
- */
- sio_ir = PENDING(port);
- }
-
- /* If the tx_mt condition still persists even after the
- * lowat call, we've got some work to do.
- */
- if (sio_ir & hooks->intr_tx_mt) {
-
- /* If we are not currently expecting DMA input,
- * and the transmitter has just gone idle,
- * there is no longer any reason for DMA, so
- * disable it.
- */
- if (!(port->ip_notify
- & (N_DATA_READY | N_DDCD))) {
- BUG_ON(!(port->ip_sscr
- & IOC4_SSCR_DMA_EN));
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr,
- &port->ip_serial_regs->sscr);
- }
-
- /* Prevent infinite tx_mt interrupt */
- port->ip_ienb &= ~hooks->intr_tx_mt;
- }
- }
- sio_ir = PENDING(port);
-
- /* if the read was aborted and only hooks->intr_rx_high,
- * clear hooks->intr_rx_high, so we do not loop forever.
- */
-
- if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
- sio_ir &= ~hooks->intr_rx_high;
- }
- } while (sio_ir & hooks->intr_all);
-
- spin_unlock_irqrestore(&port->ip_lock, flags);
-
- /* Re-enable interrupts before returning from interrupt handler.
- * Getting interrupted here is okay. It'll just v() our semaphore, and
- * we'll come through the loop again.
- */
-
- write_ireg(port->ip_ioc4_soft, port->ip_ienb, IOC4_W_IES,
- IOC4_SIO_INTR_TYPE);
-}
-
-/*
- * ioc4_cb_post_ncs - called for some basic errors
- * @port: port to use
- * @ncs: event
- */
-static void ioc4_cb_post_ncs(struct uart_port *the_port, int ncs)
-{
- struct uart_icount *icount;
-
- icount = &the_port->icount;
-
- if (ncs & NCS_BREAK)
- icount->brk++;
- if (ncs & NCS_FRAMING)
- icount->frame++;
- if (ncs & NCS_OVERRUN)
- icount->overrun++;
- if (ncs & NCS_PARITY)
- icount->parity++;
-}
-
-/**
- * do_read - Read in bytes from the port. Return the number of bytes
- * actually read.
- * @the_port: port to use
- * @buf: place to put the stuff we read
- * @len: how big 'buf' is
- */
-
-static inline int do_read(struct uart_port *the_port, unsigned char *buf,
- int len)
-{
- int prod_ptr, cons_ptr, total;
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- struct ring *inring;
- struct ring_entry *entry;
- struct hooks *hooks;
- int byte_num;
- char *sc;
- int loop_counter;
-
- BUG_ON(!(len >= 0));
- BUG_ON(!port);
- hooks = port->ip_hooks;
-
- /* There is a nasty timing issue in the IOC4. When the rx_timer
- * expires or the rx_high condition arises, we take an interrupt.
- * At some point while servicing the interrupt, we read bytes from
- * the ring buffer and re-arm the rx_timer. However the rx_timer is
- * not started until the first byte is received *after* it is armed,
- * and any bytes pending in the rx construction buffers are not drained
- * to memory until either there are 4 bytes available or the rx_timer
- * expires. This leads to a potential situation where data is left
- * in the construction buffers forever - 1 to 3 bytes were received
- * after the interrupt was generated but before the rx_timer was
- * re-armed. At that point as long as no subsequent bytes are received
- * the timer will never be started and the bytes will remain in the
- * construction buffer forever. The solution is to execute a DRAIN
- * command after rearming the timer. This way any bytes received before
- * the DRAIN will be drained to memory, and any bytes received after
- * the DRAIN will start the TIMER and be drained when it expires.
- * Luckily, this only needs to be done when the DMA buffer is empty
- * since there is no requirement that this function return all
- * available data as long as it returns some.
- */
- /* Re-arm the timer */
- writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- cons_ptr = port->ip_rx_cons;
-
- if (prod_ptr == cons_ptr) {
- int reset_dma = 0;
-
- /* Input buffer appears empty, do a flush. */
-
- /* DMA must be enabled for this to work. */
- if (!(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- reset_dma = 1;
- }
-
- /* Potential race condition: we must reload the srpir after
- * issuing the drain command, otherwise we could think the rx
- * buffer is empty, then take a very long interrupt, and when
- * we come back it's full and we wait forever for the drain to
- * complete.
- */
- writel(port->ip_sscr | IOC4_SSCR_RX_DRAIN,
- &port->ip_serial_regs->sscr);
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
-
- /* We must not wait for the DRAIN to complete unless there are
- * at least 8 bytes (2 ring entries) available to receive the
- * data otherwise the DRAIN will never complete and we'll
- * deadlock here.
- * In fact, to make things easier, I'll just ignore the flush if
- * there is any data at all now available.
- */
- if (prod_ptr == cons_ptr) {
- loop_counter = 0;
- while (readl(&port->ip_serial_regs->sscr) &
- IOC4_SSCR_RX_DRAIN) {
- loop_counter++;
- if (loop_counter > MAXITER)
- return -1;
- }
-
- /* SIGH. We have to reload the prod_ptr *again* since
- * the drain may have caused it to change
- */
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
- }
- if (reset_dma) {
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- }
- inring = port->ip_inring;
- port->ip_flags &= ~READ_ABORTED;
-
- total = 0;
- loop_counter = 0xfffff; /* to avoid hangs */
-
- /* Grab bytes from the hardware */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- entry = (struct ring_entry *)((caddr_t)inring + cons_ptr);
-
- if ( loop_counter-- <= 0 ) {
- printk(KERN_WARNING "IOC4 serial: "
- "possible hang condition/"
- "port stuck on read.\n");
- break;
- }
-
- /* According to the producer pointer, this ring entry
- * must contain some data. But if the PIO happened faster
- * than the DMA, the data may not be available yet, so let's
- * wait until it arrives.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- /* Indicate the read is aborted so we don't disable
- * the interrupt thinking that the consumer is
- * congested.
- */
- port->ip_flags |= READ_ABORTED;
- len = 0;
- break;
- }
-
- /* Load the bytes/status out of the ring entry */
- for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
- sc = &(entry->ring_sc[byte_num]);
-
- /* Check for change in modem state or overrun */
- if ((*sc & IOC4_RXSB_MODEM_VALID)
- && (port->ip_notify & N_DDCD)) {
- /* Notify upper layer if DCD dropped */
-
- if ((port->ip_flags & DCD_ON)
- && !(*sc & IOC4_RXSB_DCD)) {
-
- /* If we have already copied some data,
- * return it. We'll pick up the carrier
- * drop on the next pass. That way we
- * don't throw away the data that has
- * already been copied back to
- * the caller's buffer.
- */
- if (total > 0) {
- len = 0;
- break;
- }
- port->ip_flags &= ~DCD_ON;
-
- /* Turn off this notification so the
- * carrier drop protocol won't see it
- * again when it does a read.
- */
- *sc &= ~IOC4_RXSB_MODEM_VALID;
-
- /* To keep things consistent, we need
- * to update the consumer pointer so
- * the next reader won't come in and
- * try to read the same ring entries
- * again. This must be done here before
- * the dcd change.
- */
-
- if ((entry->ring_allsc & RING_ANY_VALID)
- == 0) {
- cons_ptr += (int)sizeof
- (struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- writel(cons_ptr,
- &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* Notify upper layer of carrier drop */
- if ((port->ip_notify & N_DDCD)
- && port->ip_port) {
- the_port->icount.dcd = 0;
- wake_up_interruptible
- (&the_port->state->
- port.delta_msr_wait);
- }
-
- /* If we had any data to return, we
- * would have returned it above.
- */
- return 0;
- }
- }
- if (*sc & IOC4_RXSB_MODEM_VALID) {
- /* Notify that an input overrun occurred */
- if ((*sc & IOC4_RXSB_OVERRUN)
- && (port->ip_notify & N_OVERRUN_ERROR)) {
- ioc4_cb_post_ncs(the_port, NCS_OVERRUN);
- }
- /* Don't look at this byte again */
- *sc &= ~IOC4_RXSB_MODEM_VALID;
- }
-
- /* Check for valid data or RX errors */
- if ((*sc & IOC4_RXSB_DATA_VALID) &&
- ((*sc & (IOC4_RXSB_PAR_ERR
- | IOC4_RXSB_FRAME_ERR
- | IOC4_RXSB_BREAK))
- && (port->ip_notify & (N_PARITY_ERROR
- | N_FRAMING_ERROR
- | N_BREAK)))) {
- /* There is an error condition on the next byte.
- * If we have already transferred some bytes,
- * we'll stop here. Otherwise if this is the
- * first byte to be read, we'll just transfer
- * it alone after notifying the
- * upper layer of its status.
- */
- if (total > 0) {
- len = 0;
- break;
- } else {
- if ((*sc & IOC4_RXSB_PAR_ERR) &&
- (port->ip_notify & N_PARITY_ERROR)) {
- ioc4_cb_post_ncs(the_port,
- NCS_PARITY);
- }
- if ((*sc & IOC4_RXSB_FRAME_ERR) &&
- (port->ip_notify & N_FRAMING_ERROR)){
- ioc4_cb_post_ncs(the_port,
- NCS_FRAMING);
- }
- if ((*sc & IOC4_RXSB_BREAK)
- && (port->ip_notify & N_BREAK)) {
- ioc4_cb_post_ncs
- (the_port,
- NCS_BREAK);
- }
- len = 1;
- }
- }
- if (*sc & IOC4_RXSB_DATA_VALID) {
- *sc &= ~IOC4_RXSB_DATA_VALID;
- *buf = entry->ring_data[byte_num];
- buf++;
- len--;
- total++;
- }
- }
-
- /* If we used up this entry entirely, go on to the next one,
- * otherwise we must have run out of buffer space, so
- * leave the consumer pointer here for the next read in case
- * there are still unread bytes in this entry.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- cons_ptr += (int)sizeof(struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- }
-
- /* Update consumer pointer and re-arm rx timer interrupt */
- writel(cons_ptr, &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* If we have now dipped below the rx high water mark and we have
- * rx_high interrupt turned off, we can now turn it back on again.
- */
- if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
- & PROD_CONS_MASK) < ((port->ip_sscr &
- IOC4_SSCR_RX_THRESHOLD)
- << IOC4_PROD_CONS_PTR_OFF))) {
- port->ip_flags &= ~INPUT_HIGH;
- enable_intrs(port, hooks->intr_rx_high);
- }
- return total;
-}
-
-/**
- * receive_chars - upper level read. Called with ip_lock.
- * @the_port: port to read from
- */
-static void receive_chars(struct uart_port *the_port)
-{
- unsigned char ch[IOC4_MAX_CHARS];
- int read_count, request_count = IOC4_MAX_CHARS;
- struct uart_icount *icount;
- struct uart_state *state = the_port->state;
- unsigned long pflags;
-
- /* Make sure all the pointers are "good" ones */
- if (!state)
- return;
-
- spin_lock_irqsave(&the_port->lock, pflags);
-
- request_count = tty_buffer_request_room(&state->port, IOC4_MAX_CHARS);
-
- if (request_count > 0) {
- icount = &the_port->icount;
- read_count = do_read(the_port, ch, request_count);
- if (read_count > 0) {
- tty_insert_flip_string(&state->port, ch, read_count);
- icount->rx += read_count;
- }
- }
-
- spin_unlock_irqrestore(&the_port->lock, pflags);
-
- tty_flip_buffer_push(&state->port);
-}
-
-/**
- * ic4_type - What type of console are we?
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *ic4_type(struct uart_port *the_port)
-{
- if (the_port->mapbase == PROTO_RS232)
- return "SGI IOC4 Serial [rs232]";
- else
- return "SGI IOC4 Serial [rs422]";
-}
-
-/**
- * ic4_tx_empty - Is the transmitter empty?
- * @port: Port to operate on
- *
- */
-static unsigned int ic4_tx_empty(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- unsigned int ret = 0;
-
- if (port_is_active(port, the_port)) {
- if (readl(&port->ip_serial_regs->shadow) & IOC4_SHADOW_TEMT)
- ret = TIOCSER_TEMT;
- }
- return ret;
-}
-
-/**
- * ic4_stop_tx - stop the transmitter
- * @port: Port to operate on
- *
- */
-static void ic4_stop_tx(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
-
- if (port_is_active(port, the_port))
- set_notification(port, N_OUTPUT_LOWAT, 0);
-}
-
-/**
- * null_void_function -
- * @port: Port to operate on
- *
- */
-static void null_void_function(struct uart_port *the_port)
-{
-}
-
-/**
- * ic4_shutdown - shut down the port - free irq and disable
- * @port: Port to shut down
- *
- */
-static void ic4_shutdown(struct uart_port *the_port)
-{
- unsigned long port_flags;
- struct ioc4_port *port;
- struct uart_state *state;
-
- port = get_ioc4_port(the_port, 0);
- if (!port)
- return;
-
- state = the_port->state;
- port->ip_port = NULL;
-
- wake_up_interruptible(&state->port.delta_msr_wait);
-
- if (state->port.tty)
- set_bit(TTY_IO_ERROR, &state->port.tty->flags);
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- set_notification(port, N_ALL, 0);
- port->ip_flags = PORT_INACTIVE;
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic4_set_mctrl - set control lines (dtr, rts, etc)
- * @port: Port to operate on
- * @mctrl: Lines to set/unset
- *
- */
-static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
-{
- unsigned char mcr = 0;
- struct ioc4_port *port;
-
- port = get_ioc4_port(the_port, 0);
- if (!port_is_active(port, the_port))
- return;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- set_mcr(the_port, mcr, IOC4_SHADOW_DTR);
-}
-
-/**
- * ic4_get_mctrl - get control line info
- * @port: port to operate on
- *
- */
-static unsigned int ic4_get_mctrl(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- uint32_t shadow;
- unsigned int ret = 0;
-
- if (!port_is_active(port, the_port))
- return 0;
-
- shadow = readl(&port->ip_serial_regs->shadow);
- if (shadow & IOC4_SHADOW_DCD)
- ret |= TIOCM_CAR;
- if (shadow & IOC4_SHADOW_DR)
- ret |= TIOCM_DSR;
- if (shadow & IOC4_SHADOW_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-/**
- * ic4_start_tx - Start transmitter, flush any output
- * @port: Port to operate on
- *
- */
-static void ic4_start_tx(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
-
- if (port_is_active(port, the_port)) {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- enable_intrs(port, port->ip_hooks->intr_tx_mt);
- }
-}
-
-/**
- * ic4_break_ctl - handle breaks
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void ic4_break_ctl(struct uart_port *the_port, int break_state)
-{
-}
-
-/**
- * ic4_startup - Start up the serial port
- * @port: Port to operate on
- *
- */
-static int ic4_startup(struct uart_port *the_port)
-{
- int retval;
- struct ioc4_port *port;
- struct ioc4_control *control;
- struct uart_state *state;
- unsigned long port_flags;
-
- if (!the_port)
- return -ENODEV;
- port = get_ioc4_port(the_port, 1);
- if (!port)
- return -ENODEV;
- state = the_port->state;
-
- control = port->ip_control;
- if (!control) {
- port->ip_port = NULL;
- return -ENODEV;
- }
-
- /* Start up the serial port */
- spin_lock_irqsave(&the_port->lock, port_flags);
- retval = ic4_startup_local(the_port);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
- return retval;
-}
-
-/**
- * ic4_set_termios - set termios stuff
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-ic4_set_termios(struct uart_port *the_port,
- struct ktermios *termios, struct ktermios *old_termios)
-{
- unsigned long port_flags;
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- ioc4_change_speed(the_port, termios, old_termios);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic4_request_port - allocate resources for port - no op....
- * @port: port to operate on
- *
- */
-static int ic4_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* Associate the uart functions above - given to serial core */
-
-static const struct uart_ops ioc4_ops = {
- .tx_empty = ic4_tx_empty,
- .set_mctrl = ic4_set_mctrl,
- .get_mctrl = ic4_get_mctrl,
- .stop_tx = ic4_stop_tx,
- .start_tx = ic4_start_tx,
- .stop_rx = null_void_function,
- .break_ctl = ic4_break_ctl,
- .startup = ic4_startup,
- .shutdown = ic4_shutdown,
- .set_termios = ic4_set_termios,
- .type = ic4_type,
- .release_port = null_void_function,
- .request_port = ic4_request_port,
-};
-
-/*
- * Boot-time initialization code
- */
-
-static struct uart_driver ioc4_uart_rs232 = {
- .owner = THIS_MODULE,
- .driver_name = "ioc4_serial_rs232",
- .dev_name = DEVICE_NAME_RS232,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR_RS232,
- .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
-};
-
-static struct uart_driver ioc4_uart_rs422 = {
- .owner = THIS_MODULE,
- .driver_name = "ioc4_serial_rs422",
- .dev_name = DEVICE_NAME_RS422,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR_RS422,
- .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
-};
-
-
-/**
- * ioc4_serial_remove_one - detach function
- *
- * @idd: IOC4 master module data for this IOC4
- */
-
-static int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
-{
- int port_num, port_type;
- struct ioc4_control *control;
- struct uart_port *the_port;
- struct ioc4_port *port;
- struct ioc4_soft *soft;
-
- /* If serial driver did not attach, don't try to detach */
- control = idd->idd_serial_data;
- if (!control)
- return 0;
-
- for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
- for (port_type = UART_PORT_MIN;
- port_type < UART_PORT_COUNT;
- port_type++) {
- the_port = &control->ic_port[port_num].icp_uart_port
- [port_type];
- if (the_port) {
- switch (port_type) {
- case UART_PORT_RS422:
- uart_remove_one_port(&ioc4_uart_rs422,
- the_port);
- break;
- default:
- case UART_PORT_RS232:
- uart_remove_one_port(&ioc4_uart_rs232,
- the_port);
- break;
- }
- }
- }
- port = control->ic_port[port_num].icp_port;
- /* we allocate in pairs */
- if (!(port_num & 1) && port) {
- pci_free_consistent(port->ip_pdev,
- TOTAL_RING_BUF_SIZE,
- port->ip_cpu_ringbuf,
- port->ip_dma_ringbuf);
- kfree(port);
- }
- }
- soft = control->ic_soft;
- if (soft) {
- free_irq(control->ic_irq, soft);
- if (soft->is_ioc4_serial_addr) {
- iounmap(soft->is_ioc4_serial_addr);
- release_mem_region((unsigned long)
- soft->is_ioc4_serial_addr,
- sizeof(struct ioc4_serial));
- }
- kfree(soft);
- }
- kfree(control);
- idd->idd_serial_data = NULL;
-
- return 0;
-}
-
-
-/**
- * ioc4_serial_core_attach_rs232 - register with serial core
- * This is done during pci probing
- * @pdev: handle for this card
- */
-static inline int
-ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
-{
- struct ioc4_port *port;
- struct uart_port *the_port;
- struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
- struct ioc4_control *control = idd->idd_serial_data;
- int port_num;
- int port_type_idx;
- struct uart_driver *u_driver;
-
-
- DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
- __func__, pdev, (void *)control));
-
- if (!control)
- return -ENODEV;
-
- port_type_idx = (port_type == PROTO_RS232) ? UART_PORT_RS232
- : UART_PORT_RS422;
-
- u_driver = (port_type == PROTO_RS232) ? &ioc4_uart_rs232
- : &ioc4_uart_rs422;
-
- /* once around for each port on this card */
- for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
- the_port = &control->ic_port[port_num].icp_uart_port
- [port_type_idx];
- port = control->ic_port[port_num].icp_port;
- port->ip_all_ports[port_type_idx] = the_port;
-
- DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n",
- __func__, (void *)the_port,
- (void *)port,
- port_type == PROTO_RS232 ? "rs232" : "rs422"));
-
- /* membase, iobase and mapbase just need to be non-0 */
- the_port->membase = (unsigned char __iomem *)1;
- the_port->iobase = (pdev->bus->number << 16) | port_num;
- the_port->line = (Num_of_ioc4_cards << 2) | port_num;
- the_port->mapbase = port_type;
- the_port->type = PORT_16550A;
- the_port->fifosize = IOC4_FIFO_CHARS;
- the_port->ops = &ioc4_ops;
- the_port->irq = control->ic_irq;
- the_port->dev = &pdev->dev;
- spin_lock_init(&the_port->lock);
- if (uart_add_one_port(u_driver, the_port) < 0) {
- printk(KERN_WARNING
- "%s: unable to add port %d bus %d\n",
- __func__, the_port->line, pdev->bus->number);
- } else {
- DPRINT_CONFIG(
- ("IOC4 serial port %d irq = %d, bus %d\n",
- the_port->line, the_port->irq, pdev->bus->number));
- }
- }
- return 0;
-}
-
-/**
- * ioc4_serial_attach_one - register attach function
- * called per card found from IOC4 master module.
- * @idd: Master module data for this IOC4
- */
-static int
-ioc4_serial_attach_one(struct ioc4_driver_data *idd)
-{
- unsigned long tmp_addr1;
- struct ioc4_serial __iomem *serial;
- struct ioc4_soft *soft;
- struct ioc4_control *control;
- int ret = 0;
-
-
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, idd->idd_pdev,
- idd->idd_pci_id));
-
- /* PCI-RT does not bring out serial connections.
- * Do not attach to this particular IOC4.
- */
- if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
- return 0;
-
- /* request serial registers */
- tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
-
- if (!request_mem_region(tmp_addr1, sizeof(struct ioc4_serial),
- "sioc4_uart")) {
- printk(KERN_WARNING
- "ioc4 (%p): unable to get request region for "
- "uart space\n", (void *)idd->idd_pdev);
- ret = -ENODEV;
- goto out1;
- }
- serial = ioremap(tmp_addr1, sizeof(struct ioc4_serial));
- if (!serial) {
- printk(KERN_WARNING
- "ioc4 (%p) : unable to remap ioc4 serial register\n",
- (void *)idd->idd_pdev);
- ret = -ENODEV;
- goto out2;
- }
- DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
- __func__, (void *)idd->idd_misc_regs,
- (void *)serial));
-
- /* Get memory for the new card */
- control = kzalloc(sizeof(struct ioc4_control), GFP_KERNEL);
-
- if (!control) {
- printk(KERN_WARNING "ioc4_attach_one"
- ": unable to get memory for the IOC4\n");
- ret = -ENOMEM;
- goto out2;
- }
- idd->idd_serial_data = control;
-
- /* Allocate the soft structure */
- soft = kzalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
- if (!soft) {
- printk(KERN_WARNING
- "ioc4 (%p): unable to get memory for the soft struct\n",
- (void *)idd->idd_pdev);
- ret = -ENOMEM;
- goto out3;
- }
-
- spin_lock_init(&soft->is_ir_lock);
- soft->is_ioc4_misc_addr = idd->idd_misc_regs;
- soft->is_ioc4_serial_addr = serial;
-
- /* Init the IOC4 */
- writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
- &idd->idd_misc_regs->sio_cr.raw);
-
- /* Enable serial port mode select generic PIO pins as outputs */
- writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
- | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
- &idd->idd_misc_regs->gpcr_s.raw);
-
- /* Clear and disable all serial interrupts */
- write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
- writel(~0, &idd->idd_misc_regs->sio_ir.raw);
- write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
- IOC4_OTHER_INTR_TYPE);
- writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
- control->ic_soft = soft;
-
- /* Hook up interrupt handler */
- if (!request_irq(idd->idd_pdev->irq, ioc4_intr, IRQF_SHARED,
- "sgi-ioc4serial", soft)) {
- control->ic_irq = idd->idd_pdev->irq;
- } else {
- printk(KERN_WARNING
- "%s : request_irq fails for IRQ 0x%x\n ",
- __func__, idd->idd_pdev->irq);
- }
- ret = ioc4_attach_local(idd);
- if (ret)
- goto out4;
-
- /* register port with the serial core - 1 rs232, 1 rs422 */
-
- ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232);
- if (ret)
- goto out4;
-
- ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422);
- if (ret)
- goto out5;
-
- Num_of_ioc4_cards++;
-
- return ret;
-
- /* error exits that give back resources */
-out5:
- ioc4_serial_remove_one(idd);
- return ret;
-out4:
- kfree(soft);
-out3:
- kfree(control);
-out2:
- if (serial)
- iounmap(serial);
- release_mem_region(tmp_addr1, sizeof(struct ioc4_serial));
-out1:
-
- return ret;
-}
-
-
-static struct ioc4_submodule ioc4_serial_submodule = {
- .is_name = "IOC4_serial",
- .is_owner = THIS_MODULE,
- .is_probe = ioc4_serial_attach_one,
- .is_remove = ioc4_serial_remove_one,
-};
-
-/**
- * ioc4_serial_init - module init
- */
-static int __init ioc4_serial_init(void)
-{
- int ret;
-
- /* register with serial core */
- if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register rs232 IOC4 serial driver\n",
- __func__);
- goto out;
- }
- if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register rs422 IOC4 serial driver\n",
- __func__);
- goto out_uart_rs232;
- }
-
- /* register with IOC4 main module */
- ret = ioc4_register_submodule(&ioc4_serial_submodule);
- if (ret)
- goto out_uart_rs422;
- return 0;
-
-out_uart_rs422:
- uart_unregister_driver(&ioc4_uart_rs422);
-out_uart_rs232:
- uart_unregister_driver(&ioc4_uart_rs232);
-out:
- return ret;
-}
-
-static void __exit ioc4_serial_exit(void)
-{
- ioc4_unregister_submodule(&ioc4_serial_submodule);
- uart_unregister_driver(&ioc4_uart_rs232);
- uart_unregister_driver(&ioc4_uart_rs422);
-}
-
-late_initcall(ioc4_serial_init); /* Call only after tty init is done */
-module_exit(ioc4_serial_exit);
-
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
index bfe5e9e034ec..c7d51b51898f 100644
--- a/drivers/tty/serial/kgdboc.c
+++ b/drivers/tty/serial/kgdboc.c
@@ -277,10 +277,14 @@ static void kgdboc_pre_exp_handler(void)
/* Increment the module count when the debugger is active */
if (!kgdb_connected)
try_module_get(THIS_MODULE);
+
+ atomic_inc(&ignore_console_lock_warning);
}
static void kgdboc_post_exp_handler(void)
{
+ atomic_dec(&ignore_console_lock_warning);
+
/* decrement the module count when the debugger detaches */
if (!kgdb_connected)
module_put(THIS_MODULE);
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index f4e27d0ad947..d3843f722182 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -25,8 +25,8 @@
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/of.h>
-#include <mach/platform.h>
-#include <mach/hardware.h>
+#include <linux/sizes.h>
+#include <linux/soc/nxp/lpc32xx-misc.h>
/*
* High Speed UART register offsets
@@ -81,6 +81,8 @@
#define LPC32XX_HSU_TX_TL8B (0x2 << 0)
#define LPC32XX_HSU_TX_TL16B (0x3 << 0)
+#define LPC32XX_MAIN_OSC_FREQ 13000000
+
#define MODNAME "lpc32xx_hsuart"
struct lpc32xx_hsuart_port {
@@ -151,8 +153,6 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
local_irq_restore(flags);
}
-static void lpc32xx_loopback_set(resource_size_t mapbase, int state);
-
static int __init lpc32xx_hsuart_console_setup(struct console *co,
char *options)
{
@@ -439,35 +439,6 @@ static void serial_lpc32xx_break_ctl(struct uart_port *port,
spin_unlock_irqrestore(&port->lock, flags);
}
-/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */
-static void lpc32xx_loopback_set(resource_size_t mapbase, int state)
-{
- int bit;
- u32 tmp;
-
- switch (mapbase) {
- case LPC32XX_HS_UART1_BASE:
- bit = 0;
- break;
- case LPC32XX_HS_UART2_BASE:
- bit = 1;
- break;
- case LPC32XX_HS_UART7_BASE:
- bit = 6;
- break;
- default:
- WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase);
- return;
- }
-
- tmp = readl(LPC32XX_UARTCTL_CLOOP);
- if (state)
- tmp |= (1 << bit);
- else
- tmp &= ~(1 << bit);
- writel(tmp, LPC32XX_UARTCTL_CLOOP);
-}
-
/* port->lock is not held. */
static int serial_lpc32xx_startup(struct uart_port *port)
{
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c
deleted file mode 100644
index b3556863491f..000000000000
--- a/drivers/tty/serial/netx-serial.c
+++ /dev/null
@@ -1,733 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/netx-regs.h>
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_NX_MAJOR 204
-#define MINOR_START 170
-
-enum uart_regs {
- UART_DR = 0x00,
- UART_SR = 0x04,
- UART_LINE_CR = 0x08,
- UART_BAUDDIV_MSB = 0x0c,
- UART_BAUDDIV_LSB = 0x10,
- UART_CR = 0x14,
- UART_FR = 0x18,
- UART_IIR = 0x1c,
- UART_ILPR = 0x20,
- UART_RTS_CR = 0x24,
- UART_RTS_LEAD = 0x28,
- UART_RTS_TRAIL = 0x2c,
- UART_DRV_ENABLE = 0x30,
- UART_BRM_CR = 0x34,
- UART_RXFIFO_IRQLEVEL = 0x38,
- UART_TXFIFO_IRQLEVEL = 0x3c,
-};
-
-#define SR_FE (1<<0)
-#define SR_PE (1<<1)
-#define SR_BE (1<<2)
-#define SR_OE (1<<3)
-
-#define LINE_CR_BRK (1<<0)
-#define LINE_CR_PEN (1<<1)
-#define LINE_CR_EPS (1<<2)
-#define LINE_CR_STP2 (1<<3)
-#define LINE_CR_FEN (1<<4)
-#define LINE_CR_5BIT (0<<5)
-#define LINE_CR_6BIT (1<<5)
-#define LINE_CR_7BIT (2<<5)
-#define LINE_CR_8BIT (3<<5)
-#define LINE_CR_BITS_MASK (3<<5)
-
-#define CR_UART_EN (1<<0)
-#define CR_SIREN (1<<1)
-#define CR_SIRLP (1<<2)
-#define CR_MSIE (1<<3)
-#define CR_RIE (1<<4)
-#define CR_TIE (1<<5)
-#define CR_RTIE (1<<6)
-#define CR_LBE (1<<7)
-
-#define FR_CTS (1<<0)
-#define FR_DSR (1<<1)
-#define FR_DCD (1<<2)
-#define FR_BUSY (1<<3)
-#define FR_RXFE (1<<4)
-#define FR_TXFF (1<<5)
-#define FR_RXFF (1<<6)
-#define FR_TXFE (1<<7)
-
-#define IIR_MIS (1<<0)
-#define IIR_RIS (1<<1)
-#define IIR_TIS (1<<2)
-#define IIR_RTIS (1<<3)
-#define IIR_MASK 0xf
-
-#define RTS_CR_AUTO (1<<0)
-#define RTS_CR_RTS (1<<1)
-#define RTS_CR_COUNT (1<<2)
-#define RTS_CR_MOD2 (1<<3)
-#define RTS_CR_RTS_POL (1<<4)
-#define RTS_CR_CTS_CTR (1<<5)
-#define RTS_CR_CTS_POL (1<<6)
-#define RTS_CR_STICK (1<<7)
-
-#define UART_PORT_SIZE 0x40
-#define DRIVER_NAME "netx-uart"
-
-struct netx_port {
- struct uart_port port;
-};
-
-static void netx_stop_tx(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val & ~CR_TIE, port->membase + UART_CR);
-}
-
-static void netx_stop_rx(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val & ~CR_RIE, port->membase + UART_CR);
-}
-
-static void netx_enable_ms(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val | CR_MSIE, port->membase + UART_CR);
-}
-
-static inline void netx_transmit_buffer(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (port->x_char) {
- writel(port->x_char, port->membase + UART_DR);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
- netx_stop_tx(port);
- return;
- }
-
- do {
- /* send xmit->buf[xmit->tail]
- * out the port here */
- writel(xmit->buf[xmit->tail], port->membase + UART_DR);
- xmit->tail = (xmit->tail + 1) &
- (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (!(readl(port->membase + UART_FR) & FR_TXFF));
-
- if (uart_circ_empty(xmit))
- netx_stop_tx(port);
-}
-
-static void netx_start_tx(struct uart_port *port)
-{
- writel(
- readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
-
- if (!(readl(port->membase + UART_FR) & FR_TXFF))
- netx_transmit_buffer(port);
-}
-
-static unsigned int netx_tx_empty(struct uart_port *port)
-{
- return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
-}
-
-static void netx_txint(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- netx_stop_tx(port);
- return;
- }
-
- netx_transmit_buffer(port);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static void netx_rxint(struct uart_port *port, unsigned long *flags)
-{
- unsigned char rx, flg, status;
-
- while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
- rx = readl(port->membase + UART_DR);
- flg = TTY_NORMAL;
- port->icount.rx++;
- status = readl(port->membase + UART_SR);
- if (status & SR_BE) {
- writel(0, port->membase + UART_SR);
- if (uart_handle_break(port))
- continue;
- }
-
- if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
-
- if (status & SR_PE)
- port->icount.parity++;
- else if (status & SR_FE)
- port->icount.frame++;
- if (status & SR_OE)
- port->icount.overrun++;
-
- status &= port->read_status_mask;
-
- if (status & SR_BE)
- flg = TTY_BREAK;
- else if (status & SR_PE)
- flg = TTY_PARITY;
- else if (status & SR_FE)
- flg = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, rx))
- continue;
-
- uart_insert_char(port, status, SR_OE, rx, flg);
- }
-
- spin_unlock_irqrestore(&port->lock, *flags);
- tty_flip_buffer_push(&port->state->port);
- spin_lock_irqsave(&port->lock, *flags);
-}
-
-static irqreturn_t netx_int(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned long flags;
- unsigned char status;
-
- spin_lock_irqsave(&port->lock,flags);
-
- status = readl(port->membase + UART_IIR) & IIR_MASK;
- while (status) {
- if (status & IIR_RIS)
- netx_rxint(port, &flags);
- if (status & IIR_TIS)
- netx_txint(port);
- if (status & IIR_MIS) {
- if (readl(port->membase + UART_FR) & FR_CTS)
- uart_handle_cts_change(port, 1);
- else
- uart_handle_cts_change(port, 0);
- }
- writel(0, port->membase + UART_IIR);
- status = readl(port->membase + UART_IIR) & IIR_MASK;
- }
-
- spin_unlock_irqrestore(&port->lock,flags);
- return IRQ_HANDLED;
-}
-
-static unsigned int netx_get_mctrl(struct uart_port *port)
-{
- unsigned int ret = TIOCM_DSR | TIOCM_CAR;
-
- if (readl(port->membase + UART_FR) & FR_CTS)
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- unsigned int val;
-
- /* FIXME: Locking needed ? */
- if (mctrl & TIOCM_RTS) {
- val = readl(port->membase + UART_RTS_CR);
- writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
- }
-}
-
-static void netx_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned int line_cr;
- spin_lock_irq(&port->lock);
-
- line_cr = readl(port->membase + UART_LINE_CR);
- if (break_state != 0)
- line_cr |= LINE_CR_BRK;
- else
- line_cr &= ~LINE_CR_BRK;
- writel(line_cr, port->membase + UART_LINE_CR);
-
- spin_unlock_irq(&port->lock);
-}
-
-static int netx_startup(struct uart_port *port)
-{
- int ret;
-
- ret = request_irq(port->irq, netx_int, 0,
- DRIVER_NAME, port);
- if (ret) {
- dev_err(port->dev, "unable to grab irq%d\n",port->irq);
- goto exit;
- }
-
- writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
- port->membase + UART_LINE_CR);
-
- writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
- port->membase + UART_CR);
-
-exit:
- return ret;
-}
-
-static void netx_shutdown(struct uart_port *port)
-{
- writel(0, port->membase + UART_CR) ;
-
- free_irq(port->irq, port);
-}
-
-static void
-netx_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud, quot;
- unsigned char old_cr;
- unsigned char line_cr = LINE_CR_FEN;
- unsigned char rts_cr = 0;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- line_cr |= LINE_CR_5BIT;
- break;
- case CS6:
- line_cr |= LINE_CR_6BIT;
- break;
- case CS7:
- line_cr |= LINE_CR_7BIT;
- break;
- case CS8:
- line_cr |= LINE_CR_8BIT;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- line_cr |= LINE_CR_STP2;
-
- if (termios->c_cflag & PARENB) {
- line_cr |= LINE_CR_PEN;
- if (!(termios->c_cflag & PARODD))
- line_cr |= LINE_CR_EPS;
- }
-
- if (termios->c_cflag & CRTSCTS)
- rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = baud * 4096;
- quot /= 1000;
- quot *= 256;
- quot /= 100000;
-
- spin_lock_irq(&port->lock);
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- old_cr = readl(port->membase + UART_CR);
-
- /* disable interrupts */
- writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
- port->membase + UART_CR);
-
- /* drain transmitter */
- while (readl(port->membase + UART_FR) & FR_BUSY);
-
- /* disable UART */
- writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
-
- /* modem status interrupts */
- old_cr &= ~CR_MSIE;
- if (UART_ENABLE_MS(port, termios->c_cflag))
- old_cr |= CR_MSIE;
-
- writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
- writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
- writel(line_cr, port->membase + UART_LINE_CR);
-
- writel(rts_cr, port->membase + UART_RTS_CR);
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= SR_PE;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= SR_BE;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= SR_PE;
- }
-
- port->read_status_mask = 0;
- if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
- port->read_status_mask |= SR_BE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= SR_PE | SR_FE;
-
- writel(old_cr, port->membase + UART_CR);
-
- spin_unlock_irq(&port->lock);
-}
-
-static const char *netx_type(struct uart_port *port)
-{
- return port->type == PORT_NETX ? "NETX" : NULL;
-}
-
-static void netx_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-}
-
-static int netx_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE,
- DRIVER_NAME) != NULL ? 0 : -EBUSY;
-}
-
-static void netx_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
- port->type = PORT_NETX;
-}
-
-static int
-netx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
- ret = -EINVAL;
-
- return ret;
-}
-
-static struct uart_ops netx_pops = {
- .tx_empty = netx_tx_empty,
- .set_mctrl = netx_set_mctrl,
- .get_mctrl = netx_get_mctrl,
- .stop_tx = netx_stop_tx,
- .start_tx = netx_start_tx,
- .stop_rx = netx_stop_rx,
- .enable_ms = netx_enable_ms,
- .break_ctl = netx_break_ctl,
- .startup = netx_startup,
- .shutdown = netx_shutdown,
- .set_termios = netx_set_termios,
- .type = netx_type,
- .release_port = netx_release_port,
- .request_port = netx_request_port,
- .config_port = netx_config_port,
- .verify_port = netx_verify_port,
-};
-
-static struct netx_port netx_ports[] = {
- {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART0),
- .mapbase = NETX_PA_UART0,
- .irq = NETX_IRQ_UART0,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 0,
- },
- }, {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART1),
- .mapbase = NETX_PA_UART1,
- .irq = NETX_IRQ_UART1,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 1,
- },
- }, {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART2),
- .mapbase = NETX_PA_UART2,
- .irq = NETX_IRQ_UART2,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 2,
- },
- }
-};
-
-#ifdef CONFIG_SERIAL_NETX_CONSOLE
-
-static void netx_console_putchar(struct uart_port *port, int ch)
-{
- while (readl(port->membase + UART_FR) & FR_BUSY);
- writel(ch, port->membase + UART_DR);
-}
-
-static void
-netx_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_port *port = &netx_ports[co->index].port;
- unsigned char cr_save;
-
- cr_save = readl(port->membase + UART_CR);
- writel(cr_save | CR_UART_EN, port->membase + UART_CR);
-
- uart_console_write(port, s, count, netx_console_putchar);
-
- while (readl(port->membase + UART_FR) & FR_BUSY);
- writel(cr_save, port->membase + UART_CR);
-}
-
-static void __init
-netx_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits, int *flow)
-{
- unsigned char line_cr;
-
- *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
- readl(port->membase + UART_BAUDDIV_LSB);
- *baud *= 1000;
- *baud /= 4096;
- *baud *= 1000;
- *baud /= 256;
- *baud *= 100;
-
- line_cr = readl(port->membase + UART_LINE_CR);
- *parity = 'n';
- if (line_cr & LINE_CR_PEN) {
- if (line_cr & LINE_CR_EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- switch (line_cr & LINE_CR_BITS_MASK) {
- case LINE_CR_8BIT:
- *bits = 8;
- break;
- case LINE_CR_7BIT:
- *bits = 7;
- break;
- case LINE_CR_6BIT:
- *bits = 6;
- break;
- case LINE_CR_5BIT:
- *bits = 5;
- break;
- }
-
- if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
- *flow = 'r';
-}
-
-static int __init
-netx_console_setup(struct console *co, char *options)
-{
- struct netx_port *sport;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
- co->index = 0;
- sport = &netx_ports[co->index];
-
- if (options) {
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- } else {
- /* if the UART is enabled, assume it has been correctly setup
- * by the bootloader and get the options
- */
- if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
- netx_console_get_options(&sport->port, &baud,
- &parity, &bits, &flow);
- }
-
- }
-
- return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver netx_reg;
-static struct console netx_console = {
- .name = "ttyNX",
- .write = netx_console_write,
- .device = uart_console_device,
- .setup = netx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &netx_reg,
-};
-
-static int __init netx_console_init(void)
-{
- register_console(&netx_console);
- return 0;
-}
-console_initcall(netx_console_init);
-
-#define NETX_CONSOLE &netx_console
-#else
-#define NETX_CONSOLE NULL
-#endif
-
-static struct uart_driver netx_reg = {
- .owner = THIS_MODULE,
- .driver_name = DRIVER_NAME,
- .dev_name = "ttyNX",
- .major = SERIAL_NX_MAJOR,
- .minor = MINOR_START,
- .nr = ARRAY_SIZE(netx_ports),
- .cons = NETX_CONSOLE,
-};
-
-static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- if (sport)
- uart_suspend_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_netx_resume(struct platform_device *pdev)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- if (sport)
- uart_resume_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_netx_probe(struct platform_device *pdev)
-{
- struct uart_port *port = &netx_ports[pdev->id].port;
-
- dev_info(&pdev->dev, "initialising\n");
-
- port->dev = &pdev->dev;
-
- writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
- uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
- platform_set_drvdata(pdev, &netx_ports[pdev->id]);
-
- return 0;
-}
-
-static int serial_netx_remove(struct platform_device *pdev)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- if (sport)
- uart_remove_one_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static struct platform_driver serial_netx_driver = {
- .probe = serial_netx_probe,
- .remove = serial_netx_remove,
-
- .suspend = serial_netx_suspend,
- .resume = serial_netx_resume,
-
- .driver = {
- .name = DRIVER_NAME,
- },
-};
-
-static int __init netx_serial_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: NetX driver\n");
-
- ret = uart_register_driver(&netx_reg);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&serial_netx_driver);
- if (ret != 0)
- uart_unregister_driver(&netx_reg);
-
- return 0;
-}
-
-static void __exit netx_serial_exit(void)
-{
- platform_driver_unregister(&serial_netx_driver);
- uart_unregister_driver(&netx_reg);
-}
-
-module_init(netx_serial_init);
-module_exit(netx_serial_exit);
-
-MODULE_AUTHOR("Sascha Hauer");
-MODULE_DESCRIPTION("NetX serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c
deleted file mode 100644
index 283493358a62..000000000000
--- a/drivers/tty/serial/sn_console.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * C-Brick Serial Port (and console) driver for SGI Altix machines.
- *
- * This driver is NOT suitable for talking to the l1-controller for
- * anything other than 'console activities' --- please use the l1
- * driver for that.
- *
- *
- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/sysrq.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/delay.h> /* for mdelay */
-#include <linux/miscdevice.h>
-#include <linux/serial_core.h>
-
-#include <asm/io.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/sn_sal.h>
-
-/* number of characters we can transmit to the SAL console at a time */
-#define SN_SAL_MAX_CHARS 120
-
-/* 64K, when we're asynch, it must be at least printk's LOG_BUF_LEN to
- * avoid losing chars, (always has to be a power of 2) */
-#define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
-
-#define SN_SAL_UART_FIFO_DEPTH 16
-#define SN_SAL_UART_FIFO_SPEED_CPS (9600/10)
-
-/* sn_transmit_chars() calling args */
-#define TRANSMIT_BUFFERED 0
-#define TRANSMIT_RAW 1
-
-/* To use dynamic numbers only and not use the assigned major and minor,
- * define the following.. */
- /* #define USE_DYNAMIC_MINOR 1 *//* use dynamic minor number */
-#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */
-
-/* Device name we're using */
-#define DEVICE_NAME "ttySG"
-#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */
-/* The major/minor we are using, ignored for USE_DYNAMIC_MINOR */
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR 40
-
-#ifdef CONFIG_MAGIC_SYSRQ
-static char sysrq_serial_str[] = "\eSYS";
-static char *sysrq_serial_ptr = sysrq_serial_str;
-static unsigned long sysrq_requested;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
-/*
- * Port definition - this kinda drives it all
- */
-struct sn_cons_port {
- struct timer_list sc_timer;
- struct uart_port sc_port;
- struct sn_sal_ops {
- int (*sal_puts_raw) (const char *s, int len);
- int (*sal_puts) (const char *s, int len);
- int (*sal_getc) (void);
- int (*sal_input_pending) (void);
- void (*sal_wakeup_transmit) (struct sn_cons_port *, int);
- } *sc_ops;
- unsigned long sc_interrupt_timeout;
- int sc_is_asynch;
-};
-
-static struct sn_cons_port sal_console_port;
-static int sn_process_input;
-
-/* Only used if USE_DYNAMIC_MINOR is set to 1 */
-static struct miscdevice misc; /* used with misc_register for dynamic */
-
-extern void early_sn_setup(void);
-
-#undef DEBUG
-#ifdef DEBUG
-static int sn_debug_printf(const char *fmt, ...);
-#define DPRINTF(x...) sn_debug_printf(x)
-#else
-#define DPRINTF(x...) do { } while (0)
-#endif
-
-/* Prototypes */
-static int snt_hw_puts_raw(const char *, int);
-static int snt_hw_puts_buffered(const char *, int);
-static int snt_poll_getc(void);
-static int snt_poll_input_pending(void);
-static int snt_intr_getc(void);
-static int snt_intr_input_pending(void);
-static void sn_transmit_chars(struct sn_cons_port *, int);
-
-/* A table for polling:
- */
-static struct sn_sal_ops poll_ops = {
- .sal_puts_raw = snt_hw_puts_raw,
- .sal_puts = snt_hw_puts_raw,
- .sal_getc = snt_poll_getc,
- .sal_input_pending = snt_poll_input_pending
-};
-
-/* A table for interrupts enabled */
-static struct sn_sal_ops intr_ops = {
- .sal_puts_raw = snt_hw_puts_raw,
- .sal_puts = snt_hw_puts_buffered,
- .sal_getc = snt_intr_getc,
- .sal_input_pending = snt_intr_input_pending,
- .sal_wakeup_transmit = sn_transmit_chars
-};
-
-/* the console does output in two distinctly different ways:
- * synchronous (raw) and asynchronous (buffered). initially, early_printk
- * does synchronous output. any data written goes directly to the SAL
- * to be output (incidentally, it is internally buffered by the SAL)
- * after interrupts and timers are initialized and available for use,
- * the console init code switches to asynchronous output. this is
- * also the earliest opportunity to begin polling for console input.
- * after console initialization, console output and tty (serial port)
- * output is buffered and sent to the SAL asynchronously (either by
- * timer callback or by UART interrupt) */
-
-/* routines for running the console in polling mode */
-
-/**
- * snt_poll_getc - Get a character from the console in polling mode
- *
- */
-static int snt_poll_getc(void)
-{
- int ch;
-
- ia64_sn_console_getc(&ch);
- return ch;
-}
-
-/**
- * snt_poll_input_pending - Check if any input is waiting - polling mode.
- *
- */
-static int snt_poll_input_pending(void)
-{
- int status, input;
-
- status = ia64_sn_console_check(&input);
- return !status && input;
-}
-
-/* routines for an interrupt driven console (normal) */
-
-/**
- * snt_intr_getc - Get a character from the console, interrupt mode
- *
- */
-static int snt_intr_getc(void)
-{
- return ia64_sn_console_readc();
-}
-
-/**
- * snt_intr_input_pending - Check if input is pending, interrupt mode
- *
- */
-static int snt_intr_input_pending(void)
-{
- return ia64_sn_console_intr_status() & SAL_CONSOLE_INTR_RECV;
-}
-
-/* these functions are polled and interrupt */
-
-/**
- * snt_hw_puts_raw - Send raw string to the console, polled or interrupt mode
- * @s: String
- * @len: Length
- *
- */
-static int snt_hw_puts_raw(const char *s, int len)
-{
- /* this will call the PROM and not return until this is done */
- return ia64_sn_console_putb(s, len);
-}
-
-/**
- * snt_hw_puts_buffered - Send string to console, polled or interrupt mode
- * @s: String
- * @len: Length
- *
- */
-static int snt_hw_puts_buffered(const char *s, int len)
-{
- /* queue data to the PROM */
- return ia64_sn_console_xmit_chars((char *)s, len);
-}
-
-/* uart interface structs
- * These functions are associated with the uart_port that the serial core
- * infrastructure calls.
- *
- * Note: Due to how the console works, many routines are no-ops.
- */
-
-/**
- * snp_type - What type of console are we?
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *snp_type(struct uart_port *port)
-{
- return ("SGI SN L1");
-}
-
-/**
- * snp_tx_empty - Is the transmitter empty? We pretend we're always empty
- * @port: Port to operate on (we ignore since we only have one port)
- *
- */
-static unsigned int snp_tx_empty(struct uart_port *port)
-{
- return 1;
-}
-
-/**
- * snp_stop_tx - stop the transmitter - no-op for us
- * @port: Port to operat eon - we ignore - no-op function
- *
- */
-static void snp_stop_tx(struct uart_port *port)
-{
-}
-
-/**
- * snp_release_port - Free i/o and resources for port - no-op for us
- * @port: Port to operate on - we ignore - no-op function
- *
- */
-static void snp_release_port(struct uart_port *port)
-{
-}
-
-/**
- * snp_shutdown - shut down the port - free irq and disable - no-op for us
- * @port: Port to shut down - we ignore
- *
- */
-static void snp_shutdown(struct uart_port *port)
-{
-}
-
-/**
- * snp_set_mctrl - set control lines (dtr, rts, etc) - no-op for our console
- * @port: Port to operate on - we ignore
- * @mctrl: Lines to set/unset - we ignore
- *
- */
-static void snp_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-/**
- * snp_get_mctrl - get contorl line info, we just return a static value
- * @port: port to operate on - we only have one port so we ignore this
- *
- */
-static unsigned int snp_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS;
-}
-
-/**
- * snp_stop_rx - Stop the receiver - we ignor ethis
- * @port: Port to operate on - we ignore
- *
- */
-static void snp_stop_rx(struct uart_port *port)
-{
-}
-
-/**
- * snp_start_tx - Start transmitter
- * @port: Port to operate on
- *
- */
-static void snp_start_tx(struct uart_port *port)
-{
- if (sal_console_port.sc_ops->sal_wakeup_transmit)
- sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port,
- TRANSMIT_BUFFERED);
-
-}
-
-/**
- * snp_break_ctl - handle breaks - ignored by us
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void snp_break_ctl(struct uart_port *port, int break_state)
-{
-}
-
-/**
- * snp_startup - Start up the serial port - always return 0 (We're always on)
- * @port: Port to operate on
- *
- */
-static int snp_startup(struct uart_port *port)
-{
- return 0;
-}
-
-/**
- * snp_set_termios - set termios stuff - we ignore these
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-snp_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
-}
-
-/**
- * snp_request_port - allocate resources for port - ignored by us
- * @port: port to operate on
- *
- */
-static int snp_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/**
- * snp_config_port - allocate resources, set up - we ignore, we're always on
- * @port: Port to operate on
- * @flags: flags used for port setup
- *
- */
-static void snp_config_port(struct uart_port *port, int flags)
-{
-}
-
-/* Associate the uart functions above - given to serial core */
-
-static const struct uart_ops sn_console_ops = {
- .tx_empty = snp_tx_empty,
- .set_mctrl = snp_set_mctrl,
- .get_mctrl = snp_get_mctrl,
- .stop_tx = snp_stop_tx,
- .start_tx = snp_start_tx,
- .stop_rx = snp_stop_rx,
- .break_ctl = snp_break_ctl,
- .startup = snp_startup,
- .shutdown = snp_shutdown,
- .set_termios = snp_set_termios,
- .pm = NULL,
- .type = snp_type,
- .release_port = snp_release_port,
- .request_port = snp_request_port,
- .config_port = snp_config_port,
- .verify_port = NULL,
-};
-
-/* End of uart struct functions and defines */
-
-#ifdef DEBUG
-
-/**
- * sn_debug_printf - close to hardware debugging printf
- * @fmt: printf format
- *
- * This is as "close to the metal" as we can get, used when the driver
- * itself may be broken.
- *
- */
-static int sn_debug_printf(const char *fmt, ...)
-{
- static char printk_buf[1024];
- int printed_len;
- va_list args;
-
- va_start(args, fmt);
- printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
-
- if (!sal_console_port.sc_ops) {
- sal_console_port.sc_ops = &poll_ops;
- early_sn_setup();
- }
- sal_console_port.sc_ops->sal_puts_raw(printk_buf, printed_len);
-
- va_end(args);
- return printed_len;
-}
-#endif /* DEBUG */
-
-/*
- * Interrupt handling routines.
- */
-
-/**
- * sn_receive_chars - Grab characters, pass them to tty layer
- * @port: Port to operate on
- * @flags: irq flags
- *
- * Note: If we're not registered with the serial core infrastructure yet,
- * we don't try to send characters to it...
- *
- */
-static void
-sn_receive_chars(struct sn_cons_port *port, unsigned long flags)
-{
- struct tty_port *tport = NULL;
- int ch;
-
- if (!port) {
- printk(KERN_ERR "sn_receive_chars - port NULL so can't receive\n");
- return;
- }
-
- if (!port->sc_ops) {
- printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receive\n");
- return;
- }
-
- if (port->sc_port.state) {
- /* The serial_core stuffs are initialized, use them */
- tport = &port->sc_port.state->port;
- }
-
- while (port->sc_ops->sal_input_pending()) {
- ch = port->sc_ops->sal_getc();
- if (ch < 0) {
- printk(KERN_ERR "sn_console: An error occurred while "
- "obtaining data from the console (0x%0x)\n", ch);
- break;
- }
-#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_requested) {
- unsigned long sysrq_timeout = sysrq_requested + HZ*5;
-
- sysrq_requested = 0;
- if (ch && time_before(jiffies, sysrq_timeout)) {
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- handle_sysrq(ch);
- spin_lock_irqsave(&port->sc_port.lock, flags);
- /* ignore actual sysrq command char */
- continue;
- }
- }
- if (ch == *sysrq_serial_ptr) {
- if (!(*++sysrq_serial_ptr)) {
- sysrq_requested = jiffies;
- sysrq_serial_ptr = sysrq_serial_str;
- }
- /*
- * ignore the whole sysrq string except for the
- * leading escape
- */
- if (ch != '\e')
- continue;
- }
- else
- sysrq_serial_ptr = sysrq_serial_str;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
- /* record the character to pass up to the tty layer */
- if (tport) {
- if (tty_insert_flip_char(tport, ch, TTY_NORMAL) == 0)
- break;
- }
- port->sc_port.icount.rx++;
- }
-
- if (tport)
- tty_flip_buffer_push(tport);
-}
-
-/**
- * sn_transmit_chars - grab characters from serial core, send off
- * @port: Port to operate on
- * @raw: Transmit raw or buffered
- *
- * Note: If we're early, before we're registered with serial core, the
- * writes are going through sn_sal_console_write because that's how
- * register_console has been set up. We currently could have asynch
- * polls calling this function due to sn_sal_switch_to_asynch but we can
- * ignore them until we register with the serial core stuffs.
- *
- */
-static void sn_transmit_chars(struct sn_cons_port *port, int raw)
-{
- int xmit_count, tail, head, loops, ii;
- int result;
- char *start;
- struct circ_buf *xmit;
-
- if (!port)
- return;
-
- BUG_ON(!port->sc_is_asynch);
-
- if (port->sc_port.state) {
- /* We're initialized, using serial core infrastructure */
- xmit = &port->sc_port.state->xmit;
- } else {
- /* Probably sn_sal_switch_to_asynch has been run but serial core isn't
- * initialized yet. Just return. Writes are going through
- * sn_sal_console_write (due to register_console) at this time.
- */
- return;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) {
- /* Nothing to do. */
- ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT);
- return;
- }
-
- head = xmit->head;
- tail = xmit->tail;
- start = &xmit->buf[tail];
-
- /* twice around gets the tail to the end of the buffer and
- * then to the head, if needed */
- loops = (head < tail) ? 2 : 1;
-
- for (ii = 0; ii < loops; ii++) {
- xmit_count = (head < tail) ?
- (UART_XMIT_SIZE - tail) : (head - tail);
-
- if (xmit_count > 0) {
- if (raw == TRANSMIT_RAW)
- result =
- port->sc_ops->sal_puts_raw(start,
- xmit_count);
- else
- result =
- port->sc_ops->sal_puts(start, xmit_count);
-#ifdef DEBUG
- if (!result)
- DPRINTF("`");
-#endif
- if (result > 0) {
- xmit_count -= result;
- port->sc_port.icount.tx += result;
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- xmit->tail = tail;
- start = &xmit->buf[tail];
- }
- }
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&port->sc_port);
-
- if (uart_circ_empty(xmit))
- snp_stop_tx(&port->sc_port); /* no-op for us */
-}
-
-/**
- * sn_sal_interrupt - Handle console interrupts
- * @irq: irq #, useful for debug statements
- * @dev_id: our pointer to our port (sn_cons_port which contains the uart port)
- *
- */
-static irqreturn_t sn_sal_interrupt(int irq, void *dev_id)
-{
- struct sn_cons_port *port = (struct sn_cons_port *)dev_id;
- unsigned long flags;
- int status = ia64_sn_console_intr_status();
-
- if (!port)
- return IRQ_NONE;
-
- spin_lock_irqsave(&port->sc_port.lock, flags);
- if (status & SAL_CONSOLE_INTR_RECV) {
- sn_receive_chars(port, flags);
- }
- if (status & SAL_CONSOLE_INTR_XMIT) {
- sn_transmit_chars(port, TRANSMIT_BUFFERED);
- }
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- return IRQ_HANDLED;
-}
-
-/**
- * sn_sal_timer_poll - this function handles polled console mode
- * @data: A pointer to our sn_cons_port (which contains the uart port)
- *
- * data is the pointer that init_timer will store for us. This function is
- * associated with init_timer to see if there is any console traffic.
- * Obviously not used in interrupt mode
- *
- */
-static void sn_sal_timer_poll(struct timer_list *t)
-{
- struct sn_cons_port *port = from_timer(port, t, sc_timer);
- unsigned long flags;
-
- if (!port)
- return;
-
- if (!port->sc_port.irq) {
- spin_lock_irqsave(&port->sc_port.lock, flags);
- if (sn_process_input)
- sn_receive_chars(port, flags);
- sn_transmit_chars(port, TRANSMIT_RAW);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- mod_timer(&port->sc_timer,
- jiffies + port->sc_interrupt_timeout);
- }
-}
-
-/*
- * Boot-time initialization code
- */
-
-/**
- * sn_sal_switch_to_asynch - Switch to async mode (as opposed to synch)
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * So this is used by sn_sal_serial_console_init (early on, before we're
- * registered with serial core). It's also used by sn_sal_init
- * right after we've registered with serial core. The later only happens
- * if we didn't already come through here via sn_sal_serial_console_init.
- *
- */
-static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
-{
- unsigned long flags;
-
- if (!port)
- return;
-
- DPRINTF("sn_console: about to switch to asynchronous console\n");
-
- /* without early_printk, we may be invoked late enough to race
- * with other cpus doing console IO at this point, however
- * console interrupts will never be enabled */
- spin_lock_irqsave(&port->sc_port.lock, flags);
-
- /* early_printk invocation may have done this for us */
- if (!port->sc_ops)
- port->sc_ops = &poll_ops;
-
- /* we can't turn on the console interrupt (as request_irq
- * calls kmalloc, which isn't set up yet), so we rely on a
- * timer to poll for input and push data from the console
- * buffer.
- */
- timer_setup(&port->sc_timer, sn_sal_timer_poll, 0);
-
- if (IS_RUNNING_ON_SIMULATOR())
- port->sc_interrupt_timeout = 6;
- else {
- /* 960cps / 16 char FIFO = 60HZ
- * HZ / (SN_SAL_FIFO_SPEED_CPS / SN_SAL_FIFO_DEPTH) */
- port->sc_interrupt_timeout =
- HZ * SN_SAL_UART_FIFO_DEPTH / SN_SAL_UART_FIFO_SPEED_CPS;
- }
- mod_timer(&port->sc_timer, jiffies + port->sc_interrupt_timeout);
-
- port->sc_is_asynch = 1;
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
-}
-
-/**
- * sn_sal_switch_to_interrupts - Switch to interrupt driven mode
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * In sn_sal_init, after we're registered with serial core and
- * the port is added, this function is called to switch us to interrupt
- * mode. We were previously in asynch/polling mode (using init_timer).
- *
- * We attempt to switch to interrupt mode here by calling
- * request_irq. If that works out, we enable receive interrupts.
- */
-static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
-{
- unsigned long flags;
-
- if (port) {
- DPRINTF("sn_console: switching to interrupt driven console\n");
-
- if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
- IRQF_SHARED,
- "SAL console driver", port) >= 0) {
- spin_lock_irqsave(&port->sc_port.lock, flags);
- port->sc_port.irq = SGI_UART_VECTOR;
- port->sc_ops = &intr_ops;
- irq_set_handler(port->sc_port.irq, handle_level_irq);
-
- /* turn on receive interrupts */
- ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- }
- else {
- printk(KERN_INFO
- "sn_console: console proceeding in polled mode\n");
- }
- }
-}
-
-/*
- * Kernel console definitions
- */
-
-static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int sn_sal_console_setup(struct console *, char *);
-static struct uart_driver sal_console_uart;
-extern struct tty_driver *uart_console_device(struct console *, int *);
-
-static struct console sal_console = {
- .name = DEVICE_NAME,
- .write = sn_sal_console_write,
- .device = uart_console_device,
- .setup = sn_sal_console_setup,
- .index = -1, /* unspecified */
- .data = &sal_console_uart,
-};
-
-#define SAL_CONSOLE &sal_console
-
-static struct uart_driver sal_console_uart = {
- .owner = THIS_MODULE,
- .driver_name = "sn_console",
- .dev_name = DEVICE_NAME,
- .major = 0, /* major/minor set at registration time per USE_DYNAMIC_MINOR */
- .minor = 0,
- .nr = 1, /* one port */
- .cons = SAL_CONSOLE,
-};
-
-/**
- * sn_sal_init - When the kernel loads us, get us rolling w/ serial core
- *
- * Before this is called, we've been printing kernel messages in a special
- * early mode not making use of the serial core infrastructure. When our
- * driver is loaded for real, we register the driver and port with serial
- * core and try to enable interrupt driven mode.
- *
- */
-static int __init sn_sal_init(void)
-{
- int retval;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- printk(KERN_INFO "sn_console: Console driver init\n");
-
- if (USE_DYNAMIC_MINOR == 1) {
- misc.minor = MISC_DYNAMIC_MINOR;
- misc.name = DEVICE_NAME_DYNAMIC;
- retval = misc_register(&misc);
- if (retval != 0) {
- printk(KERN_WARNING "Failed to register console "
- "device using misc_register.\n");
- return -ENODEV;
- }
- sal_console_uart.major = MISC_MAJOR;
- sal_console_uart.minor = misc.minor;
- } else {
- sal_console_uart.major = DEVICE_MAJOR;
- sal_console_uart.minor = DEVICE_MINOR;
- }
-
- /* We register the driver and the port before switching to interrupts
- * or async above so the proper uart structures are populated */
-
- if (uart_register_driver(&sal_console_uart) < 0) {
- printk
- ("ERROR sn_sal_init failed uart_register_driver, line %d\n",
- __LINE__);
- return -ENODEV;
- }
-
- spin_lock_init(&sal_console_port.sc_port.lock);
-
- /* Setup the port struct with the minimum needed */
- sal_console_port.sc_port.membase = (char *)1; /* just needs to be non-zero */
- sal_console_port.sc_port.type = PORT_16550A;
- sal_console_port.sc_port.fifosize = SN_SAL_MAX_CHARS;
- sal_console_port.sc_port.ops = &sn_console_ops;
- sal_console_port.sc_port.line = 0;
-
- if (uart_add_one_port(&sal_console_uart, &sal_console_port.sc_port) < 0) {
- /* error - not sure what I'd do - so I'll do nothing */
- printk(KERN_ERR "%s: unable to add port\n", __func__);
- }
-
- /* when this driver is compiled in, the console initialization
- * will have already switched us into asynchronous operation
- * before we get here through the initcalls */
- if (!sal_console_port.sc_is_asynch) {
- sn_sal_switch_to_asynch(&sal_console_port);
- }
-
- /* at this point (device_init) we can try to turn on interrupts */
- if (!IS_RUNNING_ON_SIMULATOR()) {
- sn_sal_switch_to_interrupts(&sal_console_port);
- }
- sn_process_input = 1;
- return 0;
-}
-device_initcall(sn_sal_init);
-
-/**
- * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
- * @puts_raw : puts function to do the writing
- * @s: input string
- * @count: length
- *
- * We need a \r ahead of every \n for direct writes through
- * ia64_sn_console_putb (what sal_puts_raw below actually does).
- *
- */
-
-static void puts_raw_fixed(int (*puts_raw) (const char *s, int len),
- const char *s, int count)
-{
- const char *s1;
-
- /* Output '\r' before each '\n' */
- while ((s1 = memchr(s, '\n', count)) != NULL) {
- puts_raw(s, s1 - s);
- puts_raw("\r\n", 2);
- count -= s1 + 1 - s;
- s = s1 + 1;
- }
- puts_raw(s, count);
-}
-
-/**
- * sn_sal_console_write - Print statements before serial core available
- * @console: Console to operate on - we ignore since we have just one
- * @s: String to send
- * @count: length
- *
- * This is referenced in the console struct. It is used for early
- * console printing before we register with serial core and for things
- * such as kdb. The console_lock must be held when we get here.
- *
- * This function has some code for trying to print output even if the lock
- * is held. We try to cover the case where a lock holder could have died.
- * We don't use this special case code if we're not registered with serial
- * core yet. After we're registered with serial core, the only time this
- * function would be used is for high level kernel output like magic sys req,
- * kdb, and printk's.
- */
-static void
-sn_sal_console_write(struct console *co, const char *s, unsigned count)
-{
- unsigned long flags = 0;
- struct sn_cons_port *port = &sal_console_port;
- static int stole_lock = 0;
-
- BUG_ON(!port->sc_is_asynch);
-
- /* We can't look at the xmit buffer if we're not registered with serial core
- * yet. So only do the fancy recovery after registering
- */
- if (!port->sc_port.state) {
- /* Not yet registered with serial core - simple case */
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- return;
- }
-
- /* somebody really wants this output, might be an
- * oops, kdb, panic, etc. make sure they get it. */
- if (!spin_trylock_irqsave(&port->sc_port.lock, flags)) {
- int lhead = port->sc_port.state->xmit.head;
- int ltail = port->sc_port.state->xmit.tail;
- int counter, got_lock = 0;
-
- /*
- * We attempt to determine if someone has died with the
- * lock. We wait ~20 secs after the head and tail ptrs
- * stop moving and assume the lock holder is not functional
- * and plow ahead. If the lock is freed within the time out
- * period we re-get the lock and go ahead normally. We also
- * remember if we have plowed ahead so that we don't have
- * to wait out the time out period again - the asumption
- * is that we will time out again.
- */
-
- for (counter = 0; counter < 150; mdelay(125), counter++) {
- if (stole_lock)
- break;
-
- if (spin_trylock_irqsave(&port->sc_port.lock, flags)) {
- got_lock = 1;
- break;
- } else {
- /* still locked */
- if ((lhead != port->sc_port.state->xmit.head)
- || (ltail !=
- port->sc_port.state->xmit.tail)) {
- lhead =
- port->sc_port.state->xmit.head;
- ltail =
- port->sc_port.state->xmit.tail;
- counter = 0;
- }
- }
- }
- /* flush anything in the serial core xmit buffer, raw */
- sn_transmit_chars(port, 1);
- if (got_lock) {
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- stole_lock = 0;
- } else {
- /* fell thru */
- stole_lock = 1;
- }
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- } else {
- stole_lock = 0;
- sn_transmit_chars(port, 1);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- }
-}
-
-
-/**
- * sn_sal_console_setup - Set up console for early printing
- * @co: Console to work with
- * @options: Options to set
- *
- * Altix console doesn't do anything with baud rates, etc, anyway.
- *
- * This isn't required since not providing the setup function in the
- * console struct is ok. However, other patches like KDB plop something
- * here so providing it is easier.
- *
- */
-static int sn_sal_console_setup(struct console *co, char *options)
-{
- return 0;
-}
-
-/**
- * sn_sal_console_write_early - simple early output routine
- * @co - console struct
- * @s - string to print
- * @count - count
- *
- * Simple function to provide early output, before even
- * sn_sal_serial_console_init is called. Referenced in the
- * console struct registerd in sn_serial_console_early_setup.
- *
- */
-static void __init
-sn_sal_console_write_early(struct console *co, const char *s, unsigned count)
-{
- puts_raw_fixed(sal_console_port.sc_ops->sal_puts_raw, s, count);
-}
-
-/* Used for very early console printing - again, before
- * sn_sal_serial_console_init is run */
-static struct console sal_console_early __initdata = {
- .name = "sn_sal",
- .write = sn_sal_console_write_early,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/**
- * sn_serial_console_early_setup - Sets up early console output support
- *
- * Register a console early on... This is for output before even
- * sn_sal_serial_cosnole_init is called. This function is called from
- * setup.c. This allows us to do really early polled writes. When
- * sn_sal_serial_console_init is called, this console is unregistered
- * and a new one registered.
- */
-int __init sn_serial_console_early_setup(void)
-{
- if (!ia64_platform_is("sn2"))
- return -1;
-
- sal_console_port.sc_ops = &poll_ops;
- spin_lock_init(&sal_console_port.sc_port.lock);
- early_sn_setup(); /* Find SAL entry points */
- register_console(&sal_console_early);
-
- return 0;
-}
-
-/**
- * sn_sal_serial_console_init - Early console output - set up for register
- *
- * This function is called when regular console init happens. Because we
- * support even earlier console output with sn_serial_console_early_setup
- * (called from setup.c directly), this function unregisters the really
- * early console.
- *
- * Note: Even if setup.c doesn't register sal_console_early, unregistering
- * it here doesn't hurt anything.
- *
- */
-static int __init sn_sal_serial_console_init(void)
-{
- if (ia64_platform_is("sn2")) {
- sn_sal_switch_to_asynch(&sal_console_port);
- DPRINTF("sn_sal_serial_console_init : register console\n");
- register_console(&sal_console);
- unregister_console(&sal_console_early);
- }
- return 0;
-}
-
-console_initcall(sn_sal_serial_console_init);
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index 717292c1c0df..60ff236a3d63 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -93,8 +93,7 @@ static void __ldsem_wake_readers(struct ld_semaphore *sem)
list_for_each_entry_safe(waiter, next, &sem->read_wait, list) {
tsk = waiter->task;
- smp_mb();
- waiter->task = NULL;
+ smp_store_release(&waiter->task, NULL);
wake_up_process(tsk);
put_task_struct(tsk);
}
@@ -194,7 +193,7 @@ down_read_failed(struct ld_semaphore *sem, long count, long timeout)
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (!waiter.task)
+ if (!smp_load_acquire(&waiter.task))
break;
if (!timeout)
break;
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index ec92f36ab5c4..34aa39d1aed9 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3771,7 +3771,11 @@ static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct con_driver *con = dev_get_drvdata(dev);
- int bind = con_is_bound(con->con);
+ int bind;
+
+ console_lock();
+ bind = con_is_bound(con->con);
+ console_unlock();
return snprintf(buf, PAGE_SIZE, "%i\n", bind);
}
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index b5abfe89190c..df8812c30640 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -454,9 +454,11 @@ err_clk:
imx_disable_unprepare_clks(dev);
disable_hsic_regulator:
if (data->hsic_pad_regulator)
- ret = regulator_disable(data->hsic_pad_regulator);
+ /* don't overwrite original ret (cf. EPROBE_DEFER) */
+ regulator_disable(data->hsic_pad_regulator);
if (pdata.flags & CI_HDRC_PMQOS)
pm_qos_remove_request(&data->pm_qos_req);
+ data->ci_pdev = NULL;
return ret;
}
@@ -469,14 +471,17 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
}
- ci_hdrc_remove_device(data->ci_pdev);
+ if (data->ci_pdev)
+ ci_hdrc_remove_device(data->ci_pdev);
if (data->override_phy_control)
usb_phy_shutdown(data->phy);
- imx_disable_unprepare_clks(&pdev->dev);
- if (data->plat_data->flags & CI_HDRC_PMQOS)
- pm_qos_remove_request(&data->pm_qos_req);
- if (data->hsic_pad_regulator)
- regulator_disable(data->hsic_pad_regulator);
+ if (data->ci_pdev) {
+ imx_disable_unprepare_clks(&pdev->dev);
+ if (data->plat_data->flags & CI_HDRC_PMQOS)
+ pm_qos_remove_request(&data->pm_qos_req);
+ if (data->hsic_pad_regulator)
+ regulator_disable(data->hsic_pad_regulator);
+ }
return 0;
}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 6a5ee8e6da10..67ad40b0a05b 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -709,12 +709,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
unsigned long flags;
- spin_lock_irqsave(&ci->lock, flags);
- ci->gadget.speed = USB_SPEED_UNKNOWN;
- ci->remote_wakeup = 0;
- ci->suspended = 0;
- spin_unlock_irqrestore(&ci->lock, flags);
-
/* flush all endpoints */
gadget_for_each_ep(ep, gadget) {
usb_ep_fifo_flush(ep);
@@ -732,6 +726,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
ci->status = NULL;
}
+ spin_lock_irqsave(&ci->lock, flags);
+ ci->gadget.speed = USB_SPEED_UNKNOWN;
+ ci->remote_wakeup = 0;
+ ci->suspended = 0;
+ spin_unlock_irqrestore(&ci->lock, flags);
+
return 0;
}
@@ -1303,6 +1303,10 @@ static int ep_disable(struct usb_ep *ep)
return -EBUSY;
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return 0;
+ }
/* only internal SW should disable ctrl endpts */
@@ -1392,6 +1396,10 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EINVAL;
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return 0;
+ }
retval = _ep_queue(ep, req, gfp_flags);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
@@ -1415,8 +1423,8 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
return -EINVAL;
spin_lock_irqsave(hwep->lock, flags);
-
- hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
+ if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN)
+ hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
dma_pool_free(hwep->td_pool, node->ptr, node->dma);
@@ -1487,6 +1495,10 @@ static void ep_fifo_flush(struct usb_ep *ep)
}
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return;
+ }
hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
@@ -1559,6 +1571,10 @@ static int ci_udc_wakeup(struct usb_gadget *_gadget)
int ret = 0;
spin_lock_irqsave(&ci->lock, flags);
+ if (ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(&ci->lock, flags);
+ return 0;
+ }
if (!ci->remote_wakeup) {
ret = -EOPNOTSUPP;
goto out;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 183b41753c98..62f4fb9b362f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1301,10 +1301,6 @@ made_compressed_probe:
tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops;
- minor = acm_alloc_minor(acm);
- if (minor < 0)
- goto alloc_fail1;
-
ctrlsize = usb_endpoint_maxp(epctrl);
readsize = usb_endpoint_maxp(epread) *
(quirks == SINGLE_RX_URB ? 1 : 2);
@@ -1312,6 +1308,13 @@ made_compressed_probe:
acm->writesize = usb_endpoint_maxp(epwrite) * 20;
acm->control = control_interface;
acm->data = data_interface;
+
+ usb_get_intf(acm->control); /* undone in destruct() */
+
+ minor = acm_alloc_minor(acm);
+ if (minor < 0)
+ goto alloc_fail1;
+
acm->minor = minor;
acm->dev = usb_dev;
if (h.usb_cdc_acm_descriptor)
@@ -1458,7 +1461,6 @@ skip_countries:
usb_driver_claim_interface(&acm_driver, data_interface, acm);
usb_set_intfdata(data_interface, acm);
- usb_get_intf(control_interface);
tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
&control_interface->dev);
if (IS_ERR(tty_dev)) {
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index a7824a51f86d..70afb2ca1eab 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -587,10 +587,20 @@ static int wdm_flush(struct file *file, fl_owner_t id)
{
struct wdm_device *desc = file->private_data;
- wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
+ wait_event(desc->wait,
+ /*
+ * needs both flags. We cannot do with one
+ * because resetting it would cause a race
+ * with write() yet we need to signal
+ * a disconnect
+ */
+ !test_bit(WDM_IN_USE, &desc->flags) ||
+ test_bit(WDM_DISCONNECTING, &desc->flags));
/* cannot dereference desc->intf if WDM_DISCONNECTING */
- if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags))
+ if (test_bit(WDM_DISCONNECTING, &desc->flags))
+ return -ENODEV;
+ if (desc->werr < 0)
dev_err(&desc->intf->dev, "Error in flush path: %d\n",
desc->werr);
@@ -974,8 +984,6 @@ static void wdm_disconnect(struct usb_interface *intf)
spin_lock_irqsave(&desc->iuspin, flags);
set_bit(WDM_DISCONNECTING, &desc->flags);
set_bit(WDM_READ, &desc->flags);
- /* to terminate pending flushes */
- clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
wake_up_all(&desc->wait);
mutex_lock(&desc->rlock);
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 4942122b2346..36858ddd8d9b 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -2362,8 +2362,11 @@ static int usbtmc_probe(struct usb_interface *intf,
goto err_put;
}
+ retcode = -EINVAL;
data->bulk_in = bulk_in->bEndpointAddress;
data->wMaxPacketSize = usb_endpoint_maxp(bulk_in);
+ if (!data->wMaxPacketSize)
+ goto err_put;
dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in);
data->bulk_out = bulk_out->bEndpointAddress;
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 1359b78a624e..6cf22c27f2d2 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -66,9 +66,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
char name[16];
int i, size;
- if (!IS_ENABLED(CONFIG_HAS_DMA) ||
- (!is_device_dma_capable(hcd->self.sysdev) &&
- !hcd->localmem_pool))
+ if (hcd->localmem_pool || !hcd_uses_dma(hcd))
return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
@@ -129,8 +127,7 @@ void *hcd_buffer_alloc(
return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
/* some USB hosts just use PIO */
- if (!IS_ENABLED(CONFIG_HAS_DMA) ||
- !is_device_dma_capable(bus->sysdev)) {
+ if (!hcd_uses_dma(hcd)) {
*dma = ~(dma_addr_t) 0;
return kmalloc(size, mem_flags);
}
@@ -160,8 +157,7 @@ void hcd_buffer_free(
return;
}
- if (!IS_ENABLED(CONFIG_HAS_DMA) ||
- !is_device_dma_capable(bus->sysdev)) {
+ if (!hcd_uses_dma(hcd)) {
kfree(addr);
return;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index b265ab5405f9..9063ede411ae 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
return 0;
error:
- if (as && as->usbm)
- dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count);
kfree(isopkt);
kfree(dr);
if (as)
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 65de6f73b672..558890ada0e5 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -193,9 +193,10 @@ int usb_register_dev(struct usb_interface *intf,
intf->minor = minor;
break;
}
- up_write(&minor_rwsem);
- if (intf->minor < 0)
+ if (intf->minor < 0) {
+ up_write(&minor_rwsem);
return -EXFULL;
+ }
/* create a usb class device for this usb interface */
snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -203,12 +204,11 @@ int usb_register_dev(struct usb_interface *intf,
MKDEV(USB_MAJOR, minor), class_driver,
"%s", kbasename(name));
if (IS_ERR(intf->usb_dev)) {
- down_write(&minor_rwsem);
usb_minors[minor] = NULL;
intf->minor = -1;
- up_write(&minor_rwsem);
retval = PTR_ERR(intf->usb_dev);
}
+ up_write(&minor_rwsem);
return retval;
}
EXPORT_SYMBOL_GPL(usb_register_dev);
@@ -234,12 +234,12 @@ void usb_deregister_dev(struct usb_interface *intf,
return;
dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
+ device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
up_write(&minor_rwsem);
- device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
intf->usb_dev = NULL;
intf->minor = -1;
destroy_usb_class();
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 03432467b05f..7537681355f6 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -216,17 +216,18 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* EHCI, OHCI */
hcd->rsrc_start = pci_resource_start(dev, 0);
hcd->rsrc_len = pci_resource_len(dev, 0);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description)) {
+ if (!devm_request_mem_region(&dev->dev, hcd->rsrc_start,
+ hcd->rsrc_len, driver->description)) {
dev_dbg(&dev->dev, "controller already in use\n");
retval = -EBUSY;
goto put_hcd;
}
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start,
+ hcd->rsrc_len);
if (hcd->regs == NULL) {
dev_dbg(&dev->dev, "error mapping memory\n");
retval = -EFAULT;
- goto release_mem_region;
+ goto put_hcd;
}
} else {
@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
hcd->rsrc_start = pci_resource_start(dev, region);
hcd->rsrc_len = pci_resource_len(dev, region);
- if (request_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description))
+ if (devm_request_region(&dev->dev, hcd->rsrc_start,
+ hcd->rsrc_len, driver->description))
break;
}
if (region == PCI_ROM_RESOURCE) {
@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
}
if (retval != 0)
- goto unmap_registers;
+ goto put_hcd;
device_wakeup_enable(hcd->self.controller);
if (pci_dev_run_wake(dev))
pm_runtime_put_noidle(&dev->dev);
return retval;
-unmap_registers:
- if (driver->flags & HCD_MEMORY) {
- iounmap(hcd->regs);
-release_mem_region:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- } else
- release_region(hcd->rsrc_start, hcd->rsrc_len);
put_hcd:
usb_put_hcd(hcd);
disable_pci:
@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
dev_set_drvdata(&dev->dev, NULL);
up_read(&companions_rwsem);
}
-
- if (hcd->driver->flags & HCD_MEMORY) {
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- } else {
- release_region(hcd->rsrc_start, hcd->rsrc_len);
- }
-
usb_put_hcd(hcd);
pci_disable_device(dev);
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 88533938ce19..8592c0344fe8 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
/* wait queue for synchronous unlinks */
DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
-static inline int is_root_hub(struct usb_device *udev)
-{
- return (udev->parent == NULL);
-}
-
/*-------------------------------------------------------------------------*/
/*
@@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
}
-
-/*
- * Show & store the current value of authorized_default
- */
-static ssize_t authorized_default_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct usb_device *rh_usb_dev = to_usb_device(dev);
- struct usb_bus *usb_bus = rh_usb_dev->bus;
- struct usb_hcd *hcd;
-
- hcd = bus_to_hcd(usb_bus);
- return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
-}
-
-static ssize_t authorized_default_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- ssize_t result;
- unsigned val;
- struct usb_device *rh_usb_dev = to_usb_device(dev);
- struct usb_bus *usb_bus = rh_usb_dev->bus;
- struct usb_hcd *hcd;
-
- hcd = bus_to_hcd(usb_bus);
- result = sscanf(buf, "%u\n", &val);
- if (result == 1) {
- hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
- val : USB_DEVICE_AUTHORIZE_ALL;
- result = size;
- } else {
- result = -EINVAL;
- }
- return result;
-}
-static DEVICE_ATTR_RW(authorized_default);
-
-/*
- * interface_authorized_default_show - show default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- * for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct usb_device *usb_dev = to_usb_device(dev);
- struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
-
- return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
-}
-
-/*
- * interface_authorized_default_store - store default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- * for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct usb_device *usb_dev = to_usb_device(dev);
- struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
- int rc = count;
- bool val;
-
- if (strtobool(buf, &val) != 0)
- return -EINVAL;
-
- if (val)
- set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
- else
- clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
-
- return rc;
-}
-static DEVICE_ATTR_RW(interface_authorized_default);
-
-/* Group all the USB bus attributes */
-static struct attribute *usb_bus_attrs[] = {
- &dev_attr_authorized_default.attr,
- &dev_attr_interface_authorized_default.attr,
- NULL,
-};
-
-static const struct attribute_group usb_bus_attr_group = {
- .name = NULL, /* we want them in the same directory */
- .attrs = usb_bus_attrs,
-};
-
-
-
/*-------------------------------------------------------------------------*/
/**
@@ -1512,7 +1412,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_pio_for_control)
return ret;
- if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+ if (hcd_uses_dma(hcd)) {
if (is_vmalloc_addr(urb->setup_packet)) {
WARN_ONCE(1, "setup packet is not dma capable\n");
return -EAGAIN;
@@ -1546,7 +1446,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
- if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+ if (hcd_uses_dma(hcd)) {
if (urb->num_sgs) {
int n;
@@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
if (retval != 0)
goto err_register_root_hub;
- retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
- if (retval < 0) {
- printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
- retval);
- goto error_create_attr_group;
- }
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
usb_hcd_poll_rh_status(hcd);
return retval;
-error_create_attr_group:
- clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
- if (HC_IS_RUNNING(hcd->state))
- hcd->state = HC_STATE_QUIESCING;
- spin_lock_irq(&hcd_root_hub_lock);
- hcd->rh_registered = 0;
- spin_unlock_irq(&hcd_root_hub_lock);
-
-#ifdef CONFIG_PM
- cancel_work_sync(&hcd->wakeup_work);
-#endif
- cancel_work_sync(&hcd->died_work);
- mutex_lock(&usb_bus_idr_lock);
- usb_disconnect(&rhdev); /* Sets rhdev to NULL */
- mutex_unlock(&usb_bus_idr_lock);
err_register_root_hub:
hcd->rh_pollable = 0;
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
usb_get_dev(rhdev);
- sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
-
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING (hcd->state))
hcd->state = HC_STATE_QUIESCING;
@@ -3052,8 +2929,8 @@ int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
local_mem = devm_memremap(hcd->self.sysdev, phys_addr,
size, MEMREMAP_WC);
- if (!local_mem)
- return -ENOMEM;
+ if (IS_ERR(local_mem))
+ return PTR_ERR(local_mem);
/*
* Here we pass a dma_addr_t but the arg type is a phys_addr_t.
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e844bb7b5676..5adf489428aa 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -2218,14 +2218,14 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
(struct usb_cdc_dmm_desc *)buffer;
break;
case USB_CDC_MDLM_TYPE:
- if (elength < sizeof(struct usb_cdc_mdlm_desc *))
+ if (elength < sizeof(struct usb_cdc_mdlm_desc))
goto next_desc;
if (desc)
return -EINVAL;
desc = (struct usb_cdc_mdlm_desc *)buffer;
break;
case USB_CDC_MDLM_DETAIL_TYPE:
- if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *))
+ if (elength < sizeof(struct usb_cdc_mdlm_detail_desc))
goto next_desc;
if (detail)
return -EINVAL;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 7e88fdfe3cf5..f19694e69f5c 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/of.h>
#include "usb.h"
@@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = {
.size = 18 + 65535, /* dev descr + max-size raw descriptor */
};
+/*
+ * Show & store the current value of authorized_default
+ */
+static ssize_t authorized_default_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_device *rh_usb_dev = to_usb_device(dev);
+ struct usb_bus *usb_bus = rh_usb_dev->bus;
+ struct usb_hcd *hcd;
+
+ hcd = bus_to_hcd(usb_bus);
+ return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
+}
+
+static ssize_t authorized_default_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ ssize_t result;
+ unsigned int val;
+ struct usb_device *rh_usb_dev = to_usb_device(dev);
+ struct usb_bus *usb_bus = rh_usb_dev->bus;
+ struct usb_hcd *hcd;
+
+ hcd = bus_to_hcd(usb_bus);
+ result = sscanf(buf, "%u\n", &val);
+ if (result == 1) {
+ hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
+ val : USB_DEVICE_AUTHORIZE_ALL;
+ result = size;
+ } else {
+ result = -EINVAL;
+ }
+ return result;
+}
+static DEVICE_ATTR_RW(authorized_default);
+
+/*
+ * interface_authorized_default_show - show default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ * for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_device *usb_dev = to_usb_device(dev);
+ struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+
+ return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
+}
+
+/*
+ * interface_authorized_default_store - store default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ * for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_device *usb_dev = to_usb_device(dev);
+ struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+ int rc = count;
+ bool val;
+
+ if (strtobool(buf, &val) != 0)
+ return -EINVAL;
+
+ if (val)
+ set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+ else
+ clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
+ return rc;
+}
+static DEVICE_ATTR_RW(interface_authorized_default);
+
+/* Group all the USB bus attributes */
+static struct attribute *usb_bus_attrs[] = {
+ &dev_attr_authorized_default.attr,
+ &dev_attr_interface_authorized_default.attr,
+ NULL,
+};
+
+static const struct attribute_group usb_bus_attr_group = {
+ .name = NULL, /* we want them in the same directory */
+ .attrs = usb_bus_attrs,
+};
+
+
+static int add_default_authorized_attributes(struct device *dev)
+{
+ int rc = 0;
+
+ if (is_usb_device(dev))
+ rc = sysfs_create_group(&dev->kobj, &usb_bus_attr_group);
+
+ return rc;
+}
+
+static void remove_default_authorized_attributes(struct device *dev)
+{
+ if (is_usb_device(dev)) {
+ sysfs_remove_group(&dev->kobj, &usb_bus_attr_group);
+ }
+}
+
int usb_create_sysfs_dev_files(struct usb_device *udev)
{
struct device *dev = &udev->dev;
@@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
retval = add_power_attributes(dev);
if (retval)
goto error;
+
+ if (is_root_hub(udev)) {
+ retval = add_default_authorized_attributes(dev);
+ if (retval)
+ goto error;
+ }
return retval;
+
error:
usb_remove_sysfs_dev_files(udev);
return retval;
@@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
{
struct device *dev = &udev->dev;
+ if (is_root_hub(udev))
+ remove_default_authorized_attributes(dev);
+
remove_power_attributes(dev);
remove_persist_attributes(dev);
device_remove_bin_file(dev, &dev_bin_attr_descriptors);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index bd8d01f85a13..0c9fde5ad052 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev)
return dev->type == &usb_port_device_type;
}
+static inline int is_root_hub(struct usb_device *udev)
+{
+ return (udev->parent == NULL);
+}
+
/* Do the same for device drivers and interface drivers. */
static inline int is_usb_device_driver(struct device_driver *drv)
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index ee144ff8af5b..111787a137ee 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4608,7 +4608,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
buf = urb->transfer_buffer;
- if (hcd->self.uses_dma) {
+ if (hcd_uses_dma(hcd)) {
if (!buf && (urb->transfer_dma & 3)) {
dev_err(hsotg->dev,
"%s: unaligned transfer with no transfer_buffer",
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 9118b42c70b6..76883ff4f5bb 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1976,6 +1976,7 @@ void composite_disconnect(struct usb_gadget *gadget)
* disconnect callbacks?
*/
spin_lock_irqsave(&cdev->lock, flags);
+ cdev->suspended = 0;
if (cdev->config)
reset_config(cdev);
if (cdev->driver->disconnect)
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 29cc5693e05c..7c96c4665178 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -261,7 +261,7 @@ struct fsg_common;
struct fsg_common {
struct usb_gadget *gadget;
struct usb_composite_dev *cdev;
- struct fsg_dev *fsg, *new_fsg;
+ struct fsg_dev *fsg;
wait_queue_head_t io_wait;
wait_queue_head_t fsg_wait;
@@ -290,6 +290,7 @@ struct fsg_common {
unsigned int bulk_out_maxpacket;
enum fsg_state state; /* For exception handling */
unsigned int exception_req_tag;
+ void *exception_arg;
enum data_direction data_dir;
u32 data_size;
@@ -391,7 +392,8 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
/* These routines may be called in process context or in_irq */
-static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+static void __raise_exception(struct fsg_common *common, enum fsg_state new_state,
+ void *arg)
{
unsigned long flags;
@@ -404,6 +406,7 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
if (common->state <= new_state) {
common->exception_req_tag = common->ep0_req_tag;
common->state = new_state;
+ common->exception_arg = arg;
if (common->thread_task)
send_sig_info(SIGUSR1, SEND_SIG_PRIV,
common->thread_task);
@@ -411,6 +414,10 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
spin_unlock_irqrestore(&common->lock, flags);
}
+static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+{
+ __raise_exception(common, new_state, NULL);
+}
/*-------------------------------------------------------------------------*/
@@ -2285,16 +2292,16 @@ reset:
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->new_fsg = fsg;
- raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+ __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg);
return USB_GADGET_DELAYED_STATUS;
}
static void fsg_disable(struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->new_fsg = NULL;
- raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+ __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
}
@@ -2307,6 +2314,7 @@ static void handle_exception(struct fsg_common *common)
enum fsg_state old_state;
struct fsg_lun *curlun;
unsigned int exception_req_tag;
+ struct fsg_dev *new_fsg;
/*
* Clear the existing signals. Anything but SIGUSR1 is converted
@@ -2360,6 +2368,7 @@ static void handle_exception(struct fsg_common *common)
common->next_buffhd_to_fill = &common->buffhds[0];
common->next_buffhd_to_drain = &common->buffhds[0];
exception_req_tag = common->exception_req_tag;
+ new_fsg = common->exception_arg;
old_state = common->state;
common->state = FSG_STATE_NORMAL;
@@ -2413,8 +2422,8 @@ static void handle_exception(struct fsg_common *common)
break;
case FSG_STATE_CONFIG_CHANGE:
- do_set_interface(common, common->new_fsg);
- if (common->new_fsg)
+ do_set_interface(common, new_fsg);
+ if (new_fsg)
usb_composite_setup_continue(common->cdev);
break;
@@ -2989,8 +2998,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(fsg, "unbind\n");
if (fsg->common->fsg == fsg) {
- fsg->common->new_fsg = NULL;
- raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+ __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
/* FIXME: make interruptible or killable somehow? */
wait_event(common->fsg_wait, common->fsg != fsg);
}
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index ef0259a950ba..d7e611645533 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -45,7 +45,8 @@ config USB_AT91
config USB_LPC32XX
tristate "LPC32XX USB Peripheral Controller"
- depends on ARCH_LPC32XX && I2C
+ depends on ARCH_LPC32XX
+ depends on I2C
select USB_ISP1301
help
This option selects the USB device controller in the LPC32xx SoC.
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 5f1b14f3e5a0..c65aed3e84c7 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/prefetch.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/usb/ch9.h>
@@ -35,8 +36,6 @@
#include <linux/seq_file.h>
#endif
-#include <mach/hardware.h>
-
/*
* USB device configuration structure
*/
@@ -2265,7 +2264,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
default:
break;
}
-
+ break;
case USB_REQ_SET_ADDRESS:
if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 87062d22134d..1f4c3fbd1df8 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -19,6 +19,7 @@
#include <linux/pm_runtime.h>
#include <linux/sizes.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/sys_soc.h>
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
@@ -2450,9 +2451,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
if (usb3->forced_b_device)
return -EBUSY;
- if (!strncmp(buf, "host", strlen("host")))
+ if (sysfs_streq(buf, "host"))
new_mode_is_host = true;
- else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+ else if (sysfs_streq(buf, "peripheral"))
new_mode_is_host = false;
else
return -EINVAL;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 40b5de597112..73d233d3bf4d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -441,7 +441,8 @@ config USB_OHCI_HCD_S3C2410
config USB_OHCI_HCD_LPC32XX
tristate "Support for LPC on-chip OHCI USB controller"
- depends on USB_OHCI_HCD && ARCH_LPC32XX
+ depends on USB_OHCI_HCD
+ depends on ARCH_LPC32XX || COMPILE_TEST
depends on USB_ISP1301
default y
---help---
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index fe9422d3bcdc..b0882c13a1d1 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -149,7 +149,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
break;
case PCI_VENDOR_ID_AMD:
/* AMD PLL quirk */
- if (usb_amd_find_chipset_info())
+ if (usb_amd_quirk_pll_check())
ehci->amd_pll_fix = 1;
/* AMD8111 EHCI doesn't work, according to AMD errata */
if (pdev->device == 0x7463) {
@@ -186,7 +186,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
break;
case PCI_VENDOR_ID_ATI:
/* AMD PLL quirk */
- if (usb_amd_find_chipset_info())
+ if (usb_amd_quirk_pll_check())
ehci->amd_pll_fix = 1;
/*
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 77cc36efae95..0dbfa5c10703 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -1629,6 +1629,10 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* see what we found out */
temp = check_reset_complete(fotg210, wIndex, status_reg,
fotg210_readl(fotg210, status_reg));
+
+ /* restart schedule */
+ fotg210->command |= CMD_RUN;
+ fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
}
if (!(temp & (PORT_RESUME|PORT_RESET))) {
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 09a8ebd95588..6968b9f2b76b 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -159,7 +159,7 @@ out:
return result;
error_set_cluster_id:
- wusb_cluster_id_put(wusbhc->cluster_id);
+ wusb_cluster_id_put(addr);
error_cluster_id_get:
goto out;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index b457fdaff297..1fe3deec35cf 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -419,8 +419,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
* other cases where the next software may expect clean state from the
* "firmware". this is bus-neutral, unlike shutdown() methods.
*/
-static void
-ohci_shutdown (struct usb_hcd *hcd)
+static void _ohci_shutdown(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci;
@@ -436,6 +435,16 @@ ohci_shutdown (struct usb_hcd *hcd)
ohci->rh_state = OHCI_RH_HALTED;
}
+static void ohci_shutdown(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ohci->lock, flags);
+ _ohci_shutdown(hcd);
+ spin_unlock_irqrestore(&ohci->lock, flags);
+}
+
/*-------------------------------------------------------------------------*
* HC functions
*-------------------------------------------------------------------------*/
@@ -760,7 +769,7 @@ static void io_watchdog_func(struct timer_list *t)
died:
usb_hc_died(ohci_to_hcd(ohci));
ohci_dump(ohci);
- ohci_shutdown(ohci_to_hcd(ohci));
+ _ohci_shutdown(ohci_to_hcd(ohci));
goto done;
} else {
/* No write back because the done queue was empty */
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index f5f532601092..c561881d0e79 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -29,10 +29,7 @@
#include "ohci.h"
-#include <mach/hardware.h>
-
#define USB_CONFIG_BASE 0x31020000
-#define USB_OTG_STAT_CONTROL IO_ADDRESS(USB_CONFIG_BASE + 0x110)
/* USB_OTG_STAT_CONTROL bit defines */
#define TRANSPARENT_I2C_EN (1 << 7)
@@ -122,19 +119,33 @@ static inline void isp1301_vbus_off(void)
static void ohci_nxp_start_hc(void)
{
- unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
+ void __iomem *usb_otg_stat_control = ioremap(USB_CONFIG_BASE + 0x110, 4);
+ unsigned long tmp;
+
+ if (WARN_ON(!usb_otg_stat_control))
+ return;
+
+ tmp = __raw_readl(usb_otg_stat_control) | HOST_EN;
- __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+ __raw_writel(tmp, usb_otg_stat_control);
isp1301_vbus_on();
+
+ iounmap(usb_otg_stat_control);
}
static void ohci_nxp_stop_hc(void)
{
+ void __iomem *usb_otg_stat_control = ioremap(USB_CONFIG_BASE + 0x110, 4);
unsigned long tmp;
+ if (WARN_ON(!usb_otg_stat_control))
+ return;
+
isp1301_vbus_off();
- tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
- __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+ tmp = __raw_readl(usb_otg_stat_control) & ~HOST_EN;
+ __raw_writel(tmp, usb_otg_stat_control);
+
+ iounmap(usb_otg_stat_control);
}
static int ohci_hcd_nxp_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index a033f7d855e0..f4e13a3fddee 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -152,7 +152,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- if (usb_amd_find_chipset_info())
+ if (usb_amd_quirk_pll_check())
ohci->flags |= OHCI_QUIRK_AMD_PLL;
/* SB800 needs pre-fetch fix */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 3ce71cbfbb58..f6d04491df60 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -132,7 +132,7 @@ static struct amd_chipset_info {
struct amd_chipset_type sb_type;
int isoc_reqs;
int probe_count;
- int probe_result;
+ bool need_pll_quirk;
} amd_chipset;
static DEFINE_SPINLOCK(amd_lock);
@@ -201,11 +201,11 @@ void sb800_prefetch(struct device *dev, int on)
}
EXPORT_SYMBOL_GPL(sb800_prefetch);
-int usb_amd_find_chipset_info(void)
+static void usb_amd_find_chipset_info(void)
{
unsigned long flags;
struct amd_chipset_info info;
- int ret;
+ info.need_pll_quirk = 0;
spin_lock_irqsave(&amd_lock, flags);
@@ -213,27 +213,34 @@ int usb_amd_find_chipset_info(void)
if (amd_chipset.probe_count > 0) {
amd_chipset.probe_count++;
spin_unlock_irqrestore(&amd_lock, flags);
- return amd_chipset.probe_result;
+ return;
}
memset(&info, 0, sizeof(info));
spin_unlock_irqrestore(&amd_lock, flags);
if (!amd_chipset_sb_type_init(&info)) {
- ret = 0;
goto commit;
}
- /* Below chipset generations needn't enable AMD PLL quirk */
- if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN ||
- info.sb_type.gen == AMD_CHIPSET_SB600 ||
- info.sb_type.gen == AMD_CHIPSET_YANGTZE ||
- (info.sb_type.gen == AMD_CHIPSET_SB700 &&
- info.sb_type.rev > 0x3b)) {
+ switch (info.sb_type.gen) {
+ case AMD_CHIPSET_SB700:
+ info.need_pll_quirk = info.sb_type.rev <= 0x3B;
+ break;
+ case AMD_CHIPSET_SB800:
+ case AMD_CHIPSET_HUDSON2:
+ case AMD_CHIPSET_BOLTON:
+ info.need_pll_quirk = 1;
+ break;
+ default:
+ info.need_pll_quirk = 0;
+ break;
+ }
+
+ if (!info.need_pll_quirk) {
if (info.smbus_dev) {
pci_dev_put(info.smbus_dev);
info.smbus_dev = NULL;
}
- ret = 0;
goto commit;
}
@@ -252,7 +259,6 @@ int usb_amd_find_chipset_info(void)
}
}
- ret = info.probe_result = 1;
printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
commit:
@@ -263,7 +269,6 @@ commit:
/* Mark that we where here */
amd_chipset.probe_count++;
- ret = amd_chipset.probe_result;
spin_unlock_irqrestore(&amd_lock, flags);
@@ -276,10 +281,7 @@ commit:
amd_chipset = info;
spin_unlock_irqrestore(&amd_lock, flags);
}
-
- return ret;
}
-EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev)
{
@@ -315,6 +317,13 @@ bool usb_amd_prefetch_quirk(void)
}
EXPORT_SYMBOL_GPL(usb_amd_prefetch_quirk);
+bool usb_amd_quirk_pll_check(void)
+{
+ usb_amd_find_chipset_info();
+ return amd_chipset.need_pll_quirk;
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_check);
+
/*
* The hardware normally enables the A-link power management feature, which
* lets the system lower the power consumption in idle states.
@@ -520,7 +529,7 @@ void usb_amd_dev_put(void)
amd_chipset.nb_type = 0;
memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type));
amd_chipset.isoc_reqs = 0;
- amd_chipset.probe_result = 0;
+ amd_chipset.need_pll_quirk = 0;
spin_unlock_irqrestore(&amd_lock, flags);
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 63c633077d9e..e729de21fad7 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -5,11 +5,11 @@
#ifdef CONFIG_USB_PCI
void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-int usb_amd_find_chipset_info(void);
int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
bool usb_amd_hang_symptom_quirk(void);
bool usb_amd_prefetch_quirk(void);
void usb_amd_dev_put(void);
+bool usb_amd_quirk_pll_check(void);
void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c2fe218e051f..1e0236e90687 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -130,7 +130,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_AMD_0x96_HOST;
/* AMD PLL quirk */
- if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
+ if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_quirk_pll_check())
xhci->quirks |= XHCI_AMD_PLL_FIX;
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 671bce18782c..2b0ccd150209 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -104,7 +104,7 @@ static int xhci_rcar_is_gen2(struct device *dev)
return of_device_is_compatible(node, "renesas,xhci-r8a7790") ||
of_device_is_compatible(node, "renesas,xhci-r8a7791") ||
of_device_is_compatible(node, "renesas,xhci-r8a7793") ||
- of_device_is_compatible(node, "renensas,rcar-gen2-xhci");
+ of_device_is_compatible(node, "renesas,rcar-gen2-xhci");
}
static int xhci_rcar_is_gen3(struct device *dev)
@@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
* pointers. So, this driver clears the AC64 bit of xhci->hcc_params
* to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
* xhci_gen_setup().
+ *
+ * And, since the firmware/internal CPU control the USBSTS.STS_HALT
+ * and the process speed is down when the roothub port enters U3,
+ * long delay for the handshake of STS_HALT is neeed in xhci_suspend().
*/
if (xhci_rcar_is_gen2(hcd->self.controller) ||
- xhci_rcar_is_gen3(hcd->self.controller))
- xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
+ xhci_rcar_is_gen3(hcd->self.controller)) {
+ xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND;
+ }
if (!xhci_rcar_wait_for_pll_active(hcd))
return -ETIMEDOUT;
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index dafc65911fc0..2ff7c911fbd0 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1194,6 +1194,16 @@ static int tegra_xusb_probe(struct platform_device *pdev)
tegra_xusb_config(tegra, regs);
+ /*
+ * The XUSB Falcon microcontroller can only address 40 bits, so set
+ * the DMA mask accordingly.
+ */
+ err = dma_set_mask_and_coherent(tegra->dev, DMA_BIT_MASK(40));
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
+ goto put_rpm;
+ }
+
err = tegra_xusb_load_firmware(tegra);
if (err < 0) {
dev_err(&pdev->dev, "failed to load firmware: %d\n", err);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 248cd7a8b163..03d1e552769b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
return;
udev = (struct usb_device *) host_ep->hcpriv;
vdev = xhci->devs[udev->slot_id];
+
+ /*
+ * vdev may be lost due to xHC restore error and re-initialization
+ * during S3/S4 resume. A new vdev will be allocated later by
+ * xhci_discover_or_reset_device()
+ */
+ if (!udev->slot_id || !vdev)
+ return;
ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index];
+ if (!ep)
+ return;
/* Bail out if toggle is already being cleared by a endpoint reset */
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7a264962a1a9..f5c41448d067 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2175,7 +2175,8 @@ static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) &&
usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE &&
- !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+ !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) &&
+ !urb->num_sgs)
return true;
return false;
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index ba05dd80a020..f5bed9f29e56 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface)
dev = usb_get_intfdata(interface);
mutex_lock(&iowarrior_open_disc_lock);
usb_set_intfdata(interface, NULL);
+ /* prevent device read, write and ioctl */
+ dev->present = 0;
minor = dev->minor;
+ mutex_unlock(&iowarrior_open_disc_lock);
+ /* give back our minor - this will call close() locks need to be dropped at this point*/
- /* give back our minor */
usb_deregister_dev(interface, &iowarrior_class);
mutex_lock(&dev->mutex);
/* prevent device read, write and ioctl */
- dev->present = 0;
mutex_unlock(&dev->mutex);
- mutex_unlock(&iowarrior_open_disc_lock);
if (dev->opened) {
/* There is a process that holds a filedescriptor to the device ,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 27e9c78a791e..a32d61a79ab8 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -51,6 +51,7 @@ struct rio_usb_data {
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
+ struct mutex lock; /* general race avoidance */
};
static DEFINE_MUTEX(rio500_mutex);
@@ -62,8 +63,10 @@ static int open_rio(struct inode *inode, struct file *file)
/* against disconnect() */
mutex_lock(&rio500_mutex);
+ mutex_lock(&(rio->lock));
if (rio->isopen || !rio->present) {
+ mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -EBUSY;
}
@@ -71,6 +74,7 @@ static int open_rio(struct inode *inode, struct file *file)
init_waitqueue_head(&rio->wait_q);
+ mutex_unlock(&(rio->lock));
dev_info(&rio->rio_dev->dev, "Rio opened.\n");
mutex_unlock(&rio500_mutex);
@@ -84,6 +88,7 @@ static int close_rio(struct inode *inode, struct file *file)
/* against disconnect() */
mutex_lock(&rio500_mutex);
+ mutex_lock(&(rio->lock));
rio->isopen = 0;
if (!rio->present) {
@@ -95,6 +100,7 @@ static int close_rio(struct inode *inode, struct file *file)
} else {
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
}
+ mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return 0;
}
@@ -109,7 +115,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
int retries;
int retval=0;
- mutex_lock(&rio500_mutex);
+ mutex_lock(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV;
@@ -253,7 +259,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
err_out:
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return retval;
}
@@ -273,12 +279,12 @@ write_rio(struct file *file, const char __user *buffer,
int errn = 0;
int intr;
- intr = mutex_lock_interruptible(&rio500_mutex);
+ intr = mutex_lock_interruptible(&(rio->lock));
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return -ENODEV;
}
@@ -301,7 +307,7 @@ write_rio(struct file *file, const char __user *buffer,
goto error;
}
if (signal_pending(current)) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return bytes_written ? bytes_written : -EINTR;
}
@@ -339,12 +345,12 @@ write_rio(struct file *file, const char __user *buffer,
buffer += copy_size;
} while (count > 0);
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return bytes_written ? bytes_written : -EIO;
error:
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return errn;
}
@@ -361,12 +367,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
char *ibuf;
int intr;
- intr = mutex_lock_interruptible(&rio500_mutex);
+ intr = mutex_lock_interruptible(&(rio->lock));
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return -ENODEV;
}
@@ -377,11 +383,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
while (count > 0) {
if (signal_pending(current)) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return read_count ? read_count : -EINTR;
}
if (!rio->rio_dev) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return -ENODEV;
}
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
@@ -399,7 +405,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
dev_err(&rio->rio_dev->dev,
"read_rio: maxretry timeout\n");
return -ETIME;
@@ -409,19 +415,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
dev_err(&rio->rio_dev->dev,
"Read Whoops - result:%d partial:%u this_read:%u\n",
result, partial, this_read);
return -EIO;
} else {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) {
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return -EFAULT;
}
count -= this_read;
@@ -429,7 +435,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
buffer += this_read;
}
}
- mutex_unlock(&rio500_mutex);
+ mutex_unlock(&(rio->lock));
return read_count;
}
@@ -494,6 +500,8 @@ static int probe_rio(struct usb_interface *intf,
}
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
+ mutex_init(&(rio->lock));
+
usb_set_intfdata (intf, rio);
rio->present = 1;
bail_out:
@@ -511,10 +519,12 @@ static void disconnect_rio(struct usb_interface *intf)
if (rio) {
usb_deregister_dev(intf, &usb_rio_class);
+ mutex_lock(&(rio->lock));
if (rio->isopen) {
rio->isopen = 0;
/* better let it finish - the release will do whats needed */
rio->rio_dev = NULL;
+ mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return;
}
@@ -524,6 +534,7 @@ static void disconnect_rio(struct usb_interface *intf)
dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0;
+ mutex_unlock(&(rio->lock));
}
mutex_unlock(&rio500_mutex);
}
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
index 4d6ae3795a88..6ca9111d150a 100644
--- a/drivers/usb/misc/usb251xb.c
+++ b/drivers/usb/misc/usb251xb.c
@@ -375,7 +375,8 @@ out_err:
#ifdef CONFIG_OF
static void usb251xb_get_ports_field(struct usb251xb *hub,
- const char *prop_name, u8 port_cnt, u8 *fld)
+ const char *prop_name, u8 port_cnt,
+ bool ds_only, u8 *fld)
{
struct device *dev = hub->dev;
struct property *prop;
@@ -383,7 +384,7 @@ static void usb251xb_get_ports_field(struct usb251xb *hub,
u32 port;
of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) {
- if ((port >= 1) && (port <= port_cnt))
+ if ((port >= ds_only ? 1 : 0) && (port <= port_cnt))
*fld |= BIT(port);
else
dev_warn(dev, "port %u doesn't exist\n", port);
@@ -501,15 +502,15 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
hub->non_rem_dev = USB251XB_DEF_NON_REMOVABLE_DEVICES;
usb251xb_get_ports_field(hub, "non-removable-ports", data->port_cnt,
- &hub->non_rem_dev);
+ true, &hub->non_rem_dev);
hub->port_disable_sp = USB251XB_DEF_PORT_DISABLE_SELF;
usb251xb_get_ports_field(hub, "sp-disabled-ports", data->port_cnt,
- &hub->port_disable_sp);
+ true, &hub->port_disable_sp);
hub->port_disable_bp = USB251XB_DEF_PORT_DISABLE_BUS;
usb251xb_get_ports_field(hub, "bp-disabled-ports", data->port_cnt,
- &hub->port_disable_bp);
+ true, &hub->port_disable_bp);
hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF;
if (!of_property_read_u32(np, "sp-max-total-current-microamp",
@@ -573,9 +574,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
*/
hub->port_swap = USB251XB_DEF_PORT_SWAP;
usb251xb_get_ports_field(hub, "swap-dx-lanes", data->port_cnt,
- &hub->port_swap);
- if (of_get_property(np, "swap-us-lanes", NULL))
- hub->port_swap |= BIT(0);
+ false, &hub->port_swap);
/* The following parameters are currently not exposed to devicetree, but
* may be as soon as needed.
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 7b306aa22d25..6715a128e6c8 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -92,7 +92,6 @@ static void yurex_delete(struct kref *kref)
dev_dbg(&dev->interface->dev, "%s\n", __func__);
- usb_put_dev(dev->udev);
if (dev->cntl_urb) {
usb_kill_urb(dev->cntl_urb);
kfree(dev->cntl_req);
@@ -108,6 +107,7 @@ static void yurex_delete(struct kref *kref)
dev->int_buffer, dev->urb->transfer_dma);
usb_free_urb(dev->urb);
}
+ usb_put_dev(dev->udev);
kfree(dev);
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c1582fbd1150..38e920ac7f82 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -968,6 +968,11 @@ static const struct usb_device_id option_ids[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
+ /* Motorola devices */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2a70, 0xff, 0xff, 0xff) }, /* mdm6600 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2e0a, 0xff, 0xff, 0xff) }, /* mdm9600 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x4281, 0x0a, 0x00, 0xfc) }, /* mdm ram dl */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x900e, 0xff, 0xff, 0xff) }, /* mdm qc dl */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
@@ -1549,6 +1554,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G v2 */
.driver_info = RSVD(2) },
{ USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) }, /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
@@ -1952,11 +1958,15 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */
.driver_info = RSVD(4) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e3d, 0xff), /* D-Link DWM-222 A2 */
+ .driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */
.driver_info = RSVD(4) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff), /* BroadMobi BM818 */
+ .driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
{ USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index cc794e25a0b6..1d9ce9cbc831 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
static int auto_delink_en = 1;
module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
+MODULE_PARM_DESC(auto_delink_en, "auto delink mode (0=firmware, 1=software [default])");
#ifdef CONFIG_REALTEK_AUTOPM
static int ss_en = 1;
@@ -996,12 +996,15 @@ static int init_realtek_cr(struct us_data *us)
goto INIT_FAIL;
}
- if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
- CHECK_FW_VER(chip, 0x5901))
- SET_AUTO_DELINK(chip);
- if (STATUS_LEN(chip) == 16) {
- if (SUPPORT_AUTO_DELINK(chip))
+ if (CHECK_PID(chip, 0x0138) || CHECK_PID(chip, 0x0158) ||
+ CHECK_PID(chip, 0x0159)) {
+ if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
+ CHECK_FW_VER(chip, 0x5901))
SET_AUTO_DELINK(chip);
+ if (STATUS_LEN(chip) == 16) {
+ if (SUPPORT_AUTO_DELINK(chip))
+ SET_AUTO_DELINK(chip);
+ }
}
#ifdef CONFIG_REALTEK_AUTOPM
if (ss_en)
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 30790240aec6..05b80211290d 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -28,6 +28,8 @@
* status of a command.
*/
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -99,6 +101,7 @@ static int slave_alloc (struct scsi_device *sdev)
static int slave_configure(struct scsi_device *sdev)
{
struct us_data *us = host_to_us(sdev->host);
+ struct device *dev = us->pusb_dev->bus->sysdev;
/*
* Many devices have trouble transferring more than 32KB at a time,
@@ -129,6 +132,14 @@ static int slave_configure(struct scsi_device *sdev)
}
/*
+ * The max_hw_sectors should be up to maximum size of a mapping for
+ * the device. Otherwise, a DMA API might fail on swiotlb environment.
+ */
+ blk_queue_max_hw_sectors(sdev->request_queue,
+ min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
+ dma_max_mapping_size(dev) >> SECTOR_SHIFT));
+
+ /*
* Some USB host controllers can't do DMA; they have to use PIO.
* They indicate this by setting their dma_mask to NULL. For
* such controllers we need to make sure the block layer sets
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ea0d27a94afe..1cd9b6305b06 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2100,7 +2100,7 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
US_FL_IGNORE_RESIDUE ),
/* Reported by Michael Büsch <m@bues.ch> */
-UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116,
+UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0117,
"JMicron",
"USB to ATA/ATAPI Bridge",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index fba32d84e578..bcfdb55fd198 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -379,7 +379,8 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
return SNK_UNATTACHED;
else if (port->try_role == TYPEC_SOURCE)
return SRC_UNATTACHED;
- else if (port->tcpc->config->default_role == TYPEC_SINK)
+ else if (port->tcpc->config &&
+ port->tcpc->config->default_role == TYPEC_SINK)
return SNK_UNATTACHED;
/* Fall through to return SRC_UNATTACHED */
} else if (port->port_type == TYPEC_PORT_SNK) {
@@ -586,7 +587,20 @@ static void tcpm_debugfs_init(struct tcpm_port *port)
static void tcpm_debugfs_exit(struct tcpm_port *port)
{
+ int i;
+
+ mutex_lock(&port->logbuffer_lock);
+ for (i = 0; i < LOG_BUFFER_ENTRIES; i++) {
+ kfree(port->logbuffer[i]);
+ port->logbuffer[i] = NULL;
+ }
+ mutex_unlock(&port->logbuffer_lock);
+
debugfs_remove(port->dentry);
+ if (list_empty(&rootdir->d_subdirs)) {
+ debugfs_remove(rootdir);
+ rootdir = NULL;
+ }
}
#else
@@ -1095,7 +1109,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
break;
case CMD_ATTENTION:
/* Attention command does not have response */
- typec_altmode_attention(adev, p[1]);
+ if (adev)
+ typec_altmode_attention(adev, p[1]);
return 0;
default:
break;
@@ -1147,20 +1162,26 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
}
break;
case CMD_ENTER_MODE:
- typec_altmode_update_active(pdev, true);
-
- if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
- response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE);
- response[0] |= VDO_OPOS(adev->mode);
- return 1;
+ if (adev && pdev) {
+ typec_altmode_update_active(pdev, true);
+
+ if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
+ response[0] = VDO(adev->svid, 1,
+ CMD_EXIT_MODE);
+ response[0] |= VDO_OPOS(adev->mode);
+ return 1;
+ }
}
return 0;
case CMD_EXIT_MODE:
- typec_altmode_update_active(pdev, false);
+ if (adev && pdev) {
+ typec_altmode_update_active(pdev, false);
- /* Back to USB Operation */
- WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
- NULL));
+ /* Back to USB Operation */
+ WARN_ON(typec_altmode_notify(adev,
+ TYPEC_STATE_USB,
+ NULL));
+ }
break;
default:
break;
@@ -1170,8 +1191,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
switch (cmd) {
case CMD_ENTER_MODE:
/* Back to USB Operation */
- WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
- NULL));
+ if (adev)
+ WARN_ON(typec_altmode_notify(adev,
+ TYPEC_STATE_USB,
+ NULL));
break;
default:
break;
@@ -1182,7 +1205,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
}
/* Informing the alternate mode drivers about everything */
- typec_altmode_vdm(adev, p[0], &p[1], cnt);
+ if (adev)
+ typec_altmode_vdm(adev, p[0], &p[1], cnt);
return rlen;
}
@@ -1422,7 +1446,7 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo,
else if ((pdo_min_voltage(pdo[i]) ==
pdo_min_voltage(pdo[i - 1])) &&
(pdo_max_voltage(pdo[i]) ==
- pdo_min_voltage(pdo[i - 1])))
+ pdo_max_voltage(pdo[i - 1])))
return PDO_ERR_DUPE_PDO;
break;
/*
@@ -4114,7 +4138,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role)
mutex_lock(&port->lock);
if (tcpc->try_role)
ret = tcpc->try_role(tcpc, role);
- if (!ret && !tcpc->config->try_role_hw)
+ if (!ret && (!tcpc->config || !tcpc->config->try_role_hw))
port->try_role = role;
port->try_src_count = 0;
port->try_snk_count = 0;
@@ -4701,7 +4725,7 @@ static int tcpm_copy_caps(struct tcpm_port *port,
port->typec_caps.prefer_role = tcfg->default_role;
port->typec_caps.type = tcfg->type;
port->typec_caps.data = tcfg->data;
- port->self_powered = port->tcpc->config->self_powered;
+ port->self_powered = tcfg->self_powered;
return 0;
}
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index f7a79a23ebed..8e9f8fba55af 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -1018,7 +1018,7 @@ release_fw:
******************************************************************************/
static int ccg_fw_update(struct ucsi_ccg *uc, enum enum_flash_mode flash_mode)
{
- int err;
+ int err = 0;
while (flash_mode != FLASH_NOT_NEEDED) {
err = do_flash(uc, flash_mode);
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 054391f30fa8..ad830abe1021 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -650,12 +650,13 @@ unpin_exit:
}
static long vfio_sync_unpin(struct vfio_dma *dma, struct vfio_domain *domain,
- struct list_head *regions)
+ struct list_head *regions,
+ struct iommu_iotlb_gather *iotlb_gather)
{
long unlocked = 0;
struct vfio_regions *entry, *next;
- iommu_tlb_sync(domain->domain);
+ iommu_tlb_sync(domain->domain, iotlb_gather);
list_for_each_entry_safe(entry, next, regions, list) {
unlocked += vfio_unpin_pages_remote(dma,
@@ -685,18 +686,19 @@ static size_t unmap_unpin_fast(struct vfio_domain *domain,
struct vfio_dma *dma, dma_addr_t *iova,
size_t len, phys_addr_t phys, long *unlocked,
struct list_head *unmapped_list,
- int *unmapped_cnt)
+ int *unmapped_cnt,
+ struct iommu_iotlb_gather *iotlb_gather)
{
size_t unmapped = 0;
struct vfio_regions *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry) {
- unmapped = iommu_unmap_fast(domain->domain, *iova, len);
+ unmapped = iommu_unmap_fast(domain->domain, *iova, len,
+ iotlb_gather);
if (!unmapped) {
kfree(entry);
} else {
- iommu_tlb_range_add(domain->domain, *iova, unmapped);
entry->iova = *iova;
entry->phys = phys;
entry->len = unmapped;
@@ -712,8 +714,8 @@ static size_t unmap_unpin_fast(struct vfio_domain *domain,
* or in case of errors.
*/
if (*unmapped_cnt >= VFIO_IOMMU_TLB_SYNC_MAX || !unmapped) {
- *unlocked += vfio_sync_unpin(dma, domain,
- unmapped_list);
+ *unlocked += vfio_sync_unpin(dma, domain, unmapped_list,
+ iotlb_gather);
*unmapped_cnt = 0;
}
@@ -744,6 +746,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
dma_addr_t iova = dma->iova, end = dma->iova + dma->size;
struct vfio_domain *domain, *d;
LIST_HEAD(unmapped_region_list);
+ struct iommu_iotlb_gather iotlb_gather;
int unmapped_region_cnt = 0;
long unlocked = 0;
@@ -768,6 +771,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
cond_resched();
}
+ iommu_iotlb_gather_init(&iotlb_gather);
while (iova < end) {
size_t unmapped, len;
phys_addr_t phys, next;
@@ -796,7 +800,8 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
*/
unmapped = unmap_unpin_fast(domain, dma, &iova, len, phys,
&unlocked, &unmapped_region_list,
- &unmapped_region_cnt);
+ &unmapped_region_cnt,
+ &iotlb_gather);
if (!unmapped) {
unmapped = unmap_unpin_slow(domain, dma, &iova, len,
phys, &unlocked);
@@ -807,8 +812,10 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
dma->iommu_mapped = false;
- if (unmapped_region_cnt)
- unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list);
+ if (unmapped_region_cnt) {
+ unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list,
+ &iotlb_gather);
+ }
if (do_accounting) {
vfio_lock_acct(dma, -unlocked, true);
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 9e90e969af55..7804869c6a31 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -22,6 +22,12 @@
* Using this limit prevents one virtqueue from starving others. */
#define VHOST_TEST_WEIGHT 0x80000
+/* Max number of packets transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others with
+ * pkts.
+ */
+#define VHOST_TEST_PKT_WEIGHT 256
+
enum {
VHOST_TEST_VQ = 0,
VHOST_TEST_VQ_MAX = 1,
@@ -80,10 +86,8 @@ static void handle_vq(struct vhost_test *n)
}
vhost_add_used_and_signal(&n->dev, vq, head, 0);
total_len += len;
- if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
- vhost_poll_queue(&vq->poll);
+ if (unlikely(vhost_exceeds_weight(vq, 0, total_len)))
break;
- }
}
mutex_unlock(&vq->mutex);
@@ -115,7 +119,8 @@ static int vhost_test_open(struct inode *inode, struct file *f)
dev = &n->dev;
vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ];
n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
- vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX);
+ vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV,
+ VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT);
f->private_data = n;
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 0536f8526359..36ca2cf419bf 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -203,7 +203,6 @@ EXPORT_SYMBOL_GPL(vhost_poll_init);
int vhost_poll_start(struct vhost_poll *poll, struct file *file)
{
__poll_t mask;
- int ret = 0;
if (poll->wqh)
return 0;
@@ -213,10 +212,10 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file)
vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask));
if (mask & EPOLLERR) {
vhost_poll_stop(poll);
- ret = -EINVAL;
+ return -EINVAL;
}
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(vhost_poll_start);
@@ -298,160 +297,6 @@ static void vhost_vq_meta_reset(struct vhost_dev *d)
__vhost_vq_meta_reset(d->vqs[i]);
}
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_map_unprefetch(struct vhost_map *map)
-{
- kfree(map->pages);
- map->pages = NULL;
- map->npages = 0;
- map->addr = NULL;
-}
-
-static void vhost_uninit_vq_maps(struct vhost_virtqueue *vq)
-{
- struct vhost_map *map[VHOST_NUM_ADDRS];
- int i;
-
- spin_lock(&vq->mmu_lock);
- for (i = 0; i < VHOST_NUM_ADDRS; i++) {
- map[i] = rcu_dereference_protected(vq->maps[i],
- lockdep_is_held(&vq->mmu_lock));
- if (map[i])
- rcu_assign_pointer(vq->maps[i], NULL);
- }
- spin_unlock(&vq->mmu_lock);
-
- synchronize_rcu();
-
- for (i = 0; i < VHOST_NUM_ADDRS; i++)
- if (map[i])
- vhost_map_unprefetch(map[i]);
-
-}
-
-static void vhost_reset_vq_maps(struct vhost_virtqueue *vq)
-{
- int i;
-
- vhost_uninit_vq_maps(vq);
- for (i = 0; i < VHOST_NUM_ADDRS; i++)
- vq->uaddrs[i].size = 0;
-}
-
-static bool vhost_map_range_overlap(struct vhost_uaddr *uaddr,
- unsigned long start,
- unsigned long end)
-{
- if (unlikely(!uaddr->size))
- return false;
-
- return !(end < uaddr->uaddr || start > uaddr->uaddr - 1 + uaddr->size);
-}
-
-static void vhost_invalidate_vq_start(struct vhost_virtqueue *vq,
- int index,
- unsigned long start,
- unsigned long end)
-{
- struct vhost_uaddr *uaddr = &vq->uaddrs[index];
- struct vhost_map *map;
- int i;
-
- if (!vhost_map_range_overlap(uaddr, start, end))
- return;
-
- spin_lock(&vq->mmu_lock);
- ++vq->invalidate_count;
-
- map = rcu_dereference_protected(vq->maps[index],
- lockdep_is_held(&vq->mmu_lock));
- if (map) {
- if (uaddr->write) {
- for (i = 0; i < map->npages; i++)
- set_page_dirty(map->pages[i]);
- }
- rcu_assign_pointer(vq->maps[index], NULL);
- }
- spin_unlock(&vq->mmu_lock);
-
- if (map) {
- synchronize_rcu();
- vhost_map_unprefetch(map);
- }
-}
-
-static void vhost_invalidate_vq_end(struct vhost_virtqueue *vq,
- int index,
- unsigned long start,
- unsigned long end)
-{
- if (!vhost_map_range_overlap(&vq->uaddrs[index], start, end))
- return;
-
- spin_lock(&vq->mmu_lock);
- --vq->invalidate_count;
- spin_unlock(&vq->mmu_lock);
-}
-
-static int vhost_invalidate_range_start(struct mmu_notifier *mn,
- const struct mmu_notifier_range *range)
-{
- struct vhost_dev *dev = container_of(mn, struct vhost_dev,
- mmu_notifier);
- int i, j;
-
- if (!mmu_notifier_range_blockable(range))
- return -EAGAIN;
-
- for (i = 0; i < dev->nvqs; i++) {
- struct vhost_virtqueue *vq = dev->vqs[i];
-
- for (j = 0; j < VHOST_NUM_ADDRS; j++)
- vhost_invalidate_vq_start(vq, j,
- range->start,
- range->end);
- }
-
- return 0;
-}
-
-static void vhost_invalidate_range_end(struct mmu_notifier *mn,
- const struct mmu_notifier_range *range)
-{
- struct vhost_dev *dev = container_of(mn, struct vhost_dev,
- mmu_notifier);
- int i, j;
-
- for (i = 0; i < dev->nvqs; i++) {
- struct vhost_virtqueue *vq = dev->vqs[i];
-
- for (j = 0; j < VHOST_NUM_ADDRS; j++)
- vhost_invalidate_vq_end(vq, j,
- range->start,
- range->end);
- }
-}
-
-static const struct mmu_notifier_ops vhost_mmu_notifier_ops = {
- .invalidate_range_start = vhost_invalidate_range_start,
- .invalidate_range_end = vhost_invalidate_range_end,
-};
-
-static void vhost_init_maps(struct vhost_dev *dev)
-{
- struct vhost_virtqueue *vq;
- int i, j;
-
- dev->mmu_notifier.ops = &vhost_mmu_notifier_ops;
-
- for (i = 0; i < dev->nvqs; ++i) {
- vq = dev->vqs[i];
- for (j = 0; j < VHOST_NUM_ADDRS; j++)
- RCU_INIT_POINTER(vq->maps[j], NULL);
- }
-}
-#endif
-
static void vhost_vq_reset(struct vhost_dev *dev,
struct vhost_virtqueue *vq)
{
@@ -480,11 +325,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
- vq->invalidate_count = 0;
__vhost_vq_meta_reset(vq);
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- vhost_reset_vq_maps(vq);
-#endif
}
static int vhost_worker(void *data)
@@ -634,9 +475,7 @@ void vhost_dev_init(struct vhost_dev *dev,
INIT_LIST_HEAD(&dev->read_list);
INIT_LIST_HEAD(&dev->pending_list);
spin_lock_init(&dev->iotlb_lock);
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- vhost_init_maps(dev);
-#endif
+
for (i = 0; i < dev->nvqs; ++i) {
vq = dev->vqs[i];
@@ -645,7 +484,6 @@ void vhost_dev_init(struct vhost_dev *dev,
vq->heads = NULL;
vq->dev = dev;
mutex_init(&vq->mutex);
- spin_lock_init(&vq->mmu_lock);
vhost_vq_reset(dev, vq);
if (vq->handle_kick)
vhost_poll_init(&vq->poll, vq->handle_kick,
@@ -725,18 +563,7 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
if (err)
goto err_cgroup;
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- err = mmu_notifier_register(&dev->mmu_notifier, dev->mm);
- if (err)
- goto err_mmu_notifier;
-#endif
-
return 0;
-
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-err_mmu_notifier:
- vhost_dev_free_iovecs(dev);
-#endif
err_cgroup:
kthread_stop(worker);
dev->worker = NULL;
@@ -827,107 +654,6 @@ static void vhost_clear_msg(struct vhost_dev *dev)
spin_unlock(&dev->iotlb_lock);
}
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_setup_uaddr(struct vhost_virtqueue *vq,
- int index, unsigned long uaddr,
- size_t size, bool write)
-{
- struct vhost_uaddr *addr = &vq->uaddrs[index];
-
- addr->uaddr = uaddr;
- addr->size = size;
- addr->write = write;
-}
-
-static void vhost_setup_vq_uaddr(struct vhost_virtqueue *vq)
-{
- vhost_setup_uaddr(vq, VHOST_ADDR_DESC,
- (unsigned long)vq->desc,
- vhost_get_desc_size(vq, vq->num),
- false);
- vhost_setup_uaddr(vq, VHOST_ADDR_AVAIL,
- (unsigned long)vq->avail,
- vhost_get_avail_size(vq, vq->num),
- false);
- vhost_setup_uaddr(vq, VHOST_ADDR_USED,
- (unsigned long)vq->used,
- vhost_get_used_size(vq, vq->num),
- true);
-}
-
-static int vhost_map_prefetch(struct vhost_virtqueue *vq,
- int index)
-{
- struct vhost_map *map;
- struct vhost_uaddr *uaddr = &vq->uaddrs[index];
- struct page **pages;
- int npages = DIV_ROUND_UP(uaddr->size, PAGE_SIZE);
- int npinned;
- void *vaddr, *v;
- int err;
- int i;
-
- spin_lock(&vq->mmu_lock);
-
- err = -EFAULT;
- if (vq->invalidate_count)
- goto err;
-
- err = -ENOMEM;
- map = kmalloc(sizeof(*map), GFP_ATOMIC);
- if (!map)
- goto err;
-
- pages = kmalloc_array(npages, sizeof(struct page *), GFP_ATOMIC);
- if (!pages)
- goto err_pages;
-
- err = EFAULT;
- npinned = __get_user_pages_fast(uaddr->uaddr, npages,
- uaddr->write, pages);
- if (npinned > 0)
- release_pages(pages, npinned);
- if (npinned != npages)
- goto err_gup;
-
- for (i = 0; i < npinned; i++)
- if (PageHighMem(pages[i]))
- goto err_gup;
-
- vaddr = v = page_address(pages[0]);
-
- /* For simplicity, fallback to userspace address if VA is not
- * contigious.
- */
- for (i = 1; i < npinned; i++) {
- v += PAGE_SIZE;
- if (v != page_address(pages[i]))
- goto err_gup;
- }
-
- map->addr = vaddr + (uaddr->uaddr & (PAGE_SIZE - 1));
- map->npages = npages;
- map->pages = pages;
-
- rcu_assign_pointer(vq->maps[index], map);
- /* No need for a synchronize_rcu(). This function should be
- * called by dev->worker so we are serialized with all
- * readers.
- */
- spin_unlock(&vq->mmu_lock);
-
- return 0;
-
-err_gup:
- kfree(pages);
-err_pages:
- kfree(map);
-err:
- spin_unlock(&vq->mmu_lock);
- return err;
-}
-#endif
-
void vhost_dev_cleanup(struct vhost_dev *dev)
{
int i;
@@ -957,16 +683,8 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
kthread_stop(dev->worker);
dev->worker = NULL;
}
- if (dev->mm) {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- mmu_notifier_unregister(&dev->mmu_notifier, dev->mm);
-#endif
+ if (dev->mm)
mmput(dev->mm);
- }
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- for (i = 0; i < dev->nvqs; i++)
- vhost_uninit_vq_maps(dev->vqs[i]);
-#endif
dev->mm = NULL;
}
EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
@@ -1195,26 +913,6 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,
static inline int vhost_put_avail_event(struct vhost_virtqueue *vq)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_used *used;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
- if (likely(map)) {
- used = map->addr;
- *((__virtio16 *)&used->ring[vq->num]) =
- cpu_to_vhost16(vq, vq->avail_idx);
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
vhost_avail_event(vq));
}
@@ -1223,27 +921,6 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,
struct vring_used_elem *head, int idx,
int count)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_used *used;
- size_t size;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
- if (likely(map)) {
- used = map->addr;
- size = count * sizeof(*head);
- memcpy(used->ring + idx, head, size);
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_copy_to_user(vq, vq->used->ring + idx, head,
count * sizeof(*head));
}
@@ -1251,25 +928,6 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,
static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_used *used;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
- if (likely(map)) {
- used = map->addr;
- used->flags = cpu_to_vhost16(vq, vq->used_flags);
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
&vq->used->flags);
}
@@ -1277,25 +935,6 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_used *used;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
- if (likely(map)) {
- used = map->addr;
- used->idx = cpu_to_vhost16(vq, vq->last_used_idx);
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
&vq->used->idx);
}
@@ -1341,50 +980,12 @@ static void vhost_dev_unlock_vqs(struct vhost_dev *d)
static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq,
__virtio16 *idx)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_avail *avail;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
- if (likely(map)) {
- avail = map->addr;
- *idx = avail->idx;
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_get_avail(vq, *idx, &vq->avail->idx);
}
static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
__virtio16 *head, int idx)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_avail *avail;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
- if (likely(map)) {
- avail = map->addr;
- *head = avail->ring[idx & (vq->num - 1)];
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_get_avail(vq, *head,
&vq->avail->ring[idx & (vq->num - 1)]);
}
@@ -1392,98 +993,24 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq,
__virtio16 *flags)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_avail *avail;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
- if (likely(map)) {
- avail = map->addr;
- *flags = avail->flags;
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_get_avail(vq, *flags, &vq->avail->flags);
}
static inline int vhost_get_used_event(struct vhost_virtqueue *vq,
__virtio16 *event)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_avail *avail;
-
- if (!vq->iotlb) {
- rcu_read_lock();
- map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
- if (likely(map)) {
- avail = map->addr;
- *event = (__virtio16)avail->ring[vq->num];
- rcu_read_unlock();
- return 0;
- }
- rcu_read_unlock();
- }
-#endif
-
return vhost_get_avail(vq, *event, vhost_used_event(vq));
}
static inline int vhost_get_used_idx(struct vhost_virtqueue *vq,
__virtio16 *idx)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_used *used;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
- if (likely(map)) {
- used = map->addr;
- *idx = used->idx;
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_get_used(vq, *idx, &vq->used->idx);
}
static inline int vhost_get_desc(struct vhost_virtqueue *vq,
struct vring_desc *desc, int idx)
{
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- struct vhost_map *map;
- struct vring_desc *d;
-
- if (!vq->iotlb) {
- rcu_read_lock();
-
- map = rcu_dereference(vq->maps[VHOST_ADDR_DESC]);
- if (likely(map)) {
- d = map->addr;
- *desc = *(d + idx);
- rcu_read_unlock();
- return 0;
- }
-
- rcu_read_unlock();
- }
-#endif
-
return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc));
}
@@ -1824,32 +1351,12 @@ static bool iotlb_access_ok(struct vhost_virtqueue *vq,
return true;
}
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_vq_map_prefetch(struct vhost_virtqueue *vq)
-{
- struct vhost_map __rcu *map;
- int i;
-
- for (i = 0; i < VHOST_NUM_ADDRS; i++) {
- rcu_read_lock();
- map = rcu_dereference(vq->maps[i]);
- rcu_read_unlock();
- if (unlikely(!map))
- vhost_map_prefetch(vq, i);
- }
-}
-#endif
-
int vq_meta_prefetch(struct vhost_virtqueue *vq)
{
unsigned int num = vq->num;
- if (!vq->iotlb) {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- vhost_vq_map_prefetch(vq);
-#endif
+ if (!vq->iotlb)
return 1;
- }
return iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->desc,
vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) &&
@@ -2060,16 +1567,6 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
mutex_lock(&vq->mutex);
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- /* Unregister MMU notifer to allow invalidation callback
- * can access vq->uaddrs[] without holding a lock.
- */
- if (d->mm)
- mmu_notifier_unregister(&d->mmu_notifier, d->mm);
-
- vhost_uninit_vq_maps(vq);
-#endif
-
switch (ioctl) {
case VHOST_SET_VRING_NUM:
r = vhost_vring_set_num(d, vq, argp);
@@ -2081,13 +1578,6 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
BUG();
}
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- vhost_setup_vq_uaddr(vq);
-
- if (d->mm)
- mmu_notifier_register(&d->mmu_notifier, d->mm);
-#endif
-
mutex_unlock(&vq->mutex);
return r;
@@ -2688,7 +2178,7 @@ static int get_indirect(struct vhost_virtqueue *vq,
/* If this is an input descriptor, increment that count. */
if (access == VHOST_ACCESS_WO) {
*in_num += ret;
- if (unlikely(log)) {
+ if (unlikely(log && ret)) {
log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
log[*log_num].len = vhost32_to_cpu(vq, desc.len);
++*log_num;
@@ -2829,7 +2319,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
/* If this is an input descriptor,
* increment that count. */
*in_num += ret;
- if (unlikely(log)) {
+ if (unlikely(log && ret)) {
log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
log[*log_num].len = vhost32_to_cpu(vq, desc.len);
++*log_num;
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 819296332913..e9ed2722b633 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -12,9 +12,6 @@
#include <linux/virtio_config.h>
#include <linux/virtio_ring.h>
#include <linux/atomic.h>
-#include <linux/pagemap.h>
-#include <linux/mmu_notifier.h>
-#include <asm/cacheflush.h>
struct vhost_work;
typedef void (*vhost_work_fn_t)(struct vhost_work *work);
@@ -83,24 +80,6 @@ enum vhost_uaddr_type {
VHOST_NUM_ADDRS = 3,
};
-struct vhost_map {
- int npages;
- void *addr;
- struct page **pages;
-};
-
-struct vhost_uaddr {
- unsigned long uaddr;
- size_t size;
- bool write;
-};
-
-#if defined(CONFIG_MMU_NOTIFIER) && ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 0
-#define VHOST_ARCH_CAN_ACCEL_UACCESS 1
-#else
-#define VHOST_ARCH_CAN_ACCEL_UACCESS 0
-#endif
-
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
@@ -111,22 +90,7 @@ struct vhost_virtqueue {
struct vring_desc __user *desc;
struct vring_avail __user *avail;
struct vring_used __user *used;
-
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
- /* Read by memory accessors, modified by meta data
- * prefetching, MMU notifier and vring ioctl().
- * Synchonrized through mmu_lock (writers) and RCU (writers
- * and readers).
- */
- struct vhost_map __rcu *maps[VHOST_NUM_ADDRS];
- /* Read by MMU notifier, modified by vring ioctl(),
- * synchronized through MMU notifier
- * registering/unregistering.
- */
- struct vhost_uaddr uaddrs[VHOST_NUM_ADDRS];
-#endif
const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS];
-
struct file *kick;
struct eventfd_ctx *call_ctx;
struct eventfd_ctx *error_ctx;
@@ -181,8 +145,6 @@ struct vhost_virtqueue {
bool user_be;
#endif
u32 busyloop_timeout;
- spinlock_t mmu_lock;
- int invalidate_count;
};
struct vhost_msg_node {
@@ -196,9 +158,6 @@ struct vhost_msg_node {
struct vhost_dev {
struct mm_struct *mm;
-#ifdef CONFIG_MMU_NOTIFIER
- struct mmu_notifier mmu_notifier;
-#endif
struct mutex mutex;
struct vhost_virtqueue **vqs;
int nvqs;
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 6b2de93bd302..5f83cd715387 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1924,20 +1924,6 @@ config FB_S3C2410_DEBUG
Turn on debugging messages. Note that you can set/unset at run time
through sysfs
-config FB_NUC900
- tristate "NUC900 LCD framebuffer support"
- depends on FB && ARCH_W90X900
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Nuvoton
- NUC900 processor
-
-config GPM1040A0_320X240
- bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
- depends on FB_NUC900
-
config FB_SM501
tristate "Silicon Motion SM501 framebuffer support"
depends on FB && MFD_SM501
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 7dc4861a93e6..aab7155884ea 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -116,7 +116,6 @@ obj-y += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
-obj-$(CONFIG_FB_NUC900) += nuc900fb.o
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
diff --git a/drivers/video/fbdev/acornfb.c b/drivers/video/fbdev/acornfb.c
index 92f23e3bc27a..7cacae5a8797 100644
--- a/drivers/video/fbdev/acornfb.c
+++ b/drivers/video/fbdev/acornfb.c
@@ -858,6 +858,7 @@ static void acornfb_parse_dram(char *opt)
case 'M':
case 'm':
size *= 1024;
+ /* Fall through */
case 'K':
case 'k':
size *= 1024;
diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
index fc9dfb0a95af..51f5d1c56fd9 100644
--- a/drivers/video/fbdev/atafb.c
+++ b/drivers/video/fbdev/atafb.c
@@ -763,17 +763,17 @@ static void tt_get_par(struct atafb_par *par)
{
unsigned long addr;
par->hw.tt.mode = shifter_tt.tt_shiftmode;
- par->hw.tt.sync = shifter.syncmode;
- addr = ((shifter.bas_hi & 0xff) << 16) |
- ((shifter.bas_md & 0xff) << 8) |
- ((shifter.bas_lo & 0xff));
+ par->hw.tt.sync = shifter_st.syncmode;
+ addr = ((shifter_st.bas_hi & 0xff) << 16) |
+ ((shifter_st.bas_md & 0xff) << 8) |
+ ((shifter_st.bas_lo & 0xff));
par->screen_base = atari_stram_to_virt(addr);
}
static void tt_set_par(struct atafb_par *par)
{
shifter_tt.tt_shiftmode = par->hw.tt.mode;
- shifter.syncmode = par->hw.tt.sync;
+ shifter_st.syncmode = par->hw.tt.sync;
/* only set screen_base if really necessary */
if (current_par.screen_base != par->screen_base)
fbhw->set_screen_base(par->screen_base);
@@ -1543,7 +1543,7 @@ static void falcon_get_par(struct atafb_par *par)
hw->f_shift = videl.f_shift;
hw->vid_control = videl.control;
hw->vid_mode = videl.mode;
- hw->sync = shifter.syncmode & 0x1;
+ hw->sync = shifter_st.syncmode & 0x1;
hw->xoffset = videl.xoffset & 0xf;
hw->hht = videl.hht;
hw->hbb = videl.hbb;
@@ -1558,9 +1558,9 @@ static void falcon_get_par(struct atafb_par *par)
hw->vde = videl.vde;
hw->vss = videl.vss;
- addr = (shifter.bas_hi & 0xff) << 16 |
- (shifter.bas_md & 0xff) << 8 |
- (shifter.bas_lo & 0xff);
+ addr = (shifter_st.bas_hi & 0xff) << 16 |
+ (shifter_st.bas_md & 0xff) << 8 |
+ (shifter_st.bas_lo & 0xff);
par->screen_base = atari_stram_to_virt(addr);
/* derived parameters */
@@ -1605,7 +1605,7 @@ static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
/* Turn off external clocks. Read sets all output bits to 1. */
*(volatile unsigned short *)0xffff9202;
}
- shifter.syncmode = hw->sync;
+ shifter_st.syncmode = hw->sync;
videl.hht = hw->hht;
videl.hbb = hw->hbb;
@@ -1952,18 +1952,18 @@ static void stste_get_par(struct atafb_par *par)
{
unsigned long addr;
par->hw.st.mode = shifter_tt.st_shiftmode;
- par->hw.st.sync = shifter.syncmode;
- addr = ((shifter.bas_hi & 0xff) << 16) |
- ((shifter.bas_md & 0xff) << 8);
+ par->hw.st.sync = shifter_st.syncmode;
+ addr = ((shifter_st.bas_hi & 0xff) << 16) |
+ ((shifter_st.bas_md & 0xff) << 8);
if (ATARIHW_PRESENT(EXTD_SHIFTER))
- addr |= (shifter.bas_lo & 0xff);
+ addr |= (shifter_st.bas_lo & 0xff);
par->screen_base = atari_stram_to_virt(addr);
}
static void stste_set_par(struct atafb_par *par)
{
shifter_tt.st_shiftmode = par->hw.st.mode;
- shifter.syncmode = par->hw.st.sync;
+ shifter_st.syncmode = par->hw.st.sync;
/* only set screen_base if really necessary */
if (current_par.screen_base != par->screen_base)
fbhw->set_screen_base(par->screen_base);
@@ -2018,10 +2018,10 @@ static void stste_set_screen_base(void *s_base)
unsigned long addr;
addr = atari_stram_to_phys(s_base);
/* Setup Screen Memory */
- shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
- shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+ shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+ shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
if (ATARIHW_PRESENT(EXTD_SHIFTER))
- shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+ shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
}
#endif /* ATAFB_STE */
@@ -2265,9 +2265,9 @@ static void set_screen_base(void *s_base)
addr = atari_stram_to_phys(s_base);
/* Setup Screen Memory */
- shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
- shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
- shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+ shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+ shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+ shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
}
static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
index b1cf248f3291..2d3dcc52fcf3 100644
--- a/drivers/video/fbdev/da8xx-fb.c
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/console.h>
+#include <linux/regulator/consumer.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -164,7 +165,7 @@ struct da8xx_fb_par {
struct notifier_block freq_transition;
#endif
unsigned int lcdc_clk_rate;
- void (*panel_power_ctrl)(int);
+ struct regulator *lcd_supply;
u32 pseudo_palette[16];
struct fb_videomode mode;
struct lcd_ctrl_config cfg;
@@ -1066,33 +1067,30 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
static int fb_remove(struct platform_device *dev)
{
struct fb_info *info = dev_get_drvdata(&dev->dev);
-
- if (info) {
- struct da8xx_fb_par *par = info->par;
+ struct da8xx_fb_par *par = info->par;
+ int ret;
#ifdef CONFIG_CPU_FREQ
- lcd_da8xx_cpufreq_deregister(par);
+ lcd_da8xx_cpufreq_deregister(par);
#endif
- if (par->panel_power_ctrl)
- par->panel_power_ctrl(0);
+ if (par->lcd_supply) {
+ ret = regulator_disable(par->lcd_supply);
+ if (ret)
+ return ret;
+ }
- lcd_disable_raster(DA8XX_FRAME_WAIT);
- lcdc_write(0, LCD_RASTER_CTRL_REG);
+ lcd_disable_raster(DA8XX_FRAME_WAIT);
+ lcdc_write(0, LCD_RASTER_CTRL_REG);
- /* disable DMA */
- lcdc_write(0, LCD_DMA_CTRL_REG);
+ /* disable DMA */
+ lcdc_write(0, LCD_DMA_CTRL_REG);
- unregister_framebuffer(info);
- fb_dealloc_cmap(&info->cmap);
- dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base,
- par->p_palette_base);
- dma_free_coherent(par->dev, par->vram_size, par->vram_virt,
- par->vram_phys);
- pm_runtime_put_sync(&dev->dev);
- pm_runtime_disable(&dev->dev);
- framebuffer_release(info);
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ pm_runtime_put_sync(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+ framebuffer_release(info);
- }
return 0;
}
@@ -1179,15 +1177,21 @@ static int cfb_blank(int blank, struct fb_info *info)
case FB_BLANK_UNBLANK:
lcd_enable_raster();
- if (par->panel_power_ctrl)
- par->panel_power_ctrl(1);
+ if (par->lcd_supply) {
+ ret = regulator_enable(par->lcd_supply);
+ if (ret)
+ return ret;
+ }
break;
case FB_BLANK_NORMAL:
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
- if (par->panel_power_ctrl)
- par->panel_power_ctrl(0);
+ if (par->lcd_supply) {
+ ret = regulator_disable(par->lcd_supply);
+ if (ret)
+ return ret;
+ }
lcd_disable_raster(DA8XX_FRAME_WAIT);
break;
@@ -1328,7 +1332,6 @@ static int fb_probe(struct platform_device *device)
{
struct da8xx_lcdc_platform_data *fb_pdata =
dev_get_platdata(&device->dev);
- struct resource *lcdc_regs;
struct lcd_ctrl_config *lcd_cfg;
struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info;
@@ -1346,8 +1349,7 @@ static int fb_probe(struct platform_device *device)
if (lcdc_info == NULL)
return -ENODEV;
- lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
- da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs);
+ da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0);
if (IS_ERR(da8xx_fb_reg_base))
return PTR_ERR(da8xx_fb_reg_base);
@@ -1395,9 +1397,19 @@ static int fb_probe(struct platform_device *device)
par->dev = &device->dev;
par->lcdc_clk = tmp_lcdc_clk;
par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
- if (fb_pdata->panel_power_ctrl) {
- par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
- par->panel_power_ctrl(1);
+
+ par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd");
+ if (IS_ERR(par->lcd_supply)) {
+ if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_pm_runtime_disable;
+ }
+
+ par->lcd_supply = NULL;
+ } else {
+ ret = regulator_enable(par->lcd_supply);
+ if (ret)
+ goto err_pm_runtime_disable;
}
fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
@@ -1411,10 +1423,10 @@ static int fb_probe(struct platform_device *device)
par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
- par->vram_virt = dma_alloc_coherent(par->dev,
- par->vram_size,
- &par->vram_phys,
- GFP_KERNEL | GFP_DMA);
+ par->vram_virt = dmam_alloc_coherent(par->dev,
+ par->vram_size,
+ &par->vram_phys,
+ GFP_KERNEL | GFP_DMA);
if (!par->vram_virt) {
dev_err(&device->dev,
"GLCD: kmalloc for frame buffer failed\n");
@@ -1432,20 +1444,20 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
- par->v_palette_base = dma_alloc_coherent(par->dev, PALETTE_SIZE,
- &par->p_palette_base,
- GFP_KERNEL | GFP_DMA);
+ par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE,
+ &par->p_palette_base,
+ GFP_KERNEL | GFP_DMA);
if (!par->v_palette_base) {
dev_err(&device->dev,
"GLCD: kmalloc for palette buffer failed\n");
ret = -EINVAL;
- goto err_release_fb_mem;
+ goto err_release_fb;
}
par->irq = platform_get_irq(device, 0);
if (par->irq < 0) {
ret = -ENOENT;
- goto err_release_pl_mem;
+ goto err_release_fb;
}
da8xx_fb_var.grayscale =
@@ -1463,7 +1475,7 @@ static int fb_probe(struct platform_device *device)
ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
if (ret)
- goto err_release_pl_mem;
+ goto err_release_fb;
da8xx_fb_info->cmap.len = par->palette_sz;
/* initialize var_screeninfo */
@@ -1517,14 +1529,6 @@ err_cpu_freq:
err_dealloc_cmap:
fb_dealloc_cmap(&da8xx_fb_info->cmap);
-err_release_pl_mem:
- dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base,
- par->p_palette_base);
-
-err_release_fb_mem:
- dma_free_coherent(par->dev, par->vram_size, par->vram_virt,
- par->vram_phys);
-
err_release_fb:
framebuffer_release(da8xx_fb_info);
@@ -1603,10 +1607,14 @@ static int fb_suspend(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct da8xx_fb_par *par = info->par;
+ int ret;
console_lock();
- if (par->panel_power_ctrl)
- par->panel_power_ctrl(0);
+ if (par->lcd_supply) {
+ ret = regulator_disable(par->lcd_supply);
+ if (ret)
+ return ret;
+ }
fb_set_suspend(info, 1);
lcd_disable_raster(DA8XX_FRAME_WAIT);
@@ -1620,6 +1628,7 @@ static int fb_resume(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct da8xx_fb_par *par = info->par;
+ int ret;
console_lock();
pm_runtime_get_sync(dev);
@@ -1627,8 +1636,11 @@ static int fb_resume(struct device *dev)
if (par->blank == FB_BLANK_UNBLANK) {
lcd_enable_raster();
- if (par->panel_power_ctrl)
- par->panel_power_ctrl(1);
+ if (par->lcd_supply) {
+ ret = regulator_enable(par->lcd_supply);
+ if (ret)
+ return ret;
+ }
}
fb_set_suspend(info, 0);
diff --git a/drivers/video/fbdev/nuc900fb.c b/drivers/video/fbdev/nuc900fb.c
deleted file mode 100644
index 4fd851598584..000000000000
--- a/drivers/video/fbdev/nuc900fb.c
+++ /dev/null
@@ -1,760 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * Description:
- * Nuvoton LCD Controller Driver
- * Author:
- * Wang Qiang (rurality.linux@gmail.com) 2009/12/11
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/io.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ldm.h>
-#include <linux/platform_data/video-nuc900fb.h>
-
-#include "nuc900fb.h"
-
-
-/*
- * Initialize the nuc900 video (dual) buffer address
- */
-static void nuc900fb_set_lcdaddr(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- void __iomem *regs = fbi->io;
- unsigned long vbaddr1, vbaddr2;
-
- vbaddr1 = info->fix.smem_start;
- vbaddr2 = info->fix.smem_start;
- vbaddr2 += info->fix.line_length * info->var.yres;
-
- /* set frambuffer start phy addr*/
- writel(vbaddr1, regs + REG_LCM_VA_BADDR0);
- writel(vbaddr2, regs + REG_LCM_VA_BADDR1);
-
- writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL);
- writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE);
-}
-
-/*
- * calculate divider for lcd div
- */
-static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi,
- unsigned long pixclk)
-{
- unsigned long clk = fbi->clk_rate;
- unsigned long long div;
-
- /* pixclk is in picseconds. our clock is in Hz*/
- /* div = (clk * pixclk)/10^12 */
- div = (unsigned long long)clk * pixclk;
- div >>= 12;
- do_div(div, 625 * 625UL * 625);
-
- dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div);
-
- return div;
-}
-
-/*
- * Check the video params of 'var'.
- */
-static int nuc900fb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
- struct nuc900fb_display *display = NULL;
- struct nuc900fb_display *default_display = mach_info->displays +
- mach_info->default_display;
- int i;
-
- dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info);
-
- /* validate x/y resolution */
- /* choose default mode if possible */
- if (var->xres == default_display->xres &&
- var->yres == default_display->yres &&
- var->bits_per_pixel == default_display->bpp)
- display = default_display;
- else
- for (i = 0; i < mach_info->num_displays; i++)
- if (var->xres == mach_info->displays[i].xres &&
- var->yres == mach_info->displays[i].yres &&
- var->bits_per_pixel == mach_info->displays[i].bpp) {
- display = mach_info->displays + i;
- break;
- }
-
- if (display == NULL) {
- printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
-
- /* it should be the same size as the display */
- var->xres_virtual = display->xres;
- var->yres_virtual = display->yres;
- var->height = display->height;
- var->width = display->width;
-
- /* copy lcd settings */
- var->pixclock = display->pixclock;
- var->left_margin = display->left_margin;
- var->right_margin = display->right_margin;
- var->upper_margin = display->upper_margin;
- var->lower_margin = display->lower_margin;
- var->vsync_len = display->vsync_len;
- var->hsync_len = display->hsync_len;
-
- var->transp.offset = 0;
- var->transp.length = 0;
-
- fbi->regs.lcd_dccs = display->dccs;
- fbi->regs.lcd_device_ctrl = display->devctl;
- fbi->regs.lcd_va_fbctrl = display->fbctrl;
- fbi->regs.lcd_va_scale = display->scale;
-
- /* set R/G/B possions */
- switch (var->bits_per_pixel) {
- case 1:
- case 2:
- case 4:
- case 8:
- default:
- var->red.offset = 0;
- var->red.length = var->bits_per_pixel;
- var->green = var->red;
- var->blue = var->red;
- break;
- case 12:
- var->red.length = 4;
- var->green.length = 4;
- var->blue.length = 4;
- var->red.offset = 8;
- var->green.offset = 4;
- var->blue.offset = 0;
- break;
- case 16:
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- break;
- case 18:
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- var->red.offset = 12;
- var->green.offset = 6;
- var->blue.offset = 0;
- break;
- case 32:
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- break;
- }
-
- return 0;
-}
-
-/*
- * Calculate lcd register values from var setting & save into hw
- */
-static void nuc900fb_calculate_lcd_regs(const struct fb_info *info,
- struct nuc900fb_hw *regs)
-{
- const struct fb_var_screeninfo *var = &info->var;
- int vtt = var->height + var->upper_margin + var->lower_margin;
- int htt = var->width + var->left_margin + var->right_margin;
- int hsync = var->width + var->right_margin;
- int vsync = var->height + var->lower_margin;
-
- regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) |
- LCM_CRTC_SIZE_HTTVAL(htt);
- regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) |
- LCM_CRTC_DEND_HDENDVAL(var->width);
- regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) |
- LCM_CRTC_HR_SVAL(var->width + 1);
- regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) |
- LCM_CRTC_HSYNC_SVAL(hsync);
- regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) |
- LCM_CRTC_VR_SVAL(vsync);
-
-}
-
-/*
- * Activate (set) the controller from the given framebuffer
- * information
- */
-static void nuc900fb_activate_var(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- void __iomem *regs = fbi->io;
- struct fb_var_screeninfo *var = &info->var;
- int clkdiv;
-
- clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1;
- if (clkdiv < 0)
- clkdiv = 0;
-
- nuc900fb_calculate_lcd_regs(info, &fbi->regs);
-
- /* set the new lcd registers*/
-
- dev_dbg(fbi->dev, "new lcd register set:\n");
- dev_dbg(fbi->dev, "dccs = 0x%08x\n", fbi->regs.lcd_dccs);
- dev_dbg(fbi->dev, "dev_ctl = 0x%08x\n", fbi->regs.lcd_device_ctrl);
- dev_dbg(fbi->dev, "crtc_size = 0x%08x\n", fbi->regs.lcd_crtc_size);
- dev_dbg(fbi->dev, "crtc_dend = 0x%08x\n", fbi->regs.lcd_crtc_dend);
- dev_dbg(fbi->dev, "crtc_hr = 0x%08x\n", fbi->regs.lcd_crtc_hr);
- dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync);
- dev_dbg(fbi->dev, "crtc_vr = 0x%08x\n", fbi->regs.lcd_crtc_vr);
-
- writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL);
- writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE);
- writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND);
- writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR);
- writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC);
- writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR);
-
- /* set lcd address pointers */
- nuc900fb_set_lcdaddr(info);
-
- writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS);
-}
-
-/*
- * Alters the hardware state.
- *
- */
-static int nuc900fb_set_par(struct fb_info *info)
-{
- struct fb_var_screeninfo *var = &info->var;
-
- switch (var->bits_per_pixel) {
- case 32:
- case 24:
- case 18:
- case 16:
- case 12:
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- break;
- case 1:
- info->fix.visual = FB_VISUAL_MONO01;
- break;
- default:
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
- }
-
- info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
-
- /* activate this new configuration */
- nuc900fb_activate_var(info);
- return 0;
-}
-
-static inline unsigned int chan_to_field(unsigned int chan,
- struct fb_bitfield *bf)
-{
- chan &= 0xffff;
- chan >>= 16 - bf->length;
- return chan << bf->offset;
-}
-
-static int nuc900fb_setcolreg(unsigned regno,
- unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
-{
- unsigned int val;
-
- switch (info->fix.visual) {
- case FB_VISUAL_TRUECOLOR:
- /* true-colour, use pseuo-palette */
- if (regno < 16) {
- u32 *pal = info->pseudo_palette;
-
- val = chan_to_field(red, &info->var.red);
- val |= chan_to_field(green, &info->var.green);
- val |= chan_to_field(blue, &info->var.blue);
- pal[regno] = val;
- }
- break;
-
- default:
- return 1; /* unknown type */
- }
- return 0;
-}
-
-/**
- * nuc900fb_blank
- *
- */
-static int nuc900fb_blank(int blank_mode, struct fb_info *info)
-{
-
- return 0;
-}
-
-static struct fb_ops nuc900fb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = nuc900fb_check_var,
- .fb_set_par = nuc900fb_set_par,
- .fb_blank = nuc900fb_blank,
- .fb_setcolreg = nuc900fb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
-
-
-static inline void modify_gpio(void __iomem *reg,
- unsigned long set, unsigned long mask)
-{
- unsigned long tmp;
- tmp = readl(reg) & ~mask;
- writel(tmp | set, reg);
-}
-
-/*
- * Initialise LCD-related registers
- */
-static int nuc900fb_init_registers(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
- void __iomem *regs = fbi->io;
-
- /*reset the display engine*/
- writel(0, regs + REG_LCM_DCCS);
- writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST,
- regs + REG_LCM_DCCS);
- ndelay(100);
- writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST),
- regs + REG_LCM_DCCS);
- ndelay(100);
-
- writel(0, regs + REG_LCM_DEV_CTRL);
-
- /* config gpio output */
- modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir,
- mach_info->gpio_dir_mask);
- modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data,
- mach_info->gpio_data_mask);
-
- return 0;
-}
-
-
-/*
- * Alloc the SDRAM region of NUC900 for the frame buffer.
- * The buffer should be a non-cached, non-buffered, memory region
- * to allow palette and pixel writes without flushing the cache.
- */
-static int nuc900fb_map_video_memory(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- dma_addr_t map_dma;
- unsigned long map_size = PAGE_ALIGN(info->fix.smem_len);
-
- dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
- fbi, map_size);
-
- info->screen_base = dma_alloc_wc(fbi->dev, map_size, &map_dma,
- GFP_KERNEL);
-
- if (!info->screen_base)
- return -ENOMEM;
-
- memset(info->screen_base, 0x00, map_size);
- info->fix.smem_start = map_dma;
-
- return 0;
-}
-
-static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
- info->screen_base, info->fix.smem_start);
-}
-
-static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
-{
- struct nuc900fb_info *fbi = dev_id;
- void __iomem *regs = fbi->io;
- void __iomem *irq_base = fbi->irq_base;
- unsigned long lcdirq = readl(regs + REG_LCM_INT_CS);
-
- if (lcdirq & LCM_INT_CS_DISP_F_STATUS) {
- writel(readl(irq_base) | 1<<30, irq_base);
-
- /* wait VA_EN low */
- if ((readl(regs + REG_LCM_DCCS) &
- LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE)
- while ((readl(regs + REG_LCM_DCCS) &
- LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN)
- ;
- /* display_out-enable */
- writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN,
- regs + REG_LCM_DCCS);
- /* va-enable*/
- writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN,
- regs + REG_LCM_DCCS);
- } else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) {
- writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base);
- } else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) {
- writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base);
- }
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_CPU_FREQ
-
-static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
- unsigned long val, void *data)
-{
- struct nuc900fb_info *info;
- struct fb_info *fbinfo;
- long delta_f;
- info = container_of(nb, struct nuc900fb_info, freq_transition);
- fbinfo = dev_get_drvdata(info->dev);
-
- delta_f = info->clk_rate - clk_get_rate(info->clk);
-
- if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
- (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
- info->clk_rate = clk_get_rate(info->clk);
- nuc900fb_activate_var(fbinfo);
- }
-
- return 0;
-}
-
-static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
-{
- fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition;
- return cpufreq_register_notifier(&fbi->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi)
-{
- cpufreq_unregister_notifier(&fbi->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-}
-#else
-static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb,
- unsigned long val, void *data)
-{
- return 0;
-}
-
-static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
-{
- return 0;
-}
-
-static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
-{
-}
-#endif
-
-static char driver_name[] = "nuc900fb";
-
-static int nuc900fb_probe(struct platform_device *pdev)
-{
- struct nuc900fb_info *fbi;
- struct nuc900fb_display *display;
- struct fb_info *fbinfo;
- struct nuc900fb_mach_info *mach_info;
- struct resource *res;
- int ret;
- int irq;
- int i;
- int size;
-
- dev_dbg(&pdev->dev, "devinit\n");
- mach_info = dev_get_platdata(&pdev->dev);
- if (mach_info == NULL) {
- dev_err(&pdev->dev,
- "no platform data for lcd, cannot attach\n");
- return -EINVAL;
- }
-
- if (mach_info->default_display > mach_info->num_displays) {
- dev_err(&pdev->dev,
- "default display No. is %d but only %d displays \n",
- mach_info->default_display, mach_info->num_displays);
- return -EINVAL;
- }
-
-
- display = mach_info->displays + mach_info->default_display;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq for device\n");
- return -ENOENT;
- }
-
- fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev);
- if (!fbinfo)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, fbinfo);
-
- fbi = fbinfo->par;
- fbi->dev = &pdev->dev;
-
-#ifdef CONFIG_CPU_NUC950
- fbi->drv_type = LCDDRV_NUC950;
-#endif
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- size = resource_size(res);
- fbi->mem = request_mem_region(res->start, size, pdev->name);
- if (fbi->mem == NULL) {
- dev_err(&pdev->dev, "failed to alloc memory region\n");
- ret = -ENOENT;
- goto free_fb;
- }
-
- fbi->io = ioremap(res->start, size);
- if (fbi->io == NULL) {
- dev_err(&pdev->dev, "ioremap() of lcd registers failed\n");
- ret = -ENXIO;
- goto release_mem_region;
- }
-
- fbi->irq_base = fbi->io + REG_LCM_INT_CS;
-
-
- /* Stop the LCD */
- writel(0, fbi->io + REG_LCM_DCCS);
-
- /* fill the fbinfo*/
- strcpy(fbinfo->fix.id, driver_name);
- fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
- fbinfo->fix.type_aux = 0;
- fbinfo->fix.xpanstep = 0;
- fbinfo->fix.ypanstep = 0;
- fbinfo->fix.ywrapstep = 0;
- fbinfo->fix.accel = FB_ACCEL_NONE;
- fbinfo->var.nonstd = 0;
- fbinfo->var.activate = FB_ACTIVATE_NOW;
- fbinfo->var.accel_flags = 0;
- fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
- fbinfo->fbops = &nuc900fb_ops;
- fbinfo->flags = FBINFO_FLAG_DEFAULT;
- fbinfo->pseudo_palette = &fbi->pseudo_pal;
-
- ret = request_irq(irq, nuc900fb_irqhandler, 0, pdev->name, fbi);
- if (ret) {
- dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
- irq, ret);
- ret = -EBUSY;
- goto release_regs;
- }
-
- fbi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(fbi->clk)) {
- printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
- ret = PTR_ERR(fbi->clk);
- goto release_irq;
- }
-
- clk_enable(fbi->clk);
- dev_dbg(&pdev->dev, "got and enabled clock\n");
-
- fbi->clk_rate = clk_get_rate(fbi->clk);
-
- /* calutate the video buffer size */
- for (i = 0; i < mach_info->num_displays; i++) {
- unsigned long smem_len = mach_info->displays[i].xres;
- smem_len *= mach_info->displays[i].yres;
- smem_len *= mach_info->displays[i].bpp;
- smem_len >>= 3;
- if (fbinfo->fix.smem_len < smem_len)
- fbinfo->fix.smem_len = smem_len;
- }
-
- /* Initialize Video Memory */
- ret = nuc900fb_map_video_memory(fbinfo);
- if (ret) {
- printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret);
- goto release_clock;
- }
-
- dev_dbg(&pdev->dev, "got video memory\n");
-
- fbinfo->var.xres = display->xres;
- fbinfo->var.yres = display->yres;
- fbinfo->var.bits_per_pixel = display->bpp;
-
- nuc900fb_init_registers(fbinfo);
-
- nuc900fb_check_var(&fbinfo->var, fbinfo);
-
- ret = nuc900fb_cpufreq_register(fbi);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register cpufreq\n");
- goto free_video_memory;
- }
-
- ret = register_framebuffer(fbinfo);
- if (ret) {
- printk(KERN_ERR "failed to register framebuffer device: %d\n",
- ret);
- goto free_cpufreq;
- }
-
- fb_info(fbinfo, "%s frame buffer device\n", fbinfo->fix.id);
-
- return 0;
-
-free_cpufreq:
- nuc900fb_cpufreq_deregister(fbi);
-free_video_memory:
- nuc900fb_unmap_video_memory(fbinfo);
-release_clock:
- clk_disable(fbi->clk);
- clk_put(fbi->clk);
-release_irq:
- free_irq(irq, fbi);
-release_regs:
- iounmap(fbi->io);
-release_mem_region:
- release_mem_region(res->start, size);
-free_fb:
- framebuffer_release(fbinfo);
- return ret;
-}
-
-/*
- * shutdown the lcd controller
- */
-static void nuc900fb_stop_lcd(struct fb_info *info)
-{
- struct nuc900fb_info *fbi = info->par;
- void __iomem *regs = fbi->io;
-
- writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN),
- regs + REG_LCM_DCCS);
-}
-
-/*
- * Cleanup
- */
-static int nuc900fb_remove(struct platform_device *pdev)
-{
- struct fb_info *fbinfo = platform_get_drvdata(pdev);
- struct nuc900fb_info *fbi = fbinfo->par;
- int irq;
-
- nuc900fb_stop_lcd(fbinfo);
- msleep(1);
-
- unregister_framebuffer(fbinfo);
- nuc900fb_cpufreq_deregister(fbi);
- nuc900fb_unmap_video_memory(fbinfo);
-
- iounmap(fbi->io);
-
- irq = platform_get_irq(pdev, 0);
- free_irq(irq, fbi);
-
- release_resource(fbi->mem);
- kfree(fbi->mem);
-
- framebuffer_release(fbinfo);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-/*
- * suspend and resume support for the lcd controller
- */
-
-static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct fb_info *fbinfo = platform_get_drvdata(dev);
- struct nuc900fb_info *info = fbinfo->par;
-
- nuc900fb_stop_lcd(fbinfo);
- msleep(1);
- clk_disable(info->clk);
- return 0;
-}
-
-static int nuc900fb_resume(struct platform_device *dev)
-{
- struct fb_info *fbinfo = platform_get_drvdata(dev);
- struct nuc900fb_info *fbi = fbinfo->par;
-
- printk(KERN_INFO "nuc900fb resume\n");
-
- clk_enable(fbi->clk);
- msleep(1);
-
- nuc900fb_init_registers(fbinfo);
- nuc900fb_activate_var(fbinfo);
-
- return 0;
-}
-
-#else
-#define nuc900fb_suspend NULL
-#define nuc900fb_resume NULL
-#endif
-
-static struct platform_driver nuc900fb_driver = {
- .probe = nuc900fb_probe,
- .remove = nuc900fb_remove,
- .suspend = nuc900fb_suspend,
- .resume = nuc900fb_resume,
- .driver = {
- .name = "nuc900-lcd",
- },
-};
-
-module_platform_driver(nuc900fb_driver);
-
-MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/nuc900fb.h b/drivers/video/fbdev/nuc900fb.h
deleted file mode 100644
index 055ae9297931..000000000000
--- a/drivers/video/fbdev/nuc900fb.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * Author:
- * Wang Qiang(rurality.linux@gmail.com) 2009/12/16
- */
-
-#ifndef __NUC900FB_H
-#define __NUC900FB_H
-
-#include <mach/map.h>
-#include <linux/platform_data/video-nuc900fb.h>
-
-enum nuc900_lcddrv_type {
- LCDDRV_NUC910,
- LCDDRV_NUC930,
- LCDDRV_NUC932,
- LCDDRV_NUC950,
- LCDDRV_NUC960,
-};
-
-
-#define PALETTE_BUFFER_SIZE 256
-#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */
-
-struct nuc900fb_info {
- struct device *dev;
- struct clk *clk;
-
- struct resource *mem;
- void __iomem *io;
- void __iomem *irq_base;
- int drv_type;
- struct nuc900fb_hw regs;
- unsigned long clk_rate;
-
-#ifdef CONFIG_CPU_FREQ
- struct notifier_block freq_transition;
-#endif
-
- /* keep these registers in case we need to re-write palette */
- u32 palette_buffer[PALETTE_BUFFER_SIZE];
- u32 pseudo_pal[16];
-};
-
-int nuc900fb_init(void);
-
-#endif /* __NUC900FB_H */
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index 90eca64e3144..702cca59bda1 100644
--- a/drivers/video/fbdev/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -447,6 +447,7 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
return 0;
case 12:
var->bits_per_pixel = 16;
+ /* fall through */
case 16:
if (plane->fbdev->panel->bpp == 12)
plane->color_mode = OMAPFB_COLOR_RGB444;
@@ -1534,20 +1535,27 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
case OMAPFB_ACTIVE:
for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
unregister_framebuffer(fbdev->fb_info[i]);
+ /* fall through */
case 7:
omapfb_unregister_sysfs(fbdev);
+ /* fall through */
case 6:
if (fbdev->panel->disable)
fbdev->panel->disable(fbdev->panel);
+ /* fall through */
case 5:
omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+ /* fall through */
case 4:
planes_cleanup(fbdev);
+ /* fall through */
case 3:
ctrl_cleanup(fbdev);
+ /* fall through */
case 2:
if (fbdev->panel->cleanup)
fbdev->panel->cleanup(fbdev->panel);
+ /* fall through */
case 1:
dev_set_drvdata(fbdev->dev, NULL);
kfree(fbdev);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index c8be1c4f5b55..bdc08244a648 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -566,13 +566,17 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
unmap_release:
err_idx = i;
- i = head;
+
+ if (indirect)
+ i = 0;
+ else
+ i = head;
for (n = 0; n < total_sg; n++) {
if (i == err_idx)
break;
vring_unmap_one_split(vq, &desc[i]);
- i = virtio16_to_cpu(_vq->vdev, vq->split.vring.desc[i].next);
+ i = virtio16_to_cpu(_vq->vdev, desc[i].next);
}
if (indirect)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8188963a405b..a45f9e3e442b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -551,7 +551,7 @@ config OMAP_WATCHDOG
config PNX4008_WATCHDOG
tristate "LPC32XX Watchdog"
- depends on ARCH_LPC32XX
+ depends on ARCH_LPC32XX || COMPILE_TEST
select WATCHDOG_CORE
help
Say Y here if to include support for the watchdog timer
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index b9b2d06b3879..668a1c704f28 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -235,6 +235,7 @@ static long ar7_wdt_ioctl(struct file *file,
ar7_wdt_update_margin(new_margin);
ar7_wdt_kick(1);
spin_unlock(&wdt_lock);
+ /* Fall through */
case WDIOC_GETTIMEOUT:
if (put_user(margin, (int *)arg))
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 1b2cf5b95a89..c3c93e00b320 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -651,7 +651,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EINVAL;
pcwd_keepalive();
- /* Fall */
+ /* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, argp);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 7b446b696f2b..e0ea133c1690 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -30,7 +30,6 @@
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/reboot.h>
-#include <mach/hardware.h>
/* WatchDog Timer - Chapter 23 Page 207 */
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 41a2a11535a6..b35f7be20c00 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -134,7 +134,7 @@ static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EINVAL;
riowd_timeout = (new_margin + 59) / 60;
riowd_writereg(p, riowd_timeout, WDTO_INDEX);
- /* Fall */
+ /* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(riowd_timeout * 60, (int __user *)argp);
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c
index 5a6ced7a7e8f..202fc8d8ca5f 100644
--- a/drivers/watchdog/sb_wdog.c
+++ b/drivers/watchdog/sb_wdog.c
@@ -202,6 +202,7 @@ static long sbwdog_ioctl(struct file *file, unsigned int cmd,
timeout = time;
sbwdog_set(user_dog, timeout);
sbwdog_pet(user_dog);
+ /* Fall through */
case WDIOC_GETTIMEOUT:
/*
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
index efd7996694de..46268309ee9b 100644
--- a/drivers/watchdog/scx200_wdt.c
+++ b/drivers/watchdog/scx200_wdt.c
@@ -186,6 +186,7 @@ static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
margin = new_margin;
scx200_wdt_update_margin();
scx200_wdt_ping();
+ /* Fall through */
case WDIOC_GETTIMEOUT:
if (put_user(margin, p))
return -EFAULT;
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 0650100fad00..7d278b37e083 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -389,7 +389,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (wdt_set_heartbeat(new_heartbeat))
return -EINVAL;
wdt_ping();
- /* Fall */
+ /* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, p);
default:
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
index 4eacfb1ce1ac..eb729d704836 100644
--- a/drivers/watchdog/wdt285.c
+++ b/drivers/watchdog/wdt285.c
@@ -168,7 +168,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
soft_margin = new_margin;
reload = soft_margin * (mem_fclk_21285 / 256);
watchdog_ping();
- /* Fall */
+ /* Fall through */
case WDIOC_GETTIMEOUT:
ret = put_user(soft_margin, int_arg);
break;
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 567005d7598e..5c52c73e1839 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -398,7 +398,7 @@ static long wdt977_ioctl(struct file *file, unsigned int cmd,
return -EINVAL;
wdt977_keepalive();
- /* Fall */
+ /* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, uarg.i);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 4c339c7e66e5..a446a7221e13 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -1143,7 +1143,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
goto out_put_map;
if (!use_ptemod) {
- err = vm_map_pages(vma, map->pages, map->count);
+ err = vm_map_pages_zero(vma, map->pages, map->count);
if (err)
goto out_put_map;
} else {
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 2f5ce7230a43..c6070e70dd73 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -724,25 +724,6 @@ static long privcmd_ioctl_restrict(struct file *file, void __user *udata)
return 0;
}
-struct remap_pfn {
- struct mm_struct *mm;
- struct page **pages;
- pgprot_t prot;
- unsigned long i;
-};
-
-static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
-{
- struct remap_pfn *r = data;
- struct page *page = r->pages[r->i];
- pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot));
-
- set_pte_at(r->mm, addr, ptep, pte);
- r->i++;
-
- return 0;
-}
-
static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
{
struct privcmd_data *data = file->private_data;
@@ -774,7 +755,8 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
goto out;
}
- if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ if (IS_ENABLED(CONFIG_XEN_AUTO_XLATE) &&
+ xen_feature(XENFEAT_auto_translated_physmap)) {
unsigned int nr = DIV_ROUND_UP(kdata.num, XEN_PFN_PER_PAGE);
struct page **pages;
unsigned int i;
@@ -808,16 +790,9 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
if (rc)
goto out;
- if (xen_feature(XENFEAT_auto_translated_physmap)) {
- struct remap_pfn r = {
- .mm = vma->vm_mm,
- .pages = vma->vm_private_data,
- .prot = vma->vm_page_prot,
- };
-
- rc = apply_to_page_range(r.mm, kdata.addr,
- kdata.num << PAGE_SHIFT,
- remap_pfn_fn, &r);
+ if (IS_ENABLED(CONFIG_XEN_AUTO_XLATE) &&
+ xen_feature(XENFEAT_auto_translated_physmap)) {
+ rc = xen_remap_vma_range(vma, kdata.addr, kdata.num << PAGE_SHIFT);
} else {
unsigned int domid =
(xdata.flags & XENMEM_rsrc_acq_caller_owned) ?
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index cfbe46785a3b..adcabd9473eb 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -83,34 +83,18 @@ static inline dma_addr_t xen_virt_to_bus(void *address)
return xen_phys_to_bus(virt_to_phys(address));
}
-static int check_pages_physically_contiguous(unsigned long xen_pfn,
- unsigned int offset,
- size_t length)
+static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
{
- unsigned long next_bfn;
- int i;
- int nr_pages;
+ unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p);
+ unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size);
next_bfn = pfn_to_bfn(xen_pfn);
- nr_pages = (offset + length + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT;
- for (i = 1; i < nr_pages; i++) {
+ for (i = 1; i < nr_pages; i++)
if (pfn_to_bfn(++xen_pfn) != ++next_bfn)
- return 0;
- }
- return 1;
-}
+ return 1;
-static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
-{
- unsigned long xen_pfn = XEN_PFN_DOWN(p);
- unsigned int offset = p & ~XEN_PAGE_MASK;
-
- if (offset + size <= XEN_PAGE_SIZE)
- return 0;
- if (check_pages_physically_contiguous(xen_pfn, offset, size))
- return 0;
- return 1;
+ return 0;
}
static int is_xen_swiotlb_buffer(dma_addr_t dma_addr)
@@ -338,6 +322,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
return NULL;
}
+ SetPageXenRemapped(virt_to_page(ret));
}
memset(ret, 0, size);
return ret;
@@ -361,8 +346,9 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
/* Convert the size to actually allocated. */
size = 1UL << (order + XEN_PAGE_SHIFT);
- if (((dev_addr + size - 1 <= dma_mask)) ||
- range_straddles_page_boundary(phys, size))
+ if (!WARN_ON((dev_addr + size - 1 > dma_mask) ||
+ range_straddles_page_boundary(phys, size)) &&
+ TestClearPageXenRemapped(virt_to_page(vaddr)))
xen_destroy_contiguous_region(phys, order);
xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
@@ -400,8 +386,8 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
*/
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
- map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir,
- attrs);
+ map = swiotlb_tbl_map_single(dev, start_dma_addr, phys,
+ size, size, dir, attrs);
if (map == (phys_addr_t)DMA_MAPPING_ERROR)
return DMA_MAPPING_ERROR;
@@ -411,7 +397,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
* Ensure that the address returned is DMA'ble
*/
if (unlikely(!dma_capable(dev, dev_addr, size))) {
- swiotlb_tbl_unmap_single(dev, map, size, dir,
+ swiotlb_tbl_unmap_single(dev, map, size, size, dir,
attrs | DMA_ATTR_SKIP_CPU_SYNC);
return DMA_MAPPING_ERROR;
}
@@ -447,7 +433,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
/* NOTE: We use dev_addr here, not paddr! */
if (is_xen_swiotlb_buffer(dev_addr))
- swiotlb_tbl_unmap_single(hwdev, paddr, size, dir, attrs);
+ swiotlb_tbl_unmap_single(hwdev, paddr, size, size, dir, attrs);
}
static void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
index 73427d8e0116..e5694133ebe5 100644
--- a/drivers/xen/xen-pciback/conf_space_capability.c
+++ b/drivers/xen/xen-pciback/conf_space_capability.c
@@ -116,13 +116,12 @@ static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
{
int err;
u16 old_value;
- pci_power_t new_state, old_state;
+ pci_power_t new_state;
err = pci_read_config_word(dev, offset, &old_value);
if (err)
goto out;
- old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
new_value &= PM_OK_BITS;
diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
index ba883a80b3c0..7b1077f0abcb 100644
--- a/drivers/xen/xlate_mmu.c
+++ b/drivers/xen/xlate_mmu.c
@@ -262,3 +262,35 @@ int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt,
return 0;
}
EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages);
+
+struct remap_pfn {
+ struct mm_struct *mm;
+ struct page **pages;
+ pgprot_t prot;
+ unsigned long i;
+};
+
+static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
+{
+ struct remap_pfn *r = data;
+ struct page *page = r->pages[r->i];
+ pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot));
+
+ set_pte_at(r->mm, addr, ptep, pte);
+ r->i++;
+
+ return 0;
+}
+
+/* Used by the privcmd module, but has to be built-in on ARM */
+int xen_remap_vma_range(struct vm_area_struct *vma, unsigned long addr, unsigned long len)
+{
+ struct remap_pfn r = {
+ .mm = vma->vm_mm,
+ .pages = vma->vm_private_data,
+ .prot = vma->vm_page_prot,
+ };
+
+ return apply_to_page_range(vma->vm_mm, addr, len, remap_pfn_fn, &r);
+}
+EXPORT_SYMBOL_GPL(xen_remap_vma_range);
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index a2a87117d262..fd5133e26a38 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -74,6 +74,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
cell = rcu_dereference_raw(net->ws_cell);
if (cell) {
afs_get_cell(cell);
+ ret = 0;
break;
}
ret = -EDESTADDRREQ;
@@ -108,6 +109,9 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
done_seqretry(&net->cells_lock, seq);
+ if (ret != 0 && cell)
+ afs_put_cell(net, cell);
+
return ret == 0 ? cell : ERR_PTR(ret);
}
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 4f1b6f466ff5..b86195e4dc6c 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -505,18 +505,14 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
struct afs_call *call = container_of(work, struct afs_call, work);
struct afs_uuid *r = call->request;
- struct {
- __be32 match;
- } reply;
-
_enter("");
if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
- reply.match = htonl(0);
+ afs_send_empty_reply(call);
else
- reply.match = htonl(1);
+ rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
+ 1, 1, "K-1");
- afs_send_simple_reply(call, &reply, sizeof(reply));
afs_put_call(call);
_leave("");
}
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index e640d67274be..139b4e3cc946 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -440,7 +440,7 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
* iterate through the data blob that lists the contents of an AFS directory
*/
static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
- struct key *key)
+ struct key *key, afs_dataversion_t *_dir_version)
{
struct afs_vnode *dvnode = AFS_FS_I(dir);
struct afs_xdr_dir_page *dbuf;
@@ -460,6 +460,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
req = afs_read_dir(dvnode, key);
if (IS_ERR(req))
return PTR_ERR(req);
+ *_dir_version = req->data_version;
/* round the file position up to the next entry boundary */
ctx->pos += sizeof(union afs_xdr_dirent) - 1;
@@ -514,7 +515,10 @@ out:
*/
static int afs_readdir(struct file *file, struct dir_context *ctx)
{
- return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file));
+ afs_dataversion_t dir_version;
+
+ return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
+ &dir_version);
}
/*
@@ -555,7 +559,8 @@ static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
* - just returns the FID the dentry name maps to if found
*/
static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
- struct afs_fid *fid, struct key *key)
+ struct afs_fid *fid, struct key *key,
+ afs_dataversion_t *_dir_version)
{
struct afs_super_info *as = dir->i_sb->s_fs_info;
struct afs_lookup_one_cookie cookie = {
@@ -568,7 +573,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
/* search the directory */
- ret = afs_dir_iterate(dir, &cookie.ctx, key);
+ ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
if (ret < 0) {
_leave(" = %d [iter]", ret);
return ret;
@@ -642,6 +647,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
struct afs_server *server;
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
struct inode *inode = NULL, *ti;
+ afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
int ret, i;
_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -669,12 +675,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
cookie->fids[i].vid = as->volume->vid;
/* search the directory */
- ret = afs_dir_iterate(dir, &cookie->ctx, key);
+ ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
if (ret < 0) {
inode = ERR_PTR(ret);
goto out;
}
+ dentry->d_fsdata = (void *)(unsigned long)data_version;
+
inode = ERR_PTR(-ENOENT);
if (!cookie->found)
goto out;
@@ -951,7 +959,8 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
inode ? AFS_FS_I(inode) : NULL);
} else {
trace_afs_lookup(dvnode, &dentry->d_name,
- inode ? AFS_FS_I(inode) : NULL);
+ IS_ERR_OR_NULL(inode) ? NULL
+ : AFS_FS_I(inode));
}
return d;
}
@@ -968,7 +977,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
struct dentry *parent;
struct inode *inode;
struct key *key;
- long dir_version, de_version;
+ afs_dataversion_t dir_version;
+ long de_version;
int ret;
if (flags & LOOKUP_RCU)
@@ -1014,20 +1024,20 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
* on a 32-bit system, we only have 32 bits in the dentry to store the
* version.
*/
- dir_version = (long)dir->status.data_version;
+ dir_version = dir->status.data_version;
de_version = (long)dentry->d_fsdata;
- if (de_version == dir_version)
- goto out_valid;
+ if (de_version == (long)dir_version)
+ goto out_valid_noupdate;
- dir_version = (long)dir->invalid_before;
- if (de_version - dir_version >= 0)
+ dir_version = dir->invalid_before;
+ if (de_version - (long)dir_version >= 0)
goto out_valid;
_debug("dir modified");
afs_stat_v(dir, n_reval);
/* search the directory for this vnode */
- ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key);
+ ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
switch (ret) {
case 0:
/* the filename maps to something */
@@ -1080,7 +1090,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
}
out_valid:
- dentry->d_fsdata = (void *)dir_version;
+ dentry->d_fsdata = (void *)(unsigned long)dir_version;
+out_valid_noupdate:
dput(parent);
key_put(key);
_leave(" = 1 [valid]");
@@ -1186,6 +1197,20 @@ static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
}
/*
+ * Note that a dentry got changed. We need to set d_fsdata to the data version
+ * number derived from the result of the operation. It doesn't matter if
+ * d_fsdata goes backwards as we'll just revalidate.
+ */
+static void afs_update_dentry_version(struct afs_fs_cursor *fc,
+ struct dentry *dentry,
+ struct afs_status_cb *scb)
+{
+ if (fc->ac.error == 0)
+ dentry->d_fsdata =
+ (void *)(unsigned long)scb->status.data_version;
+}
+
+/*
* create a directory on an AFS filesystem
*/
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@ -1227,6 +1252,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
afs_check_for_remote_deletion(&fc, dvnode);
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
&data_version, &scb[0]);
+ afs_update_dentry_version(&fc, dentry, &scb[0]);
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
ret = afs_end_vnode_operation(&fc);
if (ret < 0)
@@ -1319,6 +1345,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
&data_version, scb);
+ afs_update_dentry_version(&fc, dentry, scb);
ret = afs_end_vnode_operation(&fc);
if (ret == 0) {
afs_dir_remove_subdir(dentry);
@@ -1458,6 +1485,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
&data_version, &scb[0]);
afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
&data_version_2, &scb[1]);
+ afs_update_dentry_version(&fc, dentry, &scb[0]);
ret = afs_end_vnode_operation(&fc);
if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
ret = afs_dir_remove_link(dvnode, dentry, key);
@@ -1526,6 +1554,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
afs_check_for_remote_deletion(&fc, dvnode);
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
&data_version, &scb[0]);
+ afs_update_dentry_version(&fc, dentry, &scb[0]);
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
ret = afs_end_vnode_operation(&fc);
if (ret < 0)
@@ -1607,6 +1636,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
NULL, &scb[1]);
ihold(&vnode->vfs_inode);
+ afs_update_dentry_version(&fc, dentry, &scb[0]);
d_instantiate(dentry, &vnode->vfs_inode);
mutex_unlock(&vnode->io_lock);
@@ -1686,6 +1716,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
afs_check_for_remote_deletion(&fc, dvnode);
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
&data_version, &scb[0]);
+ afs_update_dentry_version(&fc, dentry, &scb[0]);
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
ret = afs_end_vnode_operation(&fc);
if (ret < 0)
@@ -1791,6 +1822,17 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
}
+ /* This bit is potentially nasty as there's a potential race with
+ * afs_d_revalidate{,_rcu}(). We have to change d_fsdata on the dentry
+ * to reflect it's new parent's new data_version after the op, but
+ * d_revalidate may see old_dentry between the op having taken place
+ * and the version being updated.
+ *
+ * So drop the old_dentry for now to make other threads go through
+ * lookup instead - which we hold a lock against.
+ */
+ d_drop(old_dentry);
+
ret = -ERESTARTSYS;
if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
afs_dataversion_t orig_data_version;
@@ -1802,9 +1844,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (orig_dvnode != new_dvnode) {
if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
afs_end_vnode_operation(&fc);
- goto error_rehash;
+ goto error_rehash_old;
}
- new_data_version = new_dvnode->status.data_version;
+ new_data_version = new_dvnode->status.data_version + 1;
} else {
new_data_version = orig_data_version;
new_scb = &scb[0];
@@ -1827,7 +1869,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
ret = afs_end_vnode_operation(&fc);
if (ret < 0)
- goto error_rehash;
+ goto error_rehash_old;
}
if (ret == 0) {
@@ -1853,10 +1895,26 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
drop_nlink(new_inode);
spin_unlock(&new_inode->i_lock);
}
+
+ /* Now we can update d_fsdata on the dentries to reflect their
+ * new parent's data_version.
+ *
+ * Note that if we ever implement RENAME_EXCHANGE, we'll have
+ * to update both dentries with opposing dir versions.
+ */
+ if (new_dvnode != orig_dvnode) {
+ afs_update_dentry_version(&fc, old_dentry, &scb[1]);
+ afs_update_dentry_version(&fc, new_dentry, &scb[1]);
+ } else {
+ afs_update_dentry_version(&fc, old_dentry, &scb[0]);
+ afs_update_dentry_version(&fc, new_dentry, &scb[0]);
+ }
d_move(old_dentry, new_dentry);
goto error_tmp;
}
+error_rehash_old:
+ d_rehash(new_dentry);
error_rehash:
if (rehash)
d_rehash(rehash);
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 56b69576274d..dd3c55c9101c 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -191,11 +191,13 @@ void afs_put_read(struct afs_read *req)
int i;
if (refcount_dec_and_test(&req->usage)) {
- for (i = 0; i < req->nr_pages; i++)
- if (req->pages[i])
- put_page(req->pages[i]);
- if (req->pages != req->array)
- kfree(req->pages);
+ if (req->pages) {
+ for (i = 0; i < req->nr_pages; i++)
+ if (req->pages[i])
+ put_page(req->pages[i]);
+ if (req->pages != req->array)
+ kfree(req->pages);
+ }
kfree(req);
}
}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 1ce73e014139..114f281f3687 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -339,8 +339,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
call->tmp_u = htonl(0);
afs_extract_to_tmp(call);
}
+ /* Fall through */
- /* Fall through - and extract the returned data length */
+ /* extract the returned data length */
case 1:
_debug("extract data length");
ret = afs_extract_data(call, true);
@@ -366,8 +367,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
call->bvec[0].bv_page = req->pages[req->index];
iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
ASSERTCMP(size, <=, PAGE_SIZE);
+ /* Fall through */
- /* Fall through - and extract the returned data */
+ /* extract the returned data */
case 2:
_debug("extract data %zu/%llu",
iov_iter_count(&call->iter), req->remain);
@@ -394,8 +396,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
/* Discard any excess data the server gave us */
iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
call->unmarshall = 3;
-
/* Fall through */
+
case 3:
_debug("extract discard %zu/%llu",
iov_iter_count(&call->iter), req->actual_len - req->len);
@@ -407,8 +409,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
no_more_data:
call->unmarshall = 4;
afs_extract_to_buf(call, (21 + 3 + 6) * 4);
+ /* Fall through */
- /* Fall through - and extract the metadata */
+ /* extract the metadata */
case 4:
ret = afs_extract_data(call, false);
if (ret < 0)
@@ -1471,8 +1474,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
case 0:
call->unmarshall++;
afs_extract_to_buf(call, 12 * 4);
+ /* Fall through */
- /* Fall through - and extract the returned status record */
+ /* extract the returned status record */
case 1:
_debug("extract status");
ret = afs_extract_data(call, true);
@@ -1483,8 +1487,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus);
call->unmarshall++;
afs_extract_to_tmp(call);
+ /* Fall through */
- /* Fall through - and extract the volume name length */
+ /* extract the volume name length */
case 2:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1498,8 +1503,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the volume name */
+ /* extract the volume name */
case 3:
_debug("extract volname");
ret = afs_extract_data(call, true);
@@ -1511,8 +1517,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
_debug("volname '%s'", p);
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the offline message length */
+ /* extract the offline message length */
case 4:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1526,8 +1533,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the offline message */
+ /* extract the offline message */
case 5:
_debug("extract offline");
ret = afs_extract_data(call, true);
@@ -1540,8 +1548,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the message of the day length */
+ /* extract the message of the day length */
case 6:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1555,8 +1564,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the message of the day */
+ /* extract the message of the day */
case 7:
_debug("extract motd");
ret = afs_extract_data(call, false);
@@ -1850,8 +1860,9 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the capabilities word count */
+ /* Extract the capabilities word count */
case 1:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1863,8 +1874,9 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
call->count2 = count;
iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract capabilities words */
+ /* Extract capabilities words */
case 2:
ret = afs_extract_data(call, false);
if (ret < 0)
@@ -2020,9 +2032,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
/* Extract the file status count and array in two steps */
- /* Fall through */
case 1:
_debug("extract status count");
ret = afs_extract_data(call, true);
@@ -2039,8 +2051,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->unmarshall++;
more_counts:
afs_extract_to_buf(call, 21 * sizeof(__be32));
-
/* Fall through */
+
case 2:
_debug("extract status array %u", call->count);
ret = afs_extract_data(call, true);
@@ -2060,9 +2072,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->count = 0;
call->unmarshall++;
afs_extract_to_tmp(call);
+ /* Fall through */
/* Extract the callback count and array in two steps */
- /* Fall through */
case 3:
_debug("extract CB count");
ret = afs_extract_data(call, true);
@@ -2078,8 +2090,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->unmarshall++;
more_cbs:
afs_extract_to_buf(call, 3 * sizeof(__be32));
-
/* Fall through */
+
case 4:
_debug("extract CB array");
ret = afs_extract_data(call, true);
@@ -2096,8 +2108,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
afs_extract_to_buf(call, 6 * sizeof(__be32));
call->unmarshall++;
-
/* Fall through */
+
case 5:
ret = afs_extract_data(call, false);
if (ret < 0)
@@ -2193,6 +2205,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
/* extract the returned data length */
case 1:
@@ -2210,6 +2223,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
acl->size = call->count2;
afs_extract_begin(call, acl->data, size);
call->unmarshall++;
+ /* Fall through */
/* extract the returned data */
case 2:
@@ -2219,6 +2233,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
afs_extract_to_buf(call, (21 + 6) * 4);
call->unmarshall++;
+ /* Fall through */
/* extract the metadata */
case 3:
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index d7e0fd3c00df..cfb0ac4bd039 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -56,23 +56,24 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
struct afs_uuid__xdr *xdr;
struct afs_uuid *uuid;
int j;
+ int n = entry->nr_servers;
tmp = ntohl(uvldb->serverFlags[i]);
if (tmp & AFS_VLSF_DONTUSE ||
(new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
continue;
if (tmp & AFS_VLSF_RWVOL) {
- entry->fs_mask[i] |= AFS_VOL_VTM_RW;
+ entry->fs_mask[n] |= AFS_VOL_VTM_RW;
if (vlflags & AFS_VLF_BACKEXISTS)
- entry->fs_mask[i] |= AFS_VOL_VTM_BAK;
+ entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
}
if (tmp & AFS_VLSF_ROVOL)
- entry->fs_mask[i] |= AFS_VOL_VTM_RO;
- if (!entry->fs_mask[i])
+ entry->fs_mask[n] |= AFS_VOL_VTM_RO;
+ if (!entry->fs_mask[n])
continue;
xdr = &uvldb->serverNumber[i];
- uuid = (struct afs_uuid *)&entry->fs_server[i];
+ uuid = (struct afs_uuid *)&entry->fs_server[n];
uuid->time_low = xdr->time_low;
uuid->time_mid = htons(ntohl(xdr->time_mid));
uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version));
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
index 18722aaeda33..ca2452806ebf 100644
--- a/fs/afs/yfsclient.c
+++ b/fs/afs/yfsclient.c
@@ -450,8 +450,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
req->offset = req->pos & (PAGE_SIZE - 1);
afs_extract_to_tmp64(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the returned data length */
+ /* extract the returned data length */
case 1:
_debug("extract data length");
ret = afs_extract_data(call, true);
@@ -477,8 +478,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
call->bvec[0].bv_page = req->pages[req->index];
iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
ASSERTCMP(size, <=, PAGE_SIZE);
+ /* Fall through */
- /* Fall through - and extract the returned data */
+ /* extract the returned data */
case 2:
_debug("extract data %zu/%llu",
iov_iter_count(&call->iter), req->remain);
@@ -505,8 +507,8 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
/* Discard any excess data the server gave us */
iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
call->unmarshall = 3;
-
/* Fall through */
+
case 3:
_debug("extract discard %zu/%llu",
iov_iter_count(&call->iter), req->actual_len - req->len);
@@ -521,8 +523,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
sizeof(struct yfs_xdr_YFSFetchStatus) +
sizeof(struct yfs_xdr_YFSCallBack) +
sizeof(struct yfs_xdr_YFSVolSync));
+ /* Fall through */
- /* Fall through - and extract the metadata */
+ /* extract the metadata */
case 4:
ret = afs_extract_data(call, false);
if (ret < 0)
@@ -539,8 +542,8 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
req->file_size = call->out_scb->status.size;
call->unmarshall++;
-
/* Fall through */
+
case 5:
break;
}
@@ -1429,8 +1432,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
case 0:
call->unmarshall++;
afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));
+ /* Fall through */
- /* Fall through - and extract the returned status record */
+ /* extract the returned status record */
case 1:
_debug("extract status");
ret = afs_extract_data(call, true);
@@ -1441,8 +1445,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
xdr_decode_YFSFetchVolumeStatus(&bp, call->out_volstatus);
call->unmarshall++;
afs_extract_to_tmp(call);
+ /* Fall through */
- /* Fall through - and extract the volume name length */
+ /* extract the volume name length */
case 2:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1456,8 +1461,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the volume name */
+ /* extract the volume name */
case 3:
_debug("extract volname");
ret = afs_extract_data(call, true);
@@ -1469,8 +1475,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
_debug("volname '%s'", p);
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the offline message length */
+ /* extract the offline message length */
case 4:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1484,8 +1491,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the offline message */
+ /* extract the offline message */
case 5:
_debug("extract offline");
ret = afs_extract_data(call, true);
@@ -1498,8 +1506,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the message of the day length */
+ /* extract the message of the day length */
case 6:
ret = afs_extract_data(call, true);
if (ret < 0)
@@ -1513,8 +1522,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
size = (call->count + 3) & ~3; /* It's padded */
afs_extract_to_buf(call, size);
call->unmarshall++;
+ /* Fall through */
- /* Fall through - and extract the message of the day */
+ /* extract the message of the day */
case 7:
_debug("extract motd");
ret = afs_extract_data(call, false);
@@ -1526,8 +1536,8 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
_debug("motd '%s'", p);
call->unmarshall++;
-
/* Fall through */
+
case 8:
break;
}
@@ -1805,9 +1815,9 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
/* Extract the file status count and array in two steps */
- /* Fall through */
case 1:
_debug("extract status count");
ret = afs_extract_data(call, true);
@@ -1824,8 +1834,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->unmarshall++;
more_counts:
afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));
-
/* Fall through */
+
case 2:
_debug("extract status array %u", call->count);
ret = afs_extract_data(call, true);
@@ -1845,9 +1855,9 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->count = 0;
call->unmarshall++;
afs_extract_to_tmp(call);
+ /* Fall through */
/* Extract the callback count and array in two steps */
- /* Fall through */
case 3:
_debug("extract CB count");
ret = afs_extract_data(call, true);
@@ -1863,8 +1873,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
call->unmarshall++;
more_cbs:
afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));
-
/* Fall through */
+
case 4:
_debug("extract CB array");
ret = afs_extract_data(call, true);
@@ -1881,8 +1891,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));
call->unmarshall++;
-
/* Fall through */
+
case 5:
ret = afs_extract_data(call, false);
if (ret < 0)
@@ -1892,8 +1902,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
xdr_decode_YFSVolSync(&bp, call->out_volsync);
call->unmarshall++;
-
/* Fall through */
+
case 6:
break;
}
@@ -1978,6 +1988,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
case 0:
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
/* Extract the file ACL length */
case 1:
@@ -1999,6 +2010,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
iov_iter_discard(&call->iter, READ, size);
}
call->unmarshall++;
+ /* Fall through */
/* Extract the file ACL */
case 2:
@@ -2008,6 +2020,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
afs_extract_to_tmp(call);
call->unmarshall++;
+ /* Fall through */
/* Extract the volume ACL length */
case 3:
@@ -2029,6 +2042,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
iov_iter_discard(&call->iter, READ, size);
}
call->unmarshall++;
+ /* Fall through */
/* Extract the volume ACL */
case 4:
@@ -2041,6 +2055,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
sizeof(struct yfs_xdr_YFSFetchStatus) +
sizeof(struct yfs_xdr_YFSVolSync));
call->unmarshall++;
+ /* Fall through */
/* extract the metadata */
case 5:
@@ -2057,6 +2072,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
xdr_decode_YFSVolSync(&bp, call->out_volsync);
call->unmarshall++;
+ /* Fall through */
case 6:
break;
@@ -2155,7 +2171,7 @@ int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl
key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
size = round_up(acl->size, 4);
- call = afs_alloc_flat_call(net, &yfs_RXYFSStoreStatus,
+ call = afs_alloc_flat_call(net, &yfs_RXYFSStoreOpaqueACL2,
sizeof(__be32) * 2 +
sizeof(struct yfs_xdr_YFSFid) +
sizeof(__be32) + size,
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 4707dfff991b..677cb364d33f 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1139,8 +1139,7 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
* Pointer to the block device containing @bdev on success, ERR_PTR()
* value on failure.
*/
-static struct block_device *bd_start_claiming(struct block_device *bdev,
- void *holder)
+struct block_device *bd_start_claiming(struct block_device *bdev, void *holder)
{
struct gendisk *disk;
struct block_device *whole;
@@ -1187,6 +1186,62 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
return ERR_PTR(err);
}
}
+EXPORT_SYMBOL(bd_start_claiming);
+
+static void bd_clear_claiming(struct block_device *whole, void *holder)
+{
+ lockdep_assert_held(&bdev_lock);
+ /* tell others that we're done */
+ BUG_ON(whole->bd_claiming != holder);
+ whole->bd_claiming = NULL;
+ wake_up_bit(&whole->bd_claiming, 0);
+}
+
+/**
+ * bd_finish_claiming - finish claiming of a block device
+ * @bdev: block device of interest
+ * @whole: whole block device (returned from bd_start_claiming())
+ * @holder: holder that has claimed @bdev
+ *
+ * Finish exclusive open of a block device. Mark the device as exlusively
+ * open by the holder and wake up all waiters for exclusive open to finish.
+ */
+void bd_finish_claiming(struct block_device *bdev, struct block_device *whole,
+ void *holder)
+{
+ spin_lock(&bdev_lock);
+ BUG_ON(!bd_may_claim(bdev, whole, holder));
+ /*
+ * Note that for a whole device bd_holders will be incremented twice,
+ * and bd_holder will be set to bd_may_claim before being set to holder
+ */
+ whole->bd_holders++;
+ whole->bd_holder = bd_may_claim;
+ bdev->bd_holders++;
+ bdev->bd_holder = holder;
+ bd_clear_claiming(whole, holder);
+ spin_unlock(&bdev_lock);
+}
+EXPORT_SYMBOL(bd_finish_claiming);
+
+/**
+ * bd_abort_claiming - abort claiming of a block device
+ * @bdev: block device of interest
+ * @whole: whole block device (returned from bd_start_claiming())
+ * @holder: holder that has claimed @bdev
+ *
+ * Abort claiming of a block device when the exclusive open failed. This can be
+ * also used when exclusive open is not actually desired and we just needed
+ * to block other exclusive openers for a while.
+ */
+void bd_abort_claiming(struct block_device *bdev, struct block_device *whole,
+ void *holder)
+{
+ spin_lock(&bdev_lock);
+ bd_clear_claiming(whole, holder);
+ spin_unlock(&bdev_lock);
+}
+EXPORT_SYMBOL(bd_abort_claiming);
#ifdef CONFIG_SYSFS
struct bd_holder_disk {
@@ -1656,29 +1711,10 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
/* finish claiming */
mutex_lock(&bdev->bd_mutex);
- spin_lock(&bdev_lock);
-
- if (!res) {
- BUG_ON(!bd_may_claim(bdev, whole, holder));
- /*
- * Note that for a whole device bd_holders
- * will be incremented twice, and bd_holder
- * will be set to bd_may_claim before being
- * set to holder
- */
- whole->bd_holders++;
- whole->bd_holder = bd_may_claim;
- bdev->bd_holders++;
- bdev->bd_holder = holder;
- }
-
- /* tell others that we're done */
- BUG_ON(whole->bd_claiming != holder);
- whole->bd_claiming = NULL;
- wake_up_bit(&whole->bd_claiming, 0);
-
- spin_unlock(&bdev_lock);
-
+ if (!res)
+ bd_finish_claiming(bdev, whole, holder);
+ else
+ bd_abort_claiming(bdev, whole, holder);
/*
* Block event polling for write claims if requested. Any
* write holder makes the write_holder state stick until
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 89116afda7a2..e5d85311d5d5 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1483,7 +1483,7 @@ int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
ulist_init(roots);
ulist_init(tmp);
- trans = btrfs_attach_transaction(root);
+ trans = btrfs_join_transaction_nostart(root);
if (IS_ERR(trans)) {
if (PTR_ERR(trans) != -ENOENT && PTR_ERR(trans) != -EROFS) {
ret = PTR_ERR(trans);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 299e11e6c554..94660063a162 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -401,7 +401,6 @@ struct btrfs_dev_replace {
struct raid_kobject {
u64 flags;
struct kobject kobj;
- struct list_head list;
};
/*
@@ -915,8 +914,6 @@ struct btrfs_fs_info {
u32 thread_pool_size;
struct kobject *space_info_kobj;
- struct list_head pending_raid_kobjs;
- spinlock_t pending_raid_kobjs_lock; /* uncontended */
u64 total_pinned;
@@ -2698,7 +2695,6 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr);
int btrfs_make_block_group(struct btrfs_trans_handle *trans,
u64 bytes_used, u64 type, u64 chunk_offset,
u64 size);
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info);
struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
struct btrfs_fs_info *fs_info,
const u64 chunk_offset);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5f7ee70b3d1a..97beb351a10c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2683,8 +2683,6 @@ int open_ctree(struct super_block *sb,
INIT_LIST_HEAD(&fs_info->delayed_iputs);
INIT_LIST_HEAD(&fs_info->delalloc_roots);
INIT_LIST_HEAD(&fs_info->caching_block_groups);
- INIT_LIST_HEAD(&fs_info->pending_raid_kobjs);
- spin_lock_init(&fs_info->pending_raid_kobjs_lock);
spin_lock_init(&fs_info->delalloc_root_lock);
spin_lock_init(&fs_info->trans_lock);
spin_lock_init(&fs_info->fs_roots_radix_lock);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d3b58e388535..8b7eb22d508a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4,6 +4,7 @@
*/
#include <linux/sched.h>
+#include <linux/sched/mm.h>
#include <linux/sched/signal.h>
#include <linux/pagemap.h>
#include <linux/writeback.h>
@@ -7888,33 +7889,6 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
return 0;
}
-/* link_block_group will queue up kobjects to add when we're reclaim-safe */
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info)
-{
- struct btrfs_space_info *space_info;
- struct raid_kobject *rkobj;
- LIST_HEAD(list);
- int ret = 0;
-
- spin_lock(&fs_info->pending_raid_kobjs_lock);
- list_splice_init(&fs_info->pending_raid_kobjs, &list);
- spin_unlock(&fs_info->pending_raid_kobjs_lock);
-
- list_for_each_entry(rkobj, &list, list) {
- space_info = btrfs_find_space_info(fs_info, rkobj->flags);
-
- ret = kobject_add(&rkobj->kobj, &space_info->kobj,
- "%s", btrfs_bg_type_to_raid_name(rkobj->flags));
- if (ret) {
- kobject_put(&rkobj->kobj);
- break;
- }
- }
- if (ret)
- btrfs_warn(fs_info,
- "failed to add kobject for block cache, ignoring");
-}
-
static void link_block_group(struct btrfs_block_group_cache *cache)
{
struct btrfs_space_info *space_info = cache->space_info;
@@ -7929,18 +7903,36 @@ static void link_block_group(struct btrfs_block_group_cache *cache)
up_write(&space_info->groups_sem);
if (first) {
- struct raid_kobject *rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS);
+ struct raid_kobject *rkobj;
+ unsigned int nofs_flag;
+ int ret;
+
+ /*
+ * Setup a NOFS context because kobject_add(), deep in its call
+ * chain, does GFP_KERNEL allocations, and we are often called
+ * in a context where if reclaim is triggered we can deadlock
+ * (we are either holding a transaction handle or some lock
+ * required for a transaction commit).
+ */
+ nofs_flag = memalloc_nofs_save();
+ rkobj = kzalloc(sizeof(*rkobj), GFP_KERNEL);
if (!rkobj) {
+ memalloc_nofs_restore(nofs_flag);
btrfs_warn(cache->fs_info,
"couldn't alloc memory for raid level kobject");
return;
}
rkobj->flags = cache->flags;
kobject_init(&rkobj->kobj, &btrfs_raid_ktype);
-
- spin_lock(&fs_info->pending_raid_kobjs_lock);
- list_add_tail(&rkobj->list, &fs_info->pending_raid_kobjs);
- spin_unlock(&fs_info->pending_raid_kobjs_lock);
+ ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s",
+ btrfs_bg_type_to_raid_name(rkobj->flags));
+ memalloc_nofs_restore(nofs_flag);
+ if (ret) {
+ kobject_put(&rkobj->kobj);
+ btrfs_warn(fs_info,
+ "failed to add kobject for block cache, ignoring");
+ return;
+ }
space_info->block_group_kobjs[index] = &rkobj->kobj;
}
}
@@ -8206,7 +8198,6 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
inc_block_group_ro(cache, 1);
}
- btrfs_add_raid_kobjects(info);
btrfs_init_global_block_rsv(info);
ret = check_chunk_block_group_mappings(info);
error:
@@ -8975,6 +8966,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
struct btrfs_device *device;
struct list_head *devices;
u64 group_trimmed;
+ u64 range_end = U64_MAX;
u64 start;
u64 end;
u64 trimmed = 0;
@@ -8984,16 +8976,23 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
int dev_ret = 0;
int ret = 0;
+ /*
+ * Check range overflow if range->len is set.
+ * The default range->len is U64_MAX.
+ */
+ if (range->len != U64_MAX &&
+ check_add_overflow(range->start, range->len, &range_end))
+ return -EINVAL;
+
cache = btrfs_lookup_first_block_group(fs_info, range->start);
for (; cache; cache = next_block_group(cache)) {
- if (cache->key.objectid >= (range->start + range->len)) {
+ if (cache->key.objectid >= range_end) {
btrfs_put_block_group(cache);
break;
}
start = max(range->start, cache->key.objectid);
- end = min(range->start + range->len,
- cache->key.objectid + cache->key.offset);
+ end = min(range_end, cache->key.objectid + cache->key.offset);
if (end - start >= range->minlen) {
if (!block_group_cache_done(cache)) {
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 1ff438fd5bc2..eeb75281894e 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
TASK_UNINTERRUPTIBLE);
}
+static void end_extent_buffer_writeback(struct extent_buffer *eb)
+{
+ clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
+ smp_mb__after_atomic();
+ wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
+}
+
/*
* Lock eb pages and flush the bio if we can't the locks
*
@@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
if (!trylock_page(p)) {
if (!flush) {
- ret = flush_write_bio(epd);
- if (ret < 0) {
+ int err;
+
+ err = flush_write_bio(epd);
+ if (err < 0) {
+ ret = err;
failed_page_nr = i;
goto err_unlock;
}
@@ -3715,16 +3725,23 @@ err_unlock:
/* Unlock already locked pages */
for (i = 0; i < failed_page_nr; i++)
unlock_page(eb->pages[i]);
+ /*
+ * Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it.
+ * Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can
+ * be made and undo everything done before.
+ */
+ btrfs_tree_lock(eb);
+ spin_lock(&eb->refs_lock);
+ set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
+ end_extent_buffer_writeback(eb);
+ spin_unlock(&eb->refs_lock);
+ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len,
+ fs_info->dirty_metadata_batch);
+ btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
+ btrfs_tree_unlock(eb);
return ret;
}
-static void end_extent_buffer_writeback(struct extent_buffer *eb)
-{
- clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
- smp_mb__after_atomic();
- wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
-}
-
static void set_btree_ioerr(struct page *page)
{
struct extent_buffer *eb = (struct extent_buffer *)page->private;
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 98fccce4208c..393eceda57c8 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
if (blockers) {
btrfs_assert_no_spinning_writers(eb);
eb->blocking_writers--;
- /* Use the lighter barrier after atomic */
- smp_mb__after_atomic();
- cond_wake_up_nomb(&eb->write_lock_wq);
+ /*
+ * We need to order modifying blocking_writers above with
+ * actually waking up the sleepers to ensure they see the
+ * updated value of blocking_writers
+ */
+ cond_wake_up(&eb->write_lock_wq);
} else {
btrfs_assert_spinning_writers_put(eb);
write_unlock(&eb->lock);
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 1744ba8b2754..ae7f64a8facb 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
struct extent_state **cached_state)
{
struct btrfs_ordered_extent *ordered;
- struct extent_state *cachedp = NULL;
+ struct extent_state *cache = NULL;
+ struct extent_state **cachedp = &cache;
if (cached_state)
- cachedp = *cached_state;
+ cachedp = cached_state;
while (1) {
- lock_extent_bits(tree, start, end, &cachedp);
+ lock_extent_bits(tree, start, end, cachedp);
ordered = btrfs_lookup_ordered_range(inode, start,
end - start + 1);
if (!ordered) {
@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
* aren't exposing it outside of this function
*/
if (!cached_state)
- refcount_dec(&cachedp->refs);
+ refcount_dec(&cache->refs);
break;
}
- unlock_extent_cached(tree, start, end, &cachedp);
+ unlock_extent_cached(tree, start, end, cachedp);
btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1);
btrfs_put_ordered_extent(ordered);
}
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 69b59bf75882..c3c0c064c25d 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -6322,68 +6322,21 @@ static int changed_extent(struct send_ctx *sctx,
{
int ret = 0;
- if (sctx->cur_ino != sctx->cmp_key->objectid) {
-
- if (result == BTRFS_COMPARE_TREE_CHANGED) {
- struct extent_buffer *leaf_l;
- struct extent_buffer *leaf_r;
- struct btrfs_file_extent_item *ei_l;
- struct btrfs_file_extent_item *ei_r;
-
- leaf_l = sctx->left_path->nodes[0];
- leaf_r = sctx->right_path->nodes[0];
- ei_l = btrfs_item_ptr(leaf_l,
- sctx->left_path->slots[0],
- struct btrfs_file_extent_item);
- ei_r = btrfs_item_ptr(leaf_r,
- sctx->right_path->slots[0],
- struct btrfs_file_extent_item);
-
- /*
- * We may have found an extent item that has changed
- * only its disk_bytenr field and the corresponding
- * inode item was not updated. This case happens due to
- * very specific timings during relocation when a leaf
- * that contains file extent items is COWed while
- * relocation is ongoing and its in the stage where it
- * updates data pointers. So when this happens we can
- * safely ignore it since we know it's the same extent,
- * but just at different logical and physical locations
- * (when an extent is fully replaced with a new one, we
- * know the generation number must have changed too,
- * since snapshot creation implies committing the current
- * transaction, and the inode item must have been updated
- * as well).
- * This replacement of the disk_bytenr happens at
- * relocation.c:replace_file_extents() through
- * relocation.c:btrfs_reloc_cow_block().
- */
- if (btrfs_file_extent_generation(leaf_l, ei_l) ==
- btrfs_file_extent_generation(leaf_r, ei_r) &&
- btrfs_file_extent_ram_bytes(leaf_l, ei_l) ==
- btrfs_file_extent_ram_bytes(leaf_r, ei_r) &&
- btrfs_file_extent_compression(leaf_l, ei_l) ==
- btrfs_file_extent_compression(leaf_r, ei_r) &&
- btrfs_file_extent_encryption(leaf_l, ei_l) ==
- btrfs_file_extent_encryption(leaf_r, ei_r) &&
- btrfs_file_extent_other_encoding(leaf_l, ei_l) ==
- btrfs_file_extent_other_encoding(leaf_r, ei_r) &&
- btrfs_file_extent_type(leaf_l, ei_l) ==
- btrfs_file_extent_type(leaf_r, ei_r) &&
- btrfs_file_extent_disk_bytenr(leaf_l, ei_l) !=
- btrfs_file_extent_disk_bytenr(leaf_r, ei_r) &&
- btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) ==
- btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) &&
- btrfs_file_extent_offset(leaf_l, ei_l) ==
- btrfs_file_extent_offset(leaf_r, ei_r) &&
- btrfs_file_extent_num_bytes(leaf_l, ei_l) ==
- btrfs_file_extent_num_bytes(leaf_r, ei_r))
- return 0;
- }
-
- inconsistent_snapshot_error(sctx, result, "extent");
- return -EIO;
- }
+ /*
+ * We have found an extent item that changed without the inode item
+ * having changed. This can happen either after relocation (where the
+ * disk_bytenr of an extent item is replaced at
+ * relocation.c:replace_file_extents()) or after deduplication into a
+ * file in both the parent and send snapshots (where an extent item can
+ * get modified or replaced with a new one). Note that deduplication
+ * updates the inode item, but it only changes the iversion (sequence
+ * field in the inode item) of the inode, so if a file is deduplicated
+ * the same amount of times in both the parent and send snapshots, its
+ * iversion becames the same in both snapshots, whence the inode item is
+ * the same on both snapshots.
+ */
+ if (sctx->cur_ino != sctx->cmp_key->objectid)
+ return 0;
if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
if (result != BTRFS_COMPARE_TREE_DELETED)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 3b8ae1a8f02d..e3adb714c04b 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -28,15 +28,18 @@ static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
[TRANS_STATE_COMMIT_START] = (__TRANS_START | __TRANS_ATTACH),
[TRANS_STATE_COMMIT_DOING] = (__TRANS_START |
__TRANS_ATTACH |
- __TRANS_JOIN),
+ __TRANS_JOIN |
+ __TRANS_JOIN_NOSTART),
[TRANS_STATE_UNBLOCKED] = (__TRANS_START |
__TRANS_ATTACH |
__TRANS_JOIN |
- __TRANS_JOIN_NOLOCK),
+ __TRANS_JOIN_NOLOCK |
+ __TRANS_JOIN_NOSTART),
[TRANS_STATE_COMPLETED] = (__TRANS_START |
__TRANS_ATTACH |
__TRANS_JOIN |
- __TRANS_JOIN_NOLOCK),
+ __TRANS_JOIN_NOLOCK |
+ __TRANS_JOIN_NOSTART),
};
void btrfs_put_transaction(struct btrfs_transaction *transaction)
@@ -543,7 +546,8 @@ again:
ret = join_transaction(fs_info, type);
if (ret == -EBUSY) {
wait_current_trans(fs_info);
- if (unlikely(type == TRANS_ATTACH))
+ if (unlikely(type == TRANS_ATTACH ||
+ type == TRANS_JOIN_NOSTART))
ret = -ENOENT;
}
} while (ret == -EBUSY);
@@ -660,6 +664,16 @@ struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root
}
/*
+ * Similar to regular join but it never starts a transaction when none is
+ * running or after waiting for the current one to finish.
+ */
+struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root)
+{
+ return start_transaction(root, 0, TRANS_JOIN_NOSTART,
+ BTRFS_RESERVE_NO_FLUSH, true);
+}
+
+/*
* btrfs_attach_transaction() - catch the running transaction
*
* It is used when we want to commit the current the transaction, but
@@ -2037,6 +2051,16 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
}
} else {
spin_unlock(&fs_info->trans_lock);
+ /*
+ * The previous transaction was aborted and was already removed
+ * from the list of transactions at fs_info->trans_list. So we
+ * abort to prevent writing a new superblock that reflects a
+ * corrupt state (pointing to trees with unwritten nodes/leafs).
+ */
+ if (test_bit(BTRFS_FS_STATE_TRANS_ABORTED, &fs_info->fs_state)) {
+ ret = -EROFS;
+ goto cleanup_transaction;
+ }
}
extwriter_counter_dec(cur_trans, trans->type);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 527ea94b57d9..2c5a6f6e5bb0 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -94,11 +94,13 @@ struct btrfs_transaction {
#define __TRANS_JOIN (1U << 11)
#define __TRANS_JOIN_NOLOCK (1U << 12)
#define __TRANS_DUMMY (1U << 13)
+#define __TRANS_JOIN_NOSTART (1U << 14)
#define TRANS_START (__TRANS_START | __TRANS_FREEZABLE)
#define TRANS_ATTACH (__TRANS_ATTACH)
#define TRANS_JOIN (__TRANS_JOIN | __TRANS_FREEZABLE)
#define TRANS_JOIN_NOLOCK (__TRANS_JOIN_NOLOCK)
+#define TRANS_JOIN_NOSTART (__TRANS_JOIN_NOSTART)
#define TRANS_EXTWRITERS (__TRANS_START | __TRANS_ATTACH)
@@ -183,6 +185,7 @@ struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
int min_factor);
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
+struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_attach_transaction_barrier(
struct btrfs_root *root);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 6c8297bcfeb7..1bfd7e34f31e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4985,7 +4985,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
BTRFS_I(inode),
LOG_OTHER_INODE_ALL,
0, LLONG_MAX, ctx);
- iput(inode);
+ btrfs_add_delayed_iput(inode);
}
}
continue;
@@ -5000,7 +5000,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
LOG_OTHER_INODE, 0, LLONG_MAX, ctx);
if (ret) {
- iput(inode);
+ btrfs_add_delayed_iput(inode);
continue;
}
@@ -5009,7 +5009,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
key.offset = 0;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0) {
- iput(inode);
+ btrfs_add_delayed_iput(inode);
continue;
}
@@ -5056,7 +5056,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
}
path->slots[0]++;
}
- iput(inode);
+ btrfs_add_delayed_iput(inode);
}
return ret;
@@ -5689,7 +5689,7 @@ process_leaf:
}
if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) {
- iput(di_inode);
+ btrfs_add_delayed_iput(di_inode);
break;
}
@@ -5701,7 +5701,7 @@ process_leaf:
if (!ret &&
btrfs_must_commit_transaction(trans, BTRFS_I(di_inode)))
ret = 1;
- iput(di_inode);
+ btrfs_add_delayed_iput(di_inode);
if (ret)
goto next_dir_inode;
if (ctx->log_new_dentries) {
@@ -5848,7 +5848,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
if (!ret && ctx && ctx->log_new_dentries)
ret = log_new_dir_dentries(trans, root,
BTRFS_I(dir_inode), ctx);
- iput(dir_inode);
+ btrfs_add_delayed_iput(dir_inode);
if (ret)
goto out;
}
@@ -5891,7 +5891,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
LOG_INODE_EXISTS,
0, LLONG_MAX, ctx);
- iput(inode);
+ btrfs_add_delayed_iput(inode);
if (ret)
return ret;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index d74b74ca07af..a447d3ec48d5 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3087,16 +3087,6 @@ static int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
if (ret)
return ret;
- /*
- * We add the kobjects here (and after forcing data chunk creation)
- * since relocation is the only place we'll create chunks of a new
- * type at runtime. The only place where we'll remove the last
- * chunk of a type is the call immediately below this one. Even
- * so, we're protected against races with the cleaner thread since
- * we're covered by the delete_unused_bgs_mutex.
- */
- btrfs_add_raid_kobjects(fs_info);
-
trans = btrfs_start_trans_remove_block_group(root->fs_info,
chunk_offset);
if (IS_ERR(trans)) {
@@ -3223,9 +3213,6 @@ static int btrfs_may_alloc_data_chunk(struct btrfs_fs_info *fs_info,
btrfs_end_transaction(trans);
if (ret < 0)
return ret;
-
- btrfs_add_raid_kobjects(fs_info);
-
return 1;
}
}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index e078cc55b989..b3c8b886bf64 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -913,8 +913,9 @@ get_more_pages:
if (page_offset(page) >= ceph_wbc.i_size) {
dout("%p page eof %llu\n",
page, ceph_wbc.i_size);
- if (ceph_wbc.size_stable ||
- page_offset(page) >= i_size_read(inode))
+ if ((ceph_wbc.size_stable ||
+ page_offset(page) >= i_size_read(inode)) &&
+ clear_page_dirty_for_io(page))
mapping->a_ops->invalidatepage(page,
0, PAGE_SIZE);
unlock_page(page);
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index d98dcd976c80..ce0f5658720a 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1301,6 +1301,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
{
struct ceph_inode_info *ci = cap->ci;
struct inode *inode = &ci->vfs_inode;
+ struct ceph_buffer *old_blob = NULL;
struct cap_msg_args arg;
int held, revoking;
int wake = 0;
@@ -1365,7 +1366,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
ci->i_requested_max_size = arg.max_size;
if (flushing & CEPH_CAP_XATTR_EXCL) {
- __ceph_build_xattrs_blob(ci);
+ old_blob = __ceph_build_xattrs_blob(ci);
arg.xattr_version = ci->i_xattrs.version;
arg.xattr_buf = ci->i_xattrs.blob;
} else {
@@ -1409,6 +1410,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
spin_unlock(&ci->i_ceph_lock);
+ ceph_buffer_put(old_blob);
+
ret = send_cap_msg(&arg);
if (ret < 0) {
dout("error sending cap msg, must requeue %p\n", inode);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 791f84a13bb8..18500edefc56 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -736,6 +736,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
int issued, new_issued, info_caps;
struct timespec64 mtime, atime, ctime;
struct ceph_buffer *xattr_blob = NULL;
+ struct ceph_buffer *old_blob = NULL;
struct ceph_string *pool_ns = NULL;
struct ceph_cap *new_cap = NULL;
int err = 0;
@@ -881,7 +882,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
le64_to_cpu(info->xattr_version) > ci->i_xattrs.version) {
if (ci->i_xattrs.blob)
- ceph_buffer_put(ci->i_xattrs.blob);
+ old_blob = ci->i_xattrs.blob;
ci->i_xattrs.blob = xattr_blob;
if (xattr_blob)
memcpy(ci->i_xattrs.blob->vec.iov_base,
@@ -1022,8 +1023,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
out:
if (new_cap)
ceph_put_cap(mdsc, new_cap);
- if (xattr_blob)
- ceph_buffer_put(xattr_blob);
+ ceph_buffer_put(old_blob);
+ ceph_buffer_put(xattr_blob);
ceph_put_string(pool_ns);
return err;
}
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index ac9b53b89365..5083e238ad15 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -111,8 +111,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
req->r_wait_for_completion = ceph_lock_wait_for_completion;
err = ceph_mdsc_do_request(mdsc, inode, req);
-
- if (operation == CEPH_MDS_OP_GETFILELOCK) {
+ if (!err && operation == CEPH_MDS_OP_GETFILELOCK) {
fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid);
if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
fl->fl_type = F_RDLCK;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 4c6494eb02b5..ccfcc66aaf44 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -465,6 +465,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
struct inode *inode = &ci->vfs_inode;
struct ceph_cap_snap *capsnap;
struct ceph_snap_context *old_snapc, *new_snapc;
+ struct ceph_buffer *old_blob = NULL;
int used, dirty;
capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS);
@@ -541,7 +542,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
capsnap->gid = inode->i_gid;
if (dirty & CEPH_CAP_XATTR_EXCL) {
- __ceph_build_xattrs_blob(ci);
+ old_blob = __ceph_build_xattrs_blob(ci);
capsnap->xattr_blob =
ceph_buffer_get(ci->i_xattrs.blob);
capsnap->xattr_version = ci->i_xattrs.version;
@@ -584,6 +585,7 @@ update_snapc:
}
spin_unlock(&ci->i_ceph_lock);
+ ceph_buffer_put(old_blob);
kfree(capsnap);
ceph_put_snap_context(old_snapc);
}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index d2352fd95dbc..6b9f1ee7de85 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -926,7 +926,7 @@ extern int ceph_getattr(const struct path *path, struct kstat *stat,
int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int);
ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t);
extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
-extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci);
+extern struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci);
extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
extern const struct xattr_handler *ceph_xattr_handlers[];
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 37b458a9af3a..939eab7aa219 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -754,12 +754,15 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
/*
* If there are dirty xattrs, reencode xattrs into the prealloc_blob
- * and swap into place.
+ * and swap into place. It returns the old i_xattrs.blob (or NULL) so
+ * that it can be freed by the caller as the i_ceph_lock is likely to be
+ * held.
*/
-void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
+struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
{
struct rb_node *p;
struct ceph_inode_xattr *xattr = NULL;
+ struct ceph_buffer *old_blob = NULL;
void *dest;
dout("__build_xattrs_blob %p\n", &ci->vfs_inode);
@@ -790,12 +793,14 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
dest - ci->i_xattrs.prealloc_blob->vec.iov_base;
if (ci->i_xattrs.blob)
- ceph_buffer_put(ci->i_xattrs.blob);
+ old_blob = ci->i_xattrs.blob;
ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
ci->i_xattrs.prealloc_blob = NULL;
ci->i_xattrs.dirty = false;
ci->i_xattrs.version++;
}
+
+ return old_blob;
}
static inline int __get_request_mask(struct inode *in) {
@@ -1036,6 +1041,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
struct ceph_cap_flush *prealloc_cf = NULL;
+ struct ceph_buffer *old_blob = NULL;
int issued;
int err;
int dirty = 0;
@@ -1109,13 +1115,15 @@ retry:
struct ceph_buffer *blob;
spin_unlock(&ci->i_ceph_lock);
- dout(" preaallocating new blob size=%d\n", required_blob_size);
+ ceph_buffer_put(old_blob); /* Shouldn't be required */
+ dout(" pre-allocating new blob size=%d\n", required_blob_size);
blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
if (!blob)
goto do_sync_unlocked;
spin_lock(&ci->i_ceph_lock);
+ /* prealloc_blob can't be released while holding i_ceph_lock */
if (ci->i_xattrs.prealloc_blob)
- ceph_buffer_put(ci->i_xattrs.prealloc_blob);
+ old_blob = ci->i_xattrs.prealloc_blob;
ci->i_xattrs.prealloc_blob = blob;
goto retry;
}
@@ -1131,6 +1139,7 @@ retry:
}
spin_unlock(&ci->i_ceph_lock);
+ ceph_buffer_put(old_blob);
if (lock_snap_rwsem)
up_read(&mdsc->snap_rwsem);
if (dirty)
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 4b21a90015a9..99caf77df4a2 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -152,5 +152,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
-#define CIFS_VERSION "2.21"
+#define CIFS_VERSION "2.22"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e23234207fc2..592a6cea2b79 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset);
void extract_unc_hostname(const char *unc, const char **h, size_t *len);
+int copy_path_name(char *dst, const char *src);
#ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index e2f95965065d..3907653e63c7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -942,10 +942,8 @@ PsxDelete:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB add path length overrun check */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
}
params = 6 + name_len;
@@ -1015,10 +1013,8 @@ DelFileRetry:
remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve check for buffer overruns BB */
- name_len = strnlen(name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->fileName, name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->fileName, name);
}
pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
@@ -1062,10 +1058,8 @@ RmDirRetry:
remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve check for buffer overruns BB */
- name_len = strnlen(name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->DirName, name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->DirName, name);
}
pSMB->BufferFormat = 0x04;
@@ -1107,10 +1101,8 @@ MkDirRetry:
remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve check for buffer overruns BB */
- name_len = strnlen(name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->DirName, name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->DirName, name);
}
pSMB->BufferFormat = 0x04;
@@ -1157,10 +1149,8 @@ PsxCreat:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, name);
}
params = 6 + name_len;
@@ -1324,11 +1314,9 @@ OldOpenRetry:
fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve check for buffer overruns BB */
+ } else {
count = 0; /* no pad */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->fileName, fileName, name_len);
+ name_len = copy_path_name(pSMB->fileName, fileName);
}
if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
@@ -1442,11 +1430,8 @@ openRetry:
/* BB improve check for buffer overruns BB */
/* no pad */
count = 0;
- name_len = strnlen(path, PATH_MAX);
- /* trailing null */
- name_len++;
+ name_len = copy_path_name(req->fileName, path);
req->NameLength = cpu_to_le16(name_len);
- strncpy(req->fileName, path, name_len);
}
if (*oplock & REQ_OPLOCK)
@@ -2812,15 +2797,10 @@ renameRetry:
remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(from_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->OldFileName, from_name, name_len);
- name_len2 = strnlen(to_name, PATH_MAX);
- name_len2++; /* trailing null */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, from_name);
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
- name_len2++; /* trailing null */
name_len2++; /* signature byte */
}
@@ -2962,15 +2942,10 @@ copyRetry:
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fromName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->OldFileName, fromName, name_len);
- name_len2 = strnlen(toName, PATH_MAX);
- name_len2++; /* trailing null */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, fromName);
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
- name_len2++; /* trailing null */
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
name_len2++; /* signature byte */
}
@@ -3021,10 +2996,8 @@ createSymLinkRetry:
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fromName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fromName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fromName);
}
params = 6 + name_len;
pSMB->MaxSetupCount = 0;
@@ -3044,10 +3017,8 @@ createSymLinkRetry:
PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */
name_len_target *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len_target = strnlen(toName, PATH_MAX);
- name_len_target++; /* trailing null */
- strncpy(data_offset, toName, name_len_target);
+ } else {
+ name_len_target = copy_path_name(data_offset, toName);
}
pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3109,10 +3080,8 @@ createHardLinkRetry:
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(toName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, toName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, toName);
}
params = 6 + name_len;
pSMB->MaxSetupCount = 0;
@@ -3131,10 +3100,8 @@ createHardLinkRetry:
PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */
name_len_target *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len_target = strnlen(fromName, PATH_MAX);
- name_len_target++; /* trailing null */
- strncpy(data_offset, fromName, name_len_target);
+ } else {
+ name_len_target = copy_path_name(data_offset, fromName);
}
pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3213,15 +3180,10 @@ winCreateHardLinkRetry:
remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(from_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->OldFileName, from_name, name_len);
- name_len2 = strnlen(to_name, PATH_MAX);
- name_len2++; /* trailing null */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, from_name);
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
- name_len2++; /* trailing null */
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
name_len2++; /* signature byte */
}
@@ -3271,10 +3233,8 @@ querySymLinkRetry:
remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(searchName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, searchName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
}
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -3691,10 +3651,8 @@ queryAclRetry:
name_len *= 2;
pSMB->FileName[name_len] = 0;
pSMB->FileName[name_len+1] = 0;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(searchName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, searchName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
}
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -3776,10 +3734,8 @@ setAclRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
}
params = 6 + name_len;
pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -4184,9 +4140,7 @@ QInfRetry:
name_len++; /* trailing null */
name_len *= 2;
} else {
- name_len = strnlen(search_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, search_name, name_len);
+ name_len = copy_path_name(pSMB->FileName, search_name);
}
pSMB->BufferFormat = 0x04;
name_len++; /* account for buffer type byte */
@@ -4321,10 +4275,8 @@ QPathInfoRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(search_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, search_name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, search_name);
}
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4490,10 +4442,8 @@ UnixQPathInfoRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(searchName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, searchName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
}
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4593,17 +4543,16 @@ findFirstRetry:
pSMB->FileName[name_len+1] = 0;
name_len += 2;
}
- } else { /* BB add check for overrun of SMB buf BB */
- name_len = strnlen(searchName, PATH_MAX);
-/* BB fix here and in unicode clause above ie
- if (name_len > buffersize-header)
- free buffer exit; BB */
- strncpy(pSMB->FileName, searchName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
if (msearch) {
- pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
- pSMB->FileName[name_len+1] = '*';
- pSMB->FileName[name_len+2] = 0;
- name_len += 3;
+ if (WARN_ON_ONCE(name_len > PATH_MAX-2))
+ name_len = PATH_MAX-2;
+ /* overwrite nul byte */
+ pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
+ pSMB->FileName[name_len] = '*';
+ pSMB->FileName[name_len+1] = 0;
+ name_len += 2;
}
}
@@ -4898,10 +4847,8 @@ GetInodeNumberRetry:
remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(search_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, search_name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, search_name);
}
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -5008,9 +4955,7 @@ getDFSRetry:
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(search_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->RequestFileName, search_name, name_len);
+ name_len = copy_path_name(pSMB->RequestFileName, search_name);
}
if (ses->server->sign)
@@ -5663,10 +5608,8 @@ SetEOFRetry:
PATH_MAX, cifs_sb->local_nls, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(file_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, file_name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, file_name);
}
params = 6 + name_len;
data_count = sizeof(struct file_end_of_file_info);
@@ -5959,10 +5902,8 @@ SetTimesRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
}
params = 6 + name_len;
@@ -6040,10 +5981,8 @@ SetAttrLgcyRetry:
PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->fileName, fileName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->fileName, fileName);
}
pSMB->attr = cpu_to_le16(dos_attrs);
pSMB->BufferFormat = 0x04;
@@ -6203,10 +6142,8 @@ setPermsRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(file_name, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, file_name, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, file_name);
}
params = 6 + name_len;
@@ -6298,10 +6235,8 @@ QAllEAsRetry:
PATH_MAX, nls_codepage, remap);
list_len++; /* trailing null */
list_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- list_len = strnlen(searchName, PATH_MAX);
- list_len++; /* trailing null */
- strncpy(pSMB->FileName, searchName, list_len);
+ } else {
+ list_len = copy_path_name(pSMB->FileName, searchName);
}
params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
@@ -6480,10 +6415,8 @@ SetEARetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
}
params = 6 + name_len;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a4830ced0f98..5299effa6f7d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1113,6 +1113,7 @@ cifs_demultiplex_thread(void *p)
mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
set_freezable();
+ allow_kernel_signal(SIGKILL);
while (server->tcpStatus != CifsExiting) {
if (try_to_freeze())
continue;
@@ -2980,6 +2981,7 @@ static int
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
{
int rc = 0;
+ int is_domain = 0;
const char *delim, *payload;
char *desc;
ssize_t len;
@@ -3027,6 +3029,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
rc = PTR_ERR(key);
goto out_err;
}
+ is_domain = 1;
}
down_read(&key->sem);
@@ -3084,6 +3087,26 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
goto out_key_put;
}
+ /*
+ * If we have a domain key then we must set the domainName in the
+ * for the request.
+ */
+ if (is_domain && ses->domainName) {
+ vol->domainname = kstrndup(ses->domainName,
+ strlen(ses->domainName),
+ GFP_KERNEL);
+ if (!vol->domainname) {
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for "
+ "domain\n", len);
+ rc = -ENOMEM;
+ kfree(vol->username);
+ vol->username = NULL;
+ kzfree(vol->password);
+ vol->password = NULL;
+ goto out_key_put;
+ }
+ }
+
out_key_put:
up_read(&key->sem);
key_put(key);
@@ -4208,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol,
strlen(vol->prepath) + 1 : 0;
unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
+ if (unc_len > MAX_TREE_SIZE)
+ return ERR_PTR(-EINVAL);
+
full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);
- strncpy(full_path, vol->UNC, unc_len);
+ memcpy(full_path, vol->UNC, unc_len);
pos = full_path + unc_len;
if (pplen) {
*pos = CIFS_DIR_SEP(cifs_sb);
- strncpy(pos + 1, vol->prepath, pplen);
+ memcpy(pos + 1, vol->prepath, pplen);
pos += pplen;
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f26a48dd2e39..be424e81e3ad 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
return full_path;
if (dfsplen)
- strncpy(full_path, tcon->treeName, dfsplen);
+ memcpy(full_path, tcon->treeName, dfsplen);
full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
- strncpy(full_path + dfsplen + 1, vol->prepath, pplen);
+ memcpy(full_path + dfsplen + 1, vol->prepath, pplen);
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
- full_path[dfsplen + pplen] = 0; /* add trailing null */
return full_path;
}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index f383877a6511..5ad83bdb9bea 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len)
*h = unc;
*len = end - unc;
}
+
+/**
+ * copy_path_name - copy src path to dst, possibly truncating
+ *
+ * returns number of bytes written (including trailing nul)
+ */
+int copy_path_name(char *dst, const char *src)
+{
+ int name_len;
+
+ /*
+ * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
+ * will truncate and strlen(dst) will be PATH_MAX-1
+ */
+ name_len = strscpy(dst, src, PATH_MAX);
+ if (WARN_ON_ONCE(name_len < 0))
+ name_len = PATH_MAX-1;
+
+ /* we count the trailing nul */
+ name_len++;
+ return name_len;
+}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index dcd49ad60c83..4c764ff7edd2 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -159,13 +159,16 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
const struct nls_table *nls_cp)
{
char *bcc_ptr = *pbcc_area;
+ int len;
/* copy user */
/* BB what about null user mounts - check that we do this BB */
/* copy user */
if (ses->user_name != NULL) {
- strncpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
- bcc_ptr += strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+ len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
+ if (WARN_ON_ONCE(len < 0))
+ len = CIFS_MAX_USERNAME_LEN - 1;
+ bcc_ptr += len;
}
/* else null user mount */
*bcc_ptr = 0;
@@ -173,8 +176,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
/* copy domain */
if (ses->domainName != NULL) {
- strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
- bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ if (WARN_ON_ONCE(len < 0))
+ len = CIFS_MAX_DOMAINNAME_LEN - 1;
+ bcc_ptr += len;
} /* else we will send a null domain name
so the server will default to its own domain */
*bcc_ptr = 0;
@@ -242,9 +247,10 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
+ ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
if (ses->serverOS) {
- strncpy(ses->serverOS, bcc_ptr, len);
+ memcpy(ses->serverOS, bcc_ptr, len);
+ ses->serverOS[len] = 0;
if (strncmp(ses->serverOS, "OS/2", 4) == 0)
cifs_dbg(FYI, "OS/2 server\n");
}
@@ -258,9 +264,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
- if (ses->serverNOS)
- strncpy(ses->serverNOS, bcc_ptr, len);
+ ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
+ if (ses->serverNOS) {
+ memcpy(ses->serverNOS, bcc_ptr, len);
+ ses->serverNOS[len] = 0;
+ }
bcc_ptr += len + 1;
bleft -= len + 1;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index a5bc1b671c12..64a5864127be 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -3489,7 +3489,15 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
unsigned int buflen)
{
- sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+ void *addr;
+ /*
+ * VMAP_STACK (at least) puts stack into the vmalloc address space
+ */
+ if (is_vmalloc_addr(buf))
+ addr = vmalloc_to_page(buf);
+ else
+ addr = virt_to_page(buf);
+ sg_set_page(sg, addr, buflen, offset_in_page(buf));
}
/* Assumes the first rqst has a transform header as the first iov.
@@ -4070,7 +4078,6 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
{
int ret, length;
char *buf = server->smallbuf;
- char *tmpbuf;
struct smb2_sync_hdr *shdr;
unsigned int pdu_length = server->pdu_size;
unsigned int buf_size;
@@ -4100,18 +4107,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
return length;
next_is_large = server->large_buf;
- one_more:
+one_more:
shdr = (struct smb2_sync_hdr *)buf;
if (shdr->NextCommand) {
- if (next_is_large) {
- tmpbuf = server->bigbuf;
+ if (next_is_large)
next_buffer = (char *)cifs_buf_get();
- } else {
- tmpbuf = server->smallbuf;
+ else
next_buffer = (char *)cifs_small_buf_get();
- }
memcpy(next_buffer,
- tmpbuf + le32_to_cpu(shdr->NextCommand),
+ buf + le32_to_cpu(shdr->NextCommand),
pdu_length - le32_to_cpu(shdr->NextCommand));
}
@@ -4140,12 +4144,21 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
pdu_length -= le32_to_cpu(shdr->NextCommand);
server->large_buf = next_is_large;
if (next_is_large)
- server->bigbuf = next_buffer;
+ server->bigbuf = buf = next_buffer;
else
- server->smallbuf = next_buffer;
-
- buf += le32_to_cpu(shdr->NextCommand);
+ server->smallbuf = buf = next_buffer;
goto one_more;
+ } else if (ret != 0) {
+ /*
+ * ret != 0 here means that we didn't get to handle_mid() thus
+ * server->smallbuf and server->bigbuf are still valid. We need
+ * to free next_buffer because it is not going to be used
+ * anywhere.
+ */
+ if (next_is_large)
+ free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
+ else
+ free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
}
return ret;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index c8cd7b6cdda2..31e4a1b0b170 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -252,7 +252,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
if (tcon == NULL)
return 0;
- if (smb2_command == SMB2_TREE_CONNECT)
+ if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
return 0;
if (tcon->tidStatus == CifsExiting) {
@@ -1196,7 +1196,12 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
else
req->SecurityMode = 0;
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
+#else
req->Capabilities = 0;
+#endif /* DFS_UPCALL */
+
req->Channel = 0; /* MBZ */
sess_data->iov[0].iov_base = (char *)req;
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 6e30949d9f77..a7ec2d3dff92 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -638,9 +638,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
COMPATIBLE_IOCTL(PPPIOCATTCHAN)
COMPATIBLE_IOCTL(PPPIOCGCHAN)
COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
-/* PPPOX */
-COMPATIBLE_IOCTL(PPPOEIOCSFWD)
-COMPATIBLE_IOCTL(PPPOEIOCDFWD)
/* Big A */
/* sparc only */
/* Big Q for sound/OSS */
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f752d83a9c44..520f1813e789 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -20,6 +20,15 @@
#include <linux/list.h>
#include <linux/spinlock.h>
+struct configfs_fragment {
+ atomic_t frag_count;
+ struct rw_semaphore frag_sem;
+ bool frag_dead;
+};
+
+void put_fragment(struct configfs_fragment *);
+struct configfs_fragment *get_fragment(struct configfs_fragment *);
+
struct configfs_dirent {
atomic_t s_count;
int s_dependent_count;
@@ -34,6 +43,7 @@ struct configfs_dirent {
#ifdef CONFIG_LOCKDEP
int s_depth;
#endif
+ struct configfs_fragment *s_frag;
};
#define CONFIGFS_ROOT 0x0001
@@ -61,8 +71,8 @@ extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct in
extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
extern int configfs_create_bin_file(struct config_item *,
const struct configfs_bin_attribute *);
-extern int configfs_make_dirent(struct configfs_dirent *,
- struct dentry *, void *, umode_t, int);
+extern int configfs_make_dirent(struct configfs_dirent *, struct dentry *,
+ void *, umode_t, int, struct configfs_fragment *);
extern int configfs_dirent_is_ready(struct configfs_dirent *);
extern void configfs_hash_and_remove(struct dentry * dir, const char * name);
@@ -137,6 +147,7 @@ static inline void release_configfs_dirent(struct configfs_dirent * sd)
{
if (!(sd->s_type & CONFIGFS_ROOT)) {
kfree(sd->s_iattr);
+ put_fragment(sd->s_frag);
kmem_cache_free(configfs_dir_cachep, sd);
}
}
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 92112915de8e..79fc25aaa8cd 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -151,11 +151,38 @@ configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
#endif /* CONFIG_LOCKDEP */
+static struct configfs_fragment *new_fragment(void)
+{
+ struct configfs_fragment *p;
+
+ p = kmalloc(sizeof(struct configfs_fragment), GFP_KERNEL);
+ if (p) {
+ atomic_set(&p->frag_count, 1);
+ init_rwsem(&p->frag_sem);
+ p->frag_dead = false;
+ }
+ return p;
+}
+
+void put_fragment(struct configfs_fragment *frag)
+{
+ if (frag && atomic_dec_and_test(&frag->frag_count))
+ kfree(frag);
+}
+
+struct configfs_fragment *get_fragment(struct configfs_fragment *frag)
+{
+ if (likely(frag))
+ atomic_inc(&frag->frag_count);
+ return frag;
+}
+
/*
* Allocates a new configfs_dirent and links it to the parent configfs_dirent
*/
static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *parent_sd,
- void *element, int type)
+ void *element, int type,
+ struct configfs_fragment *frag)
{
struct configfs_dirent * sd;
@@ -175,6 +202,7 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *paren
kmem_cache_free(configfs_dir_cachep, sd);
return ERR_PTR(-ENOENT);
}
+ sd->s_frag = get_fragment(frag);
list_add(&sd->s_sibling, &parent_sd->s_children);
spin_unlock(&configfs_dirent_lock);
@@ -209,11 +237,11 @@ static int configfs_dirent_exists(struct configfs_dirent *parent_sd,
int configfs_make_dirent(struct configfs_dirent * parent_sd,
struct dentry * dentry, void * element,
- umode_t mode, int type)
+ umode_t mode, int type, struct configfs_fragment *frag)
{
struct configfs_dirent * sd;
- sd = configfs_new_dirent(parent_sd, element, type);
+ sd = configfs_new_dirent(parent_sd, element, type, frag);
if (IS_ERR(sd))
return PTR_ERR(sd);
@@ -260,7 +288,8 @@ static void init_symlink(struct inode * inode)
* until it is validated by configfs_dir_set_ready()
*/
-static int configfs_create_dir(struct config_item *item, struct dentry *dentry)
+static int configfs_create_dir(struct config_item *item, struct dentry *dentry,
+ struct configfs_fragment *frag)
{
int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
@@ -273,7 +302,8 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry)
return error;
error = configfs_make_dirent(p->d_fsdata, dentry, item, mode,
- CONFIGFS_DIR | CONFIGFS_USET_CREATING);
+ CONFIGFS_DIR | CONFIGFS_USET_CREATING,
+ frag);
if (unlikely(error))
return error;
@@ -338,9 +368,10 @@ int configfs_create_link(struct configfs_symlink *sl,
{
int err = 0;
umode_t mode = S_IFLNK | S_IRWXUGO;
+ struct configfs_dirent *p = parent->d_fsdata;
- err = configfs_make_dirent(parent->d_fsdata, dentry, sl, mode,
- CONFIGFS_ITEM_LINK);
+ err = configfs_make_dirent(p, dentry, sl, mode,
+ CONFIGFS_ITEM_LINK, p->s_frag);
if (!err) {
err = configfs_create(dentry, mode, init_symlink);
if (err) {
@@ -599,7 +630,8 @@ static int populate_attrs(struct config_item *item)
static int configfs_attach_group(struct config_item *parent_item,
struct config_item *item,
- struct dentry *dentry);
+ struct dentry *dentry,
+ struct configfs_fragment *frag);
static void configfs_detach_group(struct config_item *item);
static void detach_groups(struct config_group *group)
@@ -647,7 +679,8 @@ static void detach_groups(struct config_group *group)
* try using vfs_mkdir. Just a thought.
*/
static int create_default_group(struct config_group *parent_group,
- struct config_group *group)
+ struct config_group *group,
+ struct configfs_fragment *frag)
{
int ret;
struct configfs_dirent *sd;
@@ -663,7 +696,7 @@ static int create_default_group(struct config_group *parent_group,
d_add(child, NULL);
ret = configfs_attach_group(&parent_group->cg_item,
- &group->cg_item, child);
+ &group->cg_item, child, frag);
if (!ret) {
sd = child->d_fsdata;
sd->s_type |= CONFIGFS_USET_DEFAULT;
@@ -677,13 +710,14 @@ static int create_default_group(struct config_group *parent_group,
return ret;
}
-static int populate_groups(struct config_group *group)
+static int populate_groups(struct config_group *group,
+ struct configfs_fragment *frag)
{
struct config_group *new_group;
int ret = 0;
list_for_each_entry(new_group, &group->default_groups, group_entry) {
- ret = create_default_group(group, new_group);
+ ret = create_default_group(group, new_group, frag);
if (ret) {
detach_groups(group);
break;
@@ -797,11 +831,12 @@ static void link_group(struct config_group *parent_group, struct config_group *g
*/
static int configfs_attach_item(struct config_item *parent_item,
struct config_item *item,
- struct dentry *dentry)
+ struct dentry *dentry,
+ struct configfs_fragment *frag)
{
int ret;
- ret = configfs_create_dir(item, dentry);
+ ret = configfs_create_dir(item, dentry, frag);
if (!ret) {
ret = populate_attrs(item);
if (ret) {
@@ -831,12 +866,13 @@ static void configfs_detach_item(struct config_item *item)
static int configfs_attach_group(struct config_item *parent_item,
struct config_item *item,
- struct dentry *dentry)
+ struct dentry *dentry,
+ struct configfs_fragment *frag)
{
int ret;
struct configfs_dirent *sd;
- ret = configfs_attach_item(parent_item, item, dentry);
+ ret = configfs_attach_item(parent_item, item, dentry, frag);
if (!ret) {
sd = dentry->d_fsdata;
sd->s_type |= CONFIGFS_USET_DIR;
@@ -852,7 +888,7 @@ static int configfs_attach_group(struct config_item *parent_item,
*/
inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD);
configfs_adjust_dir_dirent_depth_before_populate(sd);
- ret = populate_groups(to_config_group(item));
+ ret = populate_groups(to_config_group(item), frag);
if (ret) {
configfs_detach_item(item);
d_inode(dentry)->i_flags |= S_DEAD;
@@ -1247,6 +1283,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
struct configfs_dirent *sd;
const struct config_item_type *type;
struct module *subsys_owner = NULL, *new_item_owner = NULL;
+ struct configfs_fragment *frag;
char *name;
sd = dentry->d_parent->d_fsdata;
@@ -1265,6 +1302,12 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
goto out;
}
+ frag = new_fragment();
+ if (!frag) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
/* Get a working ref for the duration of this function */
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
@@ -1367,9 +1410,9 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
spin_unlock(&configfs_dirent_lock);
if (group)
- ret = configfs_attach_group(parent_item, item, dentry);
+ ret = configfs_attach_group(parent_item, item, dentry, frag);
else
- ret = configfs_attach_item(parent_item, item, dentry);
+ ret = configfs_attach_item(parent_item, item, dentry, frag);
spin_lock(&configfs_dirent_lock);
sd->s_type &= ~CONFIGFS_USET_IN_MKDIR;
@@ -1406,6 +1449,7 @@ out_put:
* reference.
*/
config_item_put(parent_item);
+ put_fragment(frag);
out:
return ret;
@@ -1417,6 +1461,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
struct config_item *item;
struct configfs_subsystem *subsys;
struct configfs_dirent *sd;
+ struct configfs_fragment *frag;
struct module *subsys_owner = NULL, *dead_item_owner = NULL;
int ret;
@@ -1474,6 +1519,16 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
}
} while (ret == -EAGAIN);
+ frag = sd->s_frag;
+ if (down_write_killable(&frag->frag_sem)) {
+ spin_lock(&configfs_dirent_lock);
+ configfs_detach_rollback(dentry);
+ spin_unlock(&configfs_dirent_lock);
+ return -EINTR;
+ }
+ frag->frag_dead = true;
+ up_write(&frag->frag_sem);
+
/* Get a working ref for the duration of this function */
item = configfs_get_config_item(dentry);
@@ -1574,7 +1629,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
*/
err = -ENOENT;
if (configfs_dirent_is_ready(parent_sd)) {
- file->private_data = configfs_new_dirent(parent_sd, NULL, 0);
+ file->private_data = configfs_new_dirent(parent_sd, NULL, 0, NULL);
if (IS_ERR(file->private_data))
err = PTR_ERR(file->private_data);
else
@@ -1732,8 +1787,13 @@ int configfs_register_group(struct config_group *parent_group,
{
struct configfs_subsystem *subsys = parent_group->cg_subsys;
struct dentry *parent;
+ struct configfs_fragment *frag;
int ret;
+ frag = new_fragment();
+ if (!frag)
+ return -ENOMEM;
+
mutex_lock(&subsys->su_mutex);
link_group(parent_group, group);
mutex_unlock(&subsys->su_mutex);
@@ -1741,7 +1801,7 @@ int configfs_register_group(struct config_group *parent_group,
parent = parent_group->cg_item.ci_dentry;
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- ret = create_default_group(parent_group, group);
+ ret = create_default_group(parent_group, group, frag);
if (ret)
goto err_out;
@@ -1749,12 +1809,14 @@ int configfs_register_group(struct config_group *parent_group,
configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
spin_unlock(&configfs_dirent_lock);
inode_unlock(d_inode(parent));
+ put_fragment(frag);
return 0;
err_out:
inode_unlock(d_inode(parent));
mutex_lock(&subsys->su_mutex);
unlink_group(group);
mutex_unlock(&subsys->su_mutex);
+ put_fragment(frag);
return ret;
}
EXPORT_SYMBOL(configfs_register_group);
@@ -1770,16 +1832,12 @@ void configfs_unregister_group(struct config_group *group)
struct configfs_subsystem *subsys = group->cg_subsys;
struct dentry *dentry = group->cg_item.ci_dentry;
struct dentry *parent = group->cg_item.ci_parent->ci_dentry;
+ struct configfs_dirent *sd = dentry->d_fsdata;
+ struct configfs_fragment *frag = sd->s_frag;
- mutex_lock(&subsys->su_mutex);
- if (!group->cg_item.ci_parent->ci_group) {
- /*
- * The parent has already been unlinked and detached
- * due to a rmdir.
- */
- goto unlink_group;
- }
- mutex_unlock(&subsys->su_mutex);
+ down_write(&frag->frag_sem);
+ frag->frag_dead = true;
+ up_write(&frag->frag_sem);
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
spin_lock(&configfs_dirent_lock);
@@ -1796,7 +1854,6 @@ void configfs_unregister_group(struct config_group *group)
dput(dentry);
mutex_lock(&subsys->su_mutex);
-unlink_group:
unlink_group(group);
mutex_unlock(&subsys->su_mutex);
}
@@ -1853,10 +1910,17 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
struct dentry *dentry;
struct dentry *root;
struct configfs_dirent *sd;
+ struct configfs_fragment *frag;
+
+ frag = new_fragment();
+ if (!frag)
+ return -ENOMEM;
root = configfs_pin_fs();
- if (IS_ERR(root))
+ if (IS_ERR(root)) {
+ put_fragment(frag);
return PTR_ERR(root);
+ }
if (!group->cg_item.ci_name)
group->cg_item.ci_name = group->cg_item.ci_namebuf;
@@ -1872,7 +1936,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
d_add(dentry, NULL);
err = configfs_attach_group(sd->s_element, &group->cg_item,
- dentry);
+ dentry, frag);
if (err) {
BUG_ON(d_inode(dentry));
d_drop(dentry);
@@ -1890,6 +1954,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
unlink_group(group);
configfs_release_fs();
}
+ put_fragment(frag);
return err;
}
@@ -1899,12 +1964,18 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
struct config_group *group = &subsys->su_group;
struct dentry *dentry = group->cg_item.ci_dentry;
struct dentry *root = dentry->d_sb->s_root;
+ struct configfs_dirent *sd = dentry->d_fsdata;
+ struct configfs_fragment *frag = sd->s_frag;
if (dentry->d_parent != root) {
pr_err("Tried to unregister non-subsystem!\n");
return;
}
+ down_write(&frag->frag_sem);
+ frag->frag_dead = true;
+ up_write(&frag->frag_sem);
+
inode_lock_nested(d_inode(root),
I_MUTEX_PARENT);
inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 61e4db4390a1..fb65b706cc0d 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -39,40 +39,44 @@ struct configfs_buffer {
bool write_in_progress;
char *bin_buffer;
int bin_buffer_size;
+ int cb_max_size;
+ struct config_item *item;
+ struct module *owner;
+ union {
+ struct configfs_attribute *attr;
+ struct configfs_bin_attribute *bin_attr;
+ };
};
+static inline struct configfs_fragment *to_frag(struct file *file)
+{
+ struct configfs_dirent *sd = file->f_path.dentry->d_fsdata;
-/**
- * fill_read_buffer - allocate and fill buffer from item.
- * @dentry: dentry pointer.
- * @buffer: data buffer for file.
- *
- * Allocate @buffer->page, if it hasn't been already, then call the
- * config_item's show() method to fill the buffer with this attribute's
- * data.
- * This is called only once, on the file's first read.
- */
-static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer)
+ return sd->s_frag;
+}
+
+static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer)
{
- struct configfs_attribute * attr = to_attr(dentry);
- struct config_item * item = to_item(dentry->d_parent);
- int ret = 0;
- ssize_t count;
+ struct configfs_fragment *frag = to_frag(file);
+ ssize_t count = -ENOENT;
if (!buffer->page)
buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
if (!buffer->page)
return -ENOMEM;
- count = attr->show(item, buffer->page);
-
- BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
- if (count >= 0) {
- buffer->needs_read_fill = 0;
- buffer->count = count;
- } else
- ret = count;
- return ret;
+ down_read(&frag->frag_sem);
+ if (!frag->frag_dead)
+ count = buffer->attr->show(buffer->item, buffer->page);
+ up_read(&frag->frag_sem);
+
+ if (count < 0)
+ return count;
+ if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
+ return -EIO;
+ buffer->needs_read_fill = 0;
+ buffer->count = count;
+ return 0;
}
/**
@@ -97,12 +101,13 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
static ssize_t
configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- struct configfs_buffer * buffer = file->private_data;
+ struct configfs_buffer *buffer = file->private_data;
ssize_t retval = 0;
mutex_lock(&buffer->mutex);
if (buffer->needs_read_fill) {
- if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
+ retval = fill_read_buffer(file, buffer);
+ if (retval)
goto out;
}
pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -138,10 +143,8 @@ static ssize_t
configfs_read_bin_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
+ struct configfs_fragment *frag = to_frag(file);
struct configfs_buffer *buffer = file->private_data;
- struct dentry *dentry = file->f_path.dentry;
- struct config_item *item = to_item(dentry->d_parent);
- struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
ssize_t retval = 0;
ssize_t len = min_t(size_t, count, PAGE_SIZE);
@@ -156,14 +159,19 @@ configfs_read_bin_file(struct file *file, char __user *buf,
if (buffer->needs_read_fill) {
/* perform first read with buf == NULL to get extent */
- len = bin_attr->read(item, NULL, 0);
+ down_read(&frag->frag_sem);
+ if (!frag->frag_dead)
+ len = buffer->bin_attr->read(buffer->item, NULL, 0);
+ else
+ len = -ENOENT;
+ up_read(&frag->frag_sem);
if (len <= 0) {
retval = len;
goto out;
}
/* do not exceed the maximum value */
- if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) {
+ if (buffer->cb_max_size && len > buffer->cb_max_size) {
retval = -EFBIG;
goto out;
}
@@ -176,7 +184,13 @@ configfs_read_bin_file(struct file *file, char __user *buf,
buffer->bin_buffer_size = len;
/* perform second read to fill buffer */
- len = bin_attr->read(item, buffer->bin_buffer, len);
+ down_read(&frag->frag_sem);
+ if (!frag->frag_dead)
+ len = buffer->bin_attr->read(buffer->item,
+ buffer->bin_buffer, len);
+ else
+ len = -ENOENT;
+ up_read(&frag->frag_sem);
if (len < 0) {
retval = len;
vfree(buffer->bin_buffer);
@@ -226,25 +240,17 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size
return error ? -EFAULT : count;
}
-
-/**
- * flush_write_buffer - push buffer to config_item.
- * @dentry: dentry to the attribute
- * @buffer: data buffer for file.
- * @count: number of bytes
- *
- * Get the correct pointers for the config_item and the attribute we're
- * dealing with, then call the store() method for the attribute,
- * passing the buffer that we acquired in fill_write_buffer().
- */
-
static int
-flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count)
+flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
{
- struct configfs_attribute * attr = to_attr(dentry);
- struct config_item * item = to_item(dentry->d_parent);
-
- return attr->store(item, buffer->page, count);
+ struct configfs_fragment *frag = to_frag(file);
+ int res = -ENOENT;
+
+ down_read(&frag->frag_sem);
+ if (!frag->frag_dead)
+ res = buffer->attr->store(buffer->item, buffer->page, count);
+ up_read(&frag->frag_sem);
+ return res;
}
@@ -268,13 +274,13 @@ flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size
static ssize_t
configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct configfs_buffer * buffer = file->private_data;
+ struct configfs_buffer *buffer = file->private_data;
ssize_t len;
mutex_lock(&buffer->mutex);
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
- len = flush_write_buffer(file->f_path.dentry, buffer, len);
+ len = flush_write_buffer(file, buffer, len);
if (len > 0)
*ppos += len;
mutex_unlock(&buffer->mutex);
@@ -299,8 +305,6 @@ configfs_write_bin_file(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct configfs_buffer *buffer = file->private_data;
- struct dentry *dentry = file->f_path.dentry;
- struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
void *tbuf = NULL;
ssize_t len;
@@ -316,8 +320,8 @@ configfs_write_bin_file(struct file *file, const char __user *buf,
/* buffer grows? */
if (*ppos + count > buffer->bin_buffer_size) {
- if (bin_attr->cb_max_size &&
- *ppos + count > bin_attr->cb_max_size) {
+ if (buffer->cb_max_size &&
+ *ppos + count > buffer->cb_max_size) {
len = -EFBIG;
goto out;
}
@@ -349,31 +353,51 @@ out:
return len;
}
-static int check_perm(struct inode * inode, struct file * file, int type)
+static int __configfs_open_file(struct inode *inode, struct file *file, int type)
{
- struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
- struct configfs_attribute * attr = to_attr(file->f_path.dentry);
- struct configfs_bin_attribute *bin_attr = NULL;
- struct configfs_buffer * buffer;
- struct configfs_item_operations * ops = NULL;
- int error = 0;
+ struct dentry *dentry = file->f_path.dentry;
+ struct configfs_fragment *frag = to_frag(file);
+ struct configfs_attribute *attr;
+ struct configfs_buffer *buffer;
+ int error;
- if (!item || !attr)
- goto Einval;
+ error = -ENOMEM;
+ buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
+ if (!buffer)
+ goto out;
- if (type & CONFIGFS_ITEM_BIN_ATTR)
- bin_attr = to_bin_attr(file->f_path.dentry);
+ error = -ENOENT;
+ down_read(&frag->frag_sem);
+ if (unlikely(frag->frag_dead))
+ goto out_free_buffer;
- /* Grab the module reference for this attribute if we have one */
- if (!try_module_get(attr->ca_owner)) {
- error = -ENODEV;
- goto Done;
+ error = -EINVAL;
+ buffer->item = to_item(dentry->d_parent);
+ if (!buffer->item)
+ goto out_free_buffer;
+
+ attr = to_attr(dentry);
+ if (!attr)
+ goto out_put_item;
+
+ if (type & CONFIGFS_ITEM_BIN_ATTR) {
+ buffer->bin_attr = to_bin_attr(dentry);
+ buffer->cb_max_size = buffer->bin_attr->cb_max_size;
+ } else {
+ buffer->attr = attr;
}
- if (item->ci_type)
- ops = item->ci_type->ct_item_ops;
- else
- goto Eaccess;
+ buffer->owner = attr->ca_owner;
+ /* Grab the module reference for this attribute if we have one */
+ error = -ENODEV;
+ if (!try_module_get(buffer->owner))
+ goto out_put_item;
+
+ error = -EACCES;
+ if (!buffer->item->ci_type)
+ goto out_put_module;
+
+ buffer->ops = buffer->item->ci_type->ct_item_ops;
/* File needs write support.
* The inode's perms must say it's ok,
@@ -381,13 +405,11 @@ static int check_perm(struct inode * inode, struct file * file, int type)
*/
if (file->f_mode & FMODE_WRITE) {
if (!(inode->i_mode & S_IWUGO))
- goto Eaccess;
-
+ goto out_put_module;
if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
- goto Eaccess;
-
- if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write)
- goto Eaccess;
+ goto out_put_module;
+ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
+ goto out_put_module;
}
/* File needs read support.
@@ -396,92 +418,72 @@ static int check_perm(struct inode * inode, struct file * file, int type)
*/
if (file->f_mode & FMODE_READ) {
if (!(inode->i_mode & S_IRUGO))
- goto Eaccess;
-
+ goto out_put_module;
if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
- goto Eaccess;
-
- if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read)
- goto Eaccess;
+ goto out_put_module;
+ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
+ goto out_put_module;
}
- /* No error? Great, allocate a buffer for the file, and store it
- * it in file->private_data for easy access.
- */
- buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
- if (!buffer) {
- error = -ENOMEM;
- goto Enomem;
- }
mutex_init(&buffer->mutex);
buffer->needs_read_fill = 1;
buffer->read_in_progress = false;
buffer->write_in_progress = false;
- buffer->ops = ops;
file->private_data = buffer;
- goto Done;
+ up_read(&frag->frag_sem);
+ return 0;
- Einval:
- error = -EINVAL;
- goto Done;
- Eaccess:
- error = -EACCES;
- Enomem:
- module_put(attr->ca_owner);
- Done:
- if (error && item)
- config_item_put(item);
+out_put_module:
+ module_put(buffer->owner);
+out_put_item:
+ config_item_put(buffer->item);
+out_free_buffer:
+ up_read(&frag->frag_sem);
+ kfree(buffer);
+out:
return error;
}
static int configfs_release(struct inode *inode, struct file *filp)
{
- struct config_item * item = to_item(filp->f_path.dentry->d_parent);
- struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
- struct module * owner = attr->ca_owner;
- struct configfs_buffer * buffer = filp->private_data;
-
- if (item)
- config_item_put(item);
- /* After this point, attr should not be accessed. */
- module_put(owner);
-
- if (buffer) {
- if (buffer->page)
- free_page((unsigned long)buffer->page);
- mutex_destroy(&buffer->mutex);
- kfree(buffer);
- }
+ struct configfs_buffer *buffer = filp->private_data;
+
+ module_put(buffer->owner);
+ if (buffer->page)
+ free_page((unsigned long)buffer->page);
+ mutex_destroy(&buffer->mutex);
+ kfree(buffer);
return 0;
}
static int configfs_open_file(struct inode *inode, struct file *filp)
{
- return check_perm(inode, filp, CONFIGFS_ITEM_ATTR);
+ return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
}
static int configfs_open_bin_file(struct inode *inode, struct file *filp)
{
- return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
+ return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
}
-static int configfs_release_bin_file(struct inode *inode, struct file *filp)
+static int configfs_release_bin_file(struct inode *inode, struct file *file)
{
- struct configfs_buffer *buffer = filp->private_data;
- struct dentry *dentry = filp->f_path.dentry;
- struct config_item *item = to_item(dentry->d_parent);
- struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
- ssize_t len = 0;
- int ret;
+ struct configfs_buffer *buffer = file->private_data;
buffer->read_in_progress = false;
if (buffer->write_in_progress) {
+ struct configfs_fragment *frag = to_frag(file);
buffer->write_in_progress = false;
- len = bin_attr->write(item, buffer->bin_buffer,
- buffer->bin_buffer_size);
-
+ down_read(&frag->frag_sem);
+ if (!frag->frag_dead) {
+ /* result of ->release() is ignored */
+ buffer->bin_attr->write(buffer->item,
+ buffer->bin_buffer,
+ buffer->bin_buffer_size);
+ }
+ up_read(&frag->frag_sem);
/* vfree on NULL is safe */
vfree(buffer->bin_buffer);
buffer->bin_buffer = NULL;
@@ -489,10 +491,8 @@ static int configfs_release_bin_file(struct inode *inode, struct file *filp)
buffer->needs_read_fill = 1;
}
- ret = configfs_release(inode, filp);
- if (len < 0)
- return len;
- return ret;
+ configfs_release(inode, file);
+ return 0;
}
@@ -527,7 +527,7 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib
inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
- CONFIGFS_ITEM_ATTR);
+ CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
inode_unlock(d_inode(dir));
return error;
@@ -549,7 +549,7 @@ int configfs_create_bin_file(struct config_item *item,
inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
- CONFIGFS_ITEM_BIN_ATTR);
+ CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
inode_unlock(dir->d_inode);
return error;
diff --git a/fs/coredump.c b/fs/coredump.c
index e42e17e55bfd..b1ea7dfbd149 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -7,6 +7,7 @@
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/swap.h>
+#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/pagemap.h>
@@ -187,11 +188,13 @@ put_exe_file:
* name into corename, which must have space for at least
* CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
*/
-static int format_corename(struct core_name *cn, struct coredump_params *cprm)
+static int format_corename(struct core_name *cn, struct coredump_params *cprm,
+ size_t **argv, int *argc)
{
const struct cred *cred = current_cred();
const char *pat_ptr = core_pattern;
int ispipe = (*pat_ptr == '|');
+ bool was_space = false;
int pid_in_pattern = 0;
int err = 0;
@@ -201,12 +204,35 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
return -ENOMEM;
cn->corename[0] = '\0';
- if (ispipe)
+ if (ispipe) {
+ int argvs = sizeof(core_pattern) / 2;
+ (*argv) = kmalloc_array(argvs, sizeof(**argv), GFP_KERNEL);
+ if (!(*argv))
+ return -ENOMEM;
+ (*argv)[(*argc)++] = 0;
++pat_ptr;
+ }
/* Repeat as long as we have more pattern to process and more output
space */
while (*pat_ptr) {
+ /*
+ * Split on spaces before doing template expansion so that
+ * %e and %E don't get split if they have spaces in them
+ */
+ if (ispipe) {
+ if (isspace(*pat_ptr)) {
+ was_space = true;
+ pat_ptr++;
+ continue;
+ } else if (was_space) {
+ was_space = false;
+ err = cn_printf(cn, "%c", '\0');
+ if (err)
+ return err;
+ (*argv)[(*argc)++] = cn->used;
+ }
+ }
if (*pat_ptr != '%') {
err = cn_printf(cn, "%c", *pat_ptr++);
} else {
@@ -546,6 +572,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
struct cred *cred;
int retval = 0;
int ispipe;
+ size_t *argv = NULL;
+ int argc = 0;
struct files_struct *displaced;
/* require nonrelative corefile path and be extra careful */
bool need_suid_safe = false;
@@ -592,9 +620,10 @@ void do_coredump(const kernel_siginfo_t *siginfo)
old_cred = override_creds(cred);
- ispipe = format_corename(&cn, &cprm);
+ ispipe = format_corename(&cn, &cprm, &argv, &argc);
if (ispipe) {
+ int argi;
int dump_count;
char **helper_argv;
struct subprocess_info *sub_info;
@@ -637,12 +666,16 @@ void do_coredump(const kernel_siginfo_t *siginfo)
goto fail_dropcount;
}
- helper_argv = argv_split(GFP_KERNEL, cn.corename, NULL);
+ helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv),
+ GFP_KERNEL);
if (!helper_argv) {
printk(KERN_WARNING "%s failed to allocate memory\n",
__func__);
goto fail_dropcount;
}
+ for (argi = 0; argi < argc; argi++)
+ helper_argv[argi] = cn.corename + argv[argi];
+ helper_argv[argi] = NULL;
retval = -ENOMEM;
sub_info = call_usermodehelper_setup(helper_argv[0],
@@ -652,7 +685,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
retval = call_usermodehelper_exec(sub_info,
UMH_WAIT_EXEC);
- argv_free(helper_argv);
+ kfree(helper_argv);
if (retval) {
printk(KERN_INFO "Core dump to |%s pipe failed\n",
cn.corename);
@@ -766,6 +799,7 @@ fail_dropcount:
if (ispipe)
atomic_dec(&core_dump_count);
fail_unlock:
+ kfree(argv);
kfree(cn.corename);
coredump_finish(mm, core_dumped);
revert_creds(old_cred);
diff --git a/fs/dax.c b/fs/dax.c
index a237141d8787..6bf81f931de3 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -266,7 +266,7 @@ static void wait_entry_unlocked(struct xa_state *xas, void *entry)
static void put_unlocked_entry(struct xa_state *xas, void *entry)
{
/* If we were the only waiter woken, wake the next one */
- if (entry && dax_is_conflict(entry))
+ if (entry && !dax_is_conflict(entry))
dax_wake_entry(xas, entry, false);
}
@@ -600,7 +600,7 @@ struct page *dax_layout_busy_page(struct address_space *mapping)
* guaranteed to either see new references or prevent new
* references from being established.
*/
- unmap_mapping_range(mapping, 0, 0, 1);
+ unmap_mapping_range(mapping, 0, 0, 0);
xas_lock_irq(&xas);
xas_for_each(&xas, entry, ULONG_MAX) {
diff --git a/fs/exec.c b/fs/exec.c
index c71cbfe6826a..f7f6a140856a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1828,7 +1828,7 @@ static int __do_execve_file(int fd, struct filename *filename,
membarrier_execve(current);
rseq_execve(current);
acct_update_integrals(current);
- task_numa_free(current);
+ task_numa_free(current, false);
free_bprm(bprm);
kfree(pathbuf);
if (filename)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 420fe3deed39..006b7a2070bf 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4586,7 +4586,6 @@ static int __ext4_get_inode_loc(struct inode *inode,
struct buffer_head *bh;
struct super_block *sb = inode->i_sb;
ext4_fsblk_t block;
- struct blk_plug plug;
int inodes_per_block, inode_offset;
iloc->bh = NULL;
@@ -4675,7 +4674,6 @@ make_io:
* If we need to do any I/O, try to pre-readahead extra
* blocks from the inode table.
*/
- blk_start_plug(&plug);
if (EXT4_SB(sb)->s_inode_readahead_blks) {
ext4_fsblk_t b, end, table;
unsigned num;
@@ -4706,7 +4704,6 @@ make_io:
get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
- blk_finish_plug(&plug);
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
EXT4_ERROR_INODE_BLOCK(inode, block,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f8d46df8fa9e..3e58a6f697dd 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1653,19 +1653,12 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
- u32 oldflags;
/* Is it quota file? Do not allow user to mess with it */
if (IS_NOQUOTA(inode))
return -EPERM;
- oldflags = fi->i_flags;
-
- if ((iflags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
- if (!capable(CAP_LINUX_IMMUTABLE))
- return -EPERM;
-
- fi->i_flags = iflags | (oldflags & ~mask);
+ fi->i_flags = iflags | (fi->i_flags & ~mask);
if (fi->i_flags & F2FS_PROJINHERIT_FL)
set_inode_flag(inode, FI_PROJ_INHERIT);
@@ -1770,7 +1763,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
- u32 fsflags;
+ struct f2fs_inode_info *fi = F2FS_I(inode);
+ u32 fsflags, old_fsflags;
u32 iflags;
int ret;
@@ -1794,8 +1788,14 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
inode_lock(inode);
+ old_fsflags = f2fs_iflags_to_fsflags(fi->i_flags);
+ ret = vfs_ioc_setflags_prepare(inode, old_fsflags, fsflags);
+ if (ret)
+ goto out;
+
ret = f2fs_setflags_common(inode, iflags,
f2fs_fsflags_to_iflags(F2FS_SETTABLE_FS_FL));
+out:
inode_unlock(inode);
mnt_drop_write_file(filp);
return ret;
@@ -2855,52 +2855,32 @@ static inline u32 f2fs_xflags_to_iflags(u32 xflags)
return iflags;
}
-static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
+static void f2fs_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
{
- struct inode *inode = file_inode(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
- struct fsxattr fa;
- memset(&fa, 0, sizeof(struct fsxattr));
- fa.fsx_xflags = f2fs_iflags_to_xflags(fi->i_flags);
+ simple_fill_fsxattr(fa, f2fs_iflags_to_xflags(fi->i_flags));
if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)))
- fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
- fi->i_projid);
-
- if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
- return -EFAULT;
- return 0;
+ fa->fsx_projid = from_kprojid(&init_user_ns, fi->i_projid);
}
-static int f2fs_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
+static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
{
- /*
- * Project Quota ID state is only allowed to change from within the init
- * namespace. Enforce that restriction only if we are trying to change
- * the quota ID state. Everything else is allowed in user namespaces.
- */
- if (current_user_ns() == &init_user_ns)
- return 0;
+ struct inode *inode = file_inode(filp);
+ struct fsxattr fa;
- if (__kprojid_val(F2FS_I(inode)->i_projid) != fa->fsx_projid)
- return -EINVAL;
-
- if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) {
- if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
- return -EINVAL;
- } else {
- if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
- return -EINVAL;
- }
+ f2fs_fill_fsxattr(inode, &fa);
+ if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
+ return -EFAULT;
return 0;
}
static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
- struct fsxattr fa;
+ struct fsxattr fa, old_fa;
u32 iflags;
int err;
@@ -2923,9 +2903,12 @@ static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
return err;
inode_lock(inode);
- err = f2fs_ioctl_check_project(inode, &fa);
+
+ f2fs_fill_fsxattr(inode, &old_fa);
+ err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
if (err)
goto out;
+
err = f2fs_setflags_common(inode, iflags,
f2fs_xflags_to_iflags(F2FS_SUPPORTED_XFLAGS));
if (err)
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6691f526fa40..8974672db78f 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -796,6 +796,29 @@ static int move_data_block(struct inode *inode, block_t bidx,
if (lfs_mode)
down_write(&fio.sbi->io_order_lock);
+ mpage = f2fs_grab_cache_page(META_MAPPING(fio.sbi),
+ fio.old_blkaddr, false);
+ if (!mpage)
+ goto up_out;
+
+ fio.encrypted_page = mpage;
+
+ /* read source block in mpage */
+ if (!PageUptodate(mpage)) {
+ err = f2fs_submit_page_bio(&fio);
+ if (err) {
+ f2fs_put_page(mpage, 1);
+ goto up_out;
+ }
+ lock_page(mpage);
+ if (unlikely(mpage->mapping != META_MAPPING(fio.sbi) ||
+ !PageUptodate(mpage))) {
+ err = -EIO;
+ f2fs_put_page(mpage, 1);
+ goto up_out;
+ }
+ }
+
f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
&sum, CURSEG_COLD_DATA, NULL, false);
@@ -803,44 +826,18 @@ static int move_data_block(struct inode *inode, block_t bidx,
newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
if (!fio.encrypted_page) {
err = -ENOMEM;
- goto recover_block;
- }
-
- mpage = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
- fio.old_blkaddr, FGP_LOCK, GFP_NOFS);
- if (mpage) {
- bool updated = false;
-
- if (PageUptodate(mpage)) {
- memcpy(page_address(fio.encrypted_page),
- page_address(mpage), PAGE_SIZE);
- updated = true;
- }
f2fs_put_page(mpage, 1);
- invalidate_mapping_pages(META_MAPPING(fio.sbi),
- fio.old_blkaddr, fio.old_blkaddr);
- if (updated)
- goto write_page;
- }
-
- err = f2fs_submit_page_bio(&fio);
- if (err)
- goto put_page_out;
-
- /* write page */
- lock_page(fio.encrypted_page);
-
- if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
- err = -EIO;
- goto put_page_out;
- }
- if (unlikely(!PageUptodate(fio.encrypted_page))) {
- err = -EIO;
- goto put_page_out;
+ goto recover_block;
}
-write_page:
+ /* write target block */
f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true);
+ memcpy(page_address(fio.encrypted_page),
+ page_address(mpage), PAGE_SIZE);
+ f2fs_put_page(mpage, 1);
+ invalidate_mapping_pages(META_MAPPING(fio.sbi),
+ fio.old_blkaddr, fio.old_blkaddr);
+
set_page_dirty(fio.encrypted_page);
if (clear_page_dirty_for_io(fio.encrypted_page))
dec_page_count(fio.sbi, F2FS_DIRTY_META);
@@ -871,11 +868,12 @@ write_page:
put_page_out:
f2fs_put_page(fio.encrypted_page, 1);
recover_block:
- if (lfs_mode)
- up_write(&fio.sbi->io_order_lock);
if (err)
f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
true, true);
+up_out:
+ if (lfs_mode)
+ up_write(&fio.sbi->io_order_lock);
put_out:
f2fs_put_dnode(&dn);
out:
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 6de6cda44031..78a1b873e48a 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2422,6 +2422,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
size_t crc_offset = 0;
__u32 crc = 0;
+ if (le32_to_cpu(raw_super->magic) != F2FS_SUPER_MAGIC) {
+ f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)",
+ F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
+ return -EINVAL;
+ }
+
/* Check checksum_offset and crc in superblock */
if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_SB_CHKSUM)) {
crc_offset = le32_to_cpu(raw_super->checksum_offset);
@@ -2429,26 +2435,20 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
offsetof(struct f2fs_super_block, crc)) {
f2fs_info(sbi, "Invalid SB checksum offset: %zu",
crc_offset);
- return 1;
+ return -EFSCORRUPTED;
}
crc = le32_to_cpu(raw_super->crc);
if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) {
f2fs_info(sbi, "Invalid SB checksum value: %u", crc);
- return 1;
+ return -EFSCORRUPTED;
}
}
- if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
- f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)",
- F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
- return 1;
- }
-
/* Currently, support only 4KB page cache size */
if (F2FS_BLKSIZE != PAGE_SIZE) {
f2fs_info(sbi, "Invalid page_cache_size (%lu), supports only 4KB",
PAGE_SIZE);
- return 1;
+ return -EFSCORRUPTED;
}
/* Currently, support only 4KB block size */
@@ -2456,14 +2456,14 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
if (blocksize != F2FS_BLKSIZE) {
f2fs_info(sbi, "Invalid blocksize (%u), supports only 4KB",
blocksize);
- return 1;
+ return -EFSCORRUPTED;
}
/* check log blocks per segment */
if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) {
f2fs_info(sbi, "Invalid log blocks per segment (%u)",
le32_to_cpu(raw_super->log_blocks_per_seg));
- return 1;
+ return -EFSCORRUPTED;
}
/* Currently, support 512/1024/2048/4096 bytes sector size */
@@ -2473,7 +2473,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
F2FS_MIN_LOG_SECTOR_SIZE) {
f2fs_info(sbi, "Invalid log sectorsize (%u)",
le32_to_cpu(raw_super->log_sectorsize));
- return 1;
+ return -EFSCORRUPTED;
}
if (le32_to_cpu(raw_super->log_sectors_per_block) +
le32_to_cpu(raw_super->log_sectorsize) !=
@@ -2481,7 +2481,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
f2fs_info(sbi, "Invalid log sectors per block(%u) log sectorsize(%u)",
le32_to_cpu(raw_super->log_sectors_per_block),
le32_to_cpu(raw_super->log_sectorsize));
- return 1;
+ return -EFSCORRUPTED;
}
segment_count = le32_to_cpu(raw_super->segment_count);
@@ -2495,7 +2495,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
if (segment_count > F2FS_MAX_SEGMENT ||
segment_count < F2FS_MIN_SEGMENTS) {
f2fs_info(sbi, "Invalid segment count (%u)", segment_count);
- return 1;
+ return -EFSCORRUPTED;
}
if (total_sections > segment_count ||
@@ -2503,25 +2503,25 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
segs_per_sec > segment_count || !segs_per_sec) {
f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)",
segment_count, total_sections, segs_per_sec);
- return 1;
+ return -EFSCORRUPTED;
}
if ((segment_count / segs_per_sec) < total_sections) {
f2fs_info(sbi, "Small segment_count (%u < %u * %u)",
segment_count, segs_per_sec, total_sections);
- return 1;
+ return -EFSCORRUPTED;
}
if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) {
f2fs_info(sbi, "Wrong segment_count / block_count (%u > %llu)",
segment_count, le64_to_cpu(raw_super->block_count));
- return 1;
+ return -EFSCORRUPTED;
}
if (secs_per_zone > total_sections || !secs_per_zone) {
f2fs_info(sbi, "Wrong secs_per_zone / total_sections (%u, %u)",
secs_per_zone, total_sections);
- return 1;
+ return -EFSCORRUPTED;
}
if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION ||
raw_super->hot_ext_count > F2FS_MAX_EXTENSION ||
@@ -2531,7 +2531,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
le32_to_cpu(raw_super->extension_count),
raw_super->hot_ext_count,
F2FS_MAX_EXTENSION);
- return 1;
+ return -EFSCORRUPTED;
}
if (le32_to_cpu(raw_super->cp_payload) >
@@ -2539,7 +2539,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
f2fs_info(sbi, "Insane cp_payload (%u > %u)",
le32_to_cpu(raw_super->cp_payload),
blocks_per_seg - F2FS_CP_PACKS);
- return 1;
+ return -EFSCORRUPTED;
}
/* check reserved ino info */
@@ -2550,12 +2550,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
le32_to_cpu(raw_super->node_ino),
le32_to_cpu(raw_super->meta_ino),
le32_to_cpu(raw_super->root_ino));
- return 1;
+ return -EFSCORRUPTED;
}
/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
if (sanity_check_area_boundary(sbi, bh))
- return 1;
+ return -EFSCORRUPTED;
return 0;
}
@@ -2870,10 +2870,10 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi,
}
/* sanity checking of raw super */
- if (sanity_check_raw_super(sbi, bh)) {
+ err = sanity_check_raw_super(sbi, bh);
+ if (err) {
f2fs_err(sbi, "Can't find valid F2FS filesystem in %dth superblock",
block + 1);
- err = -EFSCORRUPTED;
brelse(bh);
continue;
}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 79581b9bdebb..4f8b5fd6c81f 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -390,6 +390,19 @@ static int fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, int h)
return mp->mp_aheight - x - 1;
}
+static sector_t metapath_to_block(struct gfs2_sbd *sdp, struct metapath *mp)
+{
+ sector_t factor = 1, block = 0;
+ int hgt;
+
+ for (hgt = mp->mp_fheight - 1; hgt >= 0; hgt--) {
+ if (hgt < mp->mp_aheight)
+ block += mp->mp_list[hgt] * factor;
+ factor *= sdp->sd_inptrs;
+ }
+ return block;
+}
+
static void release_metapath(struct metapath *mp)
{
int i;
@@ -430,60 +443,84 @@ static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *pt
return ptr - first;
}
-typedef const __be64 *(*gfs2_metadata_walker)(
- struct metapath *mp,
- const __be64 *start, const __be64 *end,
- u64 factor, void *data);
+enum walker_status { WALK_STOP, WALK_FOLLOW, WALK_CONTINUE };
+
+/*
+ * gfs2_metadata_walker - walk an indirect block
+ * @mp: Metapath to indirect block
+ * @ptrs: Number of pointers to look at
+ *
+ * When returning WALK_FOLLOW, the walker must update @mp to point at the right
+ * indirect block to follow.
+ */
+typedef enum walker_status (*gfs2_metadata_walker)(struct metapath *mp,
+ unsigned int ptrs);
-#define WALK_STOP ((__be64 *)0)
-#define WALK_NEXT ((__be64 *)1)
+/*
+ * gfs2_walk_metadata - walk a tree of indirect blocks
+ * @inode: The inode
+ * @mp: Starting point of walk
+ * @max_len: Maximum number of blocks to walk
+ * @walker: Called during the walk
+ *
+ * Returns 1 if the walk was stopped by @walker, 0 if we went past @max_len or
+ * past the end of metadata, and a negative error code otherwise.
+ */
-static int gfs2_walk_metadata(struct inode *inode, sector_t lblock,
- u64 len, struct metapath *mp, gfs2_metadata_walker walker,
- void *data)
+static int gfs2_walk_metadata(struct inode *inode, struct metapath *mp,
+ u64 max_len, gfs2_metadata_walker walker)
{
- struct metapath clone;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
- const __be64 *start, *end, *ptr;
u64 factor = 1;
unsigned int hgt;
- int ret = 0;
+ int ret;
- for (hgt = ip->i_height - 1; hgt >= mp->mp_aheight; hgt--)
+ /*
+ * The walk starts in the lowest allocated indirect block, which may be
+ * before the position indicated by @mp. Adjust @max_len accordingly
+ * to avoid a short walk.
+ */
+ for (hgt = mp->mp_fheight - 1; hgt >= mp->mp_aheight; hgt--) {
+ max_len += mp->mp_list[hgt] * factor;
+ mp->mp_list[hgt] = 0;
factor *= sdp->sd_inptrs;
+ }
for (;;) {
- u64 step;
+ u16 start = mp->mp_list[hgt];
+ enum walker_status status;
+ unsigned int ptrs;
+ u64 len;
/* Walk indirect block. */
- start = metapointer(hgt, mp);
- end = metaend(hgt, mp);
-
- step = (end - start) * factor;
- if (step > len)
- end = start + DIV_ROUND_UP_ULL(len, factor);
-
- ptr = walker(mp, start, end, factor, data);
- if (ptr == WALK_STOP)
+ ptrs = (hgt >= 1 ? sdp->sd_inptrs : sdp->sd_diptrs) - start;
+ len = ptrs * factor;
+ if (len > max_len)
+ ptrs = DIV_ROUND_UP_ULL(max_len, factor);
+ status = walker(mp, ptrs);
+ switch (status) {
+ case WALK_STOP:
+ return 1;
+ case WALK_FOLLOW:
+ BUG_ON(mp->mp_aheight == mp->mp_fheight);
+ ptrs = mp->mp_list[hgt] - start;
+ len = ptrs * factor;
break;
- if (step >= len)
+ case WALK_CONTINUE:
break;
- len -= step;
- if (ptr != WALK_NEXT) {
- BUG_ON(!*ptr);
- mp->mp_list[hgt] += ptr - start;
- goto fill_up_metapath;
}
+ if (len >= max_len)
+ break;
+ max_len -= len;
+ if (status == WALK_FOLLOW)
+ goto fill_up_metapath;
lower_metapath:
/* Decrease height of metapath. */
- if (mp != &clone) {
- clone_metapath(&clone, mp);
- mp = &clone;
- }
brelse(mp->mp_bh[hgt]);
mp->mp_bh[hgt] = NULL;
+ mp->mp_list[hgt] = 0;
if (!hgt)
break;
hgt--;
@@ -491,10 +528,7 @@ lower_metapath:
/* Advance in metadata tree. */
(mp->mp_list[hgt])++;
- start = metapointer(hgt, mp);
- end = metaend(hgt, mp);
- if (start >= end) {
- mp->mp_list[hgt] = 0;
+ if (mp->mp_list[hgt] >= sdp->sd_inptrs) {
if (!hgt)
break;
goto lower_metapath;
@@ -502,44 +536,36 @@ lower_metapath:
fill_up_metapath:
/* Increase height of metapath. */
- if (mp != &clone) {
- clone_metapath(&clone, mp);
- mp = &clone;
- }
ret = fillup_metapath(ip, mp, ip->i_height - 1);
if (ret < 0)
- break;
+ return ret;
hgt += ret;
for (; ret; ret--)
do_div(factor, sdp->sd_inptrs);
mp->mp_aheight = hgt + 1;
}
- if (mp == &clone)
- release_metapath(mp);
- return ret;
+ return 0;
}
-struct gfs2_hole_walker_args {
- u64 blocks;
-};
-
-static const __be64 *gfs2_hole_walker(struct metapath *mp,
- const __be64 *start, const __be64 *end,
- u64 factor, void *data)
+static enum walker_status gfs2_hole_walker(struct metapath *mp,
+ unsigned int ptrs)
{
- struct gfs2_hole_walker_args *args = data;
- const __be64 *ptr;
+ const __be64 *start, *ptr, *end;
+ unsigned int hgt;
+
+ hgt = mp->mp_aheight - 1;
+ start = metapointer(hgt, mp);
+ end = start + ptrs;
for (ptr = start; ptr < end; ptr++) {
if (*ptr) {
- args->blocks += (ptr - start) * factor;
+ mp->mp_list[hgt] += ptr - start;
if (mp->mp_aheight == mp->mp_fheight)
return WALK_STOP;
- return ptr; /* increase height */
+ return WALK_FOLLOW;
}
}
- args->blocks += (end - start) * factor;
- return WALK_NEXT;
+ return WALK_CONTINUE;
}
/**
@@ -557,12 +583,24 @@ static const __be64 *gfs2_hole_walker(struct metapath *mp,
static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
struct metapath *mp, struct iomap *iomap)
{
- struct gfs2_hole_walker_args args = { };
- int ret = 0;
+ struct metapath clone;
+ u64 hole_size;
+ int ret;
- ret = gfs2_walk_metadata(inode, lblock, len, mp, gfs2_hole_walker, &args);
- if (!ret)
- iomap->length = args.blocks << inode->i_blkbits;
+ clone_metapath(&clone, mp);
+ ret = gfs2_walk_metadata(inode, &clone, len, gfs2_hole_walker);
+ if (ret < 0)
+ goto out;
+
+ if (ret == 1)
+ hole_size = metapath_to_block(GFS2_SB(inode), &clone) - lblock;
+ else
+ hole_size = len;
+ iomap->length = hole_size << inode->i_blkbits;
+ ret = 0;
+
+out:
+ release_metapath(&clone);
return ret;
}
@@ -1002,11 +1040,16 @@ static void gfs2_iomap_page_done(struct inode *inode, loff_t pos,
unsigned copied, struct page *page,
struct iomap *iomap)
{
+ struct gfs2_trans *tr = current->journal_info;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
if (page && !gfs2_is_stuffed(ip))
gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied);
+
+ if (tr->tr_num_buf_new)
+ __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+
gfs2_trans_end(sdp);
}
@@ -1099,8 +1142,6 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
tr = current->journal_info;
if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
- else
- gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[0]);
gfs2_trans_end(sdp);
}
@@ -1181,10 +1222,16 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
if (ip->i_qadata && ip->i_qadata->qa_qd_num)
gfs2_quota_unlock(ip);
+
+ if (unlikely(!written))
+ goto out_unlock;
+
if (iomap->flags & IOMAP_F_SIZE_CHANGED)
mark_inode_dirty(inode);
- gfs2_write_unlock(inode);
+ set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
+out_unlock:
+ gfs2_write_unlock(inode);
out:
return 0;
}
diff --git a/fs/io_uring.c b/fs/io_uring.c
index e2a66e12fbc6..cfb48bd088e1 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -202,7 +202,7 @@ struct async_list {
struct file *file;
off_t io_end;
- size_t io_pages;
+ size_t io_len;
};
struct io_ring_ctx {
@@ -333,7 +333,8 @@ struct io_kiocb {
#define REQ_F_IO_DRAIN 16 /* drain existing IO first */
#define REQ_F_IO_DRAINED 32 /* drain done */
#define REQ_F_LINK 64 /* linked sqes */
-#define REQ_F_FAIL_LINK 128 /* fail rest of links */
+#define REQ_F_LINK_DONE 128 /* linked sqes done */
+#define REQ_F_FAIL_LINK 256 /* fail rest of links */
u64 user_data;
u32 result;
u32 sequence;
@@ -429,7 +430,7 @@ static inline bool io_sequence_defer(struct io_ring_ctx *ctx,
if ((req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
return false;
- return req->sequence > ctx->cached_cq_tail + ctx->sq_ring->dropped;
+ return req->sequence != ctx->cached_cq_tail + ctx->sq_ring->dropped;
}
static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
@@ -632,6 +633,7 @@ static void io_req_link_next(struct io_kiocb *req)
nxt->flags |= REQ_F_LINK;
}
+ nxt->flags |= REQ_F_LINK_DONE;
INIT_WORK(&nxt->work, io_sq_wq_submit_work);
queue_work(req->ctx->sqo_wq, &nxt->work);
}
@@ -677,6 +679,13 @@ static void io_put_req(struct io_kiocb *req)
io_free_req(req);
}
+static unsigned io_cqring_events(struct io_cq_ring *ring)
+{
+ /* See comment at the top of this file */
+ smp_rmb();
+ return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
+}
+
/*
* Find and free completed poll iocbs
*/
@@ -769,7 +778,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
static int io_iopoll_getevents(struct io_ring_ctx *ctx, unsigned int *nr_events,
long min)
{
- while (!list_empty(&ctx->poll_list)) {
+ while (!list_empty(&ctx->poll_list) && !need_resched()) {
int ret;
ret = io_do_iopoll(ctx, nr_events, min);
@@ -796,6 +805,12 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
unsigned int nr_events = 0;
io_iopoll_getevents(ctx, &nr_events, 1);
+
+ /*
+ * Ensure we allow local-to-the-cpu processing to take place,
+ * in this case we need to ensure that we reap all events.
+ */
+ cond_resched();
}
mutex_unlock(&ctx->uring_lock);
}
@@ -803,11 +818,42 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
long min)
{
- int ret = 0;
+ int iters, ret = 0;
+
+ /*
+ * We disallow the app entering submit/complete with polling, but we
+ * still need to lock the ring to prevent racing with polled issue
+ * that got punted to a workqueue.
+ */
+ mutex_lock(&ctx->uring_lock);
+ iters = 0;
do {
int tmin = 0;
+ /*
+ * Don't enter poll loop if we already have events pending.
+ * If we do, we can potentially be spinning for commands that
+ * already triggered a CQE (eg in error).
+ */
+ if (io_cqring_events(ctx->cq_ring))
+ break;
+
+ /*
+ * If a submit got punted to a workqueue, we can have the
+ * application entering polling for a command before it gets
+ * issued. That app will hold the uring_lock for the duration
+ * of the poll right here, so we need to take a breather every
+ * now and then to ensure that the issue has a chance to add
+ * the poll to the issued list. Otherwise we can spin here
+ * forever, while the workqueue is stuck trying to acquire the
+ * very same mutex.
+ */
+ if (!(++iters & 7)) {
+ mutex_unlock(&ctx->uring_lock);
+ mutex_lock(&ctx->uring_lock);
+ }
+
if (*nr_events < min)
tmin = min - *nr_events;
@@ -817,6 +863,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
ret = 0;
} while (min && !*nr_events && !need_resched());
+ mutex_unlock(&ctx->uring_lock);
return ret;
}
@@ -1064,8 +1111,42 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw,
*/
offset = buf_addr - imu->ubuf;
iov_iter_bvec(iter, rw, imu->bvec, imu->nr_bvecs, offset + len);
- if (offset)
- iov_iter_advance(iter, offset);
+
+ if (offset) {
+ /*
+ * Don't use iov_iter_advance() here, as it's really slow for
+ * using the latter parts of a big fixed buffer - it iterates
+ * over each segment manually. We can cheat a bit here, because
+ * we know that:
+ *
+ * 1) it's a BVEC iter, we set it up
+ * 2) all bvecs are PAGE_SIZE in size, except potentially the
+ * first and last bvec
+ *
+ * So just find our index, and adjust the iterator afterwards.
+ * If the offset is within the first bvec (or the whole first
+ * bvec, just use iov_iter_advance(). This makes it easier
+ * since we can just skip the first segment, which may not
+ * be PAGE_SIZE aligned.
+ */
+ const struct bio_vec *bvec = imu->bvec;
+
+ if (offset <= bvec->bv_len) {
+ iov_iter_advance(iter, offset);
+ } else {
+ unsigned long seg_skip;
+
+ /* skip first vec */
+ offset -= bvec->bv_len;
+ seg_skip = 1 + (offset >> PAGE_SHIFT);
+
+ iter->bvec = bvec + seg_skip;
+ iter->nr_segs -= seg_skip;
+ iter->count -= bvec->bv_len + offset;
+ iter->iov_offset = offset & ~PAGE_MASK;
+ }
+ }
+
return 0;
}
@@ -1120,28 +1201,26 @@ static void io_async_list_note(int rw, struct io_kiocb *req, size_t len)
off_t io_end = kiocb->ki_pos + len;
if (filp == async_list->file && kiocb->ki_pos == async_list->io_end) {
- unsigned long max_pages;
+ unsigned long max_bytes;
/* Use 8x RA size as a decent limiter for both reads/writes */
- max_pages = filp->f_ra.ra_pages;
- if (!max_pages)
- max_pages = VM_READAHEAD_PAGES;
- max_pages *= 8;
-
- /* If max pages are exceeded, reset the state */
- len >>= PAGE_SHIFT;
- if (async_list->io_pages + len <= max_pages) {
+ max_bytes = filp->f_ra.ra_pages << (PAGE_SHIFT + 3);
+ if (!max_bytes)
+ max_bytes = VM_READAHEAD_PAGES << (PAGE_SHIFT + 3);
+
+ /* If max len are exceeded, reset the state */
+ if (async_list->io_len + len <= max_bytes) {
req->flags |= REQ_F_SEQ_PREV;
- async_list->io_pages += len;
+ async_list->io_len += len;
} else {
io_end = 0;
- async_list->io_pages = 0;
+ async_list->io_len = 0;
}
}
/* New file? Reset state. */
if (async_list->file != filp) {
- async_list->io_pages = 0;
+ async_list->io_len = 0;
async_list->file = filp;
}
async_list->io_end = io_end;
@@ -1630,6 +1709,8 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe)
INIT_LIST_HEAD(&poll->wait.entry);
init_waitqueue_func_entry(&poll->wait, io_poll_wake);
+ INIT_LIST_HEAD(&req->list);
+
mask = vfs_poll(poll->file, &ipt.pt) & poll->events;
spin_lock_irq(&ctx->completion_lock);
@@ -1800,6 +1881,7 @@ restart:
do {
struct sqe_submit *s = &req->submit;
const struct io_uring_sqe *sqe = s->sqe;
+ unsigned int flags = req->flags;
/* Ensure we clear previously set non-block flag */
req->rw.ki_flags &= ~IOCB_NOWAIT;
@@ -1844,6 +1926,10 @@ restart:
/* async context always use a copy of the sqe */
kfree(sqe);
+ /* req from defer and link list needn't decrease async cnt */
+ if (flags & (REQ_F_IO_DRAINED | REQ_F_LINK_DONE))
+ goto out;
+
if (!async_list)
break;
if (!list_empty(&req_list)) {
@@ -1891,6 +1977,7 @@ restart:
}
}
+out:
if (cur_mm) {
set_fs(old_fs);
unuse_mm(cur_mm);
@@ -1917,6 +2004,10 @@ static bool io_add_to_prev_work(struct async_list *list, struct io_kiocb *req)
ret = true;
spin_lock(&list->lock);
list_add_tail(&req->list, &list->list);
+ /*
+ * Ensure we see a simultaneous modification from io_sq_wq_submit_work()
+ */
+ smp_mb();
if (!atomic_read(&list->cnt)) {
list_del_init(&req->list);
ret = false;
@@ -1977,6 +2068,15 @@ static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
{
int ret;
+ ret = io_req_defer(ctx, req, s->sqe);
+ if (ret) {
+ if (ret != -EIOCBQUEUED) {
+ io_free_req(req);
+ io_cqring_add_event(ctx, s->sqe->user_data, ret);
+ }
+ return 0;
+ }
+
ret = __io_submit_sqe(ctx, req, s, true);
if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) {
struct io_uring_sqe *sqe_copy;
@@ -2049,13 +2149,6 @@ err:
return;
}
- ret = io_req_defer(ctx, req, s->sqe);
- if (ret) {
- if (ret != -EIOCBQUEUED)
- goto err_req;
- return;
- }
-
/*
* If we already have a head request, queue this one for async
* submittal once the head completes. If we don't have a head but
@@ -2232,15 +2325,7 @@ static int io_sq_thread(void *data)
unsigned nr_events = 0;
if (ctx->flags & IORING_SETUP_IOPOLL) {
- /*
- * We disallow the app entering submit/complete
- * with polling, but we still need to lock the
- * ring to prevent racing with polled issue
- * that got punted to a workqueue.
- */
- mutex_lock(&ctx->uring_lock);
io_iopoll_check(ctx, &nr_events, 0);
- mutex_unlock(&ctx->uring_lock);
} else {
/*
* Normal IO, just pretend everything completed.
@@ -2385,13 +2470,6 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit)
return submit;
}
-static unsigned io_cqring_events(struct io_cq_ring *ring)
-{
- /* See comment at the top of this file */
- smp_rmb();
- return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
-}
-
/*
* Wait until events become available, if we don't already have some. The
* application must reap them itself, as they reside on the shared cq ring.
@@ -3142,9 +3220,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
min_complete = min(min_complete, ctx->cq_entries);
if (ctx->flags & IORING_SETUP_IOPOLL) {
- mutex_lock(&ctx->uring_lock);
ret = io_iopoll_check(ctx, &nr_events, min_complete);
- mutex_unlock(&ctx->uring_lock);
} else {
ret = io_cqring_wait(ctx, min_complete, sig, sigsz);
}
diff --git a/fs/iomap/Makefile b/fs/iomap/Makefile
index 2d165388d952..93cd11938bf5 100644
--- a/fs/iomap/Makefile
+++ b/fs/iomap/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-or-newer
+# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (c) 2019 Oracle.
# All Rights Reserved.
diff --git a/fs/namespace.c b/fs/namespace.c
index 6464ea4acba9..d28d30b13043 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1463,7 +1463,6 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
disconnect = disconnect_mount(p, how);
-
if (mnt_has_parent(p)) {
mnt_add_count(p->mnt_parent, -1);
if (!disconnect) {
@@ -1471,10 +1470,11 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
} else {
umount_mnt(p);
- hlist_add_head(&p->mnt_umount, &unmounted);
}
}
change_mnt_propagation(p, MS_PRIVATE);
+ if (disconnect)
+ hlist_add_head(&p->mnt_umount, &unmounted);
}
}
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 0ff3facf81da..071b90a45933 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -153,7 +153,7 @@ again:
/* Block nfs4_proc_unlck */
mutex_lock(&sp->so_delegreturn_mutex);
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
- err = nfs4_open_delegation_recall(ctx, state, stateid, type);
+ err = nfs4_open_delegation_recall(ctx, state, stateid);
if (!err)
err = nfs_delegation_claim_locks(state, stateid);
if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -1046,6 +1046,22 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
nfs4_schedule_state_manager(clp);
}
+static void
+nfs_delegation_test_free_expired(struct inode *inode,
+ nfs4_stateid *stateid,
+ const struct cred *cred)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
+ int status;
+
+ if (!cred)
+ return;
+ status = ops->test_and_free_expired(server, stateid, cred);
+ if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
+ nfs_remove_bad_delegation(inode, stateid);
+}
+
/**
* nfs_reap_expired_delegations - reap expired delegations
* @clp: nfs_client to process
@@ -1057,7 +1073,6 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
*/
void nfs_reap_expired_delegations(struct nfs_client *clp)
{
- const struct nfs4_minor_version_ops *ops = clp->cl_mvops;
struct nfs_delegation *delegation;
struct nfs_server *server;
struct inode *inode;
@@ -1088,11 +1103,7 @@ restart:
nfs4_stateid_copy(&stateid, &delegation->stateid);
clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
rcu_read_unlock();
- if (cred != NULL &&
- ops->test_and_free_expired(server, &stateid, cred) < 0) {
- nfs_revoke_delegation(inode, &stateid);
- nfs_inode_find_state_and_recover(inode, &stateid);
- }
+ nfs_delegation_test_free_expired(inode, &stateid, cred);
put_cred(cred);
if (nfs4_server_rebooted(clp)) {
nfs_inode_mark_test_expired_delegation(server,inode);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 5799777df5ec..9eb87ae4c982 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -63,7 +63,7 @@ void nfs_reap_expired_delegations(struct nfs_client *clp);
/* NFSv4 delegation-related procedures */
int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync);
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8d501093660f..0adfd8840110 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1487,7 +1487,7 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
nfs_file_set_open_context(file, ctx);
else
- err = -ESTALE;
+ err = -EOPENSTALE;
out:
return err;
}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0cb442406168..222d7115db71 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -401,15 +401,21 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
unsigned long bytes = 0;
struct nfs_direct_req *dreq = hdr->dreq;
- if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
- goto out_put;
-
spin_lock(&dreq->lock);
- if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0))
+ if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
dreq->error = hdr->error;
- else
+
+ if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+ spin_unlock(&dreq->lock);
+ goto out_put;
+ }
+
+ if (hdr->good_bytes != 0)
nfs_direct_good_bytes(dreq, hdr);
+ if (test_bit(NFS_IOHDR_EOF, &hdr->flags))
+ dreq->error = 0;
+
spin_unlock(&dreq->lock);
while (!list_empty(&hdr->pages)) {
@@ -782,16 +788,19 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
bool request_commit = false;
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
- if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
- goto out_put;
-
nfs_init_cinfo_from_dreq(&cinfo, dreq);
spin_lock(&dreq->lock);
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
dreq->error = hdr->error;
- if (dreq->error == 0) {
+
+ if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+ spin_unlock(&dreq->lock);
+ goto out_put;
+ }
+
+ if (hdr->good_bytes != 0) {
nfs_direct_good_bytes(dreq, hdr);
if (nfs_write_need_commit(hdr)) {
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index b04e20d28162..5657b7f2611f 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -8,6 +8,7 @@
*/
#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
#include <linux/nfs_page.h>
#include <linux/module.h>
#include <linux/sched/mm.h>
@@ -928,7 +929,9 @@ retry:
pgm = &pgio->pg_mirrors[0];
pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
- pgio->pg_maxretrans = io_maxretrans;
+ if (NFS_SERVER(pgio->pg_inode)->flags &
+ (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
+ pgio->pg_maxretrans = io_maxretrans;
return;
out_nolseg:
if (pgio->pg_error < 0)
@@ -940,6 +943,7 @@ out_mds:
pgio->pg_lseg);
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
+ pgio->pg_maxretrans = 0;
nfs_pageio_reset_read_mds(pgio);
}
@@ -1000,7 +1004,9 @@ retry:
pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].wsize;
}
- pgio->pg_maxretrans = io_maxretrans;
+ if (NFS_SERVER(pgio->pg_inode)->flags &
+ (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
+ pgio->pg_maxretrans = io_maxretrans;
return;
out_mds:
@@ -1010,6 +1016,7 @@ out_mds:
pgio->pg_lseg);
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
+ pgio->pg_maxretrans = 0;
nfs_pageio_reset_write_mds(pgio);
}
@@ -1148,8 +1155,6 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
break;
case -NFS4ERR_RETRY_UNCACHED_REP:
break;
- case -EAGAIN:
- return -NFS4ERR_RESET_TO_PNFS;
/* Invalidate Layout errors */
case -NFS4ERR_PNFS_NO_LAYOUT:
case -ESTALE: /* mapped NFS4ERR_STALE */
@@ -1210,7 +1215,6 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
case -EBADHANDLE:
case -ELOOP:
case -ENOSPC:
- case -EAGAIN:
break;
case -EJUKEBOX:
nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
@@ -1445,16 +1449,6 @@ static void ff_layout_read_prepare_v4(struct rpc_task *task, void *data)
ff_layout_read_prepare_common(task, hdr);
}
-static void
-ff_layout_io_prepare_transmit(struct rpc_task *task,
- void *data)
-{
- struct nfs_pgio_header *hdr = data;
-
- if (!pnfs_is_valid_lseg(hdr->lseg))
- rpc_exit(task, -EAGAIN);
-}
-
static void ff_layout_read_call_done(struct rpc_task *task, void *data)
{
struct nfs_pgio_header *hdr = data;
@@ -1740,7 +1734,6 @@ static void ff_layout_commit_release(void *data)
static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
.rpc_call_prepare = ff_layout_read_prepare_v3,
- .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
.rpc_call_done = ff_layout_read_call_done,
.rpc_count_stats = ff_layout_read_count_stats,
.rpc_release = ff_layout_read_release,
@@ -1748,7 +1741,6 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
.rpc_call_prepare = ff_layout_read_prepare_v4,
- .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
.rpc_call_done = ff_layout_read_call_done,
.rpc_count_stats = ff_layout_read_count_stats,
.rpc_release = ff_layout_read_release,
@@ -1756,7 +1748,6 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
.rpc_call_prepare = ff_layout_write_prepare_v3,
- .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
.rpc_call_done = ff_layout_write_call_done,
.rpc_count_stats = ff_layout_write_count_stats,
.rpc_release = ff_layout_write_release,
@@ -1764,7 +1755,6 @@ static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
static const struct rpc_call_ops ff_layout_write_call_ops_v4 = {
.rpc_call_prepare = ff_layout_write_prepare_v4,
- .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
.rpc_call_done = ff_layout_write_call_done,
.rpc_count_stats = ff_layout_write_count_stats,
.rpc_release = ff_layout_write_release,
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 53507aa96b0b..3800ab6f08fa 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -114,6 +114,10 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
struct rb_node **p, *parent;
int diff;
+ nfss->fscache_key = NULL;
+ nfss->fscache = NULL;
+ if (!(nfss->options & NFS_OPTION_FSCACHE))
+ return;
if (!uniq) {
uniq = "";
ulen = 1;
@@ -226,10 +230,11 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
void nfs_fscache_init_inode(struct inode *inode)
{
struct nfs_fscache_inode_auxdata auxdata;
+ struct nfs_server *nfss = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);
nfsi->fscache = NULL;
- if (!S_ISREG(inode->i_mode))
+ if (!(nfss->fscache && S_ISREG(inode->i_mode)))
return;
memset(&auxdata, 0, sizeof(auxdata));
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 25a75e40d91d..ad041cfbf9ec 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -182,7 +182,7 @@ static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
*/
static inline const char *nfs_server_fscache_state(struct nfs_server *server)
{
- if (server->fscache && (server->options & NFS_OPTION_FSCACHE))
+ if (server->fscache)
return "yes";
return "no ";
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 8a1758200b57..2a03bfeec10a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1403,12 +1403,22 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
return 0;
+ if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) {
+ /* Only a mounted-on-fileid? Just exit */
+ if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+ return 0;
/* Has the inode gone and changed behind our back? */
- if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
+ } else if (nfsi->fileid != fattr->fileid) {
+ /* Is this perhaps the mounted-on fileid? */
+ if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
+ nfsi->fileid == fattr->mounted_on_fileid)
+ return 0;
return -ESTALE;
+ }
if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
return -ESTALE;
+
if (!nfs_file_has_buffered_writers(nfsi)) {
/* Verify a few of the more important attributes */
if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr))
@@ -1768,18 +1778,6 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
-static inline bool nfs_fileid_valid(struct nfs_inode *nfsi,
- struct nfs_fattr *fattr)
-{
- bool ret1 = true, ret2 = true;
-
- if (fattr->valid & NFS_ATTR_FATTR_FILEID)
- ret1 = (nfsi->fileid == fattr->fileid);
- if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
- ret2 = (nfsi->fileid == fattr->mounted_on_fileid);
- return ret1 || ret2;
-}
-
/*
* Many nfs protocol calls return the new file attributes after
* an operation. Here we update the inode to reflect the state
@@ -1810,7 +1808,16 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_display_fhandle_hash(NFS_FH(inode)),
atomic_read(&inode->i_count), fattr->valid);
- if (!nfs_fileid_valid(nfsi, fattr)) {
+ if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) {
+ /* Only a mounted-on-fileid? Just exit */
+ if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+ return 0;
+ /* Has the inode gone and changed behind our back? */
+ } else if (nfsi->fileid != fattr->fileid) {
+ /* Is this perhaps the mounted-on fileid? */
+ if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
+ nfsi->fileid == fattr->mounted_on_fileid)
+ return 0;
printk(KERN_ERR "NFS: server %s error: fileid changed\n"
"fsid %s: expected fileid 0x%Lx, got 0x%Lx\n",
NFS_SERVER(inode)->nfs_client->cl_hostname,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index a2346a2f8361..e64f810223be 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -775,3 +775,13 @@ static inline bool nfs_error_is_fatal(int err)
}
}
+static inline bool nfs_error_is_fatal_on_server(int err)
+{
+ switch (err) {
+ case 0:
+ case -ERESTARTSYS:
+ case -EINTR:
+ return false;
+ }
+ return nfs_error_is_fatal(err);
+}
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d778dad9a75e..3564da1ba8a1 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -465,7 +465,8 @@ static inline void nfs4_schedule_session_recovery(struct nfs4_session *session,
extern struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *, const struct cred *, gfp_t);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_purge_state_owners(struct nfs_server *);
+extern void nfs4_purge_state_owners(struct nfs_server *, struct list_head *);
+extern void nfs4_free_state_owners(struct list_head *head);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, fmode_t);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 616393a01c06..da6204025a2d 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -758,9 +758,12 @@ out:
static void nfs4_destroy_server(struct nfs_server *server)
{
+ LIST_HEAD(freeme);
+
nfs_server_return_all_delegations(server);
unset_pnfs_layoutdriver(server);
- nfs4_purge_state_owners(server);
+ nfs4_purge_state_owners(server, &freeme);
+ nfs4_free_state_owners(&freeme);
}
/*
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 96db471ca2e5..339663d04bf8 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -73,13 +73,13 @@ nfs4_file_open(struct inode *inode, struct file *filp)
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
switch (err) {
- case -EPERM:
- case -EACCES:
- case -EDQUOT:
- case -ENOSPC:
- case -EROFS:
- goto out_put_ctx;
default:
+ goto out_put_ctx;
+ case -ENOENT:
+ case -ESTALE:
+ case -EISDIR:
+ case -ENOTDIR:
+ case -ELOOP:
goto out_drop;
}
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 39896afc6edf..1406858bae6c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1683,6 +1683,14 @@ static void nfs_state_set_open_stateid(struct nfs4_state *state,
write_sequnlock(&state->seqlock);
}
+static void nfs_state_clear_open_state_flags(struct nfs4_state *state)
+{
+ clear_bit(NFS_O_RDWR_STATE, &state->flags);
+ clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+ clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+ clear_bit(NFS_OPEN_STATE, &state->flags);
+}
+
static void nfs_state_set_delegation(struct nfs4_state *state,
const nfs4_stateid *deleg_stateid,
fmode_t fmode)
@@ -1907,8 +1915,9 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
if (data->o_res.delegation_type != 0)
nfs4_opendata_check_deleg(data, state);
update:
- update_open_stateid(state, &data->o_res.stateid, NULL,
- data->o_arg.fmode);
+ if (!update_open_stateid(state, &data->o_res.stateid,
+ NULL, data->o_arg.fmode))
+ return ERR_PTR(-EAGAIN);
refcount_inc(&state->count);
return state;
@@ -1973,8 +1982,11 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
if (data->o_res.delegation_type != 0)
nfs4_opendata_check_deleg(data, state);
- update_open_stateid(state, &data->o_res.stateid, NULL,
- data->o_arg.fmode);
+ if (!update_open_stateid(state, &data->o_res.stateid,
+ NULL, data->o_arg.fmode)) {
+ nfs4_put_open_state(state);
+ state = ERR_PTR(-EAGAIN);
+ }
out:
nfs_release_seqid(data->o_arg.seqid);
return state;
@@ -2074,13 +2086,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
{
int ret;
- /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
- clear_bit(NFS_O_RDWR_STATE, &state->flags);
- clear_bit(NFS_O_WRONLY_STATE, &state->flags);
- clear_bit(NFS_O_RDONLY_STATE, &state->flags);
/* memory barrier prior to reading state->n_* */
- clear_bit(NFS_DELEGATED_STATE, &state->flags);
- clear_bit(NFS_OPEN_STATE, &state->flags);
smp_rmb();
ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
if (ret != 0)
@@ -2156,6 +2162,8 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
ctx = nfs4_state_find_open_context(state);
if (IS_ERR(ctx))
return -EAGAIN;
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+ nfs_state_clear_open_state_flags(state);
ret = nfs4_do_open_reclaim(ctx, state);
put_nfs_open_context(ctx);
return ret;
@@ -2171,18 +2179,17 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
case -ENOENT:
case -EAGAIN:
case -ESTALE:
+ case -ETIMEDOUT:
break;
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
case -NFS4ERR_DEADSESSION:
- set_bit(NFS_DELEGATED_STATE, &state->flags);
nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
return -EAGAIN;
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID:
- set_bit(NFS_DELEGATED_STATE, &state->flags);
/* Don't recall a delegation if it was lost */
nfs4_schedule_lease_recovery(server->nfs_client);
return -EAGAIN;
@@ -2203,7 +2210,6 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
return -EAGAIN;
case -NFS4ERR_DELAY:
case -NFS4ERR_GRACE:
- set_bit(NFS_DELEGATED_STATE, &state->flags);
ssleep(1);
return -EAGAIN;
case -ENOMEM:
@@ -2219,8 +2225,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
}
int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
- struct nfs4_state *state, const nfs4_stateid *stateid,
- fmode_t type)
+ struct nfs4_state *state, const nfs4_stateid *stateid)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_opendata *opendata;
@@ -2231,20 +2236,23 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
if (IS_ERR(opendata))
return PTR_ERR(opendata);
nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
- nfs_state_clear_delegation(state);
- switch (type & (FMODE_READ|FMODE_WRITE)) {
- case FMODE_READ|FMODE_WRITE:
- case FMODE_WRITE:
+ if (!test_bit(NFS_O_RDWR_STATE, &state->flags)) {
err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
if (err)
- break;
+ goto out;
+ }
+ if (!test_bit(NFS_O_WRONLY_STATE, &state->flags)) {
err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
if (err)
- break;
- /* Fall through */
- case FMODE_READ:
+ goto out;
+ }
+ if (!test_bit(NFS_O_RDONLY_STATE, &state->flags)) {
err = nfs4_open_recover_helper(opendata, FMODE_READ);
+ if (err)
+ goto out;
}
+ nfs_state_clear_delegation(state);
+out:
nfs4_opendata_put(opendata);
return nfs4_handle_delegation_recall_error(server, state, stateid, NULL, err);
}
@@ -2492,6 +2500,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data,
if (!ctx) {
nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1);
data->is_recover = true;
+ task_setup_data.flags |= RPC_TASK_TIMEOUT;
} else {
nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0);
pnfs_lgopen_prepare(data, ctx);
@@ -2698,6 +2707,7 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
{
/* NFSv4.0 doesn't allow for delegation recovery on open expire */
nfs40_clear_delegation_stateid(state);
+ nfs_state_clear_open_state_flags(state);
return nfs4_open_expired(sp, state);
}
@@ -2740,13 +2750,13 @@ out_free:
return -NFS4ERR_EXPIRED;
}
-static void nfs41_check_delegation_stateid(struct nfs4_state *state)
+static int nfs41_check_delegation_stateid(struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
nfs4_stateid stateid;
struct nfs_delegation *delegation;
const struct cred *cred = NULL;
- int status;
+ int status, ret = NFS_OK;
/* Get the delegation credential for use by test/free_stateid */
rcu_read_lock();
@@ -2754,20 +2764,15 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
if (delegation == NULL) {
rcu_read_unlock();
nfs_state_clear_delegation(state);
- return;
+ return NFS_OK;
}
nfs4_stateid_copy(&stateid, &delegation->stateid);
- if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
- rcu_read_unlock();
- nfs_state_clear_delegation(state);
- return;
- }
if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
&delegation->flags)) {
rcu_read_unlock();
- return;
+ return NFS_OK;
}
if (delegation->cred)
@@ -2777,9 +2782,24 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
trace_nfs4_test_delegation_stateid(state, NULL, status);
if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
nfs_finish_clear_delegation_stateid(state, &stateid);
+ else
+ ret = status;
- if (delegation->cred)
- put_cred(cred);
+ put_cred(cred);
+ return ret;
+}
+
+static void nfs41_delegation_recover_stateid(struct nfs4_state *state)
+{
+ nfs4_stateid tmp;
+
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) &&
+ nfs4_copy_delegation_stateid(state->inode, state->state,
+ &tmp, NULL) &&
+ nfs4_stateid_match_other(&state->stateid, &tmp))
+ nfs_state_set_delegation(state, &tmp, state->state);
+ else
+ nfs_state_clear_delegation(state);
}
/**
@@ -2849,21 +2869,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
const struct cred *cred = state->owner->so_cred;
int status;
- if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
- if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) {
- if (nfs4_have_delegation(state->inode, state->state))
- return NFS_OK;
- return -NFS4ERR_OPENMODE;
- }
+ if (test_bit(NFS_OPEN_STATE, &state->flags) == 0)
return -NFS4ERR_BAD_STATEID;
- }
status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
trace_nfs4_test_open_stateid(state, NULL, status);
if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
- clear_bit(NFS_O_RDONLY_STATE, &state->flags);
- clear_bit(NFS_O_WRONLY_STATE, &state->flags);
- clear_bit(NFS_O_RDWR_STATE, &state->flags);
- clear_bit(NFS_OPEN_STATE, &state->flags);
+ nfs_state_clear_open_state_flags(state);
stateid->type = NFS4_INVALID_STATEID_TYPE;
return status;
}
@@ -2876,7 +2887,11 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
{
int status;
- nfs41_check_delegation_stateid(state);
+ status = nfs41_check_delegation_stateid(state);
+ if (status != NFS_OK)
+ return status;
+ nfs41_delegation_recover_stateid(state);
+
status = nfs41_check_expired_locks(state);
if (status != NFS_OK)
return status;
@@ -3201,7 +3216,7 @@ static int _nfs4_do_setattr(struct inode *inode,
if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
/* Use that stateid */
- } else if (ctx != NULL) {
+ } else if (ctx != NULL && ctx->state) {
struct nfs_lock_context *l_ctx;
if (!nfs4_valid_open_stateid(ctx->state))
return -EBADF;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9afd051a4876..cad4e064b328 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -624,24 +624,39 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
/**
* nfs4_purge_state_owners - Release all cached state owners
* @server: nfs_server with cached state owners to release
+ * @head: resulting list of state owners
*
* Called at umount time. Remaining state owners will be on
* the LRU with ref count of zero.
+ * Note that the state owners are not freed, but are added
+ * to the list @head, which can later be used as an argument
+ * to nfs4_free_state_owners.
*/
-void nfs4_purge_state_owners(struct nfs_server *server)
+void nfs4_purge_state_owners(struct nfs_server *server, struct list_head *head)
{
struct nfs_client *clp = server->nfs_client;
struct nfs4_state_owner *sp, *tmp;
- LIST_HEAD(doomed);
spin_lock(&clp->cl_lock);
list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) {
- list_move(&sp->so_lru, &doomed);
+ list_move(&sp->so_lru, head);
nfs4_remove_state_owner_locked(sp);
}
spin_unlock(&clp->cl_lock);
+}
- list_for_each_entry_safe(sp, tmp, &doomed, so_lru) {
+/**
+ * nfs4_purge_state_owners - Release all cached state owners
+ * @head: resulting list of state owners
+ *
+ * Frees a list of state owners that was generated by
+ * nfs4_purge_state_owners
+ */
+void nfs4_free_state_owners(struct list_head *head)
+{
+ struct nfs4_state_owner *sp, *tmp;
+
+ list_for_each_entry_safe(sp, tmp, head, so_lru) {
list_del(&sp->so_lru);
nfs4_free_state_owner(sp);
}
@@ -1463,7 +1478,7 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
nfs4_schedule_state_manager(clp);
}
-static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
+static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err)
{
struct inode *inode = state->inode;
struct nfs_inode *nfsi = NFS_I(inode);
@@ -1474,6 +1489,8 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
if (ctx->state != state)
continue;
set_bit(NFS_CONTEXT_BAD, &ctx->flags);
+ pr_warn("NFSv4: state recovery failed for open file %pd2, "
+ "error = %d\n", ctx->dentry, err);
}
rcu_read_unlock();
}
@@ -1481,7 +1498,7 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
{
set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
- nfs4_state_mark_open_context_bad(state);
+ nfs4_state_mark_open_context_bad(state, error);
}
@@ -1512,6 +1529,7 @@ restart:
switch (status) {
case 0:
break;
+ case -ETIMEDOUT:
case -ESTALE:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_STALE_STATEID:
@@ -1605,6 +1623,7 @@ static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_st
static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops)
{
struct nfs4_state *state;
+ unsigned int loop = 0;
int status = 0;
/* Note: we rely on the sp->so_states list being ordered
@@ -1631,8 +1650,10 @@ restart:
switch (status) {
default:
- if (status >= 0)
+ if (status >= 0) {
+ loop = 0;
break;
+ }
printk(KERN_ERR "NFS: %s: unhandled error %d\n", __func__, status);
/* Fall through */
case -ENOENT:
@@ -1646,6 +1667,10 @@ restart:
break;
case -EAGAIN:
ssleep(1);
+ if (loop++ < 10) {
+ set_bit(ops->state_flag_bit, &state->flags);
+ break;
+ }
/* Fall through */
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_STALE_STATEID:
@@ -1658,11 +1683,13 @@ restart:
case -NFS4ERR_EXPIRED:
case -NFS4ERR_NO_GRACE:
nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state);
+ /* Fall through */
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -ETIMEDOUT:
goto out_err;
}
nfs4_put_open_state(state);
@@ -1856,12 +1883,13 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
struct nfs4_state_owner *sp;
struct nfs_server *server;
struct rb_node *pos;
+ LIST_HEAD(freeme);
int status = 0;
restart:
rcu_read_lock();
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
- nfs4_purge_state_owners(server);
+ nfs4_purge_state_owners(server, &freeme);
spin_lock(&clp->cl_lock);
for (pos = rb_first(&server->state_owners);
pos != NULL;
@@ -1890,6 +1918,7 @@ restart:
spin_unlock(&clp->cl_lock);
}
rcu_read_unlock();
+ nfs4_free_state_owners(&freeme);
return 0;
}
@@ -1945,7 +1974,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
return -EPERM;
case -EACCES:
case -NFS4ERR_DELAY:
- case -ETIMEDOUT:
case -EAGAIN:
ssleep(1);
break;
@@ -2574,7 +2602,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
}
/* Now recover expired state... */
- if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
+ if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
section = "reclaim nograce";
status = nfs4_do_reclaim(clp,
clp->cl_mvops->nograce_recovery_ops);
@@ -2582,6 +2610,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
continue;
if (status < 0)
goto out_error;
+ clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
}
nfs4_end_drain_session(clp);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index ed4e1b07447b..20b3717cd7ca 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -590,7 +590,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr,
}
hdr->res.fattr = &hdr->fattr;
- hdr->res.count = count;
+ hdr->res.count = 0;
hdr->res.eof = 0;
hdr->res.verf = &hdr->verf;
nfs_fattr_init(&hdr->fattr);
@@ -1251,20 +1251,23 @@ static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc,
int nfs_pageio_resend(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr)
{
- LIST_HEAD(failed);
+ LIST_HEAD(pages);
desc->pg_io_completion = hdr->io_completion;
desc->pg_dreq = hdr->dreq;
- while (!list_empty(&hdr->pages)) {
- struct nfs_page *req = nfs_list_entry(hdr->pages.next);
+ list_splice_init(&hdr->pages, &pages);
+ while (!list_empty(&pages)) {
+ struct nfs_page *req = nfs_list_entry(pages.next);
if (!nfs_pageio_add_request(desc, req))
- nfs_list_move_request(req, &failed);
+ break;
}
nfs_pageio_complete(desc);
- if (!list_empty(&failed)) {
- list_move(&failed, &hdr->pages);
- return desc->pg_error < 0 ? desc->pg_error : -EIO;
+ if (!list_empty(&pages)) {
+ int err = desc->pg_error < 0 ? desc->pg_error : -EIO;
+ hdr->completion_ops->error_cleanup(&pages, err);
+ nfs_set_pgio_error(hdr, err, hdr->io_start);
+ return err;
}
return 0;
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 75bd5b552ba4..4525d5acae38 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1903,12 +1903,6 @@ lookup_again:
goto out_unlock;
}
- if (!nfs4_valid_open_stateid(ctx->state)) {
- trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
- PNFS_UPDATE_LAYOUT_INVALID_OPEN);
- goto out_unlock;
- }
-
/*
* Choose a stateid for the LAYOUTGET. If we don't have a layout
* stateid, or it has been invalidated, then we must use the open
@@ -1939,6 +1933,7 @@ lookup_again:
iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
NULL, &stateid, NULL);
if (status != 0) {
+ lseg = ERR_PTR(status);
trace_pnfs_update_layout(ino, pos, count,
iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_INVALID_OPEN);
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index c0046c348910..82af4809b869 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -627,11 +627,16 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
/* Add this address as an alias */
rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
rpc_clnt_test_and_add_xprt, NULL);
- } else
- clp = get_v3_ds_connect(mds_srv,
- (struct sockaddr *)&da->da_addr,
- da->da_addrlen, IPPROTO_TCP,
- timeo, retrans);
+ continue;
+ }
+ clp = get_v3_ds_connect(mds_srv,
+ (struct sockaddr *)&da->da_addr,
+ da->da_addrlen, IPPROTO_TCP,
+ timeo, retrans);
+ if (IS_ERR(clp))
+ continue;
+ clp->cl_rpcclient->cl_softerr = 0;
+ clp->cl_rpcclient->cl_softrtry = 0;
}
if (IS_ERR(clp)) {
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 5552fa8b6e12..0f7288b94633 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -594,7 +594,8 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
/* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes
*/
- if (hdr->args.offset + hdr->res.count >= hdr->res.fattr->size)
+ if ((hdr->res.count == 0 && hdr->args.count > 0) ||
+ hdr->args.offset + hdr->res.count >= hdr->res.fattr->size)
hdr->res.eof = 1;
}
return 0;
@@ -615,8 +616,10 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task,
static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
- if (task->tk_status >= 0)
+ if (task->tk_status >= 0) {
+ hdr->res.count = hdr->args.count;
nfs_writeback_update_inode(hdr);
+ }
return 0;
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index c19841c82b6a..cfe0b586eadd 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -91,19 +91,25 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
}
EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
-static void nfs_readpage_release(struct nfs_page *req)
+static void nfs_readpage_release(struct nfs_page *req, int error)
{
struct inode *inode = d_inode(nfs_req_openctx(req)->dentry);
+ struct page *page = req->wb_page;
dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode), req->wb_bytes,
(long long)req_offset(req));
+ if (nfs_error_is_fatal_on_server(error) && error != -ETIMEDOUT)
+ SetPageError(page);
if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
- if (PageUptodate(req->wb_page))
- nfs_readpage_to_fscache(inode, req->wb_page, 0);
+ struct address_space *mapping = page_file_mapping(page);
- unlock_page(req->wb_page);
+ if (PageUptodate(page))
+ nfs_readpage_to_fscache(inode, page, 0);
+ else if (!PageError(page) && !PagePrivate(page))
+ generic_error_remove_page(mapping, page);
+ unlock_page(page);
}
nfs_release_request(req);
}
@@ -131,7 +137,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
&nfs_async_read_completion_ops);
if (!nfs_pageio_add_request(&pgio, new)) {
nfs_list_remove_request(new);
- nfs_readpage_release(new);
+ nfs_readpage_release(new, pgio.pg_error);
}
nfs_pageio_complete(&pgio);
@@ -153,6 +159,7 @@ static void nfs_page_group_set_uptodate(struct nfs_page *req)
static void nfs_read_completion(struct nfs_pgio_header *hdr)
{
unsigned long bytes = 0;
+ int error;
if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
goto out;
@@ -179,14 +186,19 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
zero_user_segment(page, start, end);
}
}
+ error = 0;
bytes += req->wb_bytes;
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
if (bytes <= hdr->good_bytes)
nfs_page_group_set_uptodate(req);
+ else {
+ error = hdr->error;
+ xchg(&nfs_req_openctx(req)->error, error);
+ }
} else
nfs_page_group_set_uptodate(req);
nfs_list_remove_request(req);
- nfs_readpage_release(req);
+ nfs_readpage_release(req, error);
}
out:
hdr->release(hdr);
@@ -213,7 +225,7 @@ nfs_async_read_error(struct list_head *head, int error)
while (!list_empty(head)) {
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
- nfs_readpage_release(req);
+ nfs_readpage_release(req, error);
}
}
@@ -337,8 +349,13 @@ int nfs_readpage(struct file *file, struct page *page)
goto out;
}
+ xchg(&ctx->error, 0);
error = nfs_readpage_async(ctx, inode, page);
-
+ if (!error) {
+ error = wait_on_page_locked_killable(page);
+ if (!PageUptodate(page) && !error)
+ error = xchg(&ctx->error, 0);
+ }
out:
put_nfs_open_context(ctx);
return error;
@@ -372,8 +389,8 @@ readpage_async_filler(void *data, struct page *page)
zero_user_segment(page, len, PAGE_SIZE);
if (!nfs_pageio_add_request(desc->pgio, new)) {
nfs_list_remove_request(new);
- nfs_readpage_release(new);
error = desc->pgio->pg_error;
+ nfs_readpage_release(new, error);
goto out;
}
return 0;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 628631e2e34f..703f595dce90 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2260,6 +2260,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
data->acdirmin != nfss->acdirmin / HZ ||
data->acdirmax != nfss->acdirmax / HZ ||
data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
+ (data->options & NFS_OPTION_FSCACHE) != (nfss->options & NFS_OPTION_FSCACHE) ||
data->nfs_server.port != nfss->port ||
data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
!rpc_cmp_addr((struct sockaddr *)&data->nfs_server.address,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 92d9cadc6102..85ca49549b39 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -57,6 +57,7 @@ static const struct rpc_call_ops nfs_commit_ops;
static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
static const struct nfs_rw_ops nfs_rw_write_ops;
+static void nfs_inode_remove_request(struct nfs_page *req);
static void nfs_clear_request_commit(struct nfs_page *req);
static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
struct inode *inode);
@@ -591,23 +592,13 @@ release_request:
static void nfs_write_error(struct nfs_page *req, int error)
{
+ nfs_set_pageerror(page_file_mapping(req->wb_page));
nfs_mapping_set_error(req->wb_page, error);
+ nfs_inode_remove_request(req);
nfs_end_page_writeback(req);
nfs_release_request(req);
}
-static bool
-nfs_error_is_fatal_on_server(int err)
-{
- switch (err) {
- case 0:
- case -ERESTARTSYS:
- case -EINTR:
- return false;
- }
- return nfs_error_is_fatal(err);
-}
-
/*
* Find an associated nfs write request, and prepare to flush it out
* May return an error if the user signalled nfs_wait_on_request().
@@ -615,7 +606,6 @@ nfs_error_is_fatal_on_server(int err)
static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
struct page *page)
{
- struct address_space *mapping;
struct nfs_page *req;
int ret = 0;
@@ -630,12 +620,11 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
/* If there is a fatal error that covers this write, just exit */
- ret = 0;
- mapping = page_file_mapping(page);
- if (test_bit(AS_ENOSPC, &mapping->flags) ||
- test_bit(AS_EIO, &mapping->flags))
+ ret = pgio->pg_error;
+ if (nfs_error_is_fatal_on_server(ret))
goto out_launder;
+ ret = 0;
if (!nfs_pageio_add_request(pgio, req)) {
ret = pgio->pg_error;
/*
@@ -647,6 +636,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
} else
ret = -EAGAIN;
nfs_redirty_request(req);
+ pgio->pg_error = 0;
} else
nfs_add_stats(page_file_mapping(page)->host,
NFSIOS_WRITEPAGES, 1);
@@ -666,7 +656,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
ret = nfs_page_async_flush(pgio, page);
if (ret == -EAGAIN) {
redirty_page_for_writepage(wbc, page);
- ret = 0;
+ ret = AOP_WRITEPAGE_ACTIVATE;
}
return ret;
}
@@ -685,10 +675,11 @@ static int nfs_writepage_locked(struct page *page,
nfs_pageio_init_write(&pgio, inode, 0,
false, &nfs_async_write_completion_ops);
err = nfs_do_writepage(page, wbc, &pgio);
+ pgio.pg_error = 0;
nfs_pageio_complete(&pgio);
if (err < 0)
return err;
- if (pgio.pg_error < 0)
+ if (nfs_error_is_fatal(pgio.pg_error))
return pgio.pg_error;
return 0;
}
@@ -698,7 +689,8 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
int ret;
ret = nfs_writepage_locked(page, wbc);
- unlock_page(page);
+ if (ret != AOP_WRITEPAGE_ACTIVATE)
+ unlock_page(page);
return ret;
}
@@ -707,7 +699,8 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control *
int ret;
ret = nfs_do_writepage(page, wbc, data);
- unlock_page(page);
+ if (ret != AOP_WRITEPAGE_ACTIVATE)
+ unlock_page(page);
return ret;
}
@@ -733,13 +726,14 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
&nfs_async_write_completion_ops);
pgio.pg_io_completion = ioc;
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
+ pgio.pg_error = 0;
nfs_pageio_complete(&pgio);
nfs_io_completion_put(ioc);
if (err < 0)
goto out_err;
err = pgio.pg_error;
- if (err < 0)
+ if (nfs_error_is_fatal(err))
goto out_err;
return 0;
out_err:
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 26ad75ae2be0..96352ab7bd81 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -571,7 +571,7 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
*/
static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
{
- struct nfsd_net *nn = v;
+ struct nfsd_net *nn = m->private;
seq_printf(m, "max entries: %u\n", nn->max_drc_entries);
seq_printf(m, "num entries: %u\n",
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 13c548733860..3cf4f6aa48d6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1171,13 +1171,17 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
return inode;
}
-static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl)
{
struct inode *inode;
inode = nfsd_get_inode(dir->i_sb, mode);
if (!inode)
return -ENOMEM;
+ if (ncl) {
+ inode->i_private = ncl;
+ kref_get(&ncl->cl_ref);
+ }
d_add(dentry, inode);
inc_nlink(dir);
fsnotify_mkdir(dir, dentry);
@@ -1194,17 +1198,14 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc
dentry = d_alloc_name(parent, name);
if (!dentry)
goto out_err;
- ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600);
+ ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl);
if (ret)
goto out_err;
- if (ncl) {
- d_inode(dentry)->i_private = ncl;
- kref_get(&ncl->cl_ref);
- }
out:
inode_unlock(dir);
return dentry;
out_err:
+ dput(dentry);
dentry = ERR_PTR(ret);
goto out;
}
@@ -1214,11 +1215,9 @@ static void clear_ncl(struct inode *inode)
struct nfsdfs_client *ncl = inode->i_private;
inode->i_private = NULL;
- synchronize_rcu();
kref_put(&ncl->cl_ref, ncl->cl_release);
}
-
static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
{
struct nfsdfs_client *nc = inode->i_private;
@@ -1232,9 +1231,9 @@ struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
{
struct nfsdfs_client *nc;
- rcu_read_lock();
+ inode_lock_shared(inode);
nc = __get_nfsdfs_client(inode);
- rcu_read_unlock();
+ inode_unlock_shared(inode);
return nc;
}
/* from __rpc_unlink */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 385f3aaa2448..90c830e3758e 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -3825,7 +3825,6 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
int low_bucket = 0, bucket, high_bucket;
struct ocfs2_xattr_bucket *search;
- u32 last_hash;
u64 blkno, lower_blkno = 0;
search = ocfs2_xattr_bucket_new(inode);
@@ -3869,8 +3868,6 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
if (xh->xh_count)
xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1];
- last_hash = le32_to_cpu(xe->xe_name_hash);
-
/* record lower_blkno which may be the insert place. */
lower_blkno = blkno;
diff --git a/fs/open.c b/fs/open.c
index b5b80469b93d..a59abe3c669a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -374,6 +374,25 @@ long do_faccessat(int dfd, const char __user *filename, int mode)
override_cred->cap_permitted;
}
+ /*
+ * The new set of credentials can *only* be used in
+ * task-synchronous circumstances, and does not need
+ * RCU freeing, unless somebody then takes a separate
+ * reference to it.
+ *
+ * NOTE! This is _only_ true because this credential
+ * is used purely for override_creds() that installs
+ * it as the subjective cred. Other threads will be
+ * accessing ->real_cred, not the subjective cred.
+ *
+ * If somebody _does_ make a copy of this (using the
+ * 'get_current_cred()' function), that will clear the
+ * non_rcu field, because now that other user may be
+ * expecting RCU freeing. But normal thread-synchronous
+ * cred accesses will keep things non-RCY.
+ */
+ override_cred->non_rcu = 1;
+
old_cred = override_creds(override_cred);
retry:
res = user_path_at(dfd, filename, lookup_flags, &path);
diff --git a/fs/read_write.c b/fs/read_write.c
index 1f5088dec566..5bbf587f5bc1 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1811,10 +1811,7 @@ static int generic_remap_check_len(struct inode *inode_in,
return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL;
}
-/*
- * Read a page's worth of file data into the page cache. Return the page
- * locked.
- */
+/* Read a page's worth of file data into the page cache. */
static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
{
struct page *page;
@@ -1826,11 +1823,33 @@ static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
put_page(page);
return ERR_PTR(-EIO);
}
- lock_page(page);
return page;
}
/*
+ * Lock two pages, ensuring that we lock in offset order if the pages are from
+ * the same file.
+ */
+static void vfs_lock_two_pages(struct page *page1, struct page *page2)
+{
+ /* Always lock in order of increasing index. */
+ if (page1->index > page2->index)
+ swap(page1, page2);
+
+ lock_page(page1);
+ if (page1 != page2)
+ lock_page(page2);
+}
+
+/* Unlock two pages, being careful not to unlock the same page twice. */
+static void vfs_unlock_two_pages(struct page *page1, struct page *page2)
+{
+ unlock_page(page1);
+ if (page1 != page2)
+ unlock_page(page2);
+}
+
+/*
* Compare extents of two files to see if they are the same.
* Caller must have locked both inodes to prevent write races.
*/
@@ -1867,10 +1886,24 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
dest_page = vfs_dedupe_get_page(dest, destoff);
if (IS_ERR(dest_page)) {
error = PTR_ERR(dest_page);
- unlock_page(src_page);
put_page(src_page);
goto out_error;
}
+
+ vfs_lock_two_pages(src_page, dest_page);
+
+ /*
+ * Now that we've locked both pages, make sure they're still
+ * mapped to the file data we're interested in. If not,
+ * someone is invalidating pages on us and we lose.
+ */
+ if (!PageUptodate(src_page) || !PageUptodate(dest_page) ||
+ src_page->mapping != src->i_mapping ||
+ dest_page->mapping != dest->i_mapping) {
+ same = false;
+ goto unlock;
+ }
+
src_addr = kmap_atomic(src_page);
dest_addr = kmap_atomic(dest_page);
@@ -1882,8 +1915,8 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
kunmap_atomic(dest_addr);
kunmap_atomic(src_addr);
- unlock_page(dest_page);
- unlock_page(src_page);
+unlock:
+ vfs_unlock_two_pages(src_page, dest_page);
put_page(dest_page);
put_page(src_page);
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 04f09689cd6d..1600034a929b 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -119,6 +119,7 @@ static int traverse(struct seq_file *m, loff_t offset)
}
if (seq_has_overflowed(m))
goto Eoverflow;
+ p = m->op->next(m, p, &m->index);
if (pos + m->count > offset) {
m->from = offset - pos;
m->count -= m->from;
@@ -126,7 +127,6 @@ static int traverse(struct seq_file *m, loff_t offset)
}
pos += m->count;
m->count = 0;
- p = m->op->next(m, p, &m->index);
if (pos == offset)
break;
}
diff --git a/fs/super.c b/fs/super.c
index 113c58f19425..5960578a4076 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -478,13 +478,10 @@ EXPORT_SYMBOL(generic_shutdown_super);
bool mount_capable(struct fs_context *fc)
{
- struct user_namespace *user_ns = fc->global ? &init_user_ns
- : fc->user_ns;
-
if (!(fc->fs_type->fs_flags & FS_USERNS_MOUNT))
return capable(CAP_SYS_ADMIN);
else
- return ns_capable(user_ns, CAP_SYS_ADMIN);
+ return ns_capable(fc->user_ns, CAP_SYS_ADMIN);
}
/**
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
index 80d7301ab76d..c0b84e960b20 100644
--- a/fs/ubifs/budget.c
+++ b/fs/ubifs/budget.c
@@ -51,7 +51,7 @@
static void shrink_liability(struct ubifs_info *c, int nr_to_write)
{
down_read(&c->vfs_sb->s_umount);
- writeback_inodes_sb(c->vfs_sb, WB_REASON_FS_FREE_SPACE);
+ writeback_inodes_sb_nr(c->vfs_sb, nr_to_write, WB_REASON_FS_FREE_SPACE);
up_read(&c->vfs_sb->s_umount);
}
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index b52624e28fa1..3b4b4114f208 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -129,7 +129,6 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
{
if (orph->del) {
- spin_unlock(&c->orphan_lock);
dbg_gen("deleted twice ino %lu", orph->inum);
return;
}
@@ -138,7 +137,6 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
orph->del = 1;
orph->dnext = c->orph_dnext;
c->orph_dnext = orph;
- spin_unlock(&c->orphan_lock);
dbg_gen("delete later ino %lu", orph->inum);
return;
}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 2c0803b0ac3a..8c1d571334bc 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -609,6 +609,10 @@ static int init_constants_early(struct ubifs_info *c)
c->max_bu_buf_len = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
if (c->max_bu_buf_len > c->leb_size)
c->max_bu_buf_len = c->leb_size;
+
+ /* Log is ready, preserve one LEB for commits. */
+ c->min_log_bytes = c->leb_size;
+
return 0;
}
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index ccbdbd62f0d8..fe6d804a38dc 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -880,6 +880,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
/* len == 0 means wake all */
struct userfaultfd_wake_range range = { .len = 0, };
unsigned long new_flags;
+ bool still_valid;
WRITE_ONCE(ctx->released, true);
@@ -895,8 +896,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
* taking the mmap_sem for writing.
*/
down_write(&mm->mmap_sem);
- if (!mmget_still_valid(mm))
- goto skip_mm;
+ still_valid = mmget_still_valid(mm);
prev = NULL;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
cond_resched();
@@ -907,19 +907,20 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
continue;
}
new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
- prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
- new_flags, vma->anon_vma,
- vma->vm_file, vma->vm_pgoff,
- vma_policy(vma),
- NULL_VM_UFFD_CTX);
- if (prev)
- vma = prev;
- else
- prev = vma;
+ if (still_valid) {
+ prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
+ new_flags, vma->anon_vma,
+ vma->vm_file, vma->vm_pgoff,
+ vma_policy(vma),
+ NULL_VM_UFFD_CTX);
+ if (prev)
+ vma = prev;
+ else
+ prev = vma;
+ }
vma->vm_flags = new_flags;
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
}
-skip_mm:
up_write(&mm->mmap_sem);
mmput(mm);
wakeup:
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index baf0b72c0a37..07aad70f3931 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -3835,15 +3835,28 @@ xfs_bmapi_read(
XFS_STATS_INC(mp, xs_blk_mapr);
ifp = XFS_IFORK_PTR(ip, whichfork);
+ if (!ifp) {
+ /* No CoW fork? Return a hole. */
+ if (whichfork == XFS_COW_FORK) {
+ mval->br_startoff = bno;
+ mval->br_startblock = HOLESTARTBLOCK;
+ mval->br_blockcount = len;
+ mval->br_state = XFS_EXT_NORM;
+ *nmap = 1;
+ return 0;
+ }
- /* No CoW fork? Return a hole. */
- if (whichfork == XFS_COW_FORK && !ifp) {
- mval->br_startoff = bno;
- mval->br_startblock = HOLESTARTBLOCK;
- mval->br_blockcount = len;
- mval->br_state = XFS_EXT_NORM;
- *nmap = 1;
- return 0;
+ /*
+ * A missing attr ifork implies that the inode says we're in
+ * extents or btree format but failed to pass the inode fork
+ * verifier while trying to load it. Treat that as a file
+ * corruption too.
+ */
+#ifdef DEBUG
+ xfs_alert(mp, "%s: inode %llu missing fork %d",
+ __func__, ip->i_ino, whichfork);
+#endif /* DEBUG */
+ return -EFSCORRUPTED;
}
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index d1c77fd0815d..0bf56e94bfe9 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -487,10 +487,8 @@ xfs_da3_split(
ASSERT(state->path.active == 0);
oldblk = &state->path.blk[0];
error = xfs_da3_root_split(state, oldblk, addblk);
- if (error) {
- addblk->bp = NULL;
- return error; /* GROT: dir is inconsistent */
- }
+ if (error)
+ goto out;
/*
* Update pointers to the node which used to be block 0 and just got
@@ -505,7 +503,10 @@ xfs_da3_split(
*/
node = oldblk->bp->b_addr;
if (node->hdr.info.forw) {
- ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno);
+ if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
+ error = -EFSCORRUPTED;
+ goto out;
+ }
node = addblk->bp->b_addr;
node->hdr.info.back = cpu_to_be32(oldblk->blkno);
xfs_trans_log_buf(state->args->trans, addblk->bp,
@@ -514,15 +515,19 @@ xfs_da3_split(
}
node = oldblk->bp->b_addr;
if (node->hdr.info.back) {
- ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno);
+ if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
+ error = -EFSCORRUPTED;
+ goto out;
+ }
node = addblk->bp->b_addr;
node->hdr.info.forw = cpu_to_be32(oldblk->blkno);
xfs_trans_log_buf(state->args->trans, addblk->bp,
XFS_DA_LOGRANGE(node, &node->hdr.info,
sizeof(node->hdr.info)));
}
+out:
addblk->bp = NULL;
- return 0;
+ return error;
}
/*
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index afcc6642690a..1fc44efc344d 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -741,7 +741,8 @@ xfs_dir2_leafn_lookup_for_entry(
ents = dp->d_ops->leaf_ents_p(leaf);
xfs_dir3_leaf_check(dp, bp);
- ASSERT(leafhdr.count > 0);
+ if (leafhdr.count <= 0)
+ return -EFSCORRUPTED;
/*
* Look up the hash value in the leaf entries.
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index 94c4f1de1922..77ff9f97bcda 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -278,7 +278,11 @@ xchk_da_btree_block_check_sibling(
/* Compare upper level pointer to sibling pointer. */
if (ds->state->altpath.blk[level].blkno != sibling)
xchk_da_set_corrupt(ds, level);
- xfs_trans_brelse(ds->dargs.trans, ds->state->altpath.blk[level].bp);
+ if (ds->state->altpath.blk[level].bp) {
+ xfs_trans_brelse(ds->dargs.trans,
+ ds->state->altpath.blk[level].bp);
+ ds->state->altpath.blk[level].bp = NULL;
+ }
out:
return error;
}
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 7fcf7569743f..7bd7534f5051 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -547,63 +547,12 @@ xfs_file_compat_ioctl(
struct inode *inode = file_inode(filp);
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
- void __user *arg = (void __user *)p;
+ void __user *arg = compat_ptr(p);
int error;
trace_xfs_file_compat_ioctl(ip);
switch (cmd) {
- /* No size or alignment issues on any arch */
- case XFS_IOC_DIOINFO:
- case XFS_IOC_FSGEOMETRY_V4:
- case XFS_IOC_FSGEOMETRY:
- case XFS_IOC_AG_GEOMETRY:
- case XFS_IOC_FSGETXATTR:
- case XFS_IOC_FSSETXATTR:
- case XFS_IOC_FSGETXATTRA:
- case XFS_IOC_FSSETDM:
- case XFS_IOC_GETBMAP:
- case XFS_IOC_GETBMAPA:
- case XFS_IOC_GETBMAPX:
- case XFS_IOC_FSCOUNTS:
- case XFS_IOC_SET_RESBLKS:
- case XFS_IOC_GET_RESBLKS:
- case XFS_IOC_FSGROWFSLOG:
- case XFS_IOC_GOINGDOWN:
- case XFS_IOC_ERROR_INJECTION:
- case XFS_IOC_ERROR_CLEARALL:
- case FS_IOC_GETFSMAP:
- case XFS_IOC_SCRUB_METADATA:
- case XFS_IOC_BULKSTAT:
- case XFS_IOC_INUMBERS:
- return xfs_file_ioctl(filp, cmd, p);
-#if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
- /*
- * These are handled fine if no alignment issues. To support x32
- * which uses native 64-bit alignment we must emit these cases in
- * addition to the ia-32 compat set below.
- */
- case XFS_IOC_ALLOCSP:
- case XFS_IOC_FREESP:
- case XFS_IOC_RESVSP:
- case XFS_IOC_UNRESVSP:
- case XFS_IOC_ALLOCSP64:
- case XFS_IOC_FREESP64:
- case XFS_IOC_RESVSP64:
- case XFS_IOC_UNRESVSP64:
- case XFS_IOC_FSGEOMETRY_V1:
- case XFS_IOC_FSGROWFSDATA:
- case XFS_IOC_FSGROWFSRT:
- case XFS_IOC_ZERO_RANGE:
-#ifdef CONFIG_X86_X32
- /*
- * x32 special: this gets a different cmd number from the ia-32 compat
- * case below; the associated data will match native 64-bit alignment.
- */
- case XFS_IOC_SWAPEXT:
-#endif
- return xfs_file_ioctl(filp, cmd, p);
-#endif
#if defined(BROKEN_X86_ALIGNMENT)
case XFS_IOC_ALLOCSP_32:
case XFS_IOC_FREESP_32:
@@ -705,6 +654,7 @@ xfs_file_compat_ioctl(
case XFS_IOC_FSSETDM_BY_HANDLE_32:
return xfs_compat_fssetdm_by_handle(filp, arg);
default:
- return -ENOIOCTLCMD;
+ /* try the native version */
+ return xfs_file_ioctl(filp, cmd, (unsigned long)arg);
}
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ff3c1fae5357..fe285d123d69 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -793,6 +793,7 @@ xfs_setattr_nonsize(
out_cancel:
xfs_trans_cancel(tp);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
out_dqrele:
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index a8a06bb78ea8..f5c955d35be4 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -272,6 +272,7 @@ xfs_bulkstat_to_bstat(
struct xfs_bstat *bs1,
const struct xfs_bulkstat *bstat)
{
+ /* memset is needed here because of padding holes in the structure. */
memset(bs1, 0, sizeof(struct xfs_bstat));
bs1->bs_ino = bstat->bs_ino;
bs1->bs_mode = bstat->bs_mode;
@@ -388,6 +389,8 @@ xfs_inumbers_to_inogrp(
struct xfs_inogrp *ig1,
const struct xfs_inumbers *ig)
{
+ /* memset is needed here because of padding holes in the structure. */
+ memset(ig1, 0, sizeof(struct xfs_inogrp));
ig1->xi_startino = ig->xi_startino;
ig1->xi_alloccount = ig->xi_alloccount;
ig1->xi_allocmask = ig->xi_allocmask;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 00e9f5c388d3..7fc3c1ad36bc 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -429,10 +429,7 @@ xfs_log_reserve(
ASSERT(*ticp == NULL);
tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
- KM_SLEEP | KM_MAYFAIL);
- if (!tic)
- return -ENOMEM;
-
+ KM_SLEEP);
*ticp = tic;
xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 0c954cad7449..a339bd5fa260 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -32,7 +32,7 @@ xfs_break_leased_layouts(
struct xfs_inode *ip = XFS_I(inode);
int error;
- while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
+ while ((error = break_layout(inode, false)) == -EWOULDBLOCK) {
xfs_iunlock(ip, *iolock);
*did_unlock = true;
error = break_layout(inode, true);
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index c4ec7afd1170..edbe37b7f636 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1190,11 +1190,11 @@ xfs_reflink_remap_blocks(
}
/*
- * Grab the exclusive iolock for a data copy from src to dest, making
- * sure to abide vfs locking order (lowest pointer value goes first) and
- * breaking the pnfs layout leases on dest before proceeding. The loop
- * is needed because we cannot call the blocking break_layout() with the
- * src iolock held, and therefore have to back out both locks.
+ * Grab the exclusive iolock for a data copy from src to dest, making sure to
+ * abide vfs locking order (lowest pointer value goes first) and breaking the
+ * layout leases before proceeding. The loop is needed because we cannot call
+ * the blocking break_layout() with the iolocks held, and therefore have to
+ * back out both locks.
*/
static int
xfs_iolock_two_inodes_and_break_layout(
@@ -1203,33 +1203,44 @@ xfs_iolock_two_inodes_and_break_layout(
{
int error;
-retry:
- if (src < dest) {
- inode_lock_shared(src);
- inode_lock_nested(dest, I_MUTEX_NONDIR2);
- } else {
- /* src >= dest */
- inode_lock(dest);
- }
+ if (src > dest)
+ swap(src, dest);
- error = break_layout(dest, false);
- if (error == -EWOULDBLOCK) {
- inode_unlock(dest);
- if (src < dest)
- inode_unlock_shared(src);
+retry:
+ /* Wait to break both inodes' layouts before we start locking. */
+ error = break_layout(src, true);
+ if (error)
+ return error;
+ if (src != dest) {
error = break_layout(dest, true);
if (error)
return error;
- goto retry;
}
+
+ /* Lock one inode and make sure nobody got in and leased it. */
+ inode_lock(src);
+ error = break_layout(src, false);
if (error) {
+ inode_unlock(src);
+ if (error == -EWOULDBLOCK)
+ goto retry;
+ return error;
+ }
+
+ if (src == dest)
+ return 0;
+
+ /* Lock the other inode and make sure nobody got in and leased it. */
+ inode_lock_nested(dest, I_MUTEX_NONDIR2);
+ error = break_layout(dest, false);
+ if (error) {
+ inode_unlock(src);
inode_unlock(dest);
- if (src < dest)
- inode_unlock_shared(src);
+ if (error == -EWOULDBLOCK)
+ goto retry;
return error;
}
- if (src > dest)
- inode_lock_shared_nested(src, I_MUTEX_NONDIR2);
+
return 0;
}
@@ -1247,10 +1258,10 @@ xfs_reflink_remap_unlock(
xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
if (!same_inode)
- xfs_iunlock(src, XFS_MMAPLOCK_SHARED);
+ xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
inode_unlock(inode_out);
if (!same_inode)
- inode_unlock_shared(inode_in);
+ inode_unlock(inode_in);
}
/*
@@ -1325,7 +1336,7 @@ xfs_reflink_remap_prep(
if (same_inode)
xfs_ilock(src, XFS_MMAPLOCK_EXCL);
else
- xfs_lock_two_inodes(src, XFS_MMAPLOCK_SHARED, dest,
+ xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest,
XFS_MMAPLOCK_EXCL);
/* Check file eligibility and prepare for block sharing. */
diff --git a/include/Kbuild b/include/Kbuild
index c38f0d46b267..4d5a03a81fb5 100644
--- a/include/Kbuild
+++ b/include/Kbuild
@@ -550,7 +550,6 @@ header-test- += linux/platform_data/sky81452-backlight.h
header-test- += linux/platform_data/spi-davinci.h
header-test- += linux/platform_data/spi-ep93xx.h
header-test- += linux/platform_data/spi-mt65xx.h
-header-test- += linux/platform_data/spi-nuc900.h
header-test- += linux/platform_data/st_sensors_pdata.h
header-test- += linux/platform_data/ti-sysc.h
header-test- += linux/platform_data/timer-ixp4xx.h
@@ -569,7 +568,6 @@ header-test- += linux/platform_data/usb3503.h
header-test- += linux/platform_data/ux500_wdt.h
header-test- += linux/platform_data/video-clcd-versatile.h
header-test- += linux/platform_data/video-imxfb.h
-header-test- += linux/platform_data/video-nuc900fb.h
header-test- += linux/platform_data/video-pxafb.h
header-test- += linux/platform_data/video_s3c.h
header-test- += linux/platform_data/voltage-omap.h
diff --git a/include/asm-generic/5level-fixup.h b/include/asm-generic/5level-fixup.h
index bb6cb347018c..f6947da70d71 100644
--- a/include/asm-generic/5level-fixup.h
+++ b/include/asm-generic/5level-fixup.h
@@ -19,9 +19,24 @@
#define p4d_alloc(mm, pgd, address) (pgd)
#define p4d_offset(pgd, start) (pgd)
-#define p4d_none(p4d) 0
-#define p4d_bad(p4d) 0
-#define p4d_present(p4d) 1
+
+#ifndef __ASSEMBLY__
+static inline int p4d_none(p4d_t p4d)
+{
+ return 0;
+}
+
+static inline int p4d_bad(p4d_t p4d)
+{
+ return 0;
+}
+
+static inline int p4d_present(p4d_t p4d)
+{
+ return 1;
+}
+#endif
+
#define p4d_ERROR(p4d) do { } while (0)
#define p4d_clear(p4d) pgd_clear(p4d)
#define p4d_val(p4d) pgd_val(p4d)
diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h
index dc9726fdac8f..b2a9c74efa55 100644
--- a/include/asm-generic/div64.h
+++ b/include/asm-generic/div64.h
@@ -28,12 +28,12 @@
/**
* do_div - returns 2 values: calculate remainder and update new dividend
- * @n: pointer to uint64_t dividend (will be updated)
+ * @n: uint64_t dividend (will be updated)
* @base: uint32_t divisor
*
* Summary:
- * ``uint32_t remainder = *n % base;``
- * ``*n = *n / base;``
+ * ``uint32_t remainder = n % base;``
+ * ``n = n / base;``
*
* Return: (uint32_t)remainder
*
diff --git a/include/asm-generic/error-injection.h b/include/asm-generic/error-injection.h
index 95a159a4137f..80ca61058dd2 100644
--- a/include/asm-generic/error-injection.h
+++ b/include/asm-generic/error-injection.h
@@ -16,6 +16,8 @@ struct error_injection_entry {
int etype;
};
+struct pt_regs;
+
#ifdef CONFIG_FUNCTION_ERROR_INJECTION
/*
* Whitelist ganerating macro. Specify functions which can be
@@ -28,8 +30,12 @@ static struct error_injection_entry __used \
.addr = (unsigned long)fname, \
.etype = EI_ETYPE_##_etype, \
};
+
+void override_function_with_return(struct pt_regs *regs);
#else
#define ALLOW_ERROR_INJECTION(fname, _etype)
+
+static inline void override_function_with_return(struct pt_regs *regs) { }
#endif
#endif
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 8666fe7f35d7..02970b11f71f 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -118,26 +118,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
static inline int
arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
{
- int oldval = 0, ret;
-
- pagefault_disable();
-
- switch (op) {
- case FUTEX_OP_SET:
- case FUTEX_OP_ADD:
- case FUTEX_OP_OR:
- case FUTEX_OP_ANDN:
- case FUTEX_OP_XOR:
- default:
- ret = -ENOSYS;
- }
-
- pagefault_enable();
-
- if (!ret)
- *oval = oldval;
-
- return ret;
+ return -ENOSYS;
}
static inline int
diff --git a/include/asm-generic/getorder.h b/include/asm-generic/getorder.h
index c64bea7a52be..e9f20b813a69 100644
--- a/include/asm-generic/getorder.h
+++ b/include/asm-generic/getorder.h
@@ -7,24 +7,6 @@
#include <linux/compiler.h>
#include <linux/log2.h>
-/*
- * Runtime evaluation of get_order()
- */
-static inline __attribute_const__
-int __get_order(unsigned long size)
-{
- int order;
-
- size--;
- size >>= PAGE_SHIFT;
-#if BITS_PER_LONG == 32
- order = fls(size);
-#else
- order = fls64(size);
-#endif
- return order;
-}
-
/**
* get_order - Determine the allocation order of a memory size
* @size: The size for which to get the order
@@ -43,19 +25,27 @@ int __get_order(unsigned long size)
* to hold an object of the specified size.
*
* The result is undefined if the size is 0.
- *
- * This function may be used to initialise variables with compile time
- * evaluations of constants.
*/
-#define get_order(n) \
-( \
- __builtin_constant_p(n) ? ( \
- ((n) == 0UL) ? BITS_PER_LONG - PAGE_SHIFT : \
- (((n) < (1UL << PAGE_SHIFT)) ? 0 : \
- ilog2((n) - 1) - PAGE_SHIFT + 1) \
- ) : \
- __get_order(n) \
-)
+static inline __attribute_const__ int get_order(unsigned long size)
+{
+ if (__builtin_constant_p(size)) {
+ if (!size)
+ return BITS_PER_LONG - PAGE_SHIFT;
+
+ if (size < (1UL << PAGE_SHIFT))
+ return 0;
+
+ return ilog2((size) - 1) - PAGE_SHIFT + 1;
+ }
+
+ size--;
+ size >>= PAGE_SHIFT;
+#if BITS_PER_LONG == 32
+ return fls(size);
+#else
+ return fls64(size);
+#endif
+}
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h
index c3046c920063..d683f5e6d791 100644
--- a/include/asm-generic/preempt.h
+++ b/include/asm-generic/preempt.h
@@ -78,11 +78,11 @@ static __always_inline bool should_resched(int preempt_offset)
tif_need_resched());
}
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
extern asmlinkage void preempt_schedule(void);
#define __preempt_schedule() preempt_schedule()
extern asmlinkage void preempt_schedule_notrace(void);
#define __preempt_schedule_notrace() preempt_schedule_notrace()
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
#endif /* __ASM_PREEMPT_H */
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 72d51d1e9dd9..5cf2c5dd8b1e 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -149,6 +149,8 @@ struct drm_client_buffer {
struct drm_client_buffer *
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer);
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);
int drm_client_modeset_create(struct drm_client_dev *client);
void drm_client_modeset_free(struct drm_client_dev *client);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 759d462d028b..f57eea0481e0 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -853,6 +853,13 @@ struct drm_mode_config {
uint32_t preferred_depth, prefer_shadow;
/**
+ * @prefer_shadow_fbdev:
+ *
+ * Hint to framebuffer emulation to prefer shadow-fb rendering.
+ */
+ bool prefer_shadow_fbdev;
+
+ /**
* @quirk_addfb_prefer_xbgr_30bpp:
*
* Special hack for legacy ADDFB to keep nouveau userspace happy. Should
diff --git a/include/dt-bindings/bus/moxtet.h b/include/dt-bindings/bus/moxtet.h
new file mode 100644
index 000000000000..dc9345440ebe
--- /dev/null
+++ b/include/dt-bindings/bus/moxtet.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Constant for device tree bindings for Turris Mox module configuration bus
+ *
+ * Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
+ */
+
+#ifndef _DT_BINDINGS_BUS_MOXTET_H
+#define _DT_BINDINGS_BUS_MOXTET_H
+
+#define MOXTET_IRQ_PCI 0
+#define MOXTET_IRQ_USB3 4
+#define MOXTET_IRQ_PERIDOT(n) (8 + (n))
+#define MOXTET_IRQ_TOPAZ 12
+
+#endif /* _DT_BINDINGS_BUS_MOXTET_H */
diff --git a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h
index b6b127e45634..0837c1a7ae49 100644
--- a/include/dt-bindings/clock/g12a-clkc.h
+++ b/include/dt-bindings/clock/g12a-clkc.h
@@ -137,5 +137,11 @@
#define CLKID_VDEC_HEVC 207
#define CLKID_VDEC_HEVCF 210
#define CLKID_TS 212
+#define CLKID_CPUB_CLK 224
+#define CLKID_GP1_PLL 243
+#define CLKID_DSU_CLK 252
+#define CLKID_CPU1_CLK 253
+#define CLKID_CPU2_CLK 254
+#define CLKID_CPU3_CLK 255
#endif /* __G12A_CLKC_H */
diff --git a/include/dt-bindings/clock/imx8-clock.h b/include/dt-bindings/clock/imx8-clock.h
index 4236818e3be5..673a8c662340 100644
--- a/include/dt-bindings/clock/imx8-clock.h
+++ b/include/dt-bindings/clock/imx8-clock.h
@@ -283,7 +283,11 @@
#define IMX_ADMA_LPCG_PWM_IPG_CLK 38
#define IMX_ADMA_LPCG_LCD_PIX_CLK 39
#define IMX_ADMA_LPCG_LCD_APB_CLK 40
+#define IMX_ADMA_LPCG_DSP_ADB_CLK 41
+#define IMX_ADMA_LPCG_DSP_IPG_CLK 42
+#define IMX_ADMA_LPCG_DSP_CORE_CLK 43
+#define IMX_ADMA_LPCG_OCRAM_IPG_CLK 44
-#define IMX_ADMA_LPCG_CLK_END 41
+#define IMX_ADMA_LPCG_CLK_END 45
#endif /* __DT_BINDINGS_CLOCK_IMX_H */
diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h
new file mode 100644
index 000000000000..5255b1c2420e
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mn-clock.h
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2018-2019 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MN_H
+#define __DT_BINDINGS_CLOCK_IMX8MN_H
+
+#define IMX8MN_CLK_DUMMY 0
+#define IMX8MN_CLK_32K 1
+#define IMX8MN_CLK_24M 2
+#define IMX8MN_OSC_HDMI_CLK 3
+#define IMX8MN_CLK_EXT1 4
+#define IMX8MN_CLK_EXT2 5
+#define IMX8MN_CLK_EXT3 6
+#define IMX8MN_CLK_EXT4 7
+#define IMX8MN_AUDIO_PLL1_REF_SEL 8
+#define IMX8MN_AUDIO_PLL2_REF_SEL 9
+#define IMX8MN_VIDEO_PLL1_REF_SEL 10
+#define IMX8MN_DRAM_PLL_REF_SEL 11
+#define IMX8MN_GPU_PLL_REF_SEL 12
+#define IMX8MN_VPU_PLL_REF_SEL 13
+#define IMX8MN_ARM_PLL_REF_SEL 14
+#define IMX8MN_SYS_PLL1_REF_SEL 15
+#define IMX8MN_SYS_PLL2_REF_SEL 16
+#define IMX8MN_SYS_PLL3_REF_SEL 17
+#define IMX8MN_AUDIO_PLL1 18
+#define IMX8MN_AUDIO_PLL2 19
+#define IMX8MN_VIDEO_PLL1 20
+#define IMX8MN_DRAM_PLL 21
+#define IMX8MN_GPU_PLL 22
+#define IMX8MN_VPU_PLL 23
+#define IMX8MN_ARM_PLL 24
+#define IMX8MN_SYS_PLL1 25
+#define IMX8MN_SYS_PLL2 26
+#define IMX8MN_SYS_PLL3 27
+#define IMX8MN_AUDIO_PLL1_BYPASS 28
+#define IMX8MN_AUDIO_PLL2_BYPASS 29
+#define IMX8MN_VIDEO_PLL1_BYPASS 30
+#define IMX8MN_DRAM_PLL_BYPASS 31
+#define IMX8MN_GPU_PLL_BYPASS 32
+#define IMX8MN_VPU_PLL_BYPASS 33
+#define IMX8MN_ARM_PLL_BYPASS 34
+#define IMX8MN_SYS_PLL1_BYPASS 35
+#define IMX8MN_SYS_PLL2_BYPASS 36
+#define IMX8MN_SYS_PLL3_BYPASS 37
+#define IMX8MN_AUDIO_PLL1_OUT 38
+#define IMX8MN_AUDIO_PLL2_OUT 39
+#define IMX8MN_VIDEO_PLL1_OUT 40
+#define IMX8MN_DRAM_PLL_OUT 41
+#define IMX8MN_GPU_PLL_OUT 42
+#define IMX8MN_VPU_PLL_OUT 43
+#define IMX8MN_ARM_PLL_OUT 44
+#define IMX8MN_SYS_PLL1_OUT 45
+#define IMX8MN_SYS_PLL2_OUT 46
+#define IMX8MN_SYS_PLL3_OUT 47
+#define IMX8MN_SYS_PLL1_40M 48
+#define IMX8MN_SYS_PLL1_80M 49
+#define IMX8MN_SYS_PLL1_100M 50
+#define IMX8MN_SYS_PLL1_133M 51
+#define IMX8MN_SYS_PLL1_160M 52
+#define IMX8MN_SYS_PLL1_200M 53
+#define IMX8MN_SYS_PLL1_266M 54
+#define IMX8MN_SYS_PLL1_400M 55
+#define IMX8MN_SYS_PLL1_800M 56
+#define IMX8MN_SYS_PLL2_50M 57
+#define IMX8MN_SYS_PLL2_100M 58
+#define IMX8MN_SYS_PLL2_125M 59
+#define IMX8MN_SYS_PLL2_166M 60
+#define IMX8MN_SYS_PLL2_200M 61
+#define IMX8MN_SYS_PLL2_250M 62
+#define IMX8MN_SYS_PLL2_333M 63
+#define IMX8MN_SYS_PLL2_500M 64
+#define IMX8MN_SYS_PLL2_1000M 65
+
+/* CORE CLOCK ROOT */
+#define IMX8MN_CLK_A53_SRC 66
+#define IMX8MN_CLK_GPU_CORE_SRC 67
+#define IMX8MN_CLK_GPU_SHADER_SRC 68
+#define IMX8MN_CLK_A53_CG 69
+#define IMX8MN_CLK_GPU_CORE_CG 70
+#define IMX8MN_CLK_GPU_SHADER_CG 71
+#define IMX8MN_CLK_A53_DIV 72
+#define IMX8MN_CLK_GPU_CORE_DIV 73
+#define IMX8MN_CLK_GPU_SHADER_DIV 74
+
+/* BUS CLOCK ROOT */
+#define IMX8MN_CLK_MAIN_AXI 75
+#define IMX8MN_CLK_ENET_AXI 76
+#define IMX8MN_CLK_NAND_USDHC_BUS 77
+#define IMX8MN_CLK_DISP_AXI 78
+#define IMX8MN_CLK_DISP_APB 79
+#define IMX8MN_CLK_USB_BUS 80
+#define IMX8MN_CLK_GPU_AXI 81
+#define IMX8MN_CLK_GPU_AHB 82
+#define IMX8MN_CLK_NOC 83
+#define IMX8MN_CLK_AHB 84
+#define IMX8MN_CLK_AUDIO_AHB 85
+
+/* IPG CLOCK ROOT */
+#define IMX8MN_CLK_IPG_ROOT 86
+#define IMX8MN_CLK_IPG_AUDIO_ROOT 87
+
+/* IP */
+#define IMX8MN_CLK_DRAM_CORE 88
+#define IMX8MN_CLK_DRAM_ALT 89
+#define IMX8MN_CLK_DRAM_APB 90
+#define IMX8MN_CLK_DRAM_ALT_ROOT 91
+#define IMX8MN_CLK_DISP_PIXEL 92
+#define IMX8MN_CLK_SAI2 93
+#define IMX8MN_CLK_SAI3 94
+#define IMX8MN_CLK_SAI5 95
+#define IMX8MN_CLK_SAI6 96
+#define IMX8MN_CLK_SPDIF1 97
+#define IMX8MN_CLK_ENET_REF 98
+#define IMX8MN_CLK_ENET_TIMER 99
+#define IMX8MN_CLK_ENET_PHY_REF 100
+#define IMX8MN_CLK_NAND 101
+#define IMX8MN_CLK_QSPI 102
+#define IMX8MN_CLK_USDHC1 103
+#define IMX8MN_CLK_USDHC2 104
+#define IMX8MN_CLK_I2C1 105
+#define IMX8MN_CLK_I2C2 106
+#define IMX8MN_CLK_I2C3 107
+#define IMX8MN_CLK_I2C4 118
+#define IMX8MN_CLK_UART1 119
+#define IMX8MN_CLK_UART2 110
+#define IMX8MN_CLK_UART3 111
+#define IMX8MN_CLK_UART4 112
+#define IMX8MN_CLK_USB_CORE_REF 113
+#define IMX8MN_CLK_USB_PHY_REF 114
+#define IMX8MN_CLK_ECSPI1 115
+#define IMX8MN_CLK_ECSPI2 116
+#define IMX8MN_CLK_PWM1 117
+#define IMX8MN_CLK_PWM2 118
+#define IMX8MN_CLK_PWM3 119
+#define IMX8MN_CLK_PWM4 120
+#define IMX8MN_CLK_WDOG 121
+#define IMX8MN_CLK_WRCLK 122
+#define IMX8MN_CLK_CLKO1 123
+#define IMX8MN_CLK_CLKO2 124
+#define IMX8MN_CLK_DSI_CORE 125
+#define IMX8MN_CLK_DSI_PHY_REF 126
+#define IMX8MN_CLK_DSI_DBI 127
+#define IMX8MN_CLK_USDHC3 128
+#define IMX8MN_CLK_CAMERA_PIXEL 129
+#define IMX8MN_CLK_CSI1_PHY_REF 130
+#define IMX8MN_CLK_CSI2_PHY_REF 131
+#define IMX8MN_CLK_CSI2_ESC 132
+#define IMX8MN_CLK_ECSPI3 133
+#define IMX8MN_CLK_PDM 134
+#define IMX8MN_CLK_SAI7 135
+
+#define IMX8MN_CLK_ECSPI1_ROOT 136
+#define IMX8MN_CLK_ECSPI2_ROOT 137
+#define IMX8MN_CLK_ECSPI3_ROOT 138
+#define IMX8MN_CLK_ENET1_ROOT 139
+#define IMX8MN_CLK_GPIO1_ROOT 140
+#define IMX8MN_CLK_GPIO2_ROOT 141
+#define IMX8MN_CLK_GPIO3_ROOT 142
+#define IMX8MN_CLK_GPIO4_ROOT 143
+#define IMX8MN_CLK_GPIO5_ROOT 144
+#define IMX8MN_CLK_I2C1_ROOT 145
+#define IMX8MN_CLK_I2C2_ROOT 146
+#define IMX8MN_CLK_I2C3_ROOT 147
+#define IMX8MN_CLK_I2C4_ROOT 148
+#define IMX8MN_CLK_MU_ROOT 149
+#define IMX8MN_CLK_OCOTP_ROOT 150
+#define IMX8MN_CLK_PWM1_ROOT 151
+#define IMX8MN_CLK_PWM2_ROOT 152
+#define IMX8MN_CLK_PWM3_ROOT 153
+#define IMX8MN_CLK_PWM4_ROOT 154
+#define IMX8MN_CLK_QSPI_ROOT 155
+#define IMX8MN_CLK_NAND_ROOT 156
+#define IMX8MN_CLK_SAI2_ROOT 157
+#define IMX8MN_CLK_SAI2_IPG 158
+#define IMX8MN_CLK_SAI3_ROOT 159
+#define IMX8MN_CLK_SAI3_IPG 160
+#define IMX8MN_CLK_SAI5_ROOT 161
+#define IMX8MN_CLK_SAI5_IPG 162
+#define IMX8MN_CLK_SAI6_ROOT 163
+#define IMX8MN_CLK_SAI6_IPG 164
+#define IMX8MN_CLK_SAI7_ROOT 165
+#define IMX8MN_CLK_SAI7_IPG 166
+#define IMX8MN_CLK_SDMA1_ROOT 167
+#define IMX8MN_CLK_SDMA2_ROOT 168
+#define IMX8MN_CLK_UART1_ROOT 169
+#define IMX8MN_CLK_UART2_ROOT 170
+#define IMX8MN_CLK_UART3_ROOT 171
+#define IMX8MN_CLK_UART4_ROOT 172
+#define IMX8MN_CLK_USB1_CTRL_ROOT 173
+#define IMX8MN_CLK_USDHC1_ROOT 174
+#define IMX8MN_CLK_USDHC2_ROOT 175
+#define IMX8MN_CLK_WDOG1_ROOT 176
+#define IMX8MN_CLK_WDOG2_ROOT 177
+#define IMX8MN_CLK_WDOG3_ROOT 178
+#define IMX8MN_CLK_GPU_BUS_ROOT 179
+#define IMX8MN_CLK_ASRC_ROOT 180
+#define IMX8MN_CLK_GPU3D_ROOT 181
+#define IMX8MN_CLK_PDM_ROOT 182
+#define IMX8MN_CLK_PDM_IPG 183
+#define IMX8MN_CLK_DISP_AXI_ROOT 184
+#define IMX8MN_CLK_DISP_APB_ROOT 185
+#define IMX8MN_CLK_DISP_PIXEL_ROOT 186
+#define IMX8MN_CLK_CAMERA_PIXEL_ROOT 187
+#define IMX8MN_CLK_USDHC3_ROOT 188
+#define IMX8MN_CLK_SDMA3_ROOT 189
+#define IMX8MN_CLK_TMU_ROOT 190
+#define IMX8MN_CLK_ARM 191
+#define IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK 192
+#define IMX8MN_CLK_GPU_CORE_ROOT 193
+
+#define IMX8MN_CLK_END 194
+
+#endif
diff --git a/include/dt-bindings/memory/mt8183-larb-port.h b/include/dt-bindings/memory/mt8183-larb-port.h
new file mode 100644
index 000000000000..2c579f305162
--- /dev/null
+++ b/include/dt-bindings/memory/mt8183-larb-port.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Yong Wu <yong.wu@mediatek.com>
+ */
+#ifndef __DTS_IOMMU_PORT_MT8183_H
+#define __DTS_IOMMU_PORT_MT8183_H
+
+#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+
+#define M4U_LARB0_ID 0
+#define M4U_LARB1_ID 1
+#define M4U_LARB2_ID 2
+#define M4U_LARB3_ID 3
+#define M4U_LARB4_ID 4
+#define M4U_LARB5_ID 5
+#define M4U_LARB6_ID 6
+#define M4U_LARB7_ID 7
+
+/* larb0 */
+#define M4U_PORT_DISP_OVL0 MTK_M4U_ID(M4U_LARB0_ID, 0)
+#define M4U_PORT_DISP_2L_OVL0_LARB0 MTK_M4U_ID(M4U_LARB0_ID, 1)
+#define M4U_PORT_DISP_2L_OVL1_LARB0 MTK_M4U_ID(M4U_LARB0_ID, 2)
+#define M4U_PORT_DISP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 3)
+#define M4U_PORT_DISP_RDMA1 MTK_M4U_ID(M4U_LARB0_ID, 4)
+#define M4U_PORT_DISP_WDMA0 MTK_M4U_ID(M4U_LARB0_ID, 5)
+#define M4U_PORT_MDP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 6)
+#define M4U_PORT_MDP_WROT0 MTK_M4U_ID(M4U_LARB0_ID, 7)
+#define M4U_PORT_MDP_WDMA0 MTK_M4U_ID(M4U_LARB0_ID, 8)
+#define M4U_PORT_DISP_FAKE0 MTK_M4U_ID(M4U_LARB0_ID, 9)
+
+/* larb1 */
+#define M4U_PORT_HW_VDEC_MC_EXT MTK_M4U_ID(M4U_LARB1_ID, 0)
+#define M4U_PORT_HW_VDEC_PP_EXT MTK_M4U_ID(M4U_LARB1_ID, 1)
+#define M4U_PORT_HW_VDEC_VLD_EXT MTK_M4U_ID(M4U_LARB1_ID, 2)
+#define M4U_PORT_HW_VDEC_AVC_MV_EXT MTK_M4U_ID(M4U_LARB1_ID, 3)
+#define M4U_PORT_HW_VDEC_PRED_RD_EXT MTK_M4U_ID(M4U_LARB1_ID, 4)
+#define M4U_PORT_HW_VDEC_PRED_WR_EXT MTK_M4U_ID(M4U_LARB1_ID, 5)
+#define M4U_PORT_HW_VDEC_PPWRAP_EXT MTK_M4U_ID(M4U_LARB1_ID, 6)
+
+/* larb2 VPU0 */
+#define M4U_PORT_IMG_IPUO MTK_M4U_ID(M4U_LARB2_ID, 0)
+#define M4U_PORT_IMG_IPU3O MTK_M4U_ID(M4U_LARB2_ID, 1)
+#define M4U_PORT_IMG_IPUI MTK_M4U_ID(M4U_LARB2_ID, 2)
+
+/* larb3 VPU1 */
+#define M4U_PORT_CAM_IPUO MTK_M4U_ID(M4U_LARB3_ID, 0)
+#define M4U_PORT_CAM_IPU2O MTK_M4U_ID(M4U_LARB3_ID, 1)
+#define M4U_PORT_CAM_IPU3O MTK_M4U_ID(M4U_LARB3_ID, 2)
+#define M4U_PORT_CAM_IPUI MTK_M4U_ID(M4U_LARB3_ID, 3)
+#define M4U_PORT_CAM_IPU2I MTK_M4U_ID(M4U_LARB3_ID, 4)
+
+/* larb4 */
+#define M4U_PORT_VENC_RCPU MTK_M4U_ID(M4U_LARB4_ID, 0)
+#define M4U_PORT_VENC_REC MTK_M4U_ID(M4U_LARB4_ID, 1)
+#define M4U_PORT_VENC_BSDMA MTK_M4U_ID(M4U_LARB4_ID, 2)
+#define M4U_PORT_VENC_SV_COMV MTK_M4U_ID(M4U_LARB4_ID, 3)
+#define M4U_PORT_VENC_RD_COMV MTK_M4U_ID(M4U_LARB4_ID, 4)
+#define M4U_PORT_JPGENC_RDMA MTK_M4U_ID(M4U_LARB4_ID, 5)
+#define M4U_PORT_JPGENC_BSDMA MTK_M4U_ID(M4U_LARB4_ID, 6)
+#define M4U_PORT_VENC_CUR_LUMA MTK_M4U_ID(M4U_LARB4_ID, 7)
+#define M4U_PORT_VENC_CUR_CHROMA MTK_M4U_ID(M4U_LARB4_ID, 8)
+#define M4U_PORT_VENC_REF_LUMA MTK_M4U_ID(M4U_LARB4_ID, 9)
+#define M4U_PORT_VENC_REF_CHROMA MTK_M4U_ID(M4U_LARB4_ID, 10)
+
+/* larb5 */
+#define M4U_PORT_CAM_IMGI MTK_M4U_ID(M4U_LARB5_ID, 0)
+#define M4U_PORT_CAM_IMG2O MTK_M4U_ID(M4U_LARB5_ID, 1)
+#define M4U_PORT_CAM_IMG3O MTK_M4U_ID(M4U_LARB5_ID, 2)
+#define M4U_PORT_CAM_VIPI MTK_M4U_ID(M4U_LARB5_ID, 3)
+#define M4U_PORT_CAM_LCEI MTK_M4U_ID(M4U_LARB5_ID, 4)
+#define M4U_PORT_CAM_SMXI MTK_M4U_ID(M4U_LARB5_ID, 5)
+#define M4U_PORT_CAM_SMXO MTK_M4U_ID(M4U_LARB5_ID, 6)
+#define M4U_PORT_CAM_WPE0_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 7)
+#define M4U_PORT_CAM_WPE0_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 8)
+#define M4U_PORT_CAM_WPE0_WDMA MTK_M4U_ID(M4U_LARB5_ID, 9)
+#define M4U_PORT_CAM_FDVT_RP MTK_M4U_ID(M4U_LARB5_ID, 10)
+#define M4U_PORT_CAM_FDVT_WR MTK_M4U_ID(M4U_LARB5_ID, 11)
+#define M4U_PORT_CAM_FDVT_RB MTK_M4U_ID(M4U_LARB5_ID, 12)
+#define M4U_PORT_CAM_WPE1_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 13)
+#define M4U_PORT_CAM_WPE1_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 14)
+#define M4U_PORT_CAM_WPE1_WDMA MTK_M4U_ID(M4U_LARB5_ID, 15)
+#define M4U_PORT_CAM_DPE_RDMA MTK_M4U_ID(M4U_LARB5_ID, 16)
+#define M4U_PORT_CAM_DPE_WDMA MTK_M4U_ID(M4U_LARB5_ID, 17)
+#define M4U_PORT_CAM_MFB_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 18)
+#define M4U_PORT_CAM_MFB_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 19)
+#define M4U_PORT_CAM_MFB_WDMA MTK_M4U_ID(M4U_LARB5_ID, 20)
+#define M4U_PORT_CAM_RSC_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 21)
+#define M4U_PORT_CAM_RSC_WDMA MTK_M4U_ID(M4U_LARB5_ID, 22)
+#define M4U_PORT_CAM_OWE_RDMA MTK_M4U_ID(M4U_LARB5_ID, 23)
+#define M4U_PORT_CAM_OWE_WDMA MTK_M4U_ID(M4U_LARB5_ID, 24)
+
+/* larb6 */
+#define M4U_PORT_CAM_IMGO MTK_M4U_ID(M4U_LARB6_ID, 0)
+#define M4U_PORT_CAM_RRZO MTK_M4U_ID(M4U_LARB6_ID, 1)
+#define M4U_PORT_CAM_AAO MTK_M4U_ID(M4U_LARB6_ID, 2)
+#define M4U_PORT_CAM_AFO MTK_M4U_ID(M4U_LARB6_ID, 3)
+#define M4U_PORT_CAM_LSCI0 MTK_M4U_ID(M4U_LARB6_ID, 4)
+#define M4U_PORT_CAM_LSCI1 MTK_M4U_ID(M4U_LARB6_ID, 5)
+#define M4U_PORT_CAM_PDO MTK_M4U_ID(M4U_LARB6_ID, 6)
+#define M4U_PORT_CAM_BPCI MTK_M4U_ID(M4U_LARB6_ID, 7)
+#define M4U_PORT_CAM_LCSO MTK_M4U_ID(M4U_LARB6_ID, 8)
+#define M4U_PORT_CAM_CAM_RSSO_A MTK_M4U_ID(M4U_LARB6_ID, 9)
+#define M4U_PORT_CAM_UFEO MTK_M4U_ID(M4U_LARB6_ID, 10)
+#define M4U_PORT_CAM_SOCO MTK_M4U_ID(M4U_LARB6_ID, 11)
+#define M4U_PORT_CAM_SOC1 MTK_M4U_ID(M4U_LARB6_ID, 12)
+#define M4U_PORT_CAM_SOC2 MTK_M4U_ID(M4U_LARB6_ID, 13)
+#define M4U_PORT_CAM_CCUI MTK_M4U_ID(M4U_LARB6_ID, 14)
+#define M4U_PORT_CAM_CCUO MTK_M4U_ID(M4U_LARB6_ID, 15)
+#define M4U_PORT_CAM_RAWI_A MTK_M4U_ID(M4U_LARB6_ID, 16)
+#define M4U_PORT_CAM_CCUG MTK_M4U_ID(M4U_LARB6_ID, 17)
+#define M4U_PORT_CAM_PSO MTK_M4U_ID(M4U_LARB6_ID, 18)
+#define M4U_PORT_CAM_AFO_1 MTK_M4U_ID(M4U_LARB6_ID, 19)
+#define M4U_PORT_CAM_LSCI_2 MTK_M4U_ID(M4U_LARB6_ID, 20)
+#define M4U_PORT_CAM_PDI MTK_M4U_ID(M4U_LARB6_ID, 21)
+#define M4U_PORT_CAM_FLKO MTK_M4U_ID(M4U_LARB6_ID, 22)
+#define M4U_PORT_CAM_LMVO MTK_M4U_ID(M4U_LARB6_ID, 23)
+#define M4U_PORT_CAM_UFGO MTK_M4U_ID(M4U_LARB6_ID, 24)
+#define M4U_PORT_CAM_SPARE MTK_M4U_ID(M4U_LARB6_ID, 25)
+#define M4U_PORT_CAM_SPARE_2 MTK_M4U_ID(M4U_LARB6_ID, 26)
+#define M4U_PORT_CAM_SPARE_3 MTK_M4U_ID(M4U_LARB6_ID, 27)
+#define M4U_PORT_CAM_SPARE_4 MTK_M4U_ID(M4U_LARB6_ID, 28)
+#define M4U_PORT_CAM_SPARE_5 MTK_M4U_ID(M4U_LARB6_ID, 29)
+#define M4U_PORT_CAM_SPARE_6 MTK_M4U_ID(M4U_LARB6_ID, 30)
+
+/* CCU */
+#define M4U_PORT_CCU0 MTK_M4U_ID(M4U_LARB7_ID, 0)
+#define M4U_PORT_CCU1 MTK_M4U_ID(M4U_LARB7_ID, 1)
+
+#endif
diff --git a/include/dt-bindings/power/meson-g12a-power.h b/include/dt-bindings/power/meson-g12a-power.h
new file mode 100644
index 000000000000..bb5e67a842de
--- /dev/null
+++ b/include/dt-bindings/power/meson-g12a-power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef _DT_BINDINGS_MESON_G12A_POWER_H
+#define _DT_BINDINGS_MESON_G12A_POWER_H
+
+#define PWRC_G12A_VPU_ID 0
+#define PWRC_G12A_ETH_ID 1
+
+#endif
diff --git a/include/dt-bindings/power/meson-sm1-power.h b/include/dt-bindings/power/meson-sm1-power.h
new file mode 100644
index 000000000000..a020ab00c134
--- /dev/null
+++ b/include/dt-bindings/power/meson-sm1-power.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef _DT_BINDINGS_MESON_SM1_POWER_H
+#define _DT_BINDINGS_MESON_SM1_POWER_H
+
+#define PWRC_SM1_VPU_ID 0
+#define PWRC_SM1_NNA_ID 1
+#define PWRC_SM1_USB_ID 2
+#define PWRC_SM1_PCIE_ID 3
+#define PWRC_SM1_GE2D_ID 4
+#define PWRC_SM1_AUDIO_ID 5
+#define PWRC_SM1_ETH_ID 6
+
+#endif
diff --git a/include/dt-bindings/regulator/active-semi,8865-regulator.h b/include/dt-bindings/regulator/active-semi,8865-regulator.h
new file mode 100644
index 000000000000..15473dbeaf38
--- /dev/null
+++ b/include/dt-bindings/regulator/active-semi,8865-regulator.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device Tree binding constants for the ACT8865 PMIC regulators
+ */
+
+#ifndef _DT_BINDINGS_REGULATOR_ACT8865_H
+#define _DT_BINDINGS_REGULATOR_ACT8865_H
+
+/*
+ * These constants should be used to specify regulator modes in device tree for
+ * ACT8865 regulators as follows:
+ * ACT8865_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it
+ * specifies the usage of fixed-frequency
+ * PWM.
+ *
+ * ACT8865_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it
+ * specifies the usage of normal mode.
+ *
+ * ACT8865_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify
+ * the usage of proprietary power-saving
+ * mode.
+ */
+
+#define ACT8865_REGULATOR_MODE_FIXED 1
+#define ACT8865_REGULATOR_MODE_NORMAL 2
+#define ACT8865_REGULATOR_MODE_LOWPOWER 3
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h b/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
new file mode 100644
index 000000000000..14b78dabed0e
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-g12a-audio-reset.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_G12A_AUDIO_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_G12A_AUDIO_RESET_H
+
+#define AUD_RESET_PDM 0
+#define AUD_RESET_TDMIN_A 1
+#define AUD_RESET_TDMIN_B 2
+#define AUD_RESET_TDMIN_C 3
+#define AUD_RESET_TDMIN_LB 4
+#define AUD_RESET_LOOPBACK 5
+#define AUD_RESET_TODDR_A 6
+#define AUD_RESET_TODDR_B 7
+#define AUD_RESET_TODDR_C 8
+#define AUD_RESET_FRDDR_A 9
+#define AUD_RESET_FRDDR_B 10
+#define AUD_RESET_FRDDR_C 11
+#define AUD_RESET_TDMOUT_A 12
+#define AUD_RESET_TDMOUT_B 13
+#define AUD_RESET_TDMOUT_C 14
+#define AUD_RESET_SPDIFOUT 15
+#define AUD_RESET_SPDIFOUT_B 16
+#define AUD_RESET_SPDIFIN 17
+#define AUD_RESET_EQDRC 18
+#define AUD_RESET_RESAMPLE 19
+#define AUD_RESET_DDRARB 20
+#define AUD_RESET_POWDET 21
+#define AUD_RESET_TORAM 22
+#define AUD_RESET_TOACODEC 23
+#define AUD_RESET_TOHDMITX 24
+#define AUD_RESET_CLKTREE 25
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
index 524d6077ac1b..ea5058618863 100644
--- a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -1,56 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
* Copyright (c) 2016 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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. 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, see <http://www.gnu.org/licenses/>.
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * BSD LICENSE
- *
- * Copyright (c) 2016 BayLibre, SAS.
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h
index 614aff2c7aff..c614438bcbdb 100644
--- a/include/dt-bindings/reset/amlogic,meson8b-reset.h
+++ b/include/dt-bindings/reset/amlogic,meson8b-reset.h
@@ -1,56 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
* Copyright (c) 2016 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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. 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, see <http://www.gnu.org/licenses/>.
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * BSD LICENSE
- *
- * Copyright (c) 2016 BayLibre, SAS.
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
#define _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h
index 57c592498aa0..9a301082d361 100644
--- a/include/dt-bindings/reset/imx8mq-reset.h
+++ b/include/dt-bindings/reset/imx8mq-reset.h
@@ -31,33 +31,33 @@
#define IMX8MQ_RESET_OTG2_PHY_RESET 20
#define IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N 21
#define IMX8MQ_RESET_MIPI_DSI_RESET_N 22
-#define IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N 23
-#define IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N 24
-#define IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N 25
+#define IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N 23
+#define IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N 24
+#define IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N 25
#define IMX8MQ_RESET_PCIEPHY 26
#define IMX8MQ_RESET_PCIEPHY_PERST 27
#define IMX8MQ_RESET_PCIE_CTRL_APPS_EN 28
#define IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF 29
-#define IMX8MQ_RESET_HDMI_PHY_APB_RESET 30
+#define IMX8MQ_RESET_HDMI_PHY_APB_RESET 30 /* i.MX8MM does NOT support */
#define IMX8MQ_RESET_DISP_RESET 31
#define IMX8MQ_RESET_GPU_RESET 32
#define IMX8MQ_RESET_VPU_RESET 33
-#define IMX8MQ_RESET_PCIEPHY2 34
-#define IMX8MQ_RESET_PCIEPHY2_PERST 35
-#define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN 36
-#define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF 37
-#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET 38
-#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET 39
-#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET 40
-#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET 41
-#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET 42
-#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET 43
+#define IMX8MQ_RESET_PCIEPHY2 34 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_PCIEPHY2_PERST 35 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN 36 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF 37 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET 38 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET 39 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET 40 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET 41 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET 42 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET 43 /* i.MX8MM does NOT support */
#define IMX8MQ_RESET_DDRC1_PRST 44
#define IMX8MQ_RESET_DDRC1_CORE_RESET 45
#define IMX8MQ_RESET_DDRC1_PHY_RESET 46
-#define IMX8MQ_RESET_DDRC2_PRST 47
-#define IMX8MQ_RESET_DDRC2_CORE_RESET 48
-#define IMX8MQ_RESET_DDRC2_PHY_RESET 49
+#define IMX8MQ_RESET_DDRC2_PRST 47 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_DDRC2_CORE_RESET 48 /* i.MX8MM does NOT support */
+#define IMX8MQ_RESET_DDRC2_PHY_RESET 49 /* i.MX8MM does NOT support */
#define IMX8MQ_RESET_NUM 50
diff --git a/include/dt-bindings/reset/mt7629-resets.h b/include/dt-bindings/reset/mt7629-resets.h
new file mode 100644
index 000000000000..6bb85734f68d
--- /dev/null
+++ b/include/dt-bindings/reset/mt7629-resets.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7629
+#define _DT_BINDINGS_RESET_CONTROLLER_MT7629
+
+/* INFRACFG resets */
+#define MT7629_INFRA_EMI_MPU_RST 0
+#define MT7629_INFRA_UART5_RST 2
+#define MT7629_INFRA_CIRQ_EINT_RST 3
+#define MT7629_INFRA_APXGPT_RST 4
+#define MT7629_INFRA_SCPSYS_RST 5
+#define MT7629_INFRA_KP_RST 6
+#define MT7629_INFRA_SPI1_RST 7
+#define MT7629_INFRA_SPI4_RST 8
+#define MT7629_INFRA_SYSTIMER_RST 9
+#define MT7629_INFRA_IRRX_RST 10
+#define MT7629_INFRA_AO_BUS_RST 16
+#define MT7629_INFRA_EMI_RST 32
+#define MT7629_INFRA_APMIXED_RST 35
+#define MT7629_INFRA_MIPI_RST 36
+#define MT7629_INFRA_TRNG_RST 37
+#define MT7629_INFRA_SYSCIRQ_RST 38
+#define MT7629_INFRA_MIPI_CSI_RST 39
+#define MT7629_INFRA_GCE_FAXI_RST 40
+#define MT7629_INFRA_I2C_SRAM_RST 41
+#define MT7629_INFRA_IOMMU_RST 47
+
+/* PERICFG resets */
+#define MT7629_PERI_UART0_SW_RST 0
+#define MT7629_PERI_UART1_SW_RST 1
+#define MT7629_PERI_UART2_SW_RST 2
+#define MT7629_PERI_BTIF_SW_RST 6
+#define MT7629_PERI_PWN_SW_RST 8
+#define MT7629_PERI_DMA_SW_RST 11
+#define MT7629_PERI_NFI_SW_RST 14
+#define MT7629_PERI_I2C0_SW_RST 22
+#define MT7629_PERI_SPI0_SW_RST 33
+#define MT7629_PERI_SPI1_SW_RST 34
+#define MT7629_PERI_FLASHIF_SW_RST 36
+
+/* PCIe Subsystem resets */
+#define MT7629_PCIE1_CORE_RST 19
+#define MT7629_PCIE1_MMIO_RST 20
+#define MT7629_PCIE1_HRST 21
+#define MT7629_PCIE1_USER_RST 22
+#define MT7629_PCIE1_PIPE_RST 23
+#define MT7629_PCIE0_CORE_RST 27
+#define MT7629_PCIE0_MMIO_RST 28
+#define MT7629_PCIE0_HRST 29
+#define MT7629_PCIE0_USER_RST 30
+#define MT7629_PCIE0_PIPE_RST 31
+
+/* SSUSB Subsystem resets */
+#define MT7629_SSUSB_PHY_PWR_RST 3
+#define MT7629_SSUSB_MAC_PWR_RST 4
+
+/* ETH Subsystem resets */
+#define MT7629_ETHSYS_SYS_RST 0
+#define MT7629_ETHSYS_MCM_RST 2
+#define MT7629_ETHSYS_HSDMA_RST 5
+#define MT7629_ETHSYS_FE_RST 6
+#define MT7629_ETHSYS_ESW_RST 16
+#define MT7629_ETHSYS_GMAC_RST 23
+#define MT7629_ETHSYS_EPHY_RST 24
+#define MT7629_ETHSYS_CRYPTO_RST 29
+#define MT7629_ETHSYS_PPE_RST 31
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7629 */
diff --git a/include/dt-bindings/soc/ti,sci_pm_domain.h b/include/dt-bindings/soc/ti,sci_pm_domain.h
new file mode 100644
index 000000000000..8f2a7360b65e
--- /dev/null
+++ b/include/dt-bindings/soc/ti,sci_pm_domain.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DT_BINDINGS_TI_SCI_PM_DOMAIN_H
+#define __DT_BINDINGS_TI_SCI_PM_DOMAIN_H
+
+#define TI_SCI_PD_EXCLUSIVE 1
+#define TI_SCI_PD_SHARED 0
+
+#endif /* __DT_BINDINGS_TI_SCI_PM_DOMAIN_H */
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 16c769a7f979..6db030439e29 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -34,6 +34,7 @@ struct kvm_pmu {
u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val);
@@ -71,6 +72,7 @@ static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
{
return 0;
}
+static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
static inline void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 46bbc949c20a..7a30524a80ee 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -350,6 +350,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
void kvm_vgic_load(struct kvm_vcpu *vcpu);
void kvm_vgic_put(struct kvm_vcpu *vcpu);
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
#define vgic_initialized(k) ((k)->arch.vgic.initialized)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 9426b9aaed86..0fecacca51e8 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -994,62 +994,11 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c
#endif
#endif
-struct acpi_gpio_params {
- unsigned int crs_entry_index;
- unsigned int line_index;
- bool active_low;
-};
-
-struct acpi_gpio_mapping {
- const char *name;
- const struct acpi_gpio_params *data;
- unsigned int size;
-
-/* Ignore IoRestriction field */
-#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0)
-/*
- * When ACPI GPIO mapping table is in use the index parameter inside it
- * refers to the GPIO resource in _CRS method. That index has no
- * distinction of actual type of the resource. When consumer wants to
- * get GpioIo type explicitly, this quirk may be used.
- */
-#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1)
-
- unsigned int quirks;
-};
-
#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
-int acpi_dev_add_driver_gpios(struct acpi_device *adev,
- const struct acpi_gpio_mapping *gpios);
-
-static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
-{
- if (adev)
- adev->driver_gpios = NULL;
-}
-
-int devm_acpi_dev_add_driver_gpios(struct device *dev,
- const struct acpi_gpio_mapping *gpios);
-void devm_acpi_dev_remove_driver_gpios(struct device *dev);
-
bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio);
int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);
#else
-static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
- const struct acpi_gpio_mapping *gpios)
-{
- return -ENXIO;
-}
-static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
-
-static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
- const struct acpi_gpio_mapping *gpios)
-{
- return -ENXIO;
-}
-static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {}
-
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio)
{
@@ -1302,11 +1251,16 @@ static inline int lpit_read_residency_count_address(u64 *address)
#endif
#ifdef CONFIG_ACPI_PPTT
+int acpi_pptt_cpu_is_thread(unsigned int cpu);
int find_acpi_cpu_topology(unsigned int cpu, int level);
int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
int find_acpi_cpu_cache_topology(unsigned int cpu, int level);
#else
+static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
+{
+ return -EINVAL;
+}
static inline int find_acpi_cpu_topology(unsigned int cpu, int level)
{
return -EINVAL;
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h
index 4a4d00646040..21e950e4ab62 100644
--- a/include/linux/amd-iommu.h
+++ b/include/linux/amd-iommu.h
@@ -184,6 +184,9 @@ extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32));
extern int
amd_iommu_update_ga(int cpu, bool is_run, void *data);
+extern int amd_iommu_activate_guest_mode(void *data);
+extern int amd_iommu_deactivate_guest_mode(void *data);
+
#else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */
static inline int
@@ -198,6 +201,15 @@ amd_iommu_update_ga(int cpu, bool is_run, void *data)
return 0;
}
+static inline int amd_iommu_activate_guest_mode(void *data)
+{
+ return 0;
+}
+
+static inline int amd_iommu_deactivate_guest_mode(void *data)
+{
+ return 0;
+}
#endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */
#endif /* _ASM_X86_AMD_IOMMU_H */
diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h
index 1cfe05ea1d89..42f2b5126094 100644
--- a/include/linux/arch_topology.h
+++ b/include/linux/arch_topology.h
@@ -33,4 +33,30 @@ unsigned long topology_get_freq_scale(int cpu)
return per_cpu(freq_scale, cpu);
}
+struct cpu_topology {
+ int thread_id;
+ int core_id;
+ int package_id;
+ int llc_id;
+ cpumask_t thread_sibling;
+ cpumask_t core_sibling;
+ cpumask_t llc_sibling;
+};
+
+#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY
+extern struct cpu_topology cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id)
+#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
+#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
+#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling)
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
+void update_siblings_masks(unsigned int cpu);
+void remove_cpu_topology(unsigned int cpuid);
+void reset_cpu_topology(void);
+#endif
+
#endif /* _LINUX_ARCH_TOPOLOGY_H_ */
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index f58e97446abc..90528f12bdfa 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -120,6 +120,10 @@ extern int __bitmap_empty(const unsigned long *bitmap, unsigned int nbits);
extern int __bitmap_full(const unsigned long *bitmap, unsigned int nbits);
extern int __bitmap_equal(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
+extern bool __pure __bitmap_or_equal(const unsigned long *src1,
+ const unsigned long *src2,
+ const unsigned long *src3,
+ unsigned int nbits);
extern void __bitmap_complement(unsigned long *dst, const unsigned long *src,
unsigned int nbits);
extern void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
@@ -321,6 +325,25 @@ static inline int bitmap_equal(const unsigned long *src1,
return __bitmap_equal(src1, src2, nbits);
}
+/**
+ * bitmap_or_equal - Check whether the or of two bitnaps is equal to a third
+ * @src1: Pointer to bitmap 1
+ * @src2: Pointer to bitmap 2 will be or'ed with bitmap 1
+ * @src3: Pointer to bitmap 3. Compare to the result of *@src1 | *@src2
+ *
+ * Returns: True if (*@src1 | *@src2) == *@src3, false otherwise
+ */
+static inline bool bitmap_or_equal(const unsigned long *src1,
+ const unsigned long *src2,
+ const unsigned long *src3,
+ unsigned int nbits)
+{
+ if (!small_const_nbits(nbits))
+ return __bitmap_or_equal(src1, src2, src3, nbits);
+
+ return !(((*src1 | *src2) ^ *src3) & BITMAP_LAST_WORD_MASK(nbits));
+}
+
static inline int bitmap_intersects(const unsigned long *src1,
const unsigned long *src2, unsigned int nbits)
{
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 689a58231288..12811091fd50 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -181,6 +181,7 @@ struct blkcg_policy {
extern struct blkcg blkcg_root;
extern struct cgroup_subsys_state * const blkcg_root_css;
+extern bool blkcg_debug_stats;
struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,
struct request_queue *q, bool update_hint);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index feff3fe4467e..1b1fa1557e68 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -311,6 +311,7 @@ enum req_flag_bits {
__REQ_RAHEAD, /* read ahead, can fail anytime */
__REQ_BACKGROUND, /* background IO */
__REQ_NOWAIT, /* Don't wait if request will block */
+ __REQ_NOWAIT_INLINE, /* Return would-block error inline */
/*
* When a shared kthread needs to issue a bio for a cgroup, doing
* so synchronously can lead to priority inversions as the kthread
@@ -345,6 +346,7 @@ enum req_flag_bits {
#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
#define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
#define REQ_NOWAIT (1ULL << __REQ_NOWAIT)
+#define REQ_NOWAIT_INLINE (1ULL << __REQ_NOWAIT_INLINE)
#define REQ_CGROUP_PUNT (1ULL << __REQ_CGROUP_PUNT)
#define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)
@@ -418,12 +420,13 @@ static inline int op_stat_group(unsigned int op)
typedef unsigned int blk_qc_t;
#define BLK_QC_T_NONE -1U
+#define BLK_QC_T_EAGAIN -2U
#define BLK_QC_T_SHIFT 16
#define BLK_QC_T_INTERNAL (1U << 31)
static inline bool blk_qc_t_valid(blk_qc_t cookie)
{
- return cookie != BLK_QC_T_NONE;
+ return cookie != BLK_QC_T_NONE && cookie != BLK_QC_T_EAGAIN;
}
static inline unsigned int blk_qc_t_to_queue_num(blk_qc_t cookie)
diff --git a/include/linux/bug.h b/include/linux/bug.h
index fe5916550da8..f639bd0122f3 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -47,6 +47,11 @@ void generic_bug_clear_once(void);
#else /* !CONFIG_GENERIC_BUG */
+static inline void *find_bug(unsigned long bugaddr)
+{
+ return NULL;
+}
+
static inline enum bug_trap_type report_bug(unsigned long bug_addr,
struct pt_regs *regs)
{
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index 55cb455cfcb0..a5dfbaf2470d 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -170,6 +170,8 @@ struct ccp_aes_engine {
enum ccp_aes_mode mode;
enum ccp_aes_action action;
+ u32 authsize;
+
struct scatterlist *key;
u32 key_len; /* In bytes */
diff --git a/include/linux/ceph/buffer.h b/include/linux/ceph/buffer.h
index 5e58bb29b1a3..11cdc7c60480 100644
--- a/include/linux/ceph/buffer.h
+++ b/include/linux/ceph/buffer.h
@@ -30,7 +30,8 @@ static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b)
static inline void ceph_buffer_put(struct ceph_buffer *b)
{
- kref_put(&b->kref, ceph_buffer_release);
+ if (b)
+ kref_put(&b->kref, ceph_buffer_release);
}
extern int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index f6b048902d6c..3ba3e6da13a6 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -150,6 +150,7 @@ struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
struct cgroup_subsys_state **dst_cssp);
+void cgroup_enable_task_cg_lists(void);
void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags,
struct css_task_iter *it);
struct task_struct *css_task_iter_next(struct css_task_iter *it);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2ae7604783dd..dce5521a9bf6 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -817,6 +817,7 @@ unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
unsigned int index);
+int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent);
unsigned int __clk_get_enable_count(struct clk *clk);
unsigned long clk_hw_get_rate(const struct clk_hw *hw);
unsigned long __clk_get_flags(struct clk *clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 3c096c7a51dc..853a8f181394 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -359,6 +359,7 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
/**
* devm_clk_bulk_get_optional - managed get multiple optional consumer clocks
* @dev: device for clock "consumer"
+ * @num_clks: the number of clk_bulk_data
* @clks: pointer to the clk_bulk_data table of consumer
*
* Behaves the same as devm_clk_bulk_get() except where there is no clock
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index f0fd5636fddb..5e88e7e33abe 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -24,7 +24,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
long ______r; \
static struct ftrace_likely_data \
__aligned(4) \
- __section("_ftrace_annotated_branch") \
+ __section(_ftrace_annotated_branch) \
______f = { \
.data.func = __func__, \
.data.file = __FILE__, \
@@ -60,7 +60,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#define __trace_if_value(cond) ({ \
static struct ftrace_branch_data \
__aligned(4) \
- __section("_ftrace_branch") \
+ __section(_ftrace_branch) \
__if_trace = { \
.func = __func__, \
.file = __FILE__, \
@@ -118,7 +118,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
".popsection\n\t"
/* Annotate a C jump table to allow objtool to follow the code flow */
-#define __annotate_jump_table __section(".rodata..c_jump_table")
+#define __annotate_jump_table __section(.rodata..c_jump_table)
#else
#define annotate_reachable()
@@ -298,7 +298,7 @@ unsigned long read_word_at_a_time(const void *addr)
* visible to the compiler.
*/
#define __ADDRESSABLE(sym) \
- static void * __section(".discard.addressable") __used \
+ static void * __section(.discard.addressable) __used \
__PASTE(__addressable_##sym, __LINE__) = (void *)&sym;
/**
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index bb9a0db89f1a..12ae4b87494e 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -256,7 +256,10 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
{return 0;}
#endif
-#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, is_retention) \
+#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \
+ idx, \
+ state, \
+ is_retention) \
({ \
int __ret = 0; \
\
@@ -268,7 +271,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
if (!is_retention) \
__ret = cpu_pm_enter(); \
if (!__ret) { \
- __ret = low_level_idle_enter(idx); \
+ __ret = low_level_idle_enter(state); \
if (!is_retention) \
cpu_pm_exit(); \
} \
@@ -277,9 +280,15 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
})
#define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \
- __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 0)
+ __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0)
#define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \
- __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1)
+ __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1)
+
+#define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \
+ __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0)
+
+#define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \
+ __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1)
#endif /* _LINUX_CPUIDLE_H */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 21755471b1c3..b5a5a1ed9efd 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/bitmap.h>
+#include <linux/atomic.h>
#include <linux/bug.h>
/* Don't assign or return these: may not be this big! */
@@ -95,8 +96,21 @@ extern struct cpumask __cpu_active_mask;
#define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask)
#define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask)
+extern atomic_t __num_online_cpus;
+
#if NR_CPUS > 1
-#define num_online_cpus() cpumask_weight(cpu_online_mask)
+/**
+ * num_online_cpus() - Read the number of online CPUs
+ *
+ * Despite the fact that __num_online_cpus is of type atomic_t, this
+ * interface gives only a momentary snapshot and is not protected against
+ * concurrent CPU hotplug operations unless invoked from a cpuhp_lock held
+ * region.
+ */
+static inline unsigned int num_online_cpus(void)
+{
+ return atomic_read(&__num_online_cpus);
+}
#define num_possible_cpus() cpumask_weight(cpu_possible_mask)
#define num_present_cpus() cpumask_weight(cpu_present_mask)
#define num_active_cpus() cpumask_weight(cpu_active_mask)
@@ -115,6 +129,8 @@ extern struct cpumask __cpu_active_mask;
#define cpu_active(cpu) ((cpu) == 0)
#endif
+extern cpumask_t cpus_booted_once_mask;
+
static inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bits)
{
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
@@ -474,6 +490,20 @@ static inline bool cpumask_equal(const struct cpumask *src1p,
}
/**
+ * cpumask_or_equal - *src1p | *src2p == *src3p
+ * @src1p: the first input
+ * @src2p: the second input
+ * @src3p: the third input
+ */
+static inline bool cpumask_or_equal(const struct cpumask *src1p,
+ const struct cpumask *src2p,
+ const struct cpumask *src3p)
+{
+ return bitmap_or_equal(cpumask_bits(src1p), cpumask_bits(src2p),
+ cpumask_bits(src3p), nr_cpumask_bits);
+}
+
+/**
* cpumask_intersects - (*src1p & *src2p) != 0
* @src1p: the first input
* @src2p: the second input
@@ -805,14 +835,7 @@ set_cpu_present(unsigned int cpu, bool present)
cpumask_clear_cpu(cpu, &__cpu_present_mask);
}
-static inline void
-set_cpu_online(unsigned int cpu, bool online)
-{
- if (online)
- cpumask_set_cpu(cpu, &__cpu_online_mask);
- else
- cpumask_clear_cpu(cpu, &__cpu_online_mask);
-}
+void set_cpu_online(unsigned int cpu, bool online);
static inline void
set_cpu_active(unsigned int cpu, bool active)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 934633a05d20..04c20de66afc 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -40,14 +40,14 @@ static inline bool cpusets_enabled(void)
static inline void cpuset_inc(void)
{
- static_branch_inc(&cpusets_pre_enable_key);
- static_branch_inc(&cpusets_enabled_key);
+ static_branch_inc_cpuslocked(&cpusets_pre_enable_key);
+ static_branch_inc_cpuslocked(&cpusets_enabled_key);
}
static inline void cpuset_dec(void)
{
- static_branch_dec(&cpusets_enabled_key);
- static_branch_dec(&cpusets_pre_enable_key);
+ static_branch_dec_cpuslocked(&cpusets_enabled_key);
+ static_branch_dec_cpuslocked(&cpusets_pre_enable_key);
}
extern int cpuset_init(void);
@@ -55,6 +55,8 @@ extern void cpuset_init_smp(void);
extern void cpuset_force_rebuild(void);
extern void cpuset_update_active_cpus(void);
extern void cpuset_wait_for_hotplug(void);
+extern void cpuset_read_lock(void);
+extern void cpuset_read_unlock(void);
extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
@@ -176,6 +178,9 @@ static inline void cpuset_update_active_cpus(void)
static inline void cpuset_wait_for_hotplug(void) { }
+static inline void cpuset_read_lock(void) { }
+static inline void cpuset_read_unlock(void) { }
+
static inline void cpuset_cpus_allowed(struct task_struct *p,
struct cpumask *mask)
{
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 7eb43a038330..f7a30e0099be 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -145,7 +145,11 @@ struct cred {
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
struct group_info *group_info; /* supplementary groups for euid/fsgid */
- struct rcu_head rcu; /* RCU deletion hook */
+ /* RCU deletion */
+ union {
+ int non_rcu; /* Can we skip RCU deletion? */
+ struct rcu_head rcu; /* RCU deletion hook */
+ };
} __randomize_layout;
extern void __put_cred(struct cred *);
@@ -246,6 +250,7 @@ static inline const struct cred *get_cred(const struct cred *cred)
if (!cred)
return cred;
validate_creds(cred);
+ nonconst_cred->non_rcu = 0;
return get_new_cred(nonconst_cred);
}
@@ -257,6 +262,7 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred)
if (!atomic_inc_not_zero(&nonconst_cred->usage))
return NULL;
validate_creds(cred);
+ nonconst_cred->non_rcu = 0;
return cred;
}
diff --git a/include/linux/device.h b/include/linux/device.h
index c330b75c6c57..6717adee33f0 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -915,6 +915,8 @@ struct dev_links_info {
* This identifies the device type and carries type-specific
* information.
* @mutex: Mutex to synchronize calls to its driver.
+ * @lockdep_mutex: An optional debug lock that a subsystem can use as a
+ * peer lock to gain localized lockdep coverage of the device_lock.
* @bus: Type of bus device is on.
* @driver: Which driver has allocated this
* @platform_data: Platform data specific to the device.
@@ -998,6 +1000,9 @@ struct device {
core doesn't touch it */
void *driver_data; /* Driver data, set and get with
dev_set_drvdata/dev_get_drvdata */
+#ifdef CONFIG_PROVE_LOCKING
+ struct mutex lockdep_mutex;
+#endif
struct mutex mutex; /* mutex to synchronize calls to
* its driver.
*/
@@ -1383,6 +1388,7 @@ extern int (*platform_notify_remove)(struct device *dev);
*/
extern struct device *get_device(struct device *dev);
extern void put_device(struct device *dev);
+extern bool kill_device(struct device *dev);
#ifdef CONFIG_DEVTMPFS
extern int devtmpfs_create_node(struct device *dev);
diff --git a/include/linux/dim.h b/include/linux/dim.h
index d3a0fbfff2bb..9fa4b3f88c39 100644
--- a/include/linux/dim.h
+++ b/include/linux/dim.h
@@ -272,62 +272,6 @@ dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps,
/* Net DIM */
-/*
- * Net DIM profiles:
- * There are different set of profiles for each CQ period mode.
- * There are different set of profiles for RX/TX CQs.
- * Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
- */
-#define NET_DIM_PARAMS_NUM_PROFILES 5
-#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
-#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
-#define NET_DIM_DEF_PROFILE_CQE 1
-#define NET_DIM_DEF_PROFILE_EQE 1
-
-#define NET_DIM_RX_EQE_PROFILES { \
- {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-}
-
-#define NET_DIM_RX_CQE_PROFILES { \
- {2, 256}, \
- {8, 128}, \
- {16, 64}, \
- {32, 64}, \
- {64, 64} \
-}
-
-#define NET_DIM_TX_EQE_PROFILES { \
- {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
- {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \
-}
-
-#define NET_DIM_TX_CQE_PROFILES { \
- {5, 128}, \
- {8, 64}, \
- {16, 32}, \
- {32, 32}, \
- {64, 32} \
-}
-
-static const struct dim_cq_moder
-rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
- NET_DIM_RX_EQE_PROFILES,
- NET_DIM_RX_CQE_PROFILES,
-};
-
-static const struct dim_cq_moder
-tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
- NET_DIM_TX_EQE_PROFILES,
- NET_DIM_TX_CQE_PROFILES,
-};
-
/**
* net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile
* @cq_period_mode: CQ period mode
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index c05d4e661489..03f8e98e3bcc 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -160,10 +160,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
static inline struct page *dma_alloc_contiguous(struct device *dev, size_t size,
gfp_t gfp)
{
- int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
- size_t align = get_order(PAGE_ALIGN(size));
-
- return alloc_pages_node(node, gfp, align);
+ return NULL;
}
static inline void dma_free_contiguous(struct device *dev, struct page *page,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e11b115dd0e4..f7d1eea32c78 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -689,8 +689,8 @@ static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask)
*/
static inline bool dma_addressing_limited(struct device *dev)
{
- return min_not_zero(*dev->dma_mask, dev->bus_dma_mask) <
- dma_get_required_mask(dev);
+ return min_not_zero(dma_get_mask(dev), dev->bus_dma_mask) <
+ dma_get_required_mask(dev);
}
#ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS
diff --git a/include/linux/dma-noncoherent.h b/include/linux/dma-noncoherent.h
index 3813211a9aad..0bff3d7fac92 100644
--- a/include/linux/dma-noncoherent.h
+++ b/include/linux/dma-noncoherent.h
@@ -42,13 +42,18 @@ void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs);
long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
dma_addr_t dma_addr);
-
-#ifdef CONFIG_ARCH_HAS_DMA_MMAP_PGPROT
pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
unsigned long attrs);
+
+#ifdef CONFIG_MMU
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs);
#else
-# define arch_dma_mmap_pgprot(dev, prot, attrs) pgprot_noncached(prot)
-#endif
+static inline pgprot_t dma_pgprot(struct device *dev, pgprot_t prot,
+ unsigned long attrs)
+{
+ return prot; /* no protection bits supported without page tables */
+}
+#endif /* CONFIG_MMU */
#ifdef CONFIG_DMA_NONCOHERENT_CACHE_SYNC
void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 342dabda9c7e..c19483b90079 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -440,7 +440,7 @@ struct dimm_info {
char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
/* Memory location data */
- unsigned location[EDAC_MAX_LAYERS];
+ unsigned int location[EDAC_MAX_LAYERS];
struct mem_ctl_info *mci; /* the parent */
@@ -451,7 +451,7 @@ struct dimm_info {
u32 nr_pages; /* number of pages on this dimm */
- unsigned csrow, cschannel; /* Points to the old API data */
+ unsigned int csrow, cschannel; /* Points to the old API data */
u16 smbios_handle; /* Handle for SMBIOS type 17 */
};
@@ -597,7 +597,7 @@ struct mem_ctl_info {
unsigned long page);
int mc_idx;
struct csrow_info **csrows;
- unsigned nr_csrows, num_cschannel;
+ unsigned int nr_csrows, num_cschannel;
/*
* Memory Controller hierarchy
@@ -608,14 +608,14 @@ struct mem_ctl_info {
* of the recent drivers enumerate memories per DIMM, instead.
* When the memory controller is per rank, csbased is true.
*/
- unsigned n_layers;
+ unsigned int n_layers;
struct edac_mc_layer *layers;
bool csbased;
/*
* DIMM info. Will eventually remove the entire csrows_info some day
*/
- unsigned tot_dimms;
+ unsigned int tot_dimms;
struct dimm_info **dimms;
/*
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f87fabea4a85..bd3837022307 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -692,6 +692,9 @@ void efi_native_runtime_setup(void);
#define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
#define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
+/* OEM GUIDs */
+#define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55)
+
typedef struct {
efi_guid_t guid;
u64 table;
@@ -984,11 +987,9 @@ extern struct efi {
unsigned long acpi20; /* ACPI table (ACPI 2.0) */
unsigned long smbios; /* SMBIOS table (32 bit entry point) */
unsigned long smbios3; /* SMBIOS table (64 bit entry point) */
- unsigned long sal_systab; /* SAL system table */
unsigned long boot_info; /* boot info table */
unsigned long hcdp; /* HCDP table */
unsigned long uga; /* UGA table */
- unsigned long uv_systab; /* UV system table */
unsigned long fw_vendor; /* fw_vendor */
unsigned long runtime; /* runtime table */
unsigned long config_table; /* config tables */
@@ -1211,8 +1212,6 @@ static inline bool efi_enabled(int feature)
return test_bit(feature, &efi.flags) != 0;
}
extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
-
-extern bool efi_is_table_address(unsigned long phys_addr);
#else
static inline bool efi_enabled(int feature)
{
@@ -1226,11 +1225,6 @@ efi_capsule_pending(int *reset_type)
{
return false;
}
-
-static inline bool efi_is_table_address(unsigned long phys_addr)
-{
- return false;
-}
#endif
extern int efi_status_to_err(efi_status_t status);
@@ -1722,6 +1716,8 @@ struct efi_tcg2_final_events_table {
};
extern int efi_tpm_final_log_size;
+extern unsigned long rci2_table_phys;
+
/*
* efi_runtime_service() function identifiers.
* "NONE" is used by efi_recover_from_page_fault() to check if the page
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 17cd0078377c..1dd014c9c87b 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -45,7 +45,6 @@ struct elevator_mq_ops {
struct request *(*dispatch_request)(struct blk_mq_hw_ctx *);
bool (*has_work)(struct blk_mq_hw_ctx *);
void (*completed_request)(struct request *, u64);
- void (*started_request)(struct request *);
void (*requeue_request)(struct request *);
struct request *(*former_request)(struct request_queue *, struct request *);
struct request *(*next_request)(struct request_queue *, struct request *);
diff --git a/include/linux/error-injection.h b/include/linux/error-injection.h
index 280c61ecbf20..635a95caf29f 100644
--- a/include/linux/error-injection.h
+++ b/include/linux/error-injection.h
@@ -2,16 +2,16 @@
#ifndef _LINUX_ERROR_INJECTION_H
#define _LINUX_ERROR_INJECTION_H
-#ifdef CONFIG_FUNCTION_ERROR_INJECTION
+#include <linux/compiler.h>
+#include <asm-generic/error-injection.h>
-#include <asm/error-injection.h>
+#ifdef CONFIG_FUNCTION_ERROR_INJECTION
extern bool within_error_injection_list(unsigned long addr);
extern int get_injectable_error_type(unsigned long addr);
#else /* !CONFIG_FUNCTION_ERROR_INJECTION */
-#include <asm-generic/error-injection.h>
static inline bool within_error_injection_list(unsigned long addr)
{
return false;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index ff65d22cf336..92c6e31fb008 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -24,6 +24,7 @@
#include <net/sch_generic.h>
+#include <asm/byteorder.h>
#include <uapi/linux/filter.h>
#include <uapi/linux/bpf.h>
@@ -747,6 +748,18 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
return size <= size_default && (size & (size - 1)) == 0;
}
+static inline u8
+bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default)
+{
+ u8 load_off = off & (size_default - 1);
+
+#ifdef __LITTLE_ENDIAN
+ return load_off * 8;
+#else
+ return (size_default - (load_off + size)) * 8;
+#endif
+}
+
#define bpf_ctx_wide_access_ok(off, size, type, field) \
(size == sizeof(__u64) && \
off >= offsetof(type, field) && \
diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h
new file mode 100644
index 000000000000..7562099c9e46
--- /dev/null
+++ b/include/linux/firmware/imx/dsp.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 NXP
+ *
+ * Header file for the DSP IPC implementation
+ */
+
+#ifndef _IMX_DSP_IPC_H
+#define _IMX_DSP_IPC_H
+
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/mailbox_client.h>
+
+#define DSP_MU_CHAN_NUM 4
+
+struct imx_dsp_chan {
+ struct imx_dsp_ipc *ipc;
+ struct mbox_client cl;
+ struct mbox_chan *ch;
+ char *name;
+ int idx;
+};
+
+struct imx_dsp_ops {
+ void (*handle_reply)(struct imx_dsp_ipc *ipc);
+ void (*handle_request)(struct imx_dsp_ipc *ipc);
+};
+
+struct imx_dsp_ipc {
+ /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
+ struct imx_dsp_chan chans[DSP_MU_CHAN_NUM];
+ struct device *dev;
+ struct imx_dsp_ops *ops;
+ void *private_data;
+};
+
+static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data)
+{
+ if (!ipc)
+ return;
+
+ ipc->private_data = data;
+}
+
+static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc)
+{
+ if (!ipc)
+ return NULL;
+
+ return ipc->private_data;
+}
+
+#if IS_ENABLED(CONFIG_IMX_DSP)
+
+int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx);
+
+#else
+
+static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc,
+ unsigned int chan_idx)
+{
+ return -ENOTSUPP;
+}
+
+#endif
+#endif /* _IMX_DSP_IPC_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 56b8e358af5c..997a530ff4e9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2598,6 +2598,12 @@ extern struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
void *holder);
extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode,
void *holder);
+extern struct block_device *bd_start_claiming(struct block_device *bdev,
+ void *holder);
+extern void bd_finish_claiming(struct block_device *bdev,
+ struct block_device *whole, void *holder);
+extern void bd_abort_claiming(struct block_device *bdev,
+ struct block_device *whole, void *holder);
extern void blkdev_put(struct block_device *bdev, fmode_t mode);
extern int __blkdev_reread_part(struct block_device *bdev);
extern int blkdev_reread_part(struct block_device *bdev);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index fb07b503dc45..f33881688f42 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -510,22 +510,18 @@ alloc_pages(gfp_t gfp_mask, unsigned int order)
}
extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
struct vm_area_struct *vma, unsigned long addr,
- int node, bool hugepage);
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
- alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true)
+ int node);
#else
#define alloc_pages(gfp_mask, order) \
alloc_pages_node(numa_node_id(), gfp_mask, order)
-#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\
- alloc_pages(gfp_mask, order)
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
+#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\
alloc_pages(gfp_mask, order)
#endif
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
#define alloc_page_vma(gfp_mask, vma, addr) \
- alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false)
+ alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id())
#define alloc_page_vma_node(gfp_mask, vma, addr, node) \
- alloc_pages_vma(gfp_mask, 0, vma, addr, node, false)
+ alloc_pages_vma(gfp_mask, 0, vma, addr, node)
extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
extern unsigned long get_zeroed_page(gfp_t gfp_mask);
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 40915b461f18..2157717c2136 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -221,19 +221,6 @@ static inline int gpio_to_irq(unsigned gpio)
return -EINVAL;
}
-static inline int gpiochip_lock_as_irq(struct gpio_chip *chip,
- unsigned int offset)
-{
- WARN_ON(1);
- return -EINVAL;
-}
-
-static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip,
- unsigned int offset)
-{
- WARN_ON(1);
-}
-
static inline int irq_to_gpio(unsigned irq)
{
/* irq can never have been returned from gpio_to_irq() */
@@ -241,30 +228,6 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL;
}
-static inline int
-gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
- unsigned int gpio_offset, unsigned int pin_offset,
- unsigned int npins)
-{
- WARN_ON(1);
- return -EINVAL;
-}
-
-static inline int
-gpiochip_add_pingroup_range(struct gpio_chip *chip,
- struct pinctrl_dev *pctldev,
- unsigned int gpio_offset, const char *pin_group)
-{
- WARN_ON(1);
- return -EINVAL;
-}
-
-static inline void
-gpiochip_remove_pin_ranges(struct gpio_chip *chip)
-{
- WARN_ON(1);
-}
-
static inline int devm_gpio_request(struct device *dev, unsigned gpio,
const char *label)
{
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 9ddcf50a3c59..b70af921c614 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -170,18 +170,8 @@ struct gpio_desc *gpio_to_desc(unsigned gpio);
int desc_to_gpio(const struct gpio_desc *desc);
/* Child properties interface */
-struct device_node;
struct fwnode_handle;
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
- const char *propname, int index,
- enum gpiod_flags dflags,
- const char *label);
-struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
- struct device_node *node,
- const char *propname, int index,
- enum gpiod_flags dflags,
- const char *label);
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
enum gpiod_flags dflags,
@@ -247,7 +237,7 @@ static inline void gpiod_put(struct gpio_desc *desc)
might_sleep();
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline void devm_gpiod_unhinge(struct device *dev,
@@ -256,7 +246,7 @@ static inline void devm_gpiod_unhinge(struct device *dev,
might_sleep();
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline void gpiod_put_array(struct gpio_descs *descs)
@@ -264,7 +254,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs)
might_sleep();
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(descs);
}
static inline struct gpio_desc *__must_check
@@ -317,7 +307,7 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
might_sleep();
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline void devm_gpiod_put_array(struct device *dev,
@@ -326,32 +316,32 @@ static inline void devm_gpiod_put_array(struct device *dev,
might_sleep();
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(descs);
}
static inline int gpiod_get_direction(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
static inline int gpiod_direction_input(struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
@@ -359,7 +349,7 @@ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
static inline int gpiod_get_value(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_get_array_value(unsigned int array_size,
@@ -368,13 +358,13 @@ static inline int gpiod_get_array_value(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline void gpiod_set_value(struct gpio_desc *desc, int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline int gpiod_set_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
@@ -382,13 +372,13 @@ static inline int gpiod_set_array_value(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_get_raw_array_value(unsigned int array_size,
@@ -397,13 +387,13 @@ static inline int gpiod_get_raw_array_value(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline int gpiod_set_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
@@ -411,14 +401,14 @@ static inline int gpiod_set_raw_array_value(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_get_array_value_cansleep(unsigned int array_size,
@@ -427,13 +417,13 @@ static inline int gpiod_get_array_value_cansleep(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline int gpiod_set_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
@@ -441,13 +431,13 @@ static inline int gpiod_set_array_value_cansleep(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
@@ -456,14 +446,14 @@ static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
int value)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
}
static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
@@ -471,41 +461,41 @@ static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
unsigned long *value_bitmap)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc_array);
return 0;
}
static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -ENOSYS;
}
static inline int gpiod_is_active_low(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_cansleep(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return 0;
}
static inline int gpiod_to_irq(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -EINVAL;
}
@@ -513,7 +503,7 @@ static inline int gpiod_set_consumer_name(struct gpio_desc *desc,
const char *name)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -EINVAL;
}
@@ -525,34 +515,14 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
static inline int desc_to_gpio(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
- WARN_ON(1);
+ WARN_ON(desc);
return -EINVAL;
}
/* Child properties interface */
-struct device_node;
struct fwnode_handle;
static inline
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
- const char *propname, int index,
- enum gpiod_flags dflags,
- const char *label)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline
-struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
- struct device_node *node,
- const char *propname, int index,
- enum gpiod_flags dflags,
- const char *label)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
enum gpiod_flags dflags,
@@ -584,6 +554,111 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
flags, label);
}
+#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
+struct device_node;
+
+struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label);
+
+#else /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */
+
+struct device_node;
+
+static inline
+struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+#endif /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */
+
+#ifdef CONFIG_GPIOLIB
+struct device_node;
+
+struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
+ struct device_node *node,
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label);
+
+#else /* CONFIG_GPIOLIB */
+
+struct device_node;
+
+static inline
+struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
+ struct device_node *node,
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+struct acpi_gpio_params {
+ unsigned int crs_entry_index;
+ unsigned int line_index;
+ bool active_low;
+};
+
+struct acpi_gpio_mapping {
+ const char *name;
+ const struct acpi_gpio_params *data;
+ unsigned int size;
+
+/* Ignore IoRestriction field */
+#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0)
+/*
+ * When ACPI GPIO mapping table is in use the index parameter inside it
+ * refers to the GPIO resource in _CRS method. That index has no
+ * distinction of actual type of the resource. When consumer wants to
+ * get GpioIo type explicitly, this quirk may be used.
+ */
+#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1)
+
+ unsigned int quirks;
+};
+
+#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
+
+struct acpi_device;
+
+int acpi_dev_add_driver_gpios(struct acpi_device *adev,
+ const struct acpi_gpio_mapping *gpios);
+void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
+
+int devm_acpi_dev_add_driver_gpios(struct device *dev,
+ const struct acpi_gpio_mapping *gpios);
+void devm_acpi_dev_remove_driver_gpios(struct device *dev);
+
+#else /* CONFIG_GPIOLIB && CONFIG_ACPI */
+
+struct acpi_device;
+
+static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
+ const struct acpi_gpio_mapping *gpios)
+{
+ return -ENXIO;
+}
+static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
+
+static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
+ const struct acpi_gpio_mapping *gpios)
+{
+ return -ENXIO;
+}
+static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {}
+
+#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */
+
+
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 6a0e420915a3..f8245d67f070 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -20,9 +20,8 @@ struct module;
enum gpiod_flags;
enum gpio_lookup_flags;
-#ifdef CONFIG_GPIOLIB
+struct gpio_chip;
-#ifdef CONFIG_GPIOLIB_IRQCHIP
/**
* struct gpio_irq_chip - GPIO interrupt controller
*/
@@ -49,6 +48,84 @@ struct gpio_irq_chip {
*/
const struct irq_domain_ops *domain_ops;
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+ /**
+ * @fwnode:
+ *
+ * Firmware node corresponding to this gpiochip/irqchip, necessary
+ * for hierarchical irqdomain support.
+ */
+ struct fwnode_handle *fwnode;
+
+ /**
+ * @parent_domain:
+ *
+ * If non-NULL, will be set as the parent of this GPIO interrupt
+ * controller's IRQ domain to establish a hierarchical interrupt
+ * domain. The presence of this will activate the hierarchical
+ * interrupt support.
+ */
+ struct irq_domain *parent_domain;
+
+ /**
+ * @child_to_parent_hwirq:
+ *
+ * This callback translates a child hardware IRQ offset to a parent
+ * hardware IRQ offset on a hierarchical interrupt chip. The child
+ * hardware IRQs correspond to the GPIO index 0..ngpio-1 (see the
+ * ngpio field of struct gpio_chip) and the corresponding parent
+ * hardware IRQ and type (such as IRQ_TYPE_*) shall be returned by
+ * the driver. The driver can calculate this from an offset or using
+ * a lookup table or whatever method is best for this chip. Return
+ * 0 on successful translation in the driver.
+ *
+ * If some ranges of hardware IRQs do not have a corresponding parent
+ * HWIRQ, return -EINVAL, but also make sure to fill in @valid_mask and
+ * @need_valid_mask to make these GPIO lines unavailable for
+ * translation.
+ */
+ int (*child_to_parent_hwirq)(struct gpio_chip *chip,
+ unsigned int child_hwirq,
+ unsigned int child_type,
+ unsigned int *parent_hwirq,
+ unsigned int *parent_type);
+
+ /**
+ * @populate_parent_fwspec:
+ *
+ * This optional callback populates the &struct irq_fwspec for the
+ * parent's IRQ domain. If this is not specified, then
+ * &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell
+ * variant named &gpiochip_populate_parent_fwspec_fourcell is also
+ * available.
+ */
+ void (*populate_parent_fwspec)(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type);
+
+ /**
+ * @child_offset_to_irq:
+ *
+ * This optional callback is used to translate the child's GPIO line
+ * offset on the GPIO chip to an IRQ number for the GPIO to_irq()
+ * callback. If this is not specified, then a default callback will be
+ * provided that returns the line offset.
+ */
+ unsigned int (*child_offset_to_irq)(struct gpio_chip *chip,
+ unsigned int pin);
+
+ /**
+ * @child_irq_domain_ops:
+ *
+ * The IRQ domain operations that will be used for this GPIO IRQ
+ * chip. If no operations are provided, then default callbacks will
+ * be populated to setup the IRQ hierarchy. Some drivers need to
+ * supply their own translate function.
+ */
+ struct irq_domain_ops child_irq_domain_ops;
+#endif
+
/**
* @handler:
*
@@ -125,11 +202,17 @@ struct gpio_irq_chip {
bool threaded;
/**
- * @need_valid_mask:
- *
- * If set core allocates @valid_mask with all bits set to one.
+ * @init_valid_mask: optional routine to initialize @valid_mask, to be
+ * used if not all GPIO lines are valid interrupts. Sometimes some
+ * lines just cannot fire interrupts, and this routine, when defined,
+ * is passed a bitmap in "valid_mask" and it will have ngpios
+ * bits from 0..(ngpios-1) set to "1" as in valid. The callback can
+ * then directly set some bits to "0" if they cannot be used for
+ * interrupts.
*/
- bool need_valid_mask;
+ void (*init_valid_mask)(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios);
/**
* @valid_mask:
@@ -161,7 +244,6 @@ struct gpio_irq_chip {
*/
void (*irq_disable)(struct irq_data *data);
};
-#endif /* CONFIG_GPIOLIB_IRQCHIP */
/**
* struct gpio_chip - abstract a GPIO controller
@@ -282,7 +364,9 @@ struct gpio_chip {
void (*dbg_show)(struct seq_file *s,
struct gpio_chip *chip);
- int (*init_valid_mask)(struct gpio_chip *chip);
+ int (*init_valid_mask)(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios);
int base;
u16 ngpio;
@@ -321,15 +405,6 @@ struct gpio_chip {
#endif /* CONFIG_GPIOLIB_IRQCHIP */
/**
- * @need_valid_mask:
- *
- * If set core allocates @valid_mask with all its values initialized
- * with init_valid_mask() or set to one if init_valid_mask() is not
- * defined
- */
- bool need_valid_mask;
-
- /**
* @valid_mask:
*
* If not %NULL holds bitmask of GPIOs which are valid to be used
@@ -421,9 +496,6 @@ extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
extern struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip, void *data));
-/* lock/unlock as IRQ */
-int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
-void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset);
int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset);
void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset);
@@ -441,15 +513,40 @@ bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset);
/* get driver data */
void *gpiochip_get_data(struct gpio_chip *chip);
-struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
-
struct bgpio_pdata {
const char *label;
int base;
int ngpio;
};
-#if IS_ENABLED(CONFIG_GPIO_GENERIC)
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+
+void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type);
+void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type);
+
+#else
+
+static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type)
+{
+}
+
+static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
+ struct irq_fwspec *fwspec,
+ unsigned int parent_hwirq,
+ unsigned int parent_type)
+{
+}
+
+#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
int bgpio_init(struct gpio_chip *gc, struct device *dev,
unsigned long sz, void __iomem *dat, void __iomem *set,
@@ -463,10 +560,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
#define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */
#define BGPIOF_NO_OUTPUT BIT(5) /* only input */
-#endif /* CONFIG_GPIO_GENERIC */
-
-#ifdef CONFIG_GPIOLIB_IRQCHIP
-
int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq);
void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq);
@@ -555,15 +648,11 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
}
#endif /* CONFIG_LOCKDEP */
-#endif /* CONFIG_GPIOLIB_IRQCHIP */
-
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset);
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset);
int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,
unsigned long config);
-#ifdef CONFIG_PINCTRL
-
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @node: list for maintaining set of pin ranges, used internally
@@ -576,6 +665,8 @@ struct gpio_pin_range {
struct pinctrl_gpio_range range;
};
+#ifdef CONFIG_PINCTRL
+
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins);
@@ -586,8 +677,6 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else /* ! CONFIG_PINCTRL */
-struct pinctrl_dev;
-
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
@@ -619,6 +708,15 @@ void gpiochip_free_own_desc(struct gpio_desc *desc);
void devprop_gpiochip_set_names(struct gpio_chip *chip,
const struct fwnode_handle *fwnode);
+#ifdef CONFIG_GPIOLIB
+
+/* lock/unlock as IRQ */
+int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
+void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
+
+
+struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
+
#else /* CONFIG_GPIOLIB */
static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
@@ -628,6 +726,18 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
return ERR_PTR(-ENODEV);
}
+static inline int gpiochip_lock_as_irq(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ WARN_ON(1);
+ return -EINVAL;
+}
+
+static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ WARN_ON(1);
+}
#endif /* CONFIG_GPIOLIB */
-#endif
+#endif /* __LINUX_GPIO_DRIVER_H */
diff --git a/include/linux/hmm.h b/include/linux/hmm.h
index b8a08b2a10ca..7ef56dc18050 100644
--- a/include/linux/hmm.h
+++ b/include/linux/hmm.h
@@ -484,60 +484,6 @@ long hmm_range_dma_unmap(struct hmm_range *range,
*/
#define HMM_RANGE_DEFAULT_TIMEOUT 1000
-/* This is a temporary helper to avoid merge conflict between trees. */
-static inline bool hmm_vma_range_done(struct hmm_range *range)
-{
- bool ret = hmm_range_valid(range);
-
- hmm_range_unregister(range);
- return ret;
-}
-
-/* This is a temporary helper to avoid merge conflict between trees. */
-static inline int hmm_vma_fault(struct hmm_mirror *mirror,
- struct hmm_range *range, bool block)
-{
- long ret;
-
- /*
- * With the old API the driver must set each individual entries with
- * the requested flags (valid, write, ...). So here we set the mask to
- * keep intact the entries provided by the driver and zero out the
- * default_flags.
- */
- range->default_flags = 0;
- range->pfn_flags_mask = -1UL;
-
- ret = hmm_range_register(range, mirror,
- range->start, range->end,
- PAGE_SHIFT);
- if (ret)
- return (int)ret;
-
- if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
- /*
- * The mmap_sem was taken by driver we release it here and
- * returns -EAGAIN which correspond to mmap_sem have been
- * drop in the old API.
- */
- up_read(&range->vma->vm_mm->mmap_sem);
- return -EAGAIN;
- }
-
- ret = hmm_range_fault(range, block);
- if (ret <= 0) {
- if (ret == -EBUSY || !ret) {
- /* Same as above, drop mmap_sem to match old API. */
- up_read(&range->vma->vm_mm->mmap_sem);
- ret = -EBUSY;
- } else if (ret == -EAGAIN)
- ret = -EBUSY;
- hmm_range_unregister(range);
- return ret;
- }
- return 0;
-}
-
/* Below are for HMM internal use only! Not to be used by device driver! */
static inline void hmm_mm_init(struct mm_struct *mm)
{
diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
index 5ecb055fd375..de102e4418ab 100644
--- a/include/linux/i3c/device.h
+++ b/include/linux/i3c/device.h
@@ -188,6 +188,10 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv)
struct device *i3cdev_to_dev(struct i3c_device *i3cdev);
struct i3c_device *dev_to_i3cdev(struct device *dev);
+const struct i3c_device_id *
+i3c_device_match_id(struct i3c_device *i3cdev,
+ const struct i3c_device_id *id_table);
+
static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev,
void *data)
{
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 1f08fa8d69d2..9cb39d901cd5 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -71,6 +71,9 @@ struct i2c_dev_boardinfo {
* @common: common part of the I2C device descriptor
* @boardinfo: pointer to the boardinfo attached to this I2C device
* @dev: I2C device object registered to the I2C framework
+ * @addr: I2C device address
+ * @lvr: LVR (Legacy Virtual Register) needed by the I3C core to know about
+ * the I2C device limitations
*
* Each I2C device connected on the bus will have an i2c_dev_desc.
* This object is created by the core and later attached to the controller
@@ -84,6 +87,8 @@ struct i2c_dev_desc {
struct i3c_i2c_dev_desc common;
const struct i2c_dev_boardinfo *boardinfo;
struct i2c_client *dev;
+ u16 addr;
+ u8 lvr;
};
/**
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 8b728750a625..69e813bcb947 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -80,6 +80,9 @@ extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp);
extern void unregister_pppox_proto(int proto_num);
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+
+#define PPPOEIOCSFWD32 _IOW(0xB1 ,0, compat_size_t)
/* PPPoX socket states */
enum {
diff --git a/include/linux/if_rmnet.h b/include/linux/if_rmnet.h
index b4f5403383fc..9661416a9bb4 100644
--- a/include/linux/if_rmnet.h
+++ b/include/linux/if_rmnet.h
@@ -41,11 +41,11 @@ struct rmnet_map_ul_csum_header {
__be16 csum_start_offset;
#if defined(__LITTLE_ENDIAN_BITFIELD)
u16 csum_insert_offset:14;
- u16 udp_ip4_ind:1;
+ u16 udp_ind:1;
u16 csum_enabled:1;
#elif defined (__BIG_ENDIAN_BITFIELD)
u16 csum_enabled:1;
- u16 udp_ip4_ind:1;
+ u16 udp_ind:1;
u16 csum_insert_offset:14;
#else
#error "Please fix <asm/byteorder.h>"
diff --git a/include/linux/input/elan-i2c-ids.h b/include/linux/input/elan-i2c-ids.h
index ceabb01a6a7d..1ecb6b45812c 100644
--- a/include/linux/input/elan-i2c-ids.h
+++ b/include/linux/input/elan-i2c-ids.h
@@ -48,7 +48,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
{ "ELAN0618", 0 },
{ "ELAN0619", 0 },
{ "ELAN061A", 0 },
- { "ELAN061B", 0 },
+/* { "ELAN061B", 0 }, not working on the Lenovo Legion Y7000 */
{ "ELAN061C", 0 },
{ "ELAN061D", 0 },
{ "ELAN061E", 0 },
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index f2ae8a006ff8..ed11ef594378 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -272,6 +272,8 @@
#define dma_frcd_type(d) ((d >> 30) & 1)
#define dma_frcd_fault_reason(c) (c & 0xff)
#define dma_frcd_source_id(c) (c & 0xffff)
+#define dma_frcd_pasid_value(c) (((c) >> 8) & 0xfffff)
+#define dma_frcd_pasid_present(c) (((c) >> 31) & 1)
/* low 64 bit */
#define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT))
@@ -346,7 +348,6 @@ enum {
#define QI_PC_PASID_SEL (QI_PC_TYPE | QI_PC_GRAN(1))
#define QI_EIOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK)
-#define QI_EIOTLB_GL(gl) (((u64)gl) << 7)
#define QI_EIOTLB_IH(ih) (((u64)ih) << 6)
#define QI_EIOTLB_AM(am) (((u64)am))
#define QI_EIOTLB_PASID(pasid) (((u64)pasid) << 32)
@@ -378,8 +379,6 @@ enum {
#define QI_RESP_INVALID 0x1
#define QI_RESP_FAILURE 0xf
-#define QI_GRAN_ALL_ALL 0
-#define QI_GRAN_NONG_ALL 1
#define QI_GRAN_NONG_PASID 2
#define QI_GRAN_PSI_PASID 3
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5b8328a99b2a..07b527dca996 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -472,7 +472,11 @@ extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
bool state);
#ifdef CONFIG_IRQ_FORCED_THREADING
+# ifdef CONFIG_PREEMPT_RT
+# define force_irqthreads (true)
+# else
extern bool force_irqthreads;
+# endif
#else
#define force_irqthreads (0)
#endif
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index b5a450a3bb47..ec7a13405f10 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -1,7 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __IO_PGTABLE_H
#define __IO_PGTABLE_H
+
#include <linux/bitops.h>
+#include <linux/iommu.h>
/*
* Public API for use by IOMMU drivers
@@ -17,22 +19,31 @@ enum io_pgtable_fmt {
};
/**
- * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management.
+ * struct iommu_flush_ops - IOMMU callbacks for TLB and page table management.
*
- * @tlb_flush_all: Synchronously invalidate the entire TLB context.
- * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range.
- * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and
- * any corresponding page table updates are visible to the
- * IOMMU.
+ * @tlb_flush_all: Synchronously invalidate the entire TLB context.
+ * @tlb_flush_walk: Synchronously invalidate all intermediate TLB state
+ * (sometimes referred to as the "walk cache") for a virtual
+ * address range.
+ * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual
+ * address range.
+ * @tlb_add_page: Optional callback to queue up leaf TLB invalidation for a
+ * single page. IOMMUs that cannot batch TLB invalidation
+ * operations efficiently will typically issue them here, but
+ * others may decide to update the iommu_iotlb_gather structure
+ * and defer the invalidation until iommu_tlb_sync() instead.
*
* Note that these can all be called in atomic context and must therefore
* not block.
*/
-struct iommu_gather_ops {
+struct iommu_flush_ops {
void (*tlb_flush_all)(void *cookie);
- void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule,
- bool leaf, void *cookie);
- void (*tlb_sync)(void *cookie);
+ void (*tlb_flush_walk)(unsigned long iova, size_t size, size_t granule,
+ void *cookie);
+ void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule,
+ void *cookie);
+ void (*tlb_add_page)(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t granule, void *cookie);
};
/**
@@ -65,10 +76,9 @@ struct io_pgtable_cfg {
* (unmapped) entries but the hardware might do so anyway, perform
* TLB maintenance when mapping as well as when unmapping.
*
- * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all
- * PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
- * when the SoC is in "4GB mode" and they can only access the high
- * remap of DRAM (0x1_00000000 to 0x1_ffffffff).
+ * IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) MediaTek IOMMUs extend
+ * to support up to 34 bits PA where the bit32 and bit33 are
+ * encoded in the bit9 and bit4 of the PTE respectively.
*
* IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
* on unmap, for DMA domains using the flush queue mechanism for
@@ -77,14 +87,14 @@ struct io_pgtable_cfg {
#define IO_PGTABLE_QUIRK_ARM_NS BIT(0)
#define IO_PGTABLE_QUIRK_NO_PERMS BIT(1)
#define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2)
- #define IO_PGTABLE_QUIRK_ARM_MTK_4GB BIT(3)
+ #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3)
#define IO_PGTABLE_QUIRK_NON_STRICT BIT(4)
unsigned long quirks;
unsigned long pgsize_bitmap;
unsigned int ias;
unsigned int oas;
bool coherent_walk;
- const struct iommu_gather_ops *tlb;
+ const struct iommu_flush_ops *tlb;
struct device *iommu_dev;
/* Low-level data specific to the table format */
@@ -128,7 +138,7 @@ struct io_pgtable_ops {
int (*map)(struct io_pgtable_ops *ops, unsigned long iova,
phys_addr_t paddr, size_t size, int prot);
size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size);
+ size_t size, struct iommu_iotlb_gather *gather);
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
unsigned long iova);
};
@@ -184,15 +194,27 @@ static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop)
iop->cfg.tlb->tlb_flush_all(iop->cookie);
}
-static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop,
- unsigned long iova, size_t size, size_t granule, bool leaf)
+static inline void
+io_pgtable_tlb_flush_walk(struct io_pgtable *iop, unsigned long iova,
+ size_t size, size_t granule)
+{
+ iop->cfg.tlb->tlb_flush_walk(iova, size, granule, iop->cookie);
+}
+
+static inline void
+io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova,
+ size_t size, size_t granule)
{
- iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie);
+ iop->cfg.tlb->tlb_flush_leaf(iova, size, granule, iop->cookie);
}
-static inline void io_pgtable_tlb_sync(struct io_pgtable *iop)
+static inline void
+io_pgtable_tlb_add_page(struct io_pgtable *iop,
+ struct iommu_iotlb_gather * gather, unsigned long iova,
+ size_t granule)
{
- iop->cfg.tlb->tlb_sync(iop->cookie);
+ if (iop->cfg.tlb->tlb_add_page)
+ iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie);
}
/**
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
deleted file mode 100644
index 51e2b9fb6372..000000000000
--- a/include/linux/ioc4.h
+++ /dev/null
@@ -1,184 +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) 2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#ifndef _LINUX_IOC4_H
-#define _LINUX_IOC4_H
-
-#include <linux/interrupt.h>
-
-/***************
- * Definitions *
- ***************/
-
-/* Miscellaneous values inherent to hardware */
-
-#define IOC4_EXTINT_COUNT_DIVISOR 520 /* PCI clocks per COUNT tick */
-
-/***********************************
- * Structures needed by subdrivers *
- ***********************************/
-
-/* This structure fully describes the IOC4 miscellaneous registers which
- * appear at bar[0]+0x00000 through bar[0]+0x0005c. The corresponding
- * PCI resource is managed by the main IOC4 driver because it contains
- * registers of interest to many different IOC4 subdrivers.
- */
-struct ioc4_misc_regs {
- /* Miscellaneous IOC4 registers */
- union ioc4_pci_err_addr_l {
- uint32_t raw;
- struct {
- uint32_t valid:1; /* Address captured */
- uint32_t master_id:4; /* Unit causing error
- * 0/1: Serial port 0 TX/RX
- * 2/3: Serial port 1 TX/RX
- * 4/5: Serial port 2 TX/RX
- * 6/7: Serial port 3 TX/RX
- * 8: ATA/ATAPI
- * 9-15: Undefined
- */
- uint32_t mul_err:1; /* Multiple errors occurred */
- uint32_t addr:26; /* Bits 31-6 of error addr */
- } fields;
- } pci_err_addr_l;
- uint32_t pci_err_addr_h; /* Bits 63-32 of error addr */
- union ioc4_sio_int {
- uint32_t raw;
- struct {
- uint8_t tx_mt:1; /* TX ring buffer empty */
- uint8_t rx_full:1; /* RX ring buffer full */
- uint8_t rx_high:1; /* RX high-water exceeded */
- uint8_t rx_timer:1; /* RX timer has triggered */
- uint8_t delta_dcd:1; /* DELTA_DCD seen */
- uint8_t delta_cts:1; /* DELTA_CTS seen */
- uint8_t intr_pass:1; /* Interrupt pass-through */
- uint8_t tx_explicit:1; /* TX, MCW, or delay complete */
- } fields[4];
- } sio_ir; /* Serial interrupt state */
- union ioc4_other_int {
- uint32_t raw;
- struct {
- uint32_t ata_int:1; /* ATA port passthru */
- uint32_t ata_memerr:1; /* ATA halted by mem error */
- uint32_t memerr:4; /* Serial halted by mem err */
- uint32_t kbd_int:1; /* kbd/mouse intr asserted */
- uint32_t reserved:16; /* zero */
- uint32_t rt_int:1; /* INT_OUT section latch */
- uint32_t gen_int:8; /* Intr. from generic pins */
- } fields;
- } other_ir; /* Other interrupt state */
- union ioc4_sio_int sio_ies; /* Serial interrupt enable set */
- union ioc4_other_int other_ies; /* Other interrupt enable set */
- union ioc4_sio_int sio_iec; /* Serial interrupt enable clear */
- union ioc4_other_int other_iec; /* Other interrupt enable clear */
- union ioc4_sio_cr {
- uint32_t raw;
- struct {
- uint32_t cmd_pulse:4; /* Bytebus strobe width */
- uint32_t arb_diag:3; /* PCI bus requester */
- uint32_t sio_diag_idle:1; /* Active ser req? */
- uint32_t ata_diag_idle:1; /* Active ATA req? */
- uint32_t ata_diag_active:1; /* ATA req is winner */
- uint32_t reserved:22; /* zero */
- } fields;
- } sio_cr;
- uint32_t unused1;
- union ioc4_int_out {
- uint32_t raw;
- struct {
- uint32_t count:16; /* Period control */
- uint32_t mode:3; /* Output signal shape */
- uint32_t reserved:11; /* zero */
- uint32_t diag:1; /* Timebase control */
- uint32_t int_out:1; /* Current value */
- } fields;
- } int_out; /* External interrupt output control */
- uint32_t unused2;
- union ioc4_gpcr {
- uint32_t raw;
- struct {
- uint32_t dir:8; /* Pin direction */
- uint32_t edge:8; /* Edge/level mode */
- uint32_t reserved1:4; /* zero */
- uint32_t int_out_en:1; /* INT_OUT enable */
- uint32_t reserved2:11; /* zero */
- } fields;
- } gpcr_s; /* Generic PIO control set */
- union ioc4_gpcr gpcr_c; /* Generic PIO control clear */
- union ioc4_gpdr {
- uint32_t raw;
- struct {
- uint32_t gen_pin:8; /* State of pins */
- uint32_t reserved:24;
- } fields;
- } gpdr; /* Generic PIO data */
- uint32_t unused3;
- union ioc4_gppr {
- uint32_t raw;
- struct {
- uint32_t gen_pin:1; /* Single pin state */
- uint32_t reserved:31;
- } fields;
- } gppr[8]; /* Generic PIO pins */
-};
-
-/* Masks for GPCR DIR pins */
-#define IOC4_GPCR_DIR_0 0x01 /* External interrupt output */
-#define IOC4_GPCR_DIR_1 0x02 /* External interrupt input */
-#define IOC4_GPCR_DIR_2 0x04
-#define IOC4_GPCR_DIR_3 0x08 /* Keyboard/mouse presence */
-#define IOC4_GPCR_DIR_4 0x10 /* Ser. port 0 xcvr select (0=232, 1=422) */
-#define IOC4_GPCR_DIR_5 0x20 /* Ser. port 1 xcvr select (0=232, 1=422) */
-#define IOC4_GPCR_DIR_6 0x40 /* Ser. port 2 xcvr select (0=232, 1=422) */
-#define IOC4_GPCR_DIR_7 0x80 /* Ser. port 3 xcvr select (0=232, 1=422) */
-
-/* Masks for GPCR EDGE pins */
-#define IOC4_GPCR_EDGE_0 0x01
-#define IOC4_GPCR_EDGE_1 0x02 /* External interrupt input */
-#define IOC4_GPCR_EDGE_2 0x04
-#define IOC4_GPCR_EDGE_3 0x08
-#define IOC4_GPCR_EDGE_4 0x10
-#define IOC4_GPCR_EDGE_5 0x20
-#define IOC4_GPCR_EDGE_6 0x40
-#define IOC4_GPCR_EDGE_7 0x80
-
-#define IOC4_VARIANT_IO9 0x0900
-#define IOC4_VARIANT_PCI_RT 0x0901
-#define IOC4_VARIANT_IO10 0x1000
-
-/* One of these per IOC4 */
-struct ioc4_driver_data {
- struct list_head idd_list;
- unsigned long idd_bar0;
- struct pci_dev *idd_pdev;
- const struct pci_device_id *idd_pci_id;
- struct ioc4_misc_regs __iomem *idd_misc_regs;
- unsigned long count_period;
- void *idd_serial_data;
- unsigned int idd_variant;
-};
-
-/* One per submodule */
-struct ioc4_submodule {
- struct list_head is_list;
- char *is_name;
- struct module *is_owner;
- int (*is_probe) (struct ioc4_driver_data *);
- int (*is_remove) (struct ioc4_driver_data *);
-};
-
-#define IOC4_NUM_CARDS 8 /* max cards per partition */
-
-/**********************************
- * Functions needed by submodules *
- **********************************/
-
-extern int ioc4_register_submodule(struct ioc4_submodule *);
-extern void ioc4_unregister_submodule(struct ioc4_submodule *);
-
-#endif /* _LINUX_IOC4_H */
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fdc355ccc570..29bac5345563 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -192,6 +192,23 @@ struct iommu_sva_ops {
#ifdef CONFIG_IOMMU_API
/**
+ * struct iommu_iotlb_gather - Range information for a pending IOTLB flush
+ *
+ * @start: IOVA representing the start of the range to be flushed
+ * @end: IOVA representing the end of the range to be flushed (exclusive)
+ * @pgsize: The interval at which to perform the flush
+ *
+ * This structure is intended to be updated by multiple calls to the
+ * ->unmap() function in struct iommu_ops before eventually being passed
+ * into ->iotlb_sync().
+ */
+struct iommu_iotlb_gather {
+ unsigned long start;
+ unsigned long end;
+ size_t pgsize;
+};
+
+/**
* struct iommu_ops - iommu ops and capabilities
* @capable: check capability
* @domain_alloc: allocate iommu domain
@@ -201,7 +218,6 @@ struct iommu_sva_ops {
* @map: map a physically contiguous memory region to an iommu domain
* @unmap: unmap a physically contiguous memory region from an iommu domain
* @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain
- * @iotlb_range_add: Add a given iova range to the flush queue for this domain
* @iotlb_sync_map: Sync mappings created recently using @map to the hardware
* @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush
* queue
@@ -242,12 +258,11 @@ struct iommu_ops {
int (*map)(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot);
size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
- size_t size);
+ size_t size, struct iommu_iotlb_gather *iotlb_gather);
void (*flush_iotlb_all)(struct iommu_domain *domain);
- void (*iotlb_range_add)(struct iommu_domain *domain,
- unsigned long iova, size_t size);
void (*iotlb_sync_map)(struct iommu_domain *domain);
- void (*iotlb_sync)(struct iommu_domain *domain);
+ void (*iotlb_sync)(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *iotlb_gather);
phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
int (*add_device)(struct device *dev);
void (*remove_device)(struct device *dev);
@@ -378,6 +393,13 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev)
return (struct iommu_device *)dev_get_drvdata(dev);
}
+static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
+{
+ *gather = (struct iommu_iotlb_gather) {
+ .start = ULONG_MAX,
+ };
+}
+
#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */
#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */
#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */
@@ -402,7 +424,8 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
size_t size);
extern size_t iommu_unmap_fast(struct iommu_domain *domain,
- unsigned long iova, size_t size);
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *iotlb_gather);
extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
struct scatterlist *sg,unsigned int nents, int prot);
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
@@ -413,6 +436,9 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev);
extern int iommu_request_dma_domain_for_dev(struct device *dev);
+extern void iommu_set_default_passthrough(bool cmd_line);
+extern void iommu_set_default_translated(bool cmd_line);
+extern bool iommu_default_passthrough(void);
extern struct iommu_resv_region *
iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot,
enum iommu_resv_type type);
@@ -476,17 +502,38 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
domain->ops->flush_iotlb_all(domain);
}
-static inline void iommu_tlb_range_add(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+static inline void iommu_tlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *iotlb_gather)
{
- if (domain->ops->iotlb_range_add)
- domain->ops->iotlb_range_add(domain, iova, size);
+ if (domain->ops->iotlb_sync)
+ domain->ops->iotlb_sync(domain, iotlb_gather);
+
+ iommu_iotlb_gather_init(iotlb_gather);
}
-static inline void iommu_tlb_sync(struct iommu_domain *domain)
+static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size)
{
- if (domain->ops->iotlb_sync)
- domain->ops->iotlb_sync(domain);
+ unsigned long start = iova, end = start + size;
+
+ /*
+ * If the new page is disjoint from the current range or is mapped at
+ * a different granularity, then sync the TLB so that the gather
+ * structure can be rewritten.
+ */
+ if (gather->pgsize != size ||
+ end < gather->start || start > gather->end) {
+ if (gather->pgsize)
+ iommu_tlb_sync(domain, gather);
+ gather->pgsize = size;
+ }
+
+ if (gather->end < end)
+ gather->end = end;
+
+ if (gather->start > start)
+ gather->start = start;
}
/* PCI device grouping function */
@@ -567,6 +614,7 @@ struct iommu_group {};
struct iommu_fwspec {};
struct iommu_device {};
struct iommu_fault_param {};
+struct iommu_iotlb_gather {};
static inline bool iommu_present(struct bus_type *bus)
{
@@ -621,7 +669,8 @@ static inline size_t iommu_unmap(struct iommu_domain *domain,
}
static inline size_t iommu_unmap_fast(struct iommu_domain *domain,
- unsigned long iova, int gfp_order)
+ unsigned long iova, int gfp_order,
+ struct iommu_iotlb_gather *iotlb_gather)
{
return 0;
}
@@ -637,12 +686,8 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
{
}
-static inline void iommu_tlb_range_add(struct iommu_domain *domain,
- unsigned long iova, size_t size)
-{
-}
-
-static inline void iommu_tlb_sync(struct iommu_domain *domain)
+static inline void iommu_tlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *iotlb_gather)
{
}
@@ -694,6 +739,19 @@ static inline int iommu_request_dma_domain_for_dev(struct device *dev)
return -ENODEV;
}
+static inline void iommu_set_default_passthrough(bool cmd_line)
+{
+}
+
+static inline void iommu_set_default_translated(bool cmd_line)
+{
+}
+
+static inline bool iommu_default_passthrough(void)
+{
+ return true;
+}
+
static inline int iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group)
{
@@ -827,6 +885,16 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev)
return NULL;
}
+static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
+{
+}
+
+static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size)
+{
+}
+
static inline void iommu_device_unregister(struct iommu_device *iommu)
{
}
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 781b96ac706f..a0637abffee8 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -155,6 +155,7 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
unsigned long start_pfn);
+bool has_iova_flush_queue(struct iova_domain *iovad);
int init_iova_flush_queue(struct iova_domain *iovad,
iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
@@ -235,6 +236,11 @@ static inline void init_iova_domain(struct iova_domain *iovad,
{
}
+static inline bool has_iova_flush_queue(struct iova_domain *iovad)
+{
+ return false;
+}
+
static inline int init_iova_flush_queue(struct iova_domain *iovad,
iova_flush_cb flush_cb,
iova_entry_dtor entry_dtor)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 67c4b9806d43..5cc10cf7cb3e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -30,10 +30,22 @@
#define GICD_ICFGR 0x0C00
#define GICD_IGRPMODR 0x0D00
#define GICD_NSACR 0x0E00
+#define GICD_IGROUPRnE 0x1000
+#define GICD_ISENABLERnE 0x1200
+#define GICD_ICENABLERnE 0x1400
+#define GICD_ISPENDRnE 0x1600
+#define GICD_ICPENDRnE 0x1800
+#define GICD_ISACTIVERnE 0x1A00
+#define GICD_ICACTIVERnE 0x1C00
+#define GICD_IPRIORITYRnE 0x2000
+#define GICD_ICFGRnE 0x3000
#define GICD_IROUTER 0x6000
+#define GICD_IROUTERnE 0x8000
#define GICD_IDREGS 0xFFD0
#define GICD_PIDR2 0xFFE8
+#define ESPI_BASE_INTID 4096
+
/*
* Those registers are actually from GICv2, but the spec demands that they
* are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
@@ -69,10 +81,13 @@
#define GICD_TYPER_RSS (1U << 26)
#define GICD_TYPER_LPIS (1U << 17)
#define GICD_TYPER_MBIS (1U << 16)
+#define GICD_TYPER_ESPI (1U << 8)
#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
-#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_ESPIS(typer) \
+ (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
@@ -109,6 +124,18 @@
#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
+#define EPPI_BASE_INTID 1056
+
+#define GICR_TYPER_NR_PPIS(r) \
+ ({ \
+ unsigned int __ppinum = ((r) >> 27) & 0x1f; \
+ unsigned int __nr_ppis = 16; \
+ if (__ppinum == 1 || __ppinum == 2) \
+ __nr_ppis += __ppinum * 32; \
+ \
+ __nr_ppis; \
+ })
+
#define GICR_WAKER_ProcessorSleep (1U << 1)
#define GICR_WAKER_ChildrenAsleep (1U << 2)
@@ -469,6 +496,7 @@
#define ICC_CTLR_EL1_A3V_SHIFT 15
#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
#define ICC_CTLR_EL1_RSS (0x1 << 18)
+#define ICC_CTLR_EL1_ExtRange (0x1 << 19)
#define ICC_PMR_EL1_SHIFT 0
#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
#define ICC_BPR0_EL1_SHIFT 0
diff --git a/include/linux/irqchip/irq-partition-percpu.h b/include/linux/irqchip/irq-partition-percpu.h
index a783ddb58444..2f6ae7551748 100644
--- a/include/linux/irqchip/irq-partition-percpu.h
+++ b/include/linux/irqchip/irq-partition-percpu.h
@@ -4,6 +4,9 @@
* Author: Marc Zyngier <marc.zyngier@arm.com>
*/
+#ifndef __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H
+#define __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H
+
#include <linux/fwnode.h>
#include <linux/cpumask.h>
#include <linux/irqdomain.h>
@@ -46,3 +49,5 @@ struct irq_domain *partition_get_domain(struct partition_desc *dsc)
return NULL;
}
#endif
+
+#endif /* __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H */
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 07ec8b390161..583e7abd07f9 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -220,7 +220,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
#ifdef CONFIG_IRQ_DOMAIN
struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
- const char *name, void *data);
+ const char *name, phys_addr_t *pa);
enum {
IRQCHIP_FWNODE_REAL,
@@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id)
NULL);
}
-static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
{
- return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data);
+ return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, pa);
}
void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index b9b1bc5f9669..f0b809258ed3 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -216,6 +216,29 @@ extern int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map,
void **addr, unsigned long *sz);
#endif /* CONFIG_KEXEC_FILE */
+#ifdef CONFIG_KEXEC_ELF
+struct kexec_elf_info {
+ /*
+ * Where the ELF binary contents are kept.
+ * Memory managed by the user of the struct.
+ */
+ const char *buffer;
+
+ const struct elfhdr *ehdr;
+ const struct elf_phdr *proghdrs;
+};
+
+int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr,
+ struct kexec_elf_info *elf_info);
+
+int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
+ struct kexec_elf_info *elf_info,
+ struct kexec_buf *kbuf,
+ unsigned long *lowest_load_addr);
+
+void kexec_free_elf_info(struct kexec_elf_info *elf_info);
+int kexec_elf_probe(const char *buf, unsigned long len);
+#endif
struct kimage {
kimage_entry_t head;
kimage_entry_t *entry;
diff --git a/include/linux/key.h b/include/linux/key.h
index 91f391cd272e..50028338a4cc 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -94,11 +94,11 @@ struct keyring_index_key {
union {
struct {
#ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */
- u8 desc_len;
- char desc[sizeof(long) - 1]; /* First few chars of description */
+ u16 desc_len;
+ char desc[sizeof(long) - 2]; /* First few chars of description */
#else
- char desc[sizeof(long) - 1]; /* First few chars of description */
- u8 desc_len;
+ char desc[sizeof(long) - 2]; /* First few chars of description */
+ u16 desc_len;
#endif
};
unsigned long x;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 5c5b5867024c..fcb46b3374c6 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -861,8 +861,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
-bool kvm_arch_has_vcpu_debugfs(void);
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#endif
int kvm_arch_hardware_enable(void);
void kvm_arch_hardware_disable(void);
@@ -872,6 +873,7 @@ int kvm_arch_check_processor_compat(void);
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
#ifndef __KVM_HAVE_ARCH_VM_ALLOC
/*
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 0b0d7259276d..b8a835fd611b 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -66,10 +66,7 @@ struct lock_class_key {
extern struct lock_class_key __lockdep_no_validate__;
-struct lock_trace {
- unsigned int nr_entries;
- unsigned int offset;
-};
+struct lock_trace;
#define LOCKSTAT_POINTS 4
@@ -97,7 +94,7 @@ struct lock_class {
*/
struct list_head locks_after, locks_before;
- struct lockdep_subclass_key *key;
+ const struct lockdep_subclass_key *key;
unsigned int subclass;
unsigned int dep_gen_id;
@@ -105,7 +102,7 @@ struct lock_class {
* IRQ/softirq usage tracking bits:
*/
unsigned long usage_mask;
- struct lock_trace usage_traces[XXX_LOCK_USAGE_STATES];
+ const struct lock_trace *usage_traces[XXX_LOCK_USAGE_STATES];
/*
* Generation counter, when doing certain classes of graph walking,
@@ -193,7 +190,7 @@ struct lock_list {
struct list_head entry;
struct lock_class *class;
struct lock_class *links_to;
- struct lock_trace trace;
+ const struct lock_trace *trace;
int distance;
/*
diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
index cbd9d8495690..88e1e6304a71 100644
--- a/include/linux/logic_pio.h
+++ b/include/linux/logic_pio.h
@@ -117,6 +117,7 @@ struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode);
unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
resource_size_t hw_addr, resource_size_t size);
int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+void logic_pio_unregister_range(struct logic_pio_hwaddr *range);
resource_size_t logic_pio_to_hwaddr(unsigned long pio);
unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 44c41462be33..2cd4359cb38c 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -668,6 +668,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
int val);
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);
static inline void mod_lruvec_state(struct lruvec *lruvec,
enum node_stat_item idx, int val)
@@ -1072,6 +1073,14 @@ static inline void mod_lruvec_page_state(struct page *page,
mod_node_page_state(page_pgdat(page), idx, val);
}
+static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx,
+ int val)
+{
+ struct page *page = virt_to_head_page(p);
+
+ __mod_node_page_state(page_pgdat(page), idx, val);
+}
+
static inline
unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
gfp_t gfp_mask,
@@ -1159,6 +1168,16 @@ static inline void __dec_lruvec_page_state(struct page *page,
__mod_lruvec_page_state(page, idx, -1);
}
+static inline void __inc_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+ __mod_lruvec_slab_state(p, idx, 1);
+}
+
+static inline void __dec_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+ __mod_lruvec_slab_state(p, idx, -1);
+}
+
/* idx can be of type enum memcg_stat_item or node_stat_item */
static inline void inc_memcg_state(struct mem_cgroup *memcg,
int idx)
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 5228c62af416..bac395f1d00a 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -139,6 +139,8 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
struct mempolicy *get_task_policy(struct task_struct *p);
struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
unsigned long addr);
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+ unsigned long addr);
bool vma_policy_mof(struct vm_area_struct *vma);
extern void numa_default_policy(void);
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index ce9839c8bc1a..c2f056b5766d 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -446,11 +446,11 @@ enum {
};
enum {
- MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x20,
+ MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x1,
};
enum {
- MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x20,
+ MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x1,
};
enum {
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index 04a569568eac..f049af3f3cd8 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -220,6 +220,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler,
struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
void mlx5_fc_query_cached(struct mlx5_fc *counter,
u64 *bytes, u64 *packets, u64 *lastuse);
int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index b3d5752657d9..b8b570c30b5e 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -5975,10 +5975,12 @@ struct mlx5_ifc_modify_cq_in_bits {
struct mlx5_ifc_cqc_bits cq_context;
- u8 reserved_at_280[0x40];
+ u8 reserved_at_280[0x60];
u8 cq_umem_valid[0x1];
- u8 reserved_at_2c1[0x5bf];
+ u8 reserved_at_2e1[0x1f];
+
+ u8 reserved_at_300[0x580];
u8 pas[0][0x40];
};
@@ -10052,9 +10054,8 @@ struct mlx5_ifc_tls_static_params_bits {
};
struct mlx5_ifc_tls_progress_params_bits {
- u8 valid[0x1];
- u8 reserved_at_1[0x7];
- u8 pd[0x18];
+ u8 reserved_at_0[0x8];
+ u8 tisn[0x18];
u8 next_record_tcp_sn[0x20];
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 3a37a89eb7a7..6a7a1083b6fb 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -159,7 +159,16 @@ struct page {
/** @pgmap: Points to the hosting device page map. */
struct dev_pagemap *pgmap;
void *zone_device_data;
- unsigned long _zd_pad_1; /* uses mapping */
+ /*
+ * ZONE_DEVICE private pages are counted as being
+ * mapped so the next 3 words hold the mapping, index,
+ * and private fields from the source anonymous or
+ * page cache page while the page is migrated to device
+ * private memory.
+ * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
+ * use the mapping, index, and private fields when
+ * pmem backed DAX files are mapped.
+ */
};
/** @rcu_head: You can use this to free a page by RCU. */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d77d717c620c..3f38c30d2f13 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -215,8 +215,9 @@ enum node_stat_item {
NR_INACTIVE_FILE, /* " " " " " */
NR_ACTIVE_FILE, /* " " " " " */
NR_UNEVICTABLE, /* " " " " " */
- NR_SLAB_RECLAIMABLE,
- NR_SLAB_UNRECLAIMABLE,
+ NR_SLAB_RECLAIMABLE, /* Please do not reorder this item */
+ NR_SLAB_UNRECLAIMABLE, /* and this one without looking at
+ * memcg_flush_percpu_vmstats() first. */
NR_ISOLATED_ANON, /* Temporary isolated pages from anon lru */
NR_ISOLATED_FILE, /* Temporary isolated pages from file lru */
WORKINGSET_NODES,
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index b2c1648f7e5d..5714fd35a83c 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -814,6 +814,7 @@ struct tee_client_device_id {
/**
* struct wmi_device_id - WMI device identifier
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
+ * @context: pointer to driver specific data
*/
struct wmi_device_id {
const char guid_string[UUID_STRING_LEN+1];
diff --git a/include/linux/moxtet.h b/include/linux/moxtet.h
new file mode 100644
index 000000000000..490db6886dcc
--- /dev/null
+++ b/include/linux/moxtet.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Turris Mox module configuration bus driver
+ *
+ * Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
+ */
+
+#ifndef __LINUX_MOXTET_H
+#define __LINUX_MOXTET_H
+
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mutex.h>
+
+#define TURRIS_MOX_MAX_MODULES 10
+
+enum turris_mox_cpu_module_id {
+ TURRIS_MOX_CPU_ID_EMMC = 0x00,
+ TURRIS_MOX_CPU_ID_SD = 0x10,
+};
+
+enum turris_mox_module_id {
+ TURRIS_MOX_MODULE_FIRST = 0x01,
+
+ TURRIS_MOX_MODULE_SFP = 0x01,
+ TURRIS_MOX_MODULE_PCI = 0x02,
+ TURRIS_MOX_MODULE_TOPAZ = 0x03,
+ TURRIS_MOX_MODULE_PERIDOT = 0x04,
+ TURRIS_MOX_MODULE_USB3 = 0x05,
+ TURRIS_MOX_MODULE_PCI_BRIDGE = 0x06,
+
+ TURRIS_MOX_MODULE_LAST = 0x06,
+};
+
+#define MOXTET_NIRQS 16
+
+extern struct bus_type moxtet_type;
+
+struct moxtet {
+ struct device *dev;
+ struct mutex lock;
+ u8 modules[TURRIS_MOX_MAX_MODULES];
+ int count;
+ u8 tx[TURRIS_MOX_MAX_MODULES];
+ int dev_irq;
+ struct {
+ struct irq_domain *domain;
+ struct irq_chip chip;
+ unsigned long masked, exists;
+ struct moxtet_irqpos {
+ u8 idx;
+ u8 bit;
+ } position[MOXTET_NIRQS];
+ } irq;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_root;
+#endif
+};
+
+struct moxtet_driver {
+ const enum turris_mox_module_id *id_table;
+ struct device_driver driver;
+};
+
+static inline struct moxtet_driver *
+to_moxtet_driver(struct device_driver *drv)
+{
+ if (!drv)
+ return NULL;
+ return container_of(drv, struct moxtet_driver, driver);
+}
+
+extern int __moxtet_register_driver(struct module *owner,
+ struct moxtet_driver *mdrv);
+
+static inline void moxtet_unregister_driver(struct moxtet_driver *mdrv)
+{
+ if (mdrv)
+ driver_unregister(&mdrv->driver);
+}
+
+#define moxtet_register_driver(driver) \
+ __moxtet_register_driver(THIS_MODULE, driver)
+
+#define module_moxtet_driver(__moxtet_driver) \
+ module_driver(__moxtet_driver, moxtet_register_driver, \
+ moxtet_unregister_driver)
+
+struct moxtet_device {
+ struct device dev;
+ struct moxtet *moxtet;
+ enum turris_mox_module_id id;
+ unsigned int idx;
+};
+
+extern int moxtet_device_read(struct device *dev);
+extern int moxtet_device_write(struct device *dev, u8 val);
+extern int moxtet_device_written(struct device *dev);
+
+static inline struct moxtet_device *
+to_moxtet_device(struct device *dev)
+{
+ if (!dev)
+ return NULL;
+ return container_of(dev, struct moxtet_device, dev);
+}
+
+#endif /* __LINUX_MOXTET_H */
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index dcd03fee6e01..aca8f36dfac9 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -66,16 +66,6 @@ struct mutex {
};
/*
- * Internal helper function; C doesn't allow us to hide it :/
- *
- * DO NOT USE (outside of mutex code).
- */
-static inline struct task_struct *__mutex_owner(struct mutex *lock)
-{
- return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07);
-}
-
-/*
* This is the control structure for tasks blocked on mutex,
* which resides on the blocked task's kernel stack:
*/
@@ -144,10 +134,7 @@ extern void __mutex_init(struct mutex *lock, const char *name,
*
* Returns true if the mutex is locked, false if unlocked.
*/
-static inline bool mutex_is_locked(struct mutex *lock)
-{
- return __mutex_owner(lock) != NULL;
-}
+extern bool mutex_is_locked(struct mutex *lock);
/*
* See kernel/locking/mutex.c for detailed documentation of these APIs.
@@ -220,13 +207,7 @@ enum mutex_trylock_recursive_enum {
* - MUTEX_TRYLOCK_SUCCESS - lock acquired,
* - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock.
*/
-static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
-mutex_trylock_recursive(struct mutex *lock)
-{
- if (unlikely(__mutex_owner(lock) == current))
- return MUTEX_TRYLOCK_RECURSIVE;
-
- return mutex_trylock(lock);
-}
+extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
+mutex_trylock_recursive(struct mutex *lock);
#endif /* __LINUX_MUTEX_H */
diff --git a/include/linux/netfilter/nf_conntrack_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h
index 7a6871ac8784..74c6f9241944 100644
--- a/include/linux/netfilter/nf_conntrack_h323_types.h
+++ b/include/linux/netfilter/nf_conntrack_h323_types.h
@@ -4,6 +4,9 @@
* Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*/
+#ifndef _NF_CONNTRACK_H323_TYPES_H
+#define _NF_CONNTRACK_H323_TYPES_H
+
typedef struct TransportAddress_ipAddress { /* SEQUENCE */
int options; /* No use */
unsigned int ip;
@@ -931,3 +934,5 @@ typedef struct RasMessage { /* CHOICE */
InfoRequestResponse infoRequestResponse;
};
} RasMessage;
+
+#endif /* _NF_CONNTRACK_H323_TYPES_H */
diff --git a/include/linux/of.h b/include/linux/of.h
index 0cf857012f11..844f89e1b039 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1164,7 +1164,7 @@ static inline int of_property_read_string_index(const struct device_node *np,
}
/**
- * of_property_read_bool - Findfrom a property
+ * of_property_read_bool - Find a property
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
*
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index f9737dea9d1f..16967390a3fe 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -61,10 +61,6 @@ static inline int of_mm_gpiochip_add(struct device_node *np,
}
extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
-extern int of_gpio_simple_xlate(struct gpio_chip *gc,
- const struct of_phandle_args *gpiospec,
- u32 *flags);
-
#else /* CONFIG_OF_GPIO */
/* Drivers may not strictly depend on the GPIO support, so let them link. */
@@ -77,13 +73,6 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
return -ENOSYS;
}
-static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
- const struct of_phandle_args *gpiospec,
- u32 *flags)
-{
- return -ENOSYS;
-}
-
#endif /* CONFIG_OF_GPIO */
/**
diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h
index 153bf25b4df3..2c32ca09df02 100644
--- a/include/linux/omap-iommu.h
+++ b/include/linux/omap-iommu.h
@@ -10,12 +10,27 @@
#ifndef _OMAP_IOMMU_H_
#define _OMAP_IOMMU_H_
+struct iommu_domain;
+
#ifdef CONFIG_OMAP_IOMMU
extern void omap_iommu_save_ctx(struct device *dev);
extern void omap_iommu_restore_ctx(struct device *dev);
+
+int omap_iommu_domain_deactivate(struct iommu_domain *domain);
+int omap_iommu_domain_activate(struct iommu_domain *domain);
#else
static inline void omap_iommu_save_ctx(struct device *dev) {}
static inline void omap_iommu_restore_ctx(struct device *dev) {}
+
+static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain)
+{
+ return -ENODEV;
+}
+
+static inline int omap_iommu_domain_activate(struct iommu_domain *domain)
+{
+ return -ENODEV;
+}
#endif
#endif
diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
index 1dda31825ec4..71283739ffd2 100644
--- a/include/linux/page-flags-layout.h
+++ b/include/linux/page-flags-layout.h
@@ -32,6 +32,7 @@
#endif /* CONFIG_SPARSEMEM */
+#ifndef BUILD_VDSO32_64
/*
* page->flags layout:
*
@@ -76,20 +77,22 @@
#define LAST_CPUPID_SHIFT 0
#endif
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#ifdef CONFIG_KASAN_SW_TAGS
+#define KASAN_TAG_WIDTH 8
+#else
+#define KASAN_TAG_WIDTH 0
+#endif
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \
+ <= BITS_PER_LONG - NR_PAGEFLAGS
#define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT
#else
#define LAST_CPUPID_WIDTH 0
#endif
-#ifdef CONFIG_KASAN_SW_TAGS
-#define KASAN_TAG_WIDTH 8
#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \
> BITS_PER_LONG - NR_PAGEFLAGS
-#error "KASAN: not enough bits in page flags for tag"
-#endif
-#else
-#define KASAN_TAG_WIDTH 0
+#error "Not enough bits in page flags"
#endif
/*
@@ -104,4 +107,5 @@
#define LAST_CPUPID_NOT_IN_PAGE_FLAGS
#endif
+#endif
#endif /* _LINUX_PAGE_FLAGS_LAYOUT */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index b848517da64c..f91cb8898ff0 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -152,6 +152,8 @@ enum pageflags {
PG_savepinned = PG_dirty,
/* Has a grant mapping of another (foreign) domain's page. */
PG_foreign = PG_owner_priv_1,
+ /* Remapped by swiotlb-xen. */
+ PG_xen_remapped = PG_owner_priv_1,
/* SLOB */
PG_slob_free = PG_private,
@@ -329,6 +331,8 @@ PAGEFLAG(Pinned, pinned, PF_NO_COMPOUND)
TESTSCFLAG(Pinned, pinned, PF_NO_COMPOUND)
PAGEFLAG(SavePinned, savepinned, PF_NO_COMPOUND);
PAGEFLAG(Foreign, foreign, PF_NO_COMPOUND);
+PAGEFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND)
+ TESTCLEARFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND)
PAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
__CLEARPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9e700d9f9f28..82e4cd1b7ac3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1567,8 +1567,10 @@ extern bool pcie_ports_native;
#ifdef CONFIG_PCIEASPM
bool pcie_aspm_support_enabled(void);
+bool pcie_aspm_enabled(struct pci_dev *pdev);
#else
static inline bool pcie_aspm_support_enabled(void) { return false; }
+static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
#endif
#ifdef CONFIG_PCIEAER
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c842735a4f45..24486f405f12 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -548,6 +548,7 @@
#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F3 0x1493
+#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F3 0x1443
#define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
@@ -1070,7 +1071,6 @@
#define PCI_VENDOR_ID_SGI 0x10a9
#define PCI_DEVICE_ID_SGI_IOC3 0x0003
#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002
-#define PCI_DEVICE_ID_SGI_IOC4 0x100a
#define PCI_VENDOR_ID_WINBOND 0x10ad
#define PCI_DEVICE_ID_WINBOND_82C105 0x0105
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e8ad3c590a23..61448c19a132 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -246,6 +246,7 @@ struct perf_event;
#define PERF_PMU_CAP_ITRACE 0x20
#define PERF_PMU_CAP_HETEROGENEOUS_CPUS 0x40
#define PERF_PMU_CAP_NO_EXCLUDE 0x80
+#define PERF_PMU_CAP_AUX_OUTPUT 0x100
/**
* struct pmu - generic performance monitoring unit
@@ -447,6 +448,16 @@ struct pmu {
/* optional */
/*
+ * Check if event can be used for aux_output purposes for
+ * events of this PMU.
+ *
+ * Runs from perf_event_open(). Should return 0 for "no match"
+ * or non-zero for "match".
+ */
+ int (*aux_output_match) (struct perf_event *event);
+ /* optional */
+
+ /*
* Filter events for PMU-specific reasons.
*/
int (*filter_match) (struct perf_event *event); /* optional */
@@ -681,6 +692,9 @@ struct perf_event {
struct perf_addr_filter_range *addr_filter_ranges;
unsigned long addr_filters_gen;
+ /* for aux_output events */
+ struct perf_event *aux_event;
+
void (*destroy)(struct perf_event *);
struct rcu_head rcu_head;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 462b90b73f93..2fb9c8ffaf10 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1107,6 +1107,7 @@ int genphy_c45_an_disable_aneg(struct phy_device *phydev);
int genphy_c45_read_mdix(struct phy_device *phydev);
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
int genphy_c45_read_status(struct phy_device *phydev);
+int genphy_c45_config_aneg(struct phy_device *phydev);
/* The gen10g_* functions are the old Clause 45 stub */
int gen10g_config_aneg(struct phy_device *phydev);
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
index 1e5d86ebdaeb..52bc8e487ef7 100644
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -11,6 +11,7 @@ struct fixed_phy_status {
};
struct device_node;
+struct gpio_desc;
#if IS_ENABLED(CONFIG_FIXED_PHY)
extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier);
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 2a83e434db9d..9645b1194c98 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -72,6 +72,10 @@ extern struct pid init_struct_pid;
extern const struct file_operations pidfd_fops;
+struct file;
+
+extern struct pid *pidfd_pid(const struct file *file);
+
static inline struct pid *get_pid(struct pid *pid)
{
if (pid)
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/include/linux/platform_data/dma-iop32x.h
index bcedbab90ac0..ac83cff89549 100644
--- a/arch/arm/include/asm/hardware/iop_adma.h
+++ b/include/linux/platform_data/dma-iop32x.h
@@ -17,6 +17,10 @@
#endif
#define iop_paranoia(x) BUG_ON(IOP_PARANOIA && (x))
+#define DMA0_ID 0
+#define DMA1_ID 1
+#define AAU_ID 2
+
/**
* struct iop_adma_device - internal representation of an ADMA device
* @pdev: Platform device
diff --git a/include/linux/platform_data/gpio-htc-egpio.h b/include/linux/platform_data/gpio-htc-egpio.h
index 9a3e78082883..eaefba0b6465 100644
--- a/include/linux/platform_data/gpio-htc-egpio.h
+++ b/include/linux/platform_data/gpio-htc-egpio.h
@@ -50,7 +50,4 @@ struct htc_egpio_platform_data {
int num_chips;
};
-/* Determine the wakeup irq, to be called during early resume */
-extern int htc_egpio_get_wakeup_irq(struct device *dev);
-
#endif
diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h
index 44d913a7580c..8474a0208b34 100644
--- a/include/linux/platform_data/iommu-omap.h
+++ b/include/linux/platform_data/iommu-omap.h
@@ -13,4 +13,8 @@ struct iommu_platform_data {
const char *reset_name;
int (*assert_reset)(struct platform_device *pdev, const char *name);
int (*deassert_reset)(struct platform_device *pdev, const char *name);
+ int (*device_enable)(struct platform_device *pdev);
+ int (*device_idle)(struct platform_device *pdev);
+ int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request,
+ u8 *pwrst);
};
diff --git a/include/linux/platform_data/spi-nuc900.h b/include/linux/platform_data/spi-nuc900.h
deleted file mode 100644
index ca3510877000..000000000000
--- a/include/linux/platform_data/spi-nuc900.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#ifndef __SPI_NUC900_H
-#define __SPI_NUC900_H
-
-extern void mfp_set_groupg(struct device *dev, const char *subname);
-
-struct nuc900_spi_info {
- unsigned int num_cs;
- unsigned int lsb;
- unsigned int txneg;
- unsigned int rxneg;
- unsigned int divider;
- unsigned int sleep;
- unsigned int txnum;
- unsigned int txbitlen;
- int bus_num;
-};
-
-struct nuc900_spi_chip {
- unsigned char bits_per_word;
-};
-
-#endif /* __SPI_NUC900_H */
diff --git a/include/linux/platform_data/video-nuc900fb.h b/include/linux/platform_data/video-nuc900fb.h
deleted file mode 100644
index 3da504460c91..000000000000
--- a/include/linux/platform_data/video-nuc900fb.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* linux/include/asm/arch-nuc900/fb.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Changelog:
- *
- * 2008/08/26 vincen.zswan modify this file for LCD.
- */
-
-#ifndef __ASM_ARM_FB_H
-#define __ASM_ARM_FB_H
-
-
-
-/* LCD Controller Hardware Desc */
-struct nuc900fb_hw {
- unsigned int lcd_dccs;
- unsigned int lcd_device_ctrl;
- unsigned int lcd_mpulcd_cmd;
- unsigned int lcd_int_cs;
- unsigned int lcd_crtc_size;
- unsigned int lcd_crtc_dend;
- unsigned int lcd_crtc_hr;
- unsigned int lcd_crtc_hsync;
- unsigned int lcd_crtc_vr;
- unsigned int lcd_va_baddr0;
- unsigned int lcd_va_baddr1;
- unsigned int lcd_va_fbctrl;
- unsigned int lcd_va_scale;
- unsigned int lcd_va_test;
- unsigned int lcd_va_win;
- unsigned int lcd_va_stuff;
-};
-
-/* LCD Display Description */
-struct nuc900fb_display {
- /* LCD Image type */
- unsigned type;
-
- /* LCD Screen Size */
- unsigned short width;
- unsigned short height;
-
- /* LCD Screen Info */
- unsigned short xres;
- unsigned short yres;
- unsigned short bpp;
-
- unsigned long pixclock;
- unsigned short left_margin;
- unsigned short right_margin;
- unsigned short hsync_len;
- unsigned short upper_margin;
- unsigned short lower_margin;
- unsigned short vsync_len;
-
- /* hardware special register value */
- unsigned int dccs;
- unsigned int devctl;
- unsigned int fbctrl;
- unsigned int scale;
-};
-
-struct nuc900fb_mach_info {
- struct nuc900fb_display *displays;
- unsigned num_displays;
- unsigned default_display;
- /* GPIO Setting Info */
- unsigned gpio_dir;
- unsigned gpio_dir_mask;
- unsigned gpio_data;
- unsigned gpio_data_mask;
-};
-
-extern void __init nuc900_fb_set_platdata(struct nuc900fb_mach_info *);
-
-#endif /* __ASM_ARM_FB_H */
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 4802cd2c7309..60249e22e844 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -12,7 +12,7 @@
#define ASUS_WMI_METHODID_GPID 0x44495047 /* Get Panel ID?? (Resol) */
#define ASUS_WMI_METHODID_QMOD 0x444F4D51 /* Quiet MODe */
#define ASUS_WMI_METHODID_SPLV 0x4C425053 /* Set Panel Light Value */
-#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* FaN? */
+#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* Atk Generic FuNction */
#define ASUS_WMI_METHODID_SFUN 0x4E554653 /* FUNCtionalities */
#define ASUS_WMI_METHODID_SDSP 0x50534453 /* Set DiSPlay output */
#define ASUS_WMI_METHODID_GDSP 0x50534447 /* Get DiSPlay output */
@@ -72,7 +72,8 @@
/* Fan, Thermal */
#define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
-#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012
+#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */
+#define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013
/* Power */
#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
@@ -80,6 +81,9 @@
/* Deep S3 / Resume on LID open */
#define ASUS_WMI_DEVID_LID_RESUME 0x00120031
+/* Maximum charging percentage */
+#define ASUS_WMI_DEVID_RSOC 0x00120057
+
/* DSTS masks */
#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index dd92b1a93919..bbb68dba37cc 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -182,7 +182,7 @@ do { \
#define preemptible() (preempt_count() == 0 && !irqs_disabled())
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
#define preempt_enable() \
do { \
barrier(); \
@@ -203,7 +203,7 @@ do { \
__preempt_schedule(); \
} while (0)
-#else /* !CONFIG_PREEMPT */
+#else /* !CONFIG_PREEMPTION */
#define preempt_enable() \
do { \
barrier(); \
@@ -217,7 +217,7 @@ do { \
} while (0)
#define preempt_check_resched() do { } while (0)
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
#define preempt_disable_notrace() \
do { \
diff --git a/include/linux/psci.h b/include/linux/psci.h
index a8a15613c157..e2bacc6fd2f2 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -15,8 +15,8 @@
bool psci_tos_resident_on(int cpu);
-int psci_cpu_init_idle(unsigned int cpu);
-int psci_cpu_suspend_enter(unsigned long index);
+int psci_cpu_suspend_enter(u32 state);
+bool psci_power_state_is_valid(u32 state);
enum psci_conduit {
PSCI_CONDUIT_NONE,
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 3f12cc77fb58..2d5eff506e13 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -49,8 +49,9 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
extern int qcom_scm_pas_shutdown(u32 peripheral);
extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
- unsigned int *src, struct qcom_scm_vmperm *newvm,
- int dest_cnt);
+ unsigned int *src,
+ const struct qcom_scm_vmperm *newvm,
+ unsigned int dest_cnt);
extern void qcom_scm_cpu_power_down(u32 flags);
extern u32 qcom_scm_get_version(void);
extern int qcom_scm_set_remote_state(u32 state, u32 id);
@@ -87,8 +88,8 @@ qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; }
static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; }
static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
unsigned int *src,
- struct qcom_scm_vmperm *newvm,
- int dest_cnt) { return -ENODEV; }
+ const struct qcom_scm_vmperm *newvm,
+ unsigned int dest_cnt) { return -ENODEV; }
static inline void qcom_scm_cpu_power_down(u32 flags) {}
static inline u32 qcom_scm_get_version(void) { return 0; }
static inline u32
diff --git a/include/linux/random.h b/include/linux/random.h
index 1f7dced2bba6..f189c927fdea 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -19,6 +19,7 @@ struct random_ready_callback {
};
extern void add_device_randomness(const void *, unsigned int);
+extern void add_bootloader_randomness(const void *, unsigned int);
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
static inline void add_latent_entropy(void)
diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h
index 87404cb015f1..646759042333 100644
--- a/include/linux/rcu_segcblist.h
+++ b/include/linux/rcu_segcblist.h
@@ -14,6 +14,9 @@
#ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H
#define __INCLUDE_LINUX_RCU_SEGCBLIST_H
+#include <linux/types.h>
+#include <linux/atomic.h>
+
/* Simple unsegmented callback lists. */
struct rcu_cblist {
struct rcu_head *head;
@@ -65,8 +68,14 @@ struct rcu_segcblist {
struct rcu_head *head;
struct rcu_head **tails[RCU_CBLIST_NSEGS];
unsigned long gp_seq[RCU_CBLIST_NSEGS];
+#ifdef CONFIG_RCU_NOCB_CPU
+ atomic_long_t len;
+#else
long len;
+#endif
long len_lazy;
+ u8 enabled;
+ u8 offloaded;
};
#define RCU_SEGCBLIST_INITIALIZER(n) \
diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h
index 9b83865d24f9..0027d4c8087c 100644
--- a/include/linux/rcu_sync.h
+++ b/include/linux/rcu_sync.h
@@ -31,9 +31,7 @@ struct rcu_sync {
*/
static inline bool rcu_sync_is_idle(struct rcu_sync *rsp)
{
- RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&
- !rcu_read_lock_bh_held() &&
- !rcu_read_lock_sched_held(),
+ RCU_LOCKDEP_WARN(!rcu_read_lock_any_held(),
"suspicious rcu_sync_is_idle() usage");
return !READ_ONCE(rsp->gp_state); /* GP_IDLE */
}
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index e91ec9ddcd30..4158b7212936 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -41,6 +41,24 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
#define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next)))
/*
+ * Check during list traversal that we are within an RCU reader
+ */
+
+#define check_arg_count_one(dummy)
+
+#ifdef CONFIG_PROVE_RCU_LIST
+#define __list_check_rcu(dummy, cond, extra...) \
+ ({ \
+ check_arg_count_one(extra); \
+ RCU_LOCKDEP_WARN(!cond && !rcu_read_lock_any_held(), \
+ "RCU-list traversed in non-reader section!"); \
+ })
+#else
+#define __list_check_rcu(dummy, cond, extra...) \
+ ({ check_arg_count_one(extra); })
+#endif
+
+/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
@@ -343,14 +361,16 @@ static inline void list_splice_tail_init_rcu(struct list_head *list,
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
+ * @cond: optional lockdep expression if called from non-RCU protection.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
-#define list_for_each_entry_rcu(pos, head, member) \
- for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
+#define list_for_each_entry_rcu(pos, head, member, cond...) \
+ for (__list_check_rcu(dummy, ## cond, 0), \
+ pos = list_entry_rcu((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
/**
@@ -616,13 +636,15 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n,
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
+ * @cond: optional lockdep expression if called from non-RCU protection.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
-#define hlist_for_each_entry_rcu(pos, head, member) \
- for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
+#define hlist_for_each_entry_rcu(pos, head, member, cond...) \
+ for (__list_check_rcu(dummy, ## cond, 0), \
+ pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
@@ -642,10 +664,10 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n,
* not do any RCU debugging or tracing.
*/
#define hlist_for_each_entry_rcu_notrace(pos, head, member) \
- for (pos = hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\
+ for (pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
- pos = hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\
+ pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
/**
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 8f7167478c1d..75a2eded7aa2 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -221,6 +221,7 @@ int debug_lockdep_rcu_enabled(void);
int rcu_read_lock_held(void);
int rcu_read_lock_bh_held(void);
int rcu_read_lock_sched_held(void);
+int rcu_read_lock_any_held(void);
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
@@ -241,6 +242,12 @@ static inline int rcu_read_lock_sched_held(void)
{
return !preemptible();
}
+
+static inline int rcu_read_lock_any_held(void)
+{
+ return !preemptible();
+}
+
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
#ifdef CONFIG_PROVE_RCU
@@ -476,7 +483,7 @@ do { \
* The no-tracing version of rcu_dereference_raw() must not call
* rcu_read_lock_held().
*/
-#define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu)
+#define rcu_dereference_raw_check(p) __rcu_dereference_check((p), 1, __rcu)
/**
* rcu_dereference_protected() - fetch RCU pointer when updates prevented
@@ -578,7 +585,7 @@ do { \
*
* In non-preemptible RCU implementations (TREE_RCU and TINY_RCU),
* it is illegal to block while in an RCU read-side critical section.
- * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPT
+ * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPTION
* kernel builds, RCU read-side critical sections may be preempted,
* but explicit blocking is illegal. Finally, in preemptible RCU
* implementations in real-time (with -rt patchset) kernel builds, RCU
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 8e727f57d814..9bf1dfe7781f 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -12,7 +12,7 @@
#ifndef __LINUX_TINY_H
#define __LINUX_TINY_H
-#include <linux/ktime.h>
+#include <asm/param.h> /* for HZ */
/* Never flag non-existent other CPUs! */
static inline bool rcu_eqs_special_set(int cpu) { return false; }
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 735601ac27d3..18b1ed9864b0 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -53,7 +53,7 @@ void rcu_scheduler_starting(void);
extern int rcu_scheduler_active __read_mostly;
void rcu_end_inkernel_boot(void);
bool rcu_is_watching(void);
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
void rcu_all_qs(void);
#endif
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 815983419375..337a46391527 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -281,6 +281,12 @@ void devm_regulator_unregister_notifier(struct regulator *regulator,
void *regulator_get_drvdata(struct regulator *regulator);
void regulator_set_drvdata(struct regulator *regulator, void *data);
+/* misc helpers */
+
+void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers,
+ const char *const *supply_names,
+ unsigned int num_supplies);
+
#else
/*
@@ -580,6 +586,13 @@ static inline int regulator_list_voltage(struct regulator *regulator, unsigned s
return -EINVAL;
}
+static inline void
+regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers,
+ const char *const *supply_names,
+ unsigned int num_supplies)
+{
+}
+
#endif
static inline int regulator_set_voltage_triplet(struct regulator *regulator,
diff --git a/include/linux/regulator/mt6358-regulator.h b/include/linux/regulator/mt6358-regulator.h
new file mode 100644
index 000000000000..1cc304946d09
--- /dev/null
+++ b/include/linux/regulator/mt6358-regulator.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __LINUX_REGULATOR_MT6358_H
+#define __LINUX_REGULATOR_MT6358_H
+
+enum {
+ MT6358_ID_VDRAM1 = 0,
+ MT6358_ID_VCORE,
+ MT6358_ID_VPA,
+ MT6358_ID_VPROC11,
+ MT6358_ID_VPROC12,
+ MT6358_ID_VGPU,
+ MT6358_ID_VS2,
+ MT6358_ID_VMODEM,
+ MT6358_ID_VS1,
+ MT6358_ID_VDRAM2 = 9,
+ MT6358_ID_VSIM1,
+ MT6358_ID_VIBR,
+ MT6358_ID_VRF12,
+ MT6358_ID_VIO18,
+ MT6358_ID_VUSB,
+ MT6358_ID_VCAMIO,
+ MT6358_ID_VCAMD,
+ MT6358_ID_VCN18,
+ MT6358_ID_VFE28,
+ MT6358_ID_VSRAM_PROC11,
+ MT6358_ID_VCN28,
+ MT6358_ID_VSRAM_OTHERS,
+ MT6358_ID_VSRAM_GPU,
+ MT6358_ID_VXO22,
+ MT6358_ID_VEFUSE,
+ MT6358_ID_VAUX18,
+ MT6358_ID_VMCH,
+ MT6358_ID_VBIF28,
+ MT6358_ID_VSRAM_PROC12,
+ MT6358_ID_VCAMA1,
+ MT6358_ID_VEMC,
+ MT6358_ID_VIO28,
+ MT6358_ID_VA12,
+ MT6358_ID_VRF18,
+ MT6358_ID_VCN33_BT,
+ MT6358_ID_VCN33_WIFI,
+ MT6358_ID_VCAMA2,
+ MT6358_ID_VMC,
+ MT6358_ID_VLDO28,
+ MT6358_ID_VAUD28,
+ MT6358_ID_VSIM2,
+ MT6358_ID_RG_MAX,
+};
+
+#define MT6358_MAX_REGULATOR MT6358_ID_RG_MAX
+
+#endif /* __LINUX_REGULATOR_MT6358_H */
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 9d9c663987d8..00d6054687dd 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -45,6 +45,9 @@ struct rw_semaphore {
#endif
raw_spinlock_t wait_lock;
struct list_head wait_list;
+#ifdef CONFIG_DEBUG_RWSEMS
+ void *magic;
+#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
@@ -73,6 +76,12 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem)
# define __RWSEM_DEP_MAP_INIT(lockname)
#endif
+#ifdef CONFIG_DEBUG_RWSEMS
+# define __DEBUG_RWSEM_INITIALIZER(lockname) , .magic = &lockname
+#else
+# define __DEBUG_RWSEM_INITIALIZER(lockname)
+#endif
+
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
#define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED
#else
@@ -85,6 +94,7 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem)
.wait_list = LIST_HEAD_INIT((name).wait_list), \
.wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \
__RWSEM_OPT_INIT(name) \
+ __DEBUG_RWSEM_INITIALIZER(name) \
__RWSEM_DEP_MAP_INIT(name) }
#define DECLARE_RWSEM(name) \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8cc8e323093f..b75b28287005 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -276,6 +276,11 @@ enum uclamp_id {
UCLAMP_CNT
};
+#ifdef CONFIG_SMP
+extern struct root_domain def_root_domain;
+extern struct mutex sched_domains_mutex;
+#endif
+
struct sched_info {
#ifdef CONFIG_SCHED_INFO
/* Cumulative counters: */
@@ -1071,7 +1076,15 @@ struct task_struct {
u64 last_sum_exec_runtime;
struct callback_head numa_work;
- struct numa_group *numa_group;
+ /*
+ * This pointer is only modified for current in syscall and
+ * pagefault context (and for tasks being destroyed), so it can be read
+ * from any of the following contexts:
+ * - RCU read-side critical section
+ * - current->numa_group from everywhere
+ * - task's runqueue locked, task not running
+ */
+ struct numa_group __rcu *numa_group;
/*
* numa_faults is an array split into four regions:
@@ -1738,7 +1751,7 @@ static inline int test_tsk_need_resched(struct task_struct *tsk)
* value indicates whether a reschedule was done in fact.
* cond_resched_lock() will drop the spinlock before scheduling,
*/
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
extern int _cond_resched(void);
#else
static inline int _cond_resched(void) { return 0; }
@@ -1767,12 +1780,12 @@ static inline void cond_resched_rcu(void)
/*
* Does a critical section need to be broken due to another
- * task waiting?: (technically does not depend on CONFIG_PREEMPT,
+ * task waiting?: (technically does not depend on CONFIG_PREEMPTION,
* but a general need for low latency)
*/
static inline int spin_needbreak(spinlock_t *lock)
{
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
return spin_is_contended(lock);
#else
return 0;
diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
index 0cb034331cbb..1aff00b65f3c 100644
--- a/include/linux/sched/deadline.h
+++ b/include/linux/sched/deadline.h
@@ -24,3 +24,11 @@ static inline bool dl_time_before(u64 a, u64 b)
{
return (s64)(a - b) < 0;
}
+
+#ifdef CONFIG_SMP
+
+struct root_domain;
+extern void dl_add_task_root_domain(struct task_struct *p);
+extern void dl_clear_root_domain(struct root_domain *rd);
+
+#endif /* CONFIG_SMP */
diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/numa_balancing.h
index e7dd04a84ba8..3988762efe15 100644
--- a/include/linux/sched/numa_balancing.h
+++ b/include/linux/sched/numa_balancing.h
@@ -19,7 +19,7 @@
extern void task_numa_fault(int last_node, int node, int pages, int flags);
extern pid_t task_numa_group_id(struct task_struct *p);
extern void set_numabalancing_state(bool enabled);
-extern void task_numa_free(struct task_struct *p);
+extern void task_numa_free(struct task_struct *p, bool final);
extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page,
int src_nid, int dst_cpu);
#else
@@ -34,7 +34,7 @@ static inline pid_t task_numa_group_id(struct task_struct *p)
static inline void set_numabalancing_state(bool enabled)
{
}
-static inline void task_numa_free(struct task_struct *p)
+static inline void task_numa_free(struct task_struct *p, bool final)
{
}
static inline bool should_numa_migrate_memory(struct task_struct *p,
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 0497091e40c1..3d90ed8f75f0 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -105,7 +105,11 @@ extern void sched_exec(void);
#define sched_exec() {}
#endif
-#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
+static inline struct task_struct *get_task_struct(struct task_struct *t)
+{
+ refcount_inc(&t->usage);
+ return t;
+}
extern void __put_task_struct(struct task_struct *t);
diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
index 7863bb62d2ab..f341163fedc9 100644
--- a/include/linux/sched/topology.h
+++ b/include/linux/sched/topology.h
@@ -150,6 +150,10 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd)
return to_cpumask(sd->span);
}
+extern void partition_sched_domains_locked(int ndoms_new,
+ cpumask_var_t doms_new[],
+ struct sched_domain_attr *dattr_new);
+
extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
struct sched_domain_attr *dattr_new);
@@ -195,6 +199,12 @@ extern void set_sched_topology(struct sched_domain_topology_level *tl);
struct sched_domain_attr;
static inline void
+partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[],
+ struct sched_domain_attr *dattr_new)
+{
+}
+
+static inline void
partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
struct sched_domain_attr *dattr_new)
{
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 9ff2e9357e9a..881fea47c83d 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* SCMI Message Protocol driver header
*
@@ -71,7 +71,7 @@ struct scmi_clk_ops {
int (*rate_get)(const struct scmi_handle *handle, u32 clk_id,
u64 *rate);
int (*rate_set)(const struct scmi_handle *handle, u32 clk_id,
- u32 config, u64 rate);
+ u64 rate);
int (*enable)(const struct scmi_handle *handle, u32 clk_id);
int (*disable)(const struct scmi_handle *handle, u32 clk_id);
};
@@ -145,6 +145,8 @@ struct scmi_sensor_info {
u32 id;
u8 type;
s8 scale;
+ u8 num_trip_points;
+ bool async;
char name[SCMI_MAX_STR_SIZE];
};
@@ -167,9 +169,9 @@ enum scmi_sensor_class {
*
* @count_get: get the count of sensors provided by SCMI
* @info_get: get the information of the specified sensor
- * @configuration_set: control notifications on cross-over events for
+ * @trip_point_notify: control notifications on cross-over events for
* the trip-points
- * @trip_point_set: selects and configures a trip-point of interest
+ * @trip_point_config: selects and configures a trip-point of interest
* @reading_get: gets the current value of the sensor
*/
struct scmi_sensor_ops {
@@ -177,12 +179,32 @@ struct scmi_sensor_ops {
const struct scmi_sensor_info *(*info_get)
(const struct scmi_handle *handle, u32 sensor_id);
- int (*configuration_set)(const struct scmi_handle *handle,
- u32 sensor_id);
- int (*trip_point_set)(const struct scmi_handle *handle, u32 sensor_id,
- u8 trip_id, u64 trip_value);
+ int (*trip_point_notify)(const struct scmi_handle *handle,
+ u32 sensor_id, bool enable);
+ int (*trip_point_config)(const struct scmi_handle *handle,
+ u32 sensor_id, u8 trip_id, u64 trip_value);
int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id,
- bool async, u64 *value);
+ u64 *value);
+};
+
+/**
+ * struct scmi_reset_ops - represents the various operations provided
+ * by SCMI Reset Protocol
+ *
+ * @num_domains_get: get the count of reset domains provided by SCMI
+ * @name_get: gets the name of a reset domain
+ * @latency_get: gets the reset latency for the specified reset domain
+ * @reset: resets the specified reset domain
+ * @assert: explicitly assert reset signal of the specified reset domain
+ * @deassert: explicitly deassert reset signal of the specified reset domain
+ */
+struct scmi_reset_ops {
+ int (*num_domains_get)(const struct scmi_handle *handle);
+ char *(*name_get)(const struct scmi_handle *handle, u32 domain);
+ int (*latency_get)(const struct scmi_handle *handle, u32 domain);
+ int (*reset)(const struct scmi_handle *handle, u32 domain);
+ int (*assert)(const struct scmi_handle *handle, u32 domain);
+ int (*deassert)(const struct scmi_handle *handle, u32 domain);
};
/**
@@ -194,6 +216,7 @@ struct scmi_sensor_ops {
* @perf_ops: pointer to set of performance protocol operations
* @clk_ops: pointer to set of clock protocol operations
* @sensor_ops: pointer to set of sensor protocol operations
+ * @reset_ops: pointer to set of reset protocol operations
* @perf_priv: pointer to private data structure specific to performance
* protocol(for internal use only)
* @clk_priv: pointer to private data structure specific to clock
@@ -202,6 +225,8 @@ struct scmi_sensor_ops {
* protocol(for internal use only)
* @sensor_priv: pointer to private data structure specific to sensors
* protocol(for internal use only)
+ * @reset_priv: pointer to private data structure specific to reset
+ * protocol(for internal use only)
*/
struct scmi_handle {
struct device *dev;
@@ -210,11 +235,13 @@ struct scmi_handle {
struct scmi_clk_ops *clk_ops;
struct scmi_power_ops *power_ops;
struct scmi_sensor_ops *sensor_ops;
+ struct scmi_reset_ops *reset_ops;
/* for protocol internal use */
void *perf_priv;
void *clk_priv;
void *power_priv;
void *sensor_priv;
+ void *reset_priv;
};
enum scmi_std_protocol {
@@ -224,6 +251,7 @@ enum scmi_std_protocol {
SCMI_PROTOCOL_PERF = 0x13,
SCMI_PROTOCOL_CLOCK = 0x14,
SCMI_PROTOCOL_SENSOR = 0x15,
+ SCMI_PROTOCOL_RESET = 0x16,
};
struct scmi_device {
diff --git a/include/linux/signal.h b/include/linux/signal.h
index b5d99482d3fe..1a5f88316b08 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -282,6 +282,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
extern void exit_signals(struct task_struct *tsk);
extern void kernel_sigaction(int, __sighandler_t);
+#define SIG_KTHREAD ((__force __sighandler_t)2)
+#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3)
+
static inline void allow_signal(int sig)
{
/*
@@ -289,7 +292,17 @@ static inline void allow_signal(int sig)
* know it'll be handled, so that they don't get converted to
* SIGKILL or just silently dropped.
*/
- kernel_sigaction(sig, (__force __sighandler_t)2);
+ kernel_sigaction(sig, SIG_KTHREAD);
+}
+
+static inline void allow_kernel_signal(int sig)
+{
+ /*
+ * Kernel threads handle their own signals. Let the signal code
+ * know signals sent by the kernel will be handled, so that they
+ * don't get silently dropped.
+ */
+ kernel_sigaction(sig, SIG_KTHREAD_KERNEL);
}
static inline void disallow_signal(int sig)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d8af86d995d6..ba5583522d24 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1374,6 +1374,14 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
to->l4_hash = from->l4_hash;
};
+static inline void skb_copy_decrypted(struct sk_buff *to,
+ const struct sk_buff *from)
+{
+#ifdef CONFIG_TLS_DEVICE
+ to->decrypted = from->decrypted;
+#endif
+}
+
#ifdef NET_SKBUFF_DATA_USES_OFFSET
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
index 50ced8aba9db..e4b3fb4bb77c 100644
--- a/include/linux/skmsg.h
+++ b/include/linux/skmsg.h
@@ -354,7 +354,13 @@ static inline void sk_psock_restore_proto(struct sock *sk,
sk->sk_write_space = psock->saved_write_space;
if (psock->sk_proto) {
- sk->sk_prot = psock->sk_proto;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ bool has_ulp = !!icsk->icsk_ulp_data;
+
+ if (has_ulp)
+ tcp_update_ulp(sk, psock->sk_proto);
+ else
+ sk->sk_prot = psock->sk_proto;
psock->sk_proto = NULL;
}
}
diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
index 54ade13a9b15..f3ae45d02e80 100644
--- a/include/linux/soc/mediatek/mtk-cmdq.h
+++ b/include/linux/soc/mediatek/mtk-cmdq.h
@@ -63,26 +63,26 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt);
/**
* cmdq_pkt_write() - append write command to the CMDQ packet
* @pkt: the CMDQ packet
- * @value: the specified target register value
* @subsys: the CMDQ sub system code
* @offset: register offset from CMDQ sub system
+ * @value: the specified target register value
*
* Return: 0 for success; else the error code is returned
*/
-int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset);
+int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value);
/**
* cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet
* @pkt: the CMDQ packet
- * @value: the specified target register value
* @subsys: the CMDQ sub system code
* @offset: register offset from CMDQ sub system
+ * @value: the specified target register value
* @mask: the specified target register mask
*
* Return: 0 for success; else the error code is returned
*/
-int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
- u32 subsys, u32 offset, u32 mask);
+int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
+ u16 offset, u32 value, u32 mask);
/**
* cmdq_pkt_wfe() - append wait for event command to the CMDQ packet
@@ -91,7 +91,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
*
* Return: 0 for success; else the error code is returned
*/
-int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event);
+int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event);
/**
* cmdq_pkt_clear_event() - append clear event command to the CMDQ packet
@@ -100,7 +100,7 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event);
*
* Return: 0 for success; else the error code is returned
*/
-int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event);
+int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event);
/**
* cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ
diff --git a/include/linux/soc/nxp/lpc32xx-misc.h b/include/linux/soc/nxp/lpc32xx-misc.h
new file mode 100644
index 000000000000..699c6f1e3aab
--- /dev/null
+++ b/include/linux/soc/nxp/lpc32xx-misc.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ */
+
+#ifndef __SOC_LPC32XX_MISC_H
+#define __SOC_LPC32XX_MISC_H
+
+#include <linux/types.h>
+#include <linux/phy.h>
+
+#ifdef CONFIG_ARCH_LPC32XX
+extern u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr);
+extern void lpc32xx_set_phy_interface_mode(phy_interface_t mode);
+extern void lpc32xx_loopback_set(resource_size_t mapbase, int state);
+#else
+static inline u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr)
+{
+ *mapbase = NULL;
+ *dmaaddr = 0;
+ return 0;
+}
+static inline void lpc32xx_set_phy_interface_mode(phy_interface_t mode)
+{
+}
+static inline void lpc32xx_loopback_set(resource_size_t mapbase, int state)
+{
+}
+#endif
+
+#endif /* __SOC_LPC32XX_MISC_H */
diff --git a/include/linux/soc/samsung/exynos-chipid.h b/include/linux/soc/samsung/exynos-chipid.h
new file mode 100644
index 000000000000..8bca6763f99c
--- /dev/null
+++ b/include/linux/soc/samsung/exynos-chipid.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Exynos - CHIPID support
+ */
+#ifndef __LINUX_SOC_EXYNOS_CHIPID_H
+#define __LINUX_SOC_EXYNOS_CHIPID_H
+
+#define EXYNOS_CHIPID_REG_PRO_ID 0x00
+#define EXYNOS_SUBREV_MASK (0xf << 4)
+#define EXYNOS_MAINREV_MASK (0xf << 0)
+#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \
+ EXYNOS_MAINREV_MASK)
+#define EXYNOS_MASK 0xfffff000
+
+#define EXYNOS_CHIPID_REG_PKG_ID 0x04
+/* Bit field definitions for EXYNOS_CHIPID_REG_PKG_ID register */
+#define EXYNOS5422_IDS_OFFSET 24
+#define EXYNOS5422_IDS_MASK 0xff
+#define EXYNOS5422_USESG_OFFSET 3
+#define EXYNOS5422_USESG_MASK 0x01
+#define EXYNOS5422_SG_OFFSET 0
+#define EXYNOS5422_SG_MASK 0x07
+#define EXYNOS5422_TABLE_OFFSET 8
+#define EXYNOS5422_TABLE_MASK 0x03
+#define EXYNOS5422_SG_A_OFFSET 17
+#define EXYNOS5422_SG_A_MASK 0x0f
+#define EXYNOS5422_SG_B_OFFSET 21
+#define EXYNOS5422_SG_B_MASK 0x03
+#define EXYNOS5422_SG_BSIGN_OFFSET 23
+#define EXYNOS5422_SG_BSIGN_MASK 0x01
+#define EXYNOS5422_BIN2_OFFSET 12
+#define EXYNOS5422_BIN2_MASK 0x01
+
+#define EXYNOS_CHIPID_REG_LOT_ID 0x14
+
+#define EXYNOS_CHIPID_REG_AUX_INFO 0x1c
+/* Bit field definitions for EXYNOS_CHIPID_REG_AUX_INFO register */
+#define EXYNOS5422_TMCB_OFFSET 0
+#define EXYNOS5422_TMCB_MASK 0x7f
+#define EXYNOS5422_ARM_UP_OFFSET 8
+#define EXYNOS5422_ARM_UP_MASK 0x03
+#define EXYNOS5422_ARM_DN_OFFSET 10
+#define EXYNOS5422_ARM_DN_MASK 0x03
+#define EXYNOS5422_KFC_UP_OFFSET 12
+#define EXYNOS5422_KFC_UP_MASK 0x03
+#define EXYNOS5422_KFC_DN_OFFSET 14
+#define EXYNOS5422_KFC_DN_MASK 0x03
+
+#endif /*__LINUX_SOC_EXYNOS_CHIPID_H */
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index 6c610e188a44..9531ec823298 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -97,7 +97,10 @@ struct ti_sci_core_ops {
*/
struct ti_sci_dev_ops {
int (*get_device)(const struct ti_sci_handle *handle, u32 id);
+ int (*get_device_exclusive)(const struct ti_sci_handle *handle, u32 id);
int (*idle_device)(const struct ti_sci_handle *handle, u32 id);
+ int (*idle_device_exclusive)(const struct ti_sci_handle *handle,
+ u32 id);
int (*put_device)(const struct ti_sci_handle *handle, u32 id);
int (*is_valid)(const struct ti_sci_handle *handle, u32 id);
int (*get_context_loss_count)(const struct ti_sci_handle *handle,
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 97523818cb14..fc0bed59fc84 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -292,6 +292,9 @@ struct ucred {
#define MSG_BATCH 0x40000 /* sendmmsg(): more messages coming */
#define MSG_EOF MSG_FIN
#define MSG_NO_SHARED_FRAGS 0x80000 /* sendpage() internal : page frags are not shared */
+#define MSG_SENDPAGE_DECRYPTED 0x100000 /* sendpage() internal : page may carry
+ * plain text and require encryption
+ */
#define MSG_ZEROCOPY 0x4000000 /* Use user data in kernel path */
#define MSG_FASTOPEN 0x20000000 /* Send data in TCP SYN */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index ed7c4d6b8235..031ce8617df8 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -214,7 +214,7 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
/*
* Define the various spin_lock methods. Note we define these
- * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The
+ * regardless of whether CONFIG_SMP or CONFIG_PREEMPTION are set. The
* various methods are defined as nops in the case they are not
* required.
*/
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
index 42dfab89e740..b762eaba4cdf 100644
--- a/include/linux/spinlock_api_smp.h
+++ b/include/linux/spinlock_api_smp.h
@@ -96,7 +96,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
/*
* If lockdep is enabled then we use the non-preemption spin-ops
- * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are
+ * even on CONFIG_PREEMPTION, because lockdep assumes that interrupts are
* not re-enabled during lock-acquire (which the preempt-spin-ops do):
*/
#if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC)
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
index f0cfd12cb45e..83bd8cb475d7 100644
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -9,9 +9,9 @@ struct task_struct;
struct pt_regs;
#ifdef CONFIG_STACKTRACE
-void stack_trace_print(unsigned long *trace, unsigned int nr_entries,
+void stack_trace_print(const unsigned long *trace, unsigned int nr_entries,
int spaces);
-int stack_trace_snprint(char *buf, size_t size, unsigned long *entries,
+int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
unsigned int nr_entries, int spaces);
unsigned int stack_trace_save(unsigned long *store, unsigned int size,
unsigned int skipnr);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index baa3ecdb882f..27536b961552 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -98,7 +98,6 @@ typedef void (*rpc_action)(struct rpc_task *);
struct rpc_call_ops {
void (*rpc_call_prepare)(struct rpc_task *, void *);
- void (*rpc_call_prepare_transmit)(struct rpc_task *, void *);
void (*rpc_call_done)(struct rpc_task *, void *);
void (*rpc_count_stats)(struct rpc_task *, void *);
void (*rpc_release)(void *);
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 361f62bb4a8e..cde3dc18e21a 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -46,13 +46,17 @@ enum dma_sync_target {
extern phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
dma_addr_t tbl_dma_addr,
- phys_addr_t phys, size_t size,
+ phys_addr_t phys,
+ size_t mapping_size,
+ size_t alloc_size,
enum dma_data_direction dir,
unsigned long attrs);
extern void swiotlb_tbl_unmap_single(struct device *hwdev,
phys_addr_t tlb_addr,
- size_t size, enum dma_data_direction dir,
+ size_t mapping_size,
+ size_t alloc_size,
+ enum dma_data_direction dir,
unsigned long attrs);
extern void swiotlb_tbl_sync_single(struct device *hwdev,
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
index b7c70c3e953f..48ceea867dd6 100644
--- a/include/linux/sys_soc.h
+++ b/include/linux/sys_soc.h
@@ -12,6 +12,7 @@ struct soc_device_attribute {
const char *machine;
const char *family;
const char *revision;
+ const char *serial_number;
const char *soc_id;
const void *data;
};
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 88145da7d140..f7c561c4dcdd 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1402,4 +1402,23 @@ static inline unsigned int ksys_personality(unsigned int personality)
return old;
}
+/* for __ARCH_WANT_SYS_IPC */
+long ksys_semtimedop(int semid, struct sembuf __user *tsops,
+ unsigned int nsops,
+ const struct __kernel_timespec __user *timeout);
+long ksys_semget(key_t key, int nsems, int semflg);
+long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
+long ksys_msgget(key_t key, int msgflg);
+long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
+long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+ long msgtyp, int msgflg);
+long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+ int msgflg);
+long ksys_shmget(key_t key, size_t size, int shmflg);
+long ksys_shmdt(char __user *shmaddr);
+long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
+long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
+ unsigned int nsops,
+ const struct old_timespec32 __user *timeout);
+
#endif
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 7acb953298a7..84ff2844df2a 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -57,6 +57,7 @@ struct tk_read_base {
* @cs_was_changed_seq: The sequence number of clocksource change events
* @next_leap_ktime: CLOCK_MONOTONIC time value of a pending leap-second
* @raw_sec: CLOCK_MONOTONIC_RAW time in seconds
+ * @monotonic_to_boot: CLOCK_MONOTONIC to CLOCK_BOOTTIME offset
* @cycle_interval: Number of clock cycles in one NTP interval
* @xtime_interval: Number of clock shifted nano seconds in one NTP
* interval.
@@ -84,6 +85,9 @@ struct tk_read_base {
*
* wall_to_monotonic is no longer the boot time, getboottime must be
* used instead.
+ *
+ * @monotonic_to_boottime is a timespec64 representation of @offs_boot to
+ * accelerate the VDSO update for CLOCK_BOOTTIME.
*/
struct timekeeper {
struct tk_read_base tkr_mono;
@@ -99,6 +103,7 @@ struct timekeeper {
u8 cs_was_changed_seq;
ktime_t next_leap_ktime;
u64 raw_sec;
+ struct timespec64 monotonic_to_boot;
/* The following members are for timekeeping internal use */
u64 cycle_interval;
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 47a3e3c08036..eb2fe6edd73c 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -27,6 +27,7 @@
#ifndef _LINUX_TOPOLOGY_H
#define _LINUX_TOPOLOGY_H
+#include <linux/arch_topology.h>
#include <linux/cpumask.h>
#include <linux/bitops.h>
#include <linux/mmzone.h>
@@ -59,6 +60,20 @@ int arch_update_cpu_topology(void);
*/
#define RECLAIM_DISTANCE 30
#endif
+
+/*
+ * The following tunable allows platforms to override the default node
+ * reclaim distance (RECLAIM_DISTANCE) if remote memory accesses are
+ * sufficiently fast that the default value actually hurts
+ * performance.
+ *
+ * AMD EPYC machines use this because even though the 2-hop distance
+ * is 32 (3.2x slower than a local memory access) performance actually
+ * *improves* if allowed to reclaim memory and load balance tasks
+ * between NUMA nodes 2-hops apart.
+ */
+extern int __read_mostly node_reclaim_distance;
+
#ifndef PENALTY_FOR_NODE_WITH_CPUS
#define PENALTY_FOR_NODE_WITH_CPUS (1)
#endif
diff --git a/include/linux/torture.h b/include/linux/torture.h
index a620118385bb..6241f59e2d6f 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -86,7 +86,7 @@ void _torture_stop_kthread(char *m, struct task_struct **tp);
#define torture_stop_kthread(n, tp) \
_torture_stop_kthread("Stopping " #n " task", &(tp))
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
#define torture_preempt_schedule() preempt_schedule()
#else
#define torture_preempt_schedule()
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 5150436783e8..30a8cdcfd4a4 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -548,6 +548,7 @@ extern int trace_event_get_offsets(struct trace_event_call *call);
#define is_signed_type(type) (((type)(-1)) < (type)1)
+int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
int trace_set_clr_event(const char *system, const char *event, int set);
/*
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 83d35d993e8c..e87826e23d59 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1457,7 +1457,7 @@ typedef void (*usb_complete_t)(struct urb *);
* field rather than determining a dma address themselves.
*
* Note that transfer_buffer must still be set if the controller
- * does not support DMA (as indicated by bus.uses_dma) and when talking
+ * does not support DMA (as indicated by hcd_uses_dma()) and when talking
* to root hub. If you have to trasfer between highmem zone and the device
* on such controller, create a bounce buffer or bail out with an error.
* If transfer_buffer cannot be set (is in highmem) and the controller is DMA
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index bab27ccc8ff5..a20e7815d814 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -422,6 +422,9 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
return hcd->high_prio_bh.completing_ep == ep;
}
+#define hcd_uses_dma(hcd) \
+ (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma)
+
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
int status);
diff --git a/include/linux/usb/samsung_usb_phy.h b/include/linux/usb/samsung_usb_phy.h
deleted file mode 100644
index dc0071741695..000000000000
--- a/include/linux/usb/samsung_usb_phy.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * http://www.samsung.com/
- *
- * Defines phy types for samsung usb phy controllers - HOST or DEIVCE.
- *
- * 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.
- */
-
-enum samsung_usb_phy_type {
- USB_PHY_TYPE_DEVICE,
- USB_PHY_TYPE_HOST,
-};
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 4707543ef575..3eb7cae8206c 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -127,6 +127,19 @@ static inline int waitqueue_active(struct wait_queue_head *wq_head)
}
/**
+ * wq_has_single_sleeper - check if there is only one sleeper
+ * @wq_head: wait queue head
+ *
+ * Returns true of wq_head has only one sleeper on the list.
+ *
+ * Please refer to the comment for waitqueue_active.
+ */
+static inline bool wq_has_single_sleeper(struct wait_queue_head *wq_head)
+{
+ return list_is_singular(&wq_head->head);
+}
+
+/**
* wq_has_sleeper - check if there are any waiting processes
* @wq_head: wait queue head
*
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h
index f37d12877754..adcc6a97db61 100644
--- a/include/math-emu/op-common.h
+++ b/include/math-emu/op-common.h
@@ -308,6 +308,7 @@ do { \
\
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
R##_e = X##_e; \
+ /* Fall through */ \
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
@@ -318,6 +319,7 @@ do { \
\
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
R##_e = Y##_e; \
+ /* Fall through */ \
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
@@ -415,6 +417,7 @@ do { \
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
R##_s = X##_s; \
+ /* Fall through */ \
\
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
@@ -428,6 +431,7 @@ do { \
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
R##_s = Y##_s; \
+ /* Fall through */ \
\
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
@@ -493,6 +497,7 @@ do { \
\
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
FP_SET_EXCEPTION(FP_EX_DIVZERO); \
+ /* Fall through */ \
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
R##_c = FP_CLS_INF; \
diff --git a/include/net/act_api.h b/include/net/act_api.h
index c61a1bf4e3de..3a1a72990fce 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -15,6 +15,7 @@
struct tcf_idrinfo {
struct mutex lock;
struct idr action_idr;
+ struct net *net;
};
struct tc_action_ops;
@@ -108,7 +109,7 @@ struct tc_action_net {
};
static inline
-int tc_action_net_init(struct tc_action_net *tn,
+int tc_action_net_init(struct net *net, struct tc_action_net *tn,
const struct tc_action_ops *ops)
{
int err = 0;
@@ -117,6 +118,7 @@ int tc_action_net_init(struct tc_action_net *tn,
if (!tn->idrinfo)
return -ENOMEM;
tn->ops = ops;
+ tn->idrinfo->net = net;
mutex_init(&tn->idrinfo->lock);
idr_init(&tn->idrinfo->action_idr);
return err;
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index becdad576859..3f62b347b04a 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -206,7 +206,7 @@ static inline int ipv6_mc_may_pull(struct sk_buff *skb,
unsigned int len)
{
if (skb_transport_offset(skb) + ipv6_transport_len(skb) < len)
- return -EINVAL;
+ return 0;
return pskb_may_pull(skb, len);
}
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ded574b32c20..ffc95b382eb5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -278,6 +278,7 @@ struct hci_dev {
__u16 conn_info_min_age;
__u16 conn_info_max_age;
__u16 auth_payload_timeout;
+ __u8 min_enc_key_size;
__u8 ssp_debug_mode;
__u8 hw_error_code;
__u32 clock;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 45850a8391d9..26e2ad2c7027 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -7320,6 +7320,21 @@ void cfg80211_pmsr_complete(struct wireless_dev *wdev,
struct cfg80211_pmsr_request *req,
gfp_t gfp);
+/**
+ * cfg80211_iftype_allowed - check whether the interface can be allowed
+ * @wiphy: the wiphy
+ * @iftype: interface type
+ * @is_4addr: use_4addr flag, must be '0' when check_swif is '1'
+ * @check_swif: check iftype against software interfaces
+ *
+ * Check whether the interface is allowed to operate; additionally, this API
+ * can be used to check iftype against the software interfaces when
+ * check_swif is '1'.
+ */
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+ bool is_4addr, u8 check_swif);
+
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 010f26b31c89..bac79e817776 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -171,7 +171,7 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
struct sk_buff *parent);
void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
- void *reasm_data);
+ void *reasm_data, bool try_coalesce);
struct sk_buff *inet_frag_pull_head(struct inet_frag_queue *q);
#endif
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 4c81846ccce8..ab1ca9e238d2 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -513,7 +513,7 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
struct netlink_callback *cb);
int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
- unsigned char *flags, bool skip_oif);
+ u8 rt_family, unsigned char *flags, bool skip_oif);
int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
- int nh_weight);
+ int nh_weight, u8 rt_family);
#endif /* _NET_FIB_H */
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 4a9da951a794..ab40d7afdc54 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -52,7 +52,7 @@ struct bpf_prog;
#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
struct net {
- refcount_t passive; /* To decided when the network
+ refcount_t passive; /* To decide when the network
* namespace should be freed.
*/
refcount_t count; /* To decided when the network
@@ -61,7 +61,6 @@ struct net {
spinlock_t rules_mod_lock;
u32 hash_mix;
- atomic64_t cookie_gen;
struct list_head list; /* list of network namespaces */
struct list_head exit_list; /* To linked to call pernet exit
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 9b624566b82d..475d6f28ca67 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -421,8 +421,7 @@ struct nft_set {
unsigned char *udata;
/* runtime data below here */
const struct nft_set_ops *ops ____cacheline_aligned;
- u16 flags:13,
- bound:1,
+ u16 flags:14,
genmask:2;
u8 klen;
u8 dlen;
@@ -1348,12 +1347,15 @@ struct nft_trans_rule {
struct nft_trans_set {
struct nft_set *set;
u32 set_id;
+ bool bound;
};
#define nft_trans_set(trans) \
(((struct nft_trans_set *)trans->data)->set)
#define nft_trans_set_id(trans) \
(((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans) \
+ (((struct nft_trans_set *)trans->data)->bound)
struct nft_trans_chain {
bool update;
@@ -1384,12 +1386,15 @@ struct nft_trans_table {
struct nft_trans_elem {
struct nft_set *set;
struct nft_set_elem elem;
+ bool bound;
};
#define nft_trans_elem_set(trans) \
(((struct nft_trans_elem *)trans->data)->set)
#define nft_trans_elem(trans) \
(((struct nft_trans_elem *)trans->data)->elem)
+#define nft_trans_elem_set_bound(trans) \
+ (((struct nft_trans_elem *)trans->data)->bound)
struct nft_trans_obj {
struct nft_object *obj;
diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h
index 3196663a10e3..c8b9dec376f5 100644
--- a/include/net/netfilter/nf_tables_offload.h
+++ b/include/net/netfilter/nf_tables_offload.h
@@ -73,4 +73,6 @@ int nft_flow_rule_offload_commit(struct net *net);
(__reg)->key = __key; \
memset(&(__reg)->mask, 0xff, (__reg)->len);
+int nft_chain_offload_priority(struct nft_base_chain *basechain);
+
#endif
diff --git a/include/net/netlink.h b/include/net/netlink.h
index e4650e5b64a1..b140c8f1be22 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -684,9 +684,8 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
const struct nla_policy *policy,
struct netlink_ext_ack *extack)
{
- return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
- nlmsg_attrlen(nlh, hdrlen), policy,
- NL_VALIDATE_STRICT, extack);
+ return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+ NL_VALIDATE_STRICT, extack);
}
/**
diff --git a/include/net/nexthop.h b/include/net/nexthop.h
index 25f1f9a8419b..331ebbc94fe7 100644
--- a/include/net/nexthop.h
+++ b/include/net/nexthop.h
@@ -141,12 +141,6 @@ static inline unsigned int nexthop_num_path(const struct nexthop *nh)
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
rc = nh_grp->num_nh;
- } else {
- const struct nh_info *nhi;
-
- nhi = rcu_dereference_rtnl(nh->nh_info);
- if (nhi->reject_nh)
- rc = 0;
}
return rc;
@@ -167,7 +161,8 @@ struct nexthop *nexthop_mpath_select(const struct nexthop *nh, int nhsel)
}
static inline
-int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh)
+int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh,
+ u8 rt_family)
{
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
int i;
@@ -178,7 +173,7 @@ int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh)
struct fib_nh_common *nhc = &nhi->fib_nhc;
int weight = nhg->nh_entries[i].weight;
- if (fib_add_nexthop(skb, nhc, weight) < 0)
+ if (fib_add_nexthop(skb, nhc, weight, rt_family) < 0)
return -EMSGSIZE;
}
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index e429809ca90d..98be18ef1ed3 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -646,7 +646,7 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
{
cls_common->chain_index = tp->chain->index;
cls_common->protocol = tp->protocol;
- cls_common->prio = tp->prio;
+ cls_common->prio = tp->prio >> 16;
if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE)
cls_common->extack = extack;
}
diff --git a/include/net/psample.h b/include/net/psample.h
index 37a4df2325b2..6b578ce69cd8 100644
--- a/include/net/psample.h
+++ b/include/net/psample.h
@@ -11,6 +11,7 @@ struct psample_group {
u32 group_num;
u32 refcount;
u32 seq;
+ struct rcu_head rcu;
};
struct psample_group *psample_group_get(struct net *net, u32 group_num);
diff --git a/include/net/route.h b/include/net/route.h
index 630a0493f1f3..dfce19c9fa96 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -233,7 +233,7 @@ void rt_del_uncached_list(struct rtable *rt);
int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
u32 table_id, struct fib_info *fi,
- int *fa_index, int fa_start);
+ int *fa_index, int fa_start, unsigned int flags);
static inline void ip_rt_put(struct rtable *rt)
{
diff --git a/include/net/sock.h b/include/net/sock.h
index 228db3998e46..2c53f1a1d905 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2482,6 +2482,7 @@ static inline bool sk_fullsock(const struct sock *sk)
/* Checks if this SKB belongs to an HW offloaded socket
* and whether any SW fallbacks are required based on dev.
+ * Check decrypted mark in case skb_orphan() cleared socket.
*/
static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
struct net_device *dev)
@@ -2489,8 +2490,15 @@ static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
#ifdef CONFIG_SOCK_VALIDATE_XMIT
struct sock *sk = skb->sk;
- if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb)
+ if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
skb = sk->sk_validate_xmit_skb(sk, dev, skb);
+#ifdef CONFIG_TLS_DEVICE
+ } else if (unlikely(skb->decrypted)) {
+ pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
+ kfree_skb(skb);
+ skb = NULL;
+#endif
+ }
#endif
return skb;
diff --git a/include/net/tc_act/tc_police.h b/include/net/tc_act/tc_police.h
index 8b9ef3664262..cfdc7cb82cad 100644
--- a/include/net/tc_act/tc_police.h
+++ b/include/net/tc_act/tc_police.h
@@ -54,7 +54,7 @@ static inline u64 tcf_police_rate_bytes_ps(const struct tc_action *act)
struct tcf_police *police = to_police(act);
struct tcf_police_params *params;
- params = rcu_dereference_bh(police->params);
+ params = rcu_dereference_bh_rtnl(police->params);
return params->rate.rate_bytes_ps;
}
@@ -63,7 +63,7 @@ static inline s64 tcf_police_tcfp_burst(const struct tc_action *act)
struct tcf_police *police = to_police(act);
struct tcf_police_params *params;
- params = rcu_dereference_bh(police->params);
+ params = rcu_dereference_bh_rtnl(police->params);
return params->tcfp_burst;
}
diff --git a/include/net/tc_act/tc_sample.h b/include/net/tc_act/tc_sample.h
index 0a559d4b6f0f..b4fce0fae645 100644
--- a/include/net/tc_act/tc_sample.h
+++ b/include/net/tc_act/tc_sample.h
@@ -44,7 +44,7 @@ static inline int tcf_sample_trunc_size(const struct tc_action *a)
static inline struct psample_group *
tcf_sample_psample_group(const struct tc_action *a)
{
- return rcu_dereference(to_sample(a)->psample_group);
+ return rcu_dereference_rtnl(to_sample(a)->psample_group);
}
#endif /* __NET_TC_SAMPLE_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e5cf514ba118..81e8ade1e6e4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2108,6 +2108,8 @@ struct tcp_ulp_ops {
/* initialize ulp */
int (*init)(struct sock *sk);
+ /* update ulp */
+ void (*update)(struct sock *sk, struct proto *p);
/* cleanup ulp */
void (*release)(struct sock *sk);
@@ -2119,6 +2121,7 @@ void tcp_unregister_ulp(struct tcp_ulp_ops *type);
int tcp_set_ulp(struct sock *sk, const char *name);
void tcp_get_available_ulp(char *buf, size_t len);
void tcp_cleanup_ulp(struct sock *sk);
+void tcp_update_ulp(struct sock *sk, struct proto *p);
#define MODULE_ALIAS_TCP_ULP(name) \
__MODULE_INFO(alias, alias_userspace, name); \
diff --git a/include/net/tls.h b/include/net/tls.h
index 584609174fe0..41b2d41bb1b8 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -107,9 +107,7 @@ struct tls_device {
enum {
TLS_BASE,
TLS_SW,
-#ifdef CONFIG_TLS_DEVICE
TLS_HW,
-#endif
TLS_HW_RECORD,
TLS_NUM_CONFIG,
};
@@ -162,6 +160,7 @@ struct tls_sw_context_tx {
int async_capable;
#define BIT_TX_SCHEDULED 0
+#define BIT_TX_CLOSING 1
unsigned long tx_bitmask;
};
@@ -272,6 +271,8 @@ struct tls_context {
unsigned long flags;
/* cache cold stuff */
+ struct proto *sk_proto;
+
void (*sk_destruct)(struct sock *sk);
void (*sk_proto_close)(struct sock *sk, long timeout);
@@ -355,13 +356,17 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
unsigned int optlen);
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx);
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx);
+void tls_sw_strparser_done(struct tls_context *tls_ctx);
int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int tls_sw_sendpage(struct sock *sk, struct page *page,
int offset, size_t size, int flags);
-void tls_sw_close(struct sock *sk, long timeout);
-void tls_sw_free_resources_tx(struct sock *sk);
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx);
+void tls_sw_release_resources_tx(struct sock *sk);
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx);
void tls_sw_free_resources_rx(struct sock *sk);
void tls_sw_release_resources_rx(struct sock *sk);
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx);
int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len);
bool tls_sw_stream_read(const struct sock *sk);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index b22db30c3d88..aa08a7a5f6ac 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -983,7 +983,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
struct xfrm_if_parms {
- char name[IFNAMSIZ]; /* name of XFRM device */
int link; /* ifindex of underlying L2 interface */
u32 if_id; /* interface identifyer */
};
@@ -991,7 +990,6 @@ struct xfrm_if_parms {
struct xfrm_if {
struct xfrm_if __rcu *next; /* next interface in list */
struct net_device *dev; /* virtual device associated with interface */
- struct net_device *phydev; /* physical device */
struct net *net; /* netns for packet i/o */
struct xfrm_if_parms p; /* interface parms */
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c5f8a9f17063..4f225175cb91 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2647,7 +2647,9 @@ struct ib_client {
const union ib_gid *gid,
const struct sockaddr *addr,
void *client_data);
- struct list_head list;
+
+ refcount_t uses;
+ struct completion uses_zero;
u32 client_id;
/* kverbs are not required by the client */
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 0eeea520a853..e06c77d76463 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -608,7 +608,7 @@ static inline void rvt_qp_wqe_reserve(
/**
* rvt_qp_wqe_unreserve - clean reserved operation
* @qp - the rvt qp
- * @wqe - the send wqe
+ * @flags - send wqe flags
*
* This decrements the reserve use count.
*
@@ -620,11 +620,9 @@ static inline void rvt_qp_wqe_reserve(
* the compiler does not juggle the order of the s_last
* ring index and the decrementing of s_reserved_used.
*/
-static inline void rvt_qp_wqe_unreserve(
- struct rvt_qp *qp,
- struct rvt_swqe *wqe)
+static inline void rvt_qp_wqe_unreserve(struct rvt_qp *qp, int flags)
{
- if (unlikely(wqe->wr.send_flags & RVT_SEND_RESERVE_USED)) {
+ if (unlikely(flags & RVT_SEND_RESERVE_USED)) {
atomic_dec(&qp->s_reserved_used);
/* insure no compiler re-order up to s_last change */
smp_mb__after_atomic();
@@ -853,6 +851,7 @@ rvt_qp_complete_swqe(struct rvt_qp *qp,
u32 byte_len, last;
int flags = wqe->wr.send_flags;
+ rvt_qp_wqe_unreserve(qp, flags);
rvt_put_qp_swqe(qp, wqe);
need_completion =
diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
index b0fc6b26bdf5..83df1ec6664e 100644
--- a/include/rdma/restrack.h
+++ b/include/rdma/restrack.h
@@ -105,8 +105,7 @@ struct rdma_restrack_entry {
};
int rdma_restrack_count(struct ib_device *dev,
- enum rdma_restrack_type type,
- struct pid_namespace *ns);
+ enum rdma_restrack_type type);
void rdma_restrack_kadd(struct rdma_restrack_entry *res);
void rdma_restrack_uadd(struct rdma_restrack_entry *res);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 2d64b53f947c..9b87e1a1c646 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -115,7 +115,7 @@ struct fc_disc_port {
struct fc_lport *lp;
struct list_head peers;
struct work_struct rport_work;
- u32 port_id;
+ u32 port_id;
};
/**
@@ -155,14 +155,14 @@ struct fc_rport_operations {
*/
struct fc_rport_libfc_priv {
struct fc_lport *local_port;
- enum fc_rport_state rp_state;
+ enum fc_rport_state rp_state;
u16 flags;
#define FC_RP_FLAGS_REC_SUPPORTED (1 << 0)
#define FC_RP_FLAGS_RETRY (1 << 1)
#define FC_RP_STARTED (1 << 2)
#define FC_RP_FLAGS_CONF_REQ (1 << 3)
- unsigned int e_d_tov;
- unsigned int r_a_tov;
+ unsigned int e_d_tov;
+ unsigned int r_a_tov;
};
/**
@@ -191,24 +191,24 @@ struct fc_rport_priv {
struct fc_lport *local_port;
struct fc_rport *rport;
struct kref kref;
- enum fc_rport_state rp_state;
+ enum fc_rport_state rp_state;
struct fc_rport_identifiers ids;
u16 flags;
- u16 max_seq;
+ u16 max_seq;
u16 disc_id;
u16 maxframe_size;
- unsigned int retries;
- unsigned int major_retries;
- unsigned int e_d_tov;
- unsigned int r_a_tov;
- struct mutex rp_mutex;
+ unsigned int retries;
+ unsigned int major_retries;
+ unsigned int e_d_tov;
+ unsigned int r_a_tov;
+ struct mutex rp_mutex;
struct delayed_work retry_work;
- enum fc_rport_event event;
+ enum fc_rport_event event;
struct fc_rport_operations *ops;
- struct list_head peers;
- struct work_struct event_work;
+ struct list_head peers;
+ struct work_struct event_work;
u32 supported_classes;
- u16 prli_count;
+ u16 prli_count;
struct rcu_head rcu;
u16 sp_features;
u8 spp_type;
@@ -618,12 +618,12 @@ struct libfc_function_template {
* @disc_callback: Callback routine called when discovery completes
*/
struct fc_disc {
- unsigned char retry_count;
- unsigned char pending;
- unsigned char requested;
- unsigned short seq_count;
- unsigned char buf_len;
- u16 disc_id;
+ unsigned char retry_count;
+ unsigned char pending;
+ unsigned char requested;
+ unsigned short seq_count;
+ unsigned char buf_len;
+ u16 disc_id;
struct list_head rports;
void *priv;
@@ -697,7 +697,7 @@ struct fc_lport {
struct fc_rport_priv *ms_rdata;
struct fc_rport_priv *ptp_rdata;
void *scsi_priv;
- struct fc_disc disc;
+ struct fc_disc disc;
/* Virtual port information */
struct list_head vports;
@@ -715,7 +715,7 @@ struct fc_lport {
u8 retry_count;
/* Fabric information */
- u32 port_id;
+ u32 port_id;
u64 wwpn;
u64 wwnn;
unsigned int service_params;
@@ -743,11 +743,11 @@ struct fc_lport {
struct fc_ns_fts fcts;
/* Miscellaneous */
- struct mutex lp_mutex;
- struct list_head list;
+ struct mutex lp_mutex;
+ struct list_head list;
struct delayed_work retry_work;
void *prov[FC_FC4_PROV_SIZE];
- struct list_head lport_list;
+ struct list_head lport_list;
};
/**
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index c50fb297e265..2568cb0627ec 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -31,7 +31,7 @@
* FIP tunable parameters.
*/
#define FCOE_CTLR_START_DELAY 2000 /* mS after first adv. to choose FCF */
-#define FCOE_CTRL_SOL_TOV 2000 /* min. solicitation interval (mS) */
+#define FCOE_CTLR_SOL_TOV 2000 /* min. solicitation interval (mS) */
#define FCOE_CTLR_FCF_LIMIT 20 /* max. number of FCF entries */
#define FCOE_CTLR_VN2VN_LOGIN_LIMIT 3 /* max. VN2VN rport login retries */
@@ -229,6 +229,7 @@ struct fcoe_fcf {
* @vn_mac: VN_Node assigned MAC address for data
*/
struct fcoe_rport {
+ struct fc_rport_priv rdata;
unsigned long time;
u16 fcoe_len;
u16 flags;
diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index 50f49e043668..d1a93c73f006 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -46,7 +46,9 @@ struct mcip_cmd {
#define CMD_IDU_ENABLE 0x71
#define CMD_IDU_DISABLE 0x72
#define CMD_IDU_SET_MODE 0x74
+#define CMD_IDU_READ_MODE 0x75
#define CMD_IDU_SET_DEST 0x76
+#define CMD_IDU_ACK_CIRQ 0x79
#define CMD_IDU_SET_MASK 0x7C
#define IDU_M_TRIG_LEVEL 0x0
@@ -119,4 +121,13 @@ static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
__mcip_cmd(cmd, param);
}
+/*
+ * Read MCIP register
+ */
+static inline unsigned int __mcip_cmd_read(unsigned int cmd, unsigned int param)
+{
+ __mcip_cmd(cmd, param);
+ return read_aux_reg(ARC_REG_MCIP_READBACK);
+}
+
#endif
diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h
index 3f9d6b6a5691..c1036d16ed03 100644
--- a/include/soc/fsl/qe/qe.h
+++ b/include/soc/fsl/qe/qe.h
@@ -259,7 +259,7 @@ static inline int qe_alive_during_sleep(void)
/* Structure that defines QE firmware binary files.
*
- * See Documentation/powerpc/qe_firmware.txt for a description of these
+ * See Documentation/powerpc/qe_firmware.rst for a description of these
* fields.
*/
struct qe_firmware {
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 79b74ced9d91..5a34b87d89e3 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -20,11 +20,6 @@ struct mtk_smi_larb_iommu {
unsigned int mmu;
};
-struct mtk_smi_iommu {
- unsigned int larb_nr;
- struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
-};
-
/*
* mtk_smi_larb_get: Enable the power domain and clocks for this local arbiter.
* It also initialize some basic setting(like iommu).
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index c5188ff724d1..bc88d6f964da 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -173,10 +173,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
if (snd_BUG_ON(!stream))
return;
- if (stream->direction == SND_COMPRESS_PLAYBACK)
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- else
- stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
wake_up(&stream->runtime->sleep);
}
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 954563ee2277..985a5f583de4 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
{
struct device *dev = simple_priv_to_dev(priv);
+ /* dai might be NULL */
+ if (!dai)
+ return;
+
if (dai->name)
dev_dbg(dev, "%s dai name = %s\n",
name, dai->name);
diff --git a/include/sound/sof/control.h b/include/sound/sof/control.h
index bded69e696d4..6080ea0facd7 100644
--- a/include/sound/sof/control.h
+++ b/include/sound/sof/control.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h
index 4bb8ee138ba7..65e4c20e567c 100644
--- a/include/sound/sof/dai-intel.h
+++ b/include/sound/sof/dai-intel.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h
index 3d174e20aa53..5b8de1b1983c 100644
--- a/include/sound/sof/dai.h
+++ b/include/sound/sof/dai.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h
index 12867bbd4372..10f00c08dbb7 100644
--- a/include/sound/sof/header.h
+++ b/include/sound/sof/header.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h
index 16528d2b4a50..a9156b4a062c 100644
--- a/include/sound/sof/info.h
+++ b/include/sound/sof/info.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/pm.h b/include/sound/sof/pm.h
index 8ae3ad45bdf7..003879401d63 100644
--- a/include/sound/sof/pm.h
+++ b/include/sound/sof/pm.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h
index 643f175cb479..0b71b381b952 100644
--- a/include/sound/sof/stream.h
+++ b/include/sound/sof/stream.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h
index 41dcabf89899..c47b36240920 100644
--- a/include/sound/sof/topology.h
+++ b/include/sound/sof/topology.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h
index 9257d5473d97..fda6e8f6ead4 100644
--- a/include/sound/sof/trace.h
+++ b/include/sound/sof/trace.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/sound/sof/xtensa.h b/include/sound/sof/xtensa.h
index d25c764b10e8..dd53d36b34e1 100644
--- a/include/sound/sof/xtensa.h
+++ b/include/sound/sof/xtensa.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h
index 2212adda8f77..64e92d56c6a8 100644
--- a/include/trace/events/dma_fence.h
+++ b/include/trace/events/dma_fence.h
@@ -2,7 +2,7 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM dma_fence
-#if !defined(_TRACE_FENCE_H) || defined(TRACE_HEADER_MULTI_READ)
+#if !defined(_TRACE_DMA_FENCE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_DMA_FENCE_H
#include <linux/tracepoint.h>
diff --git a/include/trace/events/intel_iommu.h b/include/trace/events/intel_iommu.h
new file mode 100644
index 000000000000..54e61d456cdf
--- /dev/null
+++ b/include/trace/events/intel_iommu.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Intel IOMMU trace support
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+#ifdef CONFIG_INTEL_IOMMU
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_iommu
+
+#if !defined(_TRACE_INTEL_IOMMU_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_INTEL_IOMMU_H
+
+#include <linux/tracepoint.h>
+#include <linux/intel-iommu.h>
+
+DECLARE_EVENT_CLASS(dma_map,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, phys_addr_t phys_addr,
+ size_t size),
+
+ TP_ARGS(dev, dev_addr, phys_addr, size),
+
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ __field(dma_addr_t, dev_addr)
+ __field(phys_addr_t, phys_addr)
+ __field(size_t, size)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev_name, dev_name(dev));
+ __entry->dev_addr = dev_addr;
+ __entry->phys_addr = phys_addr;
+ __entry->size = size;
+ ),
+
+ TP_printk("dev=%s dev_addr=0x%llx phys_addr=0x%llx size=%zu",
+ __get_str(dev_name),
+ (unsigned long long)__entry->dev_addr,
+ (unsigned long long)__entry->phys_addr,
+ __entry->size)
+);
+
+DEFINE_EVENT(dma_map, map_single,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, phys_addr_t phys_addr,
+ size_t size),
+ TP_ARGS(dev, dev_addr, phys_addr, size)
+);
+
+DEFINE_EVENT(dma_map, map_sg,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, phys_addr_t phys_addr,
+ size_t size),
+ TP_ARGS(dev, dev_addr, phys_addr, size)
+);
+
+DEFINE_EVENT(dma_map, bounce_map_single,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, phys_addr_t phys_addr,
+ size_t size),
+ TP_ARGS(dev, dev_addr, phys_addr, size)
+);
+
+DECLARE_EVENT_CLASS(dma_unmap,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, size_t size),
+
+ TP_ARGS(dev, dev_addr, size),
+
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ __field(dma_addr_t, dev_addr)
+ __field(size_t, size)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev_name, dev_name(dev));
+ __entry->dev_addr = dev_addr;
+ __entry->size = size;
+ ),
+
+ TP_printk("dev=%s dev_addr=0x%llx size=%zu",
+ __get_str(dev_name),
+ (unsigned long long)__entry->dev_addr,
+ __entry->size)
+);
+
+DEFINE_EVENT(dma_unmap, unmap_single,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, size_t size),
+ TP_ARGS(dev, dev_addr, size)
+);
+
+DEFINE_EVENT(dma_unmap, unmap_sg,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, size_t size),
+ TP_ARGS(dev, dev_addr, size)
+);
+
+DEFINE_EVENT(dma_unmap, bounce_unmap_single,
+ TP_PROTO(struct device *dev, dma_addr_t dev_addr, size_t size),
+ TP_ARGS(dev, dev_addr, size)
+);
+
+#endif /* _TRACE_INTEL_IOMMU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
+#endif /* CONFIG_INTEL_IOMMU */
diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h
index f3a12566bed0..6678cf8b235b 100644
--- a/include/trace/events/napi.h
+++ b/include/trace/events/napi.h
@@ -3,7 +3,7 @@
#define TRACE_SYSTEM napi
#if !defined(_TRACE_NAPI_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_NAPI_H_
+#define _TRACE_NAPI_H
#include <linux/netdevice.h>
#include <linux/tracepoint.h>
@@ -38,7 +38,7 @@ TRACE_EVENT(napi_poll,
#undef NO_DEV
-#endif /* _TRACE_NAPI_H_ */
+#endif /* _TRACE_NAPI_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
diff --git a/include/trace/events/qdisc.h b/include/trace/events/qdisc.h
index 60d0d8bd336d..0d1a9ebf55ba 100644
--- a/include/trace/events/qdisc.h
+++ b/include/trace/events/qdisc.h
@@ -2,7 +2,7 @@
#define TRACE_SYSTEM qdisc
#if !defined(_TRACE_QDISC_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_QDISC_H_
+#define _TRACE_QDISC_H
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -44,7 +44,7 @@ TRACE_EVENT(qdisc_dequeue,
__entry->txq_state, __entry->packets, __entry->skbaddr )
);
-#endif /* _TRACE_QDISC_H_ */
+#endif /* _TRACE_QDISC_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 02a3f78f7cd8..694bd040cf51 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -100,7 +100,6 @@ TRACE_EVENT_RCU(rcu_grace_period,
* "Startedroot": Requested a nocb grace period based on root-node data.
* "NoGPkthread": The RCU grace-period kthread has not yet started.
* "StartWait": Start waiting for the requested grace period.
- * "ResumeWait": Resume waiting after signal.
* "EndWait": Complete wait.
* "Cleanup": Clean up rcu_node structure after previous GP.
* "CleanupMore": Clean up, and another GP is needed.
@@ -267,7 +266,8 @@ TRACE_EVENT_RCU(rcu_exp_funnel_lock,
* "WakeNotPoll": Don't wake rcuo kthread because it is polling.
* "DeferredWake": Carried out the "IsDeferred" wakeup.
* "Poll": Start of new polling cycle for rcu_nocb_poll.
- * "Sleep": Sleep waiting for CBs for !rcu_nocb_poll.
+ * "Sleep": Sleep waiting for GP for !rcu_nocb_poll.
+ * "CBSleep": Sleep waiting for CBs for !rcu_nocb_poll.
* "WokeEmpty": rcuo kthread woke to find empty list.
* "WokeNonEmpty": rcuo kthread woke to find non-empty list.
* "WaitQueue": Enqueue partially done, timed wait for it to complete.
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index cc1d060cbf13..a13a62db3565 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -23,20 +23,17 @@
#define __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY
enum rxrpc_skb_trace {
- rxrpc_skb_rx_cleaned,
- rxrpc_skb_rx_freed,
- rxrpc_skb_rx_got,
- rxrpc_skb_rx_lost,
- rxrpc_skb_rx_purged,
- rxrpc_skb_rx_received,
- rxrpc_skb_rx_rotated,
- rxrpc_skb_rx_seen,
- rxrpc_skb_tx_cleaned,
- rxrpc_skb_tx_freed,
- rxrpc_skb_tx_got,
- rxrpc_skb_tx_new,
- rxrpc_skb_tx_rotated,
- rxrpc_skb_tx_seen,
+ rxrpc_skb_cleaned,
+ rxrpc_skb_freed,
+ rxrpc_skb_got,
+ rxrpc_skb_lost,
+ rxrpc_skb_new,
+ rxrpc_skb_purged,
+ rxrpc_skb_received,
+ rxrpc_skb_rotated,
+ rxrpc_skb_seen,
+ rxrpc_skb_unshared,
+ rxrpc_skb_unshared_nomem,
};
enum rxrpc_local_trace {
@@ -228,20 +225,17 @@ enum rxrpc_tx_point {
* Declare tracing information enums and their string mappings for display.
*/
#define rxrpc_skb_traces \
- EM(rxrpc_skb_rx_cleaned, "Rx CLN") \
- EM(rxrpc_skb_rx_freed, "Rx FRE") \
- EM(rxrpc_skb_rx_got, "Rx GOT") \
- EM(rxrpc_skb_rx_lost, "Rx *L*") \
- EM(rxrpc_skb_rx_purged, "Rx PUR") \
- EM(rxrpc_skb_rx_received, "Rx RCV") \
- EM(rxrpc_skb_rx_rotated, "Rx ROT") \
- EM(rxrpc_skb_rx_seen, "Rx SEE") \
- EM(rxrpc_skb_tx_cleaned, "Tx CLN") \
- EM(rxrpc_skb_tx_freed, "Tx FRE") \
- EM(rxrpc_skb_tx_got, "Tx GOT") \
- EM(rxrpc_skb_tx_new, "Tx NEW") \
- EM(rxrpc_skb_tx_rotated, "Tx ROT") \
- E_(rxrpc_skb_tx_seen, "Tx SEE")
+ EM(rxrpc_skb_cleaned, "CLN") \
+ EM(rxrpc_skb_freed, "FRE") \
+ EM(rxrpc_skb_got, "GOT") \
+ EM(rxrpc_skb_lost, "*L*") \
+ EM(rxrpc_skb_new, "NEW") \
+ EM(rxrpc_skb_purged, "PUR") \
+ EM(rxrpc_skb_received, "RCV") \
+ EM(rxrpc_skb_rotated, "ROT") \
+ EM(rxrpc_skb_seen, "SEE") \
+ EM(rxrpc_skb_unshared, "UNS") \
+ E_(rxrpc_skb_unshared_nomem, "US0")
#define rxrpc_local_traces \
EM(rxrpc_local_got, "GOT") \
@@ -498,10 +492,10 @@ rxrpc_tx_points;
#define E_(a, b) { a, b }
TRACE_EVENT(rxrpc_local,
- TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
+ TP_PROTO(unsigned int local_debug_id, enum rxrpc_local_trace op,
int usage, const void *where),
- TP_ARGS(local, op, usage, where),
+ TP_ARGS(local_debug_id, op, usage, where),
TP_STRUCT__entry(
__field(unsigned int, local )
@@ -511,7 +505,7 @@ TRACE_EVENT(rxrpc_local,
),
TP_fast_assign(
- __entry->local = local->debug_id;
+ __entry->local = local_debug_id;
__entry->op = op;
__entry->usage = usage;
__entry->where = where;
@@ -643,13 +637,14 @@ TRACE_EVENT(rxrpc_call,
TRACE_EVENT(rxrpc_skb,
TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op,
- int usage, int mod_count, const void *where),
+ int usage, int mod_count, u8 flags, const void *where),
- TP_ARGS(skb, op, usage, mod_count, where),
+ TP_ARGS(skb, op, usage, mod_count, flags, where),
TP_STRUCT__entry(
__field(struct sk_buff *, skb )
__field(enum rxrpc_skb_trace, op )
+ __field(u8, flags )
__field(int, usage )
__field(int, mod_count )
__field(const void *, where )
@@ -657,14 +652,16 @@ TRACE_EVENT(rxrpc_skb,
TP_fast_assign(
__entry->skb = skb;
+ __entry->flags = flags;
__entry->op = op;
__entry->usage = usage;
__entry->mod_count = mod_count;
__entry->where = where;
),
- TP_printk("s=%p %s u=%d m=%d p=%pSR",
+ TP_printk("s=%p %cx %s u=%d m=%d p=%pSR",
__entry->skb,
+ __entry->flags & RXRPC_SKB_TX_BUFFER ? 'T' : 'R',
__print_symbolic(__entry->op, rxrpc_skb_traces),
__entry->usage,
__entry->mod_count,
diff --git a/include/trace/events/tegra_apb_dma.h b/include/trace/events/tegra_apb_dma.h
index 0818f6286110..971cd02d2daf 100644
--- a/include/trace/events/tegra_apb_dma.h
+++ b/include/trace/events/tegra_apb_dma.h
@@ -1,5 +1,5 @@
#if !defined(_TRACE_TEGRA_APB_DMA_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_TEGRA_APM_DMA_H
+#define _TRACE_TEGRA_APB_DMA_H
#include <linux/tracepoint.h>
#include <linux/dmaengine.h>
@@ -55,7 +55,7 @@ TRACE_EVENT(tegra_dma_isr,
TP_printk("%s: irq %d\n", __get_str(chan), __entry->irq)
);
-#endif /* _TRACE_TEGRADMA_H */
+#endif /* _TRACE_TEGRA_APB_DMA_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 1be0e798e362..1fc8faa6e973 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -569,7 +569,7 @@ __SYSCALL(__NR_semget, sys_semget)
__SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl)
#if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32
#define __NR_semtimedop 192
-__SC_COMP(__NR_semtimedop, sys_semtimedop, sys_semtimedop_time32)
+__SC_3264(__NR_semtimedop, sys_semtimedop_time32, sys_semtimedop)
#endif
#define __NR_semop 193
__SYSCALL(__NR_semop, sys_semop)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index fa1c753dcdbc..a5aa7d3ac6a1 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1466,8 +1466,8 @@ union bpf_attr {
* If no cookie has been set yet, generate a new cookie. Once
* generated, the socket cookie remains stable for the life of the
* socket. This helper can be useful for monitoring per socket
- * networking traffic statistics as it provides a unique socket
- * identifier per namespace.
+ * networking traffic statistics as it provides a global socket
+ * identifier that can be assumed unique.
* Return
* A 8-byte long non-decreasing number on success, or 0 if the
* socket field is missing inside *skb*.
diff --git a/include/uapi/linux/bpfilter.h b/include/uapi/linux/bpfilter.h
index 2ec3cc99ea4c..cbc1f5813f50 100644
--- a/include/uapi/linux/bpfilter.h
+++ b/include/uapi/linux/bpfilter.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_BPFILTER_H
#define _UAPI_LINUX_BPFILTER_H
diff --git a/include/uapi/linux/ipmi_bmc.h b/include/uapi/linux/ipmi_bmc.h
index 1670f0944227..782a03eb1086 100644
--- a/include/uapi/linux/ipmi_bmc.h
+++ b/include/uapi/linux/ipmi_bmc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2015-2018, Intel Corporation.
*/
diff --git a/include/uapi/linux/isdn/capicmd.h b/include/uapi/linux/isdn/capicmd.h
index 4941628a4fb9..5ec88e7548a9 100644
--- a/include/uapi/linux/isdn/capicmd.h
+++ b/include/uapi/linux/isdn/capicmd.h
@@ -16,6 +16,7 @@
#define CAPI_MSG_BASELEN 8
#define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2)
#define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2)
+#define CAPI_DISCONNECT_B3_RESP_LEN (CAPI_MSG_BASELEN+4)
/*----- CAPI commands -----*/
#define CAPI_ALERT 0x01
diff --git a/include/uapi/linux/isst_if.h b/include/uapi/linux/isst_if.h
index d10b832c58c5..0a52b7b093d3 100644
--- a/include/uapi/linux/isst_if.h
+++ b/include/uapi/linux/isst_if.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Intel Speed Select Interface: OS to hardware Interface
* Copyright (c) 2019, Intel Corporation.
diff --git a/include/uapi/linux/jffs2.h b/include/uapi/linux/jffs2.h
index a18b719f49d4..784ba0b9690a 100644
--- a/include/uapi/linux/jffs2.h
+++ b/include/uapi/linux/jffs2.h
@@ -77,11 +77,6 @@
#define JFFS2_ACL_VERSION 0x0001
-// Maybe later...
-//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
-//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
-
-
#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at
mount time, don't wait for it to
happen later */
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 6d112868272d..05669c87a0af 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -31,6 +31,7 @@
#define KEXEC_ARCH_DEFAULT ( 0 << 16)
#define KEXEC_ARCH_386 ( 3 << 16)
#define KEXEC_ARCH_68K ( 4 << 16)
+#define KEXEC_ARCH_PARISC (15 << 16)
#define KEXEC_ARCH_X86_64 (62 << 16)
#define KEXEC_ARCH_PPC (20 << 16)
#define KEXEC_ARCH_PPC64 (21 << 16)
diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
index 070d1bc7e725..20917c59f39c 100644
--- a/include/uapi/linux/kfd_ioctl.h
+++ b/include/uapi/linux/kfd_ioctl.h
@@ -410,21 +410,6 @@ struct kfd_ioctl_unmap_memory_from_gpu_args {
__u32 n_success; /* to/from KFD */
};
-/* Allocate GWS for specific queue
- *
- * @gpu_id: device identifier
- * @queue_id: queue's id that GWS is allocated for
- * @num_gws: how many GWS to allocate
- * @first_gws: index of the first GWS allocated.
- * only support contiguous GWS allocation
- */
-struct kfd_ioctl_alloc_queue_gws_args {
- __u32 gpu_id; /* to KFD */
- __u32 queue_id; /* to KFD */
- __u32 num_gws; /* to KFD */
- __u32 first_gws; /* from KFD */
-};
-
struct kfd_ioctl_get_dmabuf_info_args {
__u64 size; /* from KFD */
__u64 metadata_ptr; /* to KFD */
@@ -544,10 +529,7 @@ enum kfd_mmio_remap {
#define AMDKFD_IOC_IMPORT_DMABUF \
AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
-#define AMDKFD_IOC_ALLOC_QUEUE_GWS \
- AMDKFD_IOWR(0x1E, struct kfd_ioctl_alloc_queue_gws_args)
-
#define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x1F
+#define AMDKFD_COMMAND_END 0x1E
#endif
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a7c19540ce21..5e3f12d5359e 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -116,7 +116,7 @@ struct kvm_irq_level {
* ACPI gsi notion of irq.
* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
- * For ARM: See Documentation/virtual/kvm/api.txt
+ * For ARM: See Documentation/virt/kvm/api.txt
*/
union {
__u32 irq;
@@ -1086,7 +1086,7 @@ struct kvm_xen_hvm_config {
*
* KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
* the irqfd to operate in resampling mode for level triggered interrupt
- * emulation. See Documentation/virtual/kvm/api.txt.
+ * emulation. See Documentation/virt/kvm/api.txt.
*/
#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
diff --git a/include/uapi/linux/netfilter/nf_synproxy.h b/include/uapi/linux/netfilter/nf_synproxy.h
index 6f3791c8946f..00d787f0260e 100644
--- a/include/uapi/linux/netfilter/nf_synproxy.h
+++ b/include/uapi/linux/netfilter/nf_synproxy.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _NF_SYNPROXY_H
#define _NF_SYNPROXY_H
diff --git a/include/uapi/linux/netfilter/xt_connlabel.h b/include/uapi/linux/netfilter/xt_connlabel.h
index 2312f0ec07b2..323f0dfc2a4e 100644
--- a/include/uapi/linux/netfilter/xt_connlabel.h
+++ b/include/uapi/linux/netfilter/xt_connlabel.h
@@ -1,4 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _UAPI_XT_CONNLABEL_H
+#define _UAPI_XT_CONNLABEL_H
+
#include <linux/types.h>
#define XT_CONNLABEL_MAXBIT 127
@@ -11,3 +15,5 @@ struct xt_connlabel_mtinfo {
__u16 bit;
__u16 options;
};
+
+#endif /* _UAPI_XT_CONNLABEL_H */
diff --git a/include/uapi/linux/netfilter/xt_nfacct.h b/include/uapi/linux/netfilter/xt_nfacct.h
index 5c8a4d760ee3..b5123ab8d54a 100644
--- a/include/uapi/linux/netfilter/xt_nfacct.h
+++ b/include/uapi/linux/netfilter/xt_nfacct.h
@@ -11,4 +11,9 @@ struct xt_nfacct_match_info {
struct nf_acct *nfacct;
};
+struct xt_nfacct_match_info_v1 {
+ char name[NFACCT_NAME_MAX];
+ struct nf_acct *nfacct __attribute__((aligned(8)));
+};
+
#endif /* _XT_NFACCT_MATCH_H */
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 7198ddd0c6b1..bb7b271397a6 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -374,7 +374,8 @@ struct perf_event_attr {
namespaces : 1, /* include namespaces data */
ksymbol : 1, /* include ksymbol events */
bpf_event : 1, /* include bpf events */
- __reserved_1 : 33;
+ aux_output : 1, /* generate AUX records instead of events */
+ __reserved_1 : 32;
union {
__u32 wakeup_events; /* wakeup every n events */
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 094bb03b9cc2..7da1b37b27aa 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -181,7 +181,7 @@ struct prctl_mm_map {
#define PR_GET_THP_DISABLE 42
/*
- * Tell the kernel to start/stop helping userspace manage bounds tables.
+ * No longer implemented, but left here to ensure the numbers stay reserved:
*/
#define PR_MPX_ENABLE_MANAGEMENT 43
#define PR_MPX_DISABLE_MANAGEMENT 44
@@ -229,4 +229,9 @@ struct prctl_mm_map {
# define PR_PAC_APDBKEY (1UL << 3)
# define PR_PAC_APGAKEY (1UL << 4)
+/* Tagged user address controls for arm64 */
+#define PR_SET_TAGGED_ADDR_CTRL 55
+#define PR_GET_TAGGED_ADDR_CTRL 56
+# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+
#endif /* _LINUX_PRCTL_H */
diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h
index 8654b2442f6a..592a0c1b77c9 100644
--- a/include/uapi/linux/psp-sev.h
+++ b/include/uapi/linux/psp-sev.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Userspace interface for AMD Secure Encrypted Virtualization (SEV)
* platform management commands.
diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
index fd6b5f66e2c5..cba368e55863 100644
--- a/include/uapi/linux/rds.h
+++ b/include/uapi/linux/rds.h
@@ -250,6 +250,7 @@ struct rds_info_rdma_connection {
__u32 rdma_mr_max;
__u32 rdma_mr_size;
__u8 tos;
+ __u8 sl;
__u32 cache_allocs;
};
@@ -265,6 +266,7 @@ struct rds6_info_rdma_connection {
__u32 rdma_mr_max;
__u32 rdma_mr_size;
__u8 tos;
+ __u8 sl;
__u32 cache_allocs;
};
diff --git a/include/uapi/linux/rxrpc.h b/include/uapi/linux/rxrpc.h
index 782069dcf607..4accfa7e266d 100644
--- a/include/uapi/linux/rxrpc.h
+++ b/include/uapi/linux/rxrpc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
/* Types and definitions for AF_RXRPC.
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 5642c05e0da0..3cc3af1c2ee1 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -150,9 +150,6 @@
#define PORT_PNX8XXX 70
-/* Hilscher netx */
-#define PORT_NETX 71
-
/* SUN4V Hypervisor Console */
#define PORT_SUNHV 72
diff --git a/include/uapi/linux/socket.h b/include/uapi/linux/socket.h
index 8eb96021709c..c3409c8ec0dd 100644
--- a/include/uapi/linux/socket.h
+++ b/include/uapi/linux/socket.h
@@ -6,17 +6,24 @@
* Desired design of maximum size and alignment (see RFC2553)
*/
#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
-#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
- /* Implementation specific desired alignment */
typedef unsigned short __kernel_sa_family_t;
+/*
+ * The definition uses anonymous union and struct in order to control the
+ * default alignment.
+ */
struct __kernel_sockaddr_storage {
- __kernel_sa_family_t ss_family; /* address family */
- /* Following field(s) are implementation specific */
- char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+ union {
+ struct {
+ __kernel_sa_family_t ss_family; /* address family */
+ /* Following field(s) are implementation specific */
+ char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
/* space to achieve desired size, */
/* _SS_MAXSIZE value minus size of ss_family */
-} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
+ };
+ void *__align; /* implementation specific desired alignment */
+ };
+};
#endif /* _UAPI_LINUX_SOCKET_H */
diff --git a/include/uapi/linux/usb/g_uvc.h b/include/uapi/linux/usb/g_uvc.h
index 3c9ee3020cbb..652f169a019e 100644
--- a/include/uapi/linux/usb/g_uvc.h
+++ b/include/uapi/linux/usb/g_uvc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* g_uvc.h -- USB Video Class Gadget driver API
*
diff --git a/include/uapi/linux/vbox_vmmdev_types.h b/include/uapi/linux/vbox_vmmdev_types.h
index 26f39816af14..c27289fd619a 100644
--- a/include/uapi/linux/vbox_vmmdev_types.h
+++ b/include/uapi/linux/vbox_vmmdev_types.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR CDDL-1.0) */
/*
* Virtual Device for Guest <-> VMM/Host communication, type definitions
* which are also used for the vboxguest ioctl interface / by vboxsf
diff --git a/include/uapi/linux/vboxguest.h b/include/uapi/linux/vboxguest.h
index 612f0c7d3558..9cec58a6a5ea 100644
--- a/include/uapi/linux/vboxguest.h
+++ b/include/uapi/linux/vboxguest.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR CDDL-1.0) */
/*
* VBoxGuest - VirtualBox Guest Additions Driver Interface.
*
diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index ba1b460c9944..237e36a280cb 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
- * Virtio-iommu definition v0.9
+ * Virtio-iommu definition v0.12
*
- * Copyright (C) 2018 Arm Ltd.
+ * Copyright (C) 2019 Arm Ltd.
*/
#ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
#define _UAPI_LINUX_VIRTIO_IOMMU_H
@@ -11,26 +11,31 @@
/* Feature bits */
#define VIRTIO_IOMMU_F_INPUT_RANGE 0
-#define VIRTIO_IOMMU_F_DOMAIN_BITS 1
+#define VIRTIO_IOMMU_F_DOMAIN_RANGE 1
#define VIRTIO_IOMMU_F_MAP_UNMAP 2
#define VIRTIO_IOMMU_F_BYPASS 3
#define VIRTIO_IOMMU_F_PROBE 4
+#define VIRTIO_IOMMU_F_MMIO 5
-struct virtio_iommu_range {
- __u64 start;
- __u64 end;
+struct virtio_iommu_range_64 {
+ __le64 start;
+ __le64 end;
+};
+
+struct virtio_iommu_range_32 {
+ __le32 start;
+ __le32 end;
};
struct virtio_iommu_config {
/* Supported page sizes */
- __u64 page_size_mask;
+ __le64 page_size_mask;
/* Supported IOVA range */
- struct virtio_iommu_range input_range;
+ struct virtio_iommu_range_64 input_range;
/* Max domain ID size */
- __u8 domain_bits;
- __u8 padding[3];
+ struct virtio_iommu_range_32 domain_range;
/* Probe buffer size */
- __u32 probe_size;
+ __le32 probe_size;
};
/* Request types */
@@ -49,6 +54,7 @@ struct virtio_iommu_config {
#define VIRTIO_IOMMU_S_RANGE 0x05
#define VIRTIO_IOMMU_S_NOENT 0x06
#define VIRTIO_IOMMU_S_FAULT 0x07
+#define VIRTIO_IOMMU_S_NOMEM 0x08
struct virtio_iommu_req_head {
__u8 type;
@@ -78,12 +84,10 @@ struct virtio_iommu_req_detach {
#define VIRTIO_IOMMU_MAP_F_READ (1 << 0)
#define VIRTIO_IOMMU_MAP_F_WRITE (1 << 1)
-#define VIRTIO_IOMMU_MAP_F_EXEC (1 << 2)
-#define VIRTIO_IOMMU_MAP_F_MMIO (1 << 3)
+#define VIRTIO_IOMMU_MAP_F_MMIO (1 << 2)
#define VIRTIO_IOMMU_MAP_F_MASK (VIRTIO_IOMMU_MAP_F_READ | \
VIRTIO_IOMMU_MAP_F_WRITE | \
- VIRTIO_IOMMU_MAP_F_EXEC | \
VIRTIO_IOMMU_MAP_F_MMIO)
struct virtio_iommu_req_map {
diff --git a/include/uapi/linux/virtio_pmem.h b/include/uapi/linux/virtio_pmem.h
index 9a63ed6d062f..b022787ffb94 100644
--- a/include/uapi/linux/virtio_pmem.h
+++ b/include/uapi/linux/virtio_pmem.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
/*
* Definitions for virtio-pmem devices.
*
diff --git a/include/uapi/linux/vmcore.h b/include/uapi/linux/vmcore.h
index 022619668e0e..3e9da91866ff 100644
--- a/include/uapi/linux/vmcore.h
+++ b/include/uapi/linux/vmcore.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_VMCORE_H
#define _UAPI_VMCORE_H
diff --git a/include/uapi/linux/wait.h b/include/uapi/linux/wait.h
index ac49a220cf2a..85b809fc9f11 100644
--- a/include/uapi/linux/wait.h
+++ b/include/uapi/linux/wait.h
@@ -17,6 +17,7 @@
#define P_ALL 0
#define P_PID 1
#define P_PGID 2
+#define P_PIDFD 3
#endif /* _UAPI_LINUX_WAIT_H */
diff --git a/include/uapi/linux/wmi.h b/include/uapi/linux/wmi.h
index c36f2d7675a4..7085c5dca9fa 100644
--- a/include/uapi/linux/wmi.h
+++ b/include/uapi/linux/wmi.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* User API methods for ACPI-WMI mapping driver
*
diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h
index 6d701af9fc42..fb792e882cef 100644
--- a/include/uapi/misc/fastrpc.h
+++ b/include/uapi/misc/fastrpc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __QCOM_FASTRPC_H__
#define __QCOM_FASTRPC_H__
diff --git a/include/uapi/rdma/rvt-abi.h b/include/uapi/rdma/rvt-abi.h
index 7328293c715c..7c05a02d2be5 100644
--- a/include/uapi/rdma/rvt-abi.h
+++ b/include/uapi/rdma/rvt-abi.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file contains defines, structures, etc. that are used
diff --git a/include/uapi/rdma/siw-abi.h b/include/uapi/rdma/siw-abi.h
index 3dd8071ace7b..af735f55b291 100644
--- a/include/uapi/rdma/siw-abi.h
+++ b/include/uapi/rdma/siw-abi.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) or BSD-3-Clause */
/* Authors: Bernard Metzler <bmt@zurich.ibm.com> */
/* Copyright (c) 2008-2019, IBM Corporation */
@@ -180,6 +180,7 @@ struct siw_cqe {
* to control CQ arming.
*/
struct siw_cq_ctrl {
- __aligned_u64 notify;
+ __u32 flags;
+ __u32 pad;
};
#endif
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 17c7abd0803a..9988db6ad244 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* UFS Transport SGIO v4 BSG Message Support
*
diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h
index f39352cef382..9eee32f5e407 100644
--- a/include/uapi/sound/skl-tplg-interface.h
+++ b/include/uapi/sound/skl-tplg-interface.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* skl-tplg-interface.h - Intel DSP FW private data interface
*
diff --git a/include/uapi/sound/sof/fw.h b/include/uapi/sound/sof/fw.h
index 1afca973eb09..e9f697467a86 100644
--- a/include/uapi/sound/sof/fw.h
+++ b/include/uapi/sound/sof/fw.h
@@ -13,6 +13,8 @@
#ifndef __INCLUDE_UAPI_SOF_FW_H__
#define __INCLUDE_UAPI_SOF_FW_H__
+#include <linux/types.h>
+
#define SND_SOF_FW_SIG_SIZE 4
#define SND_SOF_FW_ABI 1
#define SND_SOF_FW_SIG "Reef"
@@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type {
struct snd_sof_blk_hdr {
enum snd_sof_fw_blk_type type;
- uint32_t size; /* bytes minus this header */
- uint32_t offset; /* offset from base */
+ __u32 size; /* bytes minus this header */
+ __u32 offset; /* offset from base */
} __packed;
/*
@@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type {
struct snd_sof_mod_hdr {
enum snd_sof_fw_mod_type type;
- uint32_t size; /* bytes minus this header */
- uint32_t num_blocks; /* number of blocks */
+ __u32 size; /* bytes minus this header */
+ __u32 num_blocks; /* number of blocks */
} __packed;
/*
@@ -70,9 +72,9 @@ struct snd_sof_mod_hdr {
*/
struct snd_sof_fw_header {
unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
- uint32_t file_size; /* size of file minus this header */
- uint32_t num_modules; /* number of modules */
- uint32_t abi; /* version of header format */
+ __u32 file_size; /* size of file minus this header */
+ __u32 num_modules; /* number of modules */
+ __u32 abi; /* version of header format */
} __packed;
#endif
diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h
index 7868990b0d6f..5f4518e7a972 100644
--- a/include/uapi/sound/sof/header.h
+++ b/include/uapi/sound/sof/header.h
@@ -9,6 +9,8 @@
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
+#include <linux/types.h>
+
/*
* Header for all non IPC ABI data.
*
@@ -16,12 +18,12 @@
* Used by any bespoke component data structures or binary blobs.
*/
struct sof_abi_hdr {
- uint32_t magic; /**< 'S', 'O', 'F', '\0' */
- uint32_t type; /**< component specific type */
- uint32_t size; /**< size in bytes of data excl. this struct */
- uint32_t abi; /**< SOF ABI version */
- uint32_t reserved[4]; /**< reserved for future use */
- uint32_t data[0]; /**< Component data - opaque to core */
+ __u32 magic; /**< 'S', 'O', 'F', '\0' */
+ __u32 type; /**< component specific type */
+ __u32 size; /**< size in bytes of data excl. this struct */
+ __u32 abi; /**< SOF ABI version */
+ __u32 reserved[4]; /**< reserved for future use */
+ __u32 data[0]; /**< Component data - opaque to core */
} __packed;
#endif
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
index efed3c3383d6..1d19ae62b844 100644
--- a/include/video/da8xx-fb.h
+++ b/include/video/da8xx-fb.h
@@ -32,7 +32,6 @@ struct da8xx_lcdc_platform_data {
const char manu_name[10];
void *controller_data;
const char type[25];
- void (*panel_power_ctrl)(int);
};
struct lcd_ctrl_config {
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 4969817124a8..98b30c1613b2 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -109,6 +109,9 @@ static inline int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
}
#endif
+int xen_remap_vma_range(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long len);
+
/*
* xen_remap_domain_gfn_array() - map an array of foreign frames by gfn
* @vma: VMA to map the pages into
diff --git a/init/Kconfig b/init/Kconfig
index bd7d650d4a99..ec1021fd3371 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -30,6 +30,9 @@ config CC_CAN_LINK
config CC_HAS_ASM_GOTO
def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC))
+config TOOLS_SUPPORT_RELR
+ def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh)
+
config CC_HAS_WARN_MAYBE_UNINITIALIZED
def_bool $(cc-option,-Wmaybe-uninitialized)
help
@@ -928,6 +931,28 @@ config RT_GROUP_SCHED
endif #CGROUP_SCHED
+config UCLAMP_TASK_GROUP
+ bool "Utilization clamping per group of tasks"
+ depends on CGROUP_SCHED
+ depends on UCLAMP_TASK
+ default n
+ help
+ This feature enables the scheduler to track the clamped utilization
+ of each CPU based on RUNNABLE tasks currently scheduled on that CPU.
+
+ When this option is enabled, the user can specify a min and max
+ CPU bandwidth which is allowed for each single task in a group.
+ The max bandwidth allows to clamp the maximum frequency a task
+ can use, while the min bandwidth allows to define a minimum
+ frequency a task will always use.
+
+ When task group based utilization clamping is enabled, an eventually
+ specified task-specific clamp value is constrained by the cgroup
+ specified clamp value. Both minimum and maximum task clamping cannot
+ be bigger than the corresponding clamping defined at task group level.
+
+ If in doubt, say N.
+
config CGROUP_PIDS
bool "PIDs controller"
help
diff --git a/init/init_task.c b/init/init_task.c
index d49692a0ec51..9e5cbe5eab7b 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -172,7 +172,7 @@ struct task_struct init_task
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.ret_stack = NULL,
#endif
-#if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPT)
+#if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPTION)
.trace_recursion = 0,
#endif
#ifdef CONFIG_LIVEPATCH
diff --git a/init/main.c b/init/main.c
index 96f8d5af52d6..653693da8da6 100644
--- a/init/main.c
+++ b/init/main.c
@@ -433,7 +433,7 @@ noinline void __ref rest_init(void)
/*
* Enable might_sleep() and smp_processor_id() checks.
- * They cannot be enabled earlier because with CONFIG_PREEMPT=y
+ * They cannot be enabled earlier because with CONFIG_PREEMPTION=y
* kernel_thread() would trigger might_sleep() splats. With
* CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled
* already, but it's stuck on the kthreadd_done completion.
diff --git a/ipc/util.h b/ipc/util.h
index 0fcf8e719b76..5766c61aed0e 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -276,29 +276,7 @@ static inline int compat_ipc_parse_version(int *cmd)
*cmd &= ~IPC_64;
return version;
}
-#endif
-/* for __ARCH_WANT_SYS_IPC */
-long ksys_semtimedop(int semid, struct sembuf __user *tsops,
- unsigned int nsops,
- const struct __kernel_timespec __user *timeout);
-long ksys_semget(key_t key, int nsems, int semflg);
-long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
-long ksys_msgget(key_t key, int msgflg);
-long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
-long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
- long msgtyp, int msgflg);
-long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
- int msgflg);
-long ksys_shmget(key_t key, size_t size, int shmflg);
-long ksys_shmdt(char __user *shmaddr);
-long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
-
-/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
-long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
- unsigned int nsops,
- const struct old_timespec32 __user *timeout);
-#ifdef CONFIG_COMPAT
long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg);
long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr);
long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
@@ -306,6 +284,7 @@ long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp,
compat_ssize_t msgsz, int msgflg);
long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr);
-#endif /* CONFIG_COMPAT */
+
+#endif
#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index a8d923b5481b..48c5376d290a 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_CRASH_CORE) += crash_core.o
obj-$(CONFIG_KEXEC_CORE) += kexec_core.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
+obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o
obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_CGROUPS) += cgroup/
@@ -111,7 +112,6 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
obj-$(CONFIG_TORTURE_TEST) += torture.o
obj-$(CONFIG_HAS_IOMEM) += iomem.o
-obj-$(CONFIG_ZONE_DEVICE) += memremap.o
obj-$(CONFIG_RSEQ) += rseq.o
obj-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak.o
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 8191a7db2777..66088a9e9b9e 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -890,7 +890,8 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog,
static int bpf_jit_blind_insn(const struct bpf_insn *from,
const struct bpf_insn *aux,
- struct bpf_insn *to_buff)
+ struct bpf_insn *to_buff,
+ bool emit_zext)
{
struct bpf_insn *to = to_buff;
u32 imm_rnd = get_random_int();
@@ -1005,6 +1006,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from,
case 0: /* Part 2 of BPF_LD | BPF_IMM | BPF_DW. */
*to++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ aux[0].imm);
*to++ = BPF_ALU32_IMM(BPF_XOR, BPF_REG_AX, imm_rnd);
+ if (emit_zext)
+ *to++ = BPF_ZEXT_REG(BPF_REG_AX);
*to++ = BPF_ALU64_REG(BPF_OR, aux[0].dst_reg, BPF_REG_AX);
break;
@@ -1088,7 +1091,8 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
insn[1].code == 0)
memcpy(aux, insn, sizeof(aux));
- rewritten = bpf_jit_blind_insn(insn, aux, insn_buff);
+ rewritten = bpf_jit_blind_insn(insn, aux, insn_buff,
+ clone->aux->verifier_zext);
if (!rewritten)
continue;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5d141f16f6fa..272071e9112f 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1707,20 +1707,26 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
if (err)
goto free_used_maps;
- err = bpf_prog_new_fd(prog);
- if (err < 0) {
- /* failed to allocate fd.
- * bpf_prog_put() is needed because the above
- * bpf_prog_alloc_id() has published the prog
- * to the userspace and the userspace may
- * have refcnt-ed it through BPF_PROG_GET_FD_BY_ID.
- */
- bpf_prog_put(prog);
- return err;
- }
-
+ /* Upon success of bpf_prog_alloc_id(), the BPF prog is
+ * effectively publicly exposed. However, retrieving via
+ * bpf_prog_get_fd_by_id() will take another reference,
+ * therefore it cannot be gone underneath us.
+ *
+ * Only for the time /after/ successful bpf_prog_new_fd()
+ * and before returning to userspace, we might just hold
+ * one reference and any parallel close on that fd could
+ * rip everything out. Hence, below notifications must
+ * happen before bpf_prog_new_fd().
+ *
+ * Also, any failure handling from this point onwards must
+ * be using bpf_prog_put() given the program is exposed.
+ */
bpf_prog_kallsyms_add(prog);
perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
+
+ err = bpf_prog_new_fd(prog);
+ if (err < 0)
+ bpf_prog_put(prog);
return err;
free_used_maps:
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5900cbb966b1..c36a719fee6d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -985,9 +985,6 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg)
reg->smax_value = S64_MAX;
reg->umin_value = 0;
reg->umax_value = U64_MAX;
-
- /* constant backtracking is enabled for root only for now */
- reg->precise = capable(CAP_SYS_ADMIN) ? false : true;
}
/* Mark a register as having a completely unknown (scalar) value. */
@@ -1014,7 +1011,11 @@ static void mark_reg_unknown(struct bpf_verifier_env *env,
__mark_reg_not_init(regs + regno);
return;
}
- __mark_reg_unknown(regs + regno);
+ regs += regno;
+ __mark_reg_unknown(regs);
+ /* constant backtracking is enabled for root without bpf2bpf calls */
+ regs->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
+ true : false;
}
static void __mark_reg_not_init(struct bpf_reg_state *reg)
@@ -1771,16 +1772,21 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
bitmap_from_u64(mask, stack_mask);
for_each_set_bit(i, mask, 64) {
if (i >= func->allocated_stack / BPF_REG_SIZE) {
- /* This can happen if backtracking
- * is propagating stack precision where
- * caller has larger stack frame
- * than callee, but backtrack_insn() should
- * have returned -ENOTSUPP.
+ /* the sequence of instructions:
+ * 2: (bf) r3 = r10
+ * 3: (7b) *(u64 *)(r3 -8) = r0
+ * 4: (79) r4 = *(u64 *)(r10 -8)
+ * doesn't contain jmps. It's backtracked
+ * as a single block.
+ * During backtracking insn 3 is not recognized as
+ * stack access, so at the end of backtracking
+ * stack slot fp-8 is still marked in stack_mask.
+ * However the parent state may not have accessed
+ * fp-8 and it's "unallocated" stack space.
+ * In such case fallback to conservative.
*/
- verbose(env, "BUG spi %d stack_size %d\n",
- i, func->allocated_stack);
- WARN_ONCE(1, "verifier backtracking bug");
- return -EFAULT;
+ mark_all_scalars_precise(env, st);
+ return 0;
}
if (func->stack[i].slot_type[0] != STACK_SPILL) {
@@ -8616,8 +8622,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
}
if (is_narrower_load && size < target_size) {
- u8 shift = (off & (size_default - 1)) * 8;
-
+ u8 shift = bpf_ctx_narrow_load_shift(off, size,
+ size_default);
if (ctx_field_size <= 4) {
if (shift)
insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH,
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 753afbca549f..a7ce73a2c401 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1891,7 +1891,7 @@ static int cgroup_reconfigure(struct fs_context *fc)
*/
static bool use_task_css_set_links __read_mostly;
-static void cgroup_enable_task_cg_lists(void)
+void cgroup_enable_task_cg_lists(void)
{
struct task_struct *p, *g;
@@ -5255,8 +5255,16 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
* if the parent has to be frozen, the child has too.
*/
cgrp->freezer.e_freeze = parent->freezer.e_freeze;
- if (cgrp->freezer.e_freeze)
+ if (cgrp->freezer.e_freeze) {
+ /*
+ * Set the CGRP_FREEZE flag, so when a process will be
+ * attached to the child cgroup, it will become frozen.
+ * At this point the new cgroup is unpopulated, so we can
+ * consider it frozen immediately.
+ */
+ set_bit(CGRP_FREEZE, &cgrp->flags);
set_bit(CGRP_FROZEN, &cgrp->flags);
+ }
spin_lock_irq(&css_set_lock);
for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 5aa37531ce76..c52bc91f882b 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -45,6 +45,7 @@
#include <linux/proc_fs.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
+#include <linux/sched/deadline.h>
#include <linux/sched/mm.h>
#include <linux/sched/task.h>
#include <linux/seq_file.h>
@@ -332,7 +333,18 @@ static struct cpuset top_cpuset = {
* guidelines for accessing subsystem state in kernel/cgroup.c
*/
-static DEFINE_MUTEX(cpuset_mutex);
+DEFINE_STATIC_PERCPU_RWSEM(cpuset_rwsem);
+
+void cpuset_read_lock(void)
+{
+ percpu_down_read(&cpuset_rwsem);
+}
+
+void cpuset_read_unlock(void)
+{
+ percpu_up_read(&cpuset_rwsem);
+}
+
static DEFINE_SPINLOCK(callback_lock);
static struct workqueue_struct *cpuset_migrate_mm_wq;
@@ -894,6 +906,67 @@ done:
return ndoms;
}
+static void update_tasks_root_domain(struct cpuset *cs)
+{
+ struct css_task_iter it;
+ struct task_struct *task;
+
+ css_task_iter_start(&cs->css, 0, &it);
+
+ while ((task = css_task_iter_next(&it)))
+ dl_add_task_root_domain(task);
+
+ css_task_iter_end(&it);
+}
+
+static void rebuild_root_domains(void)
+{
+ struct cpuset *cs = NULL;
+ struct cgroup_subsys_state *pos_css;
+
+ percpu_rwsem_assert_held(&cpuset_rwsem);
+ lockdep_assert_cpus_held();
+ lockdep_assert_held(&sched_domains_mutex);
+
+ cgroup_enable_task_cg_lists();
+
+ rcu_read_lock();
+
+ /*
+ * Clear default root domain DL accounting, it will be computed again
+ * if a task belongs to it.
+ */
+ dl_clear_root_domain(&def_root_domain);
+
+ cpuset_for_each_descendant_pre(cs, pos_css, &top_cpuset) {
+
+ if (cpumask_empty(cs->effective_cpus)) {
+ pos_css = css_rightmost_descendant(pos_css);
+ continue;
+ }
+
+ css_get(&cs->css);
+
+ rcu_read_unlock();
+
+ update_tasks_root_domain(cs);
+
+ rcu_read_lock();
+ css_put(&cs->css);
+ }
+ rcu_read_unlock();
+}
+
+static void
+partition_and_rebuild_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
+ struct sched_domain_attr *dattr_new)
+{
+ mutex_lock(&sched_domains_mutex);
+ partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
+ rebuild_root_domains();
+ mutex_unlock(&sched_domains_mutex);
+}
+
/*
* Rebuild scheduler domains.
*
@@ -911,8 +984,8 @@ static void rebuild_sched_domains_locked(void)
cpumask_var_t *doms;
int ndoms;
- lockdep_assert_held(&cpuset_mutex);
- get_online_cpus();
+ lockdep_assert_cpus_held();
+ percpu_rwsem_assert_held(&cpuset_rwsem);
/*
* We have raced with CPU hotplug. Don't do anything to avoid
@@ -921,19 +994,17 @@ static void rebuild_sched_domains_locked(void)
*/
if (!top_cpuset.nr_subparts_cpus &&
!cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask))
- goto out;
+ return;
if (top_cpuset.nr_subparts_cpus &&
!cpumask_subset(top_cpuset.effective_cpus, cpu_active_mask))
- goto out;
+ return;
/* Generate domain masks and attrs */
ndoms = generate_sched_domains(&doms, &attr);
/* Have scheduler rebuild the domains */
- partition_sched_domains(ndoms, doms, attr);
-out:
- put_online_cpus();
+ partition_and_rebuild_sched_domains(ndoms, doms, attr);
}
#else /* !CONFIG_SMP */
static void rebuild_sched_domains_locked(void)
@@ -943,9 +1014,11 @@ static void rebuild_sched_domains_locked(void)
void rebuild_sched_domains(void)
{
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
rebuild_sched_domains_locked();
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
}
/**
@@ -1051,7 +1124,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
int deleting; /* Moving cpus from subparts_cpus to effective_cpus */
bool part_error = false; /* Partition error? */
- lockdep_assert_held(&cpuset_mutex);
+ percpu_rwsem_assert_held(&cpuset_rwsem);
/*
* The parent must be a partition root.
@@ -2039,7 +2112,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
cs = css_cs(css);
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
/* allow moving tasks into an empty cpuset if on default hierarchy */
ret = -ENOSPC;
@@ -2063,7 +2136,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
cs->attach_in_progress++;
ret = 0;
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
return ret;
}
@@ -2073,9 +2146,9 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
cgroup_taskset_first(tset, &css);
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
css_cs(css)->attach_in_progress--;
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
}
/*
@@ -2098,7 +2171,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cgroup_taskset_first(tset, &css);
cs = css_cs(css);
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
/* prepare for attach */
if (cs == &top_cpuset)
@@ -2152,7 +2225,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
}
/* The various types of files and directories in a cpuset file system */
@@ -2183,7 +2256,8 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = 0;
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
if (!is_cpuset_online(cs)) {
retval = -ENODEV;
goto out_unlock;
@@ -2219,7 +2293,8 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
break;
}
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
return retval;
}
@@ -2230,7 +2305,8 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = -ENODEV;
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
if (!is_cpuset_online(cs))
goto out_unlock;
@@ -2243,7 +2319,8 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
break;
}
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
return retval;
}
@@ -2282,7 +2359,8 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
kernfs_break_active_protection(of->kn);
flush_work(&cpuset_hotplug_work);
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
if (!is_cpuset_online(cs))
goto out_unlock;
@@ -2306,7 +2384,8 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
free_cpuset(trialcs);
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
kernfs_unbreak_active_protection(of->kn);
css_put(&cs->css);
flush_workqueue(cpuset_migrate_mm_wq);
@@ -2437,13 +2516,15 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf,
return -EINVAL;
css_get(&cs->css);
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
if (!is_cpuset_online(cs))
goto out_unlock;
retval = update_prstate(cs, val);
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
css_put(&cs->css);
return retval ?: nbytes;
}
@@ -2649,7 +2730,8 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
if (!parent)
return 0;
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
set_bit(CS_ONLINE, &cs->flags);
if (is_spread_page(parent))
@@ -2700,7 +2782,8 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
cpumask_copy(cs->effective_cpus, parent->cpus_allowed);
spin_unlock_irq(&callback_lock);
out_unlock:
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
return 0;
}
@@ -2719,7 +2802,8 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css)
{
struct cpuset *cs = css_cs(css);
- mutex_lock(&cpuset_mutex);
+ get_online_cpus();
+ percpu_down_write(&cpuset_rwsem);
if (is_partition_root(cs))
update_prstate(cs, 0);
@@ -2738,7 +2822,8 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css)
cpuset_dec();
clear_bit(CS_ONLINE, &cs->flags);
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
+ put_online_cpus();
}
static void cpuset_css_free(struct cgroup_subsys_state *css)
@@ -2750,7 +2835,7 @@ static void cpuset_css_free(struct cgroup_subsys_state *css)
static void cpuset_bind(struct cgroup_subsys_state *root_css)
{
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
spin_lock_irq(&callback_lock);
if (is_in_v2_mode()) {
@@ -2763,7 +2848,7 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
}
spin_unlock_irq(&callback_lock);
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
}
/*
@@ -2805,6 +2890,8 @@ struct cgroup_subsys cpuset_cgrp_subsys = {
int __init cpuset_init(void)
{
+ BUG_ON(percpu_init_rwsem(&cpuset_rwsem));
+
BUG_ON(!alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_KERNEL));
BUG_ON(!alloc_cpumask_var(&top_cpuset.effective_cpus, GFP_KERNEL));
BUG_ON(!zalloc_cpumask_var(&top_cpuset.subparts_cpus, GFP_KERNEL));
@@ -2876,7 +2963,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs,
is_empty = cpumask_empty(cs->cpus_allowed) ||
nodes_empty(cs->mems_allowed);
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
/*
* Move tasks to the nearest ancestor with execution resources,
@@ -2886,7 +2973,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs,
if (is_empty)
remove_tasks_in_empty_cpuset(cs);
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
}
static void
@@ -2936,14 +3023,14 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
retry:
wait_event(cpuset_attach_wq, cs->attach_in_progress == 0);
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
/*
* We have raced with task attaching. We wait until attaching
* is finished, so we won't attach a task to an empty cpuset.
*/
if (cs->attach_in_progress) {
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
goto retry;
}
@@ -3011,7 +3098,7 @@ update_tasks:
hotplug_update_tasks_legacy(cs, &new_cpus, &new_mems,
cpus_updated, mems_updated);
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
}
/**
@@ -3041,7 +3128,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
if (on_dfl && !alloc_cpumasks(NULL, &tmp))
ptmp = &tmp;
- mutex_lock(&cpuset_mutex);
+ percpu_down_write(&cpuset_rwsem);
/* fetch the available cpus/mems and find out which changed how */
cpumask_copy(&new_cpus, cpu_active_mask);
@@ -3091,7 +3178,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
update_tasks_nodemask(&top_cpuset);
}
- mutex_unlock(&cpuset_mutex);
+ percpu_up_write(&cpuset_rwsem);
/* if cpus or mems changed, we need to propagate to descendants */
if (cpus_updated || mems_updated) {
diff --git a/kernel/configs.c b/kernel/configs.c
index b062425ccf8d..c09ea4c995e1 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* kernel/configs.c
* Echo the kernel .config file used to build the kernel
@@ -6,21 +7,6 @@
* Copyright (C) 2002 Randy Dunlap <rdunlap@xenotime.net>
* Copyright (C) 2002 Al Stone <ahs3@fc.hp.com>
* Copyright (C) 2002 Hewlett-Packard Company
- *
- * 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.
*/
#include <linux/kernel.h>
diff --git a/kernel/cpu.c b/kernel/cpu.c
index e84c0873559e..e1967e9eddc2 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -62,7 +62,6 @@ struct cpuhp_cpu_state {
bool rollback;
bool single;
bool bringup;
- bool booted_once;
struct hlist_node *node;
struct hlist_node *last;
enum cpuhp_state cb_state;
@@ -76,6 +75,10 @@ static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = {
.fail = CPUHP_INVALID,
};
+#ifdef CONFIG_SMP
+cpumask_t cpus_booted_once_mask;
+#endif
+
#if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP)
static struct lockdep_map cpuhp_state_up_map =
STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map);
@@ -433,7 +436,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu)
* CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any
* core will shutdown the machine.
*/
- return !per_cpu(cpuhp_state, cpu).booted_once;
+ return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
}
#else
static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
@@ -1066,7 +1069,7 @@ void notify_cpu_starting(unsigned int cpu)
int ret;
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
- st->booted_once = true;
+ cpumask_set_cpu(cpu, &cpus_booted_once_mask);
while (st->state < target) {
st->state++;
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
@@ -2295,6 +2298,9 @@ EXPORT_SYMBOL(__cpu_present_mask);
struct cpumask __cpu_active_mask __read_mostly;
EXPORT_SYMBOL(__cpu_active_mask);
+atomic_t __num_online_cpus __read_mostly;
+EXPORT_SYMBOL(__num_online_cpus);
+
void init_cpu_present(const struct cpumask *src)
{
cpumask_copy(&__cpu_present_mask, src);
@@ -2310,6 +2316,27 @@ void init_cpu_online(const struct cpumask *src)
cpumask_copy(&__cpu_online_mask, src);
}
+void set_cpu_online(unsigned int cpu, bool online)
+{
+ /*
+ * atomic_inc/dec() is required to handle the horrid abuse of this
+ * function by the reboot and kexec code which invoke it from
+ * IPI/NMI broadcasts when shutting down CPUs. Invocation from
+ * regular CPU hotplug is properly serialized.
+ *
+ * Note, that the fact that __num_online_cpus is of type atomic_t
+ * does not protect readers which are not serialized against
+ * concurrent hotplug operations.
+ */
+ if (online) {
+ if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask))
+ atomic_inc(&__num_online_cpus);
+ } else {
+ if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask))
+ atomic_dec(&__num_online_cpus);
+ }
+}
+
/*
* Activate the first processor.
*/
@@ -2334,7 +2361,7 @@ void __init boot_cpu_init(void)
void __init boot_cpu_hotplug_init(void)
{
#ifdef CONFIG_SMP
- this_cpu_write(cpuhp_state.booted_once, true);
+ cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
#endif
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
}
diff --git a/kernel/cred.c b/kernel/cred.c
index f9a0ce66c9c3..c0a4c12d38b2 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -144,7 +144,10 @@ void __put_cred(struct cred *cred)
BUG_ON(cred == current->cred);
BUG_ON(cred == current->real_cred);
- call_rcu(&cred->rcu, put_cred_rcu);
+ if (cred->non_rcu)
+ put_cred_rcu(&cred->rcu);
+ else
+ call_rcu(&cred->rcu, put_cred_rcu);
}
EXPORT_SYMBOL(__put_cred);
@@ -261,6 +264,7 @@ struct cred *prepare_creds(void)
old = task->cred;
memcpy(new, old, sizeof(struct cred));
+ new->non_rcu = 0;
atomic_set(&new->usage, 1);
set_cred_subscribers(new, 0);
get_group_info(new->group_info);
@@ -544,7 +548,19 @@ const struct cred *override_creds(const struct cred *new)
validate_creds(old);
validate_creds(new);
- get_cred(new);
+
+ /*
+ * NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
+ *
+ * That means that we do not clear the 'non_rcu' flag, since
+ * we are only installing the cred into the thread-synchronous
+ * '->cred' pointer, not the '->real_cred' pointer that is
+ * visible to other threads under RCU.
+ *
+ * Also note that we did validate_creds() manually, not depending
+ * on the validation in 'get_cred()'.
+ */
+ get_new_cred((struct cred *)new);
alter_cred_subscribers(new, 1);
rcu_assign_pointer(current->cred, new);
alter_cred_subscribers(old, -1);
@@ -681,6 +697,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
validate_creds(old);
*new = *old;
+ new->non_rcu = 0;
atomic_set(&new->usage, 1);
set_cred_subscribers(new, 0);
get_uid(new->user);
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index bfc0c17f2a3d..69cfb4345388 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -230,9 +230,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
*/
struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
{
- int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
- size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- size_t align = get_order(PAGE_ALIGN(size));
+ size_t count = size >> PAGE_SHIFT;
struct page *page = NULL;
struct cma *cma = NULL;
@@ -243,13 +241,12 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
/* CMA can be used only in the context which permits sleeping */
if (cma && gfpflags_allow_blocking(gfp)) {
- align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
- page = cma_alloc(cma, count, align, gfp & __GFP_NOWARN);
+ size_t align = get_order(size);
+ size_t cma_align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
+
+ page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);
}
- /* Fallback allocation of normal pages */
- if (!page)
- page = alloc_pages_node(node, gfp, align);
return page;
}
@@ -266,7 +263,8 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
*/
void dma_free_contiguous(struct device *dev, struct page *page, size_t size)
{
- if (!cma_release(dev_get_cma_area(dev), page, size >> PAGE_SHIFT))
+ if (!cma_release(dev_get_cma_area(dev), page,
+ PAGE_ALIGN(size) >> PAGE_SHIFT))
__free_pages(page, get_order(size));
}
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 59bdceea3737..8402b29c280f 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -47,9 +47,6 @@ u64 dma_direct_get_required_mask(struct device *dev)
{
u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT);
- if (dev->bus_dma_mask && dev->bus_dma_mask < max_dma)
- max_dma = dev->bus_dma_mask;
-
return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
}
@@ -88,6 +85,8 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
+ size_t alloc_size = PAGE_ALIGN(size);
+ int node = dev_to_node(dev);
struct page *page = NULL;
u64 phys_mask;
@@ -98,8 +97,14 @@ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
gfp &= ~__GFP_ZERO;
gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_mask);
+ page = dma_alloc_contiguous(dev, alloc_size, gfp);
+ if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+ dma_free_contiguous(dev, page, alloc_size);
+ page = NULL;
+ }
again:
- page = dma_alloc_contiguous(dev, size, gfp);
+ if (!page)
+ page = alloc_pages_node(node, gfp, get_order(alloc_size));
if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
dma_free_contiguous(dev, page, size);
page = NULL;
@@ -130,10 +135,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
if (!page)
return NULL;
- if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+ if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+ !force_dma_unencrypted(dev)) {
/* remove any dirty cache lines on the kernel alias */
if (!PageHighMem(page))
arch_dma_prep_coherent(page, size);
+ *dma_handle = phys_to_dma(dev, page_to_phys(page));
/* return the page pointer as the opaque cookie */
return page;
}
@@ -178,7 +185,8 @@ void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
{
unsigned int page_order = get_order(size);
- if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+ if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+ !force_dma_unencrypted(dev)) {
/* cpu_addr is a struct page cookie, not a kernel address */
__dma_direct_free_pages(dev, size, cpu_addr);
return;
@@ -297,7 +305,7 @@ void dma_direct_unmap_page(struct device *dev, dma_addr_t addr,
dma_direct_sync_single_for_cpu(dev, addr, size, dir);
if (unlikely(is_swiotlb_buffer(phys)))
- swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
+ swiotlb_tbl_unmap_single(dev, phys, size, size, dir, attrs);
}
EXPORT_SYMBOL(dma_direct_unmap_page);
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 1f628e7ac709..b0038ca3aa92 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -116,11 +116,16 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
int ret;
if (!dev_is_dma_coherent(dev)) {
+ unsigned long pfn;
+
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
- page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr,
- dma_addr));
+ /* If the PFN is not valid, we do not have a struct page */
+ pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+ if (!pfn_valid(pfn))
+ return -ENXIO;
+ page = pfn_to_page(pfn);
} else {
page = virt_to_page(cpu_addr);
}
@@ -145,6 +150,23 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
}
EXPORT_SYMBOL(dma_get_sgtable_attrs);
+#ifdef CONFIG_MMU
+/*
+ * Return the page attributes used for mapping dma_alloc_* memory, either in
+ * kernel space if remapping is needed, or to userspace through dma_mmap_*.
+ */
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs)
+{
+ if (dev_is_dma_coherent(dev) ||
+ (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) &&
+ (attrs & DMA_ATTR_NON_CONSISTENT)))
+ return prot;
+ if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_MMAP_PGPROT))
+ return arch_dma_mmap_pgprot(dev, prot, attrs);
+ return pgprot_noncached(prot);
+}
+#endif /* CONFIG_MMU */
+
/*
* Create userspace mapping for the DMA-coherent memory.
*/
@@ -159,7 +181,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
unsigned long pfn;
int ret = -ENXIO;
- vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+ vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
@@ -170,7 +192,11 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
if (!dev_is_dma_coherent(dev)) {
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
+
+ /* If the PFN is not valid, we do not have a struct page */
pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+ if (!pfn_valid(pfn))
+ return -ENXIO;
} else {
pfn = page_to_pfn(virt_to_page(cpu_addr));
}
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index a594aec07882..ffe78f0b2fe4 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -218,7 +218,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
/* create a coherent mapping */
ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
- arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
+ dma_pgprot(dev, PAGE_KERNEL, attrs),
__builtin_return_address(0));
if (!ret) {
__dma_direct_free_pages(dev, size, page);
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 9de232229063..796a44f8ef5a 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -444,7 +444,9 @@ static void swiotlb_bounce(phys_addr_t orig_addr, phys_addr_t tlb_addr,
phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
dma_addr_t tbl_dma_addr,
- phys_addr_t orig_addr, size_t size,
+ phys_addr_t orig_addr,
+ size_t mapping_size,
+ size_t alloc_size,
enum dma_data_direction dir,
unsigned long attrs)
{
@@ -464,6 +466,12 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
pr_warn_once("%s is active and system is using DMA bounce buffers\n",
sme_active() ? "SME" : "SEV");
+ if (mapping_size > alloc_size) {
+ dev_warn_once(hwdev, "Invalid sizes (mapping: %zd bytes, alloc: %zd bytes)",
+ mapping_size, alloc_size);
+ return (phys_addr_t)DMA_MAPPING_ERROR;
+ }
+
mask = dma_get_seg_boundary(hwdev);
tbl_dma_addr &= mask;
@@ -471,8 +479,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
offset_slots = ALIGN(tbl_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
/*
- * Carefully handle integer overflow which can occur when mask == ~0UL.
- */
+ * Carefully handle integer overflow which can occur when mask == ~0UL.
+ */
max_slots = mask + 1
? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
: 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
@@ -481,8 +489,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
* For mappings greater than or equal to a page, we limit the stride
* (and hence alignment) to a page size.
*/
- nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
- if (size >= PAGE_SIZE)
+ nslots = ALIGN(alloc_size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+ if (alloc_size >= PAGE_SIZE)
stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
else
stride = 1;
@@ -547,7 +555,7 @@ not_found:
spin_unlock_irqrestore(&io_tlb_lock, flags);
if (!(attrs & DMA_ATTR_NO_WARN) && printk_ratelimit())
dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes), total %lu (slots), used %lu (slots)\n",
- size, io_tlb_nslabs, tmp_io_tlb_used);
+ alloc_size, io_tlb_nslabs, tmp_io_tlb_used);
return (phys_addr_t)DMA_MAPPING_ERROR;
found:
io_tlb_used += nslots;
@@ -562,7 +570,7 @@ found:
io_tlb_orig_addr[index+i] = orig_addr + (i << IO_TLB_SHIFT);
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
- swiotlb_bounce(orig_addr, tlb_addr, size, DMA_TO_DEVICE);
+ swiotlb_bounce(orig_addr, tlb_addr, mapping_size, DMA_TO_DEVICE);
return tlb_addr;
}
@@ -571,11 +579,11 @@ found:
* tlb_addr is the physical address of the bounce buffer to unmap.
*/
void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs)
+ size_t mapping_size, size_t alloc_size,
+ enum dma_data_direction dir, unsigned long attrs)
{
unsigned long flags;
- int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+ int i, count, nslots = ALIGN(alloc_size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT;
phys_addr_t orig_addr = io_tlb_orig_addr[index];
@@ -585,7 +593,7 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
if (orig_addr != INVALID_PHYS_ADDR &&
!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
- swiotlb_bounce(orig_addr, tlb_addr, size, DMA_FROM_DEVICE);
+ swiotlb_bounce(orig_addr, tlb_addr, mapping_size, DMA_FROM_DEVICE);
/*
* Return the buffer to the free list by setting the corresponding
@@ -665,14 +673,14 @@ bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
/* Oh well, have to allocate and map a bounce buffer. */
*phys = swiotlb_tbl_map_single(dev, __phys_to_dma(dev, io_tlb_start),
- *phys, size, dir, attrs);
+ *phys, size, size, dir, attrs);
if (*phys == (phys_addr_t)DMA_MAPPING_ERROR)
return false;
/* Ensure that the address returned is DMA'ble */
*dma_addr = __phys_to_dma(dev, *phys);
if (unlikely(!dma_capable(dev, *dma_addr, size))) {
- swiotlb_tbl_unmap_single(dev, *phys, size, dir,
+ swiotlb_tbl_unmap_single(dev, *phys, size, size, dir,
attrs | DMA_ATTR_SKIP_CPU_SYNC);
return false;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9d623e257a51..4f08b17d6426 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1887,6 +1887,89 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
ctx->generation++;
}
+static int
+perf_aux_output_match(struct perf_event *event, struct perf_event *aux_event)
+{
+ if (!has_aux(aux_event))
+ return 0;
+
+ if (!event->pmu->aux_output_match)
+ return 0;
+
+ return event->pmu->aux_output_match(aux_event);
+}
+
+static void put_event(struct perf_event *event);
+static void event_sched_out(struct perf_event *event,
+ struct perf_cpu_context *cpuctx,
+ struct perf_event_context *ctx);
+
+static void perf_put_aux_event(struct perf_event *event)
+{
+ struct perf_event_context *ctx = event->ctx;
+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
+ struct perf_event *iter;
+
+ /*
+ * If event uses aux_event tear down the link
+ */
+ if (event->aux_event) {
+ iter = event->aux_event;
+ event->aux_event = NULL;
+ put_event(iter);
+ return;
+ }
+
+ /*
+ * If the event is an aux_event, tear down all links to
+ * it from other events.
+ */
+ for_each_sibling_event(iter, event->group_leader) {
+ if (iter->aux_event != event)
+ continue;
+
+ iter->aux_event = NULL;
+ put_event(event);
+
+ /*
+ * If it's ACTIVE, schedule it out and put it into ERROR
+ * state so that we don't try to schedule it again. Note
+ * that perf_event_enable() will clear the ERROR status.
+ */
+ event_sched_out(iter, cpuctx, ctx);
+ perf_event_set_state(event, PERF_EVENT_STATE_ERROR);
+ }
+}
+
+static int perf_get_aux_event(struct perf_event *event,
+ struct perf_event *group_leader)
+{
+ /*
+ * Our group leader must be an aux event if we want to be
+ * an aux_output. This way, the aux event will precede its
+ * aux_output events in the group, and therefore will always
+ * schedule first.
+ */
+ if (!group_leader)
+ return 0;
+
+ if (!perf_aux_output_match(event, group_leader))
+ return 0;
+
+ if (!atomic_long_inc_not_zero(&group_leader->refcount))
+ return 0;
+
+ /*
+ * Link aux_outputs to their aux event; this is undone in
+ * perf_group_detach() by perf_put_aux_event(). When the
+ * group in torn down, the aux_output events loose their
+ * link to the aux_event and can't schedule any more.
+ */
+ event->aux_event = group_leader;
+
+ return 1;
+}
+
static void perf_group_detach(struct perf_event *event)
{
struct perf_event *sibling, *tmp;
@@ -1902,6 +1985,8 @@ static void perf_group_detach(struct perf_event *event)
event->attach_state &= ~PERF_ATTACH_GROUP;
+ perf_put_aux_event(event);
+
/*
* If this is a sibling, remove it from its group.
*/
@@ -4089,10 +4174,8 @@ alloc_perf_context(struct pmu *pmu, struct task_struct *task)
return NULL;
__perf_event_init_context(ctx);
- if (task) {
- ctx->task = task;
- get_task_struct(task);
- }
+ if (task)
+ ctx->task = get_task_struct(task);
ctx->pmu = pmu;
return ctx;
@@ -10355,8 +10438,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
* and we cannot use the ctx information because we need the
* pmu before we get a ctx.
*/
- get_task_struct(task);
- event->hw.target = task;
+ event->hw.target = get_task_struct(task);
}
event->clock = &local_clock;
@@ -10426,6 +10508,12 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
goto err_ns;
}
+ if (event->attr.aux_output &&
+ !(pmu->capabilities & PERF_PMU_CAP_AUX_OUTPUT)) {
+ err = -EOPNOTSUPP;
+ goto err_pmu;
+ }
+
err = exclusive_event_init(event);
if (err)
goto err_pmu;
@@ -11082,6 +11170,8 @@ SYSCALL_DEFINE5(perf_event_open,
}
}
+ if (event->attr.aux_output && !perf_get_aux_event(event, group_leader))
+ goto err_locked;
/*
* Must be under the same ctx::mutex as perf_install_in_context(),
@@ -11274,7 +11364,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
goto err_unlock;
}
- perf_install_in_context(ctx, event, cpu);
+ perf_install_in_context(ctx, event, event->cpu);
perf_unpin_context(ctx);
mutex_unlock(&ctx->mutex);
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index c5cd852fe86b..3cc8416ec844 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -413,7 +413,7 @@ static int hw_breakpoint_parse(struct perf_event *bp,
int register_perf_hw_breakpoint(struct perf_event *bp)
{
- struct arch_hw_breakpoint hw;
+ struct arch_hw_breakpoint hw = { };
int err;
err = reserve_bp_slot(bp);
@@ -461,7 +461,7 @@ int
modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr,
bool check)
{
- struct arch_hw_breakpoint hw;
+ struct arch_hw_breakpoint hw = { };
int err;
err = hw_breakpoint_parse(bp, attr, &hw);
diff --git a/kernel/exit.c b/kernel/exit.c
index 4436158a6d30..22ab6a4bdc51 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -734,9 +734,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
autoreap = true;
}
- tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
- if (tsk->exit_state == EXIT_DEAD)
+ if (autoreap) {
+ tsk->exit_state = EXIT_DEAD;
list_add(&tsk->ptrace_entry, &dead);
+ }
/* mt-exec, de_thread() is waiting for group leader */
if (unlikely(tsk->signal->notify_count < 0))
@@ -1553,6 +1554,23 @@ end:
return retval;
}
+static struct pid *pidfd_get_pid(unsigned int fd)
+{
+ struct fd f;
+ struct pid *pid;
+
+ f = fdget(fd);
+ if (!f.file)
+ return ERR_PTR(-EBADF);
+
+ pid = pidfd_pid(f.file);
+ if (!IS_ERR(pid))
+ get_pid(pid);
+
+ fdput(f);
+ return pid;
+}
+
static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
int options, struct rusage *ru)
{
@@ -1575,19 +1593,32 @@ static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
type = PIDTYPE_PID;
if (upid <= 0)
return -EINVAL;
+
+ pid = find_get_pid(upid);
break;
case P_PGID:
type = PIDTYPE_PGID;
- if (upid <= 0)
+ if (upid < 0)
return -EINVAL;
+
+ if (upid)
+ pid = find_get_pid(upid);
+ else
+ pid = get_task_pid(current, PIDTYPE_PGID);
+ break;
+ case P_PIDFD:
+ type = PIDTYPE_PID;
+ if (upid < 0)
+ return -EINVAL;
+
+ pid = pidfd_get_pid(upid);
+ if (IS_ERR(pid))
+ return PTR_ERR(pid);
break;
default:
return -EINVAL;
}
- if (type < PIDTYPE_MAX)
- pid = find_get_pid(upid);
-
wo.wo_type = type;
wo.wo_pid = pid;
wo.wo_flags = options;
diff --git a/kernel/fork.c b/kernel/fork.c
index f1228d9f0b11..53e780748fe3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -726,7 +726,7 @@ void __put_task_struct(struct task_struct *tsk)
WARN_ON(tsk == current);
cgroup_free(tsk);
- task_numa_free(tsk);
+ task_numa_free(tsk, true);
security_task_free(tsk);
exit_creds(tsk);
delayacct_tsk_free(tsk);
@@ -768,6 +768,7 @@ static void set_max_threads(unsigned int max_threads_suggested)
int arch_task_struct_size __read_mostly;
#endif
+#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
static void task_struct_whitelist(unsigned long *offset, unsigned long *size)
{
/* Fetch thread_struct whitelist for the architecture. */
@@ -782,6 +783,7 @@ static void task_struct_whitelist(unsigned long *offset, unsigned long *size)
else
*offset += offsetof(struct task_struct, thread);
}
+#endif /* CONFIG_ARCH_TASK_STRUCT_ALLOCATOR */
void __init fork_init(void)
{
@@ -1662,6 +1664,14 @@ static inline void rcu_copy_process(struct task_struct *p)
#endif /* #ifdef CONFIG_TASKS_RCU */
}
+struct pid *pidfd_pid(const struct file *file)
+{
+ if (file->f_op == &pidfd_fops)
+ return file->private_data;
+
+ return ERR_PTR(-EBADF);
+}
+
static int pidfd_release(struct inode *inode, struct file *file)
{
struct pid *pid = file->private_data;
@@ -2310,6 +2320,8 @@ struct mm_struct *copy_init_mm(void)
*
* It copies the process, and if successful kick-starts
* it and waits for it to finish using the VM if required.
+ *
+ * args->exit_signal is expected to be checked for sanity by the caller.
*/
long _do_fork(struct kernel_clone_args *args)
{
@@ -2534,6 +2546,14 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
if (copy_from_user(&args, uargs, size))
return -EFAULT;
+ /*
+ * Verify that higher 32bits of exit_signal are unset and that
+ * it is a valid signal
+ */
+ if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+ !valid_signal(args.exit_signal)))
+ return -EINVAL;
+
*kargs = (struct kernel_clone_args){
.flags = args.flags,
.pidfd = u64_to_user_ptr(args.pidfd),
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index 4352b08ae48d..4d89ad4fae3b 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/cpu.h>
+#include <linux/sort.h>
static void irq_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
unsigned int cpus_per_vec)
@@ -94,6 +95,155 @@ static int get_nodes_in_cpumask(cpumask_var_t *node_to_cpumask,
return nodes;
}
+struct node_vectors {
+ unsigned id;
+
+ union {
+ unsigned nvectors;
+ unsigned ncpus;
+ };
+};
+
+static int ncpus_cmp_func(const void *l, const void *r)
+{
+ const struct node_vectors *ln = l;
+ const struct node_vectors *rn = r;
+
+ return ln->ncpus - rn->ncpus;
+}
+
+/*
+ * Allocate vector number for each node, so that for each node:
+ *
+ * 1) the allocated number is >= 1
+ *
+ * 2) the allocated numbver is <= active CPU number of this node
+ *
+ * The actual allocated total vectors may be less than @numvecs when
+ * active total CPU number is less than @numvecs.
+ *
+ * Active CPUs means the CPUs in '@cpu_mask AND @node_to_cpumask[]'
+ * for each node.
+ */
+static void alloc_nodes_vectors(unsigned int numvecs,
+ cpumask_var_t *node_to_cpumask,
+ const struct cpumask *cpu_mask,
+ const nodemask_t nodemsk,
+ struct cpumask *nmsk,
+ struct node_vectors *node_vectors)
+{
+ unsigned n, remaining_ncpus = 0;
+
+ for (n = 0; n < nr_node_ids; n++) {
+ node_vectors[n].id = n;
+ node_vectors[n].ncpus = UINT_MAX;
+ }
+
+ for_each_node_mask(n, nodemsk) {
+ unsigned ncpus;
+
+ cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
+ ncpus = cpumask_weight(nmsk);
+
+ if (!ncpus)
+ continue;
+ remaining_ncpus += ncpus;
+ node_vectors[n].ncpus = ncpus;
+ }
+
+ numvecs = min_t(unsigned, remaining_ncpus, numvecs);
+
+ sort(node_vectors, nr_node_ids, sizeof(node_vectors[0]),
+ ncpus_cmp_func, NULL);
+
+ /*
+ * Allocate vectors for each node according to the ratio of this
+ * node's nr_cpus to remaining un-assigned ncpus. 'numvecs' is
+ * bigger than number of active numa nodes. Always start the
+ * allocation from the node with minimized nr_cpus.
+ *
+ * This way guarantees that each active node gets allocated at
+ * least one vector, and the theory is simple: over-allocation
+ * is only done when this node is assigned by one vector, so
+ * other nodes will be allocated >= 1 vector, since 'numvecs' is
+ * bigger than number of numa nodes.
+ *
+ * One perfect invariant is that number of allocated vectors for
+ * each node is <= CPU count of this node:
+ *
+ * 1) suppose there are two nodes: A and B
+ * ncpu(X) is CPU count of node X
+ * vecs(X) is the vector count allocated to node X via this
+ * algorithm
+ *
+ * ncpu(A) <= ncpu(B)
+ * ncpu(A) + ncpu(B) = N
+ * vecs(A) + vecs(B) = V
+ *
+ * vecs(A) = max(1, round_down(V * ncpu(A) / N))
+ * vecs(B) = V - vecs(A)
+ *
+ * both N and V are integer, and 2 <= V <= N, suppose
+ * V = N - delta, and 0 <= delta <= N - 2
+ *
+ * 2) obviously vecs(A) <= ncpu(A) because:
+ *
+ * if vecs(A) is 1, then vecs(A) <= ncpu(A) given
+ * ncpu(A) >= 1
+ *
+ * otherwise,
+ * vecs(A) <= V * ncpu(A) / N <= ncpu(A), given V <= N
+ *
+ * 3) prove how vecs(B) <= ncpu(B):
+ *
+ * if round_down(V * ncpu(A) / N) == 0, vecs(B) won't be
+ * over-allocated, so vecs(B) <= ncpu(B),
+ *
+ * otherwise:
+ *
+ * vecs(A) =
+ * round_down(V * ncpu(A) / N) =
+ * round_down((N - delta) * ncpu(A) / N) =
+ * round_down((N * ncpu(A) - delta * ncpu(A)) / N) >=
+ * round_down((N * ncpu(A) - delta * N) / N) =
+ * cpu(A) - delta
+ *
+ * then:
+ *
+ * vecs(A) - V >= ncpu(A) - delta - V
+ * =>
+ * V - vecs(A) <= V + delta - ncpu(A)
+ * =>
+ * vecs(B) <= N - ncpu(A)
+ * =>
+ * vecs(B) <= cpu(B)
+ *
+ * For nodes >= 3, it can be thought as one node and another big
+ * node given that is exactly what this algorithm is implemented,
+ * and we always re-calculate 'remaining_ncpus' & 'numvecs', and
+ * finally for each node X: vecs(X) <= ncpu(X).
+ *
+ */
+ for (n = 0; n < nr_node_ids; n++) {
+ unsigned nvectors, ncpus;
+
+ if (node_vectors[n].ncpus == UINT_MAX)
+ continue;
+
+ WARN_ON_ONCE(numvecs == 0);
+
+ ncpus = node_vectors[n].ncpus;
+ nvectors = max_t(unsigned, 1,
+ numvecs * ncpus / remaining_ncpus);
+ WARN_ON_ONCE(nvectors > ncpus);
+
+ node_vectors[n].nvectors = nvectors;
+
+ remaining_ncpus -= ncpus;
+ numvecs -= nvectors;
+ }
+}
+
static int __irq_build_affinity_masks(unsigned int startvec,
unsigned int numvecs,
unsigned int firstvec,
@@ -102,10 +252,11 @@ static int __irq_build_affinity_masks(unsigned int startvec,
struct cpumask *nmsk,
struct irq_affinity_desc *masks)
{
- unsigned int n, nodes, cpus_per_vec, extra_vecs, done = 0;
+ unsigned int i, n, nodes, cpus_per_vec, extra_vecs, done = 0;
unsigned int last_affv = firstvec + numvecs;
unsigned int curvec = startvec;
nodemask_t nodemsk = NODE_MASK_NONE;
+ struct node_vectors *node_vectors;
if (!cpumask_weight(cpu_mask))
return 0;
@@ -126,42 +277,56 @@ static int __irq_build_affinity_masks(unsigned int startvec,
return numvecs;
}
- for_each_node_mask(n, nodemsk) {
- unsigned int ncpus, v, vecs_to_assign, vecs_per_node;
+ node_vectors = kcalloc(nr_node_ids,
+ sizeof(struct node_vectors),
+ GFP_KERNEL);
+ if (!node_vectors)
+ return -ENOMEM;
- /* Spread the vectors per node */
- vecs_per_node = (numvecs - (curvec - firstvec)) / nodes;
+ /* allocate vector number for each node */
+ alloc_nodes_vectors(numvecs, node_to_cpumask, cpu_mask,
+ nodemsk, nmsk, node_vectors);
- /* Get the cpus on this node which are in the mask */
- cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
+ for (i = 0; i < nr_node_ids; i++) {
+ unsigned int ncpus, v;
+ struct node_vectors *nv = &node_vectors[i];
+
+ if (nv->nvectors == UINT_MAX)
+ continue;
- /* Calculate the number of cpus per vector */
+ /* Get the cpus on this node which are in the mask */
+ cpumask_and(nmsk, cpu_mask, node_to_cpumask[nv->id]);
ncpus = cpumask_weight(nmsk);
- vecs_to_assign = min(vecs_per_node, ncpus);
+ if (!ncpus)
+ continue;
+
+ WARN_ON_ONCE(nv->nvectors > ncpus);
/* Account for rounding errors */
- extra_vecs = ncpus - vecs_to_assign * (ncpus / vecs_to_assign);
+ extra_vecs = ncpus - nv->nvectors * (ncpus / nv->nvectors);
- for (v = 0; curvec < last_affv && v < vecs_to_assign;
- curvec++, v++) {
- cpus_per_vec = ncpus / vecs_to_assign;
+ /* Spread allocated vectors on CPUs of the current node */
+ for (v = 0; v < nv->nvectors; v++, curvec++) {
+ cpus_per_vec = ncpus / nv->nvectors;
/* Account for extra vectors to compensate rounding errors */
if (extra_vecs) {
cpus_per_vec++;
--extra_vecs;
}
+
+ /*
+ * wrapping has to be considered given 'startvec'
+ * may start anywhere
+ */
+ if (curvec >= last_affv)
+ curvec = firstvec;
irq_spread_init_one(&masks[curvec].mask, nmsk,
cpus_per_vec);
}
-
- done += v;
- if (done >= numvecs)
- break;
- if (curvec >= last_affv)
- curvec = firstvec;
- --nodes;
+ done += nv->nvectors;
}
+ kfree(node_vectors);
return done;
}
@@ -174,7 +339,7 @@ static int irq_build_affinity_masks(unsigned int startvec, unsigned int numvecs,
unsigned int firstvec,
struct irq_affinity_desc *masks)
{
- unsigned int curvec = startvec, nr_present, nr_others;
+ unsigned int curvec = startvec, nr_present = 0, nr_others = 0;
cpumask_var_t *node_to_cpumask;
cpumask_var_t nmsk, npresmsk;
int ret = -ENOMEM;
@@ -189,15 +354,17 @@ static int irq_build_affinity_masks(unsigned int startvec, unsigned int numvecs,
if (!node_to_cpumask)
goto fail_npresmsk;
- ret = 0;
/* Stabilize the cpumasks */
get_online_cpus();
build_node_to_cpumask(node_to_cpumask);
/* Spread on present CPUs starting from affd->pre_vectors */
- nr_present = __irq_build_affinity_masks(curvec, numvecs,
- firstvec, node_to_cpumask,
- cpu_present_mask, nmsk, masks);
+ ret = __irq_build_affinity_masks(curvec, numvecs, firstvec,
+ node_to_cpumask, cpu_present_mask,
+ nmsk, masks);
+ if (ret < 0)
+ goto fail_build_affinity;
+ nr_present = ret;
/*
* Spread on non present CPUs starting from the next vector to be
@@ -210,12 +377,16 @@ static int irq_build_affinity_masks(unsigned int startvec, unsigned int numvecs,
else
curvec = firstvec + nr_present;
cpumask_andnot(npresmsk, cpu_possible_mask, cpu_present_mask);
- nr_others = __irq_build_affinity_masks(curvec, numvecs,
- firstvec, node_to_cpumask,
- npresmsk, nmsk, masks);
+ ret = __irq_build_affinity_masks(curvec, numvecs, firstvec,
+ node_to_cpumask, npresmsk, nmsk,
+ masks);
+ if (ret >= 0)
+ nr_others = ret;
+
+ fail_build_affinity:
put_online_cpus();
- if (nr_present < numvecs)
+ if (ret >= 0)
WARN_ON(nr_present + nr_others < numvecs);
free_node_to_cpumask(node_to_cpumask);
@@ -225,7 +396,7 @@ static int irq_build_affinity_masks(unsigned int startvec, unsigned int numvecs,
fail_nmsk:
free_cpumask_var(nmsk);
- return ret;
+ return ret < 0 ? ret : 0;
}
static void default_calc_sets(struct irq_affinity *affd, unsigned int affvecs)
@@ -251,11 +422,9 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
* Determine the number of vectors which need interrupt affinities
* assigned. If the pre/post request exhausts the available vectors
* then nothing to do here except for invoking the calc_sets()
- * callback so the device driver can adjust to the situation. If there
- * is only a single vector, then managing the queue is pointless as
- * well.
+ * callback so the device driver can adjust to the situation.
*/
- if (nvecs > 1 && nvecs > affd->pre_vectors + affd->post_vectors)
+ if (nvecs > affd->pre_vectors + affd->post_vectors)
affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
else
affvecs = 0;
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 9484e88dabc2..9be995fc3c5a 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -295,6 +295,18 @@ static void irq_sysfs_add(int irq, struct irq_desc *desc)
}
}
+static void irq_sysfs_del(struct irq_desc *desc)
+{
+ /*
+ * If irq_sysfs_init() has not yet been invoked (early boot), then
+ * irq_kobj_base is NULL and the descriptor was never added.
+ * kobject_del() complains about a object with no parent, so make
+ * it conditional.
+ */
+ if (irq_kobj_base)
+ kobject_del(&desc->kobj);
+}
+
static int __init irq_sysfs_init(void)
{
struct irq_desc *desc;
@@ -325,6 +337,7 @@ static struct kobj_type irq_kobj_type = {
};
static void irq_sysfs_add(int irq, struct irq_desc *desc) {}
+static void irq_sysfs_del(struct irq_desc *desc) {}
#endif /* CONFIG_SYSFS */
@@ -438,7 +451,7 @@ static void free_desc(unsigned int irq)
* The sysfs entry must be serialized against a concurrent
* irq_sysfs_init() as well.
*/
- kobject_del(&desc->kobj);
+ irq_sysfs_del(desc);
delete_irq_desc(irq);
/*
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3078d0e48bba..132672b74e4b 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -31,7 +31,7 @@ struct irqchip_fwid {
struct fwnode_handle fwnode;
unsigned int type;
char *name;
- void *data;
+ phys_addr_t *pa;
};
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
@@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
* domain struct.
*/
struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
- const char *name, void *data)
+ const char *name,
+ phys_addr_t *pa)
{
struct irqchip_fwid *fwid;
char *n;
@@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
break;
default:
- n = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+ n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa);
break;
}
@@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
fwid->type = type;
fwid->name = n;
- fwid->data = data;
+ fwid->pa = pa;
fwid->fwnode.ops = &irqchip_fwnode_ops;
return &fwid->fwnode;
}
@@ -148,6 +149,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
switch (fwid->type) {
case IRQCHIP_FWNODE_NAMED:
case IRQCHIP_FWNODE_NAMED_ID:
+ domain->fwnode = fwnode;
domain->name = kstrdup(fwid->name, GFP_KERNEL);
if (!domain->name) {
kfree(domain);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index e8f7f179bf77..1753486b440c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -23,7 +23,7 @@
#include "internals.h"
-#ifdef CONFIG_IRQ_FORCED_THREADING
+#if defined(CONFIG_IRQ_FORCED_THREADING) && !defined(CONFIG_PREEMPT_RT)
__read_mostly bool force_irqthreads;
EXPORT_SYMBOL_GPL(force_irqthreads);
@@ -1255,8 +1255,7 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
* the thread dies to avoid that the interrupt code
* references an already freed task_struct.
*/
- get_task_struct(t);
- new->thread = t;
+ new->thread = get_task_struct(t);
/*
* Tell the thread to set its affinity. This is
* important for shared interrupt handlers as we do
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index da9addb8d655..cfc4f088a0e7 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -100,10 +100,6 @@ static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
return 0;
}
-#ifndef is_affinity_mask_valid
-#define is_affinity_mask_valid(val) 1
-#endif
-
int no_irq_affinity;
static int irq_affinity_proc_show(struct seq_file *m, void *v)
{
@@ -136,11 +132,6 @@ static ssize_t write_irq_affinity(int type, struct file *file,
if (err)
goto free_cpumask;
- if (!is_affinity_mask_valid(new_value)) {
- err = -EINVAL;
- goto free_cpumask;
- }
-
/*
* Do not allow disabling IRQs completely - it's a too easy
* way to make the system unusable accidentally :-) At least
@@ -232,11 +223,6 @@ static ssize_t default_affinity_write(struct file *file,
if (err)
goto out;
- if (!is_affinity_mask_valid(new_value)) {
- err = -EINVAL;
- goto out;
- }
-
/*
* Do not allow disabling IRQs completely - it's a too easy
* way to make the system unusable accidentally :-) At least
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 95414ad3506a..98c04ca5fa43 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -36,6 +36,8 @@ static void resend_irqs(unsigned long arg)
irq = find_first_bit(irqs_resend, nr_irqs);
clear_bit(irq, irqs_resend);
desc = irq_to_desc(irq);
+ if (!desc)
+ continue;
local_irq_disable();
desc->handle_irq(desc);
local_irq_enable();
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index df3008419a1d..cdb3ffab128b 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -407,7 +407,9 @@ static bool jump_label_can_update(struct jump_entry *entry, bool init)
return false;
if (!kernel_text_address(jump_entry_code(entry))) {
- WARN_ONCE(1, "can't patch jump_label at %pS", (void *)jump_entry_code(entry));
+ WARN_ONCE(!jump_entry_is_init(entry),
+ "can't patch jump_label at %pS",
+ (void *)jump_entry_code(entry));
return false;
}
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 95a260f9214b..136ce049c4ad 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -263,8 +263,10 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
{
char namebuf[KSYM_NAME_LEN];
- if (is_ksym_addr(addr))
- return !!get_symbol_pos(addr, symbolsize, offset);
+ if (is_ksym_addr(addr)) {
+ get_symbol_pos(addr, symbolsize, offset);
+ return 1;
+ }
return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
!!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
}
diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c
new file mode 100644
index 000000000000..d3689632e8b9
--- /dev/null
+++ b/kernel/kexec_elf.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Load ELF vmlinux file for the kexec_file_load syscall.
+ *
+ * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
+ * Copyright (C) 2004 IBM Corp.
+ * Copyright (C) 2005 R Sharada (sharada@in.ibm.com)
+ * Copyright (C) 2006 Mohan Kumar M (mohan@in.ibm.com)
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
+ * Heavily modified for the kernel by
+ * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>.
+ */
+
+#define pr_fmt(fmt) "kexec_elf: " fmt
+
+#include <linux/elf.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
+{
+ return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
+}
+
+static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
+{
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+ value = le64_to_cpu(value);
+ else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+ value = be64_to_cpu(value);
+
+ return value;
+}
+
+static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
+{
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+ value = le32_to_cpu(value);
+ else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+ value = be32_to_cpu(value);
+
+ return value;
+}
+
+static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
+{
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+ value = le16_to_cpu(value);
+ else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+ value = be16_to_cpu(value);
+
+ return value;
+}
+
+/**
+ * elf_is_ehdr_sane - check that it is safe to use the ELF header
+ * @buf_len: size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
+{
+ if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
+ pr_debug("Bad program header size.\n");
+ return false;
+ } else if (ehdr->e_shnum > 0 &&
+ ehdr->e_shentsize != sizeof(struct elf_shdr)) {
+ pr_debug("Bad section header size.\n");
+ return false;
+ } else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr->e_version != EV_CURRENT) {
+ pr_debug("Unknown ELF version.\n");
+ return false;
+ }
+
+ if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+ size_t phdr_size;
+
+ /*
+ * e_phnum is at most 65535 so calculating the size of the
+ * program header cannot overflow.
+ */
+ phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+ /* Sanity check the program header table location. */
+ if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
+ pr_debug("Program headers at invalid location.\n");
+ return false;
+ } else if (ehdr->e_phoff + phdr_size > buf_len) {
+ pr_debug("Program headers truncated.\n");
+ return false;
+ }
+ }
+
+ if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
+ size_t shdr_size;
+
+ /*
+ * e_shnum is at most 65536 so calculating
+ * the size of the section header cannot overflow.
+ */
+ shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
+
+ /* Sanity check the section header table location. */
+ if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
+ pr_debug("Section headers at invalid location.\n");
+ return false;
+ } else if (ehdr->e_shoff + shdr_size > buf_len) {
+ pr_debug("Section headers truncated.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
+{
+ struct elfhdr *buf_ehdr;
+
+ if (len < sizeof(*buf_ehdr)) {
+ pr_debug("Buffer is too small to hold ELF header.\n");
+ return -ENOEXEC;
+ }
+
+ memset(ehdr, 0, sizeof(*ehdr));
+ memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
+ if (!elf_is_elf_file(ehdr)) {
+ pr_debug("No ELF header magic.\n");
+ return -ENOEXEC;
+ }
+
+ if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
+ pr_debug("Not a supported ELF class.\n");
+ return -ENOEXEC;
+ } else if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
+ ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+ pr_debug("Not a supported ELF data format.\n");
+ return -ENOEXEC;
+ }
+
+ buf_ehdr = (struct elfhdr *) buf;
+ if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
+ pr_debug("Bad ELF header size.\n");
+ return -ENOEXEC;
+ }
+
+ ehdr->e_type = elf16_to_cpu(ehdr, buf_ehdr->e_type);
+ ehdr->e_machine = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
+ ehdr->e_version = elf32_to_cpu(ehdr, buf_ehdr->e_version);
+ ehdr->e_flags = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
+ ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
+ ehdr->e_phnum = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
+ ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
+ ehdr->e_shnum = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
+ ehdr->e_shstrndx = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
+
+ switch (ehdr->e_ident[EI_CLASS]) {
+ case ELFCLASS64:
+ ehdr->e_entry = elf64_to_cpu(ehdr, buf_ehdr->e_entry);
+ ehdr->e_phoff = elf64_to_cpu(ehdr, buf_ehdr->e_phoff);
+ ehdr->e_shoff = elf64_to_cpu(ehdr, buf_ehdr->e_shoff);
+ break;
+
+ case ELFCLASS32:
+ ehdr->e_entry = elf32_to_cpu(ehdr, buf_ehdr->e_entry);
+ ehdr->e_phoff = elf32_to_cpu(ehdr, buf_ehdr->e_phoff);
+ ehdr->e_shoff = elf32_to_cpu(ehdr, buf_ehdr->e_shoff);
+ break;
+
+ default:
+ pr_debug("Unknown ELF class.\n");
+ return -EINVAL;
+ }
+
+ return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_is_phdr_sane - check that it is safe to use the program header
+ * @buf_len: size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
+{
+
+ if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
+ pr_debug("ELF segment location wraps around.\n");
+ return false;
+ } else if (phdr->p_offset + phdr->p_filesz > buf_len) {
+ pr_debug("ELF segment not in file.\n");
+ return false;
+ } else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
+ pr_debug("ELF segment address wraps around.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int elf_read_phdr(const char *buf, size_t len,
+ struct kexec_elf_info *elf_info,
+ int idx)
+{
+ /* Override the const in proghdrs, we are the ones doing the loading. */
+ struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
+ const struct elfhdr *ehdr = elf_info->ehdr;
+ const char *pbuf;
+ struct elf_phdr *buf_phdr;
+
+ pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
+ buf_phdr = (struct elf_phdr *) pbuf;
+
+ phdr->p_type = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
+ phdr->p_flags = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
+
+ switch (ehdr->e_ident[EI_CLASS]) {
+ case ELFCLASS64:
+ phdr->p_offset = elf64_to_cpu(ehdr, buf_phdr->p_offset);
+ phdr->p_paddr = elf64_to_cpu(ehdr, buf_phdr->p_paddr);
+ phdr->p_vaddr = elf64_to_cpu(ehdr, buf_phdr->p_vaddr);
+ phdr->p_filesz = elf64_to_cpu(ehdr, buf_phdr->p_filesz);
+ phdr->p_memsz = elf64_to_cpu(ehdr, buf_phdr->p_memsz);
+ phdr->p_align = elf64_to_cpu(ehdr, buf_phdr->p_align);
+ break;
+
+ case ELFCLASS32:
+ phdr->p_offset = elf32_to_cpu(ehdr, buf_phdr->p_offset);
+ phdr->p_paddr = elf32_to_cpu(ehdr, buf_phdr->p_paddr);
+ phdr->p_vaddr = elf32_to_cpu(ehdr, buf_phdr->p_vaddr);
+ phdr->p_filesz = elf32_to_cpu(ehdr, buf_phdr->p_filesz);
+ phdr->p_memsz = elf32_to_cpu(ehdr, buf_phdr->p_memsz);
+ phdr->p_align = elf32_to_cpu(ehdr, buf_phdr->p_align);
+ break;
+
+ default:
+ pr_debug("Unknown ELF class.\n");
+ return -EINVAL;
+ }
+
+ return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_read_phdrs - read the program headers from the buffer
+ *
+ * This function assumes that the program header table was checked for sanity.
+ * Use elf_is_ehdr_sane() if it wasn't.
+ */
+static int elf_read_phdrs(const char *buf, size_t len,
+ struct kexec_elf_info *elf_info)
+{
+ size_t phdr_size, i;
+ const struct elfhdr *ehdr = elf_info->ehdr;
+
+ /*
+ * e_phnum is at most 65535 so calculating the size of the
+ * program header cannot overflow.
+ */
+ phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+ elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
+ if (!elf_info->proghdrs)
+ return -ENOMEM;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ int ret;
+
+ ret = elf_read_phdr(buf, len, elf_info, i);
+ if (ret) {
+ kfree(elf_info->proghdrs);
+ elf_info->proghdrs = NULL;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
+ * @buf: Buffer to read ELF file from.
+ * @len: Size of @buf.
+ * @ehdr: Pointer to existing struct which will be populated.
+ * @elf_info: Pointer to existing struct which will be populated.
+ *
+ * This function allows reading ELF files with different byte order than
+ * the kernel, byte-swapping the fields as needed.
+ *
+ * Return:
+ * On success returns 0, and the caller should call
+ * kexec_free_elf_info(elf_info) to free the memory allocated for the section
+ * and program headers.
+ */
+static int elf_read_from_buffer(const char *buf, size_t len,
+ struct elfhdr *ehdr,
+ struct kexec_elf_info *elf_info)
+{
+ int ret;
+
+ ret = elf_read_ehdr(buf, len, ehdr);
+ if (ret)
+ return ret;
+
+ elf_info->buffer = buf;
+ elf_info->ehdr = ehdr;
+ if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+ ret = elf_read_phdrs(buf, len, elf_info);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * kexec_free_elf_info - free memory allocated by elf_read_from_buffer
+ */
+void kexec_free_elf_info(struct kexec_elf_info *elf_info)
+{
+ kfree(elf_info->proghdrs);
+ memset(elf_info, 0, sizeof(*elf_info));
+}
+/**
+ * kexec_build_elf_info - read ELF executable and check that we can use it
+ */
+int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr,
+ struct kexec_elf_info *elf_info)
+{
+ int i;
+ int ret;
+
+ ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
+ if (ret)
+ return ret;
+
+ /* Big endian vmlinux has type ET_DYN. */
+ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+ pr_err("Not an ELF executable.\n");
+ goto error;
+ } else if (!elf_info->proghdrs) {
+ pr_err("No ELF program header.\n");
+ goto error;
+ }
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ /*
+ * Kexec does not support loading interpreters.
+ * In addition this check keeps us from attempting
+ * to kexec ordinay executables.
+ */
+ if (elf_info->proghdrs[i].p_type == PT_INTERP) {
+ pr_err("Requires an ELF interpreter.\n");
+ goto error;
+ }
+ }
+
+ return 0;
+error:
+ kexec_free_elf_info(elf_info);
+ return -ENOEXEC;
+}
+
+
+int kexec_elf_probe(const char *buf, unsigned long len)
+{
+ struct elfhdr ehdr;
+ struct kexec_elf_info elf_info;
+ int ret;
+
+ ret = kexec_build_elf_info(buf, len, &ehdr, &elf_info);
+ if (ret)
+ return ret;
+
+ kexec_free_elf_info(&elf_info);
+
+ return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
+}
+
+/**
+ * kexec_elf_load - load ELF executable image
+ * @lowest_load_addr: On return, will be the address where the first PT_LOAD
+ * section will be loaded in memory.
+ *
+ * Return:
+ * 0 on success, negative value on failure.
+ */
+int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
+ struct kexec_elf_info *elf_info,
+ struct kexec_buf *kbuf,
+ unsigned long *lowest_load_addr)
+{
+ unsigned long lowest_addr = UINT_MAX;
+ int ret;
+ size_t i;
+
+ /* Read in the PT_LOAD segments. */
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ unsigned long load_addr;
+ size_t size;
+ const struct elf_phdr *phdr;
+
+ phdr = &elf_info->proghdrs[i];
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ size = phdr->p_filesz;
+ if (size > phdr->p_memsz)
+ size = phdr->p_memsz;
+
+ kbuf->buffer = (void *) elf_info->buffer + phdr->p_offset;
+ kbuf->bufsz = size;
+ kbuf->memsz = phdr->p_memsz;
+ kbuf->buf_align = phdr->p_align;
+ kbuf->buf_min = phdr->p_paddr;
+ kbuf->mem = KEXEC_BUF_MEM_UNKNOWN;
+ ret = kexec_add_buffer(kbuf);
+ if (ret)
+ goto out;
+ load_addr = kbuf->mem;
+
+ if (load_addr < lowest_addr)
+ lowest_addr = load_addr;
+ }
+
+ *lowest_load_addr = lowest_addr;
+ ret = 0;
+ out:
+ return ret;
+}
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9873fc627d61..1b66ccbb744a 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -470,6 +470,7 @@ static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer);
*/
static void do_optimize_kprobes(void)
{
+ lockdep_assert_held(&text_mutex);
/*
* The optimization/unoptimization refers online_cpus via
* stop_machine() and cpu-hotplug modifies online_cpus.
@@ -487,9 +488,7 @@ static void do_optimize_kprobes(void)
list_empty(&optimizing_list))
return;
- mutex_lock(&text_mutex);
arch_optimize_kprobes(&optimizing_list);
- mutex_unlock(&text_mutex);
}
/*
@@ -500,6 +499,7 @@ static void do_unoptimize_kprobes(void)
{
struct optimized_kprobe *op, *tmp;
+ lockdep_assert_held(&text_mutex);
/* See comment in do_optimize_kprobes() */
lockdep_assert_cpus_held();
@@ -507,7 +507,6 @@ static void do_unoptimize_kprobes(void)
if (list_empty(&unoptimizing_list))
return;
- mutex_lock(&text_mutex);
arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
/* Loop free_list for disarming */
list_for_each_entry_safe(op, tmp, &freeing_list, list) {
@@ -524,7 +523,6 @@ static void do_unoptimize_kprobes(void)
} else
list_del_init(&op->list);
}
- mutex_unlock(&text_mutex);
}
/* Reclaim all kprobes on the free_list */
@@ -556,6 +554,7 @@ static void kprobe_optimizer(struct work_struct *work)
{
mutex_lock(&kprobe_mutex);
cpus_read_lock();
+ mutex_lock(&text_mutex);
/* Lock modules while optimizing kprobes */
mutex_lock(&module_mutex);
@@ -583,6 +582,7 @@ static void kprobe_optimizer(struct work_struct *work)
do_free_cleaned_kprobes();
mutex_unlock(&module_mutex);
+ mutex_unlock(&text_mutex);
cpus_read_unlock();
mutex_unlock(&kprobe_mutex);
@@ -1514,7 +1514,8 @@ static int check_kprobe_address_safe(struct kprobe *p,
/* Ensure it is not in reserved area nor out of text */
if (!kernel_text_address((unsigned long) p->addr) ||
within_kprobe_blacklist((unsigned long) p->addr) ||
- jump_label_text_reserved(p->addr, p->addr)) {
+ jump_label_text_reserved(p->addr, p->addr) ||
+ find_bug((unsigned long)p->addr)) {
ret = -EINVAL;
goto out;
}
@@ -1906,7 +1907,7 @@ int register_kretprobe(struct kretprobe *rp)
/* Pre-allocate memory for max kretprobe instances */
if (rp->maxactive <= 0) {
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
#else
rp->maxactive = num_possible_cpus();
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 341f52117f88..233459c03b5a 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -448,34 +448,102 @@ static void print_lockdep_off(const char *bug_msg)
unsigned long nr_stack_trace_entries;
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
+/**
+ * struct lock_trace - single stack backtrace
+ * @hash_entry: Entry in a stack_trace_hash[] list.
+ * @hash: jhash() of @entries.
+ * @nr_entries: Number of entries in @entries.
+ * @entries: Actual stack backtrace.
+ */
+struct lock_trace {
+ struct hlist_node hash_entry;
+ u32 hash;
+ u32 nr_entries;
+ unsigned long entries[0] __aligned(sizeof(unsigned long));
+};
+#define LOCK_TRACE_SIZE_IN_LONGS \
+ (sizeof(struct lock_trace) / sizeof(unsigned long))
/*
- * Stack-trace: tightly packed array of stack backtrace
- * addresses. Protected by the graph_lock.
+ * Stack-trace: sequence of lock_trace structures. Protected by the graph_lock.
*/
static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
+static struct hlist_head stack_trace_hash[STACK_TRACE_HASH_SIZE];
+
+static bool traces_identical(struct lock_trace *t1, struct lock_trace *t2)
+{
+ return t1->hash == t2->hash && t1->nr_entries == t2->nr_entries &&
+ memcmp(t1->entries, t2->entries,
+ t1->nr_entries * sizeof(t1->entries[0])) == 0;
+}
-static int save_trace(struct lock_trace *trace)
+static struct lock_trace *save_trace(void)
{
- unsigned long *entries = stack_trace + nr_stack_trace_entries;
+ struct lock_trace *trace, *t2;
+ struct hlist_head *hash_head;
+ u32 hash;
unsigned int max_entries;
- trace->offset = nr_stack_trace_entries;
- max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries;
- trace->nr_entries = stack_trace_save(entries, max_entries, 3);
- nr_stack_trace_entries += trace->nr_entries;
+ BUILD_BUG_ON_NOT_POWER_OF_2(STACK_TRACE_HASH_SIZE);
+ BUILD_BUG_ON(LOCK_TRACE_SIZE_IN_LONGS >= MAX_STACK_TRACE_ENTRIES);
- if (nr_stack_trace_entries >= MAX_STACK_TRACE_ENTRIES-1) {
+ trace = (struct lock_trace *)(stack_trace + nr_stack_trace_entries);
+ max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries -
+ LOCK_TRACE_SIZE_IN_LONGS;
+ trace->nr_entries = stack_trace_save(trace->entries, max_entries, 3);
+
+ if (nr_stack_trace_entries >= MAX_STACK_TRACE_ENTRIES -
+ LOCK_TRACE_SIZE_IN_LONGS - 1) {
if (!debug_locks_off_graph_unlock())
- return 0;
+ return NULL;
print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!");
dump_stack();
- return 0;
+ return NULL;
}
- return 1;
+ hash = jhash(trace->entries, trace->nr_entries *
+ sizeof(trace->entries[0]), 0);
+ trace->hash = hash;
+ hash_head = stack_trace_hash + (hash & (STACK_TRACE_HASH_SIZE - 1));
+ hlist_for_each_entry(t2, hash_head, hash_entry) {
+ if (traces_identical(trace, t2))
+ return t2;
+ }
+ nr_stack_trace_entries += LOCK_TRACE_SIZE_IN_LONGS + trace->nr_entries;
+ hlist_add_head(&trace->hash_entry, hash_head);
+
+ return trace;
+}
+
+/* Return the number of stack traces in the stack_trace[] array. */
+u64 lockdep_stack_trace_count(void)
+{
+ struct lock_trace *trace;
+ u64 c = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stack_trace_hash); i++) {
+ hlist_for_each_entry(trace, &stack_trace_hash[i], hash_entry) {
+ c++;
+ }
+ }
+
+ return c;
+}
+
+/* Return the number of stack hash chains that have at least one stack trace. */
+u64 lockdep_stack_hash_count(void)
+{
+ u64 c = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stack_trace_hash); i++)
+ if (!hlist_empty(&stack_trace_hash[i]))
+ c++;
+
+ return c;
}
#endif
@@ -491,7 +559,7 @@ unsigned int max_lockdep_depth;
DEFINE_PER_CPU(struct lockdep_stats, lockdep_stats);
#endif
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
/*
* Locking printouts:
*/
@@ -511,7 +579,7 @@ static const char *usage_str[] =
};
#endif
-const char * __get_key_name(struct lockdep_subclass_key *key, char *str)
+const char *__get_key_name(const struct lockdep_subclass_key *key, char *str)
{
return kallsyms_lookup((unsigned long)key, NULL, NULL, NULL, str);
}
@@ -620,7 +688,7 @@ static void print_lock(struct held_lock *hlock)
return;
}
- printk(KERN_CONT "%p", hlock->instance);
+ printk(KERN_CONT "%px", hlock->instance);
print_lock_name(lock);
printk(KERN_CONT ", at: %pS\n", (void *)hlock->acquire_ip);
}
@@ -1235,7 +1303,7 @@ static struct lock_list *alloc_list_entry(void)
static int add_lock_to_list(struct lock_class *this,
struct lock_class *links_to, struct list_head *head,
unsigned long ip, int distance,
- struct lock_trace *trace)
+ const struct lock_trace *trace)
{
struct lock_list *entry;
/*
@@ -1249,7 +1317,7 @@ static int add_lock_to_list(struct lock_class *this,
entry->class = this;
entry->links_to = links_to;
entry->distance = distance;
- entry->trace = *trace;
+ entry->trace = trace;
/*
* Both allocation and removal are done under the graph lock; but
* iteration is under RCU-sched; see look_up_lock_class() and
@@ -1470,11 +1538,10 @@ static inline int __bfs_backwards(struct lock_list *src_entry,
}
-static void print_lock_trace(struct lock_trace *trace, unsigned int spaces)
+static void print_lock_trace(const struct lock_trace *trace,
+ unsigned int spaces)
{
- unsigned long *entries = stack_trace + trace->offset;
-
- stack_trace_print(entries, trace->nr_entries, spaces);
+ stack_trace_print(trace->entries, trace->nr_entries, spaces);
}
/*
@@ -1489,7 +1556,7 @@ print_circular_bug_entry(struct lock_list *target, int depth)
printk("\n-> #%u", depth);
print_lock_name(target->class);
printk(KERN_CONT ":\n");
- print_lock_trace(&target->trace, 6);
+ print_lock_trace(target->trace, 6);
}
static void
@@ -1592,7 +1659,8 @@ static noinline void print_circular_bug(struct lock_list *this,
if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return;
- if (!save_trace(&this->trace))
+ this->trace = save_trace();
+ if (!this->trace)
return;
depth = get_lock_depth(target);
@@ -1715,7 +1783,7 @@ check_path(struct lock_class *target, struct lock_list *src_entry,
*/
static noinline int
check_noncircular(struct held_lock *src, struct held_lock *target,
- struct lock_trace *trace)
+ struct lock_trace **const trace)
{
int ret;
struct lock_list *uninitialized_var(target_entry);
@@ -1729,13 +1797,13 @@ check_noncircular(struct held_lock *src, struct held_lock *target,
ret = check_path(hlock_class(target), &src_entry, &target_entry);
if (unlikely(!ret)) {
- if (!trace->nr_entries) {
+ if (!*trace) {
/*
* If save_trace fails here, the printing might
* trigger a WARN but because of the !nr_entries it
* should not do bad things.
*/
- save_trace(trace);
+ *trace = save_trace();
}
print_circular_bug(&src_entry, target_entry, src, target);
@@ -1859,7 +1927,7 @@ static void print_lock_class_header(struct lock_class *class, int depth)
len += printk("%*s %s", depth, "", usage_str[bit]);
len += printk(KERN_CONT " at:\n");
- print_lock_trace(class->usage_traces + bit, len);
+ print_lock_trace(class->usage_traces[bit], len);
}
}
printk("%*s }\n", depth, "");
@@ -1884,7 +1952,7 @@ print_shortest_lock_dependencies(struct lock_list *leaf,
do {
print_lock_class_header(entry->class, depth);
printk("%*s ... acquired at:\n", depth, "");
- print_lock_trace(&entry->trace, 2);
+ print_lock_trace(entry->trace, 2);
printk("\n");
if (depth == 0 && (entry != root)) {
@@ -1995,14 +2063,14 @@ print_bad_irq_dependency(struct task_struct *curr,
print_lock_name(backwards_entry->class);
pr_warn("\n... which became %s-irq-safe at:\n", irqclass);
- print_lock_trace(backwards_entry->class->usage_traces + bit1, 1);
+ print_lock_trace(backwards_entry->class->usage_traces[bit1], 1);
pr_warn("\nto a %s-irq-unsafe lock:\n", irqclass);
print_lock_name(forwards_entry->class);
pr_warn("\n... which became %s-irq-unsafe at:\n", irqclass);
pr_warn("...");
- print_lock_trace(forwards_entry->class->usage_traces + bit2, 1);
+ print_lock_trace(forwards_entry->class->usage_traces[bit2], 1);
pr_warn("\nother info that might help us debug this:\n\n");
print_irq_lock_scenario(backwards_entry, forwards_entry,
@@ -2011,13 +2079,15 @@ print_bad_irq_dependency(struct task_struct *curr,
lockdep_print_held_locks(curr);
pr_warn("\nthe dependencies between %s-irq-safe lock and the holding lock:\n", irqclass);
- if (!save_trace(&prev_root->trace))
+ prev_root->trace = save_trace();
+ if (!prev_root->trace)
return;
print_shortest_lock_dependencies(backwards_entry, prev_root);
pr_warn("\nthe dependencies between the lock to be acquired");
pr_warn(" and %s-irq-unsafe lock:\n", irqclass);
- if (!save_trace(&next_root->trace))
+ next_root->trace = save_trace();
+ if (!next_root->trace)
return;
print_shortest_lock_dependencies(forwards_entry, next_root);
@@ -2369,7 +2439,8 @@ check_deadlock(struct task_struct *curr, struct held_lock *next)
*/
static int
check_prev_add(struct task_struct *curr, struct held_lock *prev,
- struct held_lock *next, int distance, struct lock_trace *trace)
+ struct held_lock *next, int distance,
+ struct lock_trace **const trace)
{
struct lock_list *entry;
int ret;
@@ -2444,8 +2515,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
return ret;
#endif
- if (!trace->nr_entries && !save_trace(trace))
- return 0;
+ if (!*trace) {
+ *trace = save_trace();
+ if (!*trace)
+ return 0;
+ }
/*
* Ok, all validations passed, add the new lock
@@ -2453,14 +2527,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
*/
ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
&hlock_class(prev)->locks_after,
- next->acquire_ip, distance, trace);
+ next->acquire_ip, distance, *trace);
if (!ret)
return 0;
ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
&hlock_class(next)->locks_before,
- next->acquire_ip, distance, trace);
+ next->acquire_ip, distance, *trace);
if (!ret)
return 0;
@@ -2476,7 +2550,7 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
static int
check_prevs_add(struct task_struct *curr, struct held_lock *next)
{
- struct lock_trace trace = { .nr_entries = 0 };
+ struct lock_trace *trace = NULL;
int depth = curr->lockdep_depth;
struct held_lock *hlock;
@@ -2969,7 +3043,7 @@ static void check_chain_key(struct task_struct *curr)
#endif
}
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
static int mark_lock(struct task_struct *curr, struct held_lock *this,
enum lock_usage_bit new_bit);
@@ -3015,7 +3089,7 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this,
print_lock(this);
pr_warn("{%s} state was registered at:\n", usage_str[prev_bit]);
- print_lock_trace(hlock_class(this)->usage_traces + prev_bit, 1);
+ print_lock_trace(hlock_class(this)->usage_traces[prev_bit], 1);
print_irqtrace_events(curr);
pr_warn("\nother info that might help us debug this:\n");
@@ -3096,7 +3170,8 @@ print_irq_inversion_bug(struct task_struct *curr,
lockdep_print_held_locks(curr);
pr_warn("\nthe shortest dependencies between 2nd lock and 1st lock:\n");
- if (!save_trace(&root->trace))
+ root->trace = save_trace();
+ if (!root->trace)
return;
print_shortest_lock_dependencies(other, root);
@@ -3580,7 +3655,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
hlock_class(this)->usage_mask |= new_mask;
- if (!save_trace(hlock_class(this)->usage_traces + new_bit))
+ if (!(hlock_class(this)->usage_traces[new_bit] = save_trace()))
return 0;
switch (new_bit) {
@@ -3608,7 +3683,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
return ret;
}
-#else /* defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) */
+#else /* CONFIG_PROVE_LOCKING */
static inline int
mark_usage(struct task_struct *curr, struct held_lock *hlock, int check)
@@ -3627,7 +3702,7 @@ static inline int separate_irq_context(struct task_struct *curr,
return 0;
}
-#endif /* defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) */
+#endif /* CONFIG_PROVE_LOCKING */
/*
* Initialize a lock instance's lock-class mapping info:
@@ -4321,8 +4396,7 @@ static void __lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie cookie
*/
static void check_flags(unsigned long flags)
{
-#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP) && \
- defined(CONFIG_TRACE_IRQFLAGS)
+#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP)
if (!debug_locks)
return;
@@ -5158,6 +5232,12 @@ void __init lockdep_init(void)
) / 1024
);
+#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+ printk(" memory used for stack traces: %zu kB\n",
+ (sizeof(stack_trace) + sizeof(stack_trace_hash)) / 1024
+ );
+#endif
+
printk(" per task-struct memory footprint: %zu bytes\n",
sizeof(((struct task_struct *)NULL)->held_locks));
}
diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h
index cc83568d5012..18d85aebbb57 100644
--- a/kernel/locking/lockdep_internals.h
+++ b/kernel/locking/lockdep_internals.h
@@ -92,6 +92,7 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ =
#define MAX_LOCKDEP_ENTRIES 16384UL
#define MAX_LOCKDEP_CHAINS_BITS 15
#define MAX_STACK_TRACE_ENTRIES 262144UL
+#define STACK_TRACE_HASH_SIZE 8192
#else
#define MAX_LOCKDEP_ENTRIES 32768UL
@@ -102,6 +103,7 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ =
* addresses. Protected by the hash_lock.
*/
#define MAX_STACK_TRACE_ENTRIES 524288UL
+#define STACK_TRACE_HASH_SIZE 16384
#endif
#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS)
@@ -116,7 +118,8 @@ extern struct lock_chain lock_chains[];
extern void get_usage_chars(struct lock_class *class,
char usage[LOCK_USAGE_CHARS]);
-extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str);
+extern const char *__get_key_name(const struct lockdep_subclass_key *key,
+ char *str);
struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i);
@@ -137,6 +140,10 @@ extern unsigned int max_bfs_queue_depth;
#ifdef CONFIG_PROVE_LOCKING
extern unsigned long lockdep_count_forward_deps(struct lock_class *);
extern unsigned long lockdep_count_backward_deps(struct lock_class *);
+#ifdef CONFIG_TRACE_IRQFLAGS
+u64 lockdep_stack_trace_count(void);
+u64 lockdep_stack_hash_count(void);
+#endif
#else
static inline unsigned long
lockdep_count_forward_deps(struct lock_class *class)
diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c
index 65b6a1600c8f..dadb7b7fba37 100644
--- a/kernel/locking/lockdep_proc.c
+++ b/kernel/locking/lockdep_proc.c
@@ -200,7 +200,6 @@ static void lockdep_stats_debug_show(struct seq_file *m)
static int lockdep_stats_show(struct seq_file *m, void *v)
{
- struct lock_class *class;
unsigned long nr_unused = 0, nr_uncategorized = 0,
nr_irq_safe = 0, nr_irq_unsafe = 0,
nr_softirq_safe = 0, nr_softirq_unsafe = 0,
@@ -211,6 +210,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
sum_forward_deps = 0;
#ifdef CONFIG_PROVE_LOCKING
+ struct lock_class *class;
+
list_for_each_entry(class, &all_lock_classes, lock_entry) {
if (class->usage_mask == 0)
@@ -284,6 +285,12 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
nr_process_chains);
seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n",
nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
+#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+ seq_printf(m, " number of stack traces: %llu\n",
+ lockdep_stack_trace_count());
+ seq_printf(m, " number of stack hash chains: %llu\n",
+ lockdep_stack_hash_count());
+#endif
seq_printf(m, " combined max dependencies: %11u\n",
(nr_hardirq_chains + 1) *
(nr_softirq_chains + 1) *
@@ -398,7 +405,7 @@ static void seq_lock_time(struct seq_file *m, struct lock_time *lt)
static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
{
- struct lockdep_subclass_key *ckey;
+ const struct lockdep_subclass_key *ckey;
struct lock_class_stats *stats;
struct lock_class *class;
const char *cname;
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index edd1c082dbf5..468a9b8422e3 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -65,11 +65,37 @@ EXPORT_SYMBOL(__mutex_init);
#define MUTEX_FLAGS 0x07
+/*
+ * Internal helper function; C doesn't allow us to hide it :/
+ *
+ * DO NOT USE (outside of mutex code).
+ */
+static inline struct task_struct *__mutex_owner(struct mutex *lock)
+{
+ return (struct task_struct *)(atomic_long_read(&lock->owner) & ~MUTEX_FLAGS);
+}
+
static inline struct task_struct *__owner_task(unsigned long owner)
{
return (struct task_struct *)(owner & ~MUTEX_FLAGS);
}
+bool mutex_is_locked(struct mutex *lock)
+{
+ return __mutex_owner(lock) != NULL;
+}
+EXPORT_SYMBOL(mutex_is_locked);
+
+__must_check enum mutex_trylock_recursive_enum
+mutex_trylock_recursive(struct mutex *lock)
+{
+ if (unlikely(__mutex_owner(lock) == current))
+ return MUTEX_TRYLOCK_RECURSIVE;
+
+ return mutex_trylock(lock);
+}
+EXPORT_SYMBOL(mutex_trylock_recursive);
+
static inline unsigned long __owner_flags(unsigned long owner)
{
return owner & MUTEX_FLAGS;
@@ -908,6 +934,10 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
might_sleep();
+#ifdef CONFIG_DEBUG_MUTEXES
+ DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+#endif
+
ww = container_of(lock, struct ww_mutex, base);
if (use_ww_ctx && ww_ctx) {
if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
@@ -1379,8 +1409,13 @@ __ww_mutex_lock_interruptible_slowpath(struct ww_mutex *lock,
*/
int __sched mutex_trylock(struct mutex *lock)
{
- bool locked = __mutex_trylock(lock);
+ bool locked;
+
+#ifdef CONFIG_DEBUG_MUTEXES
+ DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+#endif
+ locked = __mutex_trylock(lock);
if (locked)
mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index fa83d36e30c6..2874bf556162 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -628,8 +628,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
}
/* [10] Grab the next task, i.e. owner of @lock */
- task = rt_mutex_owner(lock);
- get_task_struct(task);
+ task = get_task_struct(rt_mutex_owner(lock));
raw_spin_lock(&task->pi_lock);
/*
@@ -709,8 +708,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
}
/* [10] Grab the next task, i.e. the owner of @lock */
- task = rt_mutex_owner(lock);
- get_task_struct(task);
+ task = get_task_struct(rt_mutex_owner(lock));
raw_spin_lock(&task->pi_lock);
/* [11] requeue the pi waiters if necessary */
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 37524a47f002..eef04551eae7 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -105,8 +105,9 @@
#ifdef CONFIG_DEBUG_RWSEMS
# define DEBUG_RWSEMS_WARN_ON(c, sem) do { \
if (!debug_locks_silent && \
- WARN_ONCE(c, "DEBUG_RWSEMS_WARN_ON(%s): count = 0x%lx, owner = 0x%lx, curr 0x%lx, list %sempty\n",\
+ WARN_ONCE(c, "DEBUG_RWSEMS_WARN_ON(%s): count = 0x%lx, magic = 0x%lx, owner = 0x%lx, curr 0x%lx, list %sempty\n",\
#c, atomic_long_read(&(sem)->count), \
+ (unsigned long) sem->magic, \
atomic_long_read(&(sem)->owner), (long)current, \
list_empty(&(sem)->wait_list) ? "" : "not ")) \
debug_locks_off(); \
@@ -330,6 +331,9 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name,
debug_check_no_locks_freed((void *)sem, sizeof(*sem));
lockdep_init_map(&sem->dep_map, name, key, 0);
#endif
+#ifdef CONFIG_DEBUG_RWSEMS
+ sem->magic = sem;
+#endif
atomic_long_set(&sem->count, RWSEM_UNLOCKED_VALUE);
raw_spin_lock_init(&sem->wait_lock);
INIT_LIST_HEAD(&sem->wait_list);
@@ -666,7 +670,11 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem,
preempt_disable();
rcu_read_lock();
owner = rwsem_owner_flags(sem, &flags);
- if ((flags & nonspinnable) || (owner && !owner_on_cpu(owner)))
+ /*
+ * Don't check the read-owner as the entry may be stale.
+ */
+ if ((flags & nonspinnable) ||
+ (owner && !(flags & RWSEM_READER_OWNED) && !owner_on_cpu(owner)))
ret = false;
rcu_read_unlock();
preempt_enable();
@@ -720,11 +728,12 @@ rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable)
rcu_read_lock();
for (;;) {
- if (atomic_long_read(&sem->count) & RWSEM_FLAG_HANDOFF) {
- state = OWNER_NONSPINNABLE;
- break;
- }
-
+ /*
+ * When a waiting writer set the handoff flag, it may spin
+ * on the owner as well. Once that writer acquires the lock,
+ * we can spin on it. So we don't need to quit even when the
+ * handoff bit is set.
+ */
new = rwsem_owner_flags(sem, &new_flags);
if ((new != owner) || (new_flags != flags)) {
state = rwsem_owner_state(new, new_flags, nonspinnable);
@@ -970,6 +979,13 @@ static inline bool rwsem_reader_phase_trylock(struct rw_semaphore *sem,
{
return false;
}
+
+static inline int
+rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable)
+{
+ return 0;
+}
+#define OWNER_NULL 1
#endif
/*
@@ -1000,6 +1016,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, int state)
atomic_long_add(-RWSEM_READER_BIAS, &sem->count);
adjustment = 0;
if (rwsem_optimistic_spin(sem, false)) {
+ /* rwsem_optimistic_spin() implies ACQUIRE on success */
/*
* Wake up other readers in the wait list if the front
* waiter is a reader.
@@ -1014,6 +1031,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, int state)
}
return sem;
} else if (rwsem_reader_phase_trylock(sem, waiter.last_rowner)) {
+ /* rwsem_reader_phase_trylock() implies ACQUIRE on success */
return sem;
}
@@ -1032,6 +1050,8 @@ queue:
*/
if (adjustment && !(atomic_long_read(&sem->count) &
(RWSEM_WRITER_MASK | RWSEM_FLAG_HANDOFF))) {
+ /* Provide lock ACQUIRE */
+ smp_acquire__after_ctrl_dep();
raw_spin_unlock_irq(&sem->wait_lock);
rwsem_set_reader_owned(sem);
lockevent_inc(rwsem_rlock_fast);
@@ -1065,15 +1085,18 @@ queue:
wake_up_q(&wake_q);
/* wait to be given the lock */
- while (true) {
+ for (;;) {
set_current_state(state);
- if (!waiter.task)
+ if (!smp_load_acquire(&waiter.task)) {
+ /* Matches rwsem_mark_wake()'s smp_store_release(). */
break;
+ }
if (signal_pending_state(state, current)) {
raw_spin_lock_irq(&sem->wait_lock);
if (waiter.task)
goto out_nolock;
raw_spin_unlock_irq(&sem->wait_lock);
+ /* Ordered by sem->wait_lock against rwsem_mark_wake(). */
break;
}
schedule();
@@ -1083,6 +1106,7 @@ queue:
__set_current_state(TASK_RUNNING);
lockevent_inc(rwsem_rlock);
return sem;
+
out_nolock:
list_del(&waiter.list);
if (list_empty(&sem->wait_list)) {
@@ -1123,8 +1147,10 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
/* do optimistic spinning and steal lock if possible */
if (rwsem_can_spin_on_owner(sem, RWSEM_WR_NONSPINNABLE) &&
- rwsem_optimistic_spin(sem, true))
+ rwsem_optimistic_spin(sem, true)) {
+ /* rwsem_optimistic_spin() implies ACQUIRE on success */
return sem;
+ }
/*
* Disable reader optimistic spinning for this rwsem after
@@ -1184,12 +1210,26 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
wait:
/* wait until we successfully acquire the lock */
set_current_state(state);
- while (true) {
- if (rwsem_try_write_lock(sem, wstate))
+ for (;;) {
+ if (rwsem_try_write_lock(sem, wstate)) {
+ /* rwsem_try_write_lock() implies ACQUIRE on success */
break;
+ }
raw_spin_unlock_irq(&sem->wait_lock);
+ /*
+ * After setting the handoff bit and failing to acquire
+ * the lock, attempt to spin on owner to accelerate lock
+ * transfer. If the previous owner is a on-cpu writer and it
+ * has just released the lock, OWNER_NULL will be returned.
+ * In this case, we attempt to acquire the lock again
+ * without sleeping.
+ */
+ if ((wstate == WRITER_HANDOFF) &&
+ (rwsem_spin_on_owner(sem, 0) == OWNER_NULL))
+ goto trylock_again;
+
/* Block until there are no active lockers. */
for (;;) {
if (signal_pending_state(state, current))
@@ -1224,7 +1264,7 @@ wait:
break;
}
}
-
+trylock_again:
raw_spin_lock_irq(&sem->wait_lock);
}
__set_current_state(TASK_RUNNING);
@@ -1322,11 +1362,14 @@ static inline int __down_read_killable(struct rw_semaphore *sem)
static inline int __down_read_trylock(struct rw_semaphore *sem)
{
+ long tmp;
+
+ DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem);
+
/*
* Optimize for the case when the rwsem is not locked at all.
*/
- long tmp = RWSEM_UNLOCKED_VALUE;
-
+ tmp = RWSEM_UNLOCKED_VALUE;
do {
if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp,
tmp + RWSEM_READER_BIAS)) {
@@ -1367,8 +1410,11 @@ static inline int __down_write_killable(struct rw_semaphore *sem)
static inline int __down_write_trylock(struct rw_semaphore *sem)
{
- long tmp = RWSEM_UNLOCKED_VALUE;
+ long tmp;
+
+ DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem);
+ tmp = RWSEM_UNLOCKED_VALUE;
if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp,
RWSEM_WRITER_LOCKED)) {
rwsem_set_owner(sem);
@@ -1384,7 +1430,9 @@ inline void __up_read(struct rw_semaphore *sem)
{
long tmp;
+ DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem);
DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
+
rwsem_clear_reader_owned(sem);
tmp = atomic_long_add_return_release(-RWSEM_READER_BIAS, &sem->count);
DEBUG_RWSEMS_WARN_ON(tmp < 0, sem);
@@ -1402,12 +1450,14 @@ static inline void __up_write(struct rw_semaphore *sem)
{
long tmp;
+ DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem);
/*
* sem->owner may differ from current if the ownership is transferred
* to an anonymous writer by setting the RWSEM_NONSPINNABLE bits.
*/
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) &&
!rwsem_test_oflags(sem, RWSEM_NONSPINNABLE), sem);
+
rwsem_clear_owner(sem);
tmp = atomic_long_fetch_add_release(-RWSEM_WRITER_LOCKED, &sem->count);
if (unlikely(tmp & RWSEM_FLAG_WAITERS))
diff --git a/kernel/module.c b/kernel/module.c
index 5933395af9a0..9ee93421269c 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -65,9 +65,9 @@
/*
* Modules' sections will be aligned on page boundaries
* to ensure complete separation of code and data, but
- * only when CONFIG_STRICT_MODULE_RWX=y
+ * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
*/
-#ifdef CONFIG_STRICT_MODULE_RWX
+#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
# define debug_align(X) ALIGN(X, PAGE_SIZE)
#else
# define debug_align(X) (X)
diff --git a/kernel/rcu/Kconfig b/kernel/rcu/Kconfig
index 480edf328b51..7644eda17d62 100644
--- a/kernel/rcu/Kconfig
+++ b/kernel/rcu/Kconfig
@@ -7,7 +7,7 @@ menu "RCU Subsystem"
config TREE_RCU
bool
- default y if !PREEMPT && SMP
+ default y if !PREEMPTION && SMP
help
This option selects the RCU implementation that is
designed for very large SMP system with hundreds or
@@ -16,7 +16,7 @@ config TREE_RCU
config PREEMPT_RCU
bool
- default y if PREEMPT
+ default y if PREEMPTION
help
This option selects the RCU implementation that is
designed for very large SMP systems with hundreds or
@@ -28,7 +28,7 @@ config PREEMPT_RCU
config TINY_RCU
bool
- default y if !PREEMPT && !SMP
+ default y if !PREEMPTION && !SMP
help
This option selects the RCU implementation that is
designed for UP systems from which real-time response
@@ -70,7 +70,7 @@ config TREE_SRCU
This option selects the full-fledged version of SRCU.
config TASKS_RCU
- def_bool PREEMPT
+ def_bool PREEMPTION
select SRCU
help
This option enables a task-based RCU implementation that uses
diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug
index 5ec3ea4028e2..4aa02eee8f6c 100644
--- a/kernel/rcu/Kconfig.debug
+++ b/kernel/rcu/Kconfig.debug
@@ -8,6 +8,17 @@ menu "RCU Debugging"
config PROVE_RCU
def_bool PROVE_LOCKING
+config PROVE_RCU_LIST
+ bool "RCU list lockdep debugging"
+ depends on PROVE_RCU && RCU_EXPERT
+ default n
+ help
+ Enable RCU lockdep checking for list usages. By default it is
+ turned off since there are several list RCU users that still
+ need to be converted to pass a lockdep expression. To prevent
+ false-positive splats, we keep it default disabled but once all
+ users are converted, we can remove this config option.
+
config TORTURE_TEST
tristate
default n
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index 5290b01de534..8fd4f82c9b3d 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -227,6 +227,7 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
#ifdef CONFIG_RCU_STALL_COMMON
+extern int rcu_cpu_stall_ftrace_dump;
extern int rcu_cpu_stall_suppress;
extern int rcu_cpu_stall_timeout;
int rcu_jiffies_till_stall_check(void);
diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c
index 9bd5f6023c21..495c58ce1640 100644
--- a/kernel/rcu/rcu_segcblist.c
+++ b/kernel/rcu/rcu_segcblist.c
@@ -24,6 +24,49 @@ void rcu_cblist_init(struct rcu_cblist *rclp)
}
/*
+ * Enqueue an rcu_head structure onto the specified callback list.
+ * This function assumes that the callback is non-lazy because it
+ * is intended for use by no-CBs CPUs, which do not distinguish
+ * between lazy and non-lazy RCU callbacks.
+ */
+void rcu_cblist_enqueue(struct rcu_cblist *rclp, struct rcu_head *rhp)
+{
+ *rclp->tail = rhp;
+ rclp->tail = &rhp->next;
+ WRITE_ONCE(rclp->len, rclp->len + 1);
+}
+
+/*
+ * Flush the second rcu_cblist structure onto the first one, obliterating
+ * any contents of the first. If rhp is non-NULL, enqueue it as the sole
+ * element of the second rcu_cblist structure, but ensuring that the second
+ * rcu_cblist structure, if initially non-empty, always appears non-empty
+ * throughout the process. If rdp is NULL, the second rcu_cblist structure
+ * is instead initialized to empty.
+ */
+void rcu_cblist_flush_enqueue(struct rcu_cblist *drclp,
+ struct rcu_cblist *srclp,
+ struct rcu_head *rhp)
+{
+ drclp->head = srclp->head;
+ if (drclp->head)
+ drclp->tail = srclp->tail;
+ else
+ drclp->tail = &drclp->head;
+ drclp->len = srclp->len;
+ drclp->len_lazy = srclp->len_lazy;
+ if (!rhp) {
+ rcu_cblist_init(srclp);
+ } else {
+ rhp->next = NULL;
+ srclp->head = rhp;
+ srclp->tail = &rhp->next;
+ WRITE_ONCE(srclp->len, 1);
+ srclp->len_lazy = 0;
+ }
+}
+
+/*
* Dequeue the oldest rcu_head structure from the specified callback
* list. This function assumes that the callback is non-lazy, but
* the caller can later invoke rcu_cblist_dequeued_lazy() if it
@@ -44,6 +87,67 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp)
return rhp;
}
+/* Set the length of an rcu_segcblist structure. */
+void rcu_segcblist_set_len(struct rcu_segcblist *rsclp, long v)
+{
+#ifdef CONFIG_RCU_NOCB_CPU
+ atomic_long_set(&rsclp->len, v);
+#else
+ WRITE_ONCE(rsclp->len, v);
+#endif
+}
+
+/*
+ * Increase the numeric length of an rcu_segcblist structure by the
+ * specified amount, which can be negative. This can cause the ->len
+ * field to disagree with the actual number of callbacks on the structure.
+ * This increase is fully ordered with respect to the callers accesses
+ * both before and after.
+ */
+void rcu_segcblist_add_len(struct rcu_segcblist *rsclp, long v)
+{
+#ifdef CONFIG_RCU_NOCB_CPU
+ smp_mb__before_atomic(); /* Up to the caller! */
+ atomic_long_add(v, &rsclp->len);
+ smp_mb__after_atomic(); /* Up to the caller! */
+#else
+ smp_mb(); /* Up to the caller! */
+ WRITE_ONCE(rsclp->len, rsclp->len + v);
+ smp_mb(); /* Up to the caller! */
+#endif
+}
+
+/*
+ * Increase the numeric length of an rcu_segcblist structure by one.
+ * This can cause the ->len field to disagree with the actual number of
+ * callbacks on the structure. This increase is fully ordered with respect
+ * to the callers accesses both before and after.
+ */
+void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp)
+{
+ rcu_segcblist_add_len(rsclp, 1);
+}
+
+/*
+ * Exchange the numeric length of the specified rcu_segcblist structure
+ * with the specified value. This can cause the ->len field to disagree
+ * with the actual number of callbacks on the structure. This exchange is
+ * fully ordered with respect to the callers accesses both before and after.
+ */
+long rcu_segcblist_xchg_len(struct rcu_segcblist *rsclp, long v)
+{
+#ifdef CONFIG_RCU_NOCB_CPU
+ return atomic_long_xchg(&rsclp->len, v);
+#else
+ long ret = rsclp->len;
+
+ smp_mb(); /* Up to the caller! */
+ WRITE_ONCE(rsclp->len, v);
+ smp_mb(); /* Up to the caller! */
+ return ret;
+#endif
+}
+
/*
* Initialize an rcu_segcblist structure.
*/
@@ -56,8 +160,9 @@ void rcu_segcblist_init(struct rcu_segcblist *rsclp)
rsclp->head = NULL;
for (i = 0; i < RCU_CBLIST_NSEGS; i++)
rsclp->tails[i] = &rsclp->head;
- rsclp->len = 0;
+ rcu_segcblist_set_len(rsclp, 0);
rsclp->len_lazy = 0;
+ rsclp->enabled = 1;
}
/*
@@ -69,7 +174,16 @@ void rcu_segcblist_disable(struct rcu_segcblist *rsclp)
WARN_ON_ONCE(!rcu_segcblist_empty(rsclp));
WARN_ON_ONCE(rcu_segcblist_n_cbs(rsclp));
WARN_ON_ONCE(rcu_segcblist_n_lazy_cbs(rsclp));
- rsclp->tails[RCU_NEXT_TAIL] = NULL;
+ rsclp->enabled = 0;
+}
+
+/*
+ * Mark the specified rcu_segcblist structure as offloaded. This
+ * structure must be empty.
+ */
+void rcu_segcblist_offload(struct rcu_segcblist *rsclp)
+{
+ rsclp->offloaded = 1;
}
/*
@@ -118,6 +232,18 @@ struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp)
}
/*
+ * Return false if there are no CBs awaiting grace periods, otherwise,
+ * return true and store the nearest waited-upon grace period into *lp.
+ */
+bool rcu_segcblist_nextgp(struct rcu_segcblist *rsclp, unsigned long *lp)
+{
+ if (!rcu_segcblist_pend_cbs(rsclp))
+ return false;
+ *lp = rsclp->gp_seq[RCU_WAIT_TAIL];
+ return true;
+}
+
+/*
* Enqueue the specified callback onto the specified rcu_segcblist
* structure, updating accounting as needed. Note that the ->len
* field may be accessed locklessly, hence the WRITE_ONCE().
@@ -129,13 +255,13 @@ struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp)
void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp,
struct rcu_head *rhp, bool lazy)
{
- WRITE_ONCE(rsclp->len, rsclp->len + 1); /* ->len sampled locklessly. */
+ rcu_segcblist_inc_len(rsclp);
if (lazy)
rsclp->len_lazy++;
smp_mb(); /* Ensure counts are updated before callback is enqueued. */
rhp->next = NULL;
- *rsclp->tails[RCU_NEXT_TAIL] = rhp;
- rsclp->tails[RCU_NEXT_TAIL] = &rhp->next;
+ WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rhp);
+ WRITE_ONCE(rsclp->tails[RCU_NEXT_TAIL], &rhp->next);
}
/*
@@ -155,7 +281,7 @@ bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp,
if (rcu_segcblist_n_cbs(rsclp) == 0)
return false;
- WRITE_ONCE(rsclp->len, rsclp->len + 1);
+ rcu_segcblist_inc_len(rsclp);
if (lazy)
rsclp->len_lazy++;
smp_mb(); /* Ensure counts are updated before callback is entrained. */
@@ -163,9 +289,9 @@ bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp,
for (i = RCU_NEXT_TAIL; i > RCU_DONE_TAIL; i--)
if (rsclp->tails[i] != rsclp->tails[i - 1])
break;
- *rsclp->tails[i] = rhp;
+ WRITE_ONCE(*rsclp->tails[i], rhp);
for (; i <= RCU_NEXT_TAIL; i++)
- rsclp->tails[i] = &rhp->next;
+ WRITE_ONCE(rsclp->tails[i], &rhp->next);
return true;
}
@@ -182,9 +308,8 @@ void rcu_segcblist_extract_count(struct rcu_segcblist *rsclp,
struct rcu_cblist *rclp)
{
rclp->len_lazy += rsclp->len_lazy;
- rclp->len += rsclp->len;
rsclp->len_lazy = 0;
- WRITE_ONCE(rsclp->len, 0); /* ->len sampled locklessly. */
+ rclp->len = rcu_segcblist_xchg_len(rsclp, 0);
}
/*
@@ -200,12 +325,12 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp,
if (!rcu_segcblist_ready_cbs(rsclp))
return; /* Nothing to do. */
*rclp->tail = rsclp->head;
- rsclp->head = *rsclp->tails[RCU_DONE_TAIL];
- *rsclp->tails[RCU_DONE_TAIL] = NULL;
+ WRITE_ONCE(rsclp->head, *rsclp->tails[RCU_DONE_TAIL]);
+ WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL);
rclp->tail = rsclp->tails[RCU_DONE_TAIL];
for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--)
if (rsclp->tails[i] == rsclp->tails[RCU_DONE_TAIL])
- rsclp->tails[i] = &rsclp->head;
+ WRITE_ONCE(rsclp->tails[i], &rsclp->head);
}
/*
@@ -224,9 +349,9 @@ void rcu_segcblist_extract_pend_cbs(struct rcu_segcblist *rsclp,
return; /* Nothing to do. */
*rclp->tail = *rsclp->tails[RCU_DONE_TAIL];
rclp->tail = rsclp->tails[RCU_NEXT_TAIL];
- *rsclp->tails[RCU_DONE_TAIL] = NULL;
+ WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL);
for (i = RCU_DONE_TAIL + 1; i < RCU_CBLIST_NSEGS; i++)
- rsclp->tails[i] = rsclp->tails[RCU_DONE_TAIL];
+ WRITE_ONCE(rsclp->tails[i], rsclp->tails[RCU_DONE_TAIL]);
}
/*
@@ -237,8 +362,7 @@ void rcu_segcblist_insert_count(struct rcu_segcblist *rsclp,
struct rcu_cblist *rclp)
{
rsclp->len_lazy += rclp->len_lazy;
- /* ->len sampled locklessly. */
- WRITE_ONCE(rsclp->len, rsclp->len + rclp->len);
+ rcu_segcblist_add_len(rsclp, rclp->len);
rclp->len_lazy = 0;
rclp->len = 0;
}
@@ -255,10 +379,10 @@ void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp,
if (!rclp->head)
return; /* No callbacks to move. */
*rclp->tail = rsclp->head;
- rsclp->head = rclp->head;
+ WRITE_ONCE(rsclp->head, rclp->head);
for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++)
if (&rsclp->head == rsclp->tails[i])
- rsclp->tails[i] = rclp->tail;
+ WRITE_ONCE(rsclp->tails[i], rclp->tail);
else
break;
rclp->head = NULL;
@@ -274,8 +398,8 @@ void rcu_segcblist_insert_pend_cbs(struct rcu_segcblist *rsclp,
{
if (!rclp->head)
return; /* Nothing to do. */
- *rsclp->tails[RCU_NEXT_TAIL] = rclp->head;
- rsclp->tails[RCU_NEXT_TAIL] = rclp->tail;
+ WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rclp->head);
+ WRITE_ONCE(rsclp->tails[RCU_NEXT_TAIL], rclp->tail);
rclp->head = NULL;
rclp->tail = &rclp->head;
}
@@ -299,7 +423,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++) {
if (ULONG_CMP_LT(seq, rsclp->gp_seq[i]))
break;
- rsclp->tails[RCU_DONE_TAIL] = rsclp->tails[i];
+ WRITE_ONCE(rsclp->tails[RCU_DONE_TAIL], rsclp->tails[i]);
}
/* If no callbacks moved, nothing more need be done. */
@@ -308,7 +432,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
/* Clean up tail pointers that might have been misordered above. */
for (j = RCU_WAIT_TAIL; j < i; j++)
- rsclp->tails[j] = rsclp->tails[RCU_DONE_TAIL];
+ WRITE_ONCE(rsclp->tails[j], rsclp->tails[RCU_DONE_TAIL]);
/*
* Callbacks moved, so clean up the misordered ->tails[] pointers
@@ -319,7 +443,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
for (j = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++, j++) {
if (rsclp->tails[j] == rsclp->tails[RCU_NEXT_TAIL])
break; /* No more callbacks. */
- rsclp->tails[j] = rsclp->tails[i];
+ WRITE_ONCE(rsclp->tails[j], rsclp->tails[i]);
rsclp->gp_seq[j] = rsclp->gp_seq[i];
}
}
@@ -384,7 +508,7 @@ bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq)
* structure other than in the RCU_NEXT_TAIL segment.
*/
for (; i < RCU_NEXT_TAIL; i++) {
- rsclp->tails[i] = rsclp->tails[RCU_NEXT_TAIL];
+ WRITE_ONCE(rsclp->tails[i], rsclp->tails[RCU_NEXT_TAIL]);
rsclp->gp_seq[i] = seq;
}
return true;
diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h
index 71b64648464e..815c2fdd3fcc 100644
--- a/kernel/rcu/rcu_segcblist.h
+++ b/kernel/rcu/rcu_segcblist.h
@@ -9,6 +9,12 @@
#include <linux/rcu_segcblist.h>
+/* Return number of callbacks in the specified callback list. */
+static inline long rcu_cblist_n_cbs(struct rcu_cblist *rclp)
+{
+ return READ_ONCE(rclp->len);
+}
+
/*
* Account for the fact that a previously dequeued callback turned out
* to be marked as lazy.
@@ -19,6 +25,10 @@ static inline void rcu_cblist_dequeued_lazy(struct rcu_cblist *rclp)
}
void rcu_cblist_init(struct rcu_cblist *rclp);
+void rcu_cblist_enqueue(struct rcu_cblist *rclp, struct rcu_head *rhp);
+void rcu_cblist_flush_enqueue(struct rcu_cblist *drclp,
+ struct rcu_cblist *srclp,
+ struct rcu_head *rhp);
struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp);
/*
@@ -36,13 +46,17 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp);
*/
static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp)
{
- return !rsclp->head;
+ return !READ_ONCE(rsclp->head);
}
/* Return number of callbacks in segmented callback list. */
static inline long rcu_segcblist_n_cbs(struct rcu_segcblist *rsclp)
{
+#ifdef CONFIG_RCU_NOCB_CPU
+ return atomic_long_read(&rsclp->len);
+#else
return READ_ONCE(rsclp->len);
+#endif
}
/* Return number of lazy callbacks in segmented callback list. */
@@ -54,16 +68,22 @@ static inline long rcu_segcblist_n_lazy_cbs(struct rcu_segcblist *rsclp)
/* Return number of lazy callbacks in segmented callback list. */
static inline long rcu_segcblist_n_nonlazy_cbs(struct rcu_segcblist *rsclp)
{
- return rsclp->len - rsclp->len_lazy;
+ return rcu_segcblist_n_cbs(rsclp) - rsclp->len_lazy;
}
/*
* Is the specified rcu_segcblist enabled, for example, not corresponding
- * to an offline or callback-offloaded CPU?
+ * to an offline CPU?
*/
static inline bool rcu_segcblist_is_enabled(struct rcu_segcblist *rsclp)
{
- return !!rsclp->tails[RCU_NEXT_TAIL];
+ return rsclp->enabled;
+}
+
+/* Is the specified rcu_segcblist offloaded? */
+static inline bool rcu_segcblist_is_offloaded(struct rcu_segcblist *rsclp)
+{
+ return rsclp->offloaded;
}
/*
@@ -73,36 +93,18 @@ static inline bool rcu_segcblist_is_enabled(struct rcu_segcblist *rsclp)
*/
static inline bool rcu_segcblist_restempty(struct rcu_segcblist *rsclp, int seg)
{
- return !*rsclp->tails[seg];
-}
-
-/*
- * Interim function to return rcu_segcblist head pointer. Longer term, the
- * rcu_segcblist will be used more pervasively, removing the need for this
- * function.
- */
-static inline struct rcu_head *rcu_segcblist_head(struct rcu_segcblist *rsclp)
-{
- return rsclp->head;
-}
-
-/*
- * Interim function to return rcu_segcblist head pointer. Longer term, the
- * rcu_segcblist will be used more pervasively, removing the need for this
- * function.
- */
-static inline struct rcu_head **rcu_segcblist_tail(struct rcu_segcblist *rsclp)
-{
- WARN_ON_ONCE(rcu_segcblist_empty(rsclp));
- return rsclp->tails[RCU_NEXT_TAIL];
+ return !READ_ONCE(*READ_ONCE(rsclp->tails[seg]));
}
+void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp);
void rcu_segcblist_init(struct rcu_segcblist *rsclp);
void rcu_segcblist_disable(struct rcu_segcblist *rsclp);
+void rcu_segcblist_offload(struct rcu_segcblist *rsclp);
bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp);
bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp);
struct rcu_head *rcu_segcblist_first_cb(struct rcu_segcblist *rsclp);
struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp);
+bool rcu_segcblist_nextgp(struct rcu_segcblist *rsclp, unsigned long *lp);
void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp,
struct rcu_head *rhp, bool lazy);
bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp,
diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c
index 7a6890b23c5f..5a879d073c1c 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -89,7 +89,7 @@ torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable
static char *perf_type = "rcu";
module_param(perf_type, charp, 0444);
-MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, rcu_bh, ...)");
+MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, srcu, ...)");
static int nrealreaders;
static int nrealwriters;
@@ -375,6 +375,14 @@ rcu_perf_writer(void *arg)
if (holdoff)
schedule_timeout_uninterruptible(holdoff * HZ);
+ /*
+ * Wait until rcu_end_inkernel_boot() is called for normal GP tests
+ * so that RCU is not always expedited for normal GP tests.
+ * The system_state test is approximate, but works well in practice.
+ */
+ while (!gp_exp && system_state != SYSTEM_RUNNING)
+ schedule_timeout_uninterruptible(1);
+
t = ktime_get_mono_fast_ns();
if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
t_rcu_perf_writer_started = t;
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index fce4e7e6f502..3c9feca1eab1 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -161,6 +161,7 @@ static atomic_long_t n_rcu_torture_timers;
static long n_barrier_attempts;
static long n_barrier_successes; /* did rcu_barrier test succeed? */
static struct list_head rcu_torture_removed;
+static unsigned long shutdown_jiffies;
static int rcu_torture_writer_state;
#define RTWS_FIXED_DELAY 0
@@ -228,6 +229,15 @@ static u64 notrace rcu_trace_clock_local(void)
}
#endif /* #else #ifdef CONFIG_RCU_TRACE */
+/*
+ * Stop aggressive CPU-hog tests a bit before the end of the test in order
+ * to avoid interfering with test shutdown.
+ */
+static bool shutdown_time_arrived(void)
+{
+ return shutdown_secs && time_after(jiffies, shutdown_jiffies - 30 * HZ);
+}
+
static unsigned long boost_starttime; /* jiffies of next boost test start. */
static DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
/* and boost task create/destroy. */
@@ -1713,12 +1723,14 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
}
// Give the scheduler a chance, even on nohz_full CPUs.
-static void rcu_torture_fwd_prog_cond_resched(void)
+static void rcu_torture_fwd_prog_cond_resched(unsigned long iter)
{
if (IS_ENABLED(CONFIG_PREEMPT) && IS_ENABLED(CONFIG_NO_HZ_FULL)) {
- if (need_resched())
+ // Real call_rcu() floods hit userspace, so emulate that.
+ if (need_resched() || (iter & 0xfff))
schedule();
} else {
+ // No userspace emulation: CB invocation throttles call_rcu()
cond_resched();
}
}
@@ -1746,7 +1758,7 @@ static unsigned long rcu_torture_fwd_prog_cbfree(void)
spin_unlock_irqrestore(&rcu_fwd_lock, flags);
kfree(rfcp);
freed++;
- rcu_torture_fwd_prog_cond_resched();
+ rcu_torture_fwd_prog_cond_resched(freed);
}
return freed;
}
@@ -1785,15 +1797,17 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)
WRITE_ONCE(rcu_fwd_startat, jiffies);
stopat = rcu_fwd_startat + dur;
while (time_before(jiffies, stopat) &&
+ !shutdown_time_arrived() &&
!READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
idx = cur_ops->readlock();
udelay(10);
cur_ops->readunlock(idx);
if (!fwd_progress_need_resched || need_resched())
- rcu_torture_fwd_prog_cond_resched();
+ rcu_torture_fwd_prog_cond_resched(1);
}
(*tested_tries)++;
if (!time_before(jiffies, stopat) &&
+ !shutdown_time_arrived() &&
!READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
(*tested)++;
cver = READ_ONCE(rcu_torture_current_version) - cver;
@@ -1852,6 +1866,7 @@ static void rcu_torture_fwd_prog_cr(void)
gps = cur_ops->get_gp_seq();
rcu_launder_gp_seq_start = gps;
while (time_before(jiffies, stopat) &&
+ !shutdown_time_arrived() &&
!READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
rfcp = READ_ONCE(rcu_fwd_cb_head);
rfcpn = NULL;
@@ -1875,7 +1890,7 @@ static void rcu_torture_fwd_prog_cr(void)
rfcp->rfc_gps = 0;
}
cur_ops->call(&rfcp->rh, rcu_torture_fwd_cb_cr);
- rcu_torture_fwd_prog_cond_resched();
+ rcu_torture_fwd_prog_cond_resched(n_launders + n_max_cbs);
}
stoppedat = jiffies;
n_launders_cb_snap = READ_ONCE(n_launders_cb);
@@ -1884,7 +1899,8 @@ static void rcu_torture_fwd_prog_cr(void)
cur_ops->cb_barrier(); /* Wait for callbacks to be invoked. */
(void)rcu_torture_fwd_prog_cbfree();
- if (!torture_must_stop() && !READ_ONCE(rcu_fwd_emergency_stop)) {
+ if (!torture_must_stop() && !READ_ONCE(rcu_fwd_emergency_stop) &&
+ !shutdown_time_arrived()) {
WARN_ON(n_max_gps < MIN_FWD_CBS_LAUNDERED);
pr_alert("%s Duration %lu barrier: %lu pending %ld n_launders: %ld n_launders_sa: %ld n_max_gps: %ld n_max_cbs: %ld cver %ld gps %ld\n",
__func__,
@@ -2160,6 +2176,7 @@ rcu_torture_cleanup(void)
return;
}
+ show_rcu_gp_kthreads();
rcu_torture_barrier_cleanup();
torture_stop_kthread(rcu_torture_fwd_prog, fwd_prog_task);
torture_stop_kthread(rcu_torture_stall, stall_task);
@@ -2465,6 +2482,7 @@ rcu_torture_init(void)
goto unwind;
rcutor_hp = firsterr;
}
+ shutdown_jiffies = jiffies + shutdown_secs * HZ;
firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
if (firsterr)
goto unwind;
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index cf0e886314f2..5dffade2d7cd 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -1279,8 +1279,9 @@ void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf)
c0 = l0 - u0;
c1 = l1 - u1;
- pr_cont(" %d(%ld,%ld %1p)",
- cpu, c0, c1, rcu_segcblist_head(&sdp->srcu_cblist));
+ pr_cont(" %d(%ld,%ld %c)",
+ cpu, c0, c1,
+ "C."[rcu_segcblist_empty(&sdp->srcu_cblist)]);
s0 += c0;
s1 += c1;
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index a14e5fbbea46..81105141b6a8 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -56,6 +56,7 @@
#include <linux/smpboot.h>
#include <linux/jiffies.h>
#include <linux/sched/isolation.h>
+#include <linux/sched/clock.h>
#include "../time/tick-internal.h"
#include "tree.h"
@@ -210,9 +211,9 @@ static long rcu_get_n_cbs_cpu(int cpu)
{
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
- if (rcu_segcblist_is_enabled(&rdp->cblist)) /* Online normal CPU? */
+ if (rcu_segcblist_is_enabled(&rdp->cblist))
return rcu_segcblist_n_cbs(&rdp->cblist);
- return rcu_get_n_cbs_nocb_cpu(rdp); /* Works for offline, too. */
+ return 0;
}
void rcu_softirq_qs(void)
@@ -416,6 +417,12 @@ module_param(qlowmark, long, 0444);
static ulong jiffies_till_first_fqs = ULONG_MAX;
static ulong jiffies_till_next_fqs = ULONG_MAX;
static bool rcu_kick_kthreads;
+static int rcu_divisor = 7;
+module_param(rcu_divisor, int, 0644);
+
+/* Force an exit from rcu_do_batch() after 3 milliseconds. */
+static long rcu_resched_ns = 3 * NSEC_PER_MSEC;
+module_param(rcu_resched_ns, long, 0644);
/*
* How long the grace period must be before we start recruiting
@@ -1251,6 +1258,7 @@ static bool rcu_accelerate_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
unsigned long gp_seq_req;
bool ret = false;
+ rcu_lockdep_assert_cblist_protected(rdp);
raw_lockdep_assert_held_rcu_node(rnp);
/* If no pending (not yet ready to invoke) callbacks, nothing to do. */
@@ -1292,7 +1300,7 @@ static void rcu_accelerate_cbs_unlocked(struct rcu_node *rnp,
unsigned long c;
bool needwake;
- lockdep_assert_irqs_disabled();
+ rcu_lockdep_assert_cblist_protected(rdp);
c = rcu_seq_snap(&rcu_state.gp_seq);
if (!rdp->gpwrap && ULONG_CMP_GE(rdp->gp_seq_needed, c)) {
/* Old request still live, so mark recent callbacks. */
@@ -1318,6 +1326,7 @@ static void rcu_accelerate_cbs_unlocked(struct rcu_node *rnp,
*/
static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
{
+ rcu_lockdep_assert_cblist_protected(rdp);
raw_lockdep_assert_held_rcu_node(rnp);
/* If no pending (not yet ready to invoke) callbacks, nothing to do. */
@@ -1335,6 +1344,21 @@ static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
}
/*
+ * Move and classify callbacks, but only if doing so won't require
+ * that the RCU grace-period kthread be awakened.
+ */
+static void __maybe_unused rcu_advance_cbs_nowake(struct rcu_node *rnp,
+ struct rcu_data *rdp)
+{
+ rcu_lockdep_assert_cblist_protected(rdp);
+ if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) ||
+ !raw_spin_trylock_rcu_node(rnp))
+ return;
+ WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp));
+ raw_spin_unlock_rcu_node(rnp);
+}
+
+/*
* Update CPU-local rcu_data state to record the beginnings and ends of
* grace periods. The caller must hold the ->lock of the leaf rcu_node
* structure corresponding to the current CPU, and must have irqs disabled.
@@ -1342,8 +1366,10 @@ static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
*/
static bool __note_gp_changes(struct rcu_node *rnp, struct rcu_data *rdp)
{
- bool ret;
+ bool ret = false;
bool need_gp;
+ const bool offloaded = IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ rcu_segcblist_is_offloaded(&rdp->cblist);
raw_lockdep_assert_held_rcu_node(rnp);
@@ -1353,10 +1379,12 @@ static bool __note_gp_changes(struct rcu_node *rnp, struct rcu_data *rdp)
/* Handle the ends of any preceding grace periods first. */
if (rcu_seq_completed_gp(rdp->gp_seq, rnp->gp_seq) ||
unlikely(READ_ONCE(rdp->gpwrap))) {
- ret = rcu_advance_cbs(rnp, rdp); /* Advance callbacks. */
+ if (!offloaded)
+ ret = rcu_advance_cbs(rnp, rdp); /* Advance CBs. */
trace_rcu_grace_period(rcu_state.name, rdp->gp_seq, TPS("cpuend"));
} else {
- ret = rcu_accelerate_cbs(rnp, rdp); /* Recent callbacks. */
+ if (!offloaded)
+ ret = rcu_accelerate_cbs(rnp, rdp); /* Recent CBs. */
}
/* Now handle the beginnings of any new-to-this-CPU grace periods. */
@@ -1657,6 +1685,7 @@ static void rcu_gp_cleanup(void)
unsigned long gp_duration;
bool needgp = false;
unsigned long new_gp_seq;
+ bool offloaded;
struct rcu_data *rdp;
struct rcu_node *rnp = rcu_get_root();
struct swait_queue_head *sq;
@@ -1722,7 +1751,9 @@ static void rcu_gp_cleanup(void)
needgp = true;
}
/* Advance CBs to reduce false positives below. */
- if (!rcu_accelerate_cbs(rnp, rdp) && needgp) {
+ offloaded = IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ rcu_segcblist_is_offloaded(&rdp->cblist);
+ if ((offloaded || !rcu_accelerate_cbs(rnp, rdp)) && needgp) {
WRITE_ONCE(rcu_state.gp_flags, RCU_GP_FLAG_INIT);
rcu_state.gp_req_activity = jiffies;
trace_rcu_grace_period(rcu_state.name,
@@ -1881,7 +1912,7 @@ rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
struct rcu_node *rnp_p;
raw_lockdep_assert_held_rcu_node(rnp);
- if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT)) ||
+ if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPTION)) ||
WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp)) ||
rnp->qsmask != 0) {
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
@@ -1916,7 +1947,9 @@ rcu_report_qs_rdp(int cpu, struct rcu_data *rdp)
{
unsigned long flags;
unsigned long mask;
- bool needwake;
+ bool needwake = false;
+ const bool offloaded = IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ rcu_segcblist_is_offloaded(&rdp->cblist);
struct rcu_node *rnp;
rnp = rdp->mynode;
@@ -1943,7 +1976,8 @@ rcu_report_qs_rdp(int cpu, struct rcu_data *rdp)
* This GP can't end until cpu checks in, so all of our
* callbacks can be processed during the next GP.
*/
- needwake = rcu_accelerate_cbs(rnp, rdp);
+ if (!offloaded)
+ needwake = rcu_accelerate_cbs(rnp, rdp);
rcu_report_qs_rnp(mask, rnp, rnp->gp_seq, flags);
/* ^^^ Released rnp->lock */
@@ -2077,9 +2111,12 @@ int rcutree_dead_cpu(unsigned int cpu)
static void rcu_do_batch(struct rcu_data *rdp)
{
unsigned long flags;
+ const bool offloaded = IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ rcu_segcblist_is_offloaded(&rdp->cblist);
struct rcu_head *rhp;
struct rcu_cblist rcl = RCU_CBLIST_INITIALIZER(rcl);
long bl, count;
+ long pending, tlimit = 0;
/* If no callbacks are ready, just return. */
if (!rcu_segcblist_ready_cbs(&rdp->cblist)) {
@@ -2099,13 +2136,19 @@ static void rcu_do_batch(struct rcu_data *rdp)
* callback counts, as rcu_barrier() needs to be conservative.
*/
local_irq_save(flags);
+ rcu_nocb_lock(rdp);
WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
- bl = rdp->blimit;
+ pending = rcu_segcblist_n_cbs(&rdp->cblist);
+ bl = max(rdp->blimit, pending >> rcu_divisor);
+ if (unlikely(bl > 100))
+ tlimit = local_clock() + rcu_resched_ns;
trace_rcu_batch_start(rcu_state.name,
rcu_segcblist_n_lazy_cbs(&rdp->cblist),
rcu_segcblist_n_cbs(&rdp->cblist), bl);
rcu_segcblist_extract_done_cbs(&rdp->cblist, &rcl);
- local_irq_restore(flags);
+ if (offloaded)
+ rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
/* Invoke callbacks. */
rhp = rcu_cblist_dequeue(&rcl);
@@ -2117,13 +2160,29 @@ static void rcu_do_batch(struct rcu_data *rdp)
* Stop only if limit reached and CPU has something to do.
* Note: The rcl structure counts down from zero.
*/
- if (-rcl.len >= bl &&
+ if (-rcl.len >= bl && !offloaded &&
(need_resched() ||
(!is_idle_task(current) && !rcu_is_callbacks_kthread())))
break;
+ if (unlikely(tlimit)) {
+ /* only call local_clock() every 32 callbacks */
+ if (likely((-rcl.len & 31) || local_clock() < tlimit))
+ continue;
+ /* Exceeded the time limit, so leave. */
+ break;
+ }
+ if (offloaded) {
+ WARN_ON_ONCE(in_serving_softirq());
+ local_bh_enable();
+ lockdep_assert_irqs_enabled();
+ cond_resched_tasks_rcu_qs();
+ lockdep_assert_irqs_enabled();
+ local_bh_disable();
+ }
}
local_irq_save(flags);
+ rcu_nocb_lock(rdp);
count = -rcl.len;
trace_rcu_batch_end(rcu_state.name, count, !!rcl.head, need_resched(),
is_idle_task(current), rcu_is_callbacks_kthread());
@@ -2149,12 +2208,14 @@ static void rcu_do_batch(struct rcu_data *rdp)
* The following usually indicates a double call_rcu(). To track
* this down, try building with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.
*/
- WARN_ON_ONCE(rcu_segcblist_empty(&rdp->cblist) != (count == 0));
+ WARN_ON_ONCE(count == 0 && !rcu_segcblist_empty(&rdp->cblist));
+ WARN_ON_ONCE(!IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ count != 0 && rcu_segcblist_empty(&rdp->cblist));
- local_irq_restore(flags);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
/* Re-invoke RCU core processing if there are callbacks remaining. */
- if (rcu_segcblist_ready_cbs(&rdp->cblist))
+ if (!offloaded && rcu_segcblist_ready_cbs(&rdp->cblist))
invoke_rcu_core();
}
@@ -2205,7 +2266,7 @@ static void force_qs_rnp(int (*f)(struct rcu_data *rdp))
mask = 0;
raw_spin_lock_irqsave_rcu_node(rnp, flags);
if (rnp->qsmask == 0) {
- if (!IS_ENABLED(CONFIG_PREEMPT) ||
+ if (!IS_ENABLED(CONFIG_PREEMPTION) ||
rcu_preempt_blocked_readers_cgp(rnp)) {
/*
* No point in scanning bits because they
@@ -2280,6 +2341,8 @@ static __latent_entropy void rcu_core(void)
unsigned long flags;
struct rcu_data *rdp = raw_cpu_ptr(&rcu_data);
struct rcu_node *rnp = rdp->mynode;
+ const bool offloaded = IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ rcu_segcblist_is_offloaded(&rdp->cblist);
if (cpu_is_offline(smp_processor_id()))
return;
@@ -2299,7 +2362,7 @@ static __latent_entropy void rcu_core(void)
/* No grace period and unregistered callbacks? */
if (!rcu_gp_in_progress() &&
- rcu_segcblist_is_enabled(&rdp->cblist)) {
+ rcu_segcblist_is_enabled(&rdp->cblist) && !offloaded) {
local_irq_save(flags);
if (!rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL))
rcu_accelerate_cbs_unlocked(rnp, rdp);
@@ -2309,7 +2372,7 @@ static __latent_entropy void rcu_core(void)
rcu_check_gp_start_stall(rnp, rdp, rcu_jiffies_till_stall_check());
/* If there are callbacks ready, invoke them. */
- if (rcu_segcblist_ready_cbs(&rdp->cblist) &&
+ if (!offloaded && rcu_segcblist_ready_cbs(&rdp->cblist) &&
likely(READ_ONCE(rcu_scheduler_fully_active)))
rcu_do_batch(rdp);
@@ -2489,10 +2552,11 @@ static void rcu_leak_callback(struct rcu_head *rhp)
* is expected to specify a CPU.
*/
static void
-__call_rcu(struct rcu_head *head, rcu_callback_t func, int cpu, bool lazy)
+__call_rcu(struct rcu_head *head, rcu_callback_t func, bool lazy)
{
unsigned long flags;
struct rcu_data *rdp;
+ bool was_alldone;
/* Misaligned rcu_head! */
WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1));
@@ -2514,28 +2578,18 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func, int cpu, bool lazy)
rdp = this_cpu_ptr(&rcu_data);
/* Add the callback to our list. */
- if (unlikely(!rcu_segcblist_is_enabled(&rdp->cblist)) || cpu != -1) {
- int offline;
-
- if (cpu != -1)
- rdp = per_cpu_ptr(&rcu_data, cpu);
- if (likely(rdp->mynode)) {
- /* Post-boot, so this should be for a no-CBs CPU. */
- offline = !__call_rcu_nocb(rdp, head, lazy, flags);
- WARN_ON_ONCE(offline);
- /* Offline CPU, _call_rcu() illegal, leak callback. */
- local_irq_restore(flags);
- return;
- }
- /*
- * Very early boot, before rcu_init(). Initialize if needed
- * and then drop through to queue the callback.
- */
- WARN_ON_ONCE(cpu != -1);
+ if (unlikely(!rcu_segcblist_is_enabled(&rdp->cblist))) {
+ // This can trigger due to call_rcu() from offline CPU:
+ WARN_ON_ONCE(rcu_scheduler_active != RCU_SCHEDULER_INACTIVE);
WARN_ON_ONCE(!rcu_is_watching());
+ // Very early boot, before rcu_init(). Initialize if needed
+ // and then drop through to queue the callback.
if (rcu_segcblist_empty(&rdp->cblist))
rcu_segcblist_init(&rdp->cblist);
}
+ if (rcu_nocb_try_bypass(rdp, head, &was_alldone, flags))
+ return; // Enqueued onto ->nocb_bypass, so just leave.
+ /* If we get here, rcu_nocb_try_bypass() acquired ->nocb_lock. */
rcu_segcblist_enqueue(&rdp->cblist, head, lazy);
if (__is_kfree_rcu_offset((unsigned long)func))
trace_rcu_kfree_callback(rcu_state.name, head,
@@ -2548,8 +2602,13 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func, int cpu, bool lazy)
rcu_segcblist_n_cbs(&rdp->cblist));
/* Go handle any RCU core processing required. */
- __call_rcu_core(rdp, head, flags);
- local_irq_restore(flags);
+ if (IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
+ unlikely(rcu_segcblist_is_offloaded(&rdp->cblist))) {
+ __call_rcu_nocb_wake(rdp, was_alldone, flags); /* unlocks */
+ } else {
+ __call_rcu_core(rdp, head, flags);
+ local_irq_restore(flags);
+ }
}
/**
@@ -2589,7 +2648,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func, int cpu, bool lazy)
*/
void call_rcu(struct rcu_head *head, rcu_callback_t func)
{
- __call_rcu(head, func, -1, 0);
+ __call_rcu(head, func, 0);
}
EXPORT_SYMBOL_GPL(call_rcu);
@@ -2602,7 +2661,7 @@ EXPORT_SYMBOL_GPL(call_rcu);
*/
void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func)
{
- __call_rcu(head, func, -1, 1);
+ __call_rcu(head, func, 1);
}
EXPORT_SYMBOL_GPL(kfree_call_rcu);
@@ -2622,7 +2681,7 @@ static int rcu_blocking_is_gp(void)
{
int ret;
- if (IS_ENABLED(CONFIG_PREEMPT))
+ if (IS_ENABLED(CONFIG_PREEMPTION))
return rcu_scheduler_active == RCU_SCHEDULER_INACTIVE;
might_sleep(); /* Check for RCU read-side critical section. */
preempt_disable();
@@ -2735,6 +2794,10 @@ static int rcu_pending(void)
/* Check for CPU stalls, if enabled. */
check_cpu_stall(rdp);
+ /* Does this CPU need a deferred NOCB wakeup? */
+ if (rcu_nocb_need_deferred_wakeup(rdp))
+ return 1;
+
/* Is this CPU a NO_HZ_FULL CPU that should ignore RCU? */
if (rcu_nohz_full_cpu())
return 0;
@@ -2750,6 +2813,8 @@ static int rcu_pending(void)
/* Has RCU gone idle with this CPU needing another grace period? */
if (!rcu_gp_in_progress() &&
rcu_segcblist_is_enabled(&rdp->cblist) &&
+ (!IS_ENABLED(CONFIG_RCU_NOCB_CPU) ||
+ !rcu_segcblist_is_offloaded(&rdp->cblist)) &&
!rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL))
return 1;
@@ -2758,10 +2823,6 @@ static int rcu_pending(void)
unlikely(READ_ONCE(rdp->gpwrap))) /* outside lock */
return 1;
- /* Does this CPU need a deferred NOCB wakeup? */
- if (rcu_nocb_need_deferred_wakeup(rdp))
- return 1;
-
/* nothing to do */
return 0;
}
@@ -2801,6 +2862,8 @@ static void rcu_barrier_func(void *unused)
rcu_barrier_trace(TPS("IRQ"), -1, rcu_state.barrier_sequence);
rdp->barrier_head.func = rcu_barrier_callback;
debug_rcu_head_queue(&rdp->barrier_head);
+ rcu_nocb_lock(rdp);
+ WARN_ON_ONCE(!rcu_nocb_flush_bypass(rdp, NULL, jiffies));
if (rcu_segcblist_entrain(&rdp->cblist, &rdp->barrier_head, 0)) {
atomic_inc(&rcu_state.barrier_cpu_count);
} else {
@@ -2808,6 +2871,7 @@ static void rcu_barrier_func(void *unused)
rcu_barrier_trace(TPS("IRQNQ"), -1,
rcu_state.barrier_sequence);
}
+ rcu_nocb_unlock(rdp);
}
/**
@@ -2858,22 +2922,11 @@ void rcu_barrier(void)
* corresponding CPU's preceding callbacks have been invoked.
*/
for_each_possible_cpu(cpu) {
- if (!cpu_online(cpu) && !rcu_is_nocb_cpu(cpu))
- continue;
rdp = per_cpu_ptr(&rcu_data, cpu);
- if (rcu_is_nocb_cpu(cpu)) {
- if (!rcu_nocb_cpu_needs_barrier(cpu)) {
- rcu_barrier_trace(TPS("OfflineNoCB"), cpu,
- rcu_state.barrier_sequence);
- } else {
- rcu_barrier_trace(TPS("OnlineNoCB"), cpu,
- rcu_state.barrier_sequence);
- smp_mb__before_atomic();
- atomic_inc(&rcu_state.barrier_cpu_count);
- __call_rcu(&rdp->barrier_head,
- rcu_barrier_callback, cpu, 0);
- }
- } else if (rcu_segcblist_n_cbs(&rdp->cblist)) {
+ if (!cpu_online(cpu) &&
+ !rcu_segcblist_is_offloaded(&rdp->cblist))
+ continue;
+ if (rcu_segcblist_n_cbs(&rdp->cblist)) {
rcu_barrier_trace(TPS("OnlineQ"), cpu,
rcu_state.barrier_sequence);
smp_call_function_single(cpu, rcu_barrier_func, NULL, 1);
@@ -2958,7 +3011,8 @@ rcu_boot_init_percpu_data(int cpu)
* Initializes a CPU's per-CPU RCU data. Note that only one online or
* offline event can be happening at a given time. Note also that we can
* accept some slop in the rsp->gp_seq access due to the fact that this
- * CPU cannot possibly have any RCU callbacks in flight yet.
+ * CPU cannot possibly have any non-offloaded RCU callbacks in flight yet.
+ * And any offloaded callbacks are being numbered elsewhere.
*/
int rcutree_prepare_cpu(unsigned int cpu)
{
@@ -2972,7 +3026,7 @@ int rcutree_prepare_cpu(unsigned int cpu)
rdp->n_force_qs_snap = rcu_state.n_force_qs;
rdp->blimit = blimit;
if (rcu_segcblist_empty(&rdp->cblist) && /* No early-boot CBs? */
- !init_nocb_callback_list(rdp))
+ !rcu_segcblist_is_offloaded(&rdp->cblist))
rcu_segcblist_init(&rdp->cblist); /* Re-enable callbacks. */
rdp->dynticks_nesting = 1; /* CPU not up, no tearing. */
rcu_dynticks_eqs_online();
@@ -3151,29 +3205,38 @@ void rcutree_migrate_callbacks(int cpu)
{
unsigned long flags;
struct rcu_data *my_rdp;
+ struct rcu_node *my_rnp;
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
- struct rcu_node *rnp_root = rcu_get_root();
bool needwake;
- if (rcu_is_nocb_cpu(cpu) || rcu_segcblist_empty(&rdp->cblist))
+ if (rcu_segcblist_is_offloaded(&rdp->cblist) ||
+ rcu_segcblist_empty(&rdp->cblist))
return; /* No callbacks to migrate. */
local_irq_save(flags);
my_rdp = this_cpu_ptr(&rcu_data);
- if (rcu_nocb_adopt_orphan_cbs(my_rdp, rdp, flags)) {
- local_irq_restore(flags);
- return;
- }
- raw_spin_lock_rcu_node(rnp_root); /* irqs already disabled. */
+ my_rnp = my_rdp->mynode;
+ rcu_nocb_lock(my_rdp); /* irqs already disabled. */
+ WARN_ON_ONCE(!rcu_nocb_flush_bypass(my_rdp, NULL, jiffies));
+ raw_spin_lock_rcu_node(my_rnp); /* irqs already disabled. */
/* Leverage recent GPs and set GP for new callbacks. */
- needwake = rcu_advance_cbs(rnp_root, rdp) ||
- rcu_advance_cbs(rnp_root, my_rdp);
+ needwake = rcu_advance_cbs(my_rnp, rdp) ||
+ rcu_advance_cbs(my_rnp, my_rdp);
rcu_segcblist_merge(&my_rdp->cblist, &rdp->cblist);
+ needwake = needwake || rcu_advance_cbs(my_rnp, my_rdp);
+ rcu_segcblist_disable(&rdp->cblist);
WARN_ON_ONCE(rcu_segcblist_empty(&my_rdp->cblist) !=
!rcu_segcblist_n_cbs(&my_rdp->cblist));
- raw_spin_unlock_irqrestore_rcu_node(rnp_root, flags);
+ if (rcu_segcblist_is_offloaded(&my_rdp->cblist)) {
+ raw_spin_unlock_rcu_node(my_rnp); /* irqs remain disabled. */
+ __call_rcu_nocb_wake(my_rdp, true, flags);
+ } else {
+ rcu_nocb_unlock(my_rdp); /* irqs remain disabled. */
+ raw_spin_unlock_irqrestore_rcu_node(my_rnp, flags);
+ }
if (needwake)
rcu_gp_kthread_wake();
+ lockdep_assert_irqs_enabled();
WARN_ONCE(rcu_segcblist_n_cbs(&rdp->cblist) != 0 ||
!rcu_segcblist_empty(&rdp->cblist),
"rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, 1stCB=%p\n",
@@ -3234,13 +3297,13 @@ static int __init rcu_spawn_gp_kthread(void)
t = kthread_create(rcu_gp_kthread, NULL, "%s", rcu_state.name);
if (WARN_ONCE(IS_ERR(t), "%s: Could not start grace-period kthread, OOM is now expected behavior\n", __func__))
return 0;
- rnp = rcu_get_root();
- raw_spin_lock_irqsave_rcu_node(rnp, flags);
- rcu_state.gp_kthread = t;
if (kthread_prio) {
sp.sched_priority = kthread_prio;
sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
}
+ rnp = rcu_get_root();
+ raw_spin_lock_irqsave_rcu_node(rnp, flags);
+ rcu_state.gp_kthread = t;
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
wake_up_process(t);
rcu_spawn_nocb_kthreads();
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 7acaf3a62d39..c612f306fe89 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -194,29 +194,38 @@ struct rcu_data {
/* 5) Callback offloading. */
#ifdef CONFIG_RCU_NOCB_CPU
- struct rcu_head *nocb_head; /* CBs waiting for kthread. */
- struct rcu_head **nocb_tail;
- atomic_long_t nocb_q_count; /* # CBs waiting for nocb */
- atomic_long_t nocb_q_count_lazy; /* invocation (all stages). */
- struct rcu_head *nocb_follower_head; /* CBs ready to invoke. */
- struct rcu_head **nocb_follower_tail;
- struct swait_queue_head nocb_wq; /* For nocb kthreads to sleep on. */
- struct task_struct *nocb_kthread;
+ struct swait_queue_head nocb_cb_wq; /* For nocb kthreads to sleep on. */
+ struct task_struct *nocb_gp_kthread;
raw_spinlock_t nocb_lock; /* Guard following pair of fields. */
+ atomic_t nocb_lock_contended; /* Contention experienced. */
int nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */
struct timer_list nocb_timer; /* Enforce finite deferral. */
-
- /* The following fields are used by the leader, hence own cacheline. */
- struct rcu_head *nocb_gp_head ____cacheline_internodealigned_in_smp;
- /* CBs waiting for GP. */
- struct rcu_head **nocb_gp_tail;
- bool nocb_leader_sleep; /* Is the nocb leader thread asleep? */
- struct rcu_data *nocb_next_follower;
- /* Next follower in wakeup chain. */
-
- /* The following fields are used by the follower, hence new cachline. */
- struct rcu_data *nocb_leader ____cacheline_internodealigned_in_smp;
- /* Leader CPU takes GP-end wakeups. */
+ unsigned long nocb_gp_adv_time; /* Last call_rcu() CB adv (jiffies). */
+
+ /* The following fields are used by call_rcu, hence own cacheline. */
+ raw_spinlock_t nocb_bypass_lock ____cacheline_internodealigned_in_smp;
+ struct rcu_cblist nocb_bypass; /* Lock-contention-bypass CB list. */
+ unsigned long nocb_bypass_first; /* Time (jiffies) of first enqueue. */
+ unsigned long nocb_nobypass_last; /* Last ->cblist enqueue (jiffies). */
+ int nocb_nobypass_count; /* # ->cblist enqueues at ^^^ time. */
+
+ /* The following fields are used by GP kthread, hence own cacheline. */
+ raw_spinlock_t nocb_gp_lock ____cacheline_internodealigned_in_smp;
+ struct timer_list nocb_bypass_timer; /* Force nocb_bypass flush. */
+ u8 nocb_gp_sleep; /* Is the nocb GP thread asleep? */
+ u8 nocb_gp_bypass; /* Found a bypass on last scan? */
+ u8 nocb_gp_gp; /* GP to wait for on last scan? */
+ unsigned long nocb_gp_seq; /* If so, ->gp_seq to wait for. */
+ unsigned long nocb_gp_loops; /* # passes through wait code. */
+ struct swait_queue_head nocb_gp_wq; /* For nocb kthreads to sleep on. */
+ bool nocb_cb_sleep; /* Is the nocb CB thread asleep? */
+ struct task_struct *nocb_cb_kthread;
+ struct rcu_data *nocb_next_cb_rdp;
+ /* Next rcu_data in wakeup chain. */
+
+ /* The following fields are used by CB kthread, hence new cacheline. */
+ struct rcu_data *nocb_gp_rdp ____cacheline_internodealigned_in_smp;
+ /* GP rdp takes GP-end wakeups. */
#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
/* 6) RCU priority boosting. */
@@ -419,25 +428,39 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
static bool rcu_preempt_need_deferred_qs(struct task_struct *t);
static void rcu_preempt_deferred_qs(struct task_struct *t);
static void zero_cpu_stall_ticks(struct rcu_data *rdp);
-static bool rcu_nocb_cpu_needs_barrier(int cpu);
static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp);
static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq);
static void rcu_init_one_nocb(struct rcu_node *rnp);
-static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
- bool lazy, unsigned long flags);
-static bool rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
- struct rcu_data *rdp,
- unsigned long flags);
+static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ unsigned long j);
+static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ bool *was_alldone, unsigned long flags);
+static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty,
+ unsigned long flags);
static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
static void rcu_spawn_cpu_nocb_kthread(int cpu);
static void __init rcu_spawn_nocb_kthreads(void);
+static void show_rcu_nocb_state(struct rcu_data *rdp);
+static void rcu_nocb_lock(struct rcu_data *rdp);
+static void rcu_nocb_unlock(struct rcu_data *rdp);
+static void rcu_nocb_unlock_irqrestore(struct rcu_data *rdp,
+ unsigned long flags);
+static void rcu_lockdep_assert_cblist_protected(struct rcu_data *rdp);
#ifdef CONFIG_RCU_NOCB_CPU
static void __init rcu_organize_nocb_kthreads(void);
-#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
-static bool init_nocb_callback_list(struct rcu_data *rdp);
-static unsigned long rcu_get_n_cbs_nocb_cpu(struct rcu_data *rdp);
+#define rcu_nocb_lock_irqsave(rdp, flags) \
+do { \
+ if (!rcu_segcblist_is_offloaded(&(rdp)->cblist)) \
+ local_irq_save(flags); \
+ else \
+ raw_spin_lock_irqsave(&(rdp)->nocb_lock, (flags)); \
+} while (0)
+#else /* #ifdef CONFIG_RCU_NOCB_CPU */
+#define rcu_nocb_lock_irqsave(rdp, flags) local_irq_save(flags)
+#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
+
static void rcu_bind_gp_kthread(void);
static bool rcu_nohz_full_cpu(void);
static void rcu_dynticks_task_enter(void);
diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h
index af7e7b9c86af..d632cd019597 100644
--- a/kernel/rcu/tree_exp.h
+++ b/kernel/rcu/tree_exp.h
@@ -781,7 +781,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp)
* other hand, if the CPU is not in an RCU read-side critical section,
* the IPI handler reports the quiescent state immediately.
*
- * Although this is a greate improvement over previous expedited
+ * Although this is a great improvement over previous expedited
* implementations, it is still unfriendly to real-time workloads, so is
* thus not recommended for any sort of common-case code. In fact, if
* you are using synchronize_rcu_expedited() in a loop, please restructure
@@ -792,6 +792,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp)
*/
void synchronize_rcu_expedited(void)
{
+ bool boottime = (rcu_scheduler_active == RCU_SCHEDULER_INIT);
struct rcu_exp_work rew;
struct rcu_node *rnp;
unsigned long s;
@@ -817,7 +818,7 @@ void synchronize_rcu_expedited(void)
return; /* Someone else did our work for us. */
/* Ensure that load happens before action based on it. */
- if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) {
+ if (unlikely(boottime)) {
/* Direct call during scheduler init and early_initcalls(). */
rcu_exp_sel_wait_wake(s);
} else {
@@ -835,5 +836,8 @@ void synchronize_rcu_expedited(void)
/* Let the next expedited grace period start. */
mutex_unlock(&rcu_state.exp_mutex);
+
+ if (likely(!boottime))
+ destroy_work_on_stack(&rew.rew_work);
}
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index acb225023ed1..2defc7fe74c3 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -288,7 +288,6 @@ void rcu_note_context_switch(bool preempt)
struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
struct rcu_node *rnp;
- barrier(); /* Avoid RCU read-side critical sections leaking down. */
trace_rcu_utilization(TPS("Start context switch"));
lockdep_assert_irqs_disabled();
WARN_ON_ONCE(!preempt && t->rcu_read_lock_nesting > 0);
@@ -314,15 +313,6 @@ void rcu_note_context_switch(bool preempt)
? rnp->gp_seq
: rcu_seq_snap(&rnp->gp_seq));
rcu_preempt_ctxt_queue(rnp, rdp);
- } else if (t->rcu_read_lock_nesting < 0 &&
- t->rcu_read_unlock_special.s) {
-
- /*
- * Complete exit from RCU read-side critical section on
- * behalf of preempted instance of __rcu_read_unlock().
- */
- rcu_read_unlock_special(t);
- rcu_preempt_deferred_qs(t);
} else {
rcu_preempt_deferred_qs(t);
}
@@ -340,7 +330,6 @@ void rcu_note_context_switch(bool preempt)
if (rdp->exp_deferred_qs)
rcu_report_exp_rdp(rdp);
trace_rcu_utilization(TPS("End context switch"));
- barrier(); /* Avoid RCU read-side critical sections leaking up. */
}
EXPORT_SYMBOL_GPL(rcu_note_context_switch);
@@ -626,22 +615,18 @@ static void rcu_read_unlock_special(struct task_struct *t)
(rdp->grpmask & rnp->expmask) ||
tick_nohz_full_cpu(rdp->cpu);
// Need to defer quiescent state until everything is enabled.
- if ((exp || in_irq()) && irqs_were_disabled && use_softirq &&
- (in_irq() || !t->rcu_read_unlock_special.b.deferred_qs)) {
+ if (irqs_were_disabled && use_softirq &&
+ (in_interrupt() ||
+ (exp && !t->rcu_read_unlock_special.b.deferred_qs))) {
// Using softirq, safe to awaken, and we get
// no help from enabling irqs, unlike bh/preempt.
raise_softirq_irqoff(RCU_SOFTIRQ);
- } else if (exp && irqs_were_disabled && !use_softirq &&
- !t->rcu_read_unlock_special.b.deferred_qs) {
- // Safe to awaken and we get no help from enabling
- // irqs, unlike bh/preempt.
- invoke_rcu_core();
} else {
// Enabling BH or preempt does reschedule, so...
// Also if no expediting or NO_HZ_FULL, slow is OK.
set_tsk_need_resched(current);
set_preempt_need_resched();
- if (IS_ENABLED(CONFIG_IRQ_WORK) &&
+ if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled &&
!rdp->defer_qs_iw_pending && exp) {
// Get scheduler to re-evaluate and call hooks.
// If !IRQ_WORK, FQS scan will eventually IPI.
@@ -828,11 +813,6 @@ static void rcu_qs(void)
* dyntick-idle quiescent state visible to other CPUs, which will in
* some cases serve for expedited as well as normal grace periods.
* Either way, register a lightweight quiescent state.
- *
- * The barrier() calls are redundant in the common case when this is
- * called externally, but just in case this is called from within this
- * file.
- *
*/
void rcu_all_qs(void)
{
@@ -847,14 +827,12 @@ void rcu_all_qs(void)
return;
}
this_cpu_write(rcu_data.rcu_urgent_qs, false);
- barrier(); /* Avoid RCU read-side critical sections leaking down. */
if (unlikely(raw_cpu_read(rcu_data.rcu_need_heavy_qs))) {
local_irq_save(flags);
rcu_momentary_dyntick_idle();
local_irq_restore(flags);
}
rcu_qs();
- barrier(); /* Avoid RCU read-side critical sections leaking up. */
preempt_enable();
}
EXPORT_SYMBOL_GPL(rcu_all_qs);
@@ -864,7 +842,6 @@ EXPORT_SYMBOL_GPL(rcu_all_qs);
*/
void rcu_note_context_switch(bool preempt)
{
- barrier(); /* Avoid RCU read-side critical sections leaking down. */
trace_rcu_utilization(TPS("Start context switch"));
rcu_qs();
/* Load rcu_urgent_qs before other flags. */
@@ -877,7 +854,6 @@ void rcu_note_context_switch(bool preempt)
rcu_tasks_qs(current);
out:
trace_rcu_utilization(TPS("End context switch"));
- barrier(); /* Avoid RCU read-side critical sections leaking up. */
}
EXPORT_SYMBOL_GPL(rcu_note_context_switch);
@@ -1134,7 +1110,7 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp)
* already exist. We only create this kthread for preemptible RCU.
* Returns zero if all is well, a negated errno otherwise.
*/
-static int rcu_spawn_one_boost_kthread(struct rcu_node *rnp)
+static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp)
{
int rnp_index = rnp - rcu_get_root();
unsigned long flags;
@@ -1142,25 +1118,27 @@ static int rcu_spawn_one_boost_kthread(struct rcu_node *rnp)
struct task_struct *t;
if (!IS_ENABLED(CONFIG_PREEMPT_RCU))
- return 0;
+ return;
if (!rcu_scheduler_fully_active || rcu_rnp_online_cpus(rnp) == 0)
- return 0;
+ return;
rcu_state.boost = 1;
+
if (rnp->boost_kthread_task != NULL)
- return 0;
+ return;
+
t = kthread_create(rcu_boost_kthread, (void *)rnp,
"rcub/%d", rnp_index);
- if (IS_ERR(t))
- return PTR_ERR(t);
+ if (WARN_ON_ONCE(IS_ERR(t)))
+ return;
+
raw_spin_lock_irqsave_rcu_node(rnp, flags);
rnp->boost_kthread_task = t;
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
sp.sched_priority = kthread_prio;
sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */
- return 0;
}
/*
@@ -1201,7 +1179,7 @@ static void __init rcu_spawn_boost_kthreads(void)
struct rcu_node *rnp;
rcu_for_each_leaf_node(rnp)
- (void)rcu_spawn_one_boost_kthread(rnp);
+ rcu_spawn_one_boost_kthread(rnp);
}
static void rcu_prepare_kthreads(int cpu)
@@ -1211,7 +1189,7 @@ static void rcu_prepare_kthreads(int cpu)
/* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
if (rcu_scheduler_fully_active)
- (void)rcu_spawn_one_boost_kthread(rnp);
+ rcu_spawn_one_boost_kthread(rnp);
}
#else /* #ifdef CONFIG_RCU_BOOST */
@@ -1248,10 +1226,10 @@ static void rcu_prepare_kthreads(int cpu)
#if !defined(CONFIG_RCU_FAST_NO_HZ)
/*
- * Check to see if any future RCU-related work will need to be done
- * by the current CPU, even if none need be done immediately, returning
- * 1 if so. This function is part of the RCU implementation; it is -not-
- * an exported member of the RCU API.
+ * Check to see if any future non-offloaded RCU-related work will need
+ * to be done by the current CPU, even if none need be done immediately,
+ * returning 1 if so. This function is part of the RCU implementation;
+ * it is -not- an exported member of the RCU API.
*
* Because we not have RCU_FAST_NO_HZ, just check whether or not this
* CPU has RCU callbacks queued.
@@ -1259,7 +1237,8 @@ static void rcu_prepare_kthreads(int cpu)
int rcu_needs_cpu(u64 basemono, u64 *nextevt)
{
*nextevt = KTIME_MAX;
- return !rcu_segcblist_empty(&this_cpu_ptr(&rcu_data)->cblist);
+ return !rcu_segcblist_empty(&this_cpu_ptr(&rcu_data)->cblist) &&
+ !rcu_segcblist_is_offloaded(&this_cpu_ptr(&rcu_data)->cblist);
}
/*
@@ -1360,8 +1339,9 @@ int rcu_needs_cpu(u64 basemono, u64 *nextevt)
lockdep_assert_irqs_disabled();
- /* If no callbacks, RCU doesn't need the CPU. */
- if (rcu_segcblist_empty(&rdp->cblist)) {
+ /* If no non-offloaded callbacks, RCU doesn't need the CPU. */
+ if (rcu_segcblist_empty(&rdp->cblist) ||
+ rcu_segcblist_is_offloaded(&this_cpu_ptr(&rcu_data)->cblist)) {
*nextevt = KTIME_MAX;
return 0;
}
@@ -1404,7 +1384,7 @@ static void rcu_prepare_for_idle(void)
int tne;
lockdep_assert_irqs_disabled();
- if (rcu_is_nocb_cpu(smp_processor_id()))
+ if (rcu_segcblist_is_offloaded(&rdp->cblist))
return;
/* Handle nohz enablement switches conservatively. */
@@ -1453,8 +1433,10 @@ static void rcu_prepare_for_idle(void)
*/
static void rcu_cleanup_after_idle(void)
{
+ struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
+
lockdep_assert_irqs_disabled();
- if (rcu_is_nocb_cpu(smp_processor_id()))
+ if (rcu_segcblist_is_offloaded(&rdp->cblist))
return;
if (rcu_try_advance_all_cbs())
invoke_rcu_core();
@@ -1469,10 +1451,10 @@ static void rcu_cleanup_after_idle(void)
* specified by rcu_nocb_mask. For the CPUs in the set, there are kthreads
* created that pull the callbacks from the corresponding CPU, wait for
* a grace period to elapse, and invoke the callbacks. These kthreads
- * are organized into leaders, which manage incoming callbacks, wait for
- * grace periods, and awaken followers, and the followers, which only
- * invoke callbacks. Each leader is its own follower. The no-CBs CPUs
- * do a wake_up() on their kthread when they insert a callback into any
+ * are organized into GP kthreads, which manage incoming callbacks, wait for
+ * grace periods, and awaken CB kthreads, and the CB kthreads, which only
+ * invoke callbacks. Each GP kthread invokes its own CBs. The no-CBs CPUs
+ * do a wake_up() on their GP kthread when they insert a callback into any
* empty list, unless the rcu_nocb_poll boot parameter has been specified,
* in which case each kthread actively polls its CPU. (Which isn't so great
* for energy efficiency, but which does reduce RCU's overhead on that CPU.)
@@ -1515,6 +1497,116 @@ static int __init parse_rcu_nocb_poll(char *arg)
early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
/*
+ * Don't bother bypassing ->cblist if the call_rcu() rate is low.
+ * After all, the main point of bypassing is to avoid lock contention
+ * on ->nocb_lock, which only can happen at high call_rcu() rates.
+ */
+int nocb_nobypass_lim_per_jiffy = 16 * 1000 / HZ;
+module_param(nocb_nobypass_lim_per_jiffy, int, 0);
+
+/*
+ * Acquire the specified rcu_data structure's ->nocb_bypass_lock. If the
+ * lock isn't immediately available, increment ->nocb_lock_contended to
+ * flag the contention.
+ */
+static void rcu_nocb_bypass_lock(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
+ if (raw_spin_trylock(&rdp->nocb_bypass_lock))
+ return;
+ atomic_inc(&rdp->nocb_lock_contended);
+ WARN_ON_ONCE(smp_processor_id() != rdp->cpu);
+ smp_mb__after_atomic(); /* atomic_inc() before lock. */
+ raw_spin_lock(&rdp->nocb_bypass_lock);
+ smp_mb__before_atomic(); /* atomic_dec() after lock. */
+ atomic_dec(&rdp->nocb_lock_contended);
+}
+
+/*
+ * Spinwait until the specified rcu_data structure's ->nocb_lock is
+ * not contended. Please note that this is extremely special-purpose,
+ * relying on the fact that at most two kthreads and one CPU contend for
+ * this lock, and also that the two kthreads are guaranteed to have frequent
+ * grace-period-duration time intervals between successive acquisitions
+ * of the lock. This allows us to use an extremely simple throttling
+ * mechanism, and further to apply it only to the CPU doing floods of
+ * call_rcu() invocations. Don't try this at home!
+ */
+static void rcu_nocb_wait_contended(struct rcu_data *rdp)
+{
+ WARN_ON_ONCE(smp_processor_id() != rdp->cpu);
+ while (WARN_ON_ONCE(atomic_read(&rdp->nocb_lock_contended)))
+ cpu_relax();
+}
+
+/*
+ * Conditionally acquire the specified rcu_data structure's
+ * ->nocb_bypass_lock.
+ */
+static bool rcu_nocb_bypass_trylock(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
+ return raw_spin_trylock(&rdp->nocb_bypass_lock);
+}
+
+/*
+ * Release the specified rcu_data structure's ->nocb_bypass_lock.
+ */
+static void rcu_nocb_bypass_unlock(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
+ raw_spin_unlock(&rdp->nocb_bypass_lock);
+}
+
+/*
+ * Acquire the specified rcu_data structure's ->nocb_lock, but only
+ * if it corresponds to a no-CBs CPU.
+ */
+static void rcu_nocb_lock(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
+ if (!rcu_segcblist_is_offloaded(&rdp->cblist))
+ return;
+ raw_spin_lock(&rdp->nocb_lock);
+}
+
+/*
+ * Release the specified rcu_data structure's ->nocb_lock, but only
+ * if it corresponds to a no-CBs CPU.
+ */
+static void rcu_nocb_unlock(struct rcu_data *rdp)
+{
+ if (rcu_segcblist_is_offloaded(&rdp->cblist)) {
+ lockdep_assert_irqs_disabled();
+ raw_spin_unlock(&rdp->nocb_lock);
+ }
+}
+
+/*
+ * Release the specified rcu_data structure's ->nocb_lock and restore
+ * interrupts, but only if it corresponds to a no-CBs CPU.
+ */
+static void rcu_nocb_unlock_irqrestore(struct rcu_data *rdp,
+ unsigned long flags)
+{
+ if (rcu_segcblist_is_offloaded(&rdp->cblist)) {
+ lockdep_assert_irqs_disabled();
+ raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
+ } else {
+ local_irq_restore(flags);
+ }
+}
+
+/* Lockdep check that ->cblist may be safely accessed. */
+static void rcu_lockdep_assert_cblist_protected(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
+ if (rcu_segcblist_is_offloaded(&rdp->cblist) &&
+ cpu_online(rdp->cpu))
+ lockdep_assert_held(&rdp->nocb_lock);
+}
+
+/*
* Wake up any no-CBs CPUs' kthreads that were waiting on the just-ended
* grace period.
*/
@@ -1543,440 +1635,514 @@ bool rcu_is_nocb_cpu(int cpu)
}
/*
- * Kick the leader kthread for this NOCB group. Caller holds ->nocb_lock
+ * Kick the GP kthread for this NOCB group. Caller holds ->nocb_lock
* and this function releases it.
*/
-static void __wake_nocb_leader(struct rcu_data *rdp, bool force,
- unsigned long flags)
+static void wake_nocb_gp(struct rcu_data *rdp, bool force,
+ unsigned long flags)
__releases(rdp->nocb_lock)
{
- struct rcu_data *rdp_leader = rdp->nocb_leader;
+ bool needwake = false;
+ struct rcu_data *rdp_gp = rdp->nocb_gp_rdp;
lockdep_assert_held(&rdp->nocb_lock);
- if (!READ_ONCE(rdp_leader->nocb_kthread)) {
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
+ if (!READ_ONCE(rdp_gp->nocb_gp_kthread)) {
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("AlreadyAwake"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
return;
}
- if (rdp_leader->nocb_leader_sleep || force) {
- /* Prior smp_mb__after_atomic() orders against prior enqueue. */
- WRITE_ONCE(rdp_leader->nocb_leader_sleep, false);
- del_timer(&rdp->nocb_timer);
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
- smp_mb(); /* ->nocb_leader_sleep before swake_up_one(). */
- swake_up_one(&rdp_leader->nocb_wq);
- } else {
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
+ del_timer(&rdp->nocb_timer);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ raw_spin_lock_irqsave(&rdp_gp->nocb_gp_lock, flags);
+ if (force || READ_ONCE(rdp_gp->nocb_gp_sleep)) {
+ WRITE_ONCE(rdp_gp->nocb_gp_sleep, false);
+ needwake = true;
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("DoWake"));
}
+ raw_spin_unlock_irqrestore(&rdp_gp->nocb_gp_lock, flags);
+ if (needwake)
+ wake_up_process(rdp_gp->nocb_gp_kthread);
}
/*
- * Kick the leader kthread for this NOCB group, but caller has not
- * acquired locks.
+ * Arrange to wake the GP kthread for this NOCB group at some future
+ * time when it is safe to do so.
*/
-static void wake_nocb_leader(struct rcu_data *rdp, bool force)
+static void wake_nocb_gp_defer(struct rcu_data *rdp, int waketype,
+ const char *reason)
{
- unsigned long flags;
+ if (rdp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT)
+ mod_timer(&rdp->nocb_timer, jiffies + 1);
+ if (rdp->nocb_defer_wakeup < waketype)
+ WRITE_ONCE(rdp->nocb_defer_wakeup, waketype);
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, reason);
+}
+
+/*
+ * Flush the ->nocb_bypass queue into ->cblist, enqueuing rhp if non-NULL.
+ * However, if there is a callback to be enqueued and if ->nocb_bypass
+ * proves to be initially empty, just return false because the no-CB GP
+ * kthread may need to be awakened in this case.
+ *
+ * Note that this function always returns true if rhp is NULL.
+ */
+static bool rcu_nocb_do_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ unsigned long j)
+{
+ struct rcu_cblist rcl;
- raw_spin_lock_irqsave(&rdp->nocb_lock, flags);
- __wake_nocb_leader(rdp, force, flags);
+ WARN_ON_ONCE(!rcu_segcblist_is_offloaded(&rdp->cblist));
+ rcu_lockdep_assert_cblist_protected(rdp);
+ lockdep_assert_held(&rdp->nocb_bypass_lock);
+ if (rhp && !rcu_cblist_n_cbs(&rdp->nocb_bypass)) {
+ raw_spin_unlock(&rdp->nocb_bypass_lock);
+ return false;
+ }
+ /* Note: ->cblist.len already accounts for ->nocb_bypass contents. */
+ if (rhp)
+ rcu_segcblist_inc_len(&rdp->cblist); /* Must precede enqueue. */
+ rcu_cblist_flush_enqueue(&rcl, &rdp->nocb_bypass, rhp);
+ rcu_segcblist_insert_pend_cbs(&rdp->cblist, &rcl);
+ WRITE_ONCE(rdp->nocb_bypass_first, j);
+ rcu_nocb_bypass_unlock(rdp);
+ return true;
}
/*
- * Arrange to wake the leader kthread for this NOCB group at some
- * future time when it is safe to do so.
+ * Flush the ->nocb_bypass queue into ->cblist, enqueuing rhp if non-NULL.
+ * However, if there is a callback to be enqueued and if ->nocb_bypass
+ * proves to be initially empty, just return false because the no-CB GP
+ * kthread may need to be awakened in this case.
+ *
+ * Note that this function always returns true if rhp is NULL.
*/
-static void wake_nocb_leader_defer(struct rcu_data *rdp, int waketype,
- const char *reason)
+static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ unsigned long j)
{
- unsigned long flags;
+ if (!rcu_segcblist_is_offloaded(&rdp->cblist))
+ return true;
+ rcu_lockdep_assert_cblist_protected(rdp);
+ rcu_nocb_bypass_lock(rdp);
+ return rcu_nocb_do_flush_bypass(rdp, rhp, j);
+}
- raw_spin_lock_irqsave(&rdp->nocb_lock, flags);
- if (rdp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT)
- mod_timer(&rdp->nocb_timer, jiffies + 1);
- WRITE_ONCE(rdp->nocb_defer_wakeup, waketype);
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, reason);
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
+/*
+ * If the ->nocb_bypass_lock is immediately available, flush the
+ * ->nocb_bypass queue into ->cblist.
+ */
+static void rcu_nocb_try_flush_bypass(struct rcu_data *rdp, unsigned long j)
+{
+ rcu_lockdep_assert_cblist_protected(rdp);
+ if (!rcu_segcblist_is_offloaded(&rdp->cblist) ||
+ !rcu_nocb_bypass_trylock(rdp))
+ return;
+ WARN_ON_ONCE(!rcu_nocb_do_flush_bypass(rdp, NULL, j));
}
-/* Does rcu_barrier need to queue an RCU callback on the specified CPU? */
-static bool rcu_nocb_cpu_needs_barrier(int cpu)
+/*
+ * See whether it is appropriate to use the ->nocb_bypass list in order
+ * to control contention on ->nocb_lock. A limited number of direct
+ * enqueues are permitted into ->cblist per jiffy. If ->nocb_bypass
+ * is non-empty, further callbacks must be placed into ->nocb_bypass,
+ * otherwise rcu_barrier() breaks. Use rcu_nocb_flush_bypass() to switch
+ * back to direct use of ->cblist. However, ->nocb_bypass should not be
+ * used if ->cblist is empty, because otherwise callbacks can be stranded
+ * on ->nocb_bypass because we cannot count on the current CPU ever again
+ * invoking call_rcu(). The general rule is that if ->nocb_bypass is
+ * non-empty, the corresponding no-CBs grace-period kthread must not be
+ * in an indefinite sleep state.
+ *
+ * Finally, it is not permitted to use the bypass during early boot,
+ * as doing so would confuse the auto-initialization code. Besides
+ * which, there is no point in worrying about lock contention while
+ * there is only one CPU in operation.
+ */
+static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ bool *was_alldone, unsigned long flags)
{
- struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
- unsigned long ret;
-#ifdef CONFIG_PROVE_RCU
- struct rcu_head *rhp;
-#endif /* #ifdef CONFIG_PROVE_RCU */
+ unsigned long c;
+ unsigned long cur_gp_seq;
+ unsigned long j = jiffies;
+ long ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass);
- /*
- * Check count of all no-CBs callbacks awaiting invocation.
- * There needs to be a barrier before this function is called,
- * but associated with a prior determination that no more
- * callbacks would be posted. In the worst case, the first
- * barrier in rcu_barrier() suffices (but the caller cannot
- * necessarily rely on this, not a substitute for the caller
- * getting the concurrency design right!). There must also be a
- * barrier between the following load and posting of a callback
- * (if a callback is in fact needed). This is associated with an
- * atomic_inc() in the caller.
- */
- ret = rcu_get_n_cbs_nocb_cpu(rdp);
-
-#ifdef CONFIG_PROVE_RCU
- rhp = READ_ONCE(rdp->nocb_head);
- if (!rhp)
- rhp = READ_ONCE(rdp->nocb_gp_head);
- if (!rhp)
- rhp = READ_ONCE(rdp->nocb_follower_head);
-
- /* Having no rcuo kthread but CBs after scheduler starts is bad! */
- if (!READ_ONCE(rdp->nocb_kthread) && rhp &&
- rcu_scheduler_fully_active) {
- /* RCU callback enqueued before CPU first came online??? */
- pr_err("RCU: Never-onlined no-CBs CPU %d has CB %p\n",
- cpu, rhp->func);
- WARN_ON_ONCE(1);
+ if (!rcu_segcblist_is_offloaded(&rdp->cblist)) {
+ *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist);
+ return false; /* Not offloaded, no bypassing. */
+ }
+ lockdep_assert_irqs_disabled();
+
+ // Don't use ->nocb_bypass during early boot.
+ if (rcu_scheduler_active != RCU_SCHEDULER_RUNNING) {
+ rcu_nocb_lock(rdp);
+ WARN_ON_ONCE(rcu_cblist_n_cbs(&rdp->nocb_bypass));
+ *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist);
+ return false;
+ }
+
+ // If we have advanced to a new jiffy, reset counts to allow
+ // moving back from ->nocb_bypass to ->cblist.
+ if (j == rdp->nocb_nobypass_last) {
+ c = rdp->nocb_nobypass_count + 1;
+ } else {
+ WRITE_ONCE(rdp->nocb_nobypass_last, j);
+ c = rdp->nocb_nobypass_count - nocb_nobypass_lim_per_jiffy;
+ if (ULONG_CMP_LT(rdp->nocb_nobypass_count,
+ nocb_nobypass_lim_per_jiffy))
+ c = 0;
+ else if (c > nocb_nobypass_lim_per_jiffy)
+ c = nocb_nobypass_lim_per_jiffy;
+ }
+ WRITE_ONCE(rdp->nocb_nobypass_count, c);
+
+ // If there hasn't yet been all that many ->cblist enqueues
+ // this jiffy, tell the caller to enqueue onto ->cblist. But flush
+ // ->nocb_bypass first.
+ if (rdp->nocb_nobypass_count < nocb_nobypass_lim_per_jiffy) {
+ rcu_nocb_lock(rdp);
+ *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist);
+ if (*was_alldone)
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("FirstQ"));
+ WARN_ON_ONCE(!rcu_nocb_flush_bypass(rdp, NULL, j));
+ WARN_ON_ONCE(rcu_cblist_n_cbs(&rdp->nocb_bypass));
+ return false; // Caller must enqueue the callback.
+ }
+
+ // If ->nocb_bypass has been used too long or is too full,
+ // flush ->nocb_bypass to ->cblist.
+ if ((ncbs && j != READ_ONCE(rdp->nocb_bypass_first)) ||
+ ncbs >= qhimark) {
+ rcu_nocb_lock(rdp);
+ if (!rcu_nocb_flush_bypass(rdp, rhp, j)) {
+ *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist);
+ if (*was_alldone)
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("FirstQ"));
+ WARN_ON_ONCE(rcu_cblist_n_cbs(&rdp->nocb_bypass));
+ return false; // Caller must enqueue the callback.
+ }
+ if (j != rdp->nocb_gp_adv_time &&
+ rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq) &&
+ rcu_seq_done(&rdp->mynode->gp_seq, cur_gp_seq)) {
+ rcu_advance_cbs_nowake(rdp->mynode, rdp);
+ rdp->nocb_gp_adv_time = j;
+ }
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ return true; // Callback already enqueued.
}
-#endif /* #ifdef CONFIG_PROVE_RCU */
- return !!ret;
+ // We need to use the bypass.
+ rcu_nocb_wait_contended(rdp);
+ rcu_nocb_bypass_lock(rdp);
+ ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass);
+ rcu_segcblist_inc_len(&rdp->cblist); /* Must precede enqueue. */
+ rcu_cblist_enqueue(&rdp->nocb_bypass, rhp);
+ if (!ncbs) {
+ WRITE_ONCE(rdp->nocb_bypass_first, j);
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("FirstBQ"));
+ }
+ rcu_nocb_bypass_unlock(rdp);
+ smp_mb(); /* Order enqueue before wake. */
+ if (ncbs) {
+ local_irq_restore(flags);
+ } else {
+ // No-CBs GP kthread might be indefinitely asleep, if so, wake.
+ rcu_nocb_lock(rdp); // Rare during call_rcu() flood.
+ if (!rcu_segcblist_pend_cbs(&rdp->cblist)) {
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("FirstBQwake"));
+ __call_rcu_nocb_wake(rdp, true, flags);
+ } else {
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("FirstBQnoWake"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ }
+ }
+ return true; // Callback already enqueued.
}
/*
- * Enqueue the specified string of rcu_head structures onto the specified
- * CPU's no-CBs lists. The CPU is specified by rdp, the head of the
- * string by rhp, and the tail of the string by rhtp. The non-lazy/lazy
- * counts are supplied by rhcount and rhcount_lazy.
+ * Awaken the no-CBs grace-period kthead if needed, either due to it
+ * legitimately being asleep or due to overload conditions.
*
* If warranted, also wake up the kthread servicing this CPUs queues.
*/
-static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
- struct rcu_head *rhp,
- struct rcu_head **rhtp,
- int rhcount, int rhcount_lazy,
- unsigned long flags)
+static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_alldone,
+ unsigned long flags)
+ __releases(rdp->nocb_lock)
{
- int len;
- struct rcu_head **old_rhpp;
+ unsigned long cur_gp_seq;
+ unsigned long j;
+ long len;
struct task_struct *t;
- /* Enqueue the callback on the nocb list and update counts. */
- atomic_long_add(rhcount, &rdp->nocb_q_count);
- /* rcu_barrier() relies on ->nocb_q_count add before xchg. */
- old_rhpp = xchg(&rdp->nocb_tail, rhtp);
- WRITE_ONCE(*old_rhpp, rhp);
- atomic_long_add(rhcount_lazy, &rdp->nocb_q_count_lazy);
- smp_mb__after_atomic(); /* Store *old_rhpp before _wake test. */
-
- /* If we are not being polled and there is a kthread, awaken it ... */
- t = READ_ONCE(rdp->nocb_kthread);
+ // If we are being polled or there is no kthread, just leave.
+ t = READ_ONCE(rdp->nocb_gp_kthread);
if (rcu_nocb_poll || !t) {
trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
TPS("WakeNotPoll"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
return;
}
- len = rcu_get_n_cbs_nocb_cpu(rdp);
- if (old_rhpp == &rdp->nocb_head) {
+ // Need to actually to a wakeup.
+ len = rcu_segcblist_n_cbs(&rdp->cblist);
+ if (was_alldone) {
+ rdp->qlen_last_fqs_check = len;
if (!irqs_disabled_flags(flags)) {
/* ... if queue was empty ... */
- wake_nocb_leader(rdp, false);
+ wake_nocb_gp(rdp, false, flags);
trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
TPS("WakeEmpty"));
} else {
- wake_nocb_leader_defer(rdp, RCU_NOCB_WAKE,
- TPS("WakeEmptyIsDeferred"));
+ wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE,
+ TPS("WakeEmptyIsDeferred"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
}
- rdp->qlen_last_fqs_check = 0;
} else if (len > rdp->qlen_last_fqs_check + qhimark) {
/* ... or if many callbacks queued. */
- if (!irqs_disabled_flags(flags)) {
- wake_nocb_leader(rdp, true);
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
- TPS("WakeOvf"));
- } else {
- wake_nocb_leader_defer(rdp, RCU_NOCB_WAKE_FORCE,
- TPS("WakeOvfIsDeferred"));
+ rdp->qlen_last_fqs_check = len;
+ j = jiffies;
+ if (j != rdp->nocb_gp_adv_time &&
+ rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq) &&
+ rcu_seq_done(&rdp->mynode->gp_seq, cur_gp_seq)) {
+ rcu_advance_cbs_nowake(rdp->mynode, rdp);
+ rdp->nocb_gp_adv_time = j;
}
- rdp->qlen_last_fqs_check = LONG_MAX / 2;
+ smp_mb(); /* Enqueue before timer_pending(). */
+ if ((rdp->nocb_cb_sleep ||
+ !rcu_segcblist_ready_cbs(&rdp->cblist)) &&
+ !timer_pending(&rdp->nocb_bypass_timer))
+ wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE_FORCE,
+ TPS("WakeOvfIsDeferred"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
} else {
trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WakeNot"));
+ rcu_nocb_unlock_irqrestore(rdp, flags);
}
return;
}
-/*
- * This is a helper for __call_rcu(), which invokes this when the normal
- * callback queue is inoperable. If this is not a no-CBs CPU, this
- * function returns failure back to __call_rcu(), which can complain
- * appropriately.
- *
- * Otherwise, this function queues the callback where the corresponding
- * "rcuo" kthread can find it.
- */
-static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
- bool lazy, unsigned long flags)
+/* Wake up the no-CBs GP kthread to flush ->nocb_bypass. */
+static void do_nocb_bypass_wakeup_timer(struct timer_list *t)
{
+ unsigned long flags;
+ struct rcu_data *rdp = from_timer(rdp, t, nocb_bypass_timer);
- if (!rcu_is_nocb_cpu(rdp->cpu))
- return false;
- __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy, flags);
- if (__is_kfree_rcu_offset((unsigned long)rhp->func))
- trace_rcu_kfree_callback(rcu_state.name, rhp,
- (unsigned long)rhp->func,
- -atomic_long_read(&rdp->nocb_q_count_lazy),
- -rcu_get_n_cbs_nocb_cpu(rdp));
- else
- trace_rcu_callback(rcu_state.name, rhp,
- -atomic_long_read(&rdp->nocb_q_count_lazy),
- -rcu_get_n_cbs_nocb_cpu(rdp));
-
- /*
- * If called from an extended quiescent state with interrupts
- * disabled, invoke the RCU core in order to allow the idle-entry
- * deferred-wakeup check to function.
- */
- if (irqs_disabled_flags(flags) &&
- !rcu_is_watching() &&
- cpu_online(smp_processor_id()))
- invoke_rcu_core();
-
- return true;
-}
-
-/*
- * Adopt orphaned callbacks on a no-CBs CPU, or return 0 if this is
- * not a no-CBs CPU.
- */
-static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
- struct rcu_data *rdp,
- unsigned long flags)
-{
- lockdep_assert_irqs_disabled();
- if (!rcu_is_nocb_cpu(smp_processor_id()))
- return false; /* Not NOCBs CPU, caller must migrate CBs. */
- __call_rcu_nocb_enqueue(my_rdp, rcu_segcblist_head(&rdp->cblist),
- rcu_segcblist_tail(&rdp->cblist),
- rcu_segcblist_n_cbs(&rdp->cblist),
- rcu_segcblist_n_lazy_cbs(&rdp->cblist), flags);
- rcu_segcblist_init(&rdp->cblist);
- rcu_segcblist_disable(&rdp->cblist);
- return true;
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("Timer"));
+ rcu_nocb_lock_irqsave(rdp, flags);
+ smp_mb__after_spinlock(); /* Timer expire before wakeup. */
+ __call_rcu_nocb_wake(rdp, true, flags);
}
/*
- * If necessary, kick off a new grace period, and either way wait
- * for a subsequent grace period to complete.
+ * No-CBs GP kthreads come here to wait for additional callbacks to show up
+ * or for grace periods to end.
*/
-static void rcu_nocb_wait_gp(struct rcu_data *rdp)
+static void nocb_gp_wait(struct rcu_data *my_rdp)
{
- unsigned long c;
- bool d;
+ bool bypass = false;
+ long bypass_ncbs;
+ int __maybe_unused cpu = my_rdp->cpu;
+ unsigned long cur_gp_seq;
unsigned long flags;
+ bool gotcbs;
+ unsigned long j = jiffies;
+ bool needwait_gp = false; // This prevents actual uninitialized use.
bool needwake;
- struct rcu_node *rnp = rdp->mynode;
+ bool needwake_gp;
+ struct rcu_data *rdp;
+ struct rcu_node *rnp;
+ unsigned long wait_gp_seq = 0; // Suppress "use uninitialized" warning.
- local_irq_save(flags);
- c = rcu_seq_snap(&rcu_state.gp_seq);
- if (!rdp->gpwrap && ULONG_CMP_GE(rdp->gp_seq_needed, c)) {
- local_irq_restore(flags);
- } else {
- raw_spin_lock_rcu_node(rnp); /* irqs already disabled. */
- needwake = rcu_start_this_gp(rnp, rdp, c);
- raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
- if (needwake)
+ /*
+ * Each pass through the following loop checks for CBs and for the
+ * nearest grace period (if any) to wait for next. The CB kthreads
+ * and the global grace-period kthread are awakened if needed.
+ */
+ for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_cb_rdp) {
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("Check"));
+ rcu_nocb_lock_irqsave(rdp, flags);
+ bypass_ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass);
+ if (bypass_ncbs &&
+ (time_after(j, READ_ONCE(rdp->nocb_bypass_first) + 1) ||
+ bypass_ncbs > 2 * qhimark)) {
+ // Bypass full or old, so flush it.
+ (void)rcu_nocb_try_flush_bypass(rdp, j);
+ bypass_ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass);
+ } else if (!bypass_ncbs && rcu_segcblist_empty(&rdp->cblist)) {
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ continue; /* No callbacks here, try next. */
+ }
+ if (bypass_ncbs) {
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("Bypass"));
+ bypass = true;
+ }
+ rnp = rdp->mynode;
+ if (bypass) { // Avoid race with first bypass CB.
+ WRITE_ONCE(my_rdp->nocb_defer_wakeup,
+ RCU_NOCB_WAKE_NOT);
+ del_timer(&my_rdp->nocb_timer);
+ }
+ // Advance callbacks if helpful and low contention.
+ needwake_gp = false;
+ if (!rcu_segcblist_restempty(&rdp->cblist,
+ RCU_NEXT_READY_TAIL) ||
+ (rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq) &&
+ rcu_seq_done(&rnp->gp_seq, cur_gp_seq))) {
+ raw_spin_lock_rcu_node(rnp); /* irqs disabled. */
+ needwake_gp = rcu_advance_cbs(rnp, rdp);
+ raw_spin_unlock_rcu_node(rnp); /* irqs disabled. */
+ }
+ // Need to wait on some grace period?
+ WARN_ON_ONCE(!rcu_segcblist_restempty(&rdp->cblist,
+ RCU_NEXT_READY_TAIL));
+ if (rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq)) {
+ if (!needwait_gp ||
+ ULONG_CMP_LT(cur_gp_seq, wait_gp_seq))
+ wait_gp_seq = cur_gp_seq;
+ needwait_gp = true;
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
+ TPS("NeedWaitGP"));
+ }
+ if (rcu_segcblist_ready_cbs(&rdp->cblist)) {
+ needwake = rdp->nocb_cb_sleep;
+ WRITE_ONCE(rdp->nocb_cb_sleep, false);
+ smp_mb(); /* CB invocation -after- GP end. */
+ } else {
+ needwake = false;
+ }
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ if (needwake) {
+ swake_up_one(&rdp->nocb_cb_wq);
+ gotcbs = true;
+ }
+ if (needwake_gp)
rcu_gp_kthread_wake();
}
- /*
- * Wait for the grace period. Do so interruptibly to avoid messing
- * up the load average.
- */
- trace_rcu_this_gp(rnp, rdp, c, TPS("StartWait"));
- for (;;) {
+ my_rdp->nocb_gp_bypass = bypass;
+ my_rdp->nocb_gp_gp = needwait_gp;
+ my_rdp->nocb_gp_seq = needwait_gp ? wait_gp_seq : 0;
+ if (bypass && !rcu_nocb_poll) {
+ // At least one child with non-empty ->nocb_bypass, so set
+ // timer in order to avoid stranding its callbacks.
+ raw_spin_lock_irqsave(&my_rdp->nocb_gp_lock, flags);
+ mod_timer(&my_rdp->nocb_bypass_timer, j + 2);
+ raw_spin_unlock_irqrestore(&my_rdp->nocb_gp_lock, flags);
+ }
+ if (rcu_nocb_poll) {
+ /* Polling, so trace if first poll in the series. */
+ if (gotcbs)
+ trace_rcu_nocb_wake(rcu_state.name, cpu, TPS("Poll"));
+ schedule_timeout_interruptible(1);
+ } else if (!needwait_gp) {
+ /* Wait for callbacks to appear. */
+ trace_rcu_nocb_wake(rcu_state.name, cpu, TPS("Sleep"));
+ swait_event_interruptible_exclusive(my_rdp->nocb_gp_wq,
+ !READ_ONCE(my_rdp->nocb_gp_sleep));
+ trace_rcu_nocb_wake(rcu_state.name, cpu, TPS("EndSleep"));
+ } else {
+ rnp = my_rdp->mynode;
+ trace_rcu_this_gp(rnp, my_rdp, wait_gp_seq, TPS("StartWait"));
swait_event_interruptible_exclusive(
- rnp->nocb_gp_wq[rcu_seq_ctr(c) & 0x1],
- (d = rcu_seq_done(&rnp->gp_seq, c)));
- if (likely(d))
- break;
- WARN_ON(signal_pending(current));
- trace_rcu_this_gp(rnp, rdp, c, TPS("ResumeWait"));
+ rnp->nocb_gp_wq[rcu_seq_ctr(wait_gp_seq) & 0x1],
+ rcu_seq_done(&rnp->gp_seq, wait_gp_seq) ||
+ !READ_ONCE(my_rdp->nocb_gp_sleep));
+ trace_rcu_this_gp(rnp, my_rdp, wait_gp_seq, TPS("EndWait"));
}
- trace_rcu_this_gp(rnp, rdp, c, TPS("EndWait"));
- smp_mb(); /* Ensure that CB invocation happens after GP end. */
+ if (!rcu_nocb_poll) {
+ raw_spin_lock_irqsave(&my_rdp->nocb_gp_lock, flags);
+ if (bypass)
+ del_timer(&my_rdp->nocb_bypass_timer);
+ WRITE_ONCE(my_rdp->nocb_gp_sleep, true);
+ raw_spin_unlock_irqrestore(&my_rdp->nocb_gp_lock, flags);
+ }
+ my_rdp->nocb_gp_seq = -1;
+ WARN_ON(signal_pending(current));
}
/*
- * Leaders come here to wait for additional callbacks to show up.
- * This function does not return until callbacks appear.
+ * No-CBs grace-period-wait kthread. There is one of these per group
+ * of CPUs, but only once at least one CPU in that group has come online
+ * at least once since boot. This kthread checks for newly posted
+ * callbacks from any of the CPUs it is responsible for, waits for a
+ * grace period, then awakens all of the rcu_nocb_cb_kthread() instances
+ * that then have callback-invocation work to do.
*/
-static void nocb_leader_wait(struct rcu_data *my_rdp)
+static int rcu_nocb_gp_kthread(void *arg)
{
- bool firsttime = true;
- unsigned long flags;
- bool gotcbs;
- struct rcu_data *rdp;
- struct rcu_head **tail;
-
-wait_again:
-
- /* Wait for callbacks to appear. */
- if (!rcu_nocb_poll) {
- trace_rcu_nocb_wake(rcu_state.name, my_rdp->cpu, TPS("Sleep"));
- swait_event_interruptible_exclusive(my_rdp->nocb_wq,
- !READ_ONCE(my_rdp->nocb_leader_sleep));
- raw_spin_lock_irqsave(&my_rdp->nocb_lock, flags);
- my_rdp->nocb_leader_sleep = true;
- WRITE_ONCE(my_rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT);
- del_timer(&my_rdp->nocb_timer);
- raw_spin_unlock_irqrestore(&my_rdp->nocb_lock, flags);
- } else if (firsttime) {
- firsttime = false; /* Don't drown trace log with "Poll"! */
- trace_rcu_nocb_wake(rcu_state.name, my_rdp->cpu, TPS("Poll"));
- }
-
- /*
- * Each pass through the following loop checks a follower for CBs.
- * We are our own first follower. Any CBs found are moved to
- * nocb_gp_head, where they await a grace period.
- */
- gotcbs = false;
- smp_mb(); /* wakeup and _sleep before ->nocb_head reads. */
- for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) {
- rdp->nocb_gp_head = READ_ONCE(rdp->nocb_head);
- if (!rdp->nocb_gp_head)
- continue; /* No CBs here, try next follower. */
-
- /* Move callbacks to wait-for-GP list, which is empty. */
- WRITE_ONCE(rdp->nocb_head, NULL);
- rdp->nocb_gp_tail = xchg(&rdp->nocb_tail, &rdp->nocb_head);
- gotcbs = true;
- }
-
- /* No callbacks? Sleep a bit if polling, and go retry. */
- if (unlikely(!gotcbs)) {
- WARN_ON(signal_pending(current));
- if (rcu_nocb_poll) {
- schedule_timeout_interruptible(1);
- } else {
- trace_rcu_nocb_wake(rcu_state.name, my_rdp->cpu,
- TPS("WokeEmpty"));
- }
- goto wait_again;
- }
+ struct rcu_data *rdp = arg;
- /* Wait for one grace period. */
- rcu_nocb_wait_gp(my_rdp);
-
- /* Each pass through the following loop wakes a follower, if needed. */
- for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) {
- if (!rcu_nocb_poll &&
- READ_ONCE(rdp->nocb_head) &&
- READ_ONCE(my_rdp->nocb_leader_sleep)) {
- raw_spin_lock_irqsave(&my_rdp->nocb_lock, flags);
- my_rdp->nocb_leader_sleep = false;/* No need to sleep.*/
- raw_spin_unlock_irqrestore(&my_rdp->nocb_lock, flags);
- }
- if (!rdp->nocb_gp_head)
- continue; /* No CBs, so no need to wake follower. */
-
- /* Append callbacks to follower's "done" list. */
- raw_spin_lock_irqsave(&rdp->nocb_lock, flags);
- tail = rdp->nocb_follower_tail;
- rdp->nocb_follower_tail = rdp->nocb_gp_tail;
- *tail = rdp->nocb_gp_head;
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
- if (rdp != my_rdp && tail == &rdp->nocb_follower_head) {
- /* List was empty, so wake up the follower. */
- swake_up_one(&rdp->nocb_wq);
- }
+ for (;;) {
+ WRITE_ONCE(rdp->nocb_gp_loops, rdp->nocb_gp_loops + 1);
+ nocb_gp_wait(rdp);
+ cond_resched_tasks_rcu_qs();
}
-
- /* If we (the leader) don't have CBs, go wait some more. */
- if (!my_rdp->nocb_follower_head)
- goto wait_again;
+ return 0;
}
/*
- * Followers come here to wait for additional callbacks to show up.
- * This function does not return until callbacks appear.
+ * Invoke any ready callbacks from the corresponding no-CBs CPU,
+ * then, if there are no more, wait for more to appear.
*/
-static void nocb_follower_wait(struct rcu_data *rdp)
+static void nocb_cb_wait(struct rcu_data *rdp)
{
- for (;;) {
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("FollowerSleep"));
- swait_event_interruptible_exclusive(rdp->nocb_wq,
- READ_ONCE(rdp->nocb_follower_head));
- if (smp_load_acquire(&rdp->nocb_follower_head)) {
- /* ^^^ Ensure CB invocation follows _head test. */
- return;
- }
- WARN_ON(signal_pending(current));
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeEmpty"));
+ unsigned long cur_gp_seq;
+ unsigned long flags;
+ bool needwake_gp = false;
+ struct rcu_node *rnp = rdp->mynode;
+
+ local_irq_save(flags);
+ rcu_momentary_dyntick_idle();
+ local_irq_restore(flags);
+ local_bh_disable();
+ rcu_do_batch(rdp);
+ local_bh_enable();
+ lockdep_assert_irqs_enabled();
+ rcu_nocb_lock_irqsave(rdp, flags);
+ if (rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq) &&
+ rcu_seq_done(&rnp->gp_seq, cur_gp_seq) &&
+ raw_spin_trylock_rcu_node(rnp)) { /* irqs already disabled. */
+ needwake_gp = rcu_advance_cbs(rdp->mynode, rdp);
+ raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
+ }
+ if (rcu_segcblist_ready_cbs(&rdp->cblist)) {
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ if (needwake_gp)
+ rcu_gp_kthread_wake();
+ return;
+ }
+
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("CBSleep"));
+ WRITE_ONCE(rdp->nocb_cb_sleep, true);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ if (needwake_gp)
+ rcu_gp_kthread_wake();
+ swait_event_interruptible_exclusive(rdp->nocb_cb_wq,
+ !READ_ONCE(rdp->nocb_cb_sleep));
+ if (!smp_load_acquire(&rdp->nocb_cb_sleep)) { /* VVV */
+ /* ^^^ Ensure CB invocation follows _sleep test. */
+ return;
}
+ WARN_ON(signal_pending(current));
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeEmpty"));
}
/*
- * Per-rcu_data kthread, but only for no-CBs CPUs. Each kthread invokes
- * callbacks queued by the corresponding no-CBs CPU, however, there is
- * an optional leader-follower relationship so that the grace-period
- * kthreads don't have to do quite so many wakeups.
+ * Per-rcu_data kthread, but only for no-CBs CPUs. Repeatedly invoke
+ * nocb_cb_wait() to do the dirty work.
*/
-static int rcu_nocb_kthread(void *arg)
+static int rcu_nocb_cb_kthread(void *arg)
{
- int c, cl;
- unsigned long flags;
- struct rcu_head *list;
- struct rcu_head *next;
- struct rcu_head **tail;
struct rcu_data *rdp = arg;
- /* Each pass through this loop invokes one batch of callbacks */
+ // Each pass through this loop does one callback batch, and,
+ // if there are no more ready callbacks, waits for them.
for (;;) {
- /* Wait for callbacks. */
- if (rdp->nocb_leader == rdp)
- nocb_leader_wait(rdp);
- else
- nocb_follower_wait(rdp);
-
- /* Pull the ready-to-invoke callbacks onto local list. */
- raw_spin_lock_irqsave(&rdp->nocb_lock, flags);
- list = rdp->nocb_follower_head;
- rdp->nocb_follower_head = NULL;
- tail = rdp->nocb_follower_tail;
- rdp->nocb_follower_tail = &rdp->nocb_follower_head;
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
- if (WARN_ON_ONCE(!list))
- continue;
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeNonEmpty"));
-
- /* Each pass through the following loop invokes a callback. */
- trace_rcu_batch_start(rcu_state.name,
- atomic_long_read(&rdp->nocb_q_count_lazy),
- rcu_get_n_cbs_nocb_cpu(rdp), -1);
- c = cl = 0;
- while (list) {
- next = list->next;
- /* Wait for enqueuing to complete, if needed. */
- while (next == NULL && &list->next != tail) {
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
- TPS("WaitQueue"));
- schedule_timeout_interruptible(1);
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu,
- TPS("WokeQueue"));
- next = list->next;
- }
- debug_rcu_head_unqueue(list);
- local_bh_disable();
- if (__rcu_reclaim(rcu_state.name, list))
- cl++;
- c++;
- local_bh_enable();
- cond_resched_tasks_rcu_qs();
- list = next;
- }
- trace_rcu_batch_end(rcu_state.name, c, !!list, 0, 0, 1);
- smp_mb__before_atomic(); /* _add after CB invocation. */
- atomic_long_add(-c, &rdp->nocb_q_count);
- atomic_long_add(-cl, &rdp->nocb_q_count_lazy);
+ nocb_cb_wait(rdp);
+ cond_resched_tasks_rcu_qs();
}
return 0;
}
@@ -1993,14 +2159,14 @@ static void do_nocb_deferred_wakeup_common(struct rcu_data *rdp)
unsigned long flags;
int ndw;
- raw_spin_lock_irqsave(&rdp->nocb_lock, flags);
+ rcu_nocb_lock_irqsave(rdp, flags);
if (!rcu_nocb_need_deferred_wakeup(rdp)) {
- raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
return;
}
ndw = READ_ONCE(rdp->nocb_defer_wakeup);
WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT);
- __wake_nocb_leader(rdp, ndw == RCU_NOCB_WAKE_FORCE, flags);
+ wake_nocb_gp(rdp, ndw == RCU_NOCB_WAKE_FORCE, flags);
trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("DeferredWake"));
}
@@ -2027,6 +2193,7 @@ void __init rcu_init_nohz(void)
{
int cpu;
bool need_rcu_nocb_mask = false;
+ struct rcu_data *rdp;
#if defined(CONFIG_NO_HZ_FULL)
if (tick_nohz_full_running && cpumask_weight(tick_nohz_full_mask))
@@ -2060,67 +2227,63 @@ void __init rcu_init_nohz(void)
if (rcu_nocb_poll)
pr_info("\tPoll for callbacks from no-CBs CPUs.\n");
- for_each_cpu(cpu, rcu_nocb_mask)
- init_nocb_callback_list(per_cpu_ptr(&rcu_data, cpu));
+ for_each_cpu(cpu, rcu_nocb_mask) {
+ rdp = per_cpu_ptr(&rcu_data, cpu);
+ if (rcu_segcblist_empty(&rdp->cblist))
+ rcu_segcblist_init(&rdp->cblist);
+ rcu_segcblist_offload(&rdp->cblist);
+ }
rcu_organize_nocb_kthreads();
}
/* Initialize per-rcu_data variables for no-CBs CPUs. */
static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
{
- rdp->nocb_tail = &rdp->nocb_head;
- init_swait_queue_head(&rdp->nocb_wq);
- rdp->nocb_follower_tail = &rdp->nocb_follower_head;
+ init_swait_queue_head(&rdp->nocb_cb_wq);
+ init_swait_queue_head(&rdp->nocb_gp_wq);
raw_spin_lock_init(&rdp->nocb_lock);
+ raw_spin_lock_init(&rdp->nocb_bypass_lock);
+ raw_spin_lock_init(&rdp->nocb_gp_lock);
timer_setup(&rdp->nocb_timer, do_nocb_deferred_wakeup_timer, 0);
+ timer_setup(&rdp->nocb_bypass_timer, do_nocb_bypass_wakeup_timer, 0);
+ rcu_cblist_init(&rdp->nocb_bypass);
}
/*
* If the specified CPU is a no-CBs CPU that does not already have its
- * rcuo kthread, spawn it. If the CPUs are brought online out of order,
- * this can require re-organizing the leader-follower relationships.
+ * rcuo CB kthread, spawn it. Additionally, if the rcuo GP kthread
+ * for this CPU's group has not yet been created, spawn it as well.
*/
static void rcu_spawn_one_nocb_kthread(int cpu)
{
- struct rcu_data *rdp;
- struct rcu_data *rdp_last;
- struct rcu_data *rdp_old_leader;
- struct rcu_data *rdp_spawn = per_cpu_ptr(&rcu_data, cpu);
+ struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+ struct rcu_data *rdp_gp;
struct task_struct *t;
/*
* If this isn't a no-CBs CPU or if it already has an rcuo kthread,
* then nothing to do.
*/
- if (!rcu_is_nocb_cpu(cpu) || rdp_spawn->nocb_kthread)
+ if (!rcu_is_nocb_cpu(cpu) || rdp->nocb_cb_kthread)
return;
- /* If we didn't spawn the leader first, reorganize! */
- rdp_old_leader = rdp_spawn->nocb_leader;
- if (rdp_old_leader != rdp_spawn && !rdp_old_leader->nocb_kthread) {
- rdp_last = NULL;
- rdp = rdp_old_leader;
- do {
- rdp->nocb_leader = rdp_spawn;
- if (rdp_last && rdp != rdp_spawn)
- rdp_last->nocb_next_follower = rdp;
- if (rdp == rdp_spawn) {
- rdp = rdp->nocb_next_follower;
- } else {
- rdp_last = rdp;
- rdp = rdp->nocb_next_follower;
- rdp_last->nocb_next_follower = NULL;
- }
- } while (rdp);
- rdp_spawn->nocb_next_follower = rdp_old_leader;
+ /* If we didn't spawn the GP kthread first, reorganize! */
+ rdp_gp = rdp->nocb_gp_rdp;
+ if (!rdp_gp->nocb_gp_kthread) {
+ t = kthread_run(rcu_nocb_gp_kthread, rdp_gp,
+ "rcuog/%d", rdp_gp->cpu);
+ if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo GP kthread, OOM is now expected behavior\n", __func__))
+ return;
+ WRITE_ONCE(rdp_gp->nocb_gp_kthread, t);
}
/* Spawn the kthread for this CPU. */
- t = kthread_run(rcu_nocb_kthread, rdp_spawn,
+ t = kthread_run(rcu_nocb_cb_kthread, rdp,
"rcuo%c/%d", rcu_state.abbr, cpu);
- if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo kthread, OOM is now expected behavior\n", __func__))
+ if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo CB kthread, OOM is now expected behavior\n", __func__))
return;
- WRITE_ONCE(rdp_spawn->nocb_kthread, t);
+ WRITE_ONCE(rdp->nocb_cb_kthread, t);
+ WRITE_ONCE(rdp->nocb_gp_kthread, rdp_gp->nocb_gp_kthread);
}
/*
@@ -2147,27 +2310,28 @@ static void __init rcu_spawn_nocb_kthreads(void)
rcu_spawn_cpu_nocb_kthread(cpu);
}
-/* How many follower CPU IDs per leader? Default of -1 for sqrt(nr_cpu_ids). */
-static int rcu_nocb_leader_stride = -1;
-module_param(rcu_nocb_leader_stride, int, 0444);
+/* How many CB CPU IDs per GP kthread? Default of -1 for sqrt(nr_cpu_ids). */
+static int rcu_nocb_gp_stride = -1;
+module_param(rcu_nocb_gp_stride, int, 0444);
/*
- * Initialize leader-follower relationships for all no-CBs CPU.
+ * Initialize GP-CB relationships for all no-CBs CPU.
*/
static void __init rcu_organize_nocb_kthreads(void)
{
int cpu;
- int ls = rcu_nocb_leader_stride;
- int nl = 0; /* Next leader. */
+ bool firsttime = true;
+ int ls = rcu_nocb_gp_stride;
+ int nl = 0; /* Next GP kthread. */
struct rcu_data *rdp;
- struct rcu_data *rdp_leader = NULL; /* Suppress misguided gcc warn. */
+ struct rcu_data *rdp_gp = NULL; /* Suppress misguided gcc warn. */
struct rcu_data *rdp_prev = NULL;
if (!cpumask_available(rcu_nocb_mask))
return;
if (ls == -1) {
- ls = int_sqrt(nr_cpu_ids);
- rcu_nocb_leader_stride = ls;
+ ls = nr_cpu_ids / int_sqrt(nr_cpu_ids);
+ rcu_nocb_gp_stride = ls;
}
/*
@@ -2178,39 +2342,24 @@ static void __init rcu_organize_nocb_kthreads(void)
for_each_cpu(cpu, rcu_nocb_mask) {
rdp = per_cpu_ptr(&rcu_data, cpu);
if (rdp->cpu >= nl) {
- /* New leader, set up for followers & next leader. */
+ /* New GP kthread, set up for CBs & next GP. */
nl = DIV_ROUND_UP(rdp->cpu + 1, ls) * ls;
- rdp->nocb_leader = rdp;
- rdp_leader = rdp;
+ rdp->nocb_gp_rdp = rdp;
+ rdp_gp = rdp;
+ if (!firsttime && dump_tree)
+ pr_cont("\n");
+ firsttime = false;
+ pr_alert("%s: No-CB GP kthread CPU %d:", __func__, cpu);
} else {
- /* Another follower, link to previous leader. */
- rdp->nocb_leader = rdp_leader;
- rdp_prev->nocb_next_follower = rdp;
+ /* Another CB kthread, link to previous GP kthread. */
+ rdp->nocb_gp_rdp = rdp_gp;
+ rdp_prev->nocb_next_cb_rdp = rdp;
+ pr_alert(" %d", cpu);
}
rdp_prev = rdp;
}
}
-/* Prevent __call_rcu() from enqueuing callbacks on no-CBs CPUs */
-static bool init_nocb_callback_list(struct rcu_data *rdp)
-{
- if (!rcu_is_nocb_cpu(rdp->cpu))
- return false;
-
- /* If there are early-boot callbacks, move them to nocb lists. */
- if (!rcu_segcblist_empty(&rdp->cblist)) {
- rdp->nocb_head = rcu_segcblist_head(&rdp->cblist);
- rdp->nocb_tail = rcu_segcblist_tail(&rdp->cblist);
- atomic_long_set(&rdp->nocb_q_count,
- rcu_segcblist_n_cbs(&rdp->cblist));
- atomic_long_set(&rdp->nocb_q_count_lazy,
- rcu_segcblist_n_lazy_cbs(&rdp->cblist));
- rcu_segcblist_init(&rdp->cblist);
- }
- rcu_segcblist_disable(&rdp->cblist);
- return true;
-}
-
/*
* Bind the current task to the offloaded CPUs. If there are no offloaded
* CPUs, leave the task unbound. Splat if the bind attempt fails.
@@ -2223,20 +2372,101 @@ void rcu_bind_current_to_nocb(void)
EXPORT_SYMBOL_GPL(rcu_bind_current_to_nocb);
/*
- * Return the number of RCU callbacks still queued from the specified
- * CPU, which must be a nocbs CPU.
+ * Dump out nocb grace-period kthread state for the specified rcu_data
+ * structure.
*/
-static unsigned long rcu_get_n_cbs_nocb_cpu(struct rcu_data *rdp)
+static void show_rcu_nocb_gp_state(struct rcu_data *rdp)
{
- return atomic_long_read(&rdp->nocb_q_count);
+ struct rcu_node *rnp = rdp->mynode;
+
+ pr_info("nocb GP %d %c%c%c%c%c%c %c[%c%c] %c%c:%ld rnp %d:%d %lu\n",
+ rdp->cpu,
+ "kK"[!!rdp->nocb_gp_kthread],
+ "lL"[raw_spin_is_locked(&rdp->nocb_gp_lock)],
+ "dD"[!!rdp->nocb_defer_wakeup],
+ "tT"[timer_pending(&rdp->nocb_timer)],
+ "bB"[timer_pending(&rdp->nocb_bypass_timer)],
+ "sS"[!!rdp->nocb_gp_sleep],
+ ".W"[swait_active(&rdp->nocb_gp_wq)],
+ ".W"[swait_active(&rnp->nocb_gp_wq[0])],
+ ".W"[swait_active(&rnp->nocb_gp_wq[1])],
+ ".B"[!!rdp->nocb_gp_bypass],
+ ".G"[!!rdp->nocb_gp_gp],
+ (long)rdp->nocb_gp_seq,
+ rnp->grplo, rnp->grphi, READ_ONCE(rdp->nocb_gp_loops));
+}
+
+/* Dump out nocb kthread state for the specified rcu_data structure. */
+static void show_rcu_nocb_state(struct rcu_data *rdp)
+{
+ struct rcu_segcblist *rsclp = &rdp->cblist;
+ bool waslocked;
+ bool wastimer;
+ bool wassleep;
+
+ if (rdp->nocb_gp_rdp == rdp)
+ show_rcu_nocb_gp_state(rdp);
+
+ pr_info(" CB %d->%d %c%c%c%c%c%c F%ld L%ld C%d %c%c%c%c%c q%ld\n",
+ rdp->cpu, rdp->nocb_gp_rdp->cpu,
+ "kK"[!!rdp->nocb_cb_kthread],
+ "bB"[raw_spin_is_locked(&rdp->nocb_bypass_lock)],
+ "cC"[!!atomic_read(&rdp->nocb_lock_contended)],
+ "lL"[raw_spin_is_locked(&rdp->nocb_lock)],
+ "sS"[!!rdp->nocb_cb_sleep],
+ ".W"[swait_active(&rdp->nocb_cb_wq)],
+ jiffies - rdp->nocb_bypass_first,
+ jiffies - rdp->nocb_nobypass_last,
+ rdp->nocb_nobypass_count,
+ ".D"[rcu_segcblist_ready_cbs(rsclp)],
+ ".W"[!rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL)],
+ ".R"[!rcu_segcblist_restempty(rsclp, RCU_WAIT_TAIL)],
+ ".N"[!rcu_segcblist_restempty(rsclp, RCU_NEXT_READY_TAIL)],
+ ".B"[!!rcu_cblist_n_cbs(&rdp->nocb_bypass)],
+ rcu_segcblist_n_cbs(&rdp->cblist));
+
+ /* It is OK for GP kthreads to have GP state. */
+ if (rdp->nocb_gp_rdp == rdp)
+ return;
+
+ waslocked = raw_spin_is_locked(&rdp->nocb_gp_lock);
+ wastimer = timer_pending(&rdp->nocb_timer);
+ wassleep = swait_active(&rdp->nocb_gp_wq);
+ if (!rdp->nocb_defer_wakeup && !rdp->nocb_gp_sleep &&
+ !waslocked && !wastimer && !wassleep)
+ return; /* Nothing untowards. */
+
+ pr_info(" !!! %c%c%c%c %c\n",
+ "lL"[waslocked],
+ "dD"[!!rdp->nocb_defer_wakeup],
+ "tT"[wastimer],
+ "sS"[!!rdp->nocb_gp_sleep],
+ ".W"[wassleep]);
}
#else /* #ifdef CONFIG_RCU_NOCB_CPU */
-static bool rcu_nocb_cpu_needs_barrier(int cpu)
+/* No ->nocb_lock to acquire. */
+static void rcu_nocb_lock(struct rcu_data *rdp)
+{
+}
+
+/* No ->nocb_lock to release. */
+static void rcu_nocb_unlock(struct rcu_data *rdp)
{
- WARN_ON_ONCE(1); /* Should be dead code. */
- return false;
+}
+
+/* No ->nocb_lock to release. */
+static void rcu_nocb_unlock_irqrestore(struct rcu_data *rdp,
+ unsigned long flags)
+{
+ local_irq_restore(flags);
+}
+
+/* Lockdep check that ->cblist may be safely accessed. */
+static void rcu_lockdep_assert_cblist_protected(struct rcu_data *rdp)
+{
+ lockdep_assert_irqs_disabled();
}
static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq)
@@ -2252,19 +2482,24 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
{
}
-static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
- bool lazy, unsigned long flags)
+static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ unsigned long j)
{
- return false;
+ return true;
}
-static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
- struct rcu_data *rdp,
- unsigned long flags)
+static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
+ bool *was_alldone, unsigned long flags)
{
return false;
}
+static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty,
+ unsigned long flags)
+{
+ WARN_ON_ONCE(1); /* Should be dead code! */
+}
+
static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
{
}
@@ -2286,14 +2521,8 @@ static void __init rcu_spawn_nocb_kthreads(void)
{
}
-static bool init_nocb_callback_list(struct rcu_data *rdp)
-{
- return false;
-}
-
-static unsigned long rcu_get_n_cbs_nocb_cpu(struct rcu_data *rdp)
+static void show_rcu_nocb_state(struct rcu_data *rdp)
{
- return 0;
}
#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index 065183391f75..c0b8c458d8a6 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -163,7 +163,7 @@ static void rcu_iw_handler(struct irq_work *iwp)
//
// Printing RCU CPU stall warnings
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
/*
* Dump detailed information for all tasks blocking the current RCU
@@ -215,7 +215,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
return ndetected;
}
-#else /* #ifdef CONFIG_PREEMPT */
+#else /* #ifdef CONFIG_PREEMPTION */
/*
* Because preemptible RCU does not exist, we never have to check for
@@ -233,7 +233,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
{
return 0;
}
-#endif /* #else #ifdef CONFIG_PREEMPT */
+#endif /* #else #ifdef CONFIG_PREEMPTION */
/*
* Dump stacks of all tasks running on stalled CPUs. First try using
@@ -527,6 +527,8 @@ static void check_cpu_stall(struct rcu_data *rdp)
/* We haven't checked in, so go dump stack. */
print_cpu_stall();
+ if (rcu_cpu_stall_ftrace_dump)
+ rcu_ftrace_dump(DUMP_ALL);
} else if (rcu_gp_in_progress() &&
ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY) &&
@@ -534,6 +536,8 @@ static void check_cpu_stall(struct rcu_data *rdp)
/* They had a few time units to dump stack, so complain. */
print_other_cpu_stall(gs2);
+ if (rcu_cpu_stall_ftrace_dump)
+ rcu_ftrace_dump(DUMP_ALL);
}
}
@@ -585,6 +589,11 @@ void show_rcu_gp_kthreads(void)
cpu, (long)rdp->gp_seq_needed);
}
}
+ for_each_possible_cpu(cpu) {
+ rdp = per_cpu_ptr(&rcu_data, cpu);
+ if (rcu_segcblist_is_offloaded(&rdp->cblist))
+ show_rcu_nocb_state(rdp);
+ }
/* sched_show_task(rcu_state.gp_kthread); */
}
EXPORT_SYMBOL_GPL(show_rcu_gp_kthreads);
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 61df2bf08563..1861103662db 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -61,9 +61,15 @@ module_param(rcu_normal_after_boot, int, 0);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/**
- * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
+ * rcu_read_lock_held_common() - might we be in RCU-sched read-side critical section?
+ * @ret: Best guess answer if lockdep cannot be relied on
*
- * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
+ * Returns true if lockdep must be ignored, in which case *ret contains
+ * the best guess described below. Otherwise returns false, in which
+ * case *ret tells the caller nothing and the caller should instead
+ * consult lockdep.
+ *
+ * If CONFIG_DEBUG_LOCK_ALLOC is selected, set *ret to nonzero iff in an
* RCU-sched read-side critical section. In absence of
* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
* critical section unless it can prove otherwise. Note that disabling
@@ -75,35 +81,45 @@ module_param(rcu_normal_after_boot, int, 0);
* Check debug_lockdep_rcu_enabled() to prevent false positives during boot
* and while lockdep is disabled.
*
- * Note that if the CPU is in the idle loop from an RCU point of
- * view (ie: that we are in the section between rcu_idle_enter() and
- * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU
- * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs
- * that are in such a section, considering these as in extended quiescent
- * state, so such a CPU is effectively never in an RCU read-side critical
- * section regardless of what RCU primitives it invokes. This state of
- * affairs is required --- we need to keep an RCU-free window in idle
- * where the CPU may possibly enter into low power mode. This way we can
- * notice an extended quiescent state to other CPUs that started a grace
- * period. Otherwise we would delay any grace period as long as we run in
- * the idle task.
+ * Note that if the CPU is in the idle loop from an RCU point of view (ie:
+ * that we are in the section between rcu_idle_enter() and rcu_idle_exit())
+ * then rcu_read_lock_held() sets *ret to false even if the CPU did an
+ * rcu_read_lock(). The reason for this is that RCU ignores CPUs that are
+ * in such a section, considering these as in extended quiescent state,
+ * so such a CPU is effectively never in an RCU read-side critical section
+ * regardless of what RCU primitives it invokes. This state of affairs is
+ * required --- we need to keep an RCU-free window in idle where the CPU may
+ * possibly enter into low power mode. This way we can notice an extended
+ * quiescent state to other CPUs that started a grace period. Otherwise
+ * we would delay any grace period as long as we run in the idle task.
*
- * Similarly, we avoid claiming an SRCU read lock held if the current
+ * Similarly, we avoid claiming an RCU read lock held if the current
* CPU is offline.
*/
+static bool rcu_read_lock_held_common(bool *ret)
+{
+ if (!debug_lockdep_rcu_enabled()) {
+ *ret = 1;
+ return true;
+ }
+ if (!rcu_is_watching()) {
+ *ret = 0;
+ return true;
+ }
+ if (!rcu_lockdep_current_cpu_online()) {
+ *ret = 0;
+ return true;
+ }
+ return false;
+}
+
int rcu_read_lock_sched_held(void)
{
- int lockdep_opinion = 0;
+ bool ret;
- if (!debug_lockdep_rcu_enabled())
- return 1;
- if (!rcu_is_watching())
- return 0;
- if (!rcu_lockdep_current_cpu_online())
- return 0;
- if (debug_locks)
- lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
- return lockdep_opinion || !preemptible();
+ if (rcu_read_lock_held_common(&ret))
+ return ret;
+ return lock_is_held(&rcu_sched_lock_map) || !preemptible();
}
EXPORT_SYMBOL(rcu_read_lock_sched_held);
#endif
@@ -136,8 +152,7 @@ static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1);
*/
bool rcu_gp_is_expedited(void)
{
- return rcu_expedited || atomic_read(&rcu_expedited_nesting) ||
- rcu_scheduler_active == RCU_SCHEDULER_INIT;
+ return rcu_expedited || atomic_read(&rcu_expedited_nesting);
}
EXPORT_SYMBOL_GPL(rcu_gp_is_expedited);
@@ -261,12 +276,10 @@ NOKPROBE_SYMBOL(debug_lockdep_rcu_enabled);
*/
int rcu_read_lock_held(void)
{
- if (!debug_lockdep_rcu_enabled())
- return 1;
- if (!rcu_is_watching())
- return 0;
- if (!rcu_lockdep_current_cpu_online())
- return 0;
+ bool ret;
+
+ if (rcu_read_lock_held_common(&ret))
+ return ret;
return lock_is_held(&rcu_lock_map);
}
EXPORT_SYMBOL_GPL(rcu_read_lock_held);
@@ -288,16 +301,28 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_held);
*/
int rcu_read_lock_bh_held(void)
{
- if (!debug_lockdep_rcu_enabled())
- return 1;
- if (!rcu_is_watching())
- return 0;
- if (!rcu_lockdep_current_cpu_online())
- return 0;
+ bool ret;
+
+ if (rcu_read_lock_held_common(&ret))
+ return ret;
return in_softirq() || irqs_disabled();
}
EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
+int rcu_read_lock_any_held(void)
+{
+ bool ret;
+
+ if (rcu_read_lock_held_common(&ret))
+ return ret;
+ if (lock_is_held(&rcu_lock_map) ||
+ lock_is_held(&rcu_bh_lock_map) ||
+ lock_is_held(&rcu_sched_lock_map))
+ return 1;
+ return !preemptible();
+}
+EXPORT_SYMBOL_GPL(rcu_read_lock_any_held);
+
#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
/**
@@ -437,6 +462,8 @@ EXPORT_SYMBOL_GPL(rcutorture_sched_setaffinity);
#endif
#ifdef CONFIG_RCU_STALL_COMMON
+int rcu_cpu_stall_ftrace_dump __read_mostly;
+module_param(rcu_cpu_stall_ftrace_dump, int, 0644);
int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
EXPORT_SYMBOL_GPL(rcu_cpu_stall_suppress);
module_param(rcu_cpu_stall_suppress, int, 0644);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 389e0993fbb4..5e8387bdd09c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -773,6 +773,18 @@ static void set_load_weight(struct task_struct *p, bool update_load)
}
#ifdef CONFIG_UCLAMP_TASK
+/*
+ * Serializes updates of utilization clamp values
+ *
+ * The (slow-path) user-space triggers utilization clamp value updates which
+ * can require updates on (fast-path) scheduler's data structures used to
+ * support enqueue/dequeue operations.
+ * While the per-CPU rq lock protects fast-path update operations, user-space
+ * requests are serialized using a mutex to reduce the risk of conflicting
+ * updates or API abuses.
+ */
+static DEFINE_MUTEX(uclamp_mutex);
+
/* Max allowed minimum utilization */
unsigned int sysctl_sched_uclamp_util_min = SCHED_CAPACITY_SCALE;
@@ -798,7 +810,7 @@ static inline unsigned int uclamp_bucket_base_value(unsigned int clamp_value)
return UCLAMP_BUCKET_DELTA * uclamp_bucket_id(clamp_value);
}
-static inline unsigned int uclamp_none(int clamp_id)
+static inline enum uclamp_id uclamp_none(enum uclamp_id clamp_id)
{
if (clamp_id == UCLAMP_MIN)
return 0;
@@ -814,7 +826,7 @@ static inline void uclamp_se_set(struct uclamp_se *uc_se,
}
static inline unsigned int
-uclamp_idle_value(struct rq *rq, unsigned int clamp_id,
+uclamp_idle_value(struct rq *rq, enum uclamp_id clamp_id,
unsigned int clamp_value)
{
/*
@@ -830,7 +842,7 @@ uclamp_idle_value(struct rq *rq, unsigned int clamp_id,
return uclamp_none(UCLAMP_MIN);
}
-static inline void uclamp_idle_reset(struct rq *rq, unsigned int clamp_id,
+static inline void uclamp_idle_reset(struct rq *rq, enum uclamp_id clamp_id,
unsigned int clamp_value)
{
/* Reset max-clamp retention only on idle exit */
@@ -841,8 +853,8 @@ static inline void uclamp_idle_reset(struct rq *rq, unsigned int clamp_id,
}
static inline
-unsigned int uclamp_rq_max_value(struct rq *rq, unsigned int clamp_id,
- unsigned int clamp_value)
+enum uclamp_id uclamp_rq_max_value(struct rq *rq, enum uclamp_id clamp_id,
+ unsigned int clamp_value)
{
struct uclamp_bucket *bucket = rq->uclamp[clamp_id].bucket;
int bucket_id = UCLAMP_BUCKETS - 1;
@@ -861,16 +873,42 @@ unsigned int uclamp_rq_max_value(struct rq *rq, unsigned int clamp_id,
return uclamp_idle_value(rq, clamp_id, clamp_value);
}
+static inline struct uclamp_se
+uclamp_tg_restrict(struct task_struct *p, enum uclamp_id clamp_id)
+{
+ struct uclamp_se uc_req = p->uclamp_req[clamp_id];
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ struct uclamp_se uc_max;
+
+ /*
+ * Tasks in autogroups or root task group will be
+ * restricted by system defaults.
+ */
+ if (task_group_is_autogroup(task_group(p)))
+ return uc_req;
+ if (task_group(p) == &root_task_group)
+ return uc_req;
+
+ uc_max = task_group(p)->uclamp[clamp_id];
+ if (uc_req.value > uc_max.value || !uc_req.user_defined)
+ return uc_max;
+#endif
+
+ return uc_req;
+}
+
/*
* The effective clamp bucket index of a task depends on, by increasing
* priority:
* - the task specific clamp value, when explicitly requested from userspace
+ * - the task group effective clamp value, for tasks not either in the root
+ * group or in an autogroup
* - the system default clamp value, defined by the sysadmin
*/
static inline struct uclamp_se
-uclamp_eff_get(struct task_struct *p, unsigned int clamp_id)
+uclamp_eff_get(struct task_struct *p, enum uclamp_id clamp_id)
{
- struct uclamp_se uc_req = p->uclamp_req[clamp_id];
+ struct uclamp_se uc_req = uclamp_tg_restrict(p, clamp_id);
struct uclamp_se uc_max = uclamp_default[clamp_id];
/* System default restrictions always apply */
@@ -880,7 +918,7 @@ uclamp_eff_get(struct task_struct *p, unsigned int clamp_id)
return uc_req;
}
-unsigned int uclamp_eff_value(struct task_struct *p, unsigned int clamp_id)
+enum uclamp_id uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id)
{
struct uclamp_se uc_eff;
@@ -904,7 +942,7 @@ unsigned int uclamp_eff_value(struct task_struct *p, unsigned int clamp_id)
* for each bucket when all its RUNNABLE tasks require the same clamp.
*/
static inline void uclamp_rq_inc_id(struct rq *rq, struct task_struct *p,
- unsigned int clamp_id)
+ enum uclamp_id clamp_id)
{
struct uclamp_rq *uc_rq = &rq->uclamp[clamp_id];
struct uclamp_se *uc_se = &p->uclamp[clamp_id];
@@ -942,7 +980,7 @@ static inline void uclamp_rq_inc_id(struct rq *rq, struct task_struct *p,
* enforce the expected state and warn.
*/
static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p,
- unsigned int clamp_id)
+ enum uclamp_id clamp_id)
{
struct uclamp_rq *uc_rq = &rq->uclamp[clamp_id];
struct uclamp_se *uc_se = &p->uclamp[clamp_id];
@@ -981,7 +1019,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p,
static inline void uclamp_rq_inc(struct rq *rq, struct task_struct *p)
{
- unsigned int clamp_id;
+ enum uclamp_id clamp_id;
if (unlikely(!p->sched_class->uclamp_enabled))
return;
@@ -996,7 +1034,7 @@ static inline void uclamp_rq_inc(struct rq *rq, struct task_struct *p)
static inline void uclamp_rq_dec(struct rq *rq, struct task_struct *p)
{
- unsigned int clamp_id;
+ enum uclamp_id clamp_id;
if (unlikely(!p->sched_class->uclamp_enabled))
return;
@@ -1005,15 +1043,82 @@ static inline void uclamp_rq_dec(struct rq *rq, struct task_struct *p)
uclamp_rq_dec_id(rq, p, clamp_id);
}
+static inline void
+uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id)
+{
+ struct rq_flags rf;
+ struct rq *rq;
+
+ /*
+ * Lock the task and the rq where the task is (or was) queued.
+ *
+ * We might lock the (previous) rq of a !RUNNABLE task, but that's the
+ * price to pay to safely serialize util_{min,max} updates with
+ * enqueues, dequeues and migration operations.
+ * This is the same locking schema used by __set_cpus_allowed_ptr().
+ */
+ rq = task_rq_lock(p, &rf);
+
+ /*
+ * Setting the clamp bucket is serialized by task_rq_lock().
+ * If the task is not yet RUNNABLE and its task_struct is not
+ * affecting a valid clamp bucket, the next time it's enqueued,
+ * it will already see the updated clamp bucket value.
+ */
+ if (!p->uclamp[clamp_id].active) {
+ uclamp_rq_dec_id(rq, p, clamp_id);
+ uclamp_rq_inc_id(rq, p, clamp_id);
+ }
+
+ task_rq_unlock(rq, p, &rf);
+}
+
+static inline void
+uclamp_update_active_tasks(struct cgroup_subsys_state *css,
+ unsigned int clamps)
+{
+ enum uclamp_id clamp_id;
+ struct css_task_iter it;
+ struct task_struct *p;
+
+ css_task_iter_start(css, 0, &it);
+ while ((p = css_task_iter_next(&it))) {
+ for_each_clamp_id(clamp_id) {
+ if ((0x1 << clamp_id) & clamps)
+ uclamp_update_active(p, clamp_id);
+ }
+ }
+ css_task_iter_end(&it);
+}
+
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+static void cpu_util_update_eff(struct cgroup_subsys_state *css);
+static void uclamp_update_root_tg(void)
+{
+ struct task_group *tg = &root_task_group;
+
+ uclamp_se_set(&tg->uclamp_req[UCLAMP_MIN],
+ sysctl_sched_uclamp_util_min, false);
+ uclamp_se_set(&tg->uclamp_req[UCLAMP_MAX],
+ sysctl_sched_uclamp_util_max, false);
+
+ rcu_read_lock();
+ cpu_util_update_eff(&root_task_group.css);
+ rcu_read_unlock();
+}
+#else
+static void uclamp_update_root_tg(void) { }
+#endif
+
int sysctl_sched_uclamp_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
+ bool update_root_tg = false;
int old_min, old_max;
- static DEFINE_MUTEX(mutex);
int result;
- mutex_lock(&mutex);
+ mutex_lock(&uclamp_mutex);
old_min = sysctl_sched_uclamp_util_min;
old_max = sysctl_sched_uclamp_util_max;
@@ -1032,23 +1137,30 @@ int sysctl_sched_uclamp_handler(struct ctl_table *table, int write,
if (old_min != sysctl_sched_uclamp_util_min) {
uclamp_se_set(&uclamp_default[UCLAMP_MIN],
sysctl_sched_uclamp_util_min, false);
+ update_root_tg = true;
}
if (old_max != sysctl_sched_uclamp_util_max) {
uclamp_se_set(&uclamp_default[UCLAMP_MAX],
sysctl_sched_uclamp_util_max, false);
+ update_root_tg = true;
}
+ if (update_root_tg)
+ uclamp_update_root_tg();
+
/*
- * Updating all the RUNNABLE task is expensive, keep it simple and do
- * just a lazy update at each next enqueue time.
+ * We update all RUNNABLE tasks only when task groups are in use.
+ * Otherwise, keep it simple and do just a lazy update at each next
+ * task enqueue time.
*/
+
goto done;
undo:
sysctl_sched_uclamp_util_min = old_min;
sysctl_sched_uclamp_util_max = old_max;
done:
- mutex_unlock(&mutex);
+ mutex_unlock(&uclamp_mutex);
return result;
}
@@ -1075,7 +1187,7 @@ static int uclamp_validate(struct task_struct *p,
static void __setscheduler_uclamp(struct task_struct *p,
const struct sched_attr *attr)
{
- unsigned int clamp_id;
+ enum uclamp_id clamp_id;
/*
* On scheduling class change, reset to default clamps for tasks
@@ -1112,7 +1224,7 @@ static void __setscheduler_uclamp(struct task_struct *p,
static void uclamp_fork(struct task_struct *p)
{
- unsigned int clamp_id;
+ enum uclamp_id clamp_id;
for_each_clamp_id(clamp_id)
p->uclamp[clamp_id].active = false;
@@ -1134,9 +1246,11 @@ static void uclamp_fork(struct task_struct *p)
static void __init init_uclamp(void)
{
struct uclamp_se uc_max = {};
- unsigned int clamp_id;
+ enum uclamp_id clamp_id;
int cpu;
+ mutex_init(&uclamp_mutex);
+
for_each_possible_cpu(cpu) {
memset(&cpu_rq(cpu)->uclamp, 0, sizeof(struct uclamp_rq));
cpu_rq(cpu)->uclamp_flags = 0;
@@ -1149,8 +1263,13 @@ static void __init init_uclamp(void)
/* System defaults allow max clamp values for both indexes */
uclamp_se_set(&uc_max, uclamp_none(UCLAMP_MAX), false);
- for_each_clamp_id(clamp_id)
+ for_each_clamp_id(clamp_id) {
uclamp_default[clamp_id] = uc_max;
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ root_task_group.uclamp_req[clamp_id] = uc_max;
+ root_task_group.uclamp[clamp_id] = uc_max;
+#endif
+ }
}
#else /* CONFIG_UCLAMP_TASK */
@@ -1494,7 +1613,7 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
if (queued)
enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK);
if (running)
- set_curr_task(rq, p);
+ set_next_task(rq, p);
}
/*
@@ -3214,12 +3333,8 @@ static __always_inline struct rq *
context_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next, struct rq_flags *rf)
{
- struct mm_struct *mm, *oldmm;
-
prepare_task_switch(rq, prev, next);
- mm = next->mm;
- oldmm = prev->active_mm;
/*
* For paravirt, this is coupled with an exit in switch_to to
* combine the page table reload and the switch backend into
@@ -3228,22 +3343,37 @@ context_switch(struct rq *rq, struct task_struct *prev,
arch_start_context_switch(prev);
/*
- * If mm is non-NULL, we pass through switch_mm(). If mm is
- * NULL, we will pass through mmdrop() in finish_task_switch().
- * Both of these contain the full memory barrier required by
- * membarrier after storing to rq->curr, before returning to
- * user-space.
+ * kernel -> kernel lazy + transfer active
+ * user -> kernel lazy + mmgrab() active
+ *
+ * kernel -> user switch + mmdrop() active
+ * user -> user switch
*/
- if (!mm) {
- next->active_mm = oldmm;
- mmgrab(oldmm);
- enter_lazy_tlb(oldmm, next);
- } else
- switch_mm_irqs_off(oldmm, mm, next);
+ if (!next->mm) { // to kernel
+ enter_lazy_tlb(prev->active_mm, next);
+
+ next->active_mm = prev->active_mm;
+ if (prev->mm) // from user
+ mmgrab(prev->active_mm);
+ else
+ prev->active_mm = NULL;
+ } else { // to user
+ /*
+ * sys_membarrier() requires an smp_mb() between setting
+ * rq->curr and returning to userspace.
+ *
+ * The below provides this either through switch_mm(), or in
+ * case 'prev->active_mm == next->mm' through
+ * finish_task_switch()'s mmdrop().
+ */
- if (!prev->mm) {
- prev->active_mm = NULL;
- rq->prev_mm = oldmm;
+ switch_mm_irqs_off(prev->active_mm, next->mm, next);
+
+ if (!prev->mm) { // from kernel
+ /* will mmdrop() in finish_task_switch(). */
+ rq->prev_mm = prev->active_mm;
+ prev->active_mm = NULL;
+ }
}
rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);
@@ -3486,8 +3616,36 @@ void scheduler_tick(void)
struct tick_work {
int cpu;
+ atomic_t state;
struct delayed_work work;
};
+/* Values for ->state, see diagram below. */
+#define TICK_SCHED_REMOTE_OFFLINE 0
+#define TICK_SCHED_REMOTE_OFFLINING 1
+#define TICK_SCHED_REMOTE_RUNNING 2
+
+/*
+ * State diagram for ->state:
+ *
+ *
+ * TICK_SCHED_REMOTE_OFFLINE
+ * | ^
+ * | |
+ * | | sched_tick_remote()
+ * | |
+ * | |
+ * +--TICK_SCHED_REMOTE_OFFLINING
+ * | ^
+ * | |
+ * sched_tick_start() | | sched_tick_stop()
+ * | |
+ * V |
+ * TICK_SCHED_REMOTE_RUNNING
+ *
+ *
+ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote()
+ * and sched_tick_start() are happy to leave the state in RUNNING.
+ */
static struct tick_work __percpu *tick_work_cpu;
@@ -3500,6 +3658,7 @@ static void sched_tick_remote(struct work_struct *work)
struct task_struct *curr;
struct rq_flags rf;
u64 delta;
+ int os;
/*
* Handle the tick only if it appears the remote CPU is running in full
@@ -3513,7 +3672,7 @@ static void sched_tick_remote(struct work_struct *work)
rq_lock_irq(rq, &rf);
curr = rq->curr;
- if (is_idle_task(curr))
+ if (is_idle_task(curr) || cpu_is_offline(cpu))
goto out_unlock;
update_rq_clock(rq);
@@ -3533,13 +3692,18 @@ out_requeue:
/*
* Run the remote tick once per second (1Hz). This arbitrary
* frequency is large enough to avoid overload but short enough
- * to keep scheduler internal stats reasonably up to date.
+ * to keep scheduler internal stats reasonably up to date. But
+ * first update state to reflect hotplug activity if required.
*/
- queue_delayed_work(system_unbound_wq, dwork, HZ);
+ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING);
+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE);
+ if (os == TICK_SCHED_REMOTE_RUNNING)
+ queue_delayed_work(system_unbound_wq, dwork, HZ);
}
static void sched_tick_start(int cpu)
{
+ int os;
struct tick_work *twork;
if (housekeeping_cpu(cpu, HK_FLAG_TICK))
@@ -3548,15 +3712,20 @@ static void sched_tick_start(int cpu)
WARN_ON_ONCE(!tick_work_cpu);
twork = per_cpu_ptr(tick_work_cpu, cpu);
- twork->cpu = cpu;
- INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
- queue_delayed_work(system_unbound_wq, &twork->work, HZ);
+ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING);
+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING);
+ if (os == TICK_SCHED_REMOTE_OFFLINE) {
+ twork->cpu = cpu;
+ INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
+ queue_delayed_work(system_unbound_wq, &twork->work, HZ);
+ }
}
#ifdef CONFIG_HOTPLUG_CPU
static void sched_tick_stop(int cpu)
{
struct tick_work *twork;
+ int os;
if (housekeeping_cpu(cpu, HK_FLAG_TICK))
return;
@@ -3564,7 +3733,10 @@ static void sched_tick_stop(int cpu)
WARN_ON_ONCE(!tick_work_cpu);
twork = per_cpu_ptr(tick_work_cpu, cpu);
- cancel_delayed_work_sync(&twork->work);
+ /* There cannot be competing actions, but don't rely on stop-machine. */
+ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING);
+ WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING);
+ /* Don't cancel, as this would mess up the state machine. */
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -3572,7 +3744,6 @@ int __init sched_tick_offload_init(void)
{
tick_work_cpu = alloc_percpu(struct tick_work);
BUG_ON(!tick_work_cpu);
-
return 0;
}
@@ -3581,7 +3752,7 @@ static inline void sched_tick_start(int cpu) { }
static inline void sched_tick_stop(int cpu) { }
#endif
-#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
+#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \
defined(CONFIG_TRACE_PREEMPT_TOGGLE))
/*
* If the value passed in is equal to the current preempt count
@@ -3739,7 +3910,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
p = fair_sched_class.pick_next_task(rq, prev, rf);
if (unlikely(p == RETRY_TASK))
- goto again;
+ goto restart;
/* Assumes fair_sched_class->next == idle_sched_class */
if (unlikely(!p))
@@ -3748,14 +3919,19 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
return p;
}
-again:
+restart:
+ /*
+ * Ensure that we put DL/RT tasks before the pick loop, such that they
+ * can PULL higher prio tasks when we lower the RQ 'priority'.
+ */
+ prev->sched_class->put_prev_task(rq, prev, rf);
+ if (!rq->nr_running)
+ newidle_balance(rq, rf);
+
for_each_class(class) {
- p = class->pick_next_task(rq, prev, rf);
- if (p) {
- if (unlikely(p == RETRY_TASK))
- goto again;
+ p = class->pick_next_task(rq, NULL, NULL);
+ if (p)
return p;
- }
}
/* The idle class should always have a runnable task: */
@@ -3782,7 +3958,7 @@ again:
* task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets
* called on the nearest possible occasion:
*
- * - If the kernel is preemptible (CONFIG_PREEMPT=y):
+ * - If the kernel is preemptible (CONFIG_PREEMPTION=y):
*
* - in syscall or exception context, at the next outmost
* preempt_enable(). (this might be as soon as the wake_up()'s
@@ -3791,7 +3967,7 @@ again:
* - in IRQ context, return from interrupt-handler to
* preemptible context
*
- * - If the kernel is not preemptible (CONFIG_PREEMPT is not set)
+ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set)
* then at the next:
*
* - cond_resched() call
@@ -3904,7 +4080,7 @@ void __noreturn do_task_dead(void)
static inline void sched_submit_work(struct task_struct *tsk)
{
- if (!tsk->state || tsk_is_pi_blocked(tsk))
+ if (!tsk->state)
return;
/*
@@ -3920,6 +4096,9 @@ static inline void sched_submit_work(struct task_struct *tsk)
preempt_enable_no_resched();
}
+ if (tsk_is_pi_blocked(tsk))
+ return;
+
/*
* If we are going to sleep and we have plugged IO queued,
* make sure to submit it to avoid deadlocks.
@@ -4033,7 +4212,7 @@ static void __sched notrace preempt_schedule_common(void)
} while (need_resched());
}
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
/*
* this is the entry point to schedule() from in-kernel preemption
* off of preempt_enable. Kernel preemptions off return from interrupt
@@ -4105,7 +4284,7 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
}
EXPORT_SYMBOL_GPL(preempt_schedule_notrace);
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
/*
* this is the entry point to schedule() from kernel preemption
@@ -4273,7 +4452,7 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
if (queued)
enqueue_task(rq, p, queue_flag);
if (running)
- set_curr_task(rq, p);
+ set_next_task(rq, p);
check_class_changed(rq, p, prev_class, oldprio);
out_unlock:
@@ -4340,7 +4519,7 @@ void set_user_nice(struct task_struct *p, long nice)
resched_curr(rq);
}
if (running)
- set_curr_task(rq, p);
+ set_next_task(rq, p);
out_unlock:
task_rq_unlock(rq, p, &rf);
}
@@ -4657,6 +4836,9 @@ recheck:
return retval;
}
+ if (pi)
+ cpuset_read_lock();
+
/*
* Make sure no PI-waiters arrive (or leave) while we are
* changing the priority of the task:
@@ -4671,8 +4853,8 @@ recheck:
* Changing the policy of the stop threads its a very bad idea:
*/
if (p == rq->stop) {
- task_rq_unlock(rq, p, &rf);
- return -EINVAL;
+ retval = -EINVAL;
+ goto unlock;
}
/*
@@ -4690,8 +4872,8 @@ recheck:
goto change;
p->sched_reset_on_fork = reset_on_fork;
- task_rq_unlock(rq, p, &rf);
- return 0;
+ retval = 0;
+ goto unlock;
}
change:
@@ -4704,8 +4886,8 @@ change:
if (rt_bandwidth_enabled() && rt_policy(policy) &&
task_group(p)->rt_bandwidth.rt_runtime == 0 &&
!task_group_is_autogroup(task_group(p))) {
- task_rq_unlock(rq, p, &rf);
- return -EPERM;
+ retval = -EPERM;
+ goto unlock;
}
#endif
#ifdef CONFIG_SMP
@@ -4720,8 +4902,8 @@ change:
*/
if (!cpumask_subset(span, p->cpus_ptr) ||
rq->rd->dl_bw.bw == 0) {
- task_rq_unlock(rq, p, &rf);
- return -EPERM;
+ retval = -EPERM;
+ goto unlock;
}
}
#endif
@@ -4731,6 +4913,8 @@ change:
if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
policy = oldpolicy = -1;
task_rq_unlock(rq, p, &rf);
+ if (pi)
+ cpuset_read_unlock();
goto recheck;
}
@@ -4740,8 +4924,8 @@ change:
* is available.
*/
if ((dl_policy(policy) || dl_task(p)) && sched_dl_overflow(p, policy, attr)) {
- task_rq_unlock(rq, p, &rf);
- return -EBUSY;
+ retval = -EBUSY;
+ goto unlock;
}
p->sched_reset_on_fork = reset_on_fork;
@@ -4783,7 +4967,7 @@ change:
enqueue_task(rq, p, queue_flags);
}
if (running)
- set_curr_task(rq, p);
+ set_next_task(rq, p);
check_class_changed(rq, p, prev_class, oldprio);
@@ -4791,14 +4975,22 @@ change:
preempt_disable();
task_rq_unlock(rq, p, &rf);
- if (pi)
+ if (pi) {
+ cpuset_read_unlock();
rt_mutex_adjust_pi(p);
+ }
/* Run balance callbacks after we've adjusted the PI chain: */
balance_callback(rq);
preempt_enable();
return 0;
+
+unlock:
+ task_rq_unlock(rq, p, &rf);
+ if (pi)
+ cpuset_read_unlock();
+ return retval;
}
static int _sched_setscheduler(struct task_struct *p, int policy,
@@ -4882,10 +5074,15 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
rcu_read_lock();
retval = -ESRCH;
p = find_process_by_pid(pid);
- if (p != NULL)
- retval = sched_setscheduler(p, policy, &lparam);
+ if (likely(p))
+ get_task_struct(p);
rcu_read_unlock();
+ if (likely(p)) {
+ retval = sched_setscheduler(p, policy, &lparam);
+ put_task_struct(p);
+ }
+
return retval;
}
@@ -5102,37 +5299,40 @@ out_unlock:
return retval;
}
-static int sched_read_attr(struct sched_attr __user *uattr,
- struct sched_attr *attr,
- unsigned int usize)
+/*
+ * Copy the kernel size attribute structure (which might be larger
+ * than what user-space knows about) to user-space.
+ *
+ * Note that all cases are valid: user-space buffer can be larger or
+ * smaller than the kernel-space buffer. The usual case is that both
+ * have the same size.
+ */
+static int
+sched_attr_copy_to_user(struct sched_attr __user *uattr,
+ struct sched_attr *kattr,
+ unsigned int usize)
{
- int ret;
+ unsigned int ksize = sizeof(*kattr);
if (!access_ok(uattr, usize))
return -EFAULT;
/*
- * If we're handed a smaller struct than we know of,
- * ensure all the unknown bits are 0 - i.e. old
- * user-space does not get uncomplete information.
+ * sched_getattr() ABI forwards and backwards compatibility:
+ *
+ * If usize == ksize then we just copy everything to user-space and all is good.
+ *
+ * If usize < ksize then we only copy as much as user-space has space for,
+ * this keeps ABI compatibility as well. We skip the rest.
+ *
+ * If usize > ksize then user-space is using a newer version of the ABI,
+ * which part the kernel doesn't know about. Just ignore it - tooling can
+ * detect the kernel's knowledge of attributes from the attr->size value
+ * which is set to ksize in this case.
*/
- if (usize < sizeof(*attr)) {
- unsigned char *addr;
- unsigned char *end;
-
- addr = (void *)attr + usize;
- end = (void *)attr + sizeof(*attr);
-
- for (; addr < end; addr++) {
- if (*addr)
- return -EFBIG;
- }
-
- attr->size = usize;
- }
+ kattr->size = min(usize, ksize);
- ret = copy_to_user(uattr, attr, attr->size);
- if (ret)
+ if (copy_to_user(uattr, kattr, kattr->size))
return -EFAULT;
return 0;
@@ -5142,20 +5342,18 @@ static int sched_read_attr(struct sched_attr __user *uattr,
* sys_sched_getattr - similar to sched_getparam, but with sched_attr
* @pid: the pid in question.
* @uattr: structure containing the extended parameters.
- * @size: sizeof(attr) for fwd/bwd comp.
+ * @usize: sizeof(attr) that user-space knows about, for forwards and backwards compatibility.
* @flags: for future extension.
*/
SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
- unsigned int, size, unsigned int, flags)
+ unsigned int, usize, unsigned int, flags)
{
- struct sched_attr attr = {
- .size = sizeof(struct sched_attr),
- };
+ struct sched_attr kattr = { };
struct task_struct *p;
int retval;
- if (!uattr || pid < 0 || size > PAGE_SIZE ||
- size < SCHED_ATTR_SIZE_VER0 || flags)
+ if (!uattr || pid < 0 || usize > PAGE_SIZE ||
+ usize < SCHED_ATTR_SIZE_VER0 || flags)
return -EINVAL;
rcu_read_lock();
@@ -5168,25 +5366,24 @@ SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
if (retval)
goto out_unlock;
- attr.sched_policy = p->policy;
+ kattr.sched_policy = p->policy;
if (p->sched_reset_on_fork)
- attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
+ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
if (task_has_dl_policy(p))
- __getparam_dl(p, &attr);
+ __getparam_dl(p, &kattr);
else if (task_has_rt_policy(p))
- attr.sched_priority = p->rt_priority;
+ kattr.sched_priority = p->rt_priority;
else
- attr.sched_nice = task_nice(p);
+ kattr.sched_nice = task_nice(p);
#ifdef CONFIG_UCLAMP_TASK
- attr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
- attr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
+ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
+ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
#endif
rcu_read_unlock();
- retval = sched_read_attr(uattr, &attr, size);
- return retval;
+ return sched_attr_copy_to_user(uattr, &kattr, usize);
out_unlock:
rcu_read_unlock();
@@ -5416,7 +5613,7 @@ SYSCALL_DEFINE0(sched_yield)
return 0;
}
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
int __sched _cond_resched(void)
{
if (should_resched(0)) {
@@ -5433,7 +5630,7 @@ EXPORT_SYMBOL(_cond_resched);
* __cond_resched_lock() - if a reschedule is pending, drop the given lock,
* call schedule, and on return reacquire the lock.
*
- * This works OK both with and without CONFIG_PREEMPT. We do strange low-level
+ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level
* operations here to prevent schedule() from being called twice (once via
* spin_unlock(), once by hand).
*/
@@ -5972,7 +6169,7 @@ void sched_setnuma(struct task_struct *p, int nid)
if (queued)
enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK);
if (running)
- set_curr_task(rq, p);
+ set_next_task(rq, p);
task_rq_unlock(rq, p, &rf);
}
#endif /* CONFIG_NUMA_BALANCING */
@@ -6012,21 +6209,22 @@ static void calc_load_migrate(struct rq *rq)
atomic_long_add(delta, &calc_load_tasks);
}
-static void put_prev_task_fake(struct rq *rq, struct task_struct *prev)
+static struct task_struct *__pick_migrate_task(struct rq *rq)
{
-}
+ const struct sched_class *class;
+ struct task_struct *next;
-static const struct sched_class fake_sched_class = {
- .put_prev_task = put_prev_task_fake,
-};
+ for_each_class(class) {
+ next = class->pick_next_task(rq, NULL, NULL);
+ if (next) {
+ next->sched_class->put_prev_task(rq, next, NULL);
+ return next;
+ }
+ }
-static struct task_struct fake_task = {
- /*
- * Avoid pull_{rt,dl}_task()
- */
- .prio = MAX_PRIO + 1,
- .sched_class = &fake_sched_class,
-};
+ /* The idle class should always have a runnable task */
+ BUG();
+}
/*
* Migrate all tasks from the rq, sleeping tasks will be migrated by
@@ -6069,12 +6267,7 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf)
if (rq->nr_running == 1)
break;
- /*
- * pick_next_task() assumes pinned rq->lock:
- */
- next = pick_next_task(rq, &fake_task, rf);
- BUG_ON(!next);
- put_prev_task(rq, next);
+ next = __pick_migrate_task(rq);
/*
* Rules for changing task_struct::cpus_mask are holding
@@ -6371,19 +6564,19 @@ DECLARE_PER_CPU(cpumask_var_t, select_idle_mask);
void __init sched_init(void)
{
- unsigned long alloc_size = 0, ptr;
+ unsigned long ptr = 0;
int i;
wait_bit_init();
#ifdef CONFIG_FAIR_GROUP_SCHED
- alloc_size += 2 * nr_cpu_ids * sizeof(void **);
+ ptr += 2 * nr_cpu_ids * sizeof(void **);
#endif
#ifdef CONFIG_RT_GROUP_SCHED
- alloc_size += 2 * nr_cpu_ids * sizeof(void **);
+ ptr += 2 * nr_cpu_ids * sizeof(void **);
#endif
- if (alloc_size) {
- ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT);
+ if (ptr) {
+ ptr = (unsigned long)kzalloc(ptr, GFP_NOWAIT);
#ifdef CONFIG_FAIR_GROUP_SCHED
root_task_group.se = (struct sched_entity **)ptr;
@@ -6702,7 +6895,7 @@ struct task_struct *curr_task(int cpu)
#ifdef CONFIG_IA64
/**
- * set_curr_task - set the current task for a given CPU.
+ * ia64_set_curr_task - set the current task for a given CPU.
* @cpu: the processor in question.
* @p: the task pointer to set.
*
@@ -6727,6 +6920,20 @@ void ia64_set_curr_task(int cpu, struct task_struct *p)
/* task_group_lock serializes the addition/removal of task groups */
static DEFINE_SPINLOCK(task_group_lock);
+static inline void alloc_uclamp_sched_group(struct task_group *tg,
+ struct task_group *parent)
+{
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ enum uclamp_id clamp_id;
+
+ for_each_clamp_id(clamp_id) {
+ uclamp_se_set(&tg->uclamp_req[clamp_id],
+ uclamp_none(clamp_id), false);
+ tg->uclamp[clamp_id] = parent->uclamp[clamp_id];
+ }
+#endif
+}
+
static void sched_free_group(struct task_group *tg)
{
free_fair_sched_group(tg);
@@ -6750,6 +6957,8 @@ struct task_group *sched_create_group(struct task_group *parent)
if (!alloc_rt_sched_group(tg, parent))
goto err;
+ alloc_uclamp_sched_group(tg, parent);
+
return tg;
err:
@@ -6853,7 +7062,7 @@ void sched_move_task(struct task_struct *tsk)
if (queued)
enqueue_task(rq, tsk, queue_flags);
if (running)
- set_curr_task(rq, tsk);
+ set_next_task(rq, tsk);
task_rq_unlock(rq, tsk, &rf);
}
@@ -6936,10 +7145,6 @@ static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
#ifdef CONFIG_RT_GROUP_SCHED
if (!sched_rt_can_attach(css_tg(css), task))
return -EINVAL;
-#else
- /* We don't support RT-tasks being in separate groups */
- if (task->sched_class != &fair_sched_class)
- return -EINVAL;
#endif
/*
* Serialize against wake_up_new_task() such that if its
@@ -6970,6 +7175,178 @@ static void cpu_cgroup_attach(struct cgroup_taskset *tset)
sched_move_task(task);
}
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+static void cpu_util_update_eff(struct cgroup_subsys_state *css)
+{
+ struct cgroup_subsys_state *top_css = css;
+ struct uclamp_se *uc_parent = NULL;
+ struct uclamp_se *uc_se = NULL;
+ unsigned int eff[UCLAMP_CNT];
+ enum uclamp_id clamp_id;
+ unsigned int clamps;
+
+ css_for_each_descendant_pre(css, top_css) {
+ uc_parent = css_tg(css)->parent
+ ? css_tg(css)->parent->uclamp : NULL;
+
+ for_each_clamp_id(clamp_id) {
+ /* Assume effective clamps matches requested clamps */
+ eff[clamp_id] = css_tg(css)->uclamp_req[clamp_id].value;
+ /* Cap effective clamps with parent's effective clamps */
+ if (uc_parent &&
+ eff[clamp_id] > uc_parent[clamp_id].value) {
+ eff[clamp_id] = uc_parent[clamp_id].value;
+ }
+ }
+ /* Ensure protection is always capped by limit */
+ eff[UCLAMP_MIN] = min(eff[UCLAMP_MIN], eff[UCLAMP_MAX]);
+
+ /* Propagate most restrictive effective clamps */
+ clamps = 0x0;
+ uc_se = css_tg(css)->uclamp;
+ for_each_clamp_id(clamp_id) {
+ if (eff[clamp_id] == uc_se[clamp_id].value)
+ continue;
+ uc_se[clamp_id].value = eff[clamp_id];
+ uc_se[clamp_id].bucket_id = uclamp_bucket_id(eff[clamp_id]);
+ clamps |= (0x1 << clamp_id);
+ }
+ if (!clamps) {
+ css = css_rightmost_descendant(css);
+ continue;
+ }
+
+ /* Immediately update descendants RUNNABLE tasks */
+ uclamp_update_active_tasks(css, clamps);
+ }
+}
+
+/*
+ * Integer 10^N with a given N exponent by casting to integer the literal "1eN"
+ * C expression. Since there is no way to convert a macro argument (N) into a
+ * character constant, use two levels of macros.
+ */
+#define _POW10(exp) ((unsigned int)1e##exp)
+#define POW10(exp) _POW10(exp)
+
+struct uclamp_request {
+#define UCLAMP_PERCENT_SHIFT 2
+#define UCLAMP_PERCENT_SCALE (100 * POW10(UCLAMP_PERCENT_SHIFT))
+ s64 percent;
+ u64 util;
+ int ret;
+};
+
+static inline struct uclamp_request
+capacity_from_percent(char *buf)
+{
+ struct uclamp_request req = {
+ .percent = UCLAMP_PERCENT_SCALE,
+ .util = SCHED_CAPACITY_SCALE,
+ .ret = 0,
+ };
+
+ buf = strim(buf);
+ if (strcmp(buf, "max")) {
+ req.ret = cgroup_parse_float(buf, UCLAMP_PERCENT_SHIFT,
+ &req.percent);
+ if (req.ret)
+ return req;
+ if (req.percent > UCLAMP_PERCENT_SCALE) {
+ req.ret = -ERANGE;
+ return req;
+ }
+
+ req.util = req.percent << SCHED_CAPACITY_SHIFT;
+ req.util = DIV_ROUND_CLOSEST_ULL(req.util, UCLAMP_PERCENT_SCALE);
+ }
+
+ return req;
+}
+
+static ssize_t cpu_uclamp_write(struct kernfs_open_file *of, char *buf,
+ size_t nbytes, loff_t off,
+ enum uclamp_id clamp_id)
+{
+ struct uclamp_request req;
+ struct task_group *tg;
+
+ req = capacity_from_percent(buf);
+ if (req.ret)
+ return req.ret;
+
+ mutex_lock(&uclamp_mutex);
+ rcu_read_lock();
+
+ tg = css_tg(of_css(of));
+ if (tg->uclamp_req[clamp_id].value != req.util)
+ uclamp_se_set(&tg->uclamp_req[clamp_id], req.util, false);
+
+ /*
+ * Because of not recoverable conversion rounding we keep track of the
+ * exact requested value
+ */
+ tg->uclamp_pct[clamp_id] = req.percent;
+
+ /* Update effective clamps to track the most restrictive value */
+ cpu_util_update_eff(of_css(of));
+
+ rcu_read_unlock();
+ mutex_unlock(&uclamp_mutex);
+
+ return nbytes;
+}
+
+static ssize_t cpu_uclamp_min_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes,
+ loff_t off)
+{
+ return cpu_uclamp_write(of, buf, nbytes, off, UCLAMP_MIN);
+}
+
+static ssize_t cpu_uclamp_max_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes,
+ loff_t off)
+{
+ return cpu_uclamp_write(of, buf, nbytes, off, UCLAMP_MAX);
+}
+
+static inline void cpu_uclamp_print(struct seq_file *sf,
+ enum uclamp_id clamp_id)
+{
+ struct task_group *tg;
+ u64 util_clamp;
+ u64 percent;
+ u32 rem;
+
+ rcu_read_lock();
+ tg = css_tg(seq_css(sf));
+ util_clamp = tg->uclamp_req[clamp_id].value;
+ rcu_read_unlock();
+
+ if (util_clamp == SCHED_CAPACITY_SCALE) {
+ seq_puts(sf, "max\n");
+ return;
+ }
+
+ percent = tg->uclamp_pct[clamp_id];
+ percent = div_u64_rem(percent, POW10(UCLAMP_PERCENT_SHIFT), &rem);
+ seq_printf(sf, "%llu.%0*u\n", percent, UCLAMP_PERCENT_SHIFT, rem);
+}
+
+static int cpu_uclamp_min_show(struct seq_file *sf, void *v)
+{
+ cpu_uclamp_print(sf, UCLAMP_MIN);
+ return 0;
+}
+
+static int cpu_uclamp_max_show(struct seq_file *sf, void *v)
+{
+ cpu_uclamp_print(sf, UCLAMP_MAX);
+ return 0;
+}
+#endif /* CONFIG_UCLAMP_TASK_GROUP */
+
#ifdef CONFIG_FAIR_GROUP_SCHED
static int cpu_shares_write_u64(struct cgroup_subsys_state *css,
struct cftype *cftype, u64 shareval)
@@ -7315,6 +7692,20 @@ static struct cftype cpu_legacy_files[] = {
.write_u64 = cpu_rt_period_write_uint,
},
#endif
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ {
+ .name = "uclamp.min",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .seq_show = cpu_uclamp_min_show,
+ .write = cpu_uclamp_min_write,
+ },
+ {
+ .name = "uclamp.max",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .seq_show = cpu_uclamp_max_show,
+ .write = cpu_uclamp_max_write,
+ },
+#endif
{ } /* Terminate */
};
@@ -7482,6 +7873,20 @@ static struct cftype cpu_files[] = {
.write = cpu_max_write,
},
#endif
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ {
+ .name = "uclamp.min",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .seq_show = cpu_uclamp_min_show,
+ .write = cpu_uclamp_min_write,
+ },
+ {
+ .name = "uclamp.max",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .seq_show = cpu_uclamp_max_show,
+ .write = cpu_uclamp_max_write,
+ },
+#endif
{ } /* terminate */
};
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 636ca6f88c8e..fdce9cfaca05 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -40,6 +40,7 @@ struct sugov_policy {
struct task_struct *thread;
bool work_in_progress;
+ bool limits_changed;
bool need_freq_update;
};
@@ -89,8 +90,11 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
!cpufreq_this_cpu_can_update(sg_policy->policy))
return false;
- if (unlikely(sg_policy->need_freq_update))
+ if (unlikely(sg_policy->limits_changed)) {
+ sg_policy->limits_changed = false;
+ sg_policy->need_freq_update = true;
return true;
+ }
delta_ns = time - sg_policy->last_freq_update_time;
@@ -259,9 +263,9 @@ unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs,
* irq metric. Because IRQ/steal time is hidden from the task clock we
* need to scale the task numbers:
*
- * 1 - irq
- * U' = irq + ------- * U
- * max
+ * max - irq
+ * U' = irq + --------- * U
+ * max
*/
util = scale_irq_capacity(util, irq, max);
util += irq;
@@ -437,7 +441,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
{
if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
- sg_policy->need_freq_update = true;
+ sg_policy->limits_changed = true;
}
static void sugov_update_single(struct update_util_data *hook, u64 time,
@@ -457,7 +461,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
if (!sugov_should_update_freq(sg_policy, time))
return;
- busy = sugov_cpu_is_busy(sg_cpu);
+ /* Limits may have changed, don't skip frequency update */
+ busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
util = sugov_get_util(sg_cpu);
max = sg_cpu->max;
@@ -831,6 +836,7 @@ static int sugov_start(struct cpufreq_policy *policy)
sg_policy->last_freq_update_time = 0;
sg_policy->next_freq = 0;
sg_policy->work_in_progress = false;
+ sg_policy->limits_changed = false;
sg_policy->need_freq_update = false;
sg_policy->cached_raw_freq = 0;
@@ -879,7 +885,7 @@ static void sugov_limits(struct cpufreq_policy *policy)
mutex_unlock(&sg_policy->work_lock);
}
- sg_policy->need_freq_update = true;
+ sg_policy->limits_changed = true;
}
struct cpufreq_governor schedutil_gov = {
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 83a663a34196..2dc48720f189 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -529,6 +529,7 @@ static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq);
static struct rq *dl_task_offline_migration(struct rq *rq, struct task_struct *p)
{
struct rq *later_rq = NULL;
+ struct dl_bw *dl_b;
later_rq = find_lock_later_rq(p, rq);
if (!later_rq) {
@@ -557,6 +558,38 @@ static struct rq *dl_task_offline_migration(struct rq *rq, struct task_struct *p
double_lock_balance(rq, later_rq);
}
+ if (p->dl.dl_non_contending || p->dl.dl_throttled) {
+ /*
+ * Inactive timer is armed (or callback is running, but
+ * waiting for us to release rq locks). In any case, when it
+ * will fire (or continue), it will see running_bw of this
+ * task migrated to later_rq (and correctly handle it).
+ */
+ sub_running_bw(&p->dl, &rq->dl);
+ sub_rq_bw(&p->dl, &rq->dl);
+
+ add_rq_bw(&p->dl, &later_rq->dl);
+ add_running_bw(&p->dl, &later_rq->dl);
+ } else {
+ sub_rq_bw(&p->dl, &rq->dl);
+ add_rq_bw(&p->dl, &later_rq->dl);
+ }
+
+ /*
+ * And we finally need to fixup root_domain(s) bandwidth accounting,
+ * since p is still hanging out in the old (now moved to default) root
+ * domain.
+ */
+ dl_b = &rq->rd->dl_bw;
+ raw_spin_lock(&dl_b->lock);
+ __dl_sub(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span));
+ raw_spin_unlock(&dl_b->lock);
+
+ dl_b = &later_rq->rd->dl_bw;
+ raw_spin_lock(&dl_b->lock);
+ __dl_add(dl_b, p->dl.dl_bw, cpumask_weight(later_rq->rd->span));
+ raw_spin_unlock(&dl_b->lock);
+
set_task_cpu(p, later_rq->cpu);
double_unlock_balance(later_rq, rq);
@@ -1694,12 +1727,20 @@ static void start_hrtick_dl(struct rq *rq, struct task_struct *p)
}
#endif
-static inline void set_next_task(struct rq *rq, struct task_struct *p)
+static void set_next_task_dl(struct rq *rq, struct task_struct *p)
{
p->se.exec_start = rq_clock_task(rq);
/* You can't push away the running task */
dequeue_pushable_dl_task(rq, p);
+
+ if (hrtick_enabled(rq))
+ start_hrtick_dl(rq, p);
+
+ if (rq->curr->sched_class != &dl_sched_class)
+ update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0);
+
+ deadline_queue_push_tasks(rq);
}
static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
@@ -1720,64 +1761,42 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
struct task_struct *p;
struct dl_rq *dl_rq;
- dl_rq = &rq->dl;
+ WARN_ON_ONCE(prev || rf);
- if (need_pull_dl_task(rq, prev)) {
- /*
- * This is OK, because current is on_cpu, which avoids it being
- * picked for load-balance and preemption/IRQs are still
- * disabled avoiding further scheduler activity on it and we're
- * being very careful to re-start the picking loop.
- */
- rq_unpin_lock(rq, rf);
- pull_dl_task(rq);
- rq_repin_lock(rq, rf);
- /*
- * pull_dl_task() can drop (and re-acquire) rq->lock; this
- * means a stop task can slip in, in which case we need to
- * re-start task selection.
- */
- if (rq->stop && task_on_rq_queued(rq->stop))
- return RETRY_TASK;
- }
-
- /*
- * When prev is DL, we may throttle it in put_prev_task().
- * So, we update time before we check for dl_nr_running.
- */
- if (prev->sched_class == &dl_sched_class)
- update_curr_dl(rq);
+ dl_rq = &rq->dl;
if (unlikely(!dl_rq->dl_nr_running))
return NULL;
- put_prev_task(rq, prev);
-
dl_se = pick_next_dl_entity(rq, dl_rq);
BUG_ON(!dl_se);
p = dl_task_of(dl_se);
- set_next_task(rq, p);
-
- if (hrtick_enabled(rq))
- start_hrtick_dl(rq, p);
-
- deadline_queue_push_tasks(rq);
-
- if (rq->curr->sched_class != &dl_sched_class)
- update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0);
+ set_next_task_dl(rq, p);
return p;
}
-static void put_prev_task_dl(struct rq *rq, struct task_struct *p)
+static void put_prev_task_dl(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
{
update_curr_dl(rq);
update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 1);
if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1)
enqueue_pushable_dl_task(rq, p);
+
+ if (rf && !on_dl_rq(&p->dl) && need_pull_dl_task(rq, p)) {
+ /*
+ * This is OK, because current is on_cpu, which avoids it being
+ * picked for load-balance and preemption/IRQs are still
+ * disabled avoiding further scheduler activity on it and we've
+ * not yet started the picking loop.
+ */
+ rq_unpin_lock(rq, rf);
+ pull_dl_task(rq);
+ rq_repin_lock(rq, rf);
+ }
}
/*
@@ -1811,11 +1830,6 @@ static void task_fork_dl(struct task_struct *p)
*/
}
-static void set_curr_task_dl(struct rq *rq)
-{
- set_next_task(rq, rq->curr);
-}
-
#ifdef CONFIG_SMP
/* Only try algorithms three times */
@@ -2088,17 +2102,13 @@ retry:
}
deactivate_task(rq, next_task, 0);
- sub_running_bw(&next_task->dl, &rq->dl);
- sub_rq_bw(&next_task->dl, &rq->dl);
set_task_cpu(next_task, later_rq->cpu);
- add_rq_bw(&next_task->dl, &later_rq->dl);
/*
* Update the later_rq clock here, because the clock is used
* by the cpufreq_update_util() inside __add_running_bw().
*/
update_rq_clock(later_rq);
- add_running_bw(&next_task->dl, &later_rq->dl);
activate_task(later_rq, next_task, ENQUEUE_NOCLOCK);
ret = 1;
@@ -2186,11 +2196,7 @@ static void pull_dl_task(struct rq *this_rq)
resched = true;
deactivate_task(src_rq, p, 0);
- sub_running_bw(&p->dl, &src_rq->dl);
- sub_rq_bw(&p->dl, &src_rq->dl);
set_task_cpu(p, this_cpu);
- add_rq_bw(&p->dl, &this_rq->dl);
- add_running_bw(&p->dl, &this_rq->dl);
activate_task(this_rq, p, 0);
dmin = p->dl.deadline;
@@ -2283,6 +2289,36 @@ void __init init_sched_dl_class(void)
GFP_KERNEL, cpu_to_node(i));
}
+void dl_add_task_root_domain(struct task_struct *p)
+{
+ struct rq_flags rf;
+ struct rq *rq;
+ struct dl_bw *dl_b;
+
+ rq = task_rq_lock(p, &rf);
+ if (!dl_task(p))
+ goto unlock;
+
+ dl_b = &rq->rd->dl_bw;
+ raw_spin_lock(&dl_b->lock);
+
+ __dl_add(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span));
+
+ raw_spin_unlock(&dl_b->lock);
+
+unlock:
+ task_rq_unlock(rq, p, &rf);
+}
+
+void dl_clear_root_domain(struct root_domain *rd)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&rd->dl_bw.lock, flags);
+ rd->dl_bw.total_bw = 0;
+ raw_spin_unlock_irqrestore(&rd->dl_bw.lock, flags);
+}
+
#endif /* CONFIG_SMP */
static void switched_from_dl(struct rq *rq, struct task_struct *p)
@@ -2403,6 +2439,7 @@ const struct sched_class dl_sched_class = {
.pick_next_task = pick_next_task_dl,
.put_prev_task = put_prev_task_dl,
+ .set_next_task = set_next_task_dl,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_dl,
@@ -2413,7 +2450,6 @@ const struct sched_class dl_sched_class = {
.task_woken = task_woken_dl,
#endif
- .set_curr_task = set_curr_task_dl,
.task_tick = task_tick_dl,
.task_fork = task_fork_dl,
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 036be95a87e9..d4bbf68c3161 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -96,12 +96,12 @@ int __weak arch_asym_cpu_priority(int cpu)
}
/*
- * The margin used when comparing utilization with CPU capacity:
- * util * margin < capacity * 1024
+ * The margin used when comparing utilization with CPU capacity.
*
* (default: ~20%)
*/
-static unsigned int capacity_margin = 1280;
+#define fits_capacity(cap, max) ((cap) * 1280 < (max) * 1024)
+
#endif
#ifdef CONFIG_CFS_BANDWIDTH
@@ -1086,6 +1086,21 @@ struct numa_group {
unsigned long faults[0];
};
+/*
+ * For functions that can be called in multiple contexts that permit reading
+ * ->numa_group (see struct task_struct for locking rules).
+ */
+static struct numa_group *deref_task_numa_group(struct task_struct *p)
+{
+ return rcu_dereference_check(p->numa_group, p == current ||
+ (lockdep_is_held(&task_rq(p)->lock) && !READ_ONCE(p->on_cpu)));
+}
+
+static struct numa_group *deref_curr_numa_group(struct task_struct *p)
+{
+ return rcu_dereference_protected(p->numa_group, p == current);
+}
+
static inline unsigned long group_faults_priv(struct numa_group *ng);
static inline unsigned long group_faults_shared(struct numa_group *ng);
@@ -1129,10 +1144,12 @@ static unsigned int task_scan_start(struct task_struct *p)
{
unsigned long smin = task_scan_min(p);
unsigned long period = smin;
+ struct numa_group *ng;
/* Scale the maximum scan period with the amount of shared memory. */
- if (p->numa_group) {
- struct numa_group *ng = p->numa_group;
+ rcu_read_lock();
+ ng = rcu_dereference(p->numa_group);
+ if (ng) {
unsigned long shared = group_faults_shared(ng);
unsigned long private = group_faults_priv(ng);
@@ -1140,6 +1157,7 @@ static unsigned int task_scan_start(struct task_struct *p)
period *= shared + 1;
period /= private + shared + 1;
}
+ rcu_read_unlock();
return max(smin, period);
}
@@ -1148,13 +1166,14 @@ static unsigned int task_scan_max(struct task_struct *p)
{
unsigned long smin = task_scan_min(p);
unsigned long smax;
+ struct numa_group *ng;
/* Watch for min being lower than max due to floor calculations */
smax = sysctl_numa_balancing_scan_period_max / task_nr_scan_windows(p);
/* Scale the maximum scan period with the amount of shared memory. */
- if (p->numa_group) {
- struct numa_group *ng = p->numa_group;
+ ng = deref_curr_numa_group(p);
+ if (ng) {
unsigned long shared = group_faults_shared(ng);
unsigned long private = group_faults_priv(ng);
unsigned long period = smax;
@@ -1169,47 +1188,6 @@ static unsigned int task_scan_max(struct task_struct *p)
return max(smin, smax);
}
-void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
-{
- int mm_users = 0;
- struct mm_struct *mm = p->mm;
-
- if (mm) {
- mm_users = atomic_read(&mm->mm_users);
- if (mm_users == 1) {
- mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
- mm->numa_scan_seq = 0;
- }
- }
- p->node_stamp = 0;
- p->numa_scan_seq = mm ? mm->numa_scan_seq : 0;
- p->numa_scan_period = sysctl_numa_balancing_scan_delay;
- p->numa_work.next = &p->numa_work;
- p->numa_faults = NULL;
- p->numa_group = NULL;
- p->last_task_numa_placement = 0;
- p->last_sum_exec_runtime = 0;
-
- /* New address space, reset the preferred nid */
- if (!(clone_flags & CLONE_VM)) {
- p->numa_preferred_nid = NUMA_NO_NODE;
- return;
- }
-
- /*
- * New thread, keep existing numa_preferred_nid which should be copied
- * already by arch_dup_task_struct but stagger when scans start.
- */
- if (mm) {
- unsigned int delay;
-
- delay = min_t(unsigned int, task_scan_max(current),
- current->numa_scan_period * mm_users * NSEC_PER_MSEC);
- delay += 2 * TICK_NSEC;
- p->node_stamp = delay;
- }
-}
-
static void account_numa_enqueue(struct rq *rq, struct task_struct *p)
{
rq->nr_numa_running += (p->numa_preferred_nid != NUMA_NO_NODE);
@@ -1233,7 +1211,16 @@ static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
pid_t task_numa_group_id(struct task_struct *p)
{
- return p->numa_group ? p->numa_group->gid : 0;
+ struct numa_group *ng;
+ pid_t gid = 0;
+
+ rcu_read_lock();
+ ng = rcu_dereference(p->numa_group);
+ if (ng)
+ gid = ng->gid;
+ rcu_read_unlock();
+
+ return gid;
}
/*
@@ -1258,11 +1245,13 @@ static inline unsigned long task_faults(struct task_struct *p, int nid)
static inline unsigned long group_faults(struct task_struct *p, int nid)
{
- if (!p->numa_group)
+ struct numa_group *ng = deref_task_numa_group(p);
+
+ if (!ng)
return 0;
- return p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
- p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 1)];
+ return ng->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
+ ng->faults[task_faults_idx(NUMA_MEM, nid, 1)];
}
static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
@@ -1400,12 +1389,13 @@ static inline unsigned long task_weight(struct task_struct *p, int nid,
static inline unsigned long group_weight(struct task_struct *p, int nid,
int dist)
{
+ struct numa_group *ng = deref_task_numa_group(p);
unsigned long faults, total_faults;
- if (!p->numa_group)
+ if (!ng)
return 0;
- total_faults = p->numa_group->total_faults;
+ total_faults = ng->total_faults;
if (!total_faults)
return 0;
@@ -1419,7 +1409,7 @@ static inline unsigned long group_weight(struct task_struct *p, int nid,
bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
int src_nid, int dst_cpu)
{
- struct numa_group *ng = p->numa_group;
+ struct numa_group *ng = deref_curr_numa_group(p);
int dst_nid = cpu_to_node(dst_cpu);
int last_cpupid, this_cpupid;
@@ -1600,13 +1590,14 @@ static bool load_too_imbalanced(long src_load, long dst_load,
static void task_numa_compare(struct task_numa_env *env,
long taskimp, long groupimp, bool maymove)
{
+ struct numa_group *cur_ng, *p_ng = deref_curr_numa_group(env->p);
struct rq *dst_rq = cpu_rq(env->dst_cpu);
+ long imp = p_ng ? groupimp : taskimp;
struct task_struct *cur;
long src_load, dst_load;
- long load;
- long imp = env->p->numa_group ? groupimp : taskimp;
- long moveimp = imp;
int dist = env->dist;
+ long moveimp = imp;
+ long load;
if (READ_ONCE(dst_rq->numa_migrate_on))
return;
@@ -1645,21 +1636,22 @@ static void task_numa_compare(struct task_numa_env *env,
* If dst and source tasks are in the same NUMA group, or not
* in any group then look only at task weights.
*/
- if (cur->numa_group == env->p->numa_group) {
+ cur_ng = rcu_dereference(cur->numa_group);
+ if (cur_ng == p_ng) {
imp = taskimp + task_weight(cur, env->src_nid, dist) -
task_weight(cur, env->dst_nid, dist);
/*
* Add some hysteresis to prevent swapping the
* tasks within a group over tiny differences.
*/
- if (cur->numa_group)
+ if (cur_ng)
imp -= imp / 16;
} else {
/*
* Compare the group weights. If a task is all by itself
* (not part of a group), use the task weight instead.
*/
- if (cur->numa_group && env->p->numa_group)
+ if (cur_ng && p_ng)
imp += group_weight(cur, env->src_nid, dist) -
group_weight(cur, env->dst_nid, dist);
else
@@ -1757,11 +1749,12 @@ static int task_numa_migrate(struct task_struct *p)
.best_imp = 0,
.best_cpu = -1,
};
+ unsigned long taskweight, groupweight;
struct sched_domain *sd;
+ long taskimp, groupimp;
+ struct numa_group *ng;
struct rq *best_rq;
- unsigned long taskweight, groupweight;
int nid, ret, dist;
- long taskimp, groupimp;
/*
* Pick the lowest SD_NUMA domain, as that would have the smallest
@@ -1807,7 +1800,8 @@ static int task_numa_migrate(struct task_struct *p)
* multiple NUMA nodes; in order to better consolidate the group,
* we need to check other locations.
*/
- if (env.best_cpu == -1 || (p->numa_group && p->numa_group->active_nodes > 1)) {
+ ng = deref_curr_numa_group(p);
+ if (env.best_cpu == -1 || (ng && ng->active_nodes > 1)) {
for_each_online_node(nid) {
if (nid == env.src_nid || nid == p->numa_preferred_nid)
continue;
@@ -1840,7 +1834,7 @@ static int task_numa_migrate(struct task_struct *p)
* A task that migrated to a second choice node will be better off
* trying for a better one later. Do not set the preferred node here.
*/
- if (p->numa_group) {
+ if (ng) {
if (env.best_cpu == -1)
nid = env.src_nid;
else
@@ -2135,6 +2129,7 @@ static void task_numa_placement(struct task_struct *p)
unsigned long total_faults;
u64 runtime, period;
spinlock_t *group_lock = NULL;
+ struct numa_group *ng;
/*
* The p->mm->numa_scan_seq field gets updated without
@@ -2152,8 +2147,9 @@ static void task_numa_placement(struct task_struct *p)
runtime = numa_get_avg_runtime(p, &period);
/* If the task is part of a group prevent parallel updates to group stats */
- if (p->numa_group) {
- group_lock = &p->numa_group->lock;
+ ng = deref_curr_numa_group(p);
+ if (ng) {
+ group_lock = &ng->lock;
spin_lock_irq(group_lock);
}
@@ -2194,7 +2190,7 @@ static void task_numa_placement(struct task_struct *p)
p->numa_faults[cpu_idx] += f_diff;
faults += p->numa_faults[mem_idx];
p->total_numa_faults += diff;
- if (p->numa_group) {
+ if (ng) {
/*
* safe because we can only change our own group
*
@@ -2202,14 +2198,14 @@ static void task_numa_placement(struct task_struct *p)
* nid and priv in a specific region because it
* is at the beginning of the numa_faults array.
*/
- p->numa_group->faults[mem_idx] += diff;
- p->numa_group->faults_cpu[mem_idx] += f_diff;
- p->numa_group->total_faults += diff;
- group_faults += p->numa_group->faults[mem_idx];
+ ng->faults[mem_idx] += diff;
+ ng->faults_cpu[mem_idx] += f_diff;
+ ng->total_faults += diff;
+ group_faults += ng->faults[mem_idx];
}
}
- if (!p->numa_group) {
+ if (!ng) {
if (faults > max_faults) {
max_faults = faults;
max_nid = nid;
@@ -2220,8 +2216,8 @@ static void task_numa_placement(struct task_struct *p)
}
}
- if (p->numa_group) {
- numa_group_count_active_nodes(p->numa_group);
+ if (ng) {
+ numa_group_count_active_nodes(ng);
spin_unlock_irq(group_lock);
max_nid = preferred_group_nid(p, max_nid);
}
@@ -2255,7 +2251,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
int cpu = cpupid_to_cpu(cpupid);
int i;
- if (unlikely(!p->numa_group)) {
+ if (unlikely(!deref_curr_numa_group(p))) {
unsigned int size = sizeof(struct numa_group) +
4*nr_node_ids*sizeof(unsigned long);
@@ -2291,7 +2287,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
if (!grp)
goto no_join;
- my_grp = p->numa_group;
+ my_grp = deref_curr_numa_group(p);
if (grp == my_grp)
goto no_join;
@@ -2353,13 +2349,24 @@ no_join:
return;
}
-void task_numa_free(struct task_struct *p)
+/*
+ * Get rid of NUMA staticstics associated with a task (either current or dead).
+ * If @final is set, the task is dead and has reached refcount zero, so we can
+ * safely free all relevant data structures. Otherwise, there might be
+ * concurrent reads from places like load balancing and procfs, and we should
+ * reset the data back to default state without freeing ->numa_faults.
+ */
+void task_numa_free(struct task_struct *p, bool final)
{
- struct numa_group *grp = p->numa_group;
- void *numa_faults = p->numa_faults;
+ /* safe: p either is current or is being freed by current */
+ struct numa_group *grp = rcu_dereference_raw(p->numa_group);
+ unsigned long *numa_faults = p->numa_faults;
unsigned long flags;
int i;
+ if (!numa_faults)
+ return;
+
if (grp) {
spin_lock_irqsave(&grp->lock, flags);
for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
@@ -2372,8 +2379,14 @@ void task_numa_free(struct task_struct *p)
put_numa_group(grp);
}
- p->numa_faults = NULL;
- kfree(numa_faults);
+ if (final) {
+ p->numa_faults = NULL;
+ kfree(numa_faults);
+ } else {
+ p->total_numa_faults = 0;
+ for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
+ numa_faults[i] = 0;
+ }
}
/*
@@ -2426,7 +2439,7 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
* actively using should be counted as local. This allows the
* scan rate to slow down when a workload has settled down.
*/
- ng = p->numa_group;
+ ng = deref_curr_numa_group(p);
if (!priv && !local && ng && ng->active_nodes > 1 &&
numa_is_active_node(cpu_node, ng) &&
numa_is_active_node(mem_node, ng))
@@ -2469,7 +2482,7 @@ static void reset_ptenuma_scan(struct task_struct *p)
* The expensive part of numa migration is done from task_work context.
* Triggered from task_tick_numa().
*/
-void task_numa_work(struct callback_head *work)
+static void task_numa_work(struct callback_head *work)
{
unsigned long migrate, next_scan, now = jiffies;
struct task_struct *p = current;
@@ -2482,7 +2495,7 @@ void task_numa_work(struct callback_head *work)
SCHED_WARN_ON(p != container_of(work, struct task_struct, numa_work));
- work->next = work; /* protect against double add */
+ work->next = work;
/*
* Who cares about NUMA placement when they're dying.
*
@@ -2611,6 +2624,50 @@ out:
}
}
+void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
+{
+ int mm_users = 0;
+ struct mm_struct *mm = p->mm;
+
+ if (mm) {
+ mm_users = atomic_read(&mm->mm_users);
+ if (mm_users == 1) {
+ mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
+ mm->numa_scan_seq = 0;
+ }
+ }
+ p->node_stamp = 0;
+ p->numa_scan_seq = mm ? mm->numa_scan_seq : 0;
+ p->numa_scan_period = sysctl_numa_balancing_scan_delay;
+ /* Protect against double add, see task_tick_numa and task_numa_work */
+ p->numa_work.next = &p->numa_work;
+ p->numa_faults = NULL;
+ RCU_INIT_POINTER(p->numa_group, NULL);
+ p->last_task_numa_placement = 0;
+ p->last_sum_exec_runtime = 0;
+
+ init_task_work(&p->numa_work, task_numa_work);
+
+ /* New address space, reset the preferred nid */
+ if (!(clone_flags & CLONE_VM)) {
+ p->numa_preferred_nid = NUMA_NO_NODE;
+ return;
+ }
+
+ /*
+ * New thread, keep existing numa_preferred_nid which should be copied
+ * already by arch_dup_task_struct but stagger when scans start.
+ */
+ if (mm) {
+ unsigned int delay;
+
+ delay = min_t(unsigned int, task_scan_max(current),
+ current->numa_scan_period * mm_users * NSEC_PER_MSEC);
+ delay += 2 * TICK_NSEC;
+ p->node_stamp = delay;
+ }
+}
+
/*
* Drive the periodic memory faults..
*/
@@ -2639,10 +2696,8 @@ static void task_tick_numa(struct rq *rq, struct task_struct *curr)
curr->numa_scan_period = task_scan_start(curr);
curr->node_stamp += period;
- if (!time_before(jiffies, curr->mm->numa_next_scan)) {
- init_task_work(work, task_numa_work); /* TODO: move this into sched_fork() */
+ if (!time_before(jiffies, curr->mm->numa_next_scan))
task_work_add(curr, work, true);
- }
}
}
@@ -3635,8 +3690,6 @@ static inline unsigned long cfs_rq_load_avg(struct cfs_rq *cfs_rq)
return cfs_rq->avg.load_avg;
}
-static int idle_balance(struct rq *this_rq, struct rq_flags *rf);
-
static inline unsigned long task_util(struct task_struct *p)
{
return READ_ONCE(p->se.avg.util_avg);
@@ -3753,7 +3806,7 @@ util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep)
static inline int task_fits_capacity(struct task_struct *p, long capacity)
{
- return capacity * 1024 > task_util_est(p) * capacity_margin;
+ return fits_capacity(task_util_est(p), capacity);
}
static inline void update_misfit_status(struct task_struct *p, struct rq *rq)
@@ -4316,8 +4369,6 @@ void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
now = sched_clock_cpu(smp_processor_id());
cfs_b->runtime = cfs_b->quota;
- cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period);
- cfs_b->expires_seq++;
}
static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
@@ -4339,8 +4390,7 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
{
struct task_group *tg = cfs_rq->tg;
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(tg);
- u64 amount = 0, min_amount, expires;
- int expires_seq;
+ u64 amount = 0, min_amount;
/* note: this is a positive sum as runtime_remaining <= 0 */
min_amount = sched_cfs_bandwidth_slice() - cfs_rq->runtime_remaining;
@@ -4357,65 +4407,23 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
cfs_b->idle = 0;
}
}
- expires_seq = cfs_b->expires_seq;
- expires = cfs_b->runtime_expires;
raw_spin_unlock(&cfs_b->lock);
cfs_rq->runtime_remaining += amount;
- /*
- * we may have advanced our local expiration to account for allowed
- * spread between our sched_clock and the one on which runtime was
- * issued.
- */
- if (cfs_rq->expires_seq != expires_seq) {
- cfs_rq->expires_seq = expires_seq;
- cfs_rq->runtime_expires = expires;
- }
return cfs_rq->runtime_remaining > 0;
}
-/*
- * Note: This depends on the synchronization provided by sched_clock and the
- * fact that rq->clock snapshots this value.
- */
-static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
-{
- struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
-
- /* if the deadline is ahead of our clock, nothing to do */
- if (likely((s64)(rq_clock(rq_of(cfs_rq)) - cfs_rq->runtime_expires) < 0))
- return;
-
- if (cfs_rq->runtime_remaining < 0)
- return;
-
- /*
- * If the local deadline has passed we have to consider the
- * possibility that our sched_clock is 'fast' and the global deadline
- * has not truly expired.
- *
- * Fortunately we can check determine whether this the case by checking
- * whether the global deadline(cfs_b->expires_seq) has advanced.
- */
- if (cfs_rq->expires_seq == cfs_b->expires_seq) {
- /* extend local deadline, drift is bounded above by 2 ticks */
- cfs_rq->runtime_expires += TICK_NSEC;
- } else {
- /* global deadline is ahead, expiration has passed */
- cfs_rq->runtime_remaining = 0;
- }
-}
-
static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
{
/* dock delta_exec before expiring quota (as it could span periods) */
cfs_rq->runtime_remaining -= delta_exec;
- expire_cfs_rq_runtime(cfs_rq);
if (likely(cfs_rq->runtime_remaining > 0))
return;
+ if (cfs_rq->throttled)
+ return;
/*
* if we're unable to extend our runtime we resched so that the active
* hierarchy can be throttled
@@ -4500,7 +4508,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
struct rq *rq = rq_of(cfs_rq);
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
struct sched_entity *se;
- long task_delta, dequeue = 1;
+ long task_delta, idle_task_delta, dequeue = 1;
bool empty;
se = cfs_rq->tg->se[cpu_of(rq_of(cfs_rq))];
@@ -4511,6 +4519,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
rcu_read_unlock();
task_delta = cfs_rq->h_nr_running;
+ idle_task_delta = cfs_rq->idle_h_nr_running;
for_each_sched_entity(se) {
struct cfs_rq *qcfs_rq = cfs_rq_of(se);
/* throttled entity or throttle-on-deactivate */
@@ -4520,6 +4529,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
if (dequeue)
dequeue_entity(qcfs_rq, se, DEQUEUE_SLEEP);
qcfs_rq->h_nr_running -= task_delta;
+ qcfs_rq->idle_h_nr_running -= idle_task_delta;
if (qcfs_rq->load.weight)
dequeue = 0;
@@ -4559,7 +4569,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
struct sched_entity *se;
int enqueue = 1;
- long task_delta;
+ long task_delta, idle_task_delta;
se = cfs_rq->tg->se[cpu_of(rq)];
@@ -4579,6 +4589,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
return;
task_delta = cfs_rq->h_nr_running;
+ idle_task_delta = cfs_rq->idle_h_nr_running;
for_each_sched_entity(se) {
if (se->on_rq)
enqueue = 0;
@@ -4587,6 +4598,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
if (enqueue)
enqueue_entity(cfs_rq, se, ENQUEUE_WAKEUP);
cfs_rq->h_nr_running += task_delta;
+ cfs_rq->idle_h_nr_running += idle_task_delta;
if (cfs_rq_throttled(cfs_rq))
break;
@@ -4602,8 +4614,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
resched_curr(rq);
}
-static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b,
- u64 remaining, u64 expires)
+static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, u64 remaining)
{
struct cfs_rq *cfs_rq;
u64 runtime;
@@ -4619,13 +4630,15 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b,
if (!cfs_rq_throttled(cfs_rq))
goto next;
+ /* By the above check, this should never be true */
+ SCHED_WARN_ON(cfs_rq->runtime_remaining > 0);
+
runtime = -cfs_rq->runtime_remaining + 1;
if (runtime > remaining)
runtime = remaining;
remaining -= runtime;
cfs_rq->runtime_remaining += runtime;
- cfs_rq->runtime_expires = expires;
/* we check whether we're throttled above */
if (cfs_rq->runtime_remaining > 0)
@@ -4650,7 +4663,7 @@ next:
*/
static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, unsigned long flags)
{
- u64 runtime, runtime_expires;
+ u64 runtime;
int throttled;
/* no need to continue the timer with no bandwidth constraint */
@@ -4678,8 +4691,6 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u
/* account preceding periods in which throttling occurred */
cfs_b->nr_throttled += overrun;
- runtime_expires = cfs_b->runtime_expires;
-
/*
* This check is repeated as we are holding onto the new bandwidth while
* we unthrottle. This can potentially race with an unthrottled group
@@ -4692,8 +4703,7 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u
cfs_b->distribute_running = 1;
raw_spin_unlock_irqrestore(&cfs_b->lock, flags);
/* we can't nest cfs_b->lock while distributing bandwidth */
- runtime = distribute_cfs_runtime(cfs_b, runtime,
- runtime_expires);
+ runtime = distribute_cfs_runtime(cfs_b, runtime);
raw_spin_lock_irqsave(&cfs_b->lock, flags);
cfs_b->distribute_running = 0;
@@ -4775,8 +4785,7 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq)
return;
raw_spin_lock(&cfs_b->lock);
- if (cfs_b->quota != RUNTIME_INF &&
- cfs_rq->runtime_expires == cfs_b->runtime_expires) {
+ if (cfs_b->quota != RUNTIME_INF) {
cfs_b->runtime += slack_runtime;
/* we are under rq->lock, defer unthrottling using a timer */
@@ -4809,7 +4818,6 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b)
{
u64 runtime = 0, slice = sched_cfs_bandwidth_slice();
unsigned long flags;
- u64 expires;
/* confirm we're still not at a refresh boundary */
raw_spin_lock_irqsave(&cfs_b->lock, flags);
@@ -4827,7 +4835,6 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b)
if (cfs_b->quota != RUNTIME_INF && cfs_b->runtime > slice)
runtime = cfs_b->runtime;
- expires = cfs_b->runtime_expires;
if (runtime)
cfs_b->distribute_running = 1;
@@ -4836,11 +4843,10 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b)
if (!runtime)
return;
- runtime = distribute_cfs_runtime(cfs_b, runtime, expires);
+ runtime = distribute_cfs_runtime(cfs_b, runtime);
raw_spin_lock_irqsave(&cfs_b->lock, flags);
- if (expires == cfs_b->runtime_expires)
- lsub_positive(&cfs_b->runtime, runtime);
+ lsub_positive(&cfs_b->runtime, runtime);
cfs_b->distribute_running = 0;
raw_spin_unlock_irqrestore(&cfs_b->lock, flags);
}
@@ -4997,8 +5003,6 @@ void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
cfs_b->period_active = 1;
overrun = hrtimer_forward_now(&cfs_b->period_timer, cfs_b->period);
- cfs_b->runtime_expires += (overrun + 1) * ktime_to_ns(cfs_b->period);
- cfs_b->expires_seq++;
hrtimer_start_expires(&cfs_b->period_timer, HRTIMER_MODE_ABS_PINNED);
}
@@ -5176,7 +5180,7 @@ static inline unsigned long cpu_util(int cpu);
static inline bool cpu_overutilized(int cpu)
{
- return (capacity_of(cpu) * 1024) < (cpu_util(cpu) * capacity_margin);
+ return !fits_capacity(cpu_util(cpu), capacity_of(cpu));
}
static inline void update_overutilized_status(struct rq *rq)
@@ -5200,6 +5204,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
{
struct cfs_rq *cfs_rq;
struct sched_entity *se = &p->se;
+ int idle_h_nr_running = task_has_idle_policy(p);
/*
* The code below (indirectly) updates schedutil which looks at
@@ -5232,6 +5237,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (cfs_rq_throttled(cfs_rq))
break;
cfs_rq->h_nr_running++;
+ cfs_rq->idle_h_nr_running += idle_h_nr_running;
flags = ENQUEUE_WAKEUP;
}
@@ -5239,6 +5245,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
for_each_sched_entity(se) {
cfs_rq = cfs_rq_of(se);
cfs_rq->h_nr_running++;
+ cfs_rq->idle_h_nr_running += idle_h_nr_running;
if (cfs_rq_throttled(cfs_rq))
break;
@@ -5300,6 +5307,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
struct cfs_rq *cfs_rq;
struct sched_entity *se = &p->se;
int task_sleep = flags & DEQUEUE_SLEEP;
+ int idle_h_nr_running = task_has_idle_policy(p);
for_each_sched_entity(se) {
cfs_rq = cfs_rq_of(se);
@@ -5314,6 +5322,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (cfs_rq_throttled(cfs_rq))
break;
cfs_rq->h_nr_running--;
+ cfs_rq->idle_h_nr_running -= idle_h_nr_running;
/* Don't dequeue parent if it has other entities besides us */
if (cfs_rq->load.weight) {
@@ -5333,6 +5342,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
for_each_sched_entity(se) {
cfs_rq = cfs_rq_of(se);
cfs_rq->h_nr_running--;
+ cfs_rq->idle_h_nr_running -= idle_h_nr_running;
if (cfs_rq_throttled(cfs_rq))
break;
@@ -5366,6 +5376,15 @@ static struct {
#endif /* CONFIG_NO_HZ_COMMON */
+/* CPU only has SCHED_IDLE tasks enqueued */
+static int sched_idle_cpu(int cpu)
+{
+ struct rq *rq = cpu_rq(cpu);
+
+ return unlikely(rq->nr_running == rq->cfs.idle_h_nr_running &&
+ rq->nr_running);
+}
+
static unsigned long cpu_runnable_load(struct rq *rq)
{
return cfs_rq_runnable_load_avg(&rq->cfs);
@@ -5688,7 +5707,7 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
unsigned int min_exit_latency = UINT_MAX;
u64 latest_idle_timestamp = 0;
int least_loaded_cpu = this_cpu;
- int shallowest_idle_cpu = -1;
+ int shallowest_idle_cpu = -1, si_cpu = -1;
int i;
/* Check if we have any choice: */
@@ -5719,7 +5738,12 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
latest_idle_timestamp = rq->idle_stamp;
shallowest_idle_cpu = i;
}
- } else if (shallowest_idle_cpu == -1) {
+ } else if (shallowest_idle_cpu == -1 && si_cpu == -1) {
+ if (sched_idle_cpu(i)) {
+ si_cpu = i;
+ continue;
+ }
+
load = cpu_runnable_load(cpu_rq(i));
if (load < min_load) {
min_load = load;
@@ -5728,7 +5752,11 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
}
}
- return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
+ if (shallowest_idle_cpu != -1)
+ return shallowest_idle_cpu;
+ if (si_cpu != -1)
+ return si_cpu;
+ return least_loaded_cpu;
}
static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p,
@@ -5881,7 +5909,7 @@ static int select_idle_core(struct task_struct *p, struct sched_domain *sd, int
*/
static int select_idle_smt(struct task_struct *p, int target)
{
- int cpu;
+ int cpu, si_cpu = -1;
if (!static_branch_likely(&sched_smt_present))
return -1;
@@ -5891,9 +5919,11 @@ static int select_idle_smt(struct task_struct *p, int target)
continue;
if (available_idle_cpu(cpu))
return cpu;
+ if (si_cpu == -1 && sched_idle_cpu(cpu))
+ si_cpu = cpu;
}
- return -1;
+ return si_cpu;
}
#else /* CONFIG_SCHED_SMT */
@@ -5921,8 +5951,8 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
u64 avg_cost, avg_idle;
u64 time, cost;
s64 delta;
- int cpu, nr = INT_MAX;
int this = smp_processor_id();
+ int cpu, nr = INT_MAX, si_cpu = -1;
this_sd = rcu_dereference(*this_cpu_ptr(&sd_llc));
if (!this_sd)
@@ -5950,11 +5980,13 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
for_each_cpu_wrap(cpu, sched_domain_span(sd), target) {
if (!--nr)
- return -1;
+ return si_cpu;
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
continue;
if (available_idle_cpu(cpu))
break;
+ if (si_cpu == -1 && sched_idle_cpu(cpu))
+ si_cpu = cpu;
}
time = cpu_clock(this) - time;
@@ -5973,13 +6005,14 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
struct sched_domain *sd;
int i, recent_used_cpu;
- if (available_idle_cpu(target))
+ if (available_idle_cpu(target) || sched_idle_cpu(target))
return target;
/*
* If the previous CPU is cache affine and idle, don't be stupid:
*/
- if (prev != target && cpus_share_cache(prev, target) && available_idle_cpu(prev))
+ if (prev != target && cpus_share_cache(prev, target) &&
+ (available_idle_cpu(prev) || sched_idle_cpu(prev)))
return prev;
/* Check a recently used CPU as a potential idle candidate: */
@@ -5987,7 +6020,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
if (recent_used_cpu != prev &&
recent_used_cpu != target &&
cpus_share_cache(recent_used_cpu, target) &&
- available_idle_cpu(recent_used_cpu) &&
+ (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) {
/*
* Replace recent_used_cpu with prev as it is a potential
@@ -6223,69 +6256,55 @@ static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu)
}
/*
- * compute_energy(): Estimates the energy that would be consumed if @p was
+ * compute_energy(): Estimates the energy that @pd would consume if @p was
* migrated to @dst_cpu. compute_energy() predicts what will be the utilization
- * landscape of the * CPUs after the task migration, and uses the Energy Model
+ * landscape of @pd's CPUs after the task migration, and uses the Energy Model
* to compute what would be the energy if we decided to actually migrate that
* task.
*/
static long
compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
{
- unsigned int max_util, util_cfs, cpu_util, cpu_cap;
- unsigned long sum_util, energy = 0;
- struct task_struct *tsk;
+ struct cpumask *pd_mask = perf_domain_span(pd);
+ unsigned long cpu_cap = arch_scale_cpu_capacity(cpumask_first(pd_mask));
+ unsigned long max_util = 0, sum_util = 0;
int cpu;
- for (; pd; pd = pd->next) {
- struct cpumask *pd_mask = perf_domain_span(pd);
+ /*
+ * The capacity state of CPUs of the current rd can be driven by CPUs
+ * of another rd if they belong to the same pd. So, account for the
+ * utilization of these CPUs too by masking pd with cpu_online_mask
+ * instead of the rd span.
+ *
+ * If an entire pd is outside of the current rd, it will not appear in
+ * its pd list and will not be accounted by compute_energy().
+ */
+ for_each_cpu_and(cpu, pd_mask, cpu_online_mask) {
+ unsigned long cpu_util, util_cfs = cpu_util_next(cpu, p, dst_cpu);
+ struct task_struct *tsk = cpu == dst_cpu ? p : NULL;
/*
- * The energy model mandates all the CPUs of a performance
- * domain have the same capacity.
+ * Busy time computation: utilization clamping is not
+ * required since the ratio (sum_util / cpu_capacity)
+ * is already enough to scale the EM reported power
+ * consumption at the (eventually clamped) cpu_capacity.
*/
- cpu_cap = arch_scale_cpu_capacity(cpumask_first(pd_mask));
- max_util = sum_util = 0;
+ sum_util += schedutil_cpu_util(cpu, util_cfs, cpu_cap,
+ ENERGY_UTIL, NULL);
/*
- * The capacity state of CPUs of the current rd can be driven by
- * CPUs of another rd if they belong to the same performance
- * domain. So, account for the utilization of these CPUs too
- * by masking pd with cpu_online_mask instead of the rd span.
- *
- * If an entire performance domain is outside of the current rd,
- * it will not appear in its pd list and will not be accounted
- * by compute_energy().
+ * Performance domain frequency: utilization clamping
+ * must be considered since it affects the selection
+ * of the performance domain frequency.
+ * NOTE: in case RT tasks are running, by default the
+ * FREQUENCY_UTIL's utilization can be max OPP.
*/
- for_each_cpu_and(cpu, pd_mask, cpu_online_mask) {
- util_cfs = cpu_util_next(cpu, p, dst_cpu);
-
- /*
- * Busy time computation: utilization clamping is not
- * required since the ratio (sum_util / cpu_capacity)
- * is already enough to scale the EM reported power
- * consumption at the (eventually clamped) cpu_capacity.
- */
- sum_util += schedutil_cpu_util(cpu, util_cfs, cpu_cap,
- ENERGY_UTIL, NULL);
-
- /*
- * Performance domain frequency: utilization clamping
- * must be considered since it affects the selection
- * of the performance domain frequency.
- * NOTE: in case RT tasks are running, by default the
- * FREQUENCY_UTIL's utilization can be max OPP.
- */
- tsk = cpu == dst_cpu ? p : NULL;
- cpu_util = schedutil_cpu_util(cpu, util_cfs, cpu_cap,
- FREQUENCY_UTIL, tsk);
- max_util = max(max_util, cpu_util);
- }
-
- energy += em_pd_energy(pd->em_pd, max_util, sum_util);
+ cpu_util = schedutil_cpu_util(cpu, util_cfs, cpu_cap,
+ FREQUENCY_UTIL, tsk);
+ max_util = max(max_util, cpu_util);
}
- return energy;
+ return em_pd_energy(pd->em_pd, max_util, sum_util);
}
/*
@@ -6327,21 +6346,19 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* other use-cases too. So, until someone finds a better way to solve this,
* let's keep things simple by re-using the existing slow path.
*/
-
static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
{
- unsigned long prev_energy = ULONG_MAX, best_energy = ULONG_MAX;
+ unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX;
struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
+ unsigned long cpu_cap, util, base_energy = 0;
int cpu, best_energy_cpu = prev_cpu;
- struct perf_domain *head, *pd;
- unsigned long cpu_cap, util;
struct sched_domain *sd;
+ struct perf_domain *pd;
rcu_read_lock();
pd = rcu_dereference(rd->pd);
if (!pd || READ_ONCE(rd->overutilized))
goto fail;
- head = pd;
/*
* Energy-aware wake-up happens on the lowest sched_domain starting
@@ -6358,9 +6375,14 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
goto unlock;
for (; pd; pd = pd->next) {
- unsigned long cur_energy, spare_cap, max_spare_cap = 0;
+ unsigned long cur_delta, spare_cap, max_spare_cap = 0;
+ unsigned long base_energy_pd;
int max_spare_cap_cpu = -1;
+ /* Compute the 'base' energy of the pd, without @p */
+ base_energy_pd = compute_energy(p, -1, pd);
+ base_energy += base_energy_pd;
+
for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) {
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
continue;
@@ -6368,14 +6390,14 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
/* Skip CPUs that will be overutilized. */
util = cpu_util_next(cpu, p, cpu);
cpu_cap = capacity_of(cpu);
- if (cpu_cap * 1024 < util * capacity_margin)
+ if (!fits_capacity(util, cpu_cap))
continue;
/* Always use prev_cpu as a candidate. */
if (cpu == prev_cpu) {
- prev_energy = compute_energy(p, prev_cpu, head);
- best_energy = min(best_energy, prev_energy);
- continue;
+ prev_delta = compute_energy(p, prev_cpu, pd);
+ prev_delta -= base_energy_pd;
+ best_delta = min(best_delta, prev_delta);
}
/*
@@ -6391,9 +6413,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
/* Evaluate the energy impact of using this CPU. */
if (max_spare_cap_cpu >= 0) {
- cur_energy = compute_energy(p, max_spare_cap_cpu, head);
- if (cur_energy < best_energy) {
- best_energy = cur_energy;
+ cur_delta = compute_energy(p, max_spare_cap_cpu, pd);
+ cur_delta -= base_energy_pd;
+ if (cur_delta < best_delta) {
+ best_delta = cur_delta;
best_energy_cpu = max_spare_cap_cpu;
}
}
@@ -6405,10 +6428,10 @@ unlock:
* Pick the best CPU if prev_cpu cannot be used, or if it saves at
* least 6% of the energy used by prev_cpu.
*/
- if (prev_energy == ULONG_MAX)
+ if (prev_delta == ULONG_MAX)
return best_energy_cpu;
- if ((prev_energy - best_energy) > (prev_energy >> 4))
+ if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
return best_energy_cpu;
return prev_cpu;
@@ -6742,7 +6765,7 @@ again:
goto idle;
#ifdef CONFIG_FAIR_GROUP_SCHED
- if (prev->sched_class != &fair_sched_class)
+ if (!prev || prev->sched_class != &fair_sched_class)
goto simple;
/*
@@ -6819,8 +6842,8 @@ again:
goto done;
simple:
#endif
-
- put_prev_task(rq, prev);
+ if (prev)
+ put_prev_task(rq, prev);
do {
se = pick_next_entity(cfs_rq, NULL);
@@ -6848,11 +6871,13 @@ done: __maybe_unused;
return p;
idle:
- update_misfit_status(NULL, rq);
- new_tasks = idle_balance(rq, rf);
+ if (!rf)
+ return NULL;
+
+ new_tasks = newidle_balance(rq, rf);
/*
- * Because idle_balance() releases (and re-acquires) rq->lock, it is
+ * Because newidle_balance() releases (and re-acquires) rq->lock, it is
* possible for any higher priority task to appear. In that case we
* must re-start the pick_next_entity() loop.
*/
@@ -6874,7 +6899,7 @@ idle:
/*
* Account for a descheduled task:
*/
-static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
struct sched_entity *se = &prev->se;
struct cfs_rq *cfs_rq;
@@ -7376,7 +7401,7 @@ static int detach_tasks(struct lb_env *env)
detached++;
env->imbalance -= load;
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
/*
* NEWIDLE balancing is a source of latency, so preemptible
* kernels will stop after the first task is detached to minimize
@@ -7923,8 +7948,7 @@ group_is_overloaded(struct lb_env *env, struct sg_lb_stats *sgs)
static inline bool
group_smaller_min_cpu_capacity(struct sched_group *sg, struct sched_group *ref)
{
- return sg->sgc->min_capacity * capacity_margin <
- ref->sgc->min_capacity * 1024;
+ return fits_capacity(sg->sgc->min_capacity, ref->sgc->min_capacity);
}
/*
@@ -7934,8 +7958,7 @@ group_smaller_min_cpu_capacity(struct sched_group *sg, struct sched_group *ref)
static inline bool
group_smaller_max_cpu_capacity(struct sched_group *sg, struct sched_group *ref)
{
- return sg->sgc->max_capacity * capacity_margin <
- ref->sgc->max_capacity * 1024;
+ return fits_capacity(sg->sgc->max_capacity, ref->sgc->max_capacity);
}
static inline enum
@@ -8993,9 +9016,10 @@ more_balance:
out_balanced:
/*
* We reach balance although we may have faced some affinity
- * constraints. Clear the imbalance flag if it was set.
+ * constraints. Clear the imbalance flag only if other tasks got
+ * a chance to move and fix the imbalance.
*/
- if (sd_parent) {
+ if (sd_parent && !(env.flags & LBF_ALL_PINNED)) {
int *group_imbalance = &sd_parent->groups->sgc->imbalance;
if (*group_imbalance)
@@ -9016,10 +9040,10 @@ out_one_pinned:
ld_moved = 0;
/*
- * idle_balance() disregards balance intervals, so we could repeatedly
- * reach this code, which would lead to balance_interval skyrocketting
- * in a short amount of time. Skip the balance_interval increase logic
- * to avoid that.
+ * newidle_balance() disregards balance intervals, so we could
+ * repeatedly reach this code, which would lead to balance_interval
+ * skyrocketting in a short amount of time. Skip the balance_interval
+ * increase logic to avoid that.
*/
if (env.idle == CPU_NEWLY_IDLE)
goto out;
@@ -9729,7 +9753,7 @@ static inline void nohz_newidle_balance(struct rq *this_rq) { }
* idle_balance is called by schedule() if this_cpu is about to become
* idle. Attempts to pull tasks from other CPUs.
*/
-static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
+int newidle_balance(struct rq *this_rq, struct rq_flags *rf)
{
unsigned long next_balance = jiffies + HZ;
int this_cpu = this_rq->cpu;
@@ -9737,6 +9761,7 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
int pulled_task = 0;
u64 curr_cost = 0;
+ update_misfit_status(NULL, this_rq);
/*
* We must set idle_stamp _before_ calling idle_balance(), such that we
* measure the duration of idle_balance() as idle time.
@@ -10121,9 +10146,19 @@ static void switched_to_fair(struct rq *rq, struct task_struct *p)
* This routine is mostly called to set cfs_rq->curr field when a task
* migrates between groups/classes.
*/
-static void set_curr_task_fair(struct rq *rq)
+static void set_next_task_fair(struct rq *rq, struct task_struct *p)
{
- struct sched_entity *se = &rq->curr->se;
+ struct sched_entity *se = &p->se;
+
+#ifdef CONFIG_SMP
+ if (task_on_rq_queued(p)) {
+ /*
+ * Move the next running task to the front of the list, so our
+ * cfs_tasks list becomes MRU one.
+ */
+ list_move(&se->group_node, &rq->cfs_tasks);
+ }
+#endif
for_each_sched_entity(se) {
struct cfs_rq *cfs_rq = cfs_rq_of(se);
@@ -10241,18 +10276,18 @@ err:
void online_fair_sched_group(struct task_group *tg)
{
struct sched_entity *se;
+ struct rq_flags rf;
struct rq *rq;
int i;
for_each_possible_cpu(i) {
rq = cpu_rq(i);
se = tg->se[i];
-
- raw_spin_lock_irq(&rq->lock);
+ rq_lock_irq(rq, &rf);
update_rq_clock(rq);
attach_entity_cfs_rq(se);
sync_throttle(tg, i);
- raw_spin_unlock_irq(&rq->lock);
+ rq_unlock_irq(rq, &rf);
}
}
@@ -10394,7 +10429,9 @@ const struct sched_class fair_sched_class = {
.check_preempt_curr = check_preempt_wakeup,
.pick_next_task = pick_next_task_fair,
+
.put_prev_task = put_prev_task_fair,
+ .set_next_task = set_next_task_fair,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_fair,
@@ -10407,7 +10444,6 @@ const struct sched_class fair_sched_class = {
.set_cpus_allowed = set_cpus_allowed_common,
#endif
- .set_curr_task = set_curr_task_fair,
.task_tick = task_tick_fair,
.task_fork = task_fork_fair,
@@ -10444,18 +10480,22 @@ void show_numa_stats(struct task_struct *p, struct seq_file *m)
{
int node;
unsigned long tsf = 0, tpf = 0, gsf = 0, gpf = 0;
+ struct numa_group *ng;
+ rcu_read_lock();
+ ng = rcu_dereference(p->numa_group);
for_each_online_node(node) {
if (p->numa_faults) {
tsf = p->numa_faults[task_faults_idx(NUMA_MEM, node, 0)];
tpf = p->numa_faults[task_faults_idx(NUMA_MEM, node, 1)];
}
- if (p->numa_group) {
- gsf = p->numa_group->faults[task_faults_idx(NUMA_MEM, node, 0)],
- gpf = p->numa_group->faults[task_faults_idx(NUMA_MEM, node, 1)];
+ if (ng) {
+ gsf = ng->faults[task_faults_idx(NUMA_MEM, node, 0)],
+ gpf = ng->faults[task_faults_idx(NUMA_MEM, node, 1)];
}
print_numa_stats(m, node, tsf, tpf, gsf, gpf);
}
+ rcu_read_unlock();
}
#endif /* CONFIG_NUMA_BALANCING */
#endif /* CONFIG_SCHED_DEBUG */
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 80940939b733..8bfeb6395bdd 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -241,13 +241,14 @@ static void do_idle(void)
check_pgt_cache();
rmb();
+ local_irq_disable();
+
if (cpu_is_offline(cpu)) {
- tick_nohz_idle_stop_tick_protected();
+ tick_nohz_idle_stop_tick();
cpuhp_report_idle_dead();
arch_cpu_idle_dead();
}
- local_irq_disable();
arch_cpu_idle_enter();
/*
@@ -374,14 +375,27 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
resched_curr(rq);
}
-static struct task_struct *
-pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+{
+}
+
+static void set_next_task_idle(struct rq *rq, struct task_struct *next)
{
- put_prev_task(rq, prev);
update_idle_core(rq);
schedstat_inc(rq->sched_goidle);
+}
+
+static struct task_struct *
+pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+{
+ struct task_struct *next = rq->idle;
- return rq->idle;
+ if (prev)
+ put_prev_task(rq, prev);
+
+ set_next_task_idle(rq, next);
+
+ return next;
}
/*
@@ -397,10 +411,6 @@ dequeue_task_idle(struct rq *rq, struct task_struct *p, int flags)
raw_spin_lock_irq(&rq->lock);
}
-static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
-{
-}
-
/*
* scheduler tick hitting a task of our scheduling class.
*
@@ -413,10 +423,6 @@ static void task_tick_idle(struct rq *rq, struct task_struct *curr, int queued)
{
}
-static void set_curr_task_idle(struct rq *rq)
-{
-}
-
static void switched_to_idle(struct rq *rq, struct task_struct *p)
{
BUG();
@@ -451,13 +457,13 @@ const struct sched_class idle_sched_class = {
.pick_next_task = pick_next_task_idle,
.put_prev_task = put_prev_task_idle,
+ .set_next_task = set_next_task_idle,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_idle,
.set_cpus_allowed = set_cpus_allowed_common,
#endif
- .set_curr_task = set_curr_task_idle,
.task_tick = task_tick_idle,
.get_rr_interval = get_rr_interval_idle,
diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
index ccb28085b114..9fcb2a695a41 100644
--- a/kernel/sched/isolation.c
+++ b/kernel/sched/isolation.c
@@ -22,9 +22,17 @@ EXPORT_SYMBOL_GPL(housekeeping_enabled);
int housekeeping_any_cpu(enum hk_flags flags)
{
- if (static_branch_unlikely(&housekeeping_overridden))
- if (housekeeping_flags & flags)
+ int cpu;
+
+ if (static_branch_unlikely(&housekeeping_overridden)) {
+ if (housekeeping_flags & flags) {
+ cpu = sched_numa_find_closest(housekeeping_mask, smp_processor_id());
+ if (cpu < nr_cpu_ids)
+ return cpu;
+
return cpumask_any_and(housekeeping_mask, cpu_online_mask);
+ }
+ }
return smp_processor_id();
}
EXPORT_SYMBOL_GPL(housekeeping_any_cpu);
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
index 7acc632c3b82..517e3719027e 100644
--- a/kernel/sched/psi.c
+++ b/kernel/sched/psi.c
@@ -1051,7 +1051,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
if (!rcu_access_pointer(group->poll_kworker)) {
struct sched_param param = {
- .sched_priority = MAX_RT_PRIO - 1,
+ .sched_priority = 1,
};
struct kthread_worker *kworker;
@@ -1061,7 +1061,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
mutex_unlock(&group->trigger_lock);
return ERR_CAST(kworker);
}
- sched_setscheduler(kworker->task, SCHED_FIFO, &param);
+ sched_setscheduler_nocheck(kworker->task, SCHED_FIFO, &param);
kthread_init_delayed_work(&group->poll_work,
psi_poll_work);
rcu_assign_pointer(group->poll_kworker, kworker);
@@ -1131,7 +1131,15 @@ static void psi_trigger_destroy(struct kref *ref)
* deadlock while waiting for psi_poll_work to acquire trigger_lock
*/
if (kworker_to_destroy) {
+ /*
+ * After the RCU grace period has expired, the worker
+ * can no longer be found through group->poll_kworker.
+ * But it might have been already scheduled before
+ * that - deschedule it cleanly before destroying it.
+ */
kthread_cancel_delayed_work_sync(&group->poll_work);
+ atomic_set(&group->poll_scheduled, 0);
+
kthread_destroy_worker(kworker_to_destroy);
}
kfree(t);
@@ -1190,7 +1198,7 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,
if (static_branch_likely(&psi_disabled))
return -EOPNOTSUPP;
- buf_size = min(nbytes, (sizeof(buf) - 1));
+ buf_size = min(nbytes, sizeof(buf));
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index d6678f773c96..ebaa4e619684 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1499,12 +1499,22 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag
#endif
}
-static inline void set_next_task(struct rq *rq, struct task_struct *p)
+static inline void set_next_task_rt(struct rq *rq, struct task_struct *p)
{
p->se.exec_start = rq_clock_task(rq);
/* The running task is never eligible for pushing */
dequeue_pushable_task(rq, p);
+
+ /*
+ * If prev task was rt, put_prev_task() has already updated the
+ * utilization. We only care of the case where we start to schedule a
+ * rt task
+ */
+ if (rq->curr->sched_class != &rt_sched_class)
+ update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0);
+
+ rt_queue_push_tasks(rq);
}
static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
@@ -1544,56 +1554,19 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
struct task_struct *p;
struct rt_rq *rt_rq = &rq->rt;
- if (need_pull_rt_task(rq, prev)) {
- /*
- * This is OK, because current is on_cpu, which avoids it being
- * picked for load-balance and preemption/IRQs are still
- * disabled avoiding further scheduler activity on it and we're
- * being very careful to re-start the picking loop.
- */
- rq_unpin_lock(rq, rf);
- pull_rt_task(rq);
- rq_repin_lock(rq, rf);
- /*
- * pull_rt_task() can drop (and re-acquire) rq->lock; this
- * means a dl or stop task can slip in, in which case we need
- * to re-start task selection.
- */
- if (unlikely((rq->stop && task_on_rq_queued(rq->stop)) ||
- rq->dl.dl_nr_running))
- return RETRY_TASK;
- }
-
- /*
- * We may dequeue prev's rt_rq in put_prev_task().
- * So, we update time before rt_queued check.
- */
- if (prev->sched_class == &rt_sched_class)
- update_curr_rt(rq);
+ WARN_ON_ONCE(prev || rf);
if (!rt_rq->rt_queued)
return NULL;
- put_prev_task(rq, prev);
-
p = _pick_next_task_rt(rq);
- set_next_task(rq, p);
-
- rt_queue_push_tasks(rq);
-
- /*
- * If prev task was rt, put_prev_task() has already updated the
- * utilization. We only care of the case where we start to schedule a
- * rt task
- */
- if (rq->curr->sched_class != &rt_sched_class)
- update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0);
+ set_next_task_rt(rq, p);
return p;
}
-static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
{
update_curr_rt(rq);
@@ -1605,6 +1578,18 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
*/
if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1)
enqueue_pushable_task(rq, p);
+
+ if (rf && !on_rt_rq(&p->rt) && need_pull_rt_task(rq, p)) {
+ /*
+ * This is OK, because current is on_cpu, which avoids it being
+ * picked for load-balance and preemption/IRQs are still
+ * disabled avoiding further scheduler activity on it and we've
+ * not yet started the picking loop.
+ */
+ rq_unpin_lock(rq, rf);
+ pull_rt_task(rq);
+ rq_repin_lock(rq, rf);
+ }
}
#ifdef CONFIG_SMP
@@ -2357,11 +2342,6 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
}
}
-static void set_curr_task_rt(struct rq *rq)
-{
- set_next_task(rq, rq->curr);
-}
-
static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
{
/*
@@ -2383,6 +2363,7 @@ const struct sched_class rt_sched_class = {
.pick_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
+ .set_next_task = set_next_task_rt,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_rt,
@@ -2394,7 +2375,6 @@ const struct sched_class rt_sched_class = {
.switched_from = switched_from_rt,
#endif
- .set_curr_task = set_curr_task_rt,
.task_tick = task_tick_rt,
.get_rr_interval = get_rr_interval_rt,
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 802b1f3405f2..b3cb895d14a2 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -335,8 +335,6 @@ struct cfs_bandwidth {
u64 quota;
u64 runtime;
s64 hierarchical_quota;
- u64 runtime_expires;
- int expires_seq;
u8 idle;
u8 period_active;
@@ -393,6 +391,16 @@ struct task_group {
#endif
struct cfs_bandwidth cfs_bandwidth;
+
+#ifdef CONFIG_UCLAMP_TASK_GROUP
+ /* The two decimal precision [%] value requested from user-space */
+ unsigned int uclamp_pct[UCLAMP_CNT];
+ /* Clamp values requested for a task group */
+ struct uclamp_se uclamp_req[UCLAMP_CNT];
+ /* Effective clamp values used for a task group */
+ struct uclamp_se uclamp[UCLAMP_CNT];
+#endif
+
};
#ifdef CONFIG_FAIR_GROUP_SCHED
@@ -483,7 +491,8 @@ struct cfs_rq {
struct load_weight load;
unsigned long runnable_weight;
unsigned int nr_running;
- unsigned int h_nr_running;
+ unsigned int h_nr_running; /* SCHED_{NORMAL,BATCH,IDLE} */
+ unsigned int idle_h_nr_running; /* SCHED_IDLE */
u64 exec_clock;
u64 min_vruntime;
@@ -556,8 +565,6 @@ struct cfs_rq {
#ifdef CONFIG_CFS_BANDWIDTH
int runtime_enabled;
- int expires_seq;
- u64 runtime_expires;
s64 runtime_remaining;
u64 throttled_clock;
@@ -777,9 +784,6 @@ struct root_domain {
struct perf_domain __rcu *pd;
};
-extern struct root_domain def_root_domain;
-extern struct mutex sched_domains_mutex;
-
extern void init_defrootdomain(void);
extern int sched_init_domains(const struct cpumask *cpu_map);
extern void rq_attach_root(struct rq *rq, struct root_domain *rd);
@@ -1261,16 +1265,18 @@ enum numa_topology_type {
extern enum numa_topology_type sched_numa_topology_type;
extern int sched_max_numa_distance;
extern bool find_numa_distance(int distance);
-#endif
-
-#ifdef CONFIG_NUMA
extern void sched_init_numa(void);
extern void sched_domains_numa_masks_set(unsigned int cpu);
extern void sched_domains_numa_masks_clear(unsigned int cpu);
+extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu);
#else
static inline void sched_init_numa(void) { }
static inline void sched_domains_numa_masks_set(unsigned int cpu) { }
static inline void sched_domains_numa_masks_clear(unsigned int cpu) { }
+static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
+{
+ return nr_cpu_ids;
+}
#endif
#ifdef CONFIG_NUMA_BALANCING
@@ -1449,10 +1455,14 @@ static inline void unregister_sched_domain_sysctl(void)
}
#endif
+extern int newidle_balance(struct rq *this_rq, struct rq_flags *rf);
+
#else
static inline void sched_ttwu_pending(void) { }
+static inline int newidle_balance(struct rq *this_rq, struct rq_flags *rf) { return 0; }
+
#endif /* CONFIG_SMP */
#include "stats.h"
@@ -1700,17 +1710,21 @@ struct sched_class {
void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags);
/*
- * It is the responsibility of the pick_next_task() method that will
- * return the next task to call put_prev_task() on the @prev task or
- * something equivalent.
+ * Both @prev and @rf are optional and may be NULL, in which case the
+ * caller must already have invoked put_prev_task(rq, prev, rf).
+ *
+ * Otherwise it is the responsibility of the pick_next_task() to call
+ * put_prev_task() on the @prev task or something equivalent, IFF it
+ * returns a next task.
*
- * May return RETRY_TASK when it finds a higher prio class has runnable
- * tasks.
+ * In that case (@rf != NULL) it may return RETRY_TASK when it finds a
+ * higher prio class has runnable tasks.
*/
struct task_struct * (*pick_next_task)(struct rq *rq,
struct task_struct *prev,
struct rq_flags *rf);
- void (*put_prev_task)(struct rq *rq, struct task_struct *p);
+ void (*put_prev_task)(struct rq *rq, struct task_struct *p, struct rq_flags *rf);
+ void (*set_next_task)(struct rq *rq, struct task_struct *p);
#ifdef CONFIG_SMP
int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
@@ -1725,7 +1739,6 @@ struct sched_class {
void (*rq_offline)(struct rq *rq);
#endif
- void (*set_curr_task)(struct rq *rq);
void (*task_tick)(struct rq *rq, struct task_struct *p, int queued);
void (*task_fork)(struct task_struct *p);
void (*task_dead)(struct task_struct *p);
@@ -1755,12 +1768,14 @@ struct sched_class {
static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
{
- prev->sched_class->put_prev_task(rq, prev);
+ WARN_ON_ONCE(rq->curr != prev);
+ prev->sched_class->put_prev_task(rq, prev, NULL);
}
-static inline void set_curr_task(struct rq *rq, struct task_struct *curr)
+static inline void set_next_task(struct rq *rq, struct task_struct *next)
{
- curr->sched_class->set_curr_task(rq);
+ WARN_ON_ONCE(rq->curr != next);
+ next->sched_class->set_next_task(rq, next);
}
#ifdef CONFIG_SMP
@@ -1943,7 +1958,7 @@ unsigned long arch_scale_freq_capacity(int cpu)
#endif
#ifdef CONFIG_SMP
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
static inline void double_rq_lock(struct rq *rq1, struct rq *rq2);
@@ -1995,7 +2010,7 @@ static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
return ret;
}
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
/*
* double_lock_balance - lock the busiest runqueue, this_rq is locked already.
@@ -2266,7 +2281,7 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {}
#endif /* CONFIG_CPU_FREQ */
#ifdef CONFIG_UCLAMP_TASK
-unsigned int uclamp_eff_value(struct task_struct *p, unsigned int clamp_id);
+enum uclamp_id uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id);
static __always_inline
unsigned int uclamp_util_with(struct rq *rq, unsigned int util,
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
index aa0de240fb41..ba683fe81a6e 100644
--- a/kernel/sched/stats.h
+++ b/kernel/sched/stats.h
@@ -157,9 +157,10 @@ static inline void sched_info_dequeued(struct rq *rq, struct task_struct *t)
{
unsigned long long now = rq_clock(rq), delta = 0;
- if (unlikely(sched_info_on()))
+ if (sched_info_on()) {
if (t->sched_info.last_queued)
delta = now - t->sched_info.last_queued;
+ }
sched_info_reset_dequeued(t);
t->sched_info.run_delay += delta;
@@ -192,7 +193,7 @@ static void sched_info_arrive(struct rq *rq, struct task_struct *t)
*/
static inline void sched_info_queued(struct rq *rq, struct task_struct *t)
{
- if (unlikely(sched_info_on())) {
+ if (sched_info_on()) {
if (!t->sched_info.last_queued)
t->sched_info.last_queued = rq_clock(rq);
}
@@ -239,7 +240,7 @@ __sched_info_switch(struct rq *rq, struct task_struct *prev, struct task_struct
static inline void
sched_info_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next)
{
- if (unlikely(sched_info_on()))
+ if (sched_info_on())
__sched_info_switch(rq, prev, next);
}
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index c183b790ca54..7e1cee4e65b2 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -23,17 +23,22 @@ check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
/* we're never preempted */
}
+static void set_next_task_stop(struct rq *rq, struct task_struct *stop)
+{
+ stop->se.exec_start = rq_clock_task(rq);
+}
+
static struct task_struct *
pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
struct task_struct *stop = rq->stop;
+ WARN_ON_ONCE(prev || rf);
+
if (!stop || !task_on_rq_queued(stop))
return NULL;
- put_prev_task(rq, prev);
-
- stop->se.exec_start = rq_clock_task(rq);
+ set_next_task_stop(rq, stop);
return stop;
}
@@ -55,7 +60,7 @@ static void yield_task_stop(struct rq *rq)
BUG(); /* the stop task should never yield, its pointless. */
}
-static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)
+static void put_prev_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
struct task_struct *curr = rq->curr;
u64 delta_exec;
@@ -86,13 +91,6 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued)
{
}
-static void set_curr_task_stop(struct rq *rq)
-{
- struct task_struct *stop = rq->stop;
-
- stop->se.exec_start = rq_clock_task(rq);
-}
-
static void switched_to_stop(struct rq *rq, struct task_struct *p)
{
BUG(); /* its impossible to change to this class */
@@ -128,13 +126,13 @@ const struct sched_class stop_sched_class = {
.pick_next_task = pick_next_task_stop,
.put_prev_task = put_prev_task_stop,
+ .set_next_task = set_next_task_stop,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_stop,
.set_cpus_allowed = set_cpus_allowed_common,
#endif
- .set_curr_task = set_curr_task_stop,
.task_tick = task_tick_stop,
.get_rr_interval = get_rr_interval_stop,
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index f751ce0b783e..b5667a273bf6 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -1284,6 +1284,7 @@ static int sched_domains_curr_level;
int sched_max_numa_distance;
static int *sched_domains_numa_distance;
static struct cpumask ***sched_domains_numa_masks;
+int __read_mostly node_reclaim_distance = RECLAIM_DISTANCE;
#endif
/*
@@ -1402,7 +1403,7 @@ sd_init(struct sched_domain_topology_level *tl,
sd->flags &= ~SD_PREFER_SIBLING;
sd->flags |= SD_SERIALIZE;
- if (sched_domains_numa_distance[tl->numa_level] > RECLAIM_DISTANCE) {
+ if (sched_domains_numa_distance[tl->numa_level] > node_reclaim_distance) {
sd->flags &= ~(SD_BALANCE_EXEC |
SD_BALANCE_FORK |
SD_WAKE_AFFINE);
@@ -1724,6 +1725,26 @@ void sched_domains_numa_masks_clear(unsigned int cpu)
}
}
+/*
+ * sched_numa_find_closest() - given the NUMA topology, find the cpu
+ * closest to @cpu from @cpumask.
+ * cpumask: cpumask to find a cpu from
+ * cpu: cpu to be close to
+ *
+ * returns: cpu, or nr_cpu_ids when nothing found.
+ */
+int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
+{
+ int i, j = cpu_to_node(cpu);
+
+ for (i = 0; i < sched_domains_numa_levels; i++) {
+ cpu = cpumask_any_and(cpus, sched_domains_numa_masks[i][j]);
+ if (cpu < nr_cpu_ids)
+ return cpu;
+ }
+ return nr_cpu_ids;
+}
+
#endif /* CONFIG_NUMA */
static int __sdt_alloc(const struct cpumask *cpu_map)
@@ -2149,16 +2170,16 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
* ndoms_new == 0 is a special case for destroying existing domains,
* and it will not create the default domain.
*
- * Call with hotplug lock held
+ * Call with hotplug lock and sched_domains_mutex held
*/
-void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
- struct sched_domain_attr *dattr_new)
+void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[],
+ struct sched_domain_attr *dattr_new)
{
bool __maybe_unused has_eas = false;
int i, j, n;
int new_topology;
- mutex_lock(&sched_domains_mutex);
+ lockdep_assert_held(&sched_domains_mutex);
/* Always unregister in case we don't destroy any domains: */
unregister_sched_domain_sysctl();
@@ -2183,8 +2204,19 @@ void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
for (i = 0; i < ndoms_cur; i++) {
for (j = 0; j < n && !new_topology; j++) {
if (cpumask_equal(doms_cur[i], doms_new[j]) &&
- dattrs_equal(dattr_cur, i, dattr_new, j))
+ dattrs_equal(dattr_cur, i, dattr_new, j)) {
+ struct root_domain *rd;
+
+ /*
+ * This domain won't be destroyed and as such
+ * its dl_bw->total_bw needs to be cleared. It
+ * will be recomputed in function
+ * update_tasks_root_domain().
+ */
+ rd = cpu_rq(cpumask_any(doms_cur[i]))->rd;
+ dl_clear_root_domain(rd);
goto match1;
+ }
}
/* No match - a current sched domain not in new doms_new[] */
detach_destroy_domains(doms_cur[i]);
@@ -2241,6 +2273,15 @@ match3:
ndoms_cur = ndoms_new;
register_sched_domain_sysctl();
+}
+/*
+ * Call with hotplug lock held
+ */
+void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
+ struct sched_domain_attr *dattr_new)
+{
+ mutex_lock(&sched_domains_mutex);
+ partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
mutex_unlock(&sched_domains_mutex);
}
diff --git a/kernel/signal.c b/kernel/signal.c
index 91b789dd6e72..c4da1ef56fdf 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -90,6 +90,11 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
handler == SIG_DFL && !(force && sig_kernel_only(sig)))
return true;
+ /* Only allow kernel generated signals to this kthread */
+ if (unlikely((t->flags & PF_KTHREAD) &&
+ (handler == SIG_KTHREAD_KERNEL) && !force))
+ return true;
+
return sig_handler_ignored(handler, sig);
}
@@ -349,7 +354,7 @@ void task_clear_jobctl_pending(struct task_struct *task, unsigned long mask)
* @task has %JOBCTL_STOP_PENDING set and is participating in a group stop.
* Group stop states are cleared and the group stop count is consumed if
* %JOBCTL_STOP_CONSUME was set. If the consumption completes the group
- * stop, the appropriate %SIGNAL_* flags are set.
+ * stop, the appropriate `SIGNAL_*` flags are set.
*
* CONTEXT:
* Must be called with @task->sighand->siglock held.
@@ -1885,6 +1890,7 @@ static void do_notify_pidfd(struct task_struct *task)
{
struct pid *pid;
+ WARN_ON(task->exit_state == 0);
pid = task_pid(task);
wake_up_all(&pid->wait_pidfd);
}
@@ -3672,8 +3678,11 @@ static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo, siginfo_t *info)
static struct pid *pidfd_to_pid(const struct file *file)
{
- if (file->f_op == &pidfd_fops)
- return file->private_data;
+ struct pid *pid;
+
+ pid = pidfd_pid(file);
+ if (!IS_ERR(pid))
+ return pid;
return tgid_pidfd_to_pid(file);
}
diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c
index f5440abb7532..6d1f68b7e528 100644
--- a/kernel/stacktrace.c
+++ b/kernel/stacktrace.c
@@ -20,7 +20,7 @@
* @nr_entries: Number of entries in the storage array
* @spaces: Number of leading spaces to print
*/
-void stack_trace_print(unsigned long *entries, unsigned int nr_entries,
+void stack_trace_print(const unsigned long *entries, unsigned int nr_entries,
int spaces)
{
unsigned int i;
@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(stack_trace_print);
*
* Return: Number of bytes printed.
*/
-int stack_trace_snprint(char *buf, size_t size, unsigned long *entries,
+int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
unsigned int nr_entries, int spaces)
{
unsigned int generated, i, total = 0;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b4f83f7bdf86..c7031a22aa7b 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -383,6 +383,7 @@ static bool queue_stop_cpus_work(const struct cpumask *cpumask,
*/
preempt_disable();
stop_cpus_in_progress = true;
+ barrier();
for_each_cpu(cpu, cpumask) {
work = &per_cpu(cpu_stopper.stop_work, cpu);
work->fn = fn;
@@ -391,6 +392,7 @@ static bool queue_stop_cpus_work(const struct cpumask *cpumask,
if (cpu_stop_queue_work(cpu, work))
queued = true;
}
+ barrier();
stop_cpus_in_progress = false;
preempt_enable();
diff --git a/kernel/sys.c b/kernel/sys.c
index 2462aa84247f..a611d1d58c7d 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -103,12 +103,6 @@
#ifndef SET_TSC_CTL
# define SET_TSC_CTL(a) (-EINVAL)
#endif
-#ifndef MPX_ENABLE_MANAGEMENT
-# define MPX_ENABLE_MANAGEMENT() (-EINVAL)
-#endif
-#ifndef MPX_DISABLE_MANAGEMENT
-# define MPX_DISABLE_MANAGEMENT() (-EINVAL)
-#endif
#ifndef GET_FP_MODE
# define GET_FP_MODE(a) (-EINVAL)
#endif
@@ -124,6 +118,12 @@
#ifndef PAC_RESET_KEYS
# define PAC_RESET_KEYS(a, b) (-EINVAL)
#endif
+#ifndef SET_TAGGED_ADDR_CTRL
+# define SET_TAGGED_ADDR_CTRL(a) (-EINVAL)
+#endif
+#ifndef GET_TAGGED_ADDR_CTRL
+# define GET_TAGGED_ADDR_CTRL() (-EINVAL)
+#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
@@ -2446,15 +2446,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
up_write(&me->mm->mmap_sem);
break;
case PR_MPX_ENABLE_MANAGEMENT:
- if (arg2 || arg3 || arg4 || arg5)
- return -EINVAL;
- error = MPX_ENABLE_MANAGEMENT();
- break;
case PR_MPX_DISABLE_MANAGEMENT:
- if (arg2 || arg3 || arg4 || arg5)
- return -EINVAL;
- error = MPX_DISABLE_MANAGEMENT();
- break;
+ /* No longer implemented: */
+ return -EINVAL;
case PR_SET_FP_MODE:
error = SET_FP_MODE(me, arg2);
break;
@@ -2482,6 +2476,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
return -EINVAL;
error = PAC_RESET_KEYS(me, arg2);
break;
+ case PR_SET_TAGGED_ADDR_CTRL:
+ if (arg3 || arg4 || arg5)
+ return -EINVAL;
+ error = SET_TAGGED_ADDR_CTRL(arg2);
+ break;
+ case PR_GET_TAGGED_ADDR_CTRL:
+ if (arg2 || arg3 || arg4 || arg5)
+ return -EINVAL;
+ error = GET_TAGGED_ADDR_CTRL();
+ break;
default:
error = -EINVAL;
break;
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index ec32876e284d..271ce6c12907 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -685,7 +685,7 @@ static int alarm_timer_create(struct k_itimer *new_timer)
enum alarmtimer_type type;
if (!alarmtimer_get_rtcdev())
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
if (!capable(CAP_WAKE_ALARM))
return -EPERM;
@@ -803,7 +803,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
int ret = 0;
if (!alarmtimer_get_rtcdev())
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
if (flags & ~TIMER_ABSTIME)
return -EINVAL;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d911c8470149..ca69290bee2a 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -146,6 +146,11 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm)
static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
{
tk->offs_boot = ktime_add(tk->offs_boot, delta);
+ /*
+ * Timespec representation for VDSO update to avoid 64bit division
+ * on every update.
+ */
+ tk->monotonic_to_boot = ktime_to_timespec64(tk->offs_boot);
}
/*
diff --git a/kernel/time/vsyscall.c b/kernel/time/vsyscall.c
index 8cf3596a4ce6..4bc37ac3bb05 100644
--- a/kernel/time/vsyscall.c
+++ b/kernel/time/vsyscall.c
@@ -17,7 +17,7 @@ static inline void update_vdso_data(struct vdso_data *vdata,
struct timekeeper *tk)
{
struct vdso_timestamp *vdso_ts;
- u64 nsec;
+ u64 nsec, sec;
vdata[CS_HRES_COARSE].cycle_last = tk->tkr_mono.cycle_last;
vdata[CS_HRES_COARSE].mask = tk->tkr_mono.mask;
@@ -45,23 +45,27 @@ static inline void update_vdso_data(struct vdso_data *vdata,
}
vdso_ts->nsec = nsec;
- /* CLOCK_MONOTONIC_RAW */
- vdso_ts = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
- vdso_ts->sec = tk->raw_sec;
- vdso_ts->nsec = tk->tkr_raw.xtime_nsec;
+ /* Copy MONOTONIC time for BOOTTIME */
+ sec = vdso_ts->sec;
+ /* Add the boot offset */
+ sec += tk->monotonic_to_boot.tv_sec;
+ nsec += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
/* CLOCK_BOOTTIME */
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
- vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
- nsec = tk->tkr_mono.xtime_nsec;
- nsec += ((u64)(tk->wall_to_monotonic.tv_nsec +
- ktime_to_ns(tk->offs_boot)) << tk->tkr_mono.shift);
+ vdso_ts->sec = sec;
+
while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
vdso_ts->sec++;
}
vdso_ts->nsec = nsec;
+ /* CLOCK_MONOTONIC_RAW */
+ vdso_ts = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
+ vdso_ts->sec = tk->raw_sec;
+ vdso_ts->nsec = tk->tkr_raw.xtime_nsec;
+
/* CLOCK_TAI */
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
vdso_ts->sec = tk->xtime_sec + (s64)tk->tai_offset;
diff --git a/kernel/torture.c b/kernel/torture.c
index a8d9bdfba7c3..7c13f5558b71 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -263,7 +263,6 @@ static void torture_onoff_cleanup(void)
onoff_task = NULL;
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
}
-EXPORT_SYMBOL_GPL(torture_onoff_cleanup);
/*
* Print online/offline testing statistics.
@@ -449,7 +448,6 @@ static void torture_shuffle_cleanup(void)
}
shuffler_task = NULL;
}
-EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
/*
* Variables for auto-shutdown. This allows "lights out" torture runs
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 98da8998c25c..6a64d7772870 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -146,7 +146,7 @@ config FUNCTION_TRACER
select GENERIC_TRACER
select CONTEXT_SWITCH_TRACER
select GLOB
- select TASKS_RCU if PREEMPT
+ select TASKS_RCU if PREEMPTION
help
Enable the kernel to trace every kernel function. This is done
by using a compiler feature to insert a small, 5-byte No-Operation
@@ -179,7 +179,7 @@ config TRACE_PREEMPT_TOGGLE
config PREEMPTIRQ_EVENTS
bool "Enable trace events for preempt and irq disable/enable"
select TRACE_IRQFLAGS
- select TRACE_PREEMPT_TOGGLE if PREEMPT
+ select TRACE_PREEMPT_TOGGLE if PREEMPTION
select GENERIC_TRACER
default n
help
@@ -214,7 +214,7 @@ config PREEMPT_TRACER
bool "Preemption-off Latency Tracer"
default n
depends on !ARCH_USES_GETTIMEOFFSET
- depends on PREEMPT
+ depends on PREEMPTION
select GENERIC_TRACER
select TRACER_MAX_TRACE
select RING_BUFFER_ALLOW_SWAP
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index eca34503f178..356b848c697a 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2814,7 +2814,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
* synchornize_rcu_tasks() will wait for those tasks to
* execute and either schedule voluntarily or enter user space.
*/
- if (IS_ENABLED(CONFIG_PREEMPT))
+ if (IS_ENABLED(CONFIG_PREEMPTION))
synchronize_rcu_tasks();
free_ops:
@@ -3095,6 +3095,14 @@ t_probe_next(struct seq_file *m, loff_t *pos)
hnd = &iter->probe_entry->hlist;
hash = iter->probe->ops.func_hash->filter_hash;
+
+ /*
+ * A probe being registered may temporarily have an empty hash
+ * and it's at the end of the func_probes list.
+ */
+ if (!hash || hash == EMPTY_HASH)
+ return NULL;
+
size = 1 << hash->size_bits;
retry:
@@ -4320,12 +4328,21 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr,
mutex_unlock(&ftrace_lock);
+ /*
+ * Note, there's a small window here that the func_hash->filter_hash
+ * may be NULL or empty. Need to be carefule when reading the loop.
+ */
mutex_lock(&probe->ops.func_hash->regex_lock);
orig_hash = &probe->ops.func_hash->filter_hash;
old_hash = *orig_hash;
hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, old_hash);
+ if (!hash) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
ret = ftrace_match_records(hash, glob, strlen(glob));
/* Nothing found? */
diff --git a/kernel/trace/ftrace_internal.h b/kernel/trace/ftrace_internal.h
index 0515a2096f90..0456e0a3dab1 100644
--- a/kernel/trace/ftrace_internal.h
+++ b/kernel/trace/ftrace_internal.h
@@ -6,22 +6,22 @@
/*
* Traverse the ftrace_global_list, invoking all entries. The reason that we
- * can use rcu_dereference_raw_notrace() is that elements removed from this list
+ * can use rcu_dereference_raw_check() is that elements removed from this list
* are simply leaked, so there is no need to interact with a grace-period
- * mechanism. The rcu_dereference_raw_notrace() calls are needed to handle
+ * mechanism. The rcu_dereference_raw_check() calls are needed to handle
* concurrent insertions into the ftrace_global_list.
*
* Silly Alpha and silly pointer-speculation compiler optimizations!
*/
#define do_for_each_ftrace_op(op, list) \
- op = rcu_dereference_raw_notrace(list); \
+ op = rcu_dereference_raw_check(list); \
do
/*
* Optimized for just a single item in the list (as that is the normal case).
*/
#define while_for_each_ftrace_op(op) \
- while (likely(op = rcu_dereference_raw_notrace((op)->next)) && \
+ while (likely(op = rcu_dereference_raw_check((op)->next)) && \
unlikely((op) != &ftrace_list_end))
extern struct ftrace_ops __rcu *ftrace_ops_list;
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c
index 0564f6db0561..09b0b49f346e 100644
--- a/kernel/trace/ring_buffer_benchmark.c
+++ b/kernel/trace/ring_buffer_benchmark.c
@@ -267,7 +267,7 @@ static void ring_buffer_producer(void)
if (consumer && !(cnt % wakeup_interval))
wake_up_process(consumer);
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
/*
* If we are a non preempt kernel, the 10 second run will
* stop everything while it runs. Instead, we will call
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 525a97fbbc60..947ba433865f 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1567,9 +1567,9 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu,
/**
* update_max_tr_single - only copy one trace over, and reset the rest
- * @tr - tracer
- * @tsk - task with the latency
- * @cpu - the cpu of the buffer to copy.
+ * @tr: tracer
+ * @tsk: task with the latency
+ * @cpu: the cpu of the buffer to copy.
*
* Flip the trace of a single CPU buffer between the @tr and the max_tr.
*/
@@ -1767,7 +1767,7 @@ static void __init apply_trace_boot_options(void);
/**
* register_tracer - register a tracer with the ftrace system.
- * @type - the plugin for the tracer
+ * @type: the plugin for the tracer
*
* Register a new plugin tracer.
*/
@@ -2230,9 +2230,9 @@ static bool tracing_record_taskinfo_skip(int flags)
/**
* tracing_record_taskinfo - record the task info of a task
*
- * @task - task to record
- * @flags - TRACE_RECORD_CMDLINE for recording comm
- * - TRACE_RECORD_TGID for recording tgid
+ * @task: task to record
+ * @flags: TRACE_RECORD_CMDLINE for recording comm
+ * TRACE_RECORD_TGID for recording tgid
*/
void tracing_record_taskinfo(struct task_struct *task, int flags)
{
@@ -2258,10 +2258,10 @@ void tracing_record_taskinfo(struct task_struct *task, int flags)
/**
* tracing_record_taskinfo_sched_switch - record task info for sched_switch
*
- * @prev - previous task during sched_switch
- * @next - next task during sched_switch
- * @flags - TRACE_RECORD_CMDLINE for recording comm
- * TRACE_RECORD_TGID for recording tgid
+ * @prev: previous task during sched_switch
+ * @next: next task during sched_switch
+ * @flags: TRACE_RECORD_CMDLINE for recording comm
+ * TRACE_RECORD_TGID for recording tgid
*/
void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
struct task_struct *next, int flags)
@@ -2642,10 +2642,10 @@ static void ftrace_exports(struct ring_buffer_event *event)
preempt_disable_notrace();
- export = rcu_dereference_raw_notrace(ftrace_exports_list);
+ export = rcu_dereference_raw_check(ftrace_exports_list);
while (export) {
trace_process_export(export, event);
- export = rcu_dereference_raw_notrace(export->next);
+ export = rcu_dereference_raw_check(export->next);
}
preempt_enable_notrace();
@@ -3072,7 +3072,9 @@ static void trace_printk_start_stop_comm(int enabled)
/**
* trace_vbprintk - write binary msg to tracing buffer
- *
+ * @ip: The address of the caller
+ * @fmt: The string format to write to the buffer
+ * @args: Arguments for @fmt
*/
int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
{
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index c7506bc81b75..b89cdfe20bc1 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -255,12 +255,12 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
local_save_flags(fbuffer->flags);
fbuffer->pc = preempt_count();
/*
- * If CONFIG_PREEMPT is enabled, then the tracepoint itself disables
+ * If CONFIG_PREEMPTION is enabled, then the tracepoint itself disables
* preemption (adding one to the preempt_count). Since we are
* interested in the preempt_count at the time the tracepoint was
* hit, we need to subtract one to offset the increment.
*/
- if (IS_ENABLED(CONFIG_PREEMPT))
+ if (IS_ENABLED(CONFIG_PREEMPTION))
fbuffer->pc--;
fbuffer->trace_file = trace_file;
@@ -787,7 +787,7 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
return ret;
}
-static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
+int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
{
char *event = NULL, *sub = NULL, *match;
int ret;
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 69ebf3c2f1b5..78af97163147 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -137,6 +137,13 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT))
return 0;
+ /*
+ * Do not trace a function if it's filtered by set_graph_notrace.
+ * Make the index of ret stack negative to indicate that it should
+ * ignore further functions. But it needs its own ret stack entry
+ * to recover the original index in order to continue tracing after
+ * returning from the function.
+ */
if (ftrace_graph_notrace_addr(trace->func)) {
trace_recursion_set(TRACE_GRAPH_NOTRACE_BIT);
/*
@@ -156,16 +163,6 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
return 0;
/*
- * Do not trace a function if it's filtered by set_graph_notrace.
- * Make the index of ret stack negative to indicate that it should
- * ignore further functions. But it needs its own ret stack entry
- * to recover the original index in order to continue tracing after
- * returning from the function.
- */
- if (ftrace_graph_notrace_addr(trace->func))
- return 1;
-
- /*
* Stop here if tracing_threshold is set. We only write function return
* events to the ring buffer.
*/
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index dbef0d135075..fb6bfbc5bf86 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -895,7 +895,8 @@ void trace_probe_cleanup(struct trace_probe *tp)
for (i = 0; i < tp->nr_args; i++)
traceprobe_free_probe_arg(&tp->args[i]);
- kfree(call->class->system);
+ if (call->class)
+ kfree(call->class->system);
kfree(call->name);
kfree(call->print_fmt);
}
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 743b2b520d34..5e43b9664eca 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -579,8 +579,7 @@ probe_wakeup(void *ignore, struct task_struct *p)
else
tracing_dl = 0;
- wakeup_task = p;
- get_task_struct(wakeup_task);
+ wakeup_task = get_task_struct(p);
local_save_flags(flags);
diff --git a/lib/Kconfig b/lib/Kconfig
index f33d66fc0e86..4e6b1c3e4c98 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -631,6 +631,9 @@ config SBITMAP
config PARMAN
tristate "parman" if COMPILE_TEST
+config OBJAGG
+ tristate "objagg" if COMPILE_TEST
+
config STRING_SELFTEST
tristate "Test string functions"
@@ -653,6 +656,3 @@ config GENERIC_LIB_CMPDI2
config GENERIC_LIB_UCMPDI2
bool
-
-config OBJAGG
- tristate "objagg" if COMPILE_TEST
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 4fafba1a923b..7fa97a8b5717 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -106,7 +106,6 @@ endchoice
config KASAN_STACK_ENABLE
bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && !COMPILE_TEST
- default !(CLANG_VERSION < 90000)
depends on KASAN
help
The LLVM stack address sanitizer has a know problem that
@@ -115,11 +114,11 @@ config KASAN_STACK_ENABLE
Disabling asan-stack makes it safe to run kernels build
with clang-8 with KASAN enabled, though it loses some of
the functionality.
- This feature is always disabled when compile-testing with clang-8
- or earlier to avoid cluttering the output in stack overflow
- warnings, but clang-8 users can still enable it for builds without
- CONFIG_COMPILE_TEST. On gcc and later clang versions it is
- assumed to always be safe to use and enabled by default.
+ This feature is always disabled when compile-testing with clang
+ to avoid cluttering the output in stack overflow warnings,
+ but clang users can still enable it for builds without
+ CONFIG_COMPILE_TEST. On gcc it is assumed to always be safe
+ to use and enabled by default.
config KASAN_STACK
int
diff --git a/lib/Makefile b/lib/Makefile
index 095601ce371d..c5892807e06f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,10 +21,6 @@ KCOV_INSTRUMENT_dynamic_debug.o := n
ifdef CONFIG_AMD_MEM_ENCRYPT
KASAN_SANITIZE_string.o := n
-ifdef CONFIG_FUNCTION_TRACER
-CFLAGS_REMOVE_string.o = -pg
-endif
-
CFLAGS_string.o := $(call cc-option, -fno-stack-protector)
endif
@@ -279,7 +275,8 @@ obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
obj-$(CONFIG_UBSAN) += ubsan.o
UBSAN_SANITIZE_ubsan.o := n
-CFLAGS_ubsan.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+KASAN_SANITIZE_ubsan.o := n
+CFLAGS_ubsan.o := $(call cc-option, -fno-stack-protector) $(DISABLE_STACKLEAK_PLUGIN)
obj-$(CONFIG_SBITMAP) += sbitmap.o
diff --git a/lib/bitmap.c b/lib/bitmap.c
index bbe2589e8497..f9e834841e94 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -59,6 +59,26 @@ int __bitmap_equal(const unsigned long *bitmap1,
}
EXPORT_SYMBOL(__bitmap_equal);
+bool __bitmap_or_equal(const unsigned long *bitmap1,
+ const unsigned long *bitmap2,
+ const unsigned long *bitmap3,
+ unsigned int bits)
+{
+ unsigned int k, lim = bits / BITS_PER_LONG;
+ unsigned long tmp;
+
+ for (k = 0; k < lim; ++k) {
+ if ((bitmap1[k] | bitmap2[k]) != bitmap3[k])
+ return false;
+ }
+
+ if (!(bits % BITS_PER_LONG))
+ return true;
+
+ tmp = (bitmap1[k] | bitmap2[k]) ^ bitmap3[k];
+ return (tmp & BITMAP_LAST_WORD_MASK(bits)) == 0;
+}
+
void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int bits)
{
unsigned int k, lim = BITS_TO_LONGS(bits);
diff --git a/lib/dim/dim.c b/lib/dim/dim.c
index 439d641ec796..38045d6d0538 100644
--- a/lib/dim/dim.c
+++ b/lib/dim/dim.c
@@ -74,8 +74,8 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
delta_us);
curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us);
if (curr_stats->epms != 0)
- curr_stats->cpe_ratio =
- (curr_stats->cpms * 100) / curr_stats->epms;
+ curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL(
+ curr_stats->cpms * 100, curr_stats->epms);
else
curr_stats->cpe_ratio = 0;
diff --git a/lib/dim/net_dim.c b/lib/dim/net_dim.c
index 5bcc902c5388..a4db51c21266 100644
--- a/lib/dim/net_dim.c
+++ b/lib/dim/net_dim.c
@@ -5,6 +5,62 @@
#include <linux/dim.h>
+/*
+ * Net DIM profiles:
+ * There are different set of profiles for each CQ period mode.
+ * There are different set of profiles for RX/TX CQs.
+ * Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
+ */
+#define NET_DIM_PARAMS_NUM_PROFILES 5
+#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
+#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
+#define NET_DIM_DEF_PROFILE_CQE 1
+#define NET_DIM_DEF_PROFILE_EQE 1
+
+#define NET_DIM_RX_EQE_PROFILES { \
+ {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+}
+
+#define NET_DIM_RX_CQE_PROFILES { \
+ {2, 256}, \
+ {8, 128}, \
+ {16, 64}, \
+ {32, 64}, \
+ {64, 64} \
+}
+
+#define NET_DIM_TX_EQE_PROFILES { \
+ {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+ {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \
+}
+
+#define NET_DIM_TX_CQE_PROFILES { \
+ {5, 128}, \
+ {8, 64}, \
+ {16, 32}, \
+ {32, 32}, \
+ {64, 32} \
+}
+
+static const struct dim_cq_moder
+rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+ NET_DIM_RX_EQE_PROFILES,
+ NET_DIM_RX_CQE_PROFILES,
+};
+
+static const struct dim_cq_moder
+tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+ NET_DIM_TX_EQE_PROFILES,
+ NET_DIM_TX_CQE_PROFILES,
+};
+
struct dim_cq_moder
net_dim_get_rx_moderation(u8 cq_period_mode, int ix)
{
diff --git a/lib/kfifo.c b/lib/kfifo.c
index 117ad0e7fbf4..70dab9ac7827 100644
--- a/lib/kfifo.c
+++ b/lib/kfifo.c
@@ -68,7 +68,8 @@ int __kfifo_init(struct __kfifo *fifo, void *buffer,
{
size /= esize;
- size = roundup_pow_of_two(size);
+ if (!is_power_of_2(size))
+ size = rounddown_pow_of_two(size);
fifo->in = 0;
fifo->out = 0;
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
index feea48fd1a0d..905027574e5d 100644
--- a/lib/logic_pio.c
+++ b/lib/logic_pio.c
@@ -35,7 +35,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
struct logic_pio_hwaddr *range;
resource_size_t start;
resource_size_t end;
- resource_size_t mmio_sz = 0;
+ resource_size_t mmio_end = 0;
resource_size_t iio_sz = MMIO_UPPER_LIMIT;
int ret = 0;
@@ -46,7 +46,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
end = new_range->hw_start + new_range->size;
mutex_lock(&io_range_mutex);
- list_for_each_entry_rcu(range, &io_range_list, list) {
+ list_for_each_entry(range, &io_range_list, list) {
if (range->fwnode == new_range->fwnode) {
/* range already there */
goto end_register;
@@ -56,7 +56,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
/* for MMIO ranges we need to check for overlap */
if (start >= range->hw_start + range->size ||
end < range->hw_start) {
- mmio_sz += range->size;
+ mmio_end = range->io_start + range->size;
} else {
ret = -EFAULT;
goto end_register;
@@ -69,16 +69,16 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
/* range not registered yet, check for available space */
if (new_range->flags == LOGIC_PIO_CPU_MMIO) {
- if (mmio_sz + new_range->size - 1 > MMIO_UPPER_LIMIT) {
+ if (mmio_end + new_range->size - 1 > MMIO_UPPER_LIMIT) {
/* if it's too big check if 64K space can be reserved */
- if (mmio_sz + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
+ if (mmio_end + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
ret = -E2BIG;
goto end_register;
}
new_range->size = SZ_64K;
pr_warn("Requested IO range too big, new size set to 64K\n");
}
- new_range->io_start = mmio_sz;
+ new_range->io_start = mmio_end;
} else if (new_range->flags == LOGIC_PIO_INDIRECT) {
if (iio_sz + new_range->size - 1 > IO_SPACE_LIMIT) {
ret = -E2BIG;
@@ -99,6 +99,20 @@ end_register:
}
/**
+ * logic_pio_unregister_range - unregister a logical PIO range for a host
+ * @range: pointer to the IO range which has been already registered.
+ *
+ * Unregister a previously-registered IO range node.
+ */
+void logic_pio_unregister_range(struct logic_pio_hwaddr *range)
+{
+ mutex_lock(&io_range_mutex);
+ list_del_rcu(&range->list);
+ mutex_unlock(&io_range_mutex);
+ synchronize_rcu();
+}
+
+/**
* find_io_range_by_fwnode - find logical PIO range for given FW node
* @fwnode: FW node handle associated with logical PIO range
*
@@ -108,26 +122,38 @@ end_register:
*/
struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
{
- struct logic_pio_hwaddr *range;
+ struct logic_pio_hwaddr *range, *found_range = NULL;
+ rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) {
- if (range->fwnode == fwnode)
- return range;
+ if (range->fwnode == fwnode) {
+ found_range = range;
+ break;
+ }
}
- return NULL;
+ rcu_read_unlock();
+
+ return found_range;
}
/* Return a registered range given an input PIO token */
static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
{
- struct logic_pio_hwaddr *range;
+ struct logic_pio_hwaddr *range, *found_range = NULL;
+ rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) {
- if (in_range(pio, range->io_start, range->size))
- return range;
+ if (in_range(pio, range->io_start, range->size)) {
+ found_range = range;
+ break;
+ }
}
- pr_err("PIO entry token %lx invalid\n", pio);
- return NULL;
+ rcu_read_unlock();
+
+ if (!found_range)
+ pr_err("PIO entry token 0x%lx invalid\n", pio);
+
+ return found_range;
}
/**
@@ -180,14 +206,23 @@ unsigned long logic_pio_trans_cpuaddr(resource_size_t addr)
{
struct logic_pio_hwaddr *range;
+ rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) {
if (range->flags != LOGIC_PIO_CPU_MMIO)
continue;
- if (in_range(addr, range->hw_start, range->size))
- return addr - range->hw_start + range->io_start;
+ if (in_range(addr, range->hw_start, range->size)) {
+ unsigned long cpuaddr;
+
+ cpuaddr = addr - range->hw_start + range->io_start;
+
+ rcu_read_unlock();
+ return cpuaddr;
+ }
}
- pr_err("addr %llx not registered in io_range_list\n",
- (unsigned long long) addr);
+ rcu_read_unlock();
+
+ pr_err("addr %pa not registered in io_range_list\n", &addr);
+
return ~0UL;
}
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 42695bc8d451..0083b5cc646c 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -66,7 +66,7 @@ CFLAGS_vpermxor1.o += $(altivec_flags)
CFLAGS_vpermxor2.o += $(altivec_flags)
CFLAGS_vpermxor4.o += $(altivec_flags)
CFLAGS_vpermxor8.o += $(altivec_flags)
-targets += vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o
+targets += vpermxor1.c vpermxor2.c vpermxor4.c vpermxor8.c
$(obj)/vpermxor%.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 66cab785bea0..ed717dd08ff3 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -87,7 +87,7 @@ static bool init_stack_slab(void **prealloc)
stack_slabs[depot_index + 1] = *prealloc;
/*
* This smp_store_release pairs with smp_load_acquire() from
- * |next_slab_inited| above and in depot_save_stack().
+ * |next_slab_inited| above and in stack_depot_save().
*/
smp_store_release(&next_slab_inited, 1);
}
@@ -114,7 +114,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
depot_offset = 0;
/*
* smp_store_release() here pairs with smp_load_acquire() from
- * |next_slab_inited| in depot_save_stack() and
+ * |next_slab_inited| in stack_depot_save() and
* init_stack_slab().
*/
if (depot_index + 1 < STACK_ALLOC_MAX_SLABS)
diff --git a/lib/test_firmware.c b/lib/test_firmware.c
index 83ea6c4e623c..6ca97a63b3d6 100644
--- a/lib/test_firmware.c
+++ b/lib/test_firmware.c
@@ -886,8 +886,11 @@ static int __init test_firmware_init(void)
return -ENOMEM;
rc = __test_firmware_config_init();
- if (rc)
+ if (rc) {
+ kfree(test_fw_config);
+ pr_err("could not init firmware test config: %d\n", rc);
return rc;
+ }
rc = misc_register(&test_fw_misc_device);
if (rc) {
diff --git a/lib/test_meminit.c b/lib/test_meminit.c
index 62d19f270cad..9729f271d150 100644
--- a/lib/test_meminit.c
+++ b/lib/test_meminit.c
@@ -222,7 +222,7 @@ static int __init do_kmem_cache_size(size_t size, bool want_ctor,
* Copy the buffer to check that it's not wiped on
* free().
*/
- buf_copy = kmalloc(size, GFP_KERNEL);
+ buf_copy = kmalloc(size, GFP_ATOMIC);
if (buf_copy)
memcpy(buf_copy, buf, size);
diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 2d1c1f241fd9..e630e7ff57f1 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -51,7 +51,7 @@ static int do_hres(const struct vdso_data *vd, clockid_t clk,
ns = vdso_ts->nsec;
last = vd->cycle_last;
if (unlikely((s64)cycles < 0))
- return clock_gettime_fallback(clk, ts);
+ return -1;
ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
ns >>= vd->shift;
@@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_data *vd, clockid_t clk,
}
static __maybe_unused int
-__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
{
const struct vdso_data *vd = __arch_get_vdso_data();
u32 msk;
/* Check for negative values or invalid clocks */
if (unlikely((u32) clock >= MAX_CLOCKS))
- goto fallback;
+ return -1;
/*
* Convert the clockid to a bitmask and use it to check which
@@ -104,9 +104,17 @@ __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
} else if (msk & VDSO_RAW) {
return do_hres(&vd[CS_RAW], clock, ts);
}
+ return -1;
+}
+
+static __maybe_unused int
+__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+{
+ int ret = __cvdso_clock_gettime_common(clock, ts);
-fallback:
- return clock_gettime_fallback(clock, ts);
+ if (unlikely(ret))
+ return clock_gettime_fallback(clock, ts);
+ return 0;
}
static __maybe_unused int
@@ -115,20 +123,21 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
struct __kernel_timespec ts;
int ret;
- if (res == NULL)
- goto fallback;
+ ret = __cvdso_clock_gettime_common(clock, &ts);
- ret = __cvdso_clock_gettime(clock, &ts);
+#ifdef VDSO_HAS_32BIT_FALLBACK
+ if (unlikely(ret))
+ return clock_gettime32_fallback(clock, res);
+#else
+ if (unlikely(ret))
+ ret = clock_gettime_fallback(clock, &ts);
+#endif
- if (ret == 0) {
+ if (likely(!ret)) {
res->tv_sec = ts.tv_sec;
res->tv_nsec = ts.tv_nsec;
}
-
return ret;
-
-fallback:
- return clock_gettime_fallback(clock, (struct __kernel_timespec *)res);
}
static __maybe_unused int
@@ -169,17 +178,18 @@ static __maybe_unused time_t __cvdso_time(time_t *time)
#ifdef VDSO_HAS_CLOCK_GETRES
static __maybe_unused
-int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
{
const struct vdso_data *vd = __arch_get_vdso_data();
- u64 ns;
+ u64 hrtimer_res;
u32 msk;
- u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+ u64 ns;
/* Check for negative values or invalid clocks */
if (unlikely((u32) clock >= MAX_CLOCKS))
- goto fallback;
+ return -1;
+ hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
/*
* Convert the clockid to a bitmask and use it to check which
* clocks are handled in the VDSO directly.
@@ -201,18 +211,22 @@ int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
*/
ns = hrtimer_res;
} else {
- goto fallback;
+ return -1;
}
- if (res) {
- res->tv_sec = 0;
- res->tv_nsec = ns;
- }
+ res->tv_sec = 0;
+ res->tv_nsec = ns;
return 0;
+}
+
+int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+{
+ int ret = __cvdso_clock_getres_common(clock, res);
-fallback:
- return clock_getres_fallback(clock, res);
+ if (unlikely(ret))
+ return clock_getres_fallback(clock, res);
+ return 0;
}
static __maybe_unused int
@@ -221,19 +235,20 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
struct __kernel_timespec ts;
int ret;
- if (res == NULL)
- goto fallback;
+ ret = __cvdso_clock_getres_common(clock, &ts);
- ret = __cvdso_clock_getres(clock, &ts);
+#ifdef VDSO_HAS_32BIT_FALLBACK
+ if (unlikely(ret))
+ return clock_getres32_fallback(clock, res);
+#else
+ if (unlikely(ret))
+ ret = clock_getres_fallback(clock, &ts);
+#endif
- if (ret == 0) {
+ if (likely(!ret)) {
res->tv_sec = ts.tv_sec;
res->tv_nsec = ts.tv_nsec;
}
-
return ret;
-
-fallback:
- return clock_getres_fallback(clock, (struct __kernel_timespec *)res);
}
#endif /* VDSO_HAS_CLOCK_GETRES */
diff --git a/mm/Makefile b/mm/Makefile
index 338e528ad436..d0b295c3b764 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -102,5 +102,6 @@ obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
+obj-$(CONFIG_ZONE_DEVICE) += memremap.o
obj-$(CONFIG_HMM_MIRROR) += hmm.o
obj-$(CONFIG_MEMFD_CREATE) += memfd.o
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 83a7b614061f..26de020aae7b 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -21,7 +21,6 @@ static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
* memory corruption is possible and we should stop execution.
*/
BUG_ON(!trylock_page(page));
- list_del(&page->lru);
balloon_page_insert(b_dev_info, page);
unlock_page(page);
__count_vm_event(BALLOON_INFLATE);
@@ -33,8 +32,8 @@ static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
* @b_dev_info: balloon device descriptor where we will insert a new page to
* @pages: pages to enqueue - allocated using balloon_page_alloc.
*
- * Driver must call it to properly enqueue a balloon pages before definitively
- * removing it from the guest system.
+ * Driver must call this function to properly enqueue balloon pages before
+ * definitively removing them from the guest system.
*
* Return: number of pages that were enqueued.
*/
@@ -47,6 +46,7 @@ size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
list_for_each_entry_safe(page, tmp, pages, lru) {
+ list_del(&page->lru);
balloon_page_enqueue_one(b_dev_info, page);
n_pages++;
}
@@ -63,12 +63,13 @@ EXPORT_SYMBOL_GPL(balloon_page_list_enqueue);
* @n_req_pages: number of requested pages.
*
* Driver must call this function to properly de-allocate a previous enlisted
- * balloon pages before definetively releasing it back to the guest system.
+ * balloon pages before definitively releasing it back to the guest system.
* This function tries to remove @n_req_pages from the ballooned pages and
* return them to the caller in the @pages list.
*
- * Note that this function may fail to dequeue some pages temporarily empty due
- * to compaction isolated pages.
+ * Note that this function may fail to dequeue some pages even if the balloon
+ * isn't empty - since the page list can be temporarily empty due to compaction
+ * of isolated pages.
*
* Return: number of pages that were added to the @pages list.
*/
@@ -112,31 +113,35 @@ EXPORT_SYMBOL_GPL(balloon_page_list_dequeue);
/*
* balloon_page_alloc - allocates a new page for insertion into the balloon
- * page list.
+ * page list.
+ *
+ * Driver must call this function to properly allocate a new balloon page.
+ * Driver must call balloon_page_enqueue before definitively removing the page
+ * from the guest system.
*
- * Driver must call it to properly allocate a new enlisted balloon page.
- * Driver must call balloon_page_enqueue before definitively removing it from
- * the guest system. This function returns the page address for the recently
- * allocated page or NULL in the case we fail to allocate a new page this turn.
+ * Return: struct page for the allocated page or NULL on allocation failure.
*/
struct page *balloon_page_alloc(void)
{
struct page *page = alloc_page(balloon_mapping_gfp_mask() |
- __GFP_NOMEMALLOC | __GFP_NORETRY);
+ __GFP_NOMEMALLOC | __GFP_NORETRY |
+ __GFP_NOWARN);
return page;
}
EXPORT_SYMBOL_GPL(balloon_page_alloc);
/*
- * balloon_page_enqueue - allocates a new page and inserts it into the balloon
- * page list.
- * @b_dev_info: balloon device descriptor where we will insert a new page to
+ * balloon_page_enqueue - inserts a new page into the balloon page list.
+ *
+ * @b_dev_info: balloon device descriptor where we will insert a new page
* @page: new page to enqueue - allocated using balloon_page_alloc.
*
- * Driver must call it to properly enqueue a new allocated balloon page
- * before definitively removing it from the guest system.
- * This function returns the page address for the recently enqueued page or
- * NULL in the case we fail to allocate a new page this turn.
+ * Drivers must call this function to properly enqueue a new allocated balloon
+ * page before definitively removing the page from the guest system.
+ *
+ * Drivers must not call balloon_page_enqueue on pages that have been pushed to
+ * a list with balloon_page_push before removing them with balloon_page_pop. To
+ * enqueue a list of pages, use balloon_page_list_enqueue instead.
*/
void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
struct page *page)
@@ -151,14 +156,23 @@ EXPORT_SYMBOL_GPL(balloon_page_enqueue);
/*
* balloon_page_dequeue - removes a page from balloon's page list and returns
- * the its address to allow the driver release the page.
+ * its address to allow the driver to release the page.
* @b_dev_info: balloon device decriptor where we will grab a page from.
*
- * Driver must call it to properly de-allocate a previous enlisted balloon page
- * before definetively releasing it back to the guest system.
- * This function returns the page address for the recently dequeued page or
- * NULL in the case we find balloon's page list temporarily empty due to
- * compaction isolated pages.
+ * Driver must call this function to properly dequeue a previously enqueued page
+ * before definitively releasing it back to the guest system.
+ *
+ * Caller must perform its own accounting to ensure that this
+ * function is called only if some pages are actually enqueued.
+ *
+ * Note that this function may fail to dequeue some pages even if there are
+ * some enqueued pages - since the page list can be temporarily empty due to
+ * the compaction of isolated pages.
+ *
+ * TODO: remove the caller accounting requirements, and allow caller to wait
+ * until all pages can be dequeued.
+ *
+ * Return: struct page for the dequeued page, or NULL if no page was dequeued.
*/
struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
{
@@ -171,9 +185,9 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
if (n_pages != 1) {
/*
* If we are unable to dequeue a balloon page because the page
- * list is empty and there is no isolated pages, then something
+ * list is empty and there are no isolated pages, then something
* went out of track and some balloon pages are lost.
- * BUG() here, otherwise the balloon driver may get stuck into
+ * BUG() here, otherwise the balloon driver may get stuck in
* an infinite loop while attempting to release all its pages.
*/
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
@@ -224,8 +238,8 @@ int balloon_page_migrate(struct address_space *mapping,
/*
* We can not easily support the no copy case here so ignore it as it
- * is unlikely to be use with ballon pages. See include/linux/hmm.h for
- * user of the MIGRATE_SYNC_NO_COPY mode.
+ * is unlikely to be used with balloon pages. See include/linux/hmm.h
+ * for a user of the MIGRATE_SYNC_NO_COPY mode.
*/
if (mode == MIGRATE_SYNC_NO_COPY)
return -EINVAL;
diff --git a/mm/compaction.c b/mm/compaction.c
index 9e1b9acb116b..952dc2fb24e5 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -842,13 +842,15 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
/*
* Periodically drop the lock (if held) regardless of its
- * contention, to give chance to IRQs. Abort async compaction
- * if contended.
+ * contention, to give chance to IRQs. Abort completely if
+ * a fatal signal is pending.
*/
if (!(low_pfn % SWAP_CLUSTER_MAX)
&& compact_unlock_should_abort(&pgdat->lru_lock,
- flags, &locked, cc))
- break;
+ flags, &locked, cc)) {
+ low_pfn = 0;
+ goto fatal_pending;
+ }
if (!pfn_valid_within(low_pfn))
goto isolate_fail;
@@ -1060,6 +1062,7 @@ isolate_abort:
trace_mm_compaction_isolate_migratepages(start_pfn, low_pfn,
nr_scanned, nr_isolated);
+fatal_pending:
cc->total_migrate_scanned += nr_scanned;
if (nr_isolated)
count_compact_events(COMPACTISOLATED, nr_isolated);
diff --git a/mm/hmm.c b/mm/hmm.c
index e1eedef129cf..16b6731a34db 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -946,7 +946,7 @@ EXPORT_SYMBOL(hmm_range_unregister);
* @range: range
* Return: -EINVAL if invalid argument, -ENOMEM out of memory, -EPERM invalid
* permission (for instance asking for write and range is read only),
- * -EAGAIN if you need to retry, -EFAULT invalid (ie either no valid
+ * -EBUSY if you need to retry, -EFAULT invalid (ie either no valid
* vma or it is illegal to access that range), number of valid pages
* in range->pfns[] (from range start address).
*
@@ -967,7 +967,7 @@ long hmm_range_snapshot(struct hmm_range *range)
do {
/* If range is no longer valid force retry. */
if (!range->valid)
- return -EAGAIN;
+ return -EBUSY;
vma = find_vma(hmm->mm, start);
if (vma == NULL || (vma->vm_flags & device_vma))
@@ -1062,10 +1062,8 @@ long hmm_range_fault(struct hmm_range *range, bool block)
do {
/* If range is no longer valid force retry. */
- if (!range->valid) {
- up_read(&hmm->mm->mmap_sem);
- return -EAGAIN;
- }
+ if (!range->valid)
+ return -EBUSY;
vma = find_vma(hmm->mm, start);
if (vma == NULL || (vma->vm_flags & device_vma))
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1334ede667a8..de1f15969e27 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -32,6 +32,7 @@
#include <linux/shmem_fs.h>
#include <linux/oom.h>
#include <linux/numa.h>
+#include <linux/page_owner.h>
#include <asm/tlb.h>
#include <asm/pgalloc.h>
@@ -644,30 +645,40 @@ release:
* available
* never: never stall for any thp allocation
*/
-static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma)
+static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr)
{
const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+ gfp_t this_node = 0;
+
+#ifdef CONFIG_NUMA
+ struct mempolicy *pol;
+ /*
+ * __GFP_THISNODE is used only when __GFP_DIRECT_RECLAIM is not
+ * specified, to express a general desire to stay on the current
+ * node for optimistic allocation attempts. If the defrag mode
+ * and/or madvise hint requires the direct reclaim then we prefer
+ * to fallback to other node rather than node reclaim because that
+ * can lead to excessive reclaim even though there is free memory
+ * on other nodes. We expect that NUMA preferences are specified
+ * by memory policies.
+ */
+ pol = get_vma_policy(vma, addr);
+ if (pol->mode != MPOL_BIND)
+ this_node = __GFP_THISNODE;
+ mpol_cond_put(pol);
+#endif
- /* Always do synchronous compaction */
if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
-
- /* Kick kcompactd and fail quickly */
if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
- return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
-
- /* Synchronous compaction if madvised, otherwise kick kcompactd */
+ return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM | this_node;
if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
- return GFP_TRANSHUGE_LIGHT |
- (vma_madvised ? __GFP_DIRECT_RECLAIM :
- __GFP_KSWAPD_RECLAIM);
-
- /* Only do synchronous compaction if madvised */
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ __GFP_KSWAPD_RECLAIM | this_node);
if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
- return GFP_TRANSHUGE_LIGHT |
- (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
-
- return GFP_TRANSHUGE_LIGHT;
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ this_node);
+ return GFP_TRANSHUGE_LIGHT | this_node;
}
/* Caller must hold page table lock. */
@@ -739,8 +750,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
pte_free(vma->vm_mm, pgtable);
return ret;
}
- gfp = alloc_hugepage_direct_gfpmask(vma);
- page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER);
+ gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+ page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id());
if (unlikely(!page)) {
count_vm_event(THP_FAULT_FALLBACK);
return VM_FAULT_FALLBACK;
@@ -1347,8 +1358,9 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
alloc:
if (__transparent_hugepage_enabled(vma) &&
!transparent_hugepage_debug_cow()) {
- huge_gfp = alloc_hugepage_direct_gfpmask(vma);
- new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
+ huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+ new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma,
+ haddr, numa_node_id());
} else
new_page = NULL;
@@ -2505,6 +2517,9 @@ static void __split_huge_page(struct page *page, struct list_head *list,
}
ClearPageCompound(head);
+
+ split_page_owner(head, HPAGE_PMD_ORDER);
+
/* See comment in __split_huge_page_tail() */
if (PageAnon(head)) {
/* Additional pin to swap cache */
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ede7e7f5d1ab..6d7296dd11b8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3856,6 +3856,25 @@ retry:
page = alloc_huge_page(vma, haddr, 0);
if (IS_ERR(page)) {
+ /*
+ * Returning error will result in faulting task being
+ * sent SIGBUS. The hugetlb fault mutex prevents two
+ * tasks from racing to fault in the same page which
+ * could result in false unable to allocate errors.
+ * Page migration does not take the fault mutex, but
+ * does a clear then write of pte's under page table
+ * lock. Page fault code could race with migration,
+ * notice the clear pte and try to allocate a page
+ * here. Before returning error, get ptl and make
+ * sure there really is no pte entry.
+ */
+ ptl = huge_pte_lock(h, mm, ptep);
+ if (!huge_pte_none(huge_ptep_get(ptep))) {
+ ret = 0;
+ spin_unlock(ptl);
+ goto out;
+ }
+ spin_unlock(ptl);
ret = vmf_error(PTR_ERR(page));
goto out;
}
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2277b82902d8..95d16a42db6b 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -407,8 +407,14 @@ static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
if (IS_ENABLED(CONFIG_KASAN_GENERIC))
return shadow_byte < 0 ||
shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
- else
- return tag != (u8)shadow_byte;
+
+ /* else CONFIG_KASAN_SW_TAGS: */
+ if ((u8)shadow_byte == KASAN_TAG_INVALID)
+ return true;
+ if ((tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte))
+ return true;
+
+ return false;
}
static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index eaaa21b23215..ccede2425c3f 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -710,7 +710,7 @@ static bool khugepaged_scan_abort(int nid)
for (i = 0; i < MAX_NUMNODES; i++) {
if (!khugepaged_node_load[i])
continue;
- if (node_distance(nid, i) > RECLAIM_DISTANCE)
+ if (node_distance(nid, i) > node_reclaim_distance)
return true;
}
return false;
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index dbbd518fb6b3..f6e602918dac 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -114,7 +114,7 @@
/* GFP bitmask for kmemleak internal allocations */
#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC)) | \
__GFP_NORETRY | __GFP_NOMEMALLOC | \
- __GFP_NOWARN | __GFP_NOFAIL)
+ __GFP_NOWARN)
/* scanning area inside a memory block */
struct kmemleak_scan_area {
@@ -1966,6 +1966,7 @@ static void kmemleak_disable(void)
/* stop any memory operation tracing */
kmemleak_enabled = 0;
+ kmemleak_early_log = 0;
/* check whether it is too early for a kernel thread */
if (kmemleak_initialized)
@@ -2009,7 +2010,6 @@ void __init kmemleak_init(void)
#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
if (!kmemleak_skip_disable) {
- kmemleak_early_log = 0;
kmemleak_disable();
return;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index cdbb7a84cb6e..9ec5e12486a7 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -752,15 +752,13 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
/* Update memcg */
__mod_memcg_state(memcg, idx, val);
+ /* Update lruvec */
+ __this_cpu_add(pn->lruvec_stat_local->count[idx], val);
+
x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]);
if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
struct mem_cgroup_per_node *pi;
- /*
- * Batch local counters to keep them in sync with
- * the hierarchical ones.
- */
- __this_cpu_add(pn->lruvec_stat_local->count[idx], x);
for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id))
atomic_long_add(x, &pi->lruvec_stat[idx]);
x = 0;
@@ -768,6 +766,26 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
__this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
}
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
+{
+ struct page *page = virt_to_head_page(p);
+ pg_data_t *pgdat = page_pgdat(page);
+ struct mem_cgroup *memcg;
+ struct lruvec *lruvec;
+
+ rcu_read_lock();
+ memcg = memcg_from_slab_page(page);
+
+ /* Untracked pages have no memcg, no lruvec. Update only the node */
+ if (!memcg || memcg == root_mem_cgroup) {
+ __mod_node_page_state(pgdat, idx, val);
+ } else {
+ lruvec = mem_cgroup_lruvec(pgdat, memcg);
+ __mod_lruvec_state(lruvec, idx, val);
+ }
+ rcu_read_unlock();
+}
+
/**
* __count_memcg_events - account VM events in a cgroup
* @memcg: the memory cgroup
@@ -1130,26 +1148,45 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
css_put(&prev->css);
}
-static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+static void __invalidate_reclaim_iterators(struct mem_cgroup *from,
+ struct mem_cgroup *dead_memcg)
{
- struct mem_cgroup *memcg = dead_memcg;
struct mem_cgroup_reclaim_iter *iter;
struct mem_cgroup_per_node *mz;
int nid;
int i;
- for (; memcg; memcg = parent_mem_cgroup(memcg)) {
- for_each_node(nid) {
- mz = mem_cgroup_nodeinfo(memcg, nid);
- for (i = 0; i <= DEF_PRIORITY; i++) {
- iter = &mz->iter[i];
- cmpxchg(&iter->position,
- dead_memcg, NULL);
- }
+ for_each_node(nid) {
+ mz = mem_cgroup_nodeinfo(from, nid);
+ for (i = 0; i <= DEF_PRIORITY; i++) {
+ iter = &mz->iter[i];
+ cmpxchg(&iter->position,
+ dead_memcg, NULL);
}
}
}
+static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+{
+ struct mem_cgroup *memcg = dead_memcg;
+ struct mem_cgroup *last;
+
+ do {
+ __invalidate_reclaim_iterators(memcg, dead_memcg);
+ last = memcg;
+ } while ((memcg = parent_mem_cgroup(memcg)));
+
+ /*
+ * When cgruop1 non-hierarchy mode is used,
+ * parent_mem_cgroup() does not walk all the way up to the
+ * cgroup root (root_mem_cgroup). So we have to handle
+ * dead_memcg from cgroup root separately.
+ */
+ if (last != root_mem_cgroup)
+ __invalidate_reclaim_iterators(root_mem_cgroup,
+ dead_memcg);
+}
+
/**
* mem_cgroup_scan_tasks - iterate over tasks of a memory cgroup hierarchy
* @memcg: hierarchy root
@@ -3221,6 +3258,72 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
}
}
+static void memcg_flush_percpu_vmstats(struct mem_cgroup *memcg, bool slab_only)
+{
+ unsigned long stat[MEMCG_NR_STAT];
+ struct mem_cgroup *mi;
+ int node, cpu, i;
+ int min_idx, max_idx;
+
+ if (slab_only) {
+ min_idx = NR_SLAB_RECLAIMABLE;
+ max_idx = NR_SLAB_UNRECLAIMABLE;
+ } else {
+ min_idx = 0;
+ max_idx = MEMCG_NR_STAT;
+ }
+
+ for (i = min_idx; i < max_idx; i++)
+ stat[i] = 0;
+
+ for_each_online_cpu(cpu)
+ for (i = min_idx; i < max_idx; i++)
+ stat[i] += per_cpu(memcg->vmstats_percpu->stat[i], cpu);
+
+ for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+ for (i = min_idx; i < max_idx; i++)
+ atomic_long_add(stat[i], &mi->vmstats[i]);
+
+ if (!slab_only)
+ max_idx = NR_VM_NODE_STAT_ITEMS;
+
+ for_each_node(node) {
+ struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
+ struct mem_cgroup_per_node *pi;
+
+ for (i = min_idx; i < max_idx; i++)
+ stat[i] = 0;
+
+ for_each_online_cpu(cpu)
+ for (i = min_idx; i < max_idx; i++)
+ stat[i] += per_cpu(
+ pn->lruvec_stat_cpu->count[i], cpu);
+
+ for (pi = pn; pi; pi = parent_nodeinfo(pi, node))
+ for (i = min_idx; i < max_idx; i++)
+ atomic_long_add(stat[i], &pi->lruvec_stat[i]);
+ }
+}
+
+static void memcg_flush_percpu_vmevents(struct mem_cgroup *memcg)
+{
+ unsigned long events[NR_VM_EVENT_ITEMS];
+ struct mem_cgroup *mi;
+ int cpu, i;
+
+ for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+ events[i] = 0;
+
+ for_each_online_cpu(cpu)
+ for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+ events[i] += per_cpu(memcg->vmstats_percpu->events[i],
+ cpu);
+
+ for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+ for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+ atomic_long_add(events[i], &mi->vmevents[i]);
+}
+
#ifdef CONFIG_MEMCG_KMEM
static int memcg_online_kmem(struct mem_cgroup *memcg)
{
@@ -3270,7 +3373,14 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
if (!parent)
parent = root_mem_cgroup;
+ /*
+ * Deactivate and reparent kmem_caches. Then flush percpu
+ * slab statistics to have precise values at the parent and
+ * all ancestor levels. It's required to keep slab stats
+ * accurate after the reparenting of kmem_caches.
+ */
memcg_deactivate_kmem_caches(memcg, parent);
+ memcg_flush_percpu_vmstats(memcg, true);
kmemcg_id = memcg->kmemcg_id;
BUG_ON(kmemcg_id < 0);
@@ -4643,6 +4753,12 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
{
int node;
+ /*
+ * Flush percpu vmstats and vmevents to guarantee the value correctness
+ * on parent's and all ancestor levels.
+ */
+ memcg_flush_percpu_vmstats(memcg, false);
+ memcg_flush_percpu_vmevents(memcg);
for_each_node(node)
free_mem_cgroup_per_node_info(memcg, node);
free_percpu(memcg->vmstats_percpu);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 2a9bbddb0e55..c73f09913165 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -132,7 +132,6 @@ static void release_memory_resource(struct resource *res)
return;
release_resource(res);
kfree(res);
- return;
}
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
@@ -979,7 +978,6 @@ static void rollback_node_hotadd(int nid)
arch_refresh_nodedata(nid, NULL);
free_percpu(pgdat->per_cpu_nodestats);
arch_free_nodedata(pgdat);
- return;
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f48693f75b37..65e0874fce17 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -403,7 +403,7 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
},
};
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
unsigned long flags);
struct queue_pages {
@@ -429,11 +429,14 @@ static inline bool queue_pages_required(struct page *page,
}
/*
- * queue_pages_pmd() has three possible return values:
- * 1 - pages are placed on the right node or queued successfully.
- * 0 - THP was split.
- * -EIO - is migration entry or MPOL_MF_STRICT was specified and an existing
- * page was already on a node that does not follow the policy.
+ * queue_pages_pmd() has four possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ * specified.
+ * 2 - THP was split.
+ * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
+ * existing page was already on a node that does not follow the
+ * policy.
*/
static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
unsigned long end, struct mm_walk *walk)
@@ -451,23 +454,20 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
if (is_huge_zero_page(page)) {
spin_unlock(ptl);
__split_huge_pmd(walk->vma, pmd, addr, false, NULL);
+ ret = 2;
goto out;
}
- if (!queue_pages_required(page, qp)) {
- ret = 1;
+ if (!queue_pages_required(page, qp))
goto unlock;
- }
- ret = 1;
flags = qp->flags;
/* go to thp migration */
if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
- if (!vma_migratable(walk->vma)) {
- ret = -EIO;
+ if (!vma_migratable(walk->vma) ||
+ migrate_page_add(page, qp->pagelist, flags)) {
+ ret = 1;
goto unlock;
}
-
- migrate_page_add(page, qp->pagelist, flags);
} else
ret = -EIO;
unlock:
@@ -479,6 +479,13 @@ out:
/*
* Scan through pages checking if pages follow certain conditions,
* and move them to the pagelist if they do.
+ *
+ * queue_pages_pte_range() has three possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ * specified.
+ * -EIO - only MPOL_MF_STRICT was specified and an existing page was already
+ * on a node that does not follow the policy.
*/
static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
unsigned long end, struct mm_walk *walk)
@@ -488,17 +495,17 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
struct queue_pages *qp = walk->private;
unsigned long flags = qp->flags;
int ret;
+ bool has_unmovable = false;
pte_t *pte;
spinlock_t *ptl;
ptl = pmd_trans_huge_lock(pmd, vma);
if (ptl) {
ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
- if (ret > 0)
- return 0;
- else if (ret < 0)
+ if (ret != 2)
return ret;
}
+ /* THP was split, fall through to pte walk */
if (pmd_trans_unstable(pmd))
return 0;
@@ -519,14 +526,28 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
if (!queue_pages_required(page, qp))
continue;
if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
- if (!vma_migratable(vma))
+ /* MPOL_MF_STRICT must be specified if we get here */
+ if (!vma_migratable(vma)) {
+ has_unmovable = true;
break;
- migrate_page_add(page, qp->pagelist, flags);
+ }
+
+ /*
+ * Do not abort immediately since there may be
+ * temporary off LRU pages in the range. Still
+ * need migrate other LRU pages.
+ */
+ if (migrate_page_add(page, qp->pagelist, flags))
+ has_unmovable = true;
} else
break;
}
pte_unmap_unlock(pte - 1, ptl);
cond_resched();
+
+ if (has_unmovable)
+ return 1;
+
return addr != end ? -EIO : 0;
}
@@ -639,7 +660,13 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
*
* If pages found in a given range are on a set of nodes (determined by
* @nodes and @flags,) it's isolated and queued to the pagelist which is
- * passed via @private.)
+ * passed via @private.
+ *
+ * queue_pages_range() has three possible return values:
+ * 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ * specified.
+ * 0 - queue pages successfully or no misplaced page.
+ * -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
*/
static int
queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
@@ -940,7 +967,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
/*
* page migration, thp tail pages can be passed.
*/
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
unsigned long flags)
{
struct page *head = compound_head(page);
@@ -953,8 +980,19 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
mod_node_page_state(page_pgdat(head),
NR_ISOLATED_ANON + page_is_file_cache(head),
hpage_nr_pages(head));
+ } else if (flags & MPOL_MF_STRICT) {
+ /*
+ * Non-movable page may reach here. And, there may be
+ * temporary off LRU pages or non-LRU movable pages.
+ * Treat them as unmovable pages since they can't be
+ * isolated, so they can't be moved at the moment. It
+ * should return -EIO for this case too.
+ */
+ return -EIO;
}
}
+
+ return 0;
}
/* page allocation callback for NUMA node migration */
@@ -1142,8 +1180,8 @@ static struct page *new_page(struct page *page, unsigned long start)
} else if (PageTransHuge(page)) {
struct page *thp;
- thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
- HPAGE_PMD_ORDER);
+ thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma,
+ address, numa_node_id());
if (!thp)
return NULL;
prep_transhuge_page(thp);
@@ -1157,9 +1195,10 @@ static struct page *new_page(struct page *page, unsigned long start)
}
#else
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
unsigned long flags)
{
+ return -EIO;
}
int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
@@ -1182,6 +1221,7 @@ static long do_mbind(unsigned long start, unsigned long len,
struct mempolicy *new;
unsigned long end;
int err;
+ int ret;
LIST_HEAD(pagelist);
if (flags & ~(unsigned long)MPOL_MF_VALID)
@@ -1243,10 +1283,15 @@ static long do_mbind(unsigned long start, unsigned long len,
if (err)
goto mpol_out;
- err = queue_pages_range(mm, start, end, nmask,
+ ret = queue_pages_range(mm, start, end, nmask,
flags | MPOL_MF_INVERT, &pagelist);
- if (!err)
- err = mbind_range(mm, start, end, new);
+
+ if (ret < 0) {
+ err = -EIO;
+ goto up_out;
+ }
+
+ err = mbind_range(mm, start, end, new);
if (!err) {
int nr_failed = 0;
@@ -1259,13 +1304,14 @@ static long do_mbind(unsigned long start, unsigned long len,
putback_movable_pages(&pagelist);
}
- if (nr_failed && (flags & MPOL_MF_STRICT))
+ if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
err = -EIO;
} else
putback_movable_pages(&pagelist);
+up_out:
up_write(&mm->mmap_sem);
- mpol_out:
+mpol_out:
mpol_put(new);
return err;
}
@@ -1688,7 +1734,7 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
* freeing by another task. It is the caller's responsibility to free the
* extra reference for shared policies.
*/
-static struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
unsigned long addr)
{
struct mempolicy *pol = __get_vma_policy(vma, addr);
@@ -2037,7 +2083,6 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
* @vma: Pointer to VMA or NULL if not available.
* @addr: Virtual Address of the allocation. Must be inside the VMA.
* @node: Which node to prefer for allocation (modulo policy).
- * @hugepage: for hugepages try only the preferred node if possible
*
* This function allocates a page from the kernel page pool and applies
* a NUMA policy associated with the VMA or the current process.
@@ -2048,7 +2093,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
*/
struct page *
alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
- unsigned long addr, int node, bool hugepage)
+ unsigned long addr, int node)
{
struct mempolicy *pol;
struct page *page;
@@ -2066,31 +2111,6 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
goto out;
}
- if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
- int hpage_node = node;
-
- /*
- * For hugepage allocation and non-interleave policy which
- * allows the current node (or other explicitly preferred
- * node) we only try to allocate from the current/preferred
- * node and don't fall back to other nodes, as the cost of
- * remote accesses would likely offset THP benefits.
- *
- * If the policy is interleave, or does not allow the current
- * node in its nodemask, we allocate the standard way.
- */
- if (pol->mode == MPOL_PREFERRED && !(pol->flags & MPOL_F_LOCAL))
- hpage_node = pol->v.preferred_node;
-
- nmask = policy_nodemask(gfp, pol);
- if (!nmask || node_isset(hpage_node, *nmask)) {
- mpol_cond_put(pol);
- page = __alloc_pages_node(hpage_node,
- gfp | __GFP_THISNODE, order);
- goto out;
- }
- }
-
nmask = policy_nodemask(gfp, pol);
preferred_nid = policy_node(gfp, pol, node);
page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask);
diff --git a/kernel/memremap.c b/mm/memremap.c
index 6ee03a816d67..ed70c4e8e52a 100644
--- a/kernel/memremap.c
+++ b/mm/memremap.c
@@ -91,6 +91,12 @@ static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
wait_for_completion(&pgmap->done);
percpu_ref_exit(pgmap->ref);
}
+ /*
+ * Undo the pgmap ref assignment for the internal case as the
+ * caller may re-enable the same pgmap.
+ */
+ if (pgmap->ref == &pgmap->internal_ref)
+ pgmap->ref = NULL;
}
static void devm_memremap_pages_release(void *data)
@@ -397,6 +403,30 @@ void __put_devmap_managed_page(struct page *page)
mem_cgroup_uncharge(page);
+ /*
+ * When a device_private page is freed, the page->mapping field
+ * may still contain a (stale) mapping value. For example, the
+ * lower bits of page->mapping may still identify the page as
+ * an anonymous page. Ultimately, this entire field is just
+ * stale and wrong, and it will cause errors if not cleared.
+ * One example is:
+ *
+ * migrate_vma_pages()
+ * migrate_vma_insert_page()
+ * page_add_new_anon_rmap()
+ * __page_set_anon_rmap()
+ * ...checks page->mapping, via PageAnon(page) call,
+ * and incorrectly concludes that the page is an
+ * anonymous page. Therefore, it incorrectly,
+ * silently fails to set up the new anon rmap.
+ *
+ * For other types of ZONE_DEVICE pages, migration is either
+ * handled differently or not done at all, so there is no need
+ * to clear page->mapping.
+ */
+ if (is_device_private_page(page))
+ page->mapping = NULL;
+
page->pgmap->ops->page_free(page);
} else if (!count)
__put_page(page);
diff --git a/mm/migrate.c b/mm/migrate.c
index 8992741f10aa..a42858d8e00b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -767,12 +767,12 @@ recheck_buffers:
}
bh = bh->b_this_page;
} while (bh != head);
- spin_unlock(&mapping->private_lock);
if (busy) {
if (invalidated) {
rc = -EAGAIN;
goto unlock_buffers;
}
+ spin_unlock(&mapping->private_lock);
invalidate_bh_lrus();
invalidated = true;
goto recheck_buffers;
@@ -805,6 +805,8 @@ recheck_buffers:
rc = MIGRATEPAGE_SUCCESS;
unlock_buffers:
+ if (check_refs)
+ spin_unlock(&mapping->private_lock);
bh = head;
do {
unlock_buffer(bh);
@@ -2338,16 +2340,13 @@ next:
static void migrate_vma_collect(struct migrate_vma *migrate)
{
struct mmu_notifier_range range;
- struct mm_walk mm_walk;
-
- mm_walk.pmd_entry = migrate_vma_collect_pmd;
- mm_walk.pte_entry = NULL;
- mm_walk.pte_hole = migrate_vma_collect_hole;
- mm_walk.hugetlb_entry = NULL;
- mm_walk.test_walk = NULL;
- mm_walk.vma = migrate->vma;
- mm_walk.mm = migrate->vma->vm_mm;
- mm_walk.private = migrate;
+ struct mm_walk mm_walk = {
+ .pmd_entry = migrate_vma_collect_pmd,
+ .pte_hole = migrate_vma_collect_hole,
+ .vma = migrate->vma,
+ .mm = migrate->vma->vm_mm,
+ .private = migrate,
+ };
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm_walk.mm,
migrate->start,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 272c6de1bf4e..6991ccec9c32 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2238,27 +2238,12 @@ static int move_freepages(struct zone *zone,
unsigned int order;
int pages_moved = 0;
-#ifndef CONFIG_HOLES_IN_ZONE
- /*
- * page_zone is not safe to call in this context when
- * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
- * anyway as we check zone boundaries in move_freepages_block().
- * Remove at a later date when no bug reports exist related to
- * grouping pages by mobility
- */
- VM_BUG_ON(pfn_valid(page_to_pfn(start_page)) &&
- pfn_valid(page_to_pfn(end_page)) &&
- page_zone(start_page) != page_zone(end_page));
-#endif
for (page = start_page; page <= end_page;) {
if (!pfn_valid_within(page_to_pfn(page))) {
page++;
continue;
}
- /* Make sure we are not inadvertently changing nodes */
- VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
-
if (!PageBuddy(page)) {
/*
* We assume that pages that could be isolated for
@@ -2273,6 +2258,10 @@ static int move_freepages(struct zone *zone,
continue;
}
+ /* Make sure we are not inadvertently changing nodes */
+ VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
+ VM_BUG_ON_PAGE(page_zone(page) != zone, page);
+
order = page_order(page);
move_to_free_area(page, &zone->free_area[order], migratetype);
page += 1 << order;
@@ -3522,7 +3511,7 @@ bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
{
return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <=
- RECLAIM_DISTANCE;
+ node_reclaim_distance;
}
#else /* CONFIG_NUMA */
static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
diff --git a/mm/rmap.c b/mm/rmap.c
index e5dfe2ae6b0d..003377e24232 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1475,7 +1475,15 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
/*
* No need to invalidate here it will synchronize on
* against the special swap migration pte.
+ *
+ * The assignment to subpage above was computed from a
+ * swap PTE which results in an invalid pointer.
+ * Since only PAGE_SIZE pages can currently be
+ * migrated, just set it to page. This will need to be
+ * changed when hugepage migrations to device private
+ * memory are supported.
*/
+ subpage = page;
goto discard;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 626d8c74b973..2bed4761f279 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1466,7 +1466,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
shmem_pseudo_vma_init(&pvma, info, hindex);
page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN,
- HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true);
+ HPAGE_PMD_ORDER, &pvma, 0, numa_node_id());
shmem_pseudo_vma_destroy(&pvma);
if (page)
prep_transhuge_page(page);
diff --git a/mm/slub.c b/mm/slub.c
index e6c030e47364..8834563cdb4b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1432,7 +1432,9 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
void *old_tail = *tail ? *tail : *head;
int rsize;
- if (slab_want_init_on_free(s))
+ if (slab_want_init_on_free(s)) {
+ void *p = NULL;
+
do {
object = next;
next = get_freepointer(s, object);
@@ -1445,8 +1447,10 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
: 0;
memset((char *)object + s->inuse, 0,
s->size - s->inuse - rsize);
- set_freepointer(s, object, next);
+ set_freepointer(s, object, p);
+ p = object;
} while (object != old_tail);
+ }
/*
* Compiler cannot detect this function can be removed if slab_free_hook()
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 2a09796edef8..98e924864554 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -147,7 +147,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n,
bool to_user)
{
/* Reject if object wraps past end of memory. */
- if (ptr + n < ptr)
+ if (ptr + (n - 1) < ptr)
usercopy_abort("wrapped address", NULL, to_user, 0, ptr + n);
/* Reject if NULL or ZERO-allocation. */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 4fa8d84599b0..7ba11e12a11f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1259,6 +1259,12 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
return false;
/*
+ * First make sure the mappings are removed from all page-tables
+ * before they are freed.
+ */
+ vmalloc_sync_all();
+
+ /*
* TODO: to calculate a flush range without looping.
* The list can be up to lazy_max_pages() elements.
*/
@@ -3038,6 +3044,9 @@ EXPORT_SYMBOL(remap_vmalloc_range);
/*
* Implement a stub for vmalloc_sync_all() if the architecture chose not to
* have one.
+ *
+ * The purpose of this function is to make sure the vmalloc area
+ * mappings are identical in all page-tables in the system.
*/
void __weak vmalloc_sync_all(void)
{
@@ -3270,9 +3279,19 @@ retry:
goto overflow;
/*
+ * If required width exeeds current VA block, move
+ * base downwards and then recheck.
+ */
+ if (base + end > va->va_end) {
+ base = pvm_determine_end_from_reverse(&va, align) - end;
+ term_area = area;
+ continue;
+ }
+
+ /*
* If this VA does not fit, move base downwards and recheck.
*/
- if (base + start < va->va_start || base + end > va->va_end) {
+ if (base + start < va->va_start) {
va = node_to_va(rb_prev(&va->rb_node));
base = pvm_determine_end_from_reverse(&va, align) - end;
term_area = area;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 44df66a98f2a..a6c5d0b28321 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -88,9 +88,6 @@ struct scan_control {
/* Can pages be swapped as part of reclaim? */
unsigned int may_swap:1;
- /* e.g. boosted watermark reclaim leaves slabs alone */
- unsigned int may_shrinkslab:1;
-
/*
* Cgroups are not reclaimed below their configured memory.low,
* unless we threaten to OOM. If any cgroups are skipped due to
@@ -699,7 +696,14 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
unsigned long ret, freed = 0;
struct shrinker *shrinker;
- if (!mem_cgroup_is_root(memcg))
+ /*
+ * The root memcg might be allocated even though memcg is disabled
+ * via "cgroup_disable=memory" boot parameter. This could make
+ * mem_cgroup_is_root() return false, then just run memcg slab
+ * shrink, but skip global shrink. This may result in premature
+ * oom.
+ */
+ if (!mem_cgroup_disabled() && !mem_cgroup_is_root(memcg))
return shrink_slab_memcg(gfp_mask, nid, memcg, priority);
if (!down_read_trylock(&shrinker_rwsem))
@@ -2707,10 +2711,8 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc)
shrink_node_memcg(pgdat, memcg, sc, &lru_pages);
node_lru_pages += lru_pages;
- if (sc->may_shrinkslab) {
- shrink_slab(sc->gfp_mask, pgdat->node_id,
- memcg, sc->priority);
- }
+ shrink_slab(sc->gfp_mask, pgdat->node_id, memcg,
+ sc->priority);
/* Record the group's reclaim efficiency */
vmpressure(sc->gfp_mask, memcg, false,
@@ -3187,7 +3189,6 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
.may_writepage = !laptop_mode,
.may_unmap = 1,
.may_swap = 1,
- .may_shrinkslab = 1,
};
/*
@@ -3219,6 +3220,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
#ifdef CONFIG_MEMCG
+/* Only used by soft limit reclaim. Do not reuse for anything else. */
unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
gfp_t gfp_mask, bool noswap,
pg_data_t *pgdat,
@@ -3231,11 +3233,11 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
.may_unmap = 1,
.reclaim_idx = MAX_NR_ZONES - 1,
.may_swap = !noswap,
- .may_shrinkslab = 1,
};
unsigned long lru_pages;
- set_task_reclaim_state(current, &sc.reclaim_state);
+ WARN_ON_ONCE(!current->reclaim_state);
+
sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
(GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
@@ -3253,7 +3255,6 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed);
- set_task_reclaim_state(current, NULL);
*nr_scanned = sc.nr_scanned;
return sc.nr_reclaimed;
@@ -3279,7 +3280,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
.may_writepage = !laptop_mode,
.may_unmap = 1,
.may_swap = may_swap,
- .may_shrinkslab = 1,
};
set_task_reclaim_state(current, &sc.reclaim_state);
@@ -3591,7 +3591,6 @@ restart:
*/
sc.may_writepage = !laptop_mode && !nr_boost_reclaim;
sc.may_swap = !nr_boost_reclaim;
- sc.may_shrinkslab = !nr_boost_reclaim;
/*
* Do some background aging of the anon list, to give
diff --git a/mm/workingset.c b/mm/workingset.c
index e0b4edcb88c8..c963831d354f 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -380,14 +380,12 @@ void workingset_update_node(struct xa_node *node)
if (node->count && node->count == node->nr_values) {
if (list_empty(&node->private_list)) {
list_lru_add(&shadow_nodes, &node->private_list);
- __inc_lruvec_page_state(virt_to_page(node),
- WORKINGSET_NODES);
+ __inc_lruvec_slab_state(node, WORKINGSET_NODES);
}
} else {
if (!list_empty(&node->private_list)) {
list_lru_del(&shadow_nodes, &node->private_list);
- __dec_lruvec_page_state(virt_to_page(node),
- WORKINGSET_NODES);
+ __dec_lruvec_slab_state(node, WORKINGSET_NODES);
}
}
}
@@ -480,7 +478,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
}
list_lru_isolate(lru, item);
- __dec_lruvec_page_state(virt_to_page(node), WORKINGSET_NODES);
+ __dec_lruvec_slab_state(node, WORKINGSET_NODES);
spin_unlock(lru_lock);
@@ -503,7 +501,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
* shadow entries we were tracking ...
*/
xas_store(&xas, NULL);
- __inc_lruvec_page_state(virt_to_page(node), WORKINGSET_NODERECLAIM);
+ __inc_lruvec_slab_state(node, WORKINGSET_NODERECLAIM);
out_invalid:
xa_unlock_irq(&mapping->i_pages);
diff --git a/mm/z3fold.c b/mm/z3fold.c
index 1a029a7432ee..75b7962439ff 100644
--- a/mm/z3fold.c
+++ b/mm/z3fold.c
@@ -41,6 +41,7 @@
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/wait.h>
#include <linux/zpool.h>
#include <linux/magic.h>
@@ -145,6 +146,8 @@ struct z3fold_header {
* @release_wq: workqueue for safe page release
* @work: work_struct for safe page release
* @inode: inode for z3fold pseudo filesystem
+ * @destroying: bool to stop migration once we start destruction
+ * @isolated: int to count the number of pages currently in isolation
*
* This structure is allocated at pool creation time and maintains metadata
* pertaining to a particular z3fold pool.
@@ -163,8 +166,11 @@ struct z3fold_pool {
const struct zpool_ops *zpool_ops;
struct workqueue_struct *compact_wq;
struct workqueue_struct *release_wq;
+ struct wait_queue_head isolate_wait;
struct work_struct work;
struct inode *inode;
+ bool destroying;
+ int isolated;
};
/*
@@ -769,6 +775,7 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
goto out_c;
spin_lock_init(&pool->lock);
spin_lock_init(&pool->stale_lock);
+ init_waitqueue_head(&pool->isolate_wait);
pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
if (!pool->unbuddied)
goto out_pool;
@@ -808,6 +815,15 @@ out:
return NULL;
}
+static bool pool_isolated_are_drained(struct z3fold_pool *pool)
+{
+ bool ret;
+
+ spin_lock(&pool->lock);
+ ret = pool->isolated == 0;
+ spin_unlock(&pool->lock);
+ return ret;
+}
/**
* z3fold_destroy_pool() - destroys an existing z3fold pool
* @pool: the z3fold pool to be destroyed
@@ -817,9 +833,35 @@ out:
static void z3fold_destroy_pool(struct z3fold_pool *pool)
{
kmem_cache_destroy(pool->c_handle);
- z3fold_unregister_migration(pool);
- destroy_workqueue(pool->release_wq);
+ /*
+ * We set pool-> destroying under lock to ensure that
+ * z3fold_page_isolate() sees any changes to destroying. This way we
+ * avoid the need for any memory barriers.
+ */
+
+ spin_lock(&pool->lock);
+ pool->destroying = true;
+ spin_unlock(&pool->lock);
+
+ /*
+ * We need to ensure that no pages are being migrated while we destroy
+ * these workqueues, as migration can queue work on either of the
+ * workqueues.
+ */
+ wait_event(pool->isolate_wait, !pool_isolated_are_drained(pool));
+
+ /*
+ * We need to destroy pool->compact_wq before pool->release_wq,
+ * as any pending work on pool->compact_wq will call
+ * queue_work(pool->release_wq, &pool->work).
+ *
+ * There are still outstanding pages until both workqueues are drained,
+ * so we cannot unregister migration until then.
+ */
+
destroy_workqueue(pool->compact_wq);
+ destroy_workqueue(pool->release_wq);
+ z3fold_unregister_migration(pool);
kfree(pool);
}
@@ -1297,6 +1339,28 @@ static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
return atomic64_read(&pool->pages_nr);
}
+/*
+ * z3fold_dec_isolated() expects to be called while pool->lock is held.
+ */
+static void z3fold_dec_isolated(struct z3fold_pool *pool)
+{
+ assert_spin_locked(&pool->lock);
+ VM_BUG_ON(pool->isolated <= 0);
+ pool->isolated--;
+
+ /*
+ * If we have no more isolated pages, we have to see if
+ * z3fold_destroy_pool() is waiting for a signal.
+ */
+ if (pool->isolated == 0 && waitqueue_active(&pool->isolate_wait))
+ wake_up_all(&pool->isolate_wait);
+}
+
+static void z3fold_inc_isolated(struct z3fold_pool *pool)
+{
+ pool->isolated++;
+}
+
static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
{
struct z3fold_header *zhdr;
@@ -1323,6 +1387,34 @@ static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
spin_lock(&pool->lock);
if (!list_empty(&page->lru))
list_del(&page->lru);
+ /*
+ * We need to check for destruction while holding pool->lock, as
+ * otherwise destruction could see 0 isolated pages, and
+ * proceed.
+ */
+ if (unlikely(pool->destroying)) {
+ spin_unlock(&pool->lock);
+ /*
+ * If this page isn't stale, somebody else holds a
+ * reference to it. Let't drop our refcount so that they
+ * can call the release logic.
+ */
+ if (unlikely(kref_put(&zhdr->refcount,
+ release_z3fold_page_locked))) {
+ /*
+ * If we get here we have kref problems, so we
+ * should freak out.
+ */
+ WARN(1, "Z3fold is experiencing kref problems\n");
+ z3fold_page_unlock(zhdr);
+ return false;
+ }
+ z3fold_page_unlock(zhdr);
+ return false;
+ }
+
+
+ z3fold_inc_isolated(pool);
spin_unlock(&pool->lock);
z3fold_page_unlock(zhdr);
return true;
@@ -1391,6 +1483,10 @@ static int z3fold_page_migrate(struct address_space *mapping, struct page *newpa
queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
+ spin_lock(&pool->lock);
+ z3fold_dec_isolated(pool);
+ spin_unlock(&pool->lock);
+
page_mapcount_reset(page);
put_page(page);
return 0;
@@ -1410,10 +1506,14 @@ static void z3fold_page_putback(struct page *page)
INIT_LIST_HEAD(&page->lru);
if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
atomic64_dec(&pool->pages_nr);
+ spin_lock(&pool->lock);
+ z3fold_dec_isolated(pool);
+ spin_unlock(&pool->lock);
return;
}
spin_lock(&pool->lock);
list_add(&page->lru, &pool->lru);
+ z3fold_dec_isolated(pool);
spin_unlock(&pool->lock);
z3fold_page_unlock(zhdr);
}
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 57fbb7ced69f..e98bb6ab4f7e 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -54,6 +54,7 @@
#include <linux/mount.h>
#include <linux/pseudo_fs.h>
#include <linux/migrate.h>
+#include <linux/wait.h>
#include <linux/pagemap.h>
#include <linux/fs.h>
@@ -268,6 +269,10 @@ struct zs_pool {
#ifdef CONFIG_COMPACTION
struct inode *inode;
struct work_struct free_work;
+ /* A wait queue for when migration races with async_free_zspage() */
+ struct wait_queue_head migration_wait;
+ atomic_long_t isolated_pages;
+ bool destroying;
#endif
};
@@ -1862,6 +1867,31 @@ static void dec_zspage_isolation(struct zspage *zspage)
zspage->isolated--;
}
+static void putback_zspage_deferred(struct zs_pool *pool,
+ struct size_class *class,
+ struct zspage *zspage)
+{
+ enum fullness_group fg;
+
+ fg = putback_zspage(class, zspage);
+ if (fg == ZS_EMPTY)
+ schedule_work(&pool->free_work);
+
+}
+
+static inline void zs_pool_dec_isolated(struct zs_pool *pool)
+{
+ VM_BUG_ON(atomic_long_read(&pool->isolated_pages) <= 0);
+ atomic_long_dec(&pool->isolated_pages);
+ /*
+ * There's no possibility of racing, since wait_for_isolated_drain()
+ * checks the isolated count under &class->lock after enqueuing
+ * on migration_wait.
+ */
+ if (atomic_long_read(&pool->isolated_pages) == 0 && pool->destroying)
+ wake_up_all(&pool->migration_wait);
+}
+
static void replace_sub_page(struct size_class *class, struct zspage *zspage,
struct page *newpage, struct page *oldpage)
{
@@ -1931,6 +1961,7 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
*/
if (!list_empty(&zspage->list) && !is_zspage_isolated(zspage)) {
get_zspage_mapping(zspage, &class_idx, &fullness);
+ atomic_long_inc(&pool->isolated_pages);
remove_zspage(class, zspage, fullness);
}
@@ -2030,8 +2061,16 @@ static int zs_page_migrate(struct address_space *mapping, struct page *newpage,
* Page migration is done so let's putback isolated zspage to
* the list if @page is final isolated subpage in the zspage.
*/
- if (!is_zspage_isolated(zspage))
- putback_zspage(class, zspage);
+ if (!is_zspage_isolated(zspage)) {
+ /*
+ * We cannot race with zs_destroy_pool() here because we wait
+ * for isolation to hit zero before we start destroying.
+ * Also, we ensure that everyone can see pool->destroying before
+ * we start waiting.
+ */
+ putback_zspage_deferred(pool, class, zspage);
+ zs_pool_dec_isolated(pool);
+ }
reset_page(page);
put_page(page);
@@ -2077,13 +2116,12 @@ static void zs_page_putback(struct page *page)
spin_lock(&class->lock);
dec_zspage_isolation(zspage);
if (!is_zspage_isolated(zspage)) {
- fg = putback_zspage(class, zspage);
/*
* Due to page_lock, we cannot free zspage immediately
* so let's defer.
*/
- if (fg == ZS_EMPTY)
- schedule_work(&pool->free_work);
+ putback_zspage_deferred(pool, class, zspage);
+ zs_pool_dec_isolated(pool);
}
spin_unlock(&class->lock);
}
@@ -2107,8 +2145,36 @@ static int zs_register_migration(struct zs_pool *pool)
return 0;
}
+static bool pool_isolated_are_drained(struct zs_pool *pool)
+{
+ return atomic_long_read(&pool->isolated_pages) == 0;
+}
+
+/* Function for resolving migration */
+static void wait_for_isolated_drain(struct zs_pool *pool)
+{
+
+ /*
+ * We're in the process of destroying the pool, so there are no
+ * active allocations. zs_page_isolate() fails for completely free
+ * zspages, so we need only wait for the zs_pool's isolated
+ * count to hit zero.
+ */
+ wait_event(pool->migration_wait,
+ pool_isolated_are_drained(pool));
+}
+
static void zs_unregister_migration(struct zs_pool *pool)
{
+ pool->destroying = true;
+ /*
+ * We need a memory barrier here to ensure global visibility of
+ * pool->destroying. Thus pool->isolated pages will either be 0 in which
+ * case we don't care, or it will be > 0 and pool->destroying will
+ * ensure that we wake up once isolation hits 0.
+ */
+ smp_mb();
+ wait_for_isolated_drain(pool); /* This can block */
flush_work(&pool->free_work);
iput(pool->inode);
}
@@ -2346,6 +2412,10 @@ struct zs_pool *zs_create_pool(const char *name)
if (!pool->name)
goto err;
+#ifdef CONFIG_COMPACTION
+ init_waitqueue_head(&pool->migration_wait);
+#endif
+
if (create_cache(pool))
goto err;
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 240ed70912d6..d78938e3e008 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -277,17 +277,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
* batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
* @buff_pos: current position in the skb
* @packet_len: total length of the skb
- * @tvlv_len: tvlv length of the previously considered OGM
+ * @ogm_packet: potential OGM in buffer
*
* Return: true if there is enough space for another OGM, false otherwise.
*/
-static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
- __be16 tvlv_len)
+static bool
+batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
+ const struct batadv_ogm_packet *ogm_packet)
{
int next_buff_pos = 0;
- next_buff_pos += buff_pos + BATADV_OGM_HLEN;
- next_buff_pos += ntohs(tvlv_len);
+ /* check if there is enough space for the header */
+ next_buff_pos += buff_pos + sizeof(*ogm_packet);
+ if (next_buff_pos > packet_len)
+ return false;
+
+ /* check if there is enough space for the optional TVLV */
+ next_buff_pos += ntohs(ogm_packet->tvlv_len);
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
/* adjust all flags and log packets */
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
- batadv_ogm_packet->tvlv_len)) {
+ batadv_ogm_packet)) {
/* we might have aggregated direct link packets with an
* ordinary base packet
*/
@@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
/* unpack the aggregated packets and process them one by one */
while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
- ogm_packet->tvlv_len)) {
+ ogm_packet)) {
batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
ogm_offset += BATADV_OGM_HLEN;
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index fad95ef64e01..bc06e3cdfa84 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -631,17 +631,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
* batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
* @buff_pos: current position in the skb
* @packet_len: total length of the skb
- * @tvlv_len: tvlv length of the previously considered OGM
+ * @ogm2_packet: potential OGM2 in buffer
*
* Return: true if there is enough space for another OGM, false otherwise.
*/
-static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
- __be16 tvlv_len)
+static bool
+batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
+ const struct batadv_ogm2_packet *ogm2_packet)
{
int next_buff_pos = 0;
- next_buff_pos += buff_pos + BATADV_OGM2_HLEN;
- next_buff_pos += ntohs(tvlv_len);
+ /* check if there is enough space for the header */
+ next_buff_pos += buff_pos + sizeof(*ogm2_packet);
+ if (next_buff_pos > packet_len)
+ return false;
+
+ /* check if there is enough space for the optional TVLV */
+ next_buff_pos += ntohs(ogm2_packet->tvlv_len);
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -818,7 +824,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
- ogm_packet->tvlv_len)) {
+ ogm_packet)) {
batadv_v_ogm_process(skb, ogm_offset, if_incoming);
ogm_offset += BATADV_OGM2_HLEN;
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 67d7f83009ae..1d5bdf3a4b65 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -2303,7 +2303,7 @@ __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
while (bucket_tmp < hash->size) {
if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
- *bucket, &idx_tmp))
+ bucket_tmp, &idx_tmp))
break;
bucket_tmp++;
@@ -2420,8 +2420,10 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
- batadv_mcast_want_rtr4_update(bat_priv, orig, BATADV_NO_FLAGS);
- batadv_mcast_want_rtr6_update(bat_priv, orig, BATADV_NO_FLAGS);
+ batadv_mcast_want_rtr4_update(bat_priv, orig,
+ BATADV_MCAST_WANT_NO_RTR4);
+ batadv_mcast_want_rtr6_update(bat_priv, orig,
+ BATADV_MCAST_WANT_NO_RTR6);
spin_unlock_bh(&orig->mcast_handler_lock);
}
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 6f08fd122a8d..7e052d6f759b 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -164,7 +164,7 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
{
struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
- return attr ? nla_get_u32(attr) : 0;
+ return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0;
}
/**
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b9585e7d9d2e..04bc79359a17 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3202,6 +3202,7 @@ struct hci_dev *hci_alloc_dev(void)
hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
+ hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
mutex_init(&hdev->lock);
mutex_init(&hdev->req_lock);
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
index bb67f4a5479a..402e2cc54044 100644
--- a/net/bluetooth/hci_debugfs.c
+++ b/net/bluetooth/hci_debugfs.c
@@ -433,6 +433,35 @@ static int auto_accept_delay_set(void *data, u64 val)
return 0;
}
+static int min_encrypt_key_size_set(void *data, u64 val)
+{
+ struct hci_dev *hdev = data;
+
+ if (val < 1 || val > 16)
+ return -EINVAL;
+
+ hci_dev_lock(hdev);
+ hdev->min_enc_key_size = val;
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
+static int min_encrypt_key_size_get(void *data, u64 *val)
+{
+ struct hci_dev *hdev = data;
+
+ hci_dev_lock(hdev);
+ *val = hdev->min_enc_key_size;
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
+ min_encrypt_key_size_get,
+ min_encrypt_key_size_set, "%llu\n");
+
static int auto_accept_delay_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
@@ -545,6 +574,8 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
if (lmp_ssp_capable(hdev)) {
debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
hdev, &ssp_debug_mode_fops);
+ debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
+ hdev, &min_encrypt_key_size_fops);
debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
hdev, &auto_accept_delay_fops);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cdb00c2ef242..c1d3a303d97f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5660,11 +5660,6 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_UNKNOWN_CONN_ID);
- if (min < hcon->le_conn_min_interval ||
- max > hcon->le_conn_max_interval)
- return send_conn_param_neg_reply(hdev, handle,
- HCI_ERROR_INVALID_LL_PARAMS);
-
if (hci_check_conn_params(min, max, latency, timeout))
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 5abd423b55fa..8d889969ae7e 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -101,6 +101,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
{
struct sk_buff *skb;
struct sock *sk = sock->sk;
+ int ret;
BT_DBG("session %p data %p size %d", session, data, size);
@@ -114,13 +115,17 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
}
skb_put_u8(skb, hdr);
- if (data && size > 0)
+ if (data && size > 0) {
skb_put_data(skb, data, size);
+ ret = size;
+ } else {
+ ret = 0;
+ }
skb_queue_tail(transmit, skb);
wake_up_interruptible(sk_sleep(sk));
- return 0;
+ return ret;
}
static int hidp_send_ctrl_message(struct hidp_session *session,
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index cc506fe99b4d..da7fdbdf9c41 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1361,7 +1361,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
* actually encrypted before enforcing a key size.
*/
return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
- hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE);
+ hcon->enc_key_size >= hcon->hdev->min_enc_key_size);
}
static void l2cap_do_start(struct l2cap_chan *chan)
@@ -5305,14 +5305,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
memset(&rsp, 0, sizeof(rsp));
- if (min < hcon->le_conn_min_interval ||
- max > hcon->le_conn_max_interval) {
- BT_DBG("requested connection interval exceeds current bounds.");
- err = -EINVAL;
- } else {
- err = hci_check_conn_params(min, max, latency, to_multiplier);
- }
-
+ err = hci_check_conn_params(min, max, latency, to_multiplier);
if (err)
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
else
diff --git a/net/bridge/br.c b/net/bridge/br.c
index d164f63a4345..8a8f9e5f264f 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
int err;
if (dev->priv_flags & IFF_EBRIDGE) {
+ err = br_vlan_bridge_event(dev, event, ptr);
+ if (err)
+ return notifier_from_errno(err);
+
if (event == NETDEV_REGISTER) {
/* register of bridge completed, add sysfs entries */
br_sysfs_addbr(dev);
return NOTIFY_DONE;
}
- br_vlan_bridge_event(dev, event, ptr);
}
/* not a port of a bridge */
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index bf6acd34234d..63f9c08625f0 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -437,7 +437,7 @@ static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
struct nlmsghdr *nlh;
struct nlattr *nest;
- nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
if (!nlh)
return -EMSGSIZE;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 3d8deac2353d..f8cac3702712 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1388,6 +1388,9 @@ br_multicast_leave_group(struct net_bridge *br,
if (!br_port_group_equal(p, port, src))
continue;
+ if (p->flags & MDB_PG_FLAGS_PERMANENT)
+ break;
+
rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist);
del_timer(&p->timer);
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index d3f9592f4ff8..af7800103e51 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -496,6 +496,10 @@ static unsigned int br_nf_pre_routing(void *priv,
if (!brnet->call_ip6tables &&
!br_opt_get(br, BROPT_NF_CALL_IP6TABLES))
return NF_ACCEPT;
+ if (!ipv6_mod_enabled()) {
+ pr_warn_once("Module ipv6 is disabled, so call_ip6tables is not supported.");
+ return NF_DROP;
+ }
nf_bridge_pull_encap_header_rcsum(skb);
return br_nf_pre_routing_ipv6(priv, skb, state);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e8cf03b43b7d..646504db0220 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -894,8 +894,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
void br_vlan_get_stats(const struct net_bridge_vlan *v,
struct br_vlan_stats *stats);
void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
- void *ptr);
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+ void *ptr);
static inline struct net_bridge_vlan_group *br_vlan_group(
const struct net_bridge *br)
@@ -1085,9 +1085,10 @@ static inline void br_vlan_port_event(struct net_bridge_port *p,
{
}
-static inline void br_vlan_bridge_event(struct net_device *dev,
- unsigned long event, void *ptr)
+static inline int br_vlan_bridge_event(struct net_device *dev,
+ unsigned long event, void *ptr)
{
+ return 0;
}
#endif
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 021cc9f66804..f5b2aeebbfe9 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1053,7 +1053,6 @@ int br_vlan_init(struct net_bridge *br)
{
struct net_bridge_vlan_group *vg;
int ret = -ENOMEM;
- bool changed;
vg = kzalloc(sizeof(*vg), GFP_KERNEL);
if (!vg)
@@ -1068,17 +1067,10 @@ int br_vlan_init(struct net_bridge *br)
br->vlan_proto = htons(ETH_P_8021Q);
br->default_pvid = 1;
rcu_assign_pointer(br->vlgrp, vg);
- ret = br_vlan_add(br, 1,
- BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED |
- BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
- if (ret)
- goto err_vlan_add;
out:
return ret;
-err_vlan_add:
- vlan_tunnel_deinit(vg);
err_tunnel_init:
rhashtable_destroy(&vg->vlan_hash);
err_rhtbl:
@@ -1464,13 +1456,23 @@ static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid)
}
/* Must be protected by RTNL. */
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
- void *ptr)
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr)
{
struct netdev_notifier_changeupper_info *info;
- struct net_bridge *br;
+ struct net_bridge *br = netdev_priv(dev);
+ bool changed;
+ int ret = 0;
switch (event) {
+ case NETDEV_REGISTER:
+ ret = br_vlan_add(br, br->default_pvid,
+ BRIDGE_VLAN_INFO_PVID |
+ BRIDGE_VLAN_INFO_UNTAGGED |
+ BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
+ break;
+ case NETDEV_UNREGISTER:
+ br_vlan_delete(br, br->default_pvid);
+ break;
case NETDEV_CHANGEUPPER:
info = ptr;
br_vlan_upper_change(dev, info->upper_dev, info->linking);
@@ -1478,12 +1480,13 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
case NETDEV_CHANGE:
case NETDEV_UP:
- br = netdev_priv(dev);
if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
- return;
+ break;
br_vlan_link_state_change(dev, br);
break;
}
+
+ return ret;
}
/* Must be protected by RTNL. */
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 963dfdc14827..4096d8a74a2b 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -221,7 +221,7 @@ unsigned int ebt_do_table(struct sk_buff *skb,
return NF_DROP;
}
- ADD_COUNTER(*(counter_base + i), 1, skb->len);
+ ADD_COUNTER(*(counter_base + i), skb->len, 1);
/* these should only watch: not modify, nor tell us
* what to do with the packet
@@ -959,8 +959,8 @@ static void get_counters(const struct ebt_counter *oldcounters,
continue;
counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
for (i = 0; i < nentries; i++)
- ADD_COUNTER(counters[i], counter_base[i].pcnt,
- counter_base[i].bcnt);
+ ADD_COUNTER(counters[i], counter_base[i].bcnt,
+ counter_base[i].pcnt);
}
}
@@ -1280,7 +1280,7 @@ static int do_update_counters(struct net *net, const char *name,
/* we add to the counters of the first cpu */
for (i = 0; i < num_counters; i++)
- ADD_COUNTER(t->private->counters[i], tmp[i].pcnt, tmp[i].bcnt);
+ ADD_COUNTER(t->private->counters[i], tmp[i].bcnt, tmp[i].pcnt);
write_unlock_bh(&t->lock);
ret = 0;
@@ -1770,20 +1770,28 @@ static int compat_calc_entry(const struct ebt_entry *e,
return 0;
}
+static int ebt_compat_init_offsets(unsigned int number)
+{
+ if (number > INT_MAX)
+ return -EINVAL;
+
+ /* also count the base chain policies */
+ number += NF_BR_NUMHOOKS;
+
+ return xt_compat_init_offsets(NFPROTO_BRIDGE, number);
+}
static int compat_table_info(const struct ebt_table_info *info,
struct compat_ebt_replace *newinfo)
{
unsigned int size = info->entries_size;
const void *entries = info->entries;
+ int ret;
newinfo->entries_size = size;
- if (info->nentries) {
- int ret = xt_compat_init_offsets(NFPROTO_BRIDGE,
- info->nentries);
- if (ret)
- return ret;
- }
+ ret = ebt_compat_init_offsets(info->nentries);
+ if (ret)
+ return ret;
return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
entries, newinfo);
@@ -2234,11 +2242,9 @@ static int compat_do_replace(struct net *net, void __user *user,
xt_compat_lock(NFPROTO_BRIDGE);
- if (tmp.nentries) {
- ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
- if (ret < 0)
- goto out_unlock;
- }
+ ret = ebt_compat_init_offsets(tmp.nentries);
+ if (ret < 0)
+ goto out_unlock;
ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
if (ret < 0)
@@ -2261,8 +2267,10 @@ static int compat_do_replace(struct net *net, void __user *user,
state.buf_kern_len = size64;
ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
- if (WARN_ON(ret < 0))
+ if (WARN_ON(ret < 0)) {
+ vfree(entries_tmp);
goto out_unlock;
+ }
vfree(entries_tmp);
tmp.entries_size = size64;
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c
index bed66f536b34..7c9e92b2f806 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
switch (priv->key) {
case NFT_META_BRI_IIFNAME:
br_dev = nft_meta_get_bridge(in);
- if (!br_dev)
- goto err;
break;
case NFT_META_BRI_OIFNAME:
br_dev = nft_meta_get_bridge(out);
- if (!br_dev)
- goto err;
break;
case NFT_META_BRI_IIFPVID: {
u16 p_pvid;
@@ -57,17 +53,15 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
goto err;
br_vlan_get_proto(br_dev, &p_proto);
- nft_reg_store16(dest, p_proto);
+ nft_reg_store16(dest, htons(p_proto));
return;
}
default:
- goto out;
+ return nft_meta_get_eval(expr, regs, pkt);
}
- strncpy((char *)dest, br_dev->name, IFNAMSIZ);
+ strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
return;
-out:
- return nft_meta_get_eval(expr, regs, pkt);
err:
regs->verdict.code = NFT_BREAK;
}
diff --git a/net/can/gw.c b/net/can/gw.c
index 5275ddf580bc..72711053ebe6 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -1046,32 +1046,50 @@ static __init int cgw_module_init(void)
pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
max_hops);
- register_pernet_subsys(&cangw_pernet_ops);
+ ret = register_pernet_subsys(&cangw_pernet_ops);
+ if (ret)
+ return ret;
+
+ ret = -ENOMEM;
cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
0, 0, NULL);
-
if (!cgw_cache)
- return -ENOMEM;
+ goto out_cache_create;
/* set notifier */
notifier.notifier_call = cgw_notifier;
- register_netdevice_notifier(&notifier);
+ ret = register_netdevice_notifier(&notifier);
+ if (ret)
+ goto out_register_notifier;
ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_GETROUTE,
NULL, cgw_dump_jobs, 0);
- if (ret) {
- unregister_netdevice_notifier(&notifier);
- kmem_cache_destroy(cgw_cache);
- return -ENOBUFS;
- }
-
- /* Only the first call to rtnl_register_module can fail */
- rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
- cgw_create_job, NULL, 0);
- rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
- cgw_remove_job, NULL, 0);
+ if (ret)
+ goto out_rtnl_register1;
+
+ ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
+ cgw_create_job, NULL, 0);
+ if (ret)
+ goto out_rtnl_register2;
+ ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
+ cgw_remove_job, NULL, 0);
+ if (ret)
+ goto out_rtnl_register3;
return 0;
+
+out_rtnl_register3:
+ rtnl_unregister(PF_CAN, RTM_NEWROUTE);
+out_rtnl_register2:
+ rtnl_unregister(PF_CAN, RTM_GETROUTE);
+out_rtnl_register1:
+ unregister_netdevice_notifier(&notifier);
+out_register_notifier:
+ kmem_cache_destroy(cgw_cache);
+out_cache_create:
+ unregister_pernet_subsys(&cangw_pernet_ops);
+
+ return ret;
}
static __exit void cgw_module_exit(void)
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 5d6724cee38f..4f75df40fb12 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -136,8 +136,10 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
if (key) {
kfree(key->key);
key->key = NULL;
- crypto_free_sync_skcipher(key->tfm);
- key->tfm = NULL;
+ if (key->tfm) {
+ crypto_free_sync_skcipher(key->tfm);
+ key->tfm = NULL;
+ }
}
}
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 0b2df09b2554..78ae6e8c953d 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1496,7 +1496,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
struct ceph_osds up, acting;
bool force_resend = false;
bool unpaused = false;
- bool legacy_change;
+ bool legacy_change = false;
bool split = false;
bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE);
bool recovery_deletes = ceph_osdmap_flag(osdc,
@@ -1584,15 +1584,14 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
t->osd = acting.primary;
}
- if (unpaused || legacy_change || force_resend ||
- (split && con && CEPH_HAVE_FEATURE(con->peer_features,
- RESEND_ON_SPLIT)))
+ if (unpaused || legacy_change || force_resend || split)
ct_res = CALC_TARGET_NEED_RESEND;
else
ct_res = CALC_TARGET_NO_ACTION;
out:
- dout("%s t %p -> ct_res %d osd %d\n", __func__, t, ct_res, t->osd);
+ dout("%s t %p -> %d%d%d%d ct_res %d osd%d\n", __func__, t, unpaused,
+ legacy_change, force_resend, split, ct_res, t->osd);
return ct_res;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index fc676b2610e3..5156c0edebe8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4374,12 +4374,17 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
act = bpf_prog_run_xdp(xdp_prog, xdp);
+ /* check if bpf_xdp_adjust_head was used */
off = xdp->data - orig_data;
- if (off > 0)
- __skb_pull(skb, off);
- else if (off < 0)
- __skb_push(skb, -off);
- skb->mac_header += off;
+ if (off) {
+ if (off > 0)
+ __skb_pull(skb, off);
+ else if (off < 0)
+ __skb_push(skb, -off);
+
+ skb->mac_header += off;
+ skb_reset_network_header(skb);
+ }
/* check if bpf_xdp_adjust_tail was used. it can only "shrink"
* pckt.
@@ -8753,6 +8758,8 @@ int register_netdevice(struct net_device *dev)
ret = notifier_to_errno(ret);
if (ret) {
rollback_registered(dev);
+ rcu_barrier();
+
dev->reg_state = NETREG_UNREGISTERED;
}
/*
@@ -9701,6 +9708,8 @@ static void __net_exit default_device_exit(struct net *net)
/* Push remaining network devices to init_net */
snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
+ if (__dev_get_by_name(&init_net, fb_name))
+ snprintf(fb_name, IFNAMSIZ, "dev%%d");
err = dev_change_net_namespace(dev, &init_net, fb_name);
if (err) {
pr_emerg("%s: failed to move %s to init_net: %d\n",
diff --git a/net/core/filter.c b/net/core/filter.c
index 4e2a79b2fd77..4c6a252d4212 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -7455,12 +7455,12 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
case offsetof(struct __sk_buff, gso_segs):
/* si->dst_reg = skb_shinfo(SKB); */
#ifdef NET_SKBUFF_DATA_USES_OFFSET
- *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
- si->dst_reg, si->src_reg,
- offsetof(struct sk_buff, head));
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
BPF_REG_AX, si->src_reg,
offsetof(struct sk_buff, end));
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_buff, head));
*insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
#else
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
@@ -8757,13 +8757,13 @@ sk_reuseport_is_valid_access(int off, int size,
return size == size_default;
/* Fields that allow narrowing */
- case offsetof(struct sk_reuseport_md, eth_protocol):
+ case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
if (size < FIELD_SIZEOF(struct sk_buff, protocol))
return false;
/* fall through */
- case offsetof(struct sk_reuseport_md, ip_protocol):
- case offsetof(struct sk_reuseport_md, bind_inany):
- case offsetof(struct sk_reuseport_md, len):
+ case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
+ case bpf_ctx_range(struct sk_reuseport_md, bind_inany):
+ case bpf_ctx_range(struct sk_reuseport_md, len):
bpf_ctx_record_field_size(info, size_default);
return bpf_ctx_narrow_access_ok(off, size, size_default);
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 3e6fedb57bc1..2470b4b404e6 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -142,8 +142,8 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
mutex_unlock(&flow_dissector_mutex);
return -ENOENT;
}
- bpf_prog_put(attached);
RCU_INIT_POINTER(net->flow_dissector_prog, NULL);
+ bpf_prog_put(attached);
mutex_unlock(&flow_dissector_mutex);
return 0;
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 2cf27da1baeb..849380a622ef 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -122,7 +122,7 @@ static void queue_process(struct work_struct *work)
txq = netdev_get_tx_queue(dev, q_index);
HARD_TX_LOCK(dev, txq, smp_processor_id());
if (netif_xmit_frozen_or_stopped(txq) ||
- netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
+ !dev_xmit_complete(netpoll_start_xmit(skb, dev, txq))) {
skb_queue_head(&npinfo->txq, skb);
HARD_TX_UNLOCK(dev, txq);
local_irq_restore(flags);
@@ -335,7 +335,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
HARD_TX_UNLOCK(dev, txq);
- if (status == NETDEV_TX_OK)
+ if (dev_xmit_complete(status))
break;
}
@@ -352,7 +352,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
}
- if (status != NETDEV_TX_OK) {
+ if (!dev_xmit_complete(status)) {
skb_queue_tail(&npinfo->txq, skb);
schedule_delayed_work(&npinfo->tx_work,0);
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 0338820ee0ec..982d8d12830e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3664,6 +3664,25 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
int pos;
int dummy;
+ if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) &&
+ (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) {
+ /* gso_size is untrusted, and we have a frag_list with a linear
+ * non head_frag head.
+ *
+ * (we assume checking the first list_skb member suffices;
+ * i.e if either of the list_skb members have non head_frag
+ * head, then the first one has too).
+ *
+ * If head_skb's headlen does not fit requested gso_size, it
+ * means that the frag_list members do NOT terminate on exact
+ * gso_size boundaries. Hence we cannot perform skb_frag_t page
+ * sharing. Therefore we must fallback to copying the frag_list
+ * skbs; we do so by disabling SG.
+ */
+ if (mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb))
+ features &= ~NETIF_F_SG;
+ }
+
__skb_push(head_skb, doffset);
proto = skb_network_protocol(head_skb, &dummy);
if (unlikely(!proto))
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index 93bffaad2135..6832eeb4b785 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -585,12 +585,12 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);
void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
{
- rcu_assign_sk_user_data(sk, NULL);
sk_psock_cork_free(psock);
sk_psock_zap_ingress(psock);
- sk_psock_restore_proto(sk, psock);
write_lock_bh(&sk->sk_callback_lock);
+ sk_psock_restore_proto(sk, psock);
+ rcu_assign_sk_user_data(sk, NULL);
if (psock->progs.skb_parser)
sk_psock_stop_strp(sk, psock);
write_unlock_bh(&sk->sk_callback_lock);
diff --git a/net/core/sock.c b/net/core/sock.c
index d57b0cc995a0..545fac19a711 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
}
EXPORT_SYMBOL(skb_set_owner_w);
+static bool can_skb_orphan_partial(const struct sk_buff *skb)
+{
+#ifdef CONFIG_TLS_DEVICE
+ /* Drivers depend on in-order delivery for crypto offload,
+ * partial orphan breaks out-of-order-OK logic.
+ */
+ if (skb->decrypted)
+ return false;
+#endif
+ return (skb->destructor == sock_wfree ||
+ (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
+}
+
/* This helper is used by netem, as it can hold packets in its
* delay queue. We want to allow the owner socket to send more
* packets, as if they were already TX completed by a typical driver.
@@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb)
if (skb_is_tcp_pure_ack(skb))
return;
- if (skb->destructor == sock_wfree
-#ifdef CONFIG_INET
- || skb->destructor == tcp_wfree
-#endif
- ) {
+ if (can_skb_orphan_partial(skb)) {
struct sock *sk = skb->sk;
if (refcount_inc_not_zero(&sk->sk_refcnt)) {
@@ -3278,16 +3287,17 @@ static __init int net_inuse_init(void)
core_initcall(net_inuse_init);
-static void assign_proto_idx(struct proto *prot)
+static int assign_proto_idx(struct proto *prot)
{
prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
pr_err("PROTO_INUSE_NR exhausted\n");
- return;
+ return -ENOSPC;
}
set_bit(prot->inuse_idx, proto_inuse_idx);
+ return 0;
}
static void release_proto_idx(struct proto *prot)
@@ -3296,8 +3306,9 @@ static void release_proto_idx(struct proto *prot)
clear_bit(prot->inuse_idx, proto_inuse_idx);
}
#else
-static inline void assign_proto_idx(struct proto *prot)
+static inline int assign_proto_idx(struct proto *prot)
{
+ return 0;
}
static inline void release_proto_idx(struct proto *prot)
@@ -3346,6 +3357,8 @@ static int req_prot_init(const struct proto *prot)
int proto_register(struct proto *prot, int alloc_slab)
{
+ int ret = -ENOBUFS;
+
if (alloc_slab) {
prot->slab = kmem_cache_create_usercopy(prot->name,
prot->obj_size, 0,
@@ -3382,20 +3395,27 @@ int proto_register(struct proto *prot, int alloc_slab)
}
mutex_lock(&proto_list_mutex);
+ ret = assign_proto_idx(prot);
+ if (ret) {
+ mutex_unlock(&proto_list_mutex);
+ goto out_free_timewait_sock_slab_name;
+ }
list_add(&prot->node, &proto_list);
- assign_proto_idx(prot);
mutex_unlock(&proto_list_mutex);
- return 0;
+ return ret;
out_free_timewait_sock_slab_name:
- kfree(prot->twsk_prot->twsk_slab_name);
+ if (alloc_slab && prot->twsk_prot)
+ kfree(prot->twsk_prot->twsk_slab_name);
out_free_request_sock_slab:
- req_prot_cleanup(prot->rsk_prot);
+ if (alloc_slab) {
+ req_prot_cleanup(prot->rsk_prot);
- kmem_cache_destroy(prot->slab);
- prot->slab = NULL;
+ kmem_cache_destroy(prot->slab);
+ prot->slab = NULL;
+ }
out:
- return -ENOBUFS;
+ return ret;
}
EXPORT_SYMBOL(proto_register);
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 3312a5849a97..c13ffbd33d8d 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -19,6 +19,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
static DEFINE_MUTEX(sock_diag_table_mutex);
static struct workqueue_struct *broadcast_wq;
+static atomic64_t cookie_gen;
u64 sock_gen_cookie(struct sock *sk)
{
@@ -27,7 +28,7 @@ u64 sock_gen_cookie(struct sock *sk)
if (res)
return res;
- res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
+ res = atomic64_inc_return(&cookie_gen);
atomic64_cmpxchg(&sk->sk_cookie, 0, res);
}
}
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 52d4faeee18b..50916f9bc4f2 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -247,6 +247,8 @@ static void sock_map_free(struct bpf_map *map)
raw_spin_unlock_bh(&stab->lock);
rcu_read_unlock();
+ synchronize_rcu();
+
bpf_map_area_free(stab->sks);
kfree(stab);
}
@@ -276,16 +278,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
struct sock **psk)
{
struct sock *sk;
+ int err = 0;
raw_spin_lock_bh(&stab->lock);
sk = *psk;
if (!sk_test || sk_test == sk)
- *psk = NULL;
+ sk = xchg(psk, NULL);
+
+ if (likely(sk))
+ sock_map_unref(sk, psk);
+ else
+ err = -EINVAL;
+
raw_spin_unlock_bh(&stab->lock);
- if (unlikely(!sk))
- return -EINVAL;
- sock_map_unref(sk, psk);
- return 0;
+ return err;
}
static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk,
@@ -328,6 +334,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
struct sock *sk, u64 flags)
{
struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct sk_psock_link *link;
struct sk_psock *psock;
struct sock *osk;
@@ -338,6 +345,8 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
return -EINVAL;
if (unlikely(idx >= map->max_entries))
return -E2BIG;
+ if (unlikely(icsk->icsk_ulp_data))
+ return -EINVAL;
link = sk_psock_init_link();
if (!link)
@@ -647,6 +656,7 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
struct sock *sk, u64 flags)
{
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ struct inet_connection_sock *icsk = inet_csk(sk);
u32 key_size = map->key_size, hash;
struct bpf_htab_elem *elem, *elem_new;
struct bpf_htab_bucket *bucket;
@@ -657,6 +667,8 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
WARN_ON_ONCE(!rcu_read_lock_held());
if (unlikely(flags > BPF_EXIST))
return -EINVAL;
+ if (unlikely(icsk->icsk_ulp_data))
+ return -EINVAL;
link = sk_psock_init_link();
if (!link)
diff --git a/net/core/stream.c b/net/core/stream.c
index e94bb02a5629..4f1d4aa5fb38 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -120,7 +120,6 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
int err = 0;
long vm_wait = 0;
long current_timeo = *timeo_p;
- bool noblock = (*timeo_p ? false : true);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
if (sk_stream_memory_free(sk))
@@ -133,11 +132,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
goto do_error;
- if (!*timeo_p) {
- if (noblock)
- set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
- goto do_nonblock;
- }
+ if (!*timeo_p)
+ goto do_eagain;
if (signal_pending(current))
goto do_interrupted;
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
@@ -169,7 +165,13 @@ out:
do_error:
err = -EPIPE;
goto out;
-do_nonblock:
+do_eagain:
+ /* Make sure that whenever EAGAIN is returned, EPOLLOUT event can
+ * be generated later.
+ * When TCP receives ACK packets that make room, tcp_check_space()
+ * only calls tcp_new_space() if SOCK_NOSPACE is set.
+ */
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
err = -EAGAIN;
goto out;
do_interrupted:
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 4ec5b7f85d51..09d9286b27cc 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -153,6 +153,9 @@ static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
{
int port;
+ if (!ds->ops->port_mdb_add)
+ return;
+
for_each_set_bit(port, bitmap, ds->num_ports)
ds->ops->port_mdb_add(ds, port, mdb);
}
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 6ebbd799c4eb..67a1bc635a7b 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -28,6 +28,7 @@
*
* RSV - VID[9]:
* To be used for further expansion of SWITCH_ID or for other purposes.
+ * Must be transmitted as zero and ignored on receive.
*
* SWITCH_ID - VID[8:6]:
* Index of switch within DSA tree. Must be between 0 and
@@ -35,6 +36,7 @@
*
* RSV - VID[5:4]:
* To be used for further expansion of PORT or for other purposes.
+ * Must be transmitted as zero and ignored on receive.
*
* PORT - VID[3:0]:
* Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 26363d72d25b..47ee88163a9d 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -165,6 +165,7 @@ static struct sk_buff
"Expected meta frame, is %12llx "
"in the DSA master multicast filter?\n",
SJA1105_META_DMAC);
+ kfree_skb(sp->data->stampable_skb);
}
/* Hold a reference to avoid dsa_switch_rcv
@@ -211,17 +212,8 @@ static struct sk_buff
* for further processing up the network stack.
*/
kfree_skb(skb);
-
- skb = skb_copy(stampable_skb, GFP_ATOMIC);
- if (!skb) {
- dev_err_ratelimited(dp->ds->dev,
- "Failed to copy stampable skb\n");
- spin_unlock(&sp->data->meta_lock);
- return NULL;
- }
+ skb = stampable_skb;
sja1105_transfer_meta(skb, meta);
- /* The cached copy will be freed now */
- skb_unref(stampable_skb);
spin_unlock(&sp->data->meta_lock);
}
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index e4aba5d485be..bbe9b3b2d395 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -170,7 +170,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *skb,
reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail);
if (!reasm_data)
goto out_oom;
- inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+ inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
skb->dev = ldev;
skb->tstamp = fq->q.stamp;
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index dacbd58e1799..badc5cfe4dc6 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -1092,7 +1092,7 @@ static struct packet_type ieee802154_packet_type = {
static int __init af_ieee802154_init(void)
{
- int rc = -EINVAL;
+ int rc;
rc = proto_register(&ieee802154_raw_prot, 1);
if (rc)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e8bc939b56dd..dde77f72e03e 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -124,7 +124,8 @@ struct fib_table *fib_get_table(struct net *net, u32 id)
h = id & (FIB_TABLE_HASHSZ - 1);
head = &net->ipv4.fib_table_hash[h];
- hlist_for_each_entry_rcu(tb, head, tb_hlist) {
+ hlist_for_each_entry_rcu(tb, head, tb_hlist,
+ lockdep_rtnl_is_held()) {
if (tb->tb_id == id)
return tb;
}
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 2db089e10ba0..0913a090b2bf 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1582,7 +1582,7 @@ failure:
}
int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nhc,
- unsigned char *flags, bool skip_oif)
+ u8 rt_family, unsigned char *flags, bool skip_oif)
{
if (nhc->nhc_flags & RTNH_F_DEAD)
*flags |= RTNH_F_DEAD;
@@ -1613,7 +1613,7 @@ int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nhc,
/* if gateway family does not match nexthop family
* gateway is encoded as RTA_VIA
*/
- if (nhc->nhc_gw_family != nhc->nhc_family) {
+ if (rt_family != nhc->nhc_gw_family) {
int alen = sizeof(struct in6_addr);
struct nlattr *nla;
struct rtvia *via;
@@ -1654,7 +1654,7 @@ EXPORT_SYMBOL_GPL(fib_nexthop_info);
#if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6)
int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
- int nh_weight)
+ int nh_weight, u8 rt_family)
{
const struct net_device *dev = nhc->nhc_dev;
struct rtnexthop *rtnh;
@@ -1667,7 +1667,7 @@ int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
rtnh->rtnh_hops = nh_weight - 1;
rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
- if (fib_nexthop_info(skb, nhc, &flags, true) < 0)
+ if (fib_nexthop_info(skb, nhc, rt_family, &flags, true) < 0)
goto nla_put_failure;
rtnh->rtnh_flags = flags;
@@ -1693,13 +1693,14 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
goto nla_put_failure;
if (unlikely(fi->nh)) {
- if (nexthop_mpath_fill_node(skb, fi->nh) < 0)
+ if (nexthop_mpath_fill_node(skb, fi->nh, AF_INET) < 0)
goto nla_put_failure;
goto mp_end;
}
for_nexthops(fi) {
- if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight) < 0)
+ if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight,
+ AF_INET) < 0)
goto nla_put_failure;
#ifdef CONFIG_IP_ROUTE_CLASSID
if (nh->nh_tclassid &&
@@ -1775,7 +1776,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
unsigned char flags = 0;
- if (fib_nexthop_info(skb, nhc, &flags, false) < 0)
+ if (fib_nexthop_info(skb, nhc, AF_INET, &flags, false) < 0)
goto nla_put_failure;
rtm->rtm_flags = flags;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 2b2b3d291ab0..1ab2fb6bb37d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2145,7 +2145,7 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
if (filter->dump_exceptions) {
err = fib_dump_info_fnhe(skb, cb, tb->tb_id, fi,
- &i_fa, s_fa);
+ &i_fa, s_fa, flags);
if (err < 0)
goto stop;
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 1510e951f451..4298aae74e0e 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -582,7 +582,13 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
if (!rt)
goto out;
- net = dev_net(rt->dst.dev);
+
+ if (rt->dst.dev)
+ net = dev_net(rt->dst.dev);
+ else if (skb_in->dev)
+ net = dev_net(skb_in->dev);
+ else
+ goto out;
/*
* Find the original header. It is expected to be valid, of course.
@@ -902,7 +908,7 @@ static bool icmp_redirect(struct sk_buff *skb)
return false;
}
- icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);
+ icmp_socket_deliver(skb, ntohl(icmp_hdr(skb)->un.gateway));
return true;
}
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 180f6896b98b..480d0b22db1a 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1475,7 +1475,7 @@ EXPORT_SYMBOL(__ip_mc_inc_group);
void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
{
- __ip_mc_inc_group(in_dev, addr, MCAST_EXCLUDE);
+ __ip_mc_inc_group(in_dev, addr, GFP_KERNEL);
}
EXPORT_SYMBOL(ip_mc_inc_group);
@@ -2197,7 +2197,7 @@ static int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr,
iml->sflist = NULL;
iml->sfmode = mode;
rcu_assign_pointer(inet->mc_list, iml);
- __ip_mc_inc_group(in_dev, addr, mode);
+ ____ip_mc_inc_group(in_dev, addr, mode, GFP_KERNEL);
err = 0;
done:
return err;
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index d666756be5f1..10d31733297d 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -331,7 +331,7 @@ struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key)
prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params);
if (!prev)
fq = inet_frag_create(fqdir, key, &prev);
- if (prev && !IS_ERR(prev)) {
+ if (!IS_ERR_OR_NULL(prev)) {
fq = prev;
if (!refcount_inc_not_zero(&fq->refcnt))
fq = NULL;
@@ -475,11 +475,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
EXPORT_SYMBOL(inet_frag_reasm_prepare);
void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
- void *reasm_data)
+ void *reasm_data, bool try_coalesce)
{
struct sk_buff **nextp = (struct sk_buff **)reasm_data;
struct rb_node *rbn;
struct sk_buff *fp;
+ int sum_truesize;
skb_push(head, head->data - skb_network_header(head));
@@ -487,25 +488,41 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
fp = FRAG_CB(head)->next_frag;
rbn = rb_next(&head->rbnode);
rb_erase(&head->rbnode, &q->rb_fragments);
+
+ sum_truesize = head->truesize;
while (rbn || fp) {
/* fp points to the next sk_buff in the current run;
* rbn points to the next run.
*/
/* Go through the current run. */
while (fp) {
- *nextp = fp;
- nextp = &fp->next;
- fp->prev = NULL;
- memset(&fp->rbnode, 0, sizeof(fp->rbnode));
- fp->sk = NULL;
- head->data_len += fp->len;
- head->len += fp->len;
+ struct sk_buff *next_frag = FRAG_CB(fp)->next_frag;
+ bool stolen;
+ int delta;
+
+ sum_truesize += fp->truesize;
if (head->ip_summed != fp->ip_summed)
head->ip_summed = CHECKSUM_NONE;
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
- fp = FRAG_CB(fp)->next_frag;
+
+ if (try_coalesce && skb_try_coalesce(head, fp, &stolen,
+ &delta)) {
+ kfree_skb_partial(fp, stolen);
+ } else {
+ fp->prev = NULL;
+ memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+ fp->sk = NULL;
+
+ head->data_len += fp->len;
+ head->len += fp->len;
+ head->truesize += fp->truesize;
+
+ *nextp = fp;
+ nextp = &fp->next;
+ }
+
+ fp = next_frag;
}
/* Move to the next run. */
if (rbn) {
@@ -516,7 +533,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
rbn = rbnext;
}
}
- sub_frag_mem_limit(q->fqdir, head->truesize);
+ sub_frag_mem_limit(q->fqdir, sum_truesize);
*nextp = NULL;
skb_mark_not_on_list(head);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 4385eb9e781f..cfeb8890f94e 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -393,6 +393,11 @@ err:
return err;
}
+static bool ip_frag_coalesce_ok(const struct ipq *qp)
+{
+ return qp->q.key.v4.user == IP_DEFRAG_LOCAL_DELIVER;
+}
+
/* Build a new IP datagram from all its fragments. */
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
struct sk_buff *prev_tail, struct net_device *dev)
@@ -421,7 +426,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
if (len > 65535)
goto out_oversize;
- inet_frag_reasm_finish(&qp->q, skb, reasm_data);
+ inet_frag_reasm_finish(&qp->q, skb, reasm_data,
+ ip_frag_coalesce_ok(qp));
skb->dev = dev;
IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 43adfc1641ba..2f01cf6fa0de 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -275,6 +275,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
const struct iphdr *tiph = &tunnel->parms.iph;
u8 ipproto;
+ if (!pskb_inet_may_pull(skb))
+ goto tx_error;
+
switch (skb->protocol) {
case htons(ETH_P_IP):
ipproto = IPPROTO_IPIP;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 517300d587a7..b6a6f18c3dd1 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2728,7 +2728,8 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow);
/* called with rcu_read_lock held */
static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
struct rtable *rt, u32 table_id, struct flowi4 *fl4,
- struct sk_buff *skb, u32 portid, u32 seq)
+ struct sk_buff *skb, u32 portid, u32 seq,
+ unsigned int flags)
{
struct rtmsg *r;
struct nlmsghdr *nlh;
@@ -2736,7 +2737,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
u32 error;
u32 metrics[RTAX_MAX];
- nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), 0);
+ nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), flags);
if (!nlh)
return -EMSGSIZE;
@@ -2860,7 +2861,7 @@ nla_put_failure:
static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, u32 table_id,
struct fnhe_hash_bucket *bucket, int genid,
- int *fa_index, int fa_start)
+ int *fa_index, int fa_start, unsigned int flags)
{
int i;
@@ -2891,7 +2892,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb,
err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt,
table_id, NULL, skb,
NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq);
+ cb->nlh->nlmsg_seq, flags);
if (err)
return err;
next:
@@ -2904,7 +2905,7 @@ next:
int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
u32 table_id, struct fib_info *fi,
- int *fa_index, int fa_start)
+ int *fa_index, int fa_start, unsigned int flags)
{
struct net *net = sock_net(cb->skb->sk);
int nhsel, genid = fnhe_genid(net);
@@ -2922,7 +2923,8 @@ int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
err = 0;
if (bucket)
err = fnhe_dump_bucket(net, skb, cb, table_id, bucket,
- genid, fa_index, fa_start);
+ genid, fa_index, fa_start,
+ flags);
rcu_read_unlock();
if (err)
return err;
@@ -3183,7 +3185,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
fl4.flowi4_tos, res.fi, 0);
} else {
err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb,
- NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
+ NETLINK_CB(in_skb).portid,
+ nlh->nlmsg_seq, 0);
}
if (err < 0)
goto errout_rcu;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 776905899ac0..61082065b26a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -935,6 +935,22 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
return mss_now;
}
+/* In some cases, both sendpage() and sendmsg() could have added
+ * an skb to the write queue, but failed adding payload on it.
+ * We need to remove it to consume less memory, but more
+ * importantly be able to generate EPOLLOUT for Edge Trigger epoll()
+ * users.
+ */
+static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb)
+{
+ if (skb && !skb->len) {
+ tcp_unlink_write_queue(skb, sk);
+ if (tcp_write_queue_empty(sk))
+ tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
+ sk_wmem_free_skb(sk, skb);
+ }
+}
+
ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
size_t size, int flags)
{
@@ -984,6 +1000,9 @@ new_segment:
if (!skb)
goto wait_for_memory;
+#ifdef CONFIG_TLS_DEVICE
+ skb->decrypted = !!(flags & MSG_SENDPAGE_DECRYPTED);
+#endif
skb_entail(sk, skb);
copy = size_goal;
}
@@ -1061,6 +1080,7 @@ out:
return copied;
do_error:
+ tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk));
if (copied)
goto out;
out_err:
@@ -1385,18 +1405,11 @@ out_nopush:
sock_zerocopy_put(uarg);
return copied + copied_syn;
+do_error:
+ skb = tcp_write_queue_tail(sk);
do_fault:
- if (!skb->len) {
- tcp_unlink_write_queue(skb, sk);
- /* It is the one place in all of TCP, except connection
- * reset, where we can be unlinking the send_head.
- */
- if (tcp_write_queue_empty(sk))
- tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
- sk_wmem_free_skb(sk, skb);
- }
+ tcp_remove_empty_skb(sk, skb);
-do_error:
if (copied + copied_syn)
goto out;
out_err:
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 3d1e15401384..8a56e09cfb0e 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -398,10 +398,14 @@ more_data:
static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
{
struct sk_msg tmp, *msg_tx = NULL;
- int flags = msg->msg_flags | MSG_NO_SHARED_FRAGS;
int copied = 0, err = 0;
struct sk_psock *psock;
long timeo;
+ int flags;
+
+ /* Don't let internal do_tcp_sendpages() flags through */
+ flags = (msg->msg_flags & ~MSG_SENDPAGE_DECRYPTED);
+ flags |= MSG_NO_SHARED_FRAGS;
psock = sk_psock_get(sk);
if (unlikely(!psock))
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c21e8a22fb3b..8a1cd93dbb09 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -266,7 +266,7 @@ static void tcp_ecn_accept_cwr(struct sock *sk, const struct sk_buff *skb)
static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp)
{
- tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
+ tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
}
static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 6e4afc48d7bb..8a645f304e6c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1320,6 +1320,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
buff = sk_stream_alloc_skb(sk, nsize, gfp, true);
if (!buff)
return -ENOMEM; /* We'll just try again later. */
+ skb_copy_decrypted(buff, skb);
sk->sk_wmem_queued += buff->truesize;
sk_mem_charge(sk, buff->truesize);
@@ -1874,6 +1875,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
buff = sk_stream_alloc_skb(sk, 0, gfp, true);
if (unlikely(!buff))
return -ENOMEM;
+ skb_copy_decrypted(buff, skb);
sk->sk_wmem_queued += buff->truesize;
sk_mem_charge(sk, buff->truesize);
@@ -2051,7 +2053,7 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len)
if (len <= skb->len)
break;
- if (unlikely(TCP_SKB_CB(skb)->eor))
+ if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb))
return false;
len -= skb->len;
@@ -2143,6 +2145,7 @@ static int tcp_mtu_probe(struct sock *sk)
sk_mem_charge(sk, nskb->truesize);
skb = tcp_send_head(sk);
+ skb_copy_decrypted(nskb, skb);
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
@@ -2167,6 +2170,7 @@ static int tcp_mtu_probe(struct sock *sk)
* we need to propagate it to the new skb.
*/
TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor;
+ tcp_skb_collapse_tstamp(nskb, skb);
tcp_unlink_write_queue(skb, sk);
sk_wmem_free_skb(sk, skb);
} else {
diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c
index 3d8a1d835471..4849edb62d52 100644
--- a/net/ipv4/tcp_ulp.c
+++ b/net/ipv4/tcp_ulp.c
@@ -96,6 +96,19 @@ void tcp_get_available_ulp(char *buf, size_t maxlen)
rcu_read_unlock();
}
+void tcp_update_ulp(struct sock *sk, struct proto *proto)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (!icsk->icsk_ulp_ops) {
+ sk->sk_prot = proto;
+ return;
+ }
+
+ if (icsk->icsk_ulp_ops->update)
+ icsk->icsk_ulp_ops->update(sk, proto);
+}
+
void tcp_cleanup_ulp(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index dc73888c7859..6a576ff92c39 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -478,7 +478,7 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
if (!idev) {
idev = ipv6_add_dev(dev);
if (IS_ERR(idev))
- return NULL;
+ return idev;
}
if (dev->flags&IFF_UP)
@@ -1045,7 +1045,8 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
int err = 0;
if (addr_type == IPV6_ADDR_ANY ||
- addr_type & IPV6_ADDR_MULTICAST ||
+ (addr_type & IPV6_ADDR_MULTICAST &&
+ !(cfg->ifa_flags & IFA_F_MCAUTOJOIN)) ||
(!(idev->dev->flags & IFF_LOOPBACK) &&
!netif_is_l3_master(idev->dev) &&
addr_type & IPV6_ADDR_LOOPBACK))
@@ -2465,8 +2466,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
ASSERT_RTNL();
idev = ipv6_find_idev(dev);
- if (!idev)
- return ERR_PTR(-ENOBUFS);
+ if (IS_ERR(idev))
+ return idev;
if (idev->cnf.disable_ipv6)
return ERR_PTR(-EACCES);
@@ -3158,7 +3159,7 @@ static void init_loopback(struct net_device *dev)
ASSERT_RTNL();
idev = ipv6_find_idev(dev);
- if (!idev) {
+ if (IS_ERR(idev)) {
pr_debug("%s: add_dev failed\n", __func__);
return;
}
@@ -3373,7 +3374,7 @@ static void addrconf_sit_config(struct net_device *dev)
*/
idev = ipv6_find_idev(dev);
- if (!idev) {
+ if (IS_ERR(idev)) {
pr_debug("%s: add_dev failed\n", __func__);
return;
}
@@ -3398,7 +3399,7 @@ static void addrconf_gre_config(struct net_device *dev)
ASSERT_RTNL();
idev = ipv6_find_idev(dev);
- if (!idev) {
+ if (IS_ERR(idev)) {
pr_debug("%s: add_dev failed\n", __func__);
return;
}
@@ -4772,8 +4773,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
idev = ipv6_find_idev(dev);
- if (!idev)
- return -ENOBUFS;
+ if (IS_ERR(idev))
+ return PTR_ERR(idev);
if (!ipv6_allow_optimistic_dad(net, idev))
cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c2049c72f3e5..dd2d0b963260 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -660,12 +660,13 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
struct flowi6 *fl6, __u8 *dsfield,
int *encap_limit)
{
- struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ipv6hdr *ipv6h;
struct ip6_tnl *t = netdev_priv(dev);
__u16 offset;
offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
/* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+ ipv6h = ipv6_hdr(skb);
if (offset > 0) {
struct ipv6_tlv_tnl_enc_lim *tel;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3134fbb65d7f..754a484d35df 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1278,12 +1278,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
}
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
- dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
-
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1367,12 +1366,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
}
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
- dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
-
skb_set_inner_ipproto(skb, IPPROTO_IPV6);
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 7f3f13c37916..eaa4c2cc2fbb 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -787,14 +787,15 @@ static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
if (pmc) {
im->idev = pmc->idev;
if (im->mca_sfmode == MCAST_INCLUDE) {
- im->mca_tomb = pmc->mca_tomb;
- im->mca_sources = pmc->mca_sources;
+ swap(im->mca_tomb, pmc->mca_tomb);
+ swap(im->mca_sources, pmc->mca_sources);
for (psf = im->mca_sources; psf; psf = psf->sf_next)
psf->sf_crcount = idev->mc_qrv;
} else {
im->mca_crcount = idev->mc_qrv;
}
in6_dev_put(pmc->idev);
+ ip6_mc_clear_src(pmc);
kfree(pmc);
}
spin_unlock_bh(&im->mca_lock);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 0f82c150543b..fed9666a2f7d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -348,7 +348,7 @@ static int nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *skb,
skb_reset_transport_header(skb);
- inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+ inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
skb->ignore_df = 1;
skb->dev = dev;
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 87d2d8c1db7c..98ac32b49d8c 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -223,7 +223,7 @@ static int __net_init ping_v6_proc_init_net(struct net *net)
return 0;
}
-static void __net_init ping_v6_proc_exit_net(struct net *net)
+static void __net_exit ping_v6_proc_exit_net(struct net *net)
{
remove_proc_entry("icmp6", net->proc_net);
}
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index ca05b16f1bb9..1f5d4d196dcc 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -282,7 +282,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
skb_reset_transport_header(skb);
- inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+ inet_frag_reasm_finish(&fq->q, skb, reasm_data, true);
skb->dev = dev;
ipv6_hdr(skb)->payload_len = htons(payload_len);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e49fec767a10..546088e50815 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1951,7 +1951,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
nexthop_for_each_fib6_nh(from->nh, fib6_nh_find_match, &arg);
if (!arg.match)
- return;
+ goto unlock;
fib6_nh = arg.match;
} else {
fib6_nh = from->fib6_nh;
@@ -4388,13 +4388,14 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
struct fib6_config cfg = {
.fc_table = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL,
.fc_ifindex = idev->dev->ifindex,
- .fc_flags = RTF_UP | RTF_ADDRCONF | RTF_NONEXTHOP,
+ .fc_flags = RTF_UP | RTF_NONEXTHOP,
.fc_dst = *addr,
.fc_dst_len = 128,
.fc_protocol = RTPROT_KERNEL,
.fc_nlinfo.nl_net = net,
.fc_ignore_dev_down = true,
};
+ struct fib6_info *f6i;
if (anycast) {
cfg.fc_type = RTN_ANYCAST;
@@ -4404,7 +4405,10 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
cfg.fc_flags |= RTF_LOCAL;
}
- return ip6_route_info_create(&cfg, gfp_flags, NULL);
+ f6i = ip6_route_info_create(&cfg, gfp_flags, NULL);
+ if (!IS_ERR(f6i))
+ f6i->dst_nocount = true;
+ return f6i;
}
/* remove deleted ip from prefsrc entries */
@@ -5325,11 +5329,11 @@ static int rt6_fill_node_nexthop(struct sk_buff *skb, struct nexthop *nh,
if (nexthop_is_multipath(nh)) {
struct nlattr *mp;
- mp = nla_nest_start(skb, RTA_MULTIPATH);
+ mp = nla_nest_start_noflag(skb, RTA_MULTIPATH);
if (!mp)
goto nla_put_failure;
- if (nexthop_mpath_fill_node(skb, nh))
+ if (nexthop_mpath_fill_node(skb, nh, AF_INET6))
goto nla_put_failure;
nla_nest_end(skb, mp);
@@ -5337,7 +5341,7 @@ static int rt6_fill_node_nexthop(struct sk_buff *skb, struct nexthop *nh,
struct fib6_nh *fib6_nh;
fib6_nh = nexthop_fib6_nh(nh);
- if (fib_nexthop_info(skb, &fib6_nh->nh_common,
+ if (fib_nexthop_info(skb, &fib6_nh->nh_common, AF_INET6,
flags, false) < 0)
goto nla_put_failure;
}
@@ -5466,13 +5470,14 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
goto nla_put_failure;
if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common,
- rt->fib6_nh->fib_nh_weight) < 0)
+ rt->fib6_nh->fib_nh_weight, AF_INET6) < 0)
goto nla_put_failure;
list_for_each_entry_safe(sibling, next_sibling,
&rt->fib6_siblings, fib6_siblings) {
if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common,
- sibling->fib6_nh->fib_nh_weight) < 0)
+ sibling->fib6_nh->fib_nh_weight,
+ AF_INET6) < 0)
goto nla_put_failure;
}
@@ -5489,7 +5494,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
rtm->rtm_flags |= nh_flags;
} else {
- if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common,
+ if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common, AF_INET6,
&nh_flags, false) < 0)
goto nla_put_failure;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 09e1694b6d34..ebb62a4ebe30 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -512,7 +512,9 @@ static void iucv_sock_close(struct sock *sk)
sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
}
- case IUCV_DISCONN: /* fall through */
+ /* fall through */
+
+ case IUCV_DISCONN:
sk->sk_state = IUCV_CLOSING;
sk->sk_state_change(sk);
@@ -525,8 +527,9 @@ static void iucv_sock_close(struct sock *sk)
iucv_sock_in_state(sk, IUCV_CLOSED, 0),
timeo);
}
+ /* fall through */
- case IUCV_CLOSING: /* fall through */
+ case IUCV_CLOSING:
sk->sk_state = IUCV_CLOSED;
sk->sk_state_change(sk);
@@ -535,8 +538,9 @@ static void iucv_sock_close(struct sock *sk)
skb_queue_purge(&iucv->send_skb_q);
skb_queue_purge(&iucv->backlog_skb_q);
+ /* fall through */
- default: /* fall through */
+ default:
iucv_sever_path(sk, 1);
}
@@ -2247,10 +2251,10 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
kfree_skb(skb);
break;
}
- /* fall through and receive non-zero length data */
+ /* fall through - and receive non-zero length data */
case (AF_IUCV_FLAG_SHT):
/* shutdown request */
- /* fall through and receive zero length data */
+ /* fall through - and receive zero length data */
case 0:
/* plain data frame */
IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 1d0e5904dedf..c54cb59593ef 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1681,6 +1681,9 @@ static const struct proto_ops pppol2tp_ops = {
.recvmsg = pppol2tp_recvmsg,
.mmap = sock_no_mmap,
.ioctl = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = pppox_compat_ioctl,
+#endif
};
static const struct pppox_proto pppol2tp_proto = {
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4d458067d80d..4105c97c7ba1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1529,7 +1529,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
int err;
- int layer2_update;
if (params->vlan) {
sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
@@ -1546,6 +1545,11 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
if (is_multicast_ether_addr(mac))
return -EINVAL;
+ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER) &&
+ sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !sdata->u.mgd.associated)
+ return -EINVAL;
+
sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
if (!sta)
return -ENOMEM;
@@ -1553,10 +1557,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
sta->sta.tdls = true;
- if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION &&
- !sdata->u.mgd.associated)
- return -EINVAL;
-
err = sta_apply_parameters(local, sta, params);
if (err) {
sta_info_free(local, sta);
@@ -1572,18 +1572,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
test_sta_flag(sta, WLAN_STA_ASSOC))
rate_control_rate_init(sta);
- layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
- sdata->vif.type == NL80211_IFTYPE_AP;
-
err = sta_info_insert_rcu(sta);
if (err) {
rcu_read_unlock();
return err;
}
- if (layer2_update)
- cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
-
rcu_read_unlock();
return 0;
@@ -1681,10 +1675,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
ieee80211_vif_inc_num_mcast(sta->sdata);
-
- cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
+ cfg80211_send_layer2_update(sta->sdata->dev,
+ sta->sta.addr);
+ }
}
err = sta_apply_parameters(local, sta, params);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 06aac0aaae64..8dc6580e1787 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1222,7 +1222,6 @@ static void ieee80211_if_setup(struct net_device *dev)
static void ieee80211_if_setup_no_queue(struct net_device *dev)
{
ieee80211_if_setup(dev);
- dev->features |= NETIF_F_LLTX;
dev->priv_flags |= IFF_NO_QUEUE;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a99ad0325309..4c888dc9bd81 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2042,6 +2042,16 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
}
+ /* WMM specification requires all 4 ACIs. */
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ if (params[ac].cw_min == 0) {
+ sdata_info(sdata,
+ "AP has invalid WMM params (missing AC %d), using defaults\n",
+ ac);
+ return false;
+ }
+ }
+
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
mlme_dbg(sdata,
"WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3c1ab870fefe..768d14c9a716 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2447,11 +2447,13 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
sdata->control_port_over_nl80211)) {
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- bool noencrypt = status->flag & RX_FLAG_DECRYPTED;
+ bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED);
cfg80211_rx_control_port(dev, skb, noencrypt);
dev_kfree_skb(skb);
} else {
+ memset(skb->cb, 0, sizeof(skb->cb));
+
/* deliver to local stack */
if (rx->napi)
napi_gro_receive(rx->napi, skb);
@@ -2546,8 +2548,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
if (skb) {
skb->protocol = eth_type_trans(skb, dev);
- memset(skb->cb, 0, sizeof(skb->cb));
-
ieee80211_deliver_skb_to_local_stack(skb, rx);
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 95eb8220e2e4..5fb368cc2633 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1979,6 +1979,10 @@ int sta_info_move_state(struct sta_info *sta,
ieee80211_check_fast_xmit(sta);
ieee80211_check_fast_rx(sta);
}
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP)
+ cfg80211_send_layer2_update(sta->sdata->dev,
+ sta->sta.addr);
break;
default:
break;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1b224fa27367..ad1e58184c4e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3796,9 +3796,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
}
/* Always allow software iftypes */
- if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
- (iftype == NL80211_IFTYPE_AP_VLAN &&
- local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
+ if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) {
if (radar_detect)
return -EINVAL;
return 0;
@@ -3833,7 +3831,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
if (sdata_iter == sdata ||
!ieee80211_sdata_running(sdata_iter) ||
- local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
+ cfg80211_iftype_allowed(local->hw.wiphy,
+ wdev_iter->iftype, 0, 1))
continue;
params.iftype_num[wdev_iter->iftype]++;
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index d25e91d7bdc1..44b675016393 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -133,12 +133,12 @@ static int mpls_xmit(struct sk_buff *skb)
mpls_stats_inc_outucastpkts(out_dev, skb);
if (rt) {
- if (rt->rt_gw_family == AF_INET)
- err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
- skb);
- else if (rt->rt_gw_family == AF_INET6)
+ if (rt->rt_gw_family == AF_INET6)
err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt->rt_gw6,
skb);
+ else
+ err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
+ skb);
} else if (rt6) {
if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) {
/* 6PE (RFC 4798) */
diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
index 5c3fad8cba57..0187e65176c0 100644
--- a/net/ncsi/ncsi-cmd.c
+++ b/net/ncsi/ncsi-cmd.c
@@ -54,7 +54,7 @@ static void ncsi_cmd_build_header(struct ncsi_pkt_hdr *h,
checksum = ncsi_calculate_checksum((unsigned char *)h,
sizeof(*h) + nca->payload);
pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) +
- nca->payload);
+ ALIGN(nca->payload, 4));
*pchecksum = htonl(checksum);
}
@@ -309,14 +309,21 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca)
int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca)
{
+ struct ncsi_cmd_handler *nch = NULL;
struct ncsi_request *nr;
+ unsigned char type;
struct ethhdr *eh;
- struct ncsi_cmd_handler *nch = NULL;
int i, ret;
+ /* Use OEM generic handler for Netlink request */
+ if (nca->req_flags == NCSI_REQ_FLAG_NETLINK_DRIVEN)
+ type = NCSI_PKT_CMD_OEM;
+ else
+ type = nca->type;
+
/* Search for the handler */
for (i = 0; i < ARRAY_SIZE(ncsi_cmd_handlers); i++) {
- if (ncsi_cmd_handlers[i].type == nca->type) {
+ if (ncsi_cmd_handlers[i].type == type) {
if (ncsi_cmd_handlers[i].handler)
nch = &ncsi_cmd_handlers[i];
else
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index 7581bf919885..d876bd55f356 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -47,7 +47,8 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) {
netdev_dbg(nr->ndp->ndev.dev,
- "NCSI: non zero response/reason code\n");
+ "NCSI: non zero response/reason code %04xh, %04xh\n",
+ ntohs(h->code), ntohs(h->reason));
return -EPERM;
}
@@ -55,7 +56,7 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
* sender doesn't support checksum according to NCSI
* specification.
*/
- pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
+ pchecksum = (__be32 *)((void *)(h + 1) + ALIGN(payload, 4) - 4);
if (ntohl(*pchecksum) == 0)
return 0;
@@ -63,7 +64,9 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
sizeof(*h) + payload - 4);
if (*pchecksum != htonl(checksum)) {
- netdev_dbg(nr->ndp->ndev.dev, "NCSI: checksum mismatched\n");
+ netdev_dbg(nr->ndp->ndev.dev,
+ "NCSI: checksum mismatched; recd: %08x calc: %08x\n",
+ *pchecksum, htonl(checksum));
return -EINVAL;
}
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index ca7ac4a25ada..1d4e63326e68 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -226,7 +226,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
e.id = ip_to_id(map, ip);
- if (opt->flags & IPSET_DIM_ONE_SRC)
+ if (opt->flags & IPSET_DIM_TWO_SRC)
ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
else
ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 2e151856ad99..e64d5f9a89dd 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1161,7 +1161,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
return -ENOENT;
write_lock_bh(&ip_set_ref_lock);
- if (set->ref != 0) {
+ if (set->ref != 0 || set->ref_netlink != 0) {
ret = -IPSET_ERR_REFERENCED;
goto out;
}
diff --git a/net/netfilter/ipset/ip_set_hash_ipmac.c b/net/netfilter/ipset/ip_set_hash_ipmac.c
index faf59b6a998f..24d8f4df4230 100644
--- a/net/netfilter/ipset/ip_set_hash_ipmac.c
+++ b/net/netfilter/ipset/ip_set_hash_ipmac.c
@@ -89,15 +89,11 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
- /* MAC can be src only */
- if (!(opt->flags & IPSET_DIM_TWO_SRC))
- return 0;
-
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
return -EINVAL;
- if (opt->flags & IPSET_DIM_ONE_SRC)
+ if (opt->flags & IPSET_DIM_TWO_SRC)
ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
else
ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index a542761e90d1..81a8ef42b88d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -453,13 +453,12 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
* table location, we assume id gets exposed to userspace.
*
* Following nf_conn items do not change throughout lifetime
- * of the nf_conn after it has been committed to main hash table:
+ * of the nf_conn:
*
* 1. nf_conn address
- * 2. nf_conn->ext address
- * 3. nf_conn->master address (normally NULL)
- * 4. tuple
- * 5. the associated net namespace
+ * 2. nf_conn->master address (normally NULL)
+ * 3. the associated net namespace
+ * 4. the original direction tuple
*/
u32 nf_ct_get_id(const struct nf_conn *ct)
{
@@ -469,9 +468,10 @@ u32 nf_ct_get_id(const struct nf_conn *ct)
net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
a = (unsigned long)ct;
- b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
- c = (unsigned long)ct->ext;
- d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
+ b = (unsigned long)ct->master;
+ c = (unsigned long)nf_ct_net(ct);
+ d = (unsigned long)siphash(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ sizeof(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple),
&ct_id_seed);
#ifdef CONFIG_64BIT
return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 0ecb3e289ef2..8d96738b7dfd 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -322,7 +322,7 @@ static int find_pattern(const char *data, size_t dlen,
i++;
}
- pr_debug("Skipped up to `%c'!\n", skip);
+ pr_debug("Skipped up to 0x%hhx delimiter!\n", skip);
*numoff = i;
*numlen = getnum(data + i, dlen - i, cmd, term, numoff);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 6aa01eb6fe99..e2d13cd18875 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -553,10 +553,8 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
goto nla_put_failure;
if (ctnetlink_dump_status(skb, ct) < 0 ||
- ctnetlink_dump_timeout(skb, ct) < 0 ||
ctnetlink_dump_acct(skb, ct, type) < 0 ||
ctnetlink_dump_timestamp(skb, ct) < 0 ||
- ctnetlink_dump_protoinfo(skb, ct) < 0 ||
ctnetlink_dump_helpinfo(skb, ct) < 0 ||
ctnetlink_dump_mark(skb, ct) < 0 ||
ctnetlink_dump_secctx(skb, ct) < 0 ||
@@ -568,6 +566,11 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
ctnetlink_dump_ct_synproxy(skb, ct) < 0)
goto nla_put_failure;
+ if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) &&
+ (ctnetlink_dump_timeout(skb, ct) < 0 ||
+ ctnetlink_dump_protoinfo(skb, ct) < 0))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return skb->len;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index e0d392cb3075..0006503d2da9 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -1037,9 +1037,14 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
table[NF_SYSCTL_CT_COUNT].data = &net->ct.count;
table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
+ table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct;
+ table[NF_SYSCTL_CT_HELPER].data = &net->ct.sysctl_auto_assign_helper;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp;
+#endif
table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout;
table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout;
table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout;
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index e3d797252a98..a0b4bf654de2 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -111,15 +111,16 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ)
#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ)
-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+ return (__s32)(timeout - (u32)jiffies);
+}
+
+static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
{
const struct nf_conntrack_l4proto *l4proto;
+ int l4num = nf_ct_protonum(ct);
unsigned int timeout;
- int l4num;
-
- l4num = nf_ct_protonum(ct);
- if (l4num == IPPROTO_TCP)
- flow_offload_fixup_tcp(&ct->proto.tcp);
l4proto = nf_ct_l4proto_find(l4num);
if (!l4proto)
@@ -132,7 +133,20 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)
else
return;
- ct->timeout = nfct_time_stamp + timeout;
+ if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
+ ct->timeout = nfct_time_stamp + timeout;
+}
+
+static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+{
+ if (nf_ct_protonum(ct) == IPPROTO_TCP)
+ flow_offload_fixup_tcp(&ct->proto.tcp);
+}
+
+static void flow_offload_fixup_ct(struct nf_conn *ct)
+{
+ flow_offload_fixup_ct_state(ct);
+ flow_offload_fixup_ct_timeout(ct);
}
void flow_offload_free(struct flow_offload *flow)
@@ -203,11 +217,16 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
return err;
}
- flow->timeout = (u32)jiffies;
+ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
return 0;
}
EXPORT_SYMBOL_GPL(flow_offload_add);
+static inline bool nf_flow_has_expired(const struct flow_offload *flow)
+{
+ return nf_flow_timeout_delta(flow->timeout) <= 0;
+}
+
static void flow_offload_del(struct nf_flowtable *flow_table,
struct flow_offload *flow)
{
@@ -223,6 +242,11 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
e = container_of(flow, struct flow_offload_entry, flow);
clear_bit(IPS_OFFLOAD_BIT, &e->ct->status);
+ if (nf_flow_has_expired(flow))
+ flow_offload_fixup_ct(e->ct);
+ else if (flow->flags & FLOW_OFFLOAD_TEARDOWN)
+ flow_offload_fixup_ct_timeout(e->ct);
+
flow_offload_free(flow);
}
@@ -298,11 +322,6 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
return err;
}
-static inline bool nf_flow_has_expired(const struct flow_offload *flow)
-{
- return (__s32)(flow->timeout - (u32)jiffies) <= 0;
-}
-
static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
{
struct nf_flowtable *flow_table = data;
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index cdfc33517e85..b9e7dd6e60ce 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -214,6 +214,24 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
return true;
}
+static int nf_flow_offload_dst_check(struct dst_entry *dst)
+{
+ if (unlikely(dst_xfrm(dst)))
+ return dst_check(dst, 0) ? 0 : -1;
+
+ return 0;
+}
+
+static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct dst_entry *dst)
+{
+ skb_orphan(skb);
+ skb_dst_set_noref(skb, dst);
+ dst_output(state->net, state->sk, skb);
+ return NF_STOLEN;
+}
+
unsigned int
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
@@ -254,12 +272,25 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
return NF_ACCEPT;
+ if (nf_flow_offload_dst_check(&rt->dst)) {
+ flow_offload_teardown(flow);
+ return NF_ACCEPT;
+ }
+
if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
return NF_DROP;
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
iph = ip_hdr(skb);
ip_decrease_ttl(iph);
+ skb->tstamp = 0;
+
+ if (unlikely(dst_xfrm(&rt->dst))) {
+ memset(skb->cb, 0, sizeof(struct inet_skb_parm));
+ IPCB(skb)->iif = skb->dev->ifindex;
+ IPCB(skb)->flags = IPSKB_FORWARDED;
+ return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+ }
skb->dev = outdev;
nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
@@ -467,6 +498,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
sizeof(*ip6h)))
return NF_ACCEPT;
+ if (nf_flow_offload_dst_check(&rt->dst)) {
+ flow_offload_teardown(flow);
+ return NF_ACCEPT;
+ }
+
if (skb_try_make_writable(skb, sizeof(*ip6h)))
return NF_DROP;
@@ -476,6 +512,14 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
ip6h = ipv6_hdr(skb);
ip6h->hop_limit--;
+ skb->tstamp = 0;
+
+ if (unlikely(dst_xfrm(&rt->dst))) {
+ memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+ IP6CB(skb)->iif = skb->dev->ifindex;
+ IP6CB(skb)->flags = IP6SKB_FORWARDED;
+ return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+ }
skb->dev = outdev;
nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 605a7cfe7ca7..d47469f824a1 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -138,9 +138,14 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
return;
list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
- if (trans->msg_type == NFT_MSG_NEWSET &&
- nft_trans_set(trans) == set) {
- set->bound = true;
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (nft_trans_set(trans) == set)
+ nft_trans_set_bound(trans) = true;
+ break;
+ case NFT_MSG_NEWSETELEM:
+ if (nft_trans_elem_set(trans) == set)
+ nft_trans_elem_set_bound(trans) = true;
break;
}
}
@@ -1662,6 +1667,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
chain->flags |= NFT_BASE_CHAIN | flags;
basechain->policy = NF_ACCEPT;
+ if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
+ nft_chain_offload_priority(basechain) < 0)
+ return -EOPNOTSUPP;
+
flow_block_init(&basechain->flow_block);
} else {
chain = kzalloc(sizeof(*chain), GFP_KERNEL);
@@ -6906,7 +6915,7 @@ static int __nf_tables_abort(struct net *net)
break;
case NFT_MSG_NEWSET:
trans->ctx.table->use--;
- if (nft_trans_set(trans)->bound) {
+ if (nft_trans_set_bound(trans)) {
nft_trans_destroy(trans);
break;
}
@@ -6918,7 +6927,7 @@ static int __nf_tables_abort(struct net *net)
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWSETELEM:
- if (nft_trans_elem_set(trans)->bound) {
+ if (nft_trans_elem_set_bound(trans)) {
nft_trans_destroy(trans);
break;
}
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index 64f5fd5f240e..c0d18c1d77ac 100644
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -103,10 +103,11 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
}
static void nft_flow_offload_common_init(struct flow_cls_common_offload *common,
- __be16 proto,
- struct netlink_ext_ack *extack)
+ __be16 proto, int priority,
+ struct netlink_ext_ack *extack)
{
common->protocol = proto;
+ common->prio = priority;
common->extack = extack;
}
@@ -124,6 +125,15 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
return 0;
}
+int nft_chain_offload_priority(struct nft_base_chain *basechain)
+{
+ if (basechain->ops.priority <= 0 ||
+ basechain->ops.priority > USHRT_MAX)
+ return -1;
+
+ return 0;
+}
+
static int nft_flow_offload_rule(struct nft_trans *trans,
enum flow_cls_command command)
{
@@ -142,7 +152,8 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
if (flow)
proto = flow->proto;
- nft_flow_offload_common_init(&cls_flow.common, proto, &extack);
+ nft_flow_offload_common_init(&cls_flow.common, proto,
+ basechain->ops.priority, &extack);
cls_flow.command = command;
cls_flow.cookie = (unsigned long) rule;
if (flow)
diff --git a/net/netfilter/nft_fib_netdev.c b/net/netfilter/nft_fib_netdev.c
index 2cf3f32fe6d2..a2e726ae7f07 100644
--- a/net/netfilter/nft_fib_netdev.c
+++ b/net/netfilter/nft_fib_netdev.c
@@ -14,6 +14,7 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+#include <net/ipv6.h>
#include <net/netfilter/nft_fib.h>
@@ -34,6 +35,8 @@ static void nft_fib_netdev_eval(const struct nft_expr *expr,
}
break;
case ETH_P_IPV6:
+ if (!ipv6_mod_enabled())
+ break;
switch (priv->result) {
case NFT_FIB_RESULT_OIF:
case NFT_FIB_RESULT_OIFNAME:
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index aa5f571d4361..01705ad74a9a 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -72,11 +72,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
{
struct nft_flow_offload *priv = nft_expr_priv(expr);
struct nf_flowtable *flowtable = &priv->flowtable->data;
+ struct tcphdr _tcph, *tcph = NULL;
enum ip_conntrack_info ctinfo;
struct nf_flow_route route;
struct flow_offload *flow;
enum ip_conntrack_dir dir;
- bool is_tcp = false;
struct nf_conn *ct;
int ret;
@@ -89,7 +89,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
case IPPROTO_TCP:
- is_tcp = true;
+ tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff,
+ sizeof(_tcph), &_tcph);
+ if (unlikely(!tcph || tcph->fin || tcph->rst))
+ goto out;
break;
case IPPROTO_UDP:
break;
@@ -115,7 +118,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
if (!flow)
goto err_flow_alloc;
- if (is_tcp) {
+ if (tcph) {
ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
}
@@ -146,6 +149,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
return nft_chain_validate_hooks(ctx->chain, hook_mask);
}
+static const struct nla_policy nft_flow_offload_policy[NFTA_FLOW_MAX + 1] = {
+ [NFTA_FLOW_TABLE_NAME] = { .type = NLA_STRING,
+ .len = NFT_NAME_MAXLEN - 1 },
+};
+
static int nft_flow_offload_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
@@ -204,6 +212,7 @@ static const struct nft_expr_ops nft_flow_offload_ops = {
static struct nft_expr_type nft_flow_offload_type __read_mostly = {
.name = "flow_offload",
.ops = &nft_flow_offload_ops,
+ .policy = nft_flow_offload_policy,
.maxattr = NFTA_FLOW_MAX,
.owner = THIS_MODULE,
};
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index f1b1d948c07b..f69afb9ff3cb 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
*dest = skb->mark;
break;
case NFT_META_IIF:
- if (in == NULL)
- goto err;
- *dest = in->ifindex;
+ *dest = in ? in->ifindex : 0;
break;
case NFT_META_OIF:
- if (out == NULL)
- goto err;
- *dest = out->ifindex;
+ *dest = out ? out->ifindex : 0;
break;
case NFT_META_IIFNAME:
- if (in == NULL)
- goto err;
- strncpy((char *)dest, in->name, IFNAMSIZ);
+ strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
break;
case NFT_META_OIFNAME:
- if (out == NULL)
- goto err;
- strncpy((char *)dest, out->name, IFNAMSIZ);
+ strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
break;
case NFT_META_IIFTYPE:
if (in == NULL)
diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
index d7f3776dfd71..637ce3e8c575 100644
--- a/net/netfilter/nft_socket.c
+++ b/net/netfilter/nft_socket.c
@@ -47,9 +47,6 @@ static void nft_socket_eval(const struct nft_expr *expr,
return;
}
- /* So that subsequent socket matching not to require other lookups. */
- skb->sk = sk;
-
switch(priv->key) {
case NFT_SOCKET_TRANSPARENT:
nft_reg_store8(dest, inet_sk_transparent(sk));
@@ -66,6 +63,9 @@ static void nft_socket_eval(const struct nft_expr *expr,
WARN_ON(1);
regs->verdict.code = NFT_BREAK;
}
+
+ if (sk != skb->sk)
+ sock_gen_put(sk);
}
static const struct nla_policy nft_socket_policy[NFTA_SOCKET_MAX + 1] = {
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c
index d0ab1adf5bff..5aab6df74e0f 100644
--- a/net/netfilter/xt_nfacct.c
+++ b/net/netfilter/xt_nfacct.c
@@ -54,25 +54,39 @@ nfacct_mt_destroy(const struct xt_mtdtor_param *par)
nfnl_acct_put(info->nfacct);
}
-static struct xt_match nfacct_mt_reg __read_mostly = {
- .name = "nfacct",
- .family = NFPROTO_UNSPEC,
- .checkentry = nfacct_mt_checkentry,
- .match = nfacct_mt,
- .destroy = nfacct_mt_destroy,
- .matchsize = sizeof(struct xt_nfacct_match_info),
- .usersize = offsetof(struct xt_nfacct_match_info, nfacct),
- .me = THIS_MODULE,
+static struct xt_match nfacct_mt_reg[] __read_mostly = {
+ {
+ .name = "nfacct",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = nfacct_mt_checkentry,
+ .match = nfacct_mt,
+ .destroy = nfacct_mt_destroy,
+ .matchsize = sizeof(struct xt_nfacct_match_info),
+ .usersize = offsetof(struct xt_nfacct_match_info, nfacct),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "nfacct",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = nfacct_mt_checkentry,
+ .match = nfacct_mt,
+ .destroy = nfacct_mt_destroy,
+ .matchsize = sizeof(struct xt_nfacct_match_info_v1),
+ .usersize = offsetof(struct xt_nfacct_match_info_v1, nfacct),
+ .me = THIS_MODULE,
+ },
};
static int __init nfacct_mt_init(void)
{
- return xt_register_match(&nfacct_mt_reg);
+ return xt_register_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg));
}
static void __exit nfacct_mt_exit(void)
{
- xt_unregister_match(&nfacct_mt_reg);
+ xt_unregister_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg));
}
module_init(nfacct_mt_init);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index ead7c6022208..b92b22ce8abd 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -101,11 +101,9 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) &&
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
- par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
- (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
+ par->hook_mask & (1 << NF_INET_LOCAL_OUT)) {
pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
- if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
- return -EINVAL;
+ return -EINVAL;
}
if (!brnf_probed) {
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 96740d389377..c4f54ad2b98a 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -967,6 +967,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
window = skb->data[20];
+ sock_hold(make);
skb->sk = make;
skb->destructor = sock_efree;
make->sk_state = TCP_ESTABLISHED;
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 848c6eb55064..05249eb45082 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -67,6 +67,7 @@ struct ovs_conntrack_info {
struct md_mark mark;
struct md_labels labels;
char timeout[CTNL_TIMEOUT_NAME_MAX];
+ struct nf_ct_timeout *nf_ct_timeout;
#if IS_ENABLED(CONFIG_NF_NAT)
struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */
#endif
@@ -524,6 +525,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
return -EPFNOSUPPORT;
}
+ /* The key extracted from the fragment that completed this datagram
+ * likely didn't have an L4 header, so regenerate it.
+ */
+ ovs_flow_key_update_l3l4(skb, key);
+
key->ip.frag = OVS_FRAG_TYPE_NONE;
skb_clear_hash(skb);
skb->ignore_df = 1;
@@ -697,6 +703,14 @@ static bool skb_nfct_cached(struct net *net,
if (help && rcu_access_pointer(help->helper) != info->helper)
return false;
}
+ if (info->nf_ct_timeout) {
+ struct nf_conn_timeout *timeout_ext;
+
+ timeout_ext = nf_ct_timeout_find(ct);
+ if (!timeout_ext || info->nf_ct_timeout !=
+ rcu_dereference(timeout_ext->timeout))
+ return false;
+ }
/* Force conntrack entry direction to the current packet? */
if (info->force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
/* Delete the conntrack entry if confirmed, else just release
@@ -1565,7 +1579,7 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
case OVS_CT_ATTR_TIMEOUT:
memcpy(info->timeout, nla_data(a), nla_len(a));
if (!memchr(info->timeout, '\0', nla_len(a))) {
- OVS_NLERR(log, "Invalid conntrack helper");
+ OVS_NLERR(log, "Invalid conntrack timeout");
return -EINVAL;
}
break;
@@ -1657,6 +1671,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
ct_info.timeout))
pr_info_ratelimited("Failed to associated timeout "
"policy `%s'\n", ct_info.timeout);
+ else
+ ct_info.nf_ct_timeout = rcu_dereference(
+ nf_ct_timeout_find(ct_info.ct)->timeout);
+
}
if (helper) {
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 892287d06c17..d01410e52097 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1047,7 +1047,7 @@ error:
}
/* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
-static struct sw_flow_actions *get_flow_actions(struct net *net,
+static noinline_for_stack struct sw_flow_actions *get_flow_actions(struct net *net,
const struct nlattr *a,
const struct sw_flow_key *key,
const struct sw_flow_mask *mask,
@@ -1081,12 +1081,13 @@ static struct sw_flow_actions *get_flow_actions(struct net *net,
* we should not to return match object with dangling reference
* to mask.
* */
-static int ovs_nla_init_match_and_action(struct net *net,
- struct sw_flow_match *match,
- struct sw_flow_key *key,
- struct nlattr **a,
- struct sw_flow_actions **acts,
- bool log)
+static noinline_for_stack int
+ovs_nla_init_match_and_action(struct net *net,
+ struct sw_flow_match *match,
+ struct sw_flow_key *key,
+ struct nlattr **a,
+ struct sw_flow_actions **acts,
+ bool log)
{
struct sw_flow_mask mask;
int error = 0;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index bc89e16e0505..9d81d2c7bf82 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -523,78 +523,15 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
}
/**
- * key_extract - extracts a flow key from an Ethernet frame.
+ * key_extract_l3l4 - extracts L3/L4 header information.
* @skb: sk_buff that contains the frame, with skb->data pointing to the
- * Ethernet header
+ * L3 header
* @key: output flow key
*
- * The caller must ensure that skb->len >= ETH_HLEN.
- *
- * Returns 0 if successful, otherwise a negative errno value.
- *
- * Initializes @skb header fields as follows:
- *
- * - skb->mac_header: the L2 header.
- *
- * - skb->network_header: just past the L2 header, or just past the
- * VLAN header, to the first byte of the L2 payload.
- *
- * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
- * on output, then just past the IP header, if one is present and
- * of a correct length, otherwise the same as skb->network_header.
- * For other key->eth.type values it is left untouched.
- *
- * - skb->protocol: the type of the data starting at skb->network_header.
- * Equals to key->eth.type.
*/
-static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
{
int error;
- struct ethhdr *eth;
-
- /* Flags are always used as part of stats */
- key->tp.flags = 0;
-
- skb_reset_mac_header(skb);
-
- /* Link layer. */
- clear_vlan(key);
- if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
- if (unlikely(eth_type_vlan(skb->protocol)))
- return -EINVAL;
-
- skb_reset_network_header(skb);
- key->eth.type = skb->protocol;
- } else {
- eth = eth_hdr(skb);
- ether_addr_copy(key->eth.src, eth->h_source);
- ether_addr_copy(key->eth.dst, eth->h_dest);
-
- __skb_pull(skb, 2 * ETH_ALEN);
- /* We are going to push all headers that we pull, so no need to
- * update skb->csum here.
- */
-
- if (unlikely(parse_vlan(skb, key)))
- return -ENOMEM;
-
- key->eth.type = parse_ethertype(skb);
- if (unlikely(key->eth.type == htons(0)))
- return -ENOMEM;
-
- /* Multiple tagged packets need to retain TPID to satisfy
- * skb_vlan_pop(), which will later shift the ethertype into
- * skb->protocol.
- */
- if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
- skb->protocol = key->eth.cvlan.tpid;
- else
- skb->protocol = key->eth.type;
-
- skb_reset_network_header(skb);
- __skb_push(skb, skb->data - skb_mac_header(skb));
- }
- skb_reset_mac_len(skb);
/* Network layer. */
if (key->eth.type == htons(ETH_P_IP)) {
@@ -623,6 +560,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
offset = nh->frag_off & htons(IP_OFFSET);
if (offset) {
key->ip.frag = OVS_FRAG_TYPE_LATER;
+ memset(&key->tp, 0, sizeof(key->tp));
return 0;
}
if (nh->frag_off & htons(IP_MF) ||
@@ -740,8 +678,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
return error;
}
- if (key->ip.frag == OVS_FRAG_TYPE_LATER)
+ if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
+ memset(&key->tp, 0, sizeof(key->tp));
return 0;
+ }
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
key->ip.frag = OVS_FRAG_TYPE_FIRST;
@@ -788,6 +728,92 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
return 0;
}
+/**
+ * key_extract - extracts a flow key from an Ethernet frame.
+ * @skb: sk_buff that contains the frame, with skb->data pointing to the
+ * Ethernet header
+ * @key: output flow key
+ *
+ * The caller must ensure that skb->len >= ETH_HLEN.
+ *
+ * Returns 0 if successful, otherwise a negative errno value.
+ *
+ * Initializes @skb header fields as follows:
+ *
+ * - skb->mac_header: the L2 header.
+ *
+ * - skb->network_header: just past the L2 header, or just past the
+ * VLAN header, to the first byte of the L2 payload.
+ *
+ * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
+ * on output, then just past the IP header, if one is present and
+ * of a correct length, otherwise the same as skb->network_header.
+ * For other key->eth.type values it is left untouched.
+ *
+ * - skb->protocol: the type of the data starting at skb->network_header.
+ * Equals to key->eth.type.
+ */
+static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ struct ethhdr *eth;
+
+ /* Flags are always used as part of stats */
+ key->tp.flags = 0;
+
+ skb_reset_mac_header(skb);
+
+ /* Link layer. */
+ clear_vlan(key);
+ if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
+ if (unlikely(eth_type_vlan(skb->protocol)))
+ return -EINVAL;
+
+ skb_reset_network_header(skb);
+ key->eth.type = skb->protocol;
+ } else {
+ eth = eth_hdr(skb);
+ ether_addr_copy(key->eth.src, eth->h_source);
+ ether_addr_copy(key->eth.dst, eth->h_dest);
+
+ __skb_pull(skb, 2 * ETH_ALEN);
+ /* We are going to push all headers that we pull, so no need to
+ * update skb->csum here.
+ */
+
+ if (unlikely(parse_vlan(skb, key)))
+ return -ENOMEM;
+
+ key->eth.type = parse_ethertype(skb);
+ if (unlikely(key->eth.type == htons(0)))
+ return -ENOMEM;
+
+ /* Multiple tagged packets need to retain TPID to satisfy
+ * skb_vlan_pop(), which will later shift the ethertype into
+ * skb->protocol.
+ */
+ if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
+ skb->protocol = key->eth.cvlan.tpid;
+ else
+ skb->protocol = key->eth.type;
+
+ skb_reset_network_header(skb);
+ __skb_push(skb, skb->data - skb_mac_header(skb));
+ }
+
+ skb_reset_mac_len(skb);
+
+ /* Fill out L3/L4 key info, if any */
+ return key_extract_l3l4(skb, key);
+}
+
+/* In the case of conntrack fragment handling it expects L3 headers,
+ * add a helper.
+ */
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ return key_extract_l3l4(skb, key);
+}
+
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
{
int res;
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index a5506e2d4b7a..b830d5ff7af4 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -270,6 +270,7 @@ void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies);
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key);
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
struct sk_buff *skb,
struct sw_flow_key *key);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8d54f3047768..e2742b006d25 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2618,6 +2618,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
mutex_lock(&po->pg_vec_lock);
+ /* packet_sendmsg() check on tx_ring.pg_vec was lockless,
+ * we need to confirm it under protection of pg_vec_lock.
+ */
+ if (unlikely(!po->tx_ring.pg_vec)) {
+ err = -EBUSY;
+ goto out;
+ }
if (likely(saddr == NULL)) {
dev = packet_cached_dev_get(po);
proto = po->num;
diff --git a/net/psample/psample.c b/net/psample/psample.c
index 841f198ea1a8..66e4b61a350d 100644
--- a/net/psample/psample.c
+++ b/net/psample/psample.c
@@ -154,7 +154,7 @@ static void psample_group_destroy(struct psample_group *group)
{
psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP);
list_del(&group->list);
- kfree(group);
+ kfree_rcu(group, rcu);
}
static struct psample_group *
diff --git a/net/qrtr/tun.c b/net/qrtr/tun.c
index ccff1e544c21..e35869e81766 100644
--- a/net/qrtr/tun.c
+++ b/net/qrtr/tun.c
@@ -84,11 +84,14 @@ static ssize_t qrtr_tun_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (!kbuf)
return -ENOMEM;
- if (!copy_from_iter_full(kbuf, len, from))
+ if (!copy_from_iter_full(kbuf, len, from)) {
+ kfree(kbuf);
return -EFAULT;
+ }
ret = qrtr_endpoint_post(&tun->ep, kbuf, len);
+ kfree(kbuf);
return ret < 0 ? ret : len;
}
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 0f4398e7f2a7..05464fd7c17a 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -239,34 +239,30 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out;
}
- sock_set_flag(sk, SOCK_RCU_FREE);
- ret = rds_add_bound(rs, binding_addr, &port, scope_id);
- if (ret)
- goto out;
-
- if (rs->rs_transport) { /* previously bound */
+ /* The transport can be set using SO_RDS_TRANSPORT option before the
+ * socket is bound.
+ */
+ if (rs->rs_transport) {
trans = rs->rs_transport;
if (trans->laddr_check(sock_net(sock->sk),
binding_addr, scope_id) != 0) {
ret = -ENOPROTOOPT;
- rds_remove_bound(rs);
- } else {
- ret = 0;
+ goto out;
}
- goto out;
- }
- trans = rds_trans_get_preferred(sock_net(sock->sk), binding_addr,
- scope_id);
- if (!trans) {
- ret = -EADDRNOTAVAIL;
- rds_remove_bound(rs);
- pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
- __func__, binding_addr);
- goto out;
+ } else {
+ trans = rds_trans_get_preferred(sock_net(sock->sk),
+ binding_addr, scope_id);
+ if (!trans) {
+ ret = -EADDRNOTAVAIL;
+ pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
+ __func__, binding_addr);
+ goto out;
+ }
+ rs->rs_transport = trans;
}
- rs->rs_transport = trans;
- ret = 0;
+ sock_set_flag(sk, SOCK_RCU_FREE);
+ ret = rds_add_bound(rs, binding_addr, &port, scope_id);
out:
release_sock(sk);
diff --git a/net/rds/ib.c b/net/rds/ib.c
index ec05d91aa9a2..45acab2de0cf 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -291,7 +291,7 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
void *buffer)
{
struct rds_info_rdma_connection *iinfo = buffer;
- struct rds_ib_connection *ic;
+ struct rds_ib_connection *ic = conn->c_transport_data;
/* We will only ever look at IB transports */
if (conn->c_trans != &rds_ib_transport)
@@ -301,15 +301,16 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
iinfo->src_addr = conn->c_laddr.s6_addr32[3];
iinfo->dst_addr = conn->c_faddr.s6_addr32[3];
- iinfo->tos = conn->c_tos;
+ if (ic) {
+ iinfo->tos = conn->c_tos;
+ iinfo->sl = ic->i_sl;
+ }
memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid));
memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid));
if (rds_conn_state(conn) == RDS_CONN_UP) {
struct rds_ib_device *rds_ibdev;
- ic = conn->c_transport_data;
-
rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo->src_gid,
(union ib_gid *)&iinfo->dst_gid);
@@ -329,7 +330,7 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
void *buffer)
{
struct rds6_info_rdma_connection *iinfo6 = buffer;
- struct rds_ib_connection *ic;
+ struct rds_ib_connection *ic = conn->c_transport_data;
/* We will only ever look at IB transports */
if (conn->c_trans != &rds_ib_transport)
@@ -337,6 +338,10 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
iinfo6->src_addr = conn->c_laddr;
iinfo6->dst_addr = conn->c_faddr;
+ if (ic) {
+ iinfo6->tos = conn->c_tos;
+ iinfo6->sl = ic->i_sl;
+ }
memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid));
memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid));
@@ -344,7 +349,6 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
if (rds_conn_state(conn) == RDS_CONN_UP) {
struct rds_ib_device *rds_ibdev;
- ic = conn->c_transport_data;
rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo6->src_gid,
(union ib_gid *)&iinfo6->dst_gid);
rds_ibdev = ic->rds_ibdev;
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 303c6ee8bdb7..f2b558e8b5ea 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -220,6 +220,7 @@ struct rds_ib_connection {
/* Send/Recv vectors */
int i_scq_vector;
int i_rcq_vector;
+ u8 i_sl;
};
/* This assumes that atomic_t is at least 32 bits */
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index fddaa09f7b0d..233f1368162b 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -152,6 +152,9 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
RDS_PROTOCOL_MINOR(conn->c_version),
ic->i_flowctl ? ", flow control" : "");
+ /* receive sl from the peer */
+ ic->i_sl = ic->i_cm_id->route.path_rec->sl;
+
atomic_set(&ic->i_cq_quiesce, 0);
/* Init rings and fill recv. this needs to wait until protocol
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index ff74c4bbb9fc..5f741e51b4ba 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -43,6 +43,9 @@ static struct rdma_cm_id *rds_rdma_listen_id;
static struct rdma_cm_id *rds6_rdma_listen_id;
#endif
+/* Per IB specification 7.7.3, service level is a 4-bit field. */
+#define TOS_TO_SL(tos) ((tos) & 0xF)
+
static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event,
bool isv6)
@@ -97,15 +100,19 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
struct rds_ib_connection *ibic;
ibic = conn->c_transport_data;
- if (ibic && ibic->i_cm_id == cm_id)
+ if (ibic && ibic->i_cm_id == cm_id) {
+ cm_id->route.path_rec[0].sl =
+ TOS_TO_SL(conn->c_tos);
ret = trans->cm_initiate_connect(cm_id, isv6);
- else
+ } else {
rds_conn_drop(conn);
+ }
}
break;
case RDMA_CM_EVENT_ESTABLISHED:
- trans->cm_connect_complete(conn, event);
+ if (conn)
+ trans->cm_connect_complete(conn, event);
break;
case RDMA_CM_EVENT_REJECTED:
@@ -137,6 +144,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
break;
case RDMA_CM_EVENT_DISCONNECTED:
+ if (!conn)
+ break;
rdsdebug("DISCONNECT event - dropping connection "
"%pI6c->%pI6c\n", &conn->c_laddr,
&conn->c_faddr);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 853de4876088..a42ba7fa06d5 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -811,6 +811,7 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
+ minfo6.tos = inc->i_conn->c_tos;
if (flip) {
minfo6.laddr = *daddr;
@@ -824,6 +825,8 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
minfo6.fport = inc->i_hdr.h_dport;
}
+ minfo6.flags = 0;
+
rds_info_copy(iter, &minfo6, sizeof(minfo6));
}
#endif
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index d09eaf153544..d72ddb67bb74 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -193,7 +193,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
service_in_use:
write_unlock(&local->services_lock);
- rxrpc_put_local(local);
+ rxrpc_unuse_local(local);
ret = -EADDRINUSE;
error_unlock:
release_sock(&rx->sk);
@@ -402,7 +402,7 @@ EXPORT_SYMBOL(rxrpc_kernel_check_life);
*/
void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call)
{
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
rxrpc_propose_ack_ping_for_check_life);
rxrpc_send_ack_packet(call, true, NULL);
}
@@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk)
static int rxrpc_release_sock(struct sock *sk)
{
struct rxrpc_sock *rx = rxrpc_sk(sk);
- struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
@@ -898,10 +897,8 @@ static int rxrpc_release_sock(struct sock *sk)
rxrpc_release_calls_on_socket(rx);
flush_workqueue(rxrpc_workqueue);
rxrpc_purge_queue(&sk->sk_receive_queue);
- rxrpc_queue_work(&rxnet->service_conn_reaper);
- rxrpc_queue_work(&rxnet->client_conn_reaper);
- rxrpc_put_local(rx->local);
+ rxrpc_unuse_local(rx->local);
rx->local = NULL;
key_put(rx->key);
rx->key = NULL;
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 80335b4ee4fd..8051dfdcf26d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -185,11 +185,17 @@ struct rxrpc_host_header {
* - max 48 bytes (struct sk_buff::cb)
*/
struct rxrpc_skb_priv {
- union {
- u8 nr_jumbo; /* Number of jumbo subpackets */
- };
+ atomic_t nr_ring_pins; /* Number of rxtx ring pins */
+ u8 nr_subpackets; /* Number of subpackets */
+ u8 rx_flags; /* Received packet flags */
+#define RXRPC_SKB_INCL_LAST 0x01 /* - Includes last packet */
+#define RXRPC_SKB_TX_BUFFER 0x02 /* - Is transmit buffer */
union {
int remain; /* amount of space remaining for next write */
+
+ /* List of requested ACKs on subpackets */
+ unsigned long rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) /
+ BITS_PER_LONG];
};
struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */
@@ -254,7 +260,8 @@ struct rxrpc_security {
*/
struct rxrpc_local {
struct rcu_head rcu;
- atomic_t usage;
+ atomic_t active_users; /* Number of users of the local endpoint */
+ atomic_t usage; /* Number of references to the structure */
struct rxrpc_net *rxnet; /* The network ns in which this resides */
struct list_head link;
struct socket *socket; /* my UDP socket */
@@ -612,8 +619,7 @@ struct rxrpc_call {
#define RXRPC_TX_ANNO_LAST 0x04
#define RXRPC_TX_ANNO_RESENT 0x08
-#define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */
-#define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */
+#define RXRPC_RX_ANNO_SUBPACKET 0x3f /* Subpacket number in jumbogram */
#define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */
rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but
* not hard-ACK'd packet follows this.
@@ -649,7 +655,6 @@ struct rxrpc_call {
/* receive-phase ACK management */
u8 ackr_reason; /* reason to ACK */
- u16 ackr_skew; /* skew on packet being ACK'd */
rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
rxrpc_serial_t ackr_first_seq; /* first sequence number received */
rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */
@@ -743,7 +748,7 @@ int rxrpc_reject_call(struct rxrpc_sock *);
/*
* call_event.c
*/
-void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
+void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool,
enum rxrpc_propose_ack_trace);
void rxrpc_process_call(struct work_struct *);
@@ -905,6 +910,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *);
void rxrpc_put_client_conn(struct rxrpc_connection *);
void rxrpc_discard_expired_client_conns(struct work_struct *);
void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
+void rxrpc_clean_up_local_conns(struct rxrpc_local *);
/*
* conn_event.c
@@ -1002,6 +1008,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc
struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
void rxrpc_put_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *);
+void rxrpc_unuse_local(struct rxrpc_local *);
void rxrpc_queue_local(struct rxrpc_local *);
void rxrpc_destroy_all_locals(struct rxrpc_net *);
@@ -1061,6 +1069,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *);
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
void rxrpc_put_peer(struct rxrpc_peer *);
+void rxrpc_put_peer_locked(struct rxrpc_peer *);
/*
* proc.c
@@ -1102,6 +1111,7 @@ void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
void rxrpc_packet_destructor(struct sk_buff *);
void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_purge_queue(struct sk_buff_head *);
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index bc2adeb3acb9..cedbbb3a7c2e 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -43,8 +43,7 @@ static void rxrpc_propose_ping(struct rxrpc_call *call,
* propose an ACK be sent
*/
static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
- u16 skew, u32 serial, bool immediate,
- bool background,
+ u32 serial, bool immediate, bool background,
enum rxrpc_propose_ack_trace why)
{
enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use;
@@ -69,14 +68,12 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) {
outcome = rxrpc_propose_ack_update;
call->ackr_serial = serial;
- call->ackr_skew = skew;
}
if (!immediate)
goto trace;
} else if (prior > rxrpc_ack_priority[call->ackr_reason]) {
call->ackr_reason = ack_reason;
call->ackr_serial = serial;
- call->ackr_skew = skew;
} else {
outcome = rxrpc_propose_ack_subsume;
}
@@ -137,11 +134,11 @@ trace:
* propose an ACK be sent, locking the call structure
*/
void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
- u16 skew, u32 serial, bool immediate, bool background,
+ u32 serial, bool immediate, bool background,
enum rxrpc_propose_ack_trace why)
{
spin_lock_bh(&call->lock);
- __rxrpc_propose_ACK(call, ack_reason, skew, serial,
+ __rxrpc_propose_ACK(call, ack_reason, serial,
immediate, background, why);
spin_unlock_bh(&call->lock);
}
@@ -202,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
continue;
skb = call->rxtx_buffer[ix];
- rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
if (anno_type == RXRPC_TX_ANNO_UNACK) {
if (ktime_after(skb->tstamp, max_age)) {
@@ -239,7 +236,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
ack_ts = ktime_sub(now, call->acks_latest_ts);
if (ktime_to_ns(ack_ts) < call->peer->rtt)
goto out;
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
rxrpc_propose_ack_ping_for_lost_ack);
rxrpc_send_ack_packet(call, true, NULL);
goto out;
@@ -258,18 +255,18 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
continue;
skb = call->rxtx_buffer[ix];
- rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+ rxrpc_get_skb(skb, rxrpc_skb_got);
spin_unlock_bh(&call->lock);
if (rxrpc_send_data_packet(call, skb, true) < 0) {
- rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
return;
}
if (rxrpc_is_client_call(call))
rxrpc_expose_client_call(call);
- rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
spin_lock_bh(&call->lock);
/* We need to clear the retransmit state, but there are two
@@ -372,7 +369,7 @@ recheck_state:
if (time_after_eq(now, t)) {
trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true,
rxrpc_propose_ack_ping_for_keepalive);
set_bit(RXRPC_CALL_EV_PING, &call->events);
}
@@ -407,7 +404,7 @@ recheck_state:
send_ack = NULL;
if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) {
call->acks_lost_top = call->tx_top;
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
rxrpc_propose_ack_ping_for_lost_ack);
send_ack = &call->acks_lost_ping;
}
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 217b12be9e08..014548c259ce 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -422,6 +422,19 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
}
/*
+ * Clean up the RxTx skb ring.
+ */
+static void rxrpc_cleanup_ring(struct rxrpc_call *call)
+{
+ int i;
+
+ for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
+ rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
+ call->rxtx_buffer[i] = NULL;
+ }
+}
+
+/*
* Detach a call from its owning socket.
*/
void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
@@ -429,7 +442,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
const void *here = __builtin_return_address(0);
struct rxrpc_connection *conn = call->conn;
bool put = false;
- int i;
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
@@ -479,13 +491,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
if (conn)
rxrpc_disconnect_call(call);
- for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
- rxrpc_free_skb(call->rxtx_buffer[i],
- (call->tx_phase ? rxrpc_skb_tx_cleaned :
- rxrpc_skb_rx_cleaned));
- call->rxtx_buffer[i] = NULL;
- }
-
+ rxrpc_cleanup_ring(call);
_leave("");
}
@@ -568,8 +574,6 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
*/
void rxrpc_cleanup_call(struct rxrpc_call *call)
{
- int i;
-
_net("DESTROY CALL %d", call->debug_id);
memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
@@ -580,13 +584,8 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
ASSERTCMP(call->conn, ==, NULL);
- /* Clean up the Rx/Tx buffer */
- for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++)
- rxrpc_free_skb(call->rxtx_buffer[i],
- (call->tx_phase ? rxrpc_skb_tx_cleaned :
- rxrpc_skb_rx_cleaned));
-
- rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned);
+ rxrpc_cleanup_ring(call);
+ rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned);
call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
}
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index aea82f909c60..3f1da1b49f69 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -1162,3 +1162,47 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
_leave("");
}
+
+/*
+ * Clean up the client connections on a local endpoint.
+ */
+void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
+{
+ struct rxrpc_connection *conn, *tmp;
+ struct rxrpc_net *rxnet = local->rxnet;
+ unsigned int nr_active;
+ LIST_HEAD(graveyard);
+
+ _enter("");
+
+ spin_lock(&rxnet->client_conn_cache_lock);
+ nr_active = rxnet->nr_active_client_conns;
+
+ list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
+ cache_link) {
+ if (conn->params.local == local) {
+ ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE);
+
+ trace_rxrpc_client(conn, -1, rxrpc_client_discard);
+ if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
+ BUG();
+ conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
+ list_move(&conn->cache_link, &graveyard);
+ nr_active--;
+ }
+ }
+
+ rxnet->nr_active_client_conns = nr_active;
+ spin_unlock(&rxnet->client_conn_cache_lock);
+ ASSERTCMP(nr_active, >=, 0);
+
+ while (!list_empty(&graveyard)) {
+ conn = list_entry(graveyard.next,
+ struct rxrpc_connection, cache_link);
+ list_del_init(&conn->cache_link);
+
+ rxrpc_put_connection(conn);
+ }
+
+ _leave(" [culled]");
+}
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index df6624c140be..a1ceef4f5cd0 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -472,7 +472,7 @@ void rxrpc_process_connection(struct work_struct *work)
/* go through the conn-level event packets, releasing the ref on this
* connection that each one has when we've finished with it */
while ((skb = skb_dequeue(&conn->rx_queue))) {
- rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
ret = rxrpc_process_event(conn, skb, &abort_code);
switch (ret) {
case -EPROTO:
@@ -484,7 +484,7 @@ void rxrpc_process_connection(struct work_struct *work)
goto requeue_and_leave;
case -ECONNABORTED:
default:
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
break;
}
}
@@ -501,6 +501,6 @@ requeue_and_leave:
protocol_error:
if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
goto requeue_and_leave;
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
goto out;
}
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 434ef392212b..ed05b6922132 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
continue;
- if (rxnet->live) {
+ if (rxnet->live && !conn->params.local->dead) {
idle_timestamp = READ_ONCE(conn->idle_timestamp);
expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
if (conn->params.local->service_closed)
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 5bd6f1546e5c..157be1ff8697 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -196,15 +196,14 @@ send_extra_data:
* Ping the other end to fill our RTT cache and to retrieve the rwind
* and MTU parameters.
*/
-static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
- int skew)
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
ktime_t now = skb->tstamp;
if (call->peer->rtt_usage < 3 ||
ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
true, true,
rxrpc_propose_ack_ping_for_params);
}
@@ -234,7 +233,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK;
skb = call->rxtx_buffer[ix];
annotation = call->rxtx_annotations[ix];
- rxrpc_see_skb(skb, rxrpc_skb_tx_rotated);
+ rxrpc_see_skb(skb, rxrpc_skb_rotated);
call->rxtx_buffer[ix] = NULL;
call->rxtx_annotations[ix] = 0;
skb->next = list;
@@ -259,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
skb = list;
list = skb->next;
skb_mark_not_on_list(skb);
- rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
}
return rot_last;
@@ -348,7 +347,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
}
/*
- * Scan a jumbo packet to validate its structure and to work out how many
+ * Scan a data packet to validate its structure and to work out how many
* subpackets it contains.
*
* A jumbo packet is a collection of consecutive packets glued together with
@@ -359,16 +358,21 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
* the last are RXRPC_JUMBO_DATALEN in size. The last subpacket may be of any
* size.
*/
-static bool rxrpc_validate_jumbo(struct sk_buff *skb)
+static bool rxrpc_validate_data(struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
unsigned int offset = sizeof(struct rxrpc_wire_header);
unsigned int len = skb->len;
- int nr_jumbo = 1;
u8 flags = sp->hdr.flags;
- do {
- nr_jumbo++;
+ for (;;) {
+ if (flags & RXRPC_REQUEST_ACK)
+ __set_bit(sp->nr_subpackets, sp->rx_req_ack);
+ sp->nr_subpackets++;
+
+ if (!(flags & RXRPC_JUMBO_PACKET))
+ break;
+
if (len - offset < RXRPC_JUMBO_SUBPKTLEN)
goto protocol_error;
if (flags & RXRPC_LAST_PACKET)
@@ -377,9 +381,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb)
if (skb_copy_bits(skb, offset, &flags, 1) < 0)
goto protocol_error;
offset += sizeof(struct rxrpc_jumbo_header);
- } while (flags & RXRPC_JUMBO_PACKET);
+ }
- sp->nr_jumbo = nr_jumbo;
+ if (flags & RXRPC_LAST_PACKET)
+ sp->rx_flags |= RXRPC_SKB_INCL_LAST;
return true;
protocol_error:
@@ -400,10 +405,10 @@ protocol_error:
* (that information is encoded in the ACK packet).
*/
static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
- u8 annotation, bool *_jumbo_bad)
+ bool is_jumbo, bool *_jumbo_bad)
{
/* Discard normal packets that are duplicates. */
- if (annotation == 0)
+ if (is_jumbo)
return;
/* Skip jumbo subpackets that are duplicates. When we've had three or
@@ -417,30 +422,30 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
}
/*
- * Process a DATA packet, adding the packet to the Rx ring.
+ * Process a DATA packet, adding the packet to the Rx ring. The caller's
+ * packet ref must be passed on or discarded.
*/
-static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
- u16 skew)
+static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
enum rxrpc_call_state state;
- unsigned int offset = sizeof(struct rxrpc_wire_header);
- unsigned int ix;
+ unsigned int j;
rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
- rxrpc_seq_t seq = sp->hdr.seq, hard_ack;
- bool immediate_ack = false, jumbo_bad = false, queued;
- u16 len;
- u8 ack = 0, flags, annotation = 0;
+ rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
+ bool immediate_ack = false, jumbo_bad = false;
+ u8 ack = 0;
_enter("{%u,%u},{%u,%u}",
- call->rx_hard_ack, call->rx_top, skb->len, seq);
+ call->rx_hard_ack, call->rx_top, skb->len, seq0);
- _proto("Rx DATA %%%u { #%u f=%02x }",
- sp->hdr.serial, seq, sp->hdr.flags);
+ _proto("Rx DATA %%%u { #%u f=%02x n=%u }",
+ sp->hdr.serial, seq0, sp->hdr.flags, sp->nr_subpackets);
state = READ_ONCE(call->state);
- if (state >= RXRPC_CALL_COMPLETE)
+ if (state >= RXRPC_CALL_COMPLETE) {
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
return;
+ }
if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
unsigned long timo = READ_ONCE(call->next_req_timo);
@@ -465,156 +470,157 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
!rxrpc_receiving_reply(call))
goto unlock;
- call->ackr_prev_seq = seq;
-
+ call->ackr_prev_seq = seq0;
hard_ack = READ_ONCE(call->rx_hard_ack);
- if (after(seq, hard_ack + call->rx_winsize)) {
- ack = RXRPC_ACK_EXCEEDS_WINDOW;
- ack_serial = serial;
- goto ack;
- }
- flags = sp->hdr.flags;
- if (flags & RXRPC_JUMBO_PACKET) {
+ if (sp->nr_subpackets > 1) {
if (call->nr_jumbo_bad > 3) {
ack = RXRPC_ACK_NOSPACE;
ack_serial = serial;
goto ack;
}
- annotation = 1;
}
-next_subpacket:
- queued = false;
- ix = seq & RXRPC_RXTX_BUFF_MASK;
- len = skb->len;
- if (flags & RXRPC_JUMBO_PACKET)
- len = RXRPC_JUMBO_DATALEN;
-
- if (flags & RXRPC_LAST_PACKET) {
- if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
- seq != call->rx_top) {
- rxrpc_proto_abort("LSN", call, seq);
- goto unlock;
- }
- } else {
- if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
- after_eq(seq, call->rx_top)) {
- rxrpc_proto_abort("LSA", call, seq);
- goto unlock;
+ for (j = 0; j < sp->nr_subpackets; j++) {
+ rxrpc_serial_t serial = sp->hdr.serial + j;
+ rxrpc_seq_t seq = seq0 + j;
+ unsigned int ix = seq & RXRPC_RXTX_BUFF_MASK;
+ bool terminal = (j == sp->nr_subpackets - 1);
+ bool last = terminal && (sp->rx_flags & RXRPC_SKB_INCL_LAST);
+ u8 flags, annotation = j;
+
+ _proto("Rx DATA+%u %%%u { #%x t=%u l=%u }",
+ j, serial, seq, terminal, last);
+
+ if (last) {
+ if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+ seq != call->rx_top) {
+ rxrpc_proto_abort("LSN", call, seq);
+ goto unlock;
+ }
+ } else {
+ if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+ after_eq(seq, call->rx_top)) {
+ rxrpc_proto_abort("LSA", call, seq);
+ goto unlock;
+ }
}
- }
-
- trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
- if (before_eq(seq, hard_ack)) {
- ack = RXRPC_ACK_DUPLICATE;
- ack_serial = serial;
- goto skip;
- }
- if (flags & RXRPC_REQUEST_ACK && !ack) {
- ack = RXRPC_ACK_REQUESTED;
- ack_serial = serial;
- }
+ flags = 0;
+ if (last)
+ flags |= RXRPC_LAST_PACKET;
+ if (!terminal)
+ flags |= RXRPC_JUMBO_PACKET;
+ if (test_bit(j, sp->rx_req_ack))
+ flags |= RXRPC_REQUEST_ACK;
+ trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
- if (call->rxtx_buffer[ix]) {
- rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad);
- if (ack != RXRPC_ACK_DUPLICATE) {
+ if (before_eq(seq, hard_ack)) {
ack = RXRPC_ACK_DUPLICATE;
ack_serial = serial;
+ continue;
}
- immediate_ack = true;
- goto skip;
- }
-
- /* Queue the packet. We use a couple of memory barriers here as need
- * to make sure that rx_top is perceived to be set after the buffer
- * pointer and that the buffer pointer is set after the annotation and
- * the skb data.
- *
- * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
- * and also rxrpc_fill_out_ack().
- */
- rxrpc_get_skb(skb, rxrpc_skb_rx_got);
- call->rxtx_annotations[ix] = annotation;
- smp_wmb();
- call->rxtx_buffer[ix] = skb;
- if (after(seq, call->rx_top)) {
- smp_store_release(&call->rx_top, seq);
- } else if (before(seq, call->rx_top)) {
- /* Send an immediate ACK if we fill in a hole */
- if (!ack) {
- ack = RXRPC_ACK_DELAY;
- ack_serial = serial;
- }
- immediate_ack = true;
- }
- if (flags & RXRPC_LAST_PACKET) {
- set_bit(RXRPC_CALL_RX_LAST, &call->flags);
- trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
- } else {
- trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
- }
- queued = true;
- if (after_eq(seq, call->rx_expect_next)) {
- if (after(seq, call->rx_expect_next)) {
- _net("OOS %u > %u", seq, call->rx_expect_next);
- ack = RXRPC_ACK_OUT_OF_SEQUENCE;
- ack_serial = serial;
+ if (call->rxtx_buffer[ix]) {
+ rxrpc_input_dup_data(call, seq, sp->nr_subpackets > 1,
+ &jumbo_bad);
+ if (ack != RXRPC_ACK_DUPLICATE) {
+ ack = RXRPC_ACK_DUPLICATE;
+ ack_serial = serial;
+ }
+ immediate_ack = true;
+ continue;
}
- call->rx_expect_next = seq + 1;
- }
-skip:
- offset += len;
- if (flags & RXRPC_JUMBO_PACKET) {
- if (skb_copy_bits(skb, offset, &flags, 1) < 0) {
- rxrpc_proto_abort("XJF", call, seq);
- goto unlock;
- }
- offset += sizeof(struct rxrpc_jumbo_header);
- seq++;
- serial++;
- annotation++;
- if (flags & RXRPC_JUMBO_PACKET)
- annotation |= RXRPC_RX_ANNO_JLAST;
if (after(seq, hard_ack + call->rx_winsize)) {
ack = RXRPC_ACK_EXCEEDS_WINDOW;
ack_serial = serial;
- if (!jumbo_bad) {
- call->nr_jumbo_bad++;
- jumbo_bad = true;
+ if (flags & RXRPC_JUMBO_PACKET) {
+ if (!jumbo_bad) {
+ call->nr_jumbo_bad++;
+ jumbo_bad = true;
+ }
}
+
goto ack;
}
- _proto("Rx DATA Jumbo %%%u", serial);
- goto next_subpacket;
- }
+ if (flags & RXRPC_REQUEST_ACK && !ack) {
+ ack = RXRPC_ACK_REQUESTED;
+ ack_serial = serial;
+ }
+
+ /* Queue the packet. We use a couple of memory barriers here as need
+ * to make sure that rx_top is perceived to be set after the buffer
+ * pointer and that the buffer pointer is set after the annotation and
+ * the skb data.
+ *
+ * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
+ * and also rxrpc_fill_out_ack().
+ */
+ if (!terminal)
+ rxrpc_get_skb(skb, rxrpc_skb_got);
+ call->rxtx_annotations[ix] = annotation;
+ smp_wmb();
+ call->rxtx_buffer[ix] = skb;
+ if (after(seq, call->rx_top)) {
+ smp_store_release(&call->rx_top, seq);
+ } else if (before(seq, call->rx_top)) {
+ /* Send an immediate ACK if we fill in a hole */
+ if (!ack) {
+ ack = RXRPC_ACK_DELAY;
+ ack_serial = serial;
+ }
+ immediate_ack = true;
+ }
- if (queued && flags & RXRPC_LAST_PACKET && !ack) {
- ack = RXRPC_ACK_DELAY;
- ack_serial = serial;
+ if (terminal) {
+ /* From this point on, we're not allowed to touch the
+ * packet any longer as its ref now belongs to the Rx
+ * ring.
+ */
+ skb = NULL;
+ }
+
+ if (last) {
+ set_bit(RXRPC_CALL_RX_LAST, &call->flags);
+ if (!ack) {
+ ack = RXRPC_ACK_DELAY;
+ ack_serial = serial;
+ }
+ trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
+ } else {
+ trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
+ }
+
+ if (after_eq(seq, call->rx_expect_next)) {
+ if (after(seq, call->rx_expect_next)) {
+ _net("OOS %u > %u", seq, call->rx_expect_next);
+ ack = RXRPC_ACK_OUT_OF_SEQUENCE;
+ ack_serial = serial;
+ }
+ call->rx_expect_next = seq + 1;
+ }
}
ack:
if (ack)
- rxrpc_propose_ACK(call, ack, skew, ack_serial,
+ rxrpc_propose_ACK(call, ack, ack_serial,
immediate_ack, true,
rxrpc_propose_ack_input_data);
else
- rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial,
+ rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
false, true,
rxrpc_propose_ack_input_data);
- if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) {
+ if (seq0 == READ_ONCE(call->rx_hard_ack) + 1) {
trace_rxrpc_notify_socket(call->debug_id, serial);
rxrpc_notify_socket(call);
}
unlock:
spin_unlock(&call->input_lock);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
_leave(" [queued]");
}
@@ -822,8 +828,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
* soft-ACK means that the packet may be discarded and retransmission
* requested. A phase is complete when all packets are hard-ACK'd.
*/
-static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
- u16 skew)
+static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_ack_summary summary = { 0 };
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -867,11 +872,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
if (buf.ack.reason == RXRPC_ACK_PING) {
_proto("Rx ACK %%%u PING Request", sp->hdr.serial);
rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
- skew, sp->hdr.serial, true, true,
+ sp->hdr.serial, true, true,
rxrpc_propose_ack_respond_to_ping);
} else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
- skew, sp->hdr.serial, true, true,
+ sp->hdr.serial, true, true,
rxrpc_propose_ack_respond_to_ack);
}
@@ -948,7 +953,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
RXRPC_TX_ANNO_LAST &&
summary.nr_acks == call->tx_top - hard_ack &&
rxrpc_is_client_call(call))
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
false, true,
rxrpc_propose_ack_ping_for_lost_reply);
@@ -1004,7 +1009,7 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb)
* Process an incoming call packet.
*/
static void rxrpc_input_call_packet(struct rxrpc_call *call,
- struct sk_buff *skb, u16 skew)
+ struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
unsigned long timo;
@@ -1023,11 +1028,11 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
switch (sp->hdr.type) {
case RXRPC_PACKET_TYPE_DATA:
- rxrpc_input_data(call, skb, skew);
- break;
+ rxrpc_input_data(call, skb);
+ goto no_free;
case RXRPC_PACKET_TYPE_ACK:
- rxrpc_input_ack(call, skb, skew);
+ rxrpc_input_ack(call, skb);
break;
case RXRPC_PACKET_TYPE_BUSY:
@@ -1051,6 +1056,8 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
break;
}
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
+no_free:
_leave("");
}
@@ -1108,8 +1115,12 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
{
_enter("%p,%p", local, skb);
- skb_queue_tail(&local->event_queue, skb);
- rxrpc_queue_local(local);
+ if (rxrpc_get_local_maybe(local)) {
+ skb_queue_tail(&local->event_queue, skb);
+ rxrpc_queue_local(local);
+ } else {
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
+ }
}
/*
@@ -1119,8 +1130,12 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
{
CHECK_SLAB_OKAY(&local->usage);
- skb_queue_tail(&local->reject_queue, skb);
- rxrpc_queue_local(local);
+ if (rxrpc_get_local_maybe(local)) {
+ skb_queue_tail(&local->reject_queue, skb);
+ rxrpc_queue_local(local);
+ } else {
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
+ }
}
/*
@@ -1173,7 +1188,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
struct rxrpc_peer *peer = NULL;
struct rxrpc_sock *rx = NULL;
unsigned int channel;
- int skew = 0;
_enter("%p", udp_sk);
@@ -1184,7 +1198,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
if (skb->tstamp == 0)
skb->tstamp = ktime_get_real();
- rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+ rxrpc_new_skb(skb, rxrpc_skb_received);
skb_pull(skb, sizeof(struct udphdr));
@@ -1201,7 +1215,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
static int lose;
if ((lose++ & 7) == 7) {
trace_rxrpc_rx_lose(sp);
- rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
+ rxrpc_free_skb(skb, rxrpc_skb_lost);
return 0;
}
}
@@ -1233,9 +1247,26 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
if (sp->hdr.callNumber == 0 ||
sp->hdr.seq == 0)
goto bad_message;
- if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
- !rxrpc_validate_jumbo(skb))
+ if (!rxrpc_validate_data(skb))
goto bad_message;
+
+ /* Unshare the packet so that it can be modified for in-place
+ * decryption.
+ */
+ if (sp->hdr.securityIndex != 0) {
+ struct sk_buff *nskb = skb_unshare(skb, GFP_ATOMIC);
+ if (!nskb) {
+ rxrpc_eaten_skb(skb, rxrpc_skb_unshared_nomem);
+ goto out;
+ }
+
+ if (nskb != skb) {
+ rxrpc_eaten_skb(skb, rxrpc_skb_received);
+ skb = nskb;
+ rxrpc_new_skb(skb, rxrpc_skb_unshared);
+ sp = rxrpc_skb(skb);
+ }
+ }
break;
case RXRPC_PACKET_TYPE_CHALLENGE:
@@ -1301,15 +1332,8 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
goto out;
}
- /* Note the serial number skew here */
- skew = (int)sp->hdr.serial - (int)conn->hi_serial;
- if (skew >= 0) {
- if (skew > 0)
- conn->hi_serial = sp->hdr.serial;
- } else {
- skew = -skew;
- skew = min(skew, 65535);
- }
+ if ((int)sp->hdr.serial - (int)conn->hi_serial > 0)
+ conn->hi_serial = sp->hdr.serial;
/* Call-bound packets are routed by connection channel. */
channel = sp->hdr.cid & RXRPC_CHANNELMASK;
@@ -1372,15 +1396,18 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
call = rxrpc_new_incoming_call(local, rx, skb);
if (!call)
goto reject_packet;
- rxrpc_send_ping(call, skb, skew);
+ rxrpc_send_ping(call, skb);
mutex_unlock(&call->user_mutex);
}
- rxrpc_input_call_packet(call, skb, skew);
- goto discard;
+ /* Process a call packet; this either discards or passes on the ref
+ * elsewhere.
+ */
+ rxrpc_input_call_packet(call, skb);
+ goto out;
discard:
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
out:
trace_rxrpc_rx_done(0, 0);
return 0;
diff --git a/net/rxrpc/local_event.c b/net/rxrpc/local_event.c
index e93a78f7c05e..3ce6d628cd75 100644
--- a/net/rxrpc/local_event.c
+++ b/net/rxrpc/local_event.c
@@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
if (skb) {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
_debug("{%d},{%u}", local->debug_id, sp->hdr.type);
switch (sp->hdr.type) {
@@ -108,7 +108,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
break;
}
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
}
_leave("");
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index b1c71bad510b..36587260cabd 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -79,6 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
if (local) {
atomic_set(&local->usage, 1);
+ atomic_set(&local->active_users, 1);
local->rxnet = rxnet;
INIT_LIST_HEAD(&local->link);
INIT_WORK(&local->processor, rxrpc_local_processor);
@@ -92,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
local->debug_id = atomic_inc_return(&rxrpc_debug_id);
memcpy(&local->srx, srx, sizeof(*srx));
local->srx.srx_service = 0;
- trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
+ trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL);
}
_leave(" = %p", local);
@@ -266,11 +267,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
* bind the transport socket may still fail if we're attempting
* to use a local address that the dying object is still using.
*/
- if (!rxrpc_get_local_maybe(local)) {
- cursor = cursor->next;
- list_del_init(&local->link);
+ if (!rxrpc_use_local(local))
break;
- }
age = "old";
goto found;
@@ -284,7 +282,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
if (ret < 0)
goto sock_error;
- list_add_tail(&local->link, cursor);
+ if (cursor != &rxnet->local_endpoints)
+ list_replace_init(cursor, &local->link);
+ else
+ list_add_tail(&local->link, cursor);
age = "new";
found:
@@ -320,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
int n;
n = atomic_inc_return(&local->usage);
- trace_rxrpc_local(local, rxrpc_local_got, n, here);
+ trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here);
return local;
}
@@ -334,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
if (local) {
int n = atomic_fetch_add_unless(&local->usage, 1, 0);
if (n > 0)
- trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
+ trace_rxrpc_local(local->debug_id, rxrpc_local_got,
+ n + 1, here);
else
local = NULL;
}
@@ -342,24 +344,18 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
}
/*
- * Queue a local endpoint.
+ * Queue a local endpoint and pass the caller's reference to the work item.
*/
void rxrpc_queue_local(struct rxrpc_local *local)
{
const void *here = __builtin_return_address(0);
+ unsigned int debug_id = local->debug_id;
+ int n = atomic_read(&local->usage);
if (rxrpc_queue_work(&local->processor))
- trace_rxrpc_local(local, rxrpc_local_queued,
- atomic_read(&local->usage), here);
-}
-
-/*
- * A local endpoint reached its end of life.
- */
-static void __rxrpc_put_local(struct rxrpc_local *local)
-{
- _enter("%d", local->debug_id);
- rxrpc_queue_work(&local->processor);
+ trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here);
+ else
+ rxrpc_put_local(local);
}
/*
@@ -372,10 +368,47 @@ void rxrpc_put_local(struct rxrpc_local *local)
if (local) {
n = atomic_dec_return(&local->usage);
- trace_rxrpc_local(local, rxrpc_local_put, n, here);
+ trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here);
if (n == 0)
- __rxrpc_put_local(local);
+ call_rcu(&local->rcu, rxrpc_local_rcu);
+ }
+}
+
+/*
+ * Start using a local endpoint.
+ */
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
+{
+ unsigned int au;
+
+ local = rxrpc_get_local_maybe(local);
+ if (!local)
+ return NULL;
+
+ au = atomic_fetch_add_unless(&local->active_users, 1, 0);
+ if (au == 0) {
+ rxrpc_put_local(local);
+ return NULL;
+ }
+
+ return local;
+}
+
+/*
+ * Cease using a local endpoint. Once the number of active users reaches 0, we
+ * start the closure of the transport in the work processor.
+ */
+void rxrpc_unuse_local(struct rxrpc_local *local)
+{
+ unsigned int au;
+
+ if (local) {
+ au = atomic_dec_return(&local->active_users);
+ if (au == 0)
+ rxrpc_queue_local(local);
+ else
+ rxrpc_put_local(local);
}
}
@@ -393,21 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
_enter("%d", local->debug_id);
- /* We can get a race between an incoming call packet queueing the
- * processor again and the work processor starting the destruction
- * process which will shut down the UDP socket.
- */
- if (local->dead) {
- _leave(" [already dead]");
- return;
- }
local->dead = true;
mutex_lock(&rxnet->local_mutex);
list_del_init(&local->link);
mutex_unlock(&rxnet->local_mutex);
- ASSERT(RB_EMPTY_ROOT(&local->client_conns));
+ rxrpc_clean_up_local_conns(local);
+ rxrpc_service_connection_reaper(&rxnet->service_conn_reaper);
ASSERT(!local->service);
if (socket) {
@@ -422,13 +448,11 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
*/
rxrpc_purge_queue(&local->reject_queue);
rxrpc_purge_queue(&local->event_queue);
-
- _debug("rcu local %d", local->debug_id);
- call_rcu(&local->rcu, rxrpc_local_rcu);
}
/*
- * Process events on an endpoint
+ * Process events on an endpoint. The work item carries a ref which
+ * we must release.
*/
static void rxrpc_local_processor(struct work_struct *work)
{
@@ -436,13 +460,15 @@ static void rxrpc_local_processor(struct work_struct *work)
container_of(work, struct rxrpc_local, processor);
bool again;
- trace_rxrpc_local(local, rxrpc_local_processing,
+ trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
atomic_read(&local->usage), NULL);
do {
again = false;
- if (atomic_read(&local->usage) == 0)
- return rxrpc_local_destroyer(local);
+ if (atomic_read(&local->active_users) == 0) {
+ rxrpc_local_destroyer(local);
+ break;
+ }
if (!skb_queue_empty(&local->reject_queue)) {
rxrpc_reject_packets(local);
@@ -454,6 +480,8 @@ static void rxrpc_local_processor(struct work_struct *work)
again = true;
}
} while (again);
+
+ rxrpc_put_local(local);
}
/*
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 948e3fe249ec..935bb60fff56 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -87,7 +87,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
*_top = top;
pkt->ack.bufferSpace = htons(8);
- pkt->ack.maxSkew = htons(call->ackr_skew);
+ pkt->ack.maxSkew = htons(0);
pkt->ack.firstPacket = htonl(hard_ack + 1);
pkt->ack.previousPacket = htonl(call->ackr_prev_seq);
pkt->ack.serial = htonl(serial);
@@ -228,7 +228,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
if (ping)
clear_bit(RXRPC_CALL_PINGING, &call->flags);
rxrpc_propose_ACK(call, pkt->ack.reason,
- ntohs(pkt->ack.maxSkew),
ntohl(pkt->ack.serial),
false, true,
rxrpc_propose_ack_retry_tx);
@@ -566,7 +565,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
memset(&whdr, 0, sizeof(whdr));
while ((skb = skb_dequeue(&local->reject_queue))) {
- rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
sp = rxrpc_skb(skb);
switch (skb->mark) {
@@ -582,7 +581,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
ioc = 2;
break;
default:
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
continue;
}
@@ -607,7 +606,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
rxrpc_tx_point_reject);
}
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
}
_leave("");
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c
index 9f2f45c09e58..c97ebdc043e4 100644
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -163,11 +163,11 @@ void rxrpc_error_report(struct sock *sk)
_leave("UDP socket errqueue empty");
return;
}
- rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+ rxrpc_new_skb(skb, rxrpc_skb_received);
serr = SKB_EXT_ERR(skb);
if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
_leave("UDP empty message");
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
return;
}
@@ -177,7 +177,7 @@ void rxrpc_error_report(struct sock *sk)
peer = NULL;
if (!peer) {
rcu_read_unlock();
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
_leave(" [no peer]");
return;
}
@@ -189,7 +189,7 @@ void rxrpc_error_report(struct sock *sk)
serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
rxrpc_adjust_mtu(peer, serr);
rcu_read_unlock();
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
rxrpc_put_peer(peer);
_leave(" [MTU update]");
return;
@@ -197,7 +197,7 @@ void rxrpc_error_report(struct sock *sk)
rxrpc_store_error(peer, serr);
rcu_read_unlock();
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
rxrpc_put_peer(peer);
_leave("");
@@ -378,7 +378,7 @@ static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet,
spin_lock_bh(&rxnet->peer_hash_lock);
list_add_tail(&peer->keepalive_link,
&rxnet->peer_keepalive[slot & mask]);
- rxrpc_put_peer(peer);
+ rxrpc_put_peer_locked(peer);
}
spin_unlock_bh(&rxnet->peer_hash_lock);
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
index 9d3ce81cf8ae..9c3ac96f71cb 100644
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -437,6 +437,24 @@ void rxrpc_put_peer(struct rxrpc_peer *peer)
}
/*
+ * Drop a ref on a peer record where the caller already holds the
+ * peer_hash_lock.
+ */
+void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
+{
+ const void *here = __builtin_return_address(0);
+ int n;
+
+ n = atomic_dec_return(&peer->usage);
+ trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
+ if (n == 0) {
+ hash_del_rcu(&peer->hash_link);
+ list_del_init(&peer->keepalive_link);
+ kfree_rcu(peer, rcu);
+ }
+}
+
+/*
* Make sure all peer records have been discarded.
*/
void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet)
diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h
index 99ce322d7caa..49bb972539aa 100644
--- a/net/rxrpc/protocol.h
+++ b/net/rxrpc/protocol.h
@@ -89,6 +89,15 @@ struct rxrpc_jumbo_header {
#define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */
#define RXRPC_JUMBO_SUBPKTLEN (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header))
+/*
+ * The maximum number of subpackets that can possibly fit in a UDP packet is:
+ *
+ * ((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1
+ * = ((65535 - 28 - 28) / 1416) + 1
+ * = 46 non-terminal packets and 1 terminal packet.
+ */
+#define RXRPC_MAX_NR_JUMBO 47
+
/*****************************************************************************/
/*
* on-the-wire Rx ACK packet data payload
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 5abf46cf9e6c..3b0becb12041 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -141,7 +141,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
- rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true,
+ rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true,
rxrpc_propose_ack_terminal_ack);
//rxrpc_send_ack_packet(call, false, NULL);
}
@@ -159,7 +159,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
write_unlock_bh(&call->state_lock);
- rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true,
+ rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true,
rxrpc_propose_ack_processing_op);
break;
default:
@@ -177,7 +177,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
struct sk_buff *skb;
rxrpc_serial_t serial;
rxrpc_seq_t hard_ack, top;
- u8 flags;
+ bool last = false;
+ u8 subpacket;
int ix;
_enter("%d", call->debug_id);
@@ -189,30 +190,32 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
hard_ack++;
ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
skb = call->rxtx_buffer[ix];
- rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
+ rxrpc_see_skb(skb, rxrpc_skb_rotated);
sp = rxrpc_skb(skb);
- flags = sp->hdr.flags;
- serial = sp->hdr.serial;
- if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
- serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;
+
+ subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
+ serial = sp->hdr.serial + subpacket;
+
+ if (subpacket == sp->nr_subpackets - 1 &&
+ sp->rx_flags & RXRPC_SKB_INCL_LAST)
+ last = true;
call->rxtx_buffer[ix] = NULL;
call->rxtx_annotations[ix] = 0;
/* Barrier against rxrpc_input_data(). */
smp_store_release(&call->rx_hard_ack, hard_ack);
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
- _debug("%u,%u,%02x", hard_ack, top, flags);
trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
- if (flags & RXRPC_LAST_PACKET) {
+ if (last) {
rxrpc_end_rx_phase(call, serial);
} else {
/* Check to see if there's an ACK that needs sending. */
if (after_eq(hard_ack, call->ackr_consumed + 2) ||
after_eq(top, call->ackr_seen + 2) ||
(hard_ack == top && after(hard_ack, call->ackr_consumed)))
- rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
+ rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
true, true,
rxrpc_propose_ack_rotate_rx);
if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
@@ -233,18 +236,19 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
rxrpc_seq_t seq = sp->hdr.seq;
u16 cksum = sp->hdr.cksum;
+ u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
_enter("");
/* For all but the head jumbo subpacket, the security checksum is in a
* jumbo header immediately prior to the data.
*/
- if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
+ if (subpacket > 0) {
__be16 tmp;
if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
BUG();
cksum = ntohs(tmp);
- seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
+ seq += subpacket;
}
return call->conn->security->verify_packet(call, skb, offset, len,
@@ -265,19 +269,18 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
u8 *_annotation,
unsigned int *_offset, unsigned int *_len)
{
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
unsigned int offset = sizeof(struct rxrpc_wire_header);
unsigned int len;
int ret;
u8 annotation = *_annotation;
+ u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
/* Locate the subpacket */
+ offset += subpacket * RXRPC_JUMBO_SUBPKTLEN;
len = skb->len - offset;
- if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) {
- offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) *
- RXRPC_JUMBO_SUBPKTLEN);
- len = (annotation & RXRPC_RX_ANNO_JLAST) ?
- skb->len - offset : RXRPC_JUMBO_SUBPKTLEN;
- }
+ if (subpacket < sp->nr_subpackets - 1)
+ len = RXRPC_JUMBO_DATALEN;
if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
@@ -303,6 +306,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
{
struct rxrpc_skb_priv *sp;
struct sk_buff *skb;
+ rxrpc_serial_t serial;
rxrpc_seq_t hard_ack, top, seq;
size_t remain;
bool last;
@@ -336,12 +340,15 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
break;
}
smp_rmb();
- rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
sp = rxrpc_skb(skb);
- if (!(flags & MSG_PEEK))
+ if (!(flags & MSG_PEEK)) {
+ serial = sp->hdr.serial;
+ serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
trace_rxrpc_receive(call, rxrpc_receive_front,
- sp->hdr.serial, seq);
+ serial, seq);
+ }
if (msg)
sock_recv_timestamp(msg, sock->sk, skb);
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index ae8cd8926456..c60c520fde7c 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -187,10 +187,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
struct rxrpc_skb_priv *sp;
struct rxrpc_crypt iv;
struct scatterlist sg[16];
- struct sk_buff *trailer;
unsigned int len;
u16 check;
- int nsg;
int err;
sp = rxrpc_skb(skb);
@@ -214,15 +212,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
crypto_skcipher_encrypt(req);
/* we want to encrypt the skbuff in-place */
- nsg = skb_cow_data(skb, 0, &trailer);
- err = -ENOMEM;
- if (nsg < 0 || nsg > 16)
+ err = -EMSGSIZE;
+ if (skb_shinfo(skb)->nr_frags > 16)
goto out;
len = data_size + call->conn->size_align - 1;
len &= ~(call->conn->size_align - 1);
- sg_init_table(sg, nsg);
+ sg_init_table(sg, ARRAY_SIZE(sg));
err = skb_to_sgvec(skb, sg, 0, len);
if (unlikely(err < 0))
goto out;
@@ -319,11 +316,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
struct rxkad_level1_hdr sechdr;
struct rxrpc_crypt iv;
struct scatterlist sg[16];
- struct sk_buff *trailer;
bool aborted;
u32 data_size, buf;
u16 check;
- int nsg, ret;
+ int ret;
_enter("");
@@ -336,11 +332,7 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
* directly into the target buffer.
*/
- nsg = skb_cow_data(skb, 0, &trailer);
- if (nsg < 0 || nsg > 16)
- goto nomem;
-
- sg_init_table(sg, nsg);
+ sg_init_table(sg, ARRAY_SIZE(sg));
ret = skb_to_sgvec(skb, sg, offset, 8);
if (unlikely(ret < 0))
return ret;
@@ -388,10 +380,6 @@ protocol_error:
if (aborted)
rxrpc_send_abort_packet(call);
return -EPROTO;
-
-nomem:
- _leave(" = -ENOMEM");
- return -ENOMEM;
}
/*
@@ -406,7 +394,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
struct rxkad_level2_hdr sechdr;
struct rxrpc_crypt iv;
struct scatterlist _sg[4], *sg;
- struct sk_buff *trailer;
bool aborted;
u32 data_size, buf;
u16 check;
@@ -423,12 +410,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
* directly into the target buffer.
*/
- nsg = skb_cow_data(skb, 0, &trailer);
- if (nsg < 0)
- goto nomem;
-
sg = _sg;
- if (unlikely(nsg > 4)) {
+ nsg = skb_shinfo(skb)->nr_frags;
+ if (nsg <= 4) {
+ nsg = 4;
+ } else {
sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
if (!sg)
goto nomem;
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 5d3f33ce6d41..6a1547b270fe 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -176,7 +176,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
skb->tstamp = ktime_get_real();
ix = seq & RXRPC_RXTX_BUFF_MASK;
- rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+ rxrpc_get_skb(skb, rxrpc_skb_got);
call->rxtx_annotations[ix] = annotation;
smp_wmb();
call->rxtx_buffer[ix] = skb;
@@ -226,6 +226,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
rxrpc_set_call_completion(call,
RXRPC_CALL_LOCAL_ERROR,
0, ret);
+ rxrpc_notify_socket(call);
goto out;
}
_debug("need instant resend %d", ret);
@@ -247,7 +248,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
}
out:
- rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
_leave(" = %d", ret);
return ret;
}
@@ -288,7 +289,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
skb = call->tx_pending;
call->tx_pending = NULL;
- rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+ rxrpc_see_skb(skb, rxrpc_skb_seen);
copied = 0;
do {
@@ -335,7 +336,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
if (!skb)
goto maybe_error;
- rxrpc_new_skb(skb, rxrpc_skb_tx_new);
+ sp = rxrpc_skb(skb);
+ sp->rx_flags |= RXRPC_SKB_TX_BUFFER;
+ rxrpc_new_skb(skb, rxrpc_skb_new);
_debug("ALLOC SEND %p", skb);
@@ -345,7 +348,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
skb_reserve(skb, call->conn->security_size);
skb->len += call->conn->security_size;
- sp = rxrpc_skb(skb);
sp->remain = chunk;
if (sp->remain > skb_tailroom(skb))
sp->remain = skb_tailroom(skb);
@@ -438,7 +440,7 @@ out:
return ret;
call_terminated:
- rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
_leave(" = %d", call->error);
return call->error;
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 9ad5045b7c2f..0348d2bf6f7d 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -14,7 +14,8 @@
#include <net/af_rxrpc.h>
#include "ar-internal.h"
-#define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
+#define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER)
+#define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
/*
* Note the allocation or reception of a socket buffer.
@@ -22,8 +23,9 @@
void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
- int n = atomic_inc_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+ int n = atomic_inc_return(select_skb_count(skb));
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+ rxrpc_skb(skb)->rx_flags, here);
}
/*
@@ -33,8 +35,9 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
if (skb) {
- int n = atomic_read(select_skb_count(op));
- trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+ int n = atomic_read(select_skb_count(skb));
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+ rxrpc_skb(skb)->rx_flags, here);
}
}
@@ -44,12 +47,23 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
- int n = atomic_inc_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+ int n = atomic_inc_return(select_skb_count(skb));
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+ rxrpc_skb(skb)->rx_flags, here);
skb_get(skb);
}
/*
+ * Note the dropping of a ref on a socket buffer by the core.
+ */
+void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
+{
+ const void *here = __builtin_return_address(0);
+ int n = atomic_inc_return(&rxrpc_n_rx_skbs);
+ trace_rxrpc_skb(skb, op, 0, n, 0, here);
+}
+
+/*
* Note the destruction of a socket buffer.
*/
void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
@@ -58,8 +72,9 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
if (skb) {
int n;
CHECK_SLAB_OKAY(&skb->users);
- n = atomic_dec_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+ n = atomic_dec_return(select_skb_count(skb));
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+ rxrpc_skb(skb)->rx_flags, here);
kfree_skb(skb);
}
}
@@ -72,9 +87,10 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
const void *here = __builtin_return_address(0);
struct sk_buff *skb;
while ((skb = skb_dequeue((list))) != NULL) {
- int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
- trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
- refcount_read(&skb->users), n, here);
+ int n = atomic_dec_return(select_skb_count(skb));
+ trace_rxrpc_skb(skb, rxrpc_skb_purged,
+ refcount_read(&skb->users), n,
+ rxrpc_skb(skb)->rx_flags, here);
kfree_skb(skb);
}
}
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 8126b26f125e..04b7bd4ec751 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct tcf_bpf *prog;
bool is_bpf, is_ebpf;
int ret, res = 0;
+ u32 index;
if (!nla)
return -EINVAL;
@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
-
- ret = tcf_idr_check_alloc(tn, &parm->index, act, bind);
+ index = parm->index;
+ ret = tcf_idr_check_alloc(tn, &index, act, bind);
if (!ret) {
- ret = tcf_idr_create(tn, parm->index, est, act,
+ ret = tcf_idr_create(tn, index, est, act,
&act_bpf_ops, bind, true);
if (ret < 0) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -421,7 +422,7 @@ static __net_init int bpf_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
- return tc_action_net_init(tn, &act_bpf_ops);
+ return tc_action_net_init(net, tn, &act_bpf_ops);
}
static void __net_exit bpf_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index ce36b0f7e1dc..2b43cacf82af 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
struct tcf_connmark_info *ci;
struct tc_connmark *parm;
int ret = 0, err;
+ u32 index;
if (!nla)
return -EINVAL;
@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_CONNMARK_PARMS]);
-
- ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ ret = tcf_idr_check_alloc(tn, &index, a, bind);
if (!ret) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_connmark_ops, bind, false);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -230,7 +231,7 @@ static __net_init int connmark_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
- return tc_action_net_init(tn, &act_connmark_ops);
+ return tc_action_net_init(net, tn, &act_connmark_ops);
}
static void __net_exit connmark_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 621fb22ce2a9..d3cfad88dc3a 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
struct tc_csum *parm;
struct tcf_csum *p;
int ret = 0, err;
+ u32 index;
if (nla == NULL)
return -EINVAL;
@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
if (tb[TCA_CSUM_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_CSUM_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_csum_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -713,7 +714,7 @@ static __net_init int csum_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
- return tc_action_net_init(tn, &act_csum_ops);
+ return tc_action_net_init(net, tn, &act_csum_ops);
}
static void __net_exit csum_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index b501ce0cf116..cdd6f3818097 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
struct tc_ct *parm;
struct tcf_ct *c;
int err, res = 0;
+ u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed");
@@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
parm = nla_data(tb[TCA_CT_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
if (!err) {
- err = tcf_idr_create(tn, parm->index, est, a,
+ err = tcf_idr_create(tn, index, est, a,
&act_ct_ops, bind, true);
if (err) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return err;
}
res = ACT_P_CREATED;
@@ -938,7 +939,7 @@ static __net_init int ct_init_net(struct net *net)
tn->labels = true;
}
- return tc_action_net_init(&tn->tn, &act_ct_ops);
+ return tc_action_net_init(net, &tn->tn, &act_ct_ops);
}
static void __net_exit ct_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_ctinfo.c b/net/sched/act_ctinfo.c
index 10eb2bb99861..0dbcfd1dca7b 100644
--- a/net/sched/act_ctinfo.c
+++ b/net/sched/act_ctinfo.c
@@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
struct netlink_ext_ack *extack)
{
struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
+ u32 dscpmask = 0, dscpstatemask, index;
struct nlattr *tb[TCA_CTINFO_MAX + 1];
struct tcf_ctinfo_params *cp_new;
struct tcf_chain *goto_ch = NULL;
- u32 dscpmask = 0, dscpstatemask;
struct tc_ctinfo *actparm;
struct tcf_ctinfo *ci;
u8 dscpmaskshift;
@@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
}
/* done the validation:now to the actual action allocation */
- err = tcf_idr_check_alloc(tn, &actparm->index, a, bind);
+ index = actparm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) {
- ret = tcf_idr_create(tn, actparm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_ctinfo_ops, bind, false);
if (ret) {
- tcf_idr_cleanup(tn, actparm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -375,7 +376,7 @@ static __net_init int ctinfo_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
- return tc_action_net_init(tn, &act_ctinfo_ops);
+ return tc_action_net_init(net, tn, &act_ctinfo_ops);
}
static void __net_exit ctinfo_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index b2380c5284e6..324f1d1f6d47 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
struct tc_gact *parm;
struct tcf_gact *gact;
int ret = 0;
+ u32 index;
int err;
#ifdef CONFIG_GACT_PROB
struct tc_gact_p *p_parm = NULL;
@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
if (tb[TCA_GACT_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_GACT_PARMS]);
+ index = parm->index;
#ifndef CONFIG_GACT_PROB
if (tb[TCA_GACT_PROB] != NULL)
@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
}
#endif
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_gact_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -276,7 +278,7 @@ static __net_init int gact_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
- return tc_action_net_init(tn, &act_gact_ops);
+ return tc_action_net_init(net, tn, &act_gact_ops);
}
static void __net_exit gact_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 41d5398dd2f2..3a31e241c647 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -479,8 +479,14 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
u8 *saddr = NULL;
bool exists = false;
int ret = 0;
+ u32 index;
int err;
+ if (!nla) {
+ NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed");
+ return -EINVAL;
+ }
+
err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy,
NULL);
if (err < 0)
@@ -502,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
if (!p)
return -ENOMEM;
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) {
kfree(p);
return err;
@@ -514,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
}
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
+ ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
kfree(p);
return ret;
}
@@ -883,7 +890,7 @@ static __net_init int ife_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ife_net_id);
- return tc_action_net_init(tn, &act_ife_ops);
+ return tc_action_net_init(net, tn, &act_ife_ops);
}
static void __net_exit ife_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index ce2c30a591d2..214a03d405cf 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -61,12 +61,13 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
return 0;
}
-static void ipt_destroy_target(struct xt_entry_target *t)
+static void ipt_destroy_target(struct xt_entry_target *t, struct net *net)
{
struct xt_tgdtor_param par = {
.target = t->u.kernel.target,
.targinfo = t->data,
.family = NFPROTO_IPV4,
+ .net = net,
};
if (par.target->destroy != NULL)
par.target->destroy(&par);
@@ -78,7 +79,7 @@ static void tcf_ipt_release(struct tc_action *a)
struct tcf_ipt *ipt = to_ipt(a);
if (ipt->tcfi_t) {
- ipt_destroy_target(ipt->tcfi_t);
+ ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net);
kfree(ipt->tcfi_t);
}
kfree(ipt->tcfi_tname);
@@ -180,7 +181,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
spin_lock_bh(&ipt->tcf_lock);
if (ret != ACT_P_CREATED) {
- ipt_destroy_target(ipt->tcfi_t);
+ ipt_destroy_target(ipt->tcfi_t, net);
kfree(ipt->tcfi_tname);
kfree(ipt->tcfi_t);
}
@@ -350,7 +351,7 @@ static __net_init int ipt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
- return tc_action_net_init(tn, &act_ipt_ops);
+ return tc_action_net_init(net, tn, &act_ipt_ops);
}
static void __net_exit ipt_exit_net(struct list_head *net_list)
@@ -399,7 +400,7 @@ static __net_init int xt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
- return tc_action_net_init(tn, &act_xt_ops);
+ return tc_action_net_init(net, tn, &act_xt_ops);
}
static void __net_exit xt_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 055faa298c8e..9d1bf508075a 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct net_device *dev;
bool exists = false;
int ret, err;
+ u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
@@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
parm = nla_data(tb[TCA_MIRRED_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL;
}
if (!exists) {
if (!parm->ifindex) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
return -EINVAL;
}
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_mirred_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -452,7 +453,7 @@ static __net_init int mirred_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
- return tc_action_net_init(tn, &act_mirred_ops);
+ return tc_action_net_init(net, tn, &act_mirred_ops);
}
static void __net_exit mirred_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
index ca2597ce4ac9..e168df0e008a 100644
--- a/net/sched/act_mpls.c
+++ b/net/sched/act_mpls.c
@@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
struct tcf_mpls *m;
int ret = 0, err;
u8 mpls_ttl = 0;
+ u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
@@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
parm = nla_data(tb[TCA_MPLS_PARMS]);
+ index = parm->index;
/* Verify parameters against action type. */
switch (parm->m_action) {
@@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return 0;
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_mpls_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -373,7 +375,7 @@ static __net_init int mpls_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mpls_net_id);
- return tc_action_net_init(tn, &act_mpls_ops);
+ return tc_action_net_init(net, tn, &act_mpls_ops);
}
static void __net_exit mpls_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 45923ebb7a4f..ea4c5359e7df 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
struct tc_nat *parm;
int ret = 0, err;
struct tcf_nat *p;
+ u32 index;
if (nla == NULL)
return -EINVAL;
@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
if (tb[TCA_NAT_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_NAT_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_nat_ops, bind, false);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -326,7 +327,7 @@ static __net_init int nat_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
- return tc_action_net_init(tn, &act_nat_ops);
+ return tc_action_net_init(net, tn, &act_nat_ops);
}
static void __net_exit nat_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 45e9d6bfddb3..cdfaa79382a2 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
struct tcf_pedit *p;
int ret = 0, err;
int ksize;
+ u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed");
@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
if (IS_ERR(keys_ex))
return PTR_ERR(keys_ex);
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) {
if (!parm->nkeys) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
ret = -EINVAL;
goto out_free;
}
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_pedit_ops, bind, false);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
goto out_free;
}
ret = ACT_P_CREATED;
@@ -496,7 +498,7 @@ static __net_init int pedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
- return tc_action_net_init(tn, &act_pedit_ops);
+ return tc_action_net_init(net, tn, &act_pedit_ops);
}
static void __net_exit pedit_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index a065f62fa79c..6315e0f8d26e 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
struct tc_action_net *tn = net_generic(net, police_net_id);
struct tcf_police_params *new;
bool exists = false;
+ u32 index;
if (nla == NULL)
return -EINVAL;
@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_POLICE_TBF]);
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
return 0;
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, NULL, a,
+ ret = tcf_idr_create(tn, index, NULL, a,
&act_police_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -369,7 +371,7 @@ static __net_init int police_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
- return tc_action_net_init(tn, &act_police_ops);
+ return tc_action_net_init(net, tn, &act_police_ops);
}
static void __net_exit police_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index 274d7a0c0e25..10229124a992 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
struct tc_action_net *tn = net_generic(net, sample_net_id);
struct nlattr *tb[TCA_SAMPLE_MAX + 1];
struct psample_group *psample_group;
+ u32 psample_group_num, rate, index;
struct tcf_chain *goto_ch = NULL;
- u32 psample_group_num, rate;
struct tc_sample *parm;
struct tcf_sample *s;
bool exists = false;
@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_SAMPLE_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
return 0;
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_sample_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
ret = ACT_P_CREATED;
@@ -102,13 +102,17 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
s->rate = rate;
s->psample_group_num = psample_group_num;
- RCU_INIT_POINTER(s->psample_group, psample_group);
+ rcu_swap_protected(s->psample_group, psample_group,
+ lockdep_is_held(&s->tcf_lock));
if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
s->truncate = true;
s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
}
spin_unlock_bh(&s->tcf_lock);
+
+ if (psample_group)
+ psample_group_put(psample_group);
if (goto_ch)
tcf_chain_put_by_act(goto_ch);
@@ -265,7 +269,7 @@ static __net_init int sample_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
- return tc_action_net_init(tn, &act_sample_ops);
+ return tc_action_net_init(net, tn, &act_sample_ops);
}
static void __net_exit sample_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index f28ddbabff76..6120e56117ca 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct tcf_defact *d;
bool exists = false;
int ret = 0, err;
+ u32 index;
if (nla == NULL)
return -EINVAL;
@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]);
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EINVAL;
}
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_simp_ops, bind, false);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -230,7 +232,7 @@ static __net_init int simp_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
- return tc_action_net_init(tn, &act_simp_ops);
+ return tc_action_net_init(net, tn, &act_simp_ops);
}
static void __net_exit simp_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 215a06705cef..6a8d3337c577 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false;
int ret = 0, err;
+ u32 index;
if (nla == NULL)
return -EINVAL;
@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
}
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
-
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EINVAL;
}
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_skbedit_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -306,6 +307,17 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
return tcf_idr_search(tn, a, index);
}
+static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
+{
+ return nla_total_size(sizeof(struct tc_skbedit))
+ + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */
+ + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */
+ + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */
+ + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */
+ + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */
+ + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */
+}
+
static struct tc_action_ops act_skbedit_ops = {
.kind = "skbedit",
.id = TCA_ID_SKBEDIT,
@@ -315,6 +327,7 @@ static struct tc_action_ops act_skbedit_ops = {
.init = tcf_skbedit_init,
.cleanup = tcf_skbedit_cleanup,
.walk = tcf_skbedit_walker,
+ .get_fill_size = tcf_skbedit_get_fill_size,
.lookup = tcf_skbedit_search,
.size = sizeof(struct tcf_skbedit),
};
@@ -323,7 +336,7 @@ static __net_init int skbedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
- return tc_action_net_init(tn, &act_skbedit_ops);
+ return tc_action_net_init(net, tn, &act_skbedit_ops);
}
static void __net_exit skbedit_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index 4f07706eff07..888437f97ba6 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
struct tcf_skbmod_params *p, *p_old;
struct tcf_chain *goto_ch = NULL;
struct tc_skbmod *parm;
+ u32 lflags = 0, index;
struct tcf_skbmod *d;
bool exists = false;
u8 *daddr = NULL;
u8 *saddr = NULL;
u16 eth_type = 0;
- u32 lflags = 0;
int ret = 0, err;
if (!nla)
@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
}
parm = nla_data(tb[TCA_SKBMOD_PARMS]);
+ index = parm->index;
if (parm->flags & SKBMOD_F_SWAPMAC)
lflags = SKBMOD_F_SWAPMAC;
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EINVAL;
}
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_skbmod_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -286,7 +287,7 @@ static __net_init int skbmod_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
- return tc_action_net_init(tn, &act_skbmod_ops);
+ return tc_action_net_init(net, tn, &act_skbmod_ops);
}
static void __net_exit skbmod_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 10dffda1d5cc..2f83a79f76aa 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
__be16 flags = 0;
u8 tos, ttl;
int ret = 0;
+ u32 index;
int err;
if (!nla) {
@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
}
parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
}
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_tunnel_key_ops, bind, true);
if (ret) {
NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
@@ -403,7 +405,7 @@ err_out:
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -598,7 +600,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
- return tc_action_net_init(tn, &act_tunnel_key_ops);
+ return tc_action_net_init(net, tn, &act_tunnel_key_ops);
}
static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 9269d350fb8a..287a30bf8930 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
u8 push_prio = 0;
bool exists = false;
int ret = 0, err;
+ u32 index;
if (!nla)
return -EINVAL;
@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (!tb[TCA_VLAN_PARMS])
return -EINVAL;
parm = nla_data(tb[TCA_VLAN_PARMS]);
- err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0)
return err;
exists = err;
@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EINVAL;
}
push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -ERANGE;
}
@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EPROTONOSUPPORT;
}
} else {
@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists)
tcf_idr_release(*a, bind);
else
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return -EINVAL;
}
action = parm->v_action;
if (!exists) {
- ret = tcf_idr_create(tn, parm->index, est, a,
+ ret = tcf_idr_create(tn, index, est, a,
&act_vlan_ops, bind, true);
if (ret) {
- tcf_idr_cleanup(tn, parm->index);
+ tcf_idr_cleanup(tn, index);
return ret;
}
@@ -306,6 +308,14 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
return tcf_idr_search(tn, a, index);
}
+static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
+{
+ return nla_total_size(sizeof(struct tc_vlan))
+ + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */
+ + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */
+ + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */
+}
+
static struct tc_action_ops act_vlan_ops = {
.kind = "vlan",
.id = TCA_ID_VLAN,
@@ -315,6 +325,7 @@ static struct tc_action_ops act_vlan_ops = {
.init = tcf_vlan_init,
.cleanup = tcf_vlan_cleanup,
.walk = tcf_vlan_walker,
+ .get_fill_size = tcf_vlan_get_fill_size,
.lookup = tcf_vlan_search,
.size = sizeof(struct tcf_vlan),
};
@@ -323,7 +334,7 @@ static __net_init int vlan_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
- return tc_action_net_init(tn, &act_vlan_ops);
+ return tc_action_net_init(net, tn, &act_vlan_ops);
}
static void __net_exit vlan_exit_net(struct list_head *net_list)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 04faee7ccbce..1047825d9f48 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1920,6 +1920,8 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,
cl = cops->find(q, portid);
if (!cl)
return;
+ if (!cops->tcf_block)
+ return;
block = cops->tcf_block(q, cl, NULL);
if (!block)
return;
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index 732e109c3055..810645b5c086 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -181,11 +181,6 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
s64 credits;
int len;
- if (atomic64_read(&q->port_rate) == -1) {
- WARN_ONCE(1, "cbs: dequeue() called with unknown port rate.");
- return NULL;
- }
-
if (q->credits < 0) {
credits = timediff_to_credits(now - q->last, q->idleslope);
@@ -303,11 +298,19 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
{
struct ethtool_link_ksettings ecmd;
+ int speed = SPEED_10;
int port_rate = -1;
+ int err;
+
+ err = __ethtool_get_link_ksettings(dev, &ecmd);
+ if (err < 0)
+ goto skip;
+
+ if (ecmd.base.speed != SPEED_UNKNOWN)
+ speed = ecmd.base.speed;
- if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
- ecmd.base.speed != SPEED_UNKNOWN)
- port_rate = ecmd.base.speed * 1000 * BYTES_PER_KBIT;
+skip:
+ port_rate = speed * 1000 * BYTES_PER_KBIT;
atomic64_set(&q->port_rate, port_rate);
netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index 25ef172c23df..30169b3adbbb 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -71,10 +71,10 @@ static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx)
struct Qdisc *sch = ctx;
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
- if (skb)
+ if (skb) {
sch->qstats.backlog -= qdisc_pkt_len(skb);
-
- prefetch(&skb->end); /* we'll need skb_shinfo() */
+ prefetch(&skb->end); /* we'll need skb_shinfo() */
+ }
return skb;
}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 11c03cf4aa74..ac28f6a5d70e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -46,6 +46,8 @@ EXPORT_SYMBOL(default_qdisc_ops);
* - updates to tree and tree walking are only done under the rtnl mutex.
*/
+#define SKB_XOFF_MAGIC ((struct sk_buff *)1UL)
+
static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q)
{
const struct netdev_queue *txq = q->dev_queue;
@@ -71,7 +73,7 @@ static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q)
q->q.qlen--;
}
} else {
- skb = NULL;
+ skb = SKB_XOFF_MAGIC;
}
}
@@ -253,8 +255,11 @@ validate:
return skb;
skb = qdisc_dequeue_skb_bad_txq(q);
- if (unlikely(skb))
+ if (unlikely(skb)) {
+ if (skb == SKB_XOFF_MAGIC)
+ return NULL;
goto bulk;
+ }
skb = q->dequeue(q);
if (skb) {
bulk:
@@ -624,8 +629,12 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
err = skb_array_produce(q, skb);
- if (unlikely(err))
- return qdisc_drop_cpu(skb, qdisc, to_free);
+ if (unlikely(err)) {
+ if (qdisc_is_percpu_stats(qdisc))
+ return qdisc_drop_cpu(skb, qdisc, to_free);
+ else
+ return qdisc_drop(skb, qdisc, to_free);
+ }
qdisc_update_stats_at_enqueue(qdisc, pkt_len);
return NET_XMIT_SUCCESS;
@@ -688,11 +697,14 @@ static void pfifo_fast_reset(struct Qdisc *qdisc)
kfree_skb(skb);
}
- for_each_possible_cpu(i) {
- struct gnet_stats_queue *q = per_cpu_ptr(qdisc->cpu_qstats, i);
+ if (qdisc_is_percpu_stats(qdisc)) {
+ for_each_possible_cpu(i) {
+ struct gnet_stats_queue *q;
- q->backlog = 0;
- q->qlen = 0;
+ q = per_cpu_ptr(qdisc->cpu_qstats, i);
+ q->backlog = 0;
+ q->qlen = 0;
+ }
}
}
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index cee6971c1c82..23cd1c873a2c 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -531,7 +531,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
new_hhf_non_hh_weight = nla_get_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
non_hh_quantum = (u64)new_quantum * new_hhf_non_hh_weight;
- if (non_hh_quantum > INT_MAX)
+ if (non_hh_quantum == 0 || non_hh_quantum > INT_MAX)
return -EINVAL;
sch_tree_lock(sch);
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index c39db507ba3f..8d8bc2ec5cd6 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -477,11 +477,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
u32 gate_mask;
int i;
- if (atomic64_read(&q->picos_per_byte) == -1) {
- WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte.");
- return NULL;
- }
-
rcu_read_lock();
entry = rcu_dereference(q->current_entry);
/* if there's no entry, it means that the schedule didn't
@@ -958,12 +953,20 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
struct taprio_sched *q)
{
struct ethtool_link_ksettings ecmd;
- int picos_per_byte = -1;
+ int speed = SPEED_10;
+ int picos_per_byte;
+ int err;
- if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
- ecmd.base.speed != SPEED_UNKNOWN)
- picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
- ecmd.base.speed * 1000 * 1000);
+ err = __ethtool_get_link_ksettings(dev, &ecmd);
+ if (err < 0)
+ goto skip;
+
+ if (ecmd.base.speed != SPEED_UNKNOWN)
+ speed = ecmd.base.speed;
+
+skip:
+ picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
+ speed * 1000 * 1000);
atomic64_set(&q->picos_per_byte, picos_per_byte);
netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
@@ -1195,7 +1198,8 @@ unlock:
spin_unlock_bh(qdisc_lock(sch));
free_sched:
- kfree(new_admin);
+ if (new_admin)
+ call_rcu(&new_admin->rcu, taprio_free_sched_cb);
return err;
}
@@ -1248,6 +1252,10 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
*/
q->clockid = -1;
+ spin_lock(&taprio_list_lock);
+ list_add(&q->taprio_list, &taprio_list);
+ spin_unlock(&taprio_list_lock);
+
if (sch->parent != TC_H_ROOT)
return -EOPNOTSUPP;
@@ -1265,10 +1273,6 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
if (!opt)
return -EINVAL;
- spin_lock(&taprio_list_lock);
- list_add(&q->taprio_list, &taprio_list);
- spin_unlock(&taprio_list_lock);
-
for (i = 0; i < dev->num_tx_queues; i++) {
struct netdev_queue *dev_queue;
struct Qdisc *qdisc;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2d47adcb4cbe..53746ffeeca3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1336,7 +1336,7 @@ static int __net_init sctp_ctrlsock_init(struct net *net)
return status;
}
-static void __net_init sctp_ctrlsock_exit(struct net *net)
+static void __net_exit sctp_ctrlsock_exit(struct net *net)
{
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index a554d6d15d1b..e52b2128e43b 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -546,8 +546,8 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
*/
if (net->sctp.pf_enable &&
(transport->state == SCTP_ACTIVE) &&
- (asoc->pf_retrans < transport->pathmaxrxt) &&
- (transport->error_count > asoc->pf_retrans)) {
+ (transport->error_count < transport->pathmaxrxt) &&
+ (transport->error_count > transport->pf_retrans)) {
sctp_assoc_control_transport(asoc, transport,
SCTP_TRANSPORT_PF,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index aa80cda36581..b083d4e66230 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -309,7 +309,7 @@ static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
return retval;
}
-static long sctp_get_port_local(struct sock *, union sctp_addr *);
+static int sctp_get_port_local(struct sock *, union sctp_addr *);
/* Verify this is a valid sockaddr. */
static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
@@ -399,9 +399,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
* detection.
*/
addr->v4.sin_port = htons(snum);
- if ((ret = sctp_get_port_local(sk, addr))) {
+ if (sctp_get_port_local(sk, addr))
return -EADDRINUSE;
- }
/* Refresh ephemeral port. */
if (!bp->port)
@@ -413,11 +412,13 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
SCTP_ADDR_SRC, GFP_ATOMIC);
- /* Copy back into socket for getsockname() use. */
- if (!ret) {
- inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
- sp->pf->to_sk_saddr(addr, sk);
+ if (ret) {
+ sctp_put_port(sk);
+ return ret;
}
+ /* Copy back into socket for getsockname() use. */
+ inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
+ sp->pf->to_sk_saddr(addr, sk);
return ret;
}
@@ -985,7 +986,7 @@ static int sctp_setsockopt_bindx(struct sock *sk,
return -EINVAL;
kaddrs = memdup_user(addrs, addrs_size);
- if (unlikely(IS_ERR(kaddrs)))
+ if (IS_ERR(kaddrs))
return PTR_ERR(kaddrs);
/* Walk through the addrs buffer and count the number of addresses. */
@@ -1315,7 +1316,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
return -EINVAL;
kaddrs = memdup_user(addrs, addrs_size);
- if (unlikely(IS_ERR(kaddrs)))
+ if (IS_ERR(kaddrs))
return PTR_ERR(kaddrs);
/* Allow security module to validate connectx addresses. */
@@ -7173,7 +7174,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
val.spt_pathmaxrxt = trans->pathmaxrxt;
val.spt_pathpfthld = trans->pf_retrans;
- return 0;
+ goto out;
}
asoc = sctp_id2assoc(sk, val.spt_assoc_id);
@@ -7191,6 +7192,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
val.spt_pathmaxrxt = sp->pathmaxrxt;
}
+out:
if (put_user(len, optlen) || copy_to_user(optval, &val, len))
return -EFAULT;
@@ -7998,7 +8000,7 @@ static void sctp_unhash(struct sock *sk)
static struct sctp_bind_bucket *sctp_bucket_create(
struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
-static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
+static int sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{
struct sctp_sock *sp = sctp_sk(sk);
bool reuse = (sk->sk_reuse || sp->reuse);
@@ -8108,7 +8110,7 @@ pp_found:
if (sctp_bind_addr_conflict(&ep2->base.bind_addr,
addr, sp2, sp)) {
- ret = (long)sk2;
+ ret = 1;
goto fail_unlock;
}
}
@@ -8180,7 +8182,7 @@ static int sctp_get_port(struct sock *sk, unsigned short snum)
addr.v4.sin_port = htons(snum);
/* Note: sk->sk_num gets filled in if ephemeral port request. */
- return !!sctp_get_port_local(sk, &addr);
+ return sctp_get_port_local(sk, &addr);
}
/*
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 25946604af85..e83cdaa2ab76 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -316,6 +316,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
nstr_list[i] = htons(str_list[i]);
if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) {
+ kfree(nstr_list);
retval = -EAGAIN;
goto out;
}
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 302e355f2ebc..5b932583e407 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -263,7 +263,7 @@ static int smc_bind(struct socket *sock, struct sockaddr *uaddr,
/* Check if socket is already active */
rc = -EINVAL;
- if (sk->sk_state != SMC_INIT)
+ if (sk->sk_state != SMC_INIT || smc->connect_nonblock)
goto out_rel;
smc->clcsock->sk->sk_reuse = sk->sk_reuse;
@@ -1390,7 +1390,8 @@ static int smc_listen(struct socket *sock, int backlog)
lock_sock(sk);
rc = -EINVAL;
- if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN))
+ if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) ||
+ smc->connect_nonblock)
goto out;
rc = 0;
@@ -1518,7 +1519,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
goto out;
if (msg->msg_flags & MSG_FASTOPEN) {
- if (sk->sk_state == SMC_INIT) {
+ if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
smc_switch_to_fallback(smc);
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
} else {
@@ -1732,14 +1733,18 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
}
break;
case TCP_NODELAY:
- if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+ if (sk->sk_state != SMC_INIT &&
+ sk->sk_state != SMC_LISTEN &&
+ sk->sk_state != SMC_CLOSED) {
if (val && !smc->use_fallback)
mod_delayed_work(system_wq, &smc->conn.tx_work,
0);
}
break;
case TCP_CORK:
- if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+ if (sk->sk_state != SMC_INIT &&
+ sk->sk_state != SMC_LISTEN &&
+ sk->sk_state != SMC_CLOSED) {
if (!val && !smc->use_fallback)
mod_delayed_work(system_wq, &smc->conn.tx_work,
0);
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c
index f0de323d15d6..6c8f09c1ce51 100644
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -76,13 +76,11 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct smc_connection *conn = &smc->conn;
struct sock *sk = &smc->sk;
- bool noblock;
long timeo;
int rc = 0;
/* similar to sk_stream_wait_memory */
timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
- noblock = timeo ? false : true;
add_wait_queue(sk_sleep(sk), &wait);
while (1) {
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
@@ -97,8 +95,8 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
break;
}
if (!timeo) {
- if (noblock)
- set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ /* ensure EPOLLOUT is subsequently generated */
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
rc = -EAGAIN;
break;
}
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d8679b6027e9..a07b516e503a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1970,6 +1970,7 @@ call_bind(struct rpc_task *task)
static void
call_bind_status(struct rpc_task *task)
{
+ struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
int status = -EIO;
if (rpc_task_transmitted(task)) {
@@ -1977,14 +1978,15 @@ call_bind_status(struct rpc_task *task)
return;
}
- if (task->tk_status >= 0) {
- dprint_status(task);
+ dprint_status(task);
+ trace_rpc_bind_status(task);
+ if (task->tk_status >= 0)
+ goto out_next;
+ if (xprt_bound(xprt)) {
task->tk_status = 0;
- task->tk_action = call_connect;
- return;
+ goto out_next;
}
- trace_rpc_bind_status(task);
switch (task->tk_status) {
case -ENOMEM:
dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid);
@@ -2003,6 +2005,9 @@ call_bind_status(struct rpc_task *task)
task->tk_rebind_retry--;
rpc_delay(task, 3*HZ);
goto retry_timeout;
+ case -ENOBUFS:
+ rpc_delay(task, HZ >> 2);
+ goto retry_timeout;
case -EAGAIN:
goto retry_timeout;
case -ETIMEDOUT:
@@ -2026,7 +2031,6 @@ call_bind_status(struct rpc_task *task)
case -ENETDOWN:
case -EHOSTUNREACH:
case -ENETUNREACH:
- case -ENOBUFS:
case -EPIPE:
dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
task->tk_pid, task->tk_status);
@@ -2043,7 +2047,9 @@ call_bind_status(struct rpc_task *task)
rpc_call_rpcerror(task, status);
return;
-
+out_next:
+ task->tk_action = call_connect;
+ return;
retry_timeout:
task->tk_status = 0;
task->tk_action = call_bind;
@@ -2090,6 +2096,7 @@ call_connect(struct rpc_task *task)
static void
call_connect_status(struct rpc_task *task)
{
+ struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
struct rpc_clnt *clnt = task->tk_client;
int status = task->tk_status;
@@ -2099,8 +2106,17 @@ call_connect_status(struct rpc_task *task)
}
dprint_status(task);
-
trace_rpc_connect_status(task);
+
+ if (task->tk_status == 0) {
+ clnt->cl_stats->netreconn++;
+ goto out_next;
+ }
+ if (xprt_connected(xprt)) {
+ task->tk_status = 0;
+ goto out_next;
+ }
+
task->tk_status = 0;
switch (status) {
case -ECONNREFUSED:
@@ -2117,8 +2133,6 @@ call_connect_status(struct rpc_task *task)
case -ENETDOWN:
case -ENETUNREACH:
case -EHOSTUNREACH:
- case -EADDRINUSE:
- case -ENOBUFS:
case -EPIPE:
xprt_conditional_disconnect(task->tk_rqstp->rq_xprt,
task->tk_rqstp->rq_connect_cookie);
@@ -2127,17 +2141,20 @@ call_connect_status(struct rpc_task *task)
/* retry with existing socket, after a delay */
rpc_delay(task, 3*HZ);
/* fall through */
+ case -EADDRINUSE:
case -ENOTCONN:
case -EAGAIN:
case -ETIMEDOUT:
goto out_retry;
- case 0:
- clnt->cl_stats->netreconn++;
- task->tk_action = call_transmit;
- return;
+ case -ENOBUFS:
+ rpc_delay(task, HZ >> 2);
+ goto out_retry;
}
rpc_call_rpcerror(task, status);
return;
+out_next:
+ task->tk_action = call_transmit;
+ return;
out_retry:
/* Check for timeouts before looping back to call_bind */
task->tk_action = call_bind;
@@ -2365,7 +2382,7 @@ call_status(struct rpc_task *task)
case -ECONNABORTED:
case -ENOTCONN:
rpc_force_rebind(clnt);
- /* fall through */
+ break;
case -EADDRINUSE:
rpc_delay(task, 3*HZ);
/* fall through */
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 783748dc5e6f..2e71f5455c6c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1408,13 +1408,6 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task)
status = -EBADMSG;
goto out_dequeue;
}
- if (task->tk_ops->rpc_call_prepare_transmit) {
- task->tk_ops->rpc_call_prepare_transmit(task,
- task->tk_calldata);
- status = task->tk_status;
- if (status < 0)
- goto out_dequeue;
- }
if (RPC_SIGNALLED(task)) {
status = -ERESTARTSYS;
goto out_dequeue;
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index b88d48d00913..0f1eaed1bd1b 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -75,6 +75,7 @@ void tipc_set_node_addr(struct net *net, u32 addr)
tipc_set_node_id(net, node_id);
}
tn->trial_addr = addr;
+ tn->addr_trial_end = jiffies;
pr_info("32-bit node address hash set to %x\n", addr);
}
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 66d3a07bc571..c2c5c53cad22 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -106,8 +106,6 @@ struct tipc_stats {
* @transmitq: queue for sent, non-acked messages
* @backlogq: queue for messages waiting to be sent
* @snt_nxt: next sequence number to use for outbound messages
- * @prev_from: sequence number of most previous retransmission request
- * @stale_limit: time when repeated identical retransmits must force link reset
* @ackers: # of peers that needs to ack each packet before it can be released
* @acked: # last packet acked by a certain peer. Used for broadcast.
* @rcv_nxt: next sequence number to expect for inbound messages
@@ -164,9 +162,7 @@ struct tipc_link {
u16 limit;
} backlog[5];
u16 snd_nxt;
- u16 prev_from;
u16 window;
- unsigned long stale_limit;
/* Reception */
u16 rcv_nxt;
@@ -1044,47 +1040,53 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
* link_retransmit_failure() - Detect repeated retransmit failures
* @l: tipc link sender
* @r: tipc link receiver (= l in case of unicast)
- * @from: seqno of the 1st packet in retransmit request
* @rc: returned code
*
* Return: true if the repeated retransmit failures happens, otherwise
* false
*/
static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r,
- u16 from, int *rc)
+ int *rc)
{
struct sk_buff *skb = skb_peek(&l->transmq);
struct tipc_msg *hdr;
if (!skb)
return false;
- hdr = buf_msg(skb);
- /* Detect repeated retransmit failures on same packet */
- if (r->prev_from != from) {
- r->prev_from = from;
- r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance);
- } else if (time_after(jiffies, r->stale_limit)) {
- pr_warn("Retransmission failure on link <%s>\n", l->name);
- link_print(l, "State of link ");
- pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
- msg_user(hdr), msg_type(hdr), msg_size(hdr),
- msg_errcode(hdr));
- pr_info("sqno %u, prev: %x, src: %x\n",
- msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr));
-
- trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
- trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
- trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+ if (!TIPC_SKB_CB(skb)->retr_cnt)
+ return false;
- if (link_is_bc_sndlink(l))
- *rc = TIPC_LINK_DOWN_EVT;
+ if (!time_after(jiffies, TIPC_SKB_CB(skb)->retr_stamp +
+ msecs_to_jiffies(r->tolerance)))
+ return false;
+
+ hdr = buf_msg(skb);
+ if (link_is_bc_sndlink(l) && !less(r->acked, msg_seqno(hdr)))
+ return false;
+ pr_warn("Retransmission failure on link <%s>\n", l->name);
+ link_print(l, "State of link ");
+ pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
+ msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr));
+ pr_info("sqno %u, prev: %x, dest: %x\n",
+ msg_seqno(hdr), msg_prevnode(hdr), msg_destnode(hdr));
+ pr_info("retr_stamp %d, retr_cnt %d\n",
+ jiffies_to_msecs(TIPC_SKB_CB(skb)->retr_stamp),
+ TIPC_SKB_CB(skb)->retr_cnt);
+
+ trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
+ trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
+ trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+
+ if (link_is_bc_sndlink(l)) {
+ r->state = LINK_RESET;
+ *rc = TIPC_LINK_DOWN_EVT;
+ } else {
*rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
- return true;
}
- return false;
+ return true;
}
/* tipc_link_bc_retrans() - retransmit zero or more packets
@@ -1110,7 +1112,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
trace_tipc_link_retrans(r, from, to, &l->transmq);
- if (link_retransmit_failure(l, r, from, &rc))
+ if (link_retransmit_failure(l, r, &rc))
return rc;
skb_queue_walk(&l->transmq, skb) {
@@ -1119,11 +1121,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
continue;
if (more(msg_seqno(hdr), to))
break;
- if (link_is_bc_sndlink(l)) {
- if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
- continue;
- TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
- }
+
+ if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
+ continue;
+ TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
_skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC);
if (!_skb)
return 0;
@@ -1133,6 +1134,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
_skb->priority = TC_PRIO_CONTROL;
__skb_queue_tail(xmitq, _skb);
l->stats.retransmitted++;
+
+ /* Increase actual retrans counter & mark first time */
+ if (!TIPC_SKB_CB(skb)->retr_cnt++)
+ TIPC_SKB_CB(skb)->retr_stamp = jiffies;
}
return 0;
}
@@ -1357,12 +1362,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
struct tipc_msg *hdr;
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
u16 ack = l->rcv_nxt - 1;
+ bool passed = false;
u16 seqno, n = 0;
int rc = 0;
- if (gap && link_retransmit_failure(l, l, acked + 1, &rc))
- return rc;
-
skb_queue_walk_safe(&l->transmq, skb, tmp) {
seqno = buf_seqno(skb);
@@ -1372,12 +1375,17 @@ next_gap_ack:
__skb_unlink(skb, &l->transmq);
kfree_skb(skb);
} else if (less_eq(seqno, acked + gap)) {
- /* retransmit skb */
+ /* First, check if repeated retrans failures occurs? */
+ if (!passed && link_retransmit_failure(l, l, &rc))
+ return rc;
+ passed = true;
+
+ /* retransmit skb if unrestricted*/
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
continue;
TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
-
- _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
+ _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE,
+ GFP_ATOMIC);
if (!_skb)
continue;
hdr = buf_msg(_skb);
@@ -1386,6 +1394,10 @@ next_gap_ack:
_skb->priority = TC_PRIO_CONTROL;
__skb_queue_tail(xmitq, _skb);
l->stats.retransmitted++;
+
+ /* Increase actual retrans counter & mark first time */
+ if (!TIPC_SKB_CB(skb)->retr_cnt++)
+ TIPC_SKB_CB(skb)->retr_stamp = jiffies;
} else {
/* retry with Gap ACK blocks if any */
if (!ga || n >= ga->gack_cnt)
@@ -2577,7 +2589,7 @@ int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf)
i += scnprintf(buf + i, sz - i, " %x", l->peer_caps);
i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt);
i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt);
- i += scnprintf(buf + i, sz - i, " %u", l->prev_from);
+ i += scnprintf(buf + i, sz - i, " %u", 0);
i += scnprintf(buf + i, sz - i, " %u", 0);
i += scnprintf(buf + i, sz - i, " %u", l->acked);
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index da509f0eb9ca..d7ebc9e955f6 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -102,13 +102,15 @@ struct plist;
#define TIPC_MEDIA_INFO_OFFSET 5
struct tipc_skb_cb {
- u32 bytes_read;
- u32 orig_member;
struct sk_buff *tail;
unsigned long nxt_retr;
- bool validated;
+ unsigned long retr_stamp;
+ u32 bytes_read;
+ u32 orig_member;
u16 chain_imp;
u16 ackers;
+ u16 retr_cnt;
+ bool validated;
};
#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 44abc8e9c990..241ed2274473 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -223,7 +223,8 @@ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr)
publ->key);
}
- kfree_rcu(p, rcu);
+ if (p)
+ kfree_rcu(p, rcu);
}
/**
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index d86030ef1232..e135d4e11231 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
int rep_type;
int rep_size;
int req_type;
+ int req_size;
struct net *net;
struct sk_buff *rep;
struct tlv_desc *req;
@@ -257,7 +258,8 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
int err;
struct sk_buff *arg;
- if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+ if (msg->req_type && (!msg->req_size ||
+ !TLV_CHECK_TYPE(msg->req, msg->req_type)))
return -EINVAL;
msg->rep = tipc_tlv_alloc(msg->rep_size);
@@ -354,7 +356,8 @@ static int tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
{
int err;
- if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+ if (msg->req_type && (!msg->req_size ||
+ !TLV_CHECK_TYPE(msg->req, msg->req_type)))
return -EINVAL;
err = __tipc_nl_compat_doit(cmd, msg);
@@ -1278,8 +1281,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
goto send;
}
- len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
- if (!len || !TLV_OK(msg.req, len)) {
+ msg.req_size = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
+ if (msg.req_size && !TLV_OK(msg.req, msg.req_size)) {
msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
err = -EOPNOTSUPP;
goto send;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index dd8537f988c4..83ae41d7e554 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -485,9 +485,8 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
tsk_set_unreturnable(tsk, true);
if (sock->type == SOCK_DGRAM)
tsk_set_unreliable(tsk, true);
- __skb_queue_head_init(&tsk->mc_method.deferredq);
}
-
+ __skb_queue_head_init(&tsk->mc_method.deferredq);
trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " ");
return 0;
}
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 7c0b2b778703..43922d86e510 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -373,9 +373,9 @@ static int tls_push_data(struct sock *sk,
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
- int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
struct tls_record_info *record = ctx->open_record;
+ int tls_push_record_flags;
struct page_frag *pfrag;
size_t orig_size = size;
u32 max_open_record_len;
@@ -390,6 +390,9 @@ static int tls_push_data(struct sock *sk,
if (sk->sk_err)
return -sk->sk_err;
+ flags |= MSG_SENDPAGE_DECRYPTED;
+ tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
+
timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
if (tls_is_partially_sent_record(tls_ctx)) {
rc = tls_push_partial_record(sk, tls_ctx, flags);
@@ -576,7 +579,9 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
gfp_t sk_allocation = sk->sk_allocation;
sk->sk_allocation = GFP_ATOMIC;
- tls_push_partial_record(sk, ctx, MSG_DONTWAIT | MSG_NOSIGNAL);
+ tls_push_partial_record(sk, ctx,
+ MSG_DONTWAIT | MSG_NOSIGNAL |
+ MSG_SENDPAGE_DECRYPTED);
sk->sk_allocation = sk_allocation;
}
}
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 4674e57e66b0..43252a801c3f 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -261,24 +261,9 @@ void tls_ctx_free(struct tls_context *ctx)
kfree(ctx);
}
-static void tls_sk_proto_close(struct sock *sk, long timeout)
+static void tls_sk_proto_cleanup(struct sock *sk,
+ struct tls_context *ctx, long timeo)
{
- struct tls_context *ctx = tls_get_ctx(sk);
- long timeo = sock_sndtimeo(sk, 0);
- void (*sk_proto_close)(struct sock *sk, long timeout);
- bool free_ctx = false;
-
- lock_sock(sk);
- sk_proto_close = ctx->sk_proto_close;
-
- if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD)
- goto skip_tx_cleanup;
-
- if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) {
- free_ctx = true;
- goto skip_tx_cleanup;
- }
-
if (unlikely(sk->sk_write_pending) &&
!wait_on_pending_writer(sk, &timeo))
tls_handle_open_record(sk, 0);
@@ -287,7 +272,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
if (ctx->tx_conf == TLS_SW) {
kfree(ctx->tx.rec_seq);
kfree(ctx->tx.iv);
- tls_sw_free_resources_tx(sk);
+ tls_sw_release_resources_tx(sk);
#ifdef CONFIG_TLS_DEVICE
} else if (ctx->tx_conf == TLS_HW) {
tls_device_free_resources_tx(sk);
@@ -295,26 +280,46 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
}
if (ctx->rx_conf == TLS_SW)
- tls_sw_free_resources_rx(sk);
+ tls_sw_release_resources_rx(sk);
#ifdef CONFIG_TLS_DEVICE
if (ctx->rx_conf == TLS_HW)
tls_device_offload_cleanup_rx(sk);
-
- if (ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW) {
-#else
- {
#endif
- tls_ctx_free(ctx);
- ctx = NULL;
- }
+}
-skip_tx_cleanup:
+static void tls_sk_proto_close(struct sock *sk, long timeout)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tls_context *ctx = tls_get_ctx(sk);
+ long timeo = sock_sndtimeo(sk, 0);
+ bool free_ctx;
+
+ if (ctx->tx_conf == TLS_SW)
+ tls_sw_cancel_work_tx(ctx);
+
+ lock_sock(sk);
+ free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW;
+
+ if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE)
+ tls_sk_proto_cleanup(sk, ctx, timeo);
+
+ write_lock_bh(&sk->sk_callback_lock);
+ if (free_ctx)
+ icsk->icsk_ulp_data = NULL;
+ sk->sk_prot = ctx->sk_proto;
+ if (sk->sk_write_space == tls_write_space)
+ sk->sk_write_space = ctx->sk_write_space;
+ write_unlock_bh(&sk->sk_callback_lock);
release_sock(sk);
- sk_proto_close(sk, timeout);
- /* free ctx for TLS_HW_RECORD, used by tcp_set_state
- * for sk->sk_prot->unhash [tls_hw_unhash]
- */
+ if (ctx->tx_conf == TLS_SW)
+ tls_sw_free_ctx_tx(ctx);
+ if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW)
+ tls_sw_strparser_done(ctx);
+ if (ctx->rx_conf == TLS_SW)
+ tls_sw_free_ctx_rx(ctx);
+ ctx->sk_proto_close(sk, timeout);
+
if (free_ctx)
tls_ctx_free(ctx);
}
@@ -526,6 +531,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
{
#endif
rc = tls_set_sw_offload(sk, ctx, 1);
+ if (rc)
+ goto err_crypto_info;
conf = TLS_SW;
}
} else {
@@ -537,13 +544,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
{
#endif
rc = tls_set_sw_offload(sk, ctx, 0);
+ if (rc)
+ goto err_crypto_info;
conf = TLS_SW;
}
+ tls_sw_strparser_arm(sk, ctx);
}
- if (rc)
- goto err_crypto_info;
-
if (tx)
ctx->tx_conf = conf;
else
@@ -607,6 +614,7 @@ static struct tls_context *create_ctx(struct sock *sk)
ctx->setsockopt = sk->sk_prot->setsockopt;
ctx->getsockopt = sk->sk_prot->getsockopt;
ctx->sk_proto_close = sk->sk_prot->close;
+ ctx->unhash = sk->sk_prot->unhash;
return ctx;
}
@@ -764,7 +772,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base;
prot[TLS_HW_RECORD][TLS_HW_RECORD].hash = tls_hw_hash;
prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash = tls_hw_unhash;
- prot[TLS_HW_RECORD][TLS_HW_RECORD].close = tls_sk_proto_close;
}
static int tls_init(struct sock *sk)
@@ -773,7 +780,7 @@ static int tls_init(struct sock *sk)
int rc = 0;
if (tls_hw_prot(sk))
- goto out;
+ return 0;
/* The TLS ulp is currently supported only for TCP sockets
* in ESTABLISHED state.
@@ -784,21 +791,38 @@ static int tls_init(struct sock *sk)
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTSUPP;
+ tls_build_proto(sk);
+
/* allocate tls context */
+ write_lock_bh(&sk->sk_callback_lock);
ctx = create_ctx(sk);
if (!ctx) {
rc = -ENOMEM;
goto out;
}
- tls_build_proto(sk);
ctx->tx_conf = TLS_BASE;
ctx->rx_conf = TLS_BASE;
+ ctx->sk_proto = sk->sk_prot;
update_sk_prot(sk, ctx);
out:
+ write_unlock_bh(&sk->sk_callback_lock);
return rc;
}
+static void tls_update(struct sock *sk, struct proto *p)
+{
+ struct tls_context *ctx;
+
+ ctx = tls_get_ctx(sk);
+ if (likely(ctx)) {
+ ctx->sk_proto_close = p->close;
+ ctx->sk_proto = p;
+ } else {
+ sk->sk_prot = p;
+ }
+}
+
void tls_register_device(struct tls_device *device)
{
spin_lock_bh(&device_spinlock);
@@ -819,6 +843,7 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
.name = "tls",
.owner = THIS_MODULE,
.init = tls_init,
+ .update = tls_update,
};
static int __init tls_register(void)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 53b4ad94e74a..91d21b048a9b 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2054,7 +2054,16 @@ static void tls_data_ready(struct sock *sk)
}
}
-void tls_sw_free_resources_tx(struct sock *sk)
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx)
+{
+ struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+
+ set_bit(BIT_TX_CLOSING, &ctx->tx_bitmask);
+ set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask);
+ cancel_delayed_work_sync(&ctx->tx_work.work);
+}
+
+void tls_sw_release_resources_tx(struct sock *sk)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
@@ -2065,11 +2074,6 @@ void tls_sw_free_resources_tx(struct sock *sk)
if (atomic_read(&ctx->encrypt_pending))
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
- release_sock(sk);
- cancel_delayed_work_sync(&ctx->tx_work.work);
- lock_sock(sk);
-
- /* Tx whatever records we can transmit and abandon the rest */
tls_tx_records(sk, -1);
/* Free up un-sent records in tx_list. First, free
@@ -2092,6 +2096,11 @@ void tls_sw_free_resources_tx(struct sock *sk)
crypto_free_aead(ctx->aead_send);
tls_free_open_rec(sk);
+}
+
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx)
+{
+ struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
kfree(ctx);
}
@@ -2110,25 +2119,40 @@ void tls_sw_release_resources_rx(struct sock *sk)
skb_queue_purge(&ctx->rx_list);
crypto_free_aead(ctx->aead_recv);
strp_stop(&ctx->strp);
- write_lock_bh(&sk->sk_callback_lock);
- sk->sk_data_ready = ctx->saved_data_ready;
- write_unlock_bh(&sk->sk_callback_lock);
- release_sock(sk);
- strp_done(&ctx->strp);
- lock_sock(sk);
+ /* If tls_sw_strparser_arm() was not called (cleanup paths)
+ * we still want to strp_stop(), but sk->sk_data_ready was
+ * never swapped.
+ */
+ if (ctx->saved_data_ready) {
+ write_lock_bh(&sk->sk_callback_lock);
+ sk->sk_data_ready = ctx->saved_data_ready;
+ write_unlock_bh(&sk->sk_callback_lock);
+ }
}
}
-void tls_sw_free_resources_rx(struct sock *sk)
+void tls_sw_strparser_done(struct tls_context *tls_ctx)
{
- struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
- tls_sw_release_resources_rx(sk);
+ strp_done(&ctx->strp);
+}
+
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx)
+{
+ struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
kfree(ctx);
}
+void tls_sw_free_resources_rx(struct sock *sk)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+
+ tls_sw_release_resources_rx(sk);
+ tls_sw_free_ctx_rx(tls_ctx);
+}
+
/* The work handler to transmitt the encrypted records in tx_list */
static void tx_work_handler(struct work_struct *work)
{
@@ -2137,11 +2161,17 @@ static void tx_work_handler(struct work_struct *work)
struct tx_work, work);
struct sock *sk = tx_work->sk;
struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+ struct tls_sw_context_tx *ctx;
- if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+ if (unlikely(!tls_ctx))
return;
+ ctx = tls_sw_ctx_tx(tls_ctx);
+ if (test_bit(BIT_TX_CLOSING, &ctx->tx_bitmask))
+ return;
+
+ if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+ return;
lock_sock(sk);
tls_tx_records(sk, -1);
release_sock(sk);
@@ -2160,6 +2190,18 @@ void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
}
}
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx)
+{
+ struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx);
+
+ write_lock_bh(&sk->sk_callback_lock);
+ rx_ctx->saved_data_ready = sk->sk_data_ready;
+ sk->sk_data_ready = tls_data_ready;
+ write_unlock_bh(&sk->sk_callback_lock);
+
+ strp_check_rcv(&rx_ctx->strp);
+}
+
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
@@ -2357,13 +2399,6 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
cb.parse_msg = tls_read_size;
strp_init(&sw_ctx_rx->strp, sk, &cb);
-
- write_lock_bh(&sk->sk_callback_lock);
- sw_ctx_rx->saved_data_ready = sk->sk_data_ready;
- sk->sk_data_ready = tls_data_ready;
- write_unlock_bh(&sk->sk_callback_lock);
-
- strp_check_rcv(&sw_ctx_rx->strp);
}
goto out;
diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
index f2084e3f7aa4..9d864ebeb7b3 100644
--- a/net/vmw_vsock/hyperv_transport.c
+++ b/net/vmw_vsock/hyperv_transport.c
@@ -312,6 +312,11 @@ static void hvs_close_connection(struct vmbus_channel *chan)
lock_sock(sk);
hvs_do_close_lock_held(vsock_sk(sk), true);
release_sock(sk);
+
+ /* Release the refcnt for the channel that's opened in
+ * hvs_open_connection().
+ */
+ sock_put(sk);
}
static void hvs_open_connection(struct vmbus_channel *chan)
@@ -407,6 +412,9 @@ static void hvs_open_connection(struct vmbus_channel *chan)
}
set_per_channel_state(chan, conn_from_host ? new : sk);
+
+ /* This reference will be dropped by hvs_close_connection(). */
+ sock_hold(conn_from_host ? new : sk);
vmbus_set_chn_rescind_callback(chan, hvs_close_connection);
/* Set the pending send size to max packet size to always get
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 45d9afcff6d5..32b3c719fdfc 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1410,10 +1410,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
}
break;
case NETDEV_PRE_UP:
- if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) &&
- !(wdev->iftype == NL80211_IFTYPE_AP_VLAN &&
- rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP &&
- wdev->use_4addr))
+ if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
+ wdev->use_4addr, 0))
return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fc83dd179c1a..fd05ae1437a9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3484,9 +3484,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return err;
}
- if (!(rdev->wiphy.interface_modes & (1 << type)) &&
- !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr &&
- rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP))
+ if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
return -EOPNOTSUPP;
err = nl80211_parse_mon_options(rdev, type, info, &params);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 4831ad745f91..327479ce69f5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2788,7 +2788,7 @@ static void reg_process_pending_hints(void)
/* When last_request->processed becomes true this will be rescheduled */
if (lr && !lr->processed) {
- reg_process_hint(lr);
+ pr_debug("Pending regulatory request, waiting for it to be processed...\n");
return;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 1c39d6a2e850..e74837824cea 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -233,25 +233,30 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
switch (params->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
+ /* Extended Key ID can only be used with CCMP/GCMP ciphers */
+ if ((pairwise && key_idx) ||
+ params->mode != NL80211_KEY_RX_TX)
+ return -EINVAL;
+ break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- /* IEEE802.11-2016 allows only 0 and - when using Extended Key
- * ID - 1 as index for pairwise keys.
+ /* IEEE802.11-2016 allows only 0 and - when supporting
+ * Extended Key ID - 1 as index for pairwise keys.
* @NL80211_KEY_NO_TX is only allowed for pairwise keys when
* the driver supports Extended Key ID.
* @NL80211_KEY_SET_TX can't be set when installing and
* validating a key.
*/
- if (params->mode == NL80211_KEY_NO_TX) {
- if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_EXT_KEY_ID))
- return -EINVAL;
- else if (!pairwise || key_idx < 0 || key_idx > 1)
+ if ((params->mode == NL80211_KEY_NO_TX && !pairwise) ||
+ params->mode == NL80211_KEY_SET_TX)
+ return -EINVAL;
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+ if (pairwise && (key_idx < 0 || key_idx > 1))
return -EINVAL;
- } else if ((pairwise && key_idx) ||
- params->mode == NL80211_KEY_SET_TX) {
+ } else if (pairwise && key_idx) {
return -EINVAL;
}
break;
@@ -1697,7 +1702,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
num_interfaces += params->iftype_num[iftype];
if (params->iftype_num[iftype] > 0 &&
- !(wiphy->software_iftypes & BIT(iftype)))
+ !cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
used_iftypes |= BIT(iftype);
}
@@ -1719,7 +1724,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
return -ENOMEM;
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
- if (wiphy->software_iftypes & BIT(iftype))
+ if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
continue;
for (j = 0; j < c->n_limits; j++) {
all_iftypes |= limits[j].types;
@@ -2072,3 +2077,26 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
return max_vht_nss;
}
EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
+
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+ bool is_4addr, u8 check_swif)
+
+{
+ bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
+
+ switch (check_swif) {
+ case 0:
+ if (is_vlan && is_4addr)
+ return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+ return wiphy->interface_modes & BIT(iftype);
+ case 1:
+ if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
+ return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+ return wiphy->software_iftypes & BIT(iftype);
+ default:
+ break;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_iftype_allowed);
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 83de74ca729a..688aac7a6943 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c
@@ -365,7 +365,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
umem->pages = kcalloc(umem->npgs, sizeof(*umem->pages), GFP_KERNEL);
if (!umem->pages) {
err = -ENOMEM;
- goto out_account;
+ goto out_pin;
}
for (i = 0; i < umem->npgs; i++)
@@ -373,6 +373,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
return 0;
+out_pin:
+ xdp_umem_unpin_pages(umem);
out_account:
xdp_umem_unaccount_pages(umem);
return err;
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 74868f9d81fb..2ab4859df55a 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -145,8 +145,6 @@ static int xfrmi_create(struct net_device *dev)
if (err < 0)
goto out;
- strcpy(xi->p.name, dev->name);
-
dev_hold(dev);
xfrmi_link(xfrmn, xi);
@@ -177,7 +175,6 @@ static void xfrmi_dev_uninit(struct net_device *dev)
struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
xfrmi_unlink(xfrmn, xi);
- dev_put(xi->phydev);
dev_put(dev);
}
@@ -294,7 +291,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
if (tdev == dev) {
stats->collisions++;
net_warn_ratelimited("%s: Local routing loop detected!\n",
- xi->p.name);
+ dev->name);
goto tx_err_dst_release;
}
@@ -364,7 +361,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err;
}
- fl.flowi_oif = xi->phydev->ifindex;
+ fl.flowi_oif = xi->p.link;
ret = xfrmi_xmit2(skb, dev, &fl);
if (ret < 0)
@@ -505,7 +502,7 @@ static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
{
- struct net *net = dev_net(xi->dev);
+ struct net *net = xi->net;
struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
int err;
@@ -550,7 +547,7 @@ static int xfrmi_get_iflink(const struct net_device *dev)
{
struct xfrm_if *xi = netdev_priv(dev);
- return xi->phydev->ifindex;
+ return xi->p.link;
}
@@ -576,12 +573,14 @@ static void xfrmi_dev_setup(struct net_device *dev)
dev->needs_free_netdev = true;
dev->priv_destructor = xfrmi_dev_free;
netif_keep_dst(dev);
+
+ eth_broadcast_addr(dev->broadcast);
}
static int xfrmi_dev_init(struct net_device *dev)
{
struct xfrm_if *xi = netdev_priv(dev);
- struct net_device *phydev = xi->phydev;
+ struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
int err;
dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -596,13 +595,19 @@ static int xfrmi_dev_init(struct net_device *dev)
dev->features |= NETIF_F_LLTX;
- dev->needed_headroom = phydev->needed_headroom;
- dev->needed_tailroom = phydev->needed_tailroom;
+ if (phydev) {
+ dev->needed_headroom = phydev->needed_headroom;
+ dev->needed_tailroom = phydev->needed_tailroom;
- if (is_zero_ether_addr(dev->dev_addr))
- eth_hw_addr_inherit(dev, phydev);
- if (is_zero_ether_addr(dev->broadcast))
- memcpy(dev->broadcast, phydev->broadcast, dev->addr_len);
+ if (is_zero_ether_addr(dev->dev_addr))
+ eth_hw_addr_inherit(dev, phydev);
+ if (is_zero_ether_addr(dev->broadcast))
+ memcpy(dev->broadcast, phydev->broadcast,
+ dev->addr_len);
+ } else {
+ eth_hw_addr_random(dev);
+ eth_broadcast_addr(dev->broadcast);
+ }
return 0;
}
@@ -638,12 +643,6 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
int err;
xfrmi_netlink_parms(data, &p);
-
- if (!tb[IFLA_IFNAME])
- return -EINVAL;
-
- nla_strlcpy(p.name, tb[IFLA_IFNAME], IFNAMSIZ);
-
xi = xfrmi_locate(net, &p);
if (xi)
return -EEXIST;
@@ -652,13 +651,8 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
xi->p = p;
xi->net = net;
xi->dev = dev;
- xi->phydev = dev_get_by_index(net, p.link);
- if (!xi->phydev)
- return -ENODEV;
err = xfrmi_create(dev);
- if (err < 0)
- dev_put(xi->phydev);
return err;
}
@@ -672,11 +666,11 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
struct netlink_ext_ack *extack)
{
struct xfrm_if *xi = netdev_priv(dev);
- struct net *net = dev_net(dev);
-
- xfrmi_netlink_parms(data, &xi->p);
+ struct net *net = xi->net;
+ struct xfrm_if_parms p;
- xi = xfrmi_locate(net, &xi->p);
+ xfrmi_netlink_parms(data, &p);
+ xi = xfrmi_locate(net, &p);
if (!xi) {
xi = netdev_priv(dev);
} else {
@@ -684,7 +678,7 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
return -EEXIST;
}
- return xfrmi_update(xi, &xi->p);
+ return xfrmi_update(xi, &p);
}
static size_t xfrmi_get_size(const struct net_device *dev)
@@ -715,7 +709,7 @@ static struct net *xfrmi_get_link_net(const struct net_device *dev)
{
struct xfrm_if *xi = netdev_priv(dev);
- return dev_net(xi->phydev);
+ return xi->net;
}
static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8ca637a72697..21e939235b39 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -912,6 +912,7 @@ restart:
} else if (delta > 0) {
p = &parent->rb_right;
} else {
+ bool same_prefixlen = node->prefixlen == n->prefixlen;
struct xfrm_policy *tmp;
hlist_for_each_entry(tmp, &n->hhead, bydst) {
@@ -919,9 +920,11 @@ restart:
hlist_del_rcu(&tmp->bydst);
}
+ node->prefixlen = prefixlen;
+
xfrm_policy_inexact_list_reinsert(net, node, family);
- if (node->prefixlen == n->prefixlen) {
+ if (same_prefixlen) {
kfree_rcu(n, rcu);
return;
}
@@ -929,7 +932,6 @@ restart:
rb_erase(*p, new);
kfree_rcu(n, rcu);
n = node;
- n->prefixlen = prefixlen;
goto restart;
}
}
@@ -3269,7 +3271,7 @@ decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse)
struct flowi4 *fl4 = &fl->u.ip4;
int oif = 0;
- if (skb_dst(skb))
+ if (skb_dst(skb) && skb_dst(skb)->dev)
oif = skb_dst(skb)->dev->ifindex;
memset(fl4, 0, sizeof(struct flowi4));
@@ -3387,7 +3389,7 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse)
nexthdr = nh[nhoff];
- if (skb_dst(skb))
+ if (skb_dst(skb) && skb_dst(skb)->dev)
oif = skb_dst(skb)->dev->ifindex;
memset(fl6, 0, sizeof(struct flowi6));
diff --git a/samples/auxdisplay/cfag12864b-example.c b/samples/auxdisplay/cfag12864b-example.c
index 85571e90191f..bfeab44f81d0 100644
--- a/samples/auxdisplay/cfag12864b-example.c
+++ b/samples/auxdisplay/cfag12864b-example.c
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
if (argc != 2) {
printf(
- "Sintax: %s fbdev\n"
+ "Syntax: %s fbdev\n"
"Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
return -1;
}
diff --git a/samples/vfio-mdev/mdpy-defs.h b/samples/vfio-mdev/mdpy-defs.h
index 96b3b1b49d34..eb26421b6429 100644
--- a/samples/vfio-mdev/mdpy-defs.h
+++ b/samples/vfio-mdev/mdpy-defs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Simple pci display device.
*
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 77c742fa4fb1..4b0432e095ae 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -190,9 +190,6 @@ echo-cmd = $(if $($(quiet)cmd_$(1)),\
# printing commands
cmd = @set -e; $(echo-cmd) $(cmd_$(1))
-# Add $(obj)/ for paths that are not absolute
-objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
-
###
# if_changed - execute command if any prerequisite is newer than
# target, or command line has changed
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index 8a5c4d645eb1..4bbf4fc163a2 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -25,7 +25,7 @@ failure = $(if-success,$(1),n,y)
# $(cc-option,<flag>)
# Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
+cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -E -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 0d434d0afc0b..2f66ed388d1c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -52,6 +52,13 @@ ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif
+ifeq ($(MAKECMDGOALS)$(need-modorder),)
+ifneq ($(obj-m),)
+$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
+$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
+endif
+endif
+
# ===========================================================================
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -487,7 +494,9 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
PHONY += $(subdir-ym)
$(subdir-ym):
- $(Q)$(MAKE) $(build)=$@ need-builtin=$(if $(findstring $@,$(subdir-obj-y)),1)
+ $(Q)$(MAKE) $(build)=$@ \
+ need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
+ need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 6410bd22fe38..03757cc60e06 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
+ifdef CONFIG_KASAN
+CFLAGS_KASAN_NOSANITIZE := -fno-builtin
+KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
+endif
+
ifdef CONFIG_KASAN_GENERIC
ifdef CONFIG_KASAN_INLINE
@@ -7,8 +12,6 @@ else
call_threshold := 0
endif
-KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
-
CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
@@ -45,7 +48,3 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress \
$(instrumentation_flags)
endif # CONFIG_KASAN_SW_TAGS
-
-ifdef CONFIG_KASAN
-CFLAGS_KASAN_NOSANITIZE := -fno-builtin
-endif
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 5241d0751eb0..41c50f9461e5 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -45,7 +45,6 @@ subdir-ym := $(sort $(subdir-y) $(subdir-m))
multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m))))
multi-used := $(multi-used-y) $(multi-used-m)
-single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
# tell kbuild to descend
@@ -91,7 +90,6 @@ lib-y := $(addprefix $(obj)/,$(lib-y))
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
real-obj-y := $(addprefix $(obj)/,$(real-obj-y))
real-obj-m := $(addprefix $(obj)/,$(real-obj-m))
-single-used-m := $(addprefix $(obj)/,$(single-used-m))
multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 6b19c1a4eae5..26e6574ecd08 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -38,12 +38,39 @@
# symbols in the final module linking stage
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely useful to speed up test compiles
-PHONY := _modpost
-_modpost: __modpost
+
+PHONY := __modpost
+__modpost:
include include/config/auto.conf
include scripts/Kbuild.include
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+
+MODPOST = scripts/mod/modpost \
+ $(if $(CONFIG_MODVERSIONS),-m) \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+ $(if $(KBUILD_MODPOST_WARN),-w)
+
+ifdef MODPOST_VMLINUX
+
+__modpost: vmlinux.o
+
+quiet_cmd_modpost = MODPOST $@
+ cmd_modpost = $(MODPOST) $@
+
+PHONY += vmlinux.o
+vmlinux.o:
+ $(call cmd,modpost)
+
+else
+
# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info
ifneq ($(KBUILD_EXTMOD),)
@@ -58,50 +85,25 @@ endif
include scripts/Makefile.lib
-kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
-
-modorder := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
-
-# Step 1), find all modules listed in modules.order
-ifdef CONFIG_MODULES
-modules := $(sort $(shell cat $(modorder)))
-endif
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
-_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
-
-# Step 2), invoke modpost
-# Includes step 3,4
-modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
- $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
- $(if $(KBUILD_MODPOST_WARN),-w)
-
-MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
+__modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
+ @:
-# We can go over command line length here, so be careful.
-quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
- cmd_modpost = sed 's/ko$$/o/' $(modorder) | $(modpost) $(MODPOST_OPT) -s -T -
-
-PHONY += __modpost
-__modpost: $(modules:.ko=.o) FORCE
- $(call cmd,modpost) $(wildcard vmlinux)
+MODPOST += $(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -s -T - $(wildcard vmlinux)
-quiet_cmd_kernel-mod = MODPOST $@
- cmd_kernel-mod = $(modpost) $@
+# We can go over command line length here, so be careful.
+quiet_cmd_modpost = MODPOST $(words $(modules)) modules
+ cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
-vmlinux.o: FORCE
- $(call cmd,kernel-mod)
+PHONY += modules-modpost
+modules-modpost:
+ $(call cmd,modpost)
# Declare generated files as targets for modpost
-$(modules:.ko=.mod.c): __modpost ;
-
+$(modules:.ko=.mod.c): modules-modpost
# Step 5), compile all *.mod.c files
@@ -145,10 +147,10 @@ FORCE:
# optimization, we don't need to read them if the target does not
# exist, we will rebuild anyway in that case.
-cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
+existing-targets := $(wildcard $(sort $(targets)))
+
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-ifneq ($(cmd_files),)
- include $(cmd_files)
endif
.PHONY: $(PHONY)
diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci
index 988120e0fd67..0f78d94abc35 100644
--- a/scripts/coccinelle/api/atomic_as_refcounter.cocci
+++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
// Check if refcount_t type and API should be used
// instead of atomic_t type when dealing with refcounters
//
diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py
index 7915823b92a5..c458696ef3a7 100755
--- a/scripts/gen_compile_commands.py
+++ b/scripts/gen_compile_commands.py
@@ -21,9 +21,9 @@ _LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
# A kernel build generally has over 2000 entries in its compile_commands.json
-# database. If this code finds 500 or fewer, then warn the user that they might
+# database. If this code finds 300 or fewer, then warn the user that they might
# not have all the .cmd files, and they might need to compile the kernel.
-_LOW_COUNT_THRESHOLD = 500
+_LOW_COUNT_THRESHOLD = 300
def parse_arguments():
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 47f6f3ea0771..bbaf29386995 100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -23,6 +23,12 @@ TMPFILE=$OUTFILE.tmp
trap 'rm -f $OUTFILE $TMPFILE' EXIT
+# SPDX-License-Identifier with GPL variants must have "WITH Linux-syscall-note"
+if [ -n "$(sed -n -e "/SPDX-License-Identifier:.*GPL-/{/WITH Linux-syscall-note/!p}" $INFILE)" ]; then
+ echo "error: $INFILE: missing \"WITH Linux-syscall-note\" for SPDX-License-Identifier" >&2
+ exit 1
+fi
+
sed -E -e '
s/([[:space:](])(__user|__force|__iomem)[[:space:]]/\1/g
s/__attribute_const__([[:space:]]|$)/\1/g
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1134892599da..3569d2dec37c 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -848,6 +848,7 @@ int conf_write(const char *name)
const char *str;
char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
+ int i;
bool need_newline = false;
if (!name)
@@ -930,6 +931,9 @@ next:
}
fclose(out);
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_WRITTEN;
+
if (*tmpname) {
if (is_same(name, tmpname)) {
conf_message("No change to %s", name);
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index a7124f895b24..915775eb2921 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -210,7 +210,7 @@ info LD vmlinux.o
modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
-${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
info MODINFO modules.builtin.modinfo
${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index f230e65329a2..3b638c0e1a4f 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -83,6 +83,17 @@ sub check_missing(%)
foreach my $prog (sort keys %missing) {
my $is_optional = $missing{$prog};
+ # At least on some LTS distros like CentOS 7, texlive doesn't
+ # provide all packages we need. When such distros are
+ # detected, we have to disable PDF output.
+ #
+ # So, we need to ignore the packages that distros would
+ # need for LaTeX to work
+ if ($is_optional == 2 && !$pdf) {
+ $optional--;
+ next;
+ }
+
if ($is_optional) {
print "Warning: better to also install \"$prog\".\n";
} else {
@@ -333,10 +344,13 @@ sub give_debian_hints()
if ($pdf) {
check_missing_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
- "fonts-dejavu", 1);
+ "fonts-dejavu", 2);
+
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+ "fonts-noto-cjk", 2);
}
- check_program("dvipng", 1) if ($pdf);
+ check_program("dvipng", 2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -363,6 +377,7 @@ sub give_redhat_hints()
my @fedora_tex_pkgs = (
"texlive-collection-fontsrecommended",
"texlive-collection-latex",
+ "texlive-xecjk",
"dejavu-sans-fonts",
"dejavu-serif-fonts",
"dejavu-sans-mono-fonts",
@@ -371,22 +386,45 @@ sub give_redhat_hints()
#
# Checks valid for RHEL/CentOS version 7.x.
#
- if (! $system_release =~ /Fedora/) {
+ my $old = 0;
+ my $rel;
+ $rel = $1 if ($system_release =~ /release\s+(\d+)/);
+
+ if (!($system_release =~ /Fedora/)) {
$map{"virtualenv"} = "python-virtualenv";
- }
- my $release;
+ if ($rel && $rel < 8) {
+ $old = 1;
+ $pdf = 0;
+
+ printf("Note: texlive packages on RHEL/CENTOS <= 7 are incomplete. Can't support PDF output\n");
+ printf("If you want to build PDF, please read:\n");
+ printf("\thttps://www.systutorials.com/241660/how-to-install-tex-live-on-centos-7-linux/\n");
+ }
+ } else {
+ if ($rel && $rel < 26) {
+ $old = 1;
+ }
+ }
+ if (!$rel) {
+ printf("Couldn't identify release number\n");
+ $old = 1;
+ $pdf = 0;
+ }
- $release = $1 if ($system_release =~ /Fedora\s+release\s+(\d+)/);
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+ "google-noto-sans-cjk-ttc-fonts", 2);
+ }
- check_rpm_missing(\@fedora26_opt_pkgs, 1) if ($pdf && $release >= 26);
- check_rpm_missing(\@fedora_tex_pkgs, 1) if ($pdf);
- check_missing_tex(1) if ($pdf);
+ check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old);
+ check_rpm_missing(\@fedora_tex_pkgs, 2) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
- if ($release >= 18) {
+ if (!$old) {
# dnf, for Fedora 18+
printf("You should run:\n\n\tsudo dnf install -y $install\n");
} else {
@@ -425,8 +463,15 @@ sub give_opensuse_hints()
"texlive-zapfding",
);
- check_rpm_missing(\@suse_tex_pkgs, 1) if ($pdf);
- check_missing_tex(1) if ($pdf);
+ $map{"latexmk"} = "texlive-latexmk-bin";
+
+ # FIXME: add support for installing CJK fonts
+ #
+ # I tried hard, but was unable to find a way to install
+ # "Noto Sans CJK SC" on openSUSE
+
+ check_rpm_missing(\@suse_tex_pkgs, 2) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -450,7 +495,14 @@ sub give_mageia_hints()
"texlive-fontsextra",
);
- check_rpm_missing(\@tex_pkgs, 1) if ($pdf);
+ $map{"latexmk"} = "texlive-collection-basic";
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+ "google-noto-sans-cjk-ttc-fonts", 2);
+ }
+
+ check_rpm_missing(\@tex_pkgs, 2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -473,7 +525,13 @@ sub give_arch_linux_hints()
"texlive-latexextra",
"ttf-dejavu",
);
- check_pacman_missing(\@archlinux_tex_pkgs, 1) if ($pdf);
+ check_pacman_missing(\@archlinux_tex_pkgs, 2) if ($pdf);
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+ "noto-fonts-cjk", 2);
+ }
+
check_missing(\%map);
return if (!$need && !$optional);
@@ -492,15 +550,31 @@ sub give_gentoo_hints()
);
check_missing_file("/usr/share/fonts/dejavu/DejaVuSans.ttf",
- "media-fonts/dejavu", 1) if ($pdf);
+ "media-fonts/dejavu", 2) if ($pdf);
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
+ "media-fonts/noto-cjk", 2);
+ }
check_missing(\%map);
return if (!$need && !$optional);
printf("You should run:\n\n");
- printf("\tsudo su -c 'echo \"media-gfx/imagemagick svg png\" > /etc/portage/package.use/imagemagick'\n");
- printf("\tsudo su -c 'echo \"media-gfx/graphviz cairo pdf\" > /etc/portage/package.use/graphviz'\n");
+
+ my $imagemagick = "media-gfx/imagemagick svg png";
+ my $cairo = "media-gfx/graphviz cairo pdf";
+ my $portage_imagemagick = "/etc/portage/package.use/imagemagick";
+ my $portage_cairo = "/etc/portage/package.use/graphviz";
+
+ if (qx(cat $portage_imagemagick) ne "$imagemagick\n") {
+ printf("\tsudo su -c 'echo \"$imagemagick\" > $portage_imagemagick'\n")
+ }
+ if (qx(cat $portage_cairo) ne "$cairo\n") {
+ printf("\tsudo su -c 'echo \"$cairo\" > $portage_cairo'\n");
+ }
+
printf("\tsudo emerge --ask $install\n");
}
@@ -560,7 +634,7 @@ sub check_distros()
my %map = (
"sphinx-build" => "sphinx"
);
- check_missing_tex(1) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
print "I don't know distro $system_release.\n";
print "So, I can't provide you a hint with the install procedure.\n";
@@ -589,11 +663,13 @@ sub check_needs()
check_program("make", 0);
check_program("gcc", 0);
check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv);
- check_program("xelatex", 1) if ($pdf);
check_program("dot", 1);
check_program("convert", 1);
- check_program("rsvg-convert", 1) if ($pdf);
- check_program("latexmk", 1) if ($pdf);
+
+ # Extra PDF files - should use 2 for is_optional
+ check_program("xelatex", 2) if ($pdf);
+ check_program("rsvg-convert", 2) if ($pdf);
+ check_program("latexmk", 2) if ($pdf);
check_distros();
diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh
new file mode 100755
index 000000000000..97a2c844a95e
--- /dev/null
+++ b/scripts/tools-support-relr.sh
@@ -0,0 +1,16 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0
+
+tmp_file=$(mktemp)
+trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
+
+cat << "END" | "$CC" -c -x c - -o $tmp_file.o >/dev/null 2>&1
+void *p = &p;
+END
+"$LD" $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file
+
+# Despite printing an error message, GNU nm still exits with exit code 0 if it
+# sees a relr section. So we need to check that nothing is printed to stderr.
+test -z "$("$NM" $tmp_file 2>&1 >/dev/null)"
+
+"$OBJCOPY" -O binary $tmp_file $tmp_file.bin
diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
index a1ffe2eb4d5f..af4c979b38ee 100644
--- a/security/Kconfig.hardening
+++ b/security/Kconfig.hardening
@@ -61,6 +61,7 @@ choice
config GCC_PLUGIN_STRUCTLEAK_BYREF
bool "zero-init structs passed by reference (strong)"
depends on GCC_PLUGINS
+ depends on !(KASAN && KASAN_STACK=1)
select GCC_PLUGIN_STRUCTLEAK
help
Zero-initialize any structures on the stack that may
@@ -70,9 +71,15 @@ choice
exposures, like CVE-2017-1000410:
https://git.kernel.org/linus/06e7e776ca4d3654
+ As a side-effect, this keeps a lot of variables on the
+ stack that can otherwise be optimized out, so combining
+ this with CONFIG_KASAN_STACK can lead to a stack overflow
+ and is disallowed.
+
config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
bool "zero-init anything passed by reference (very strong)"
depends on GCC_PLUGINS
+ depends on !(KASAN && KASAN_STACK=1)
select GCC_PLUGIN_STRUCTLEAK
help
Zero-initialize any stack variables that may be passed
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 7325f382dbf4..957b9e3e1492 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -595,7 +595,7 @@ struct key *request_key_and_link(struct key_type *type,
key = check_cached_key(&ctx);
if (key)
- return key;
+ goto error_free;
/* search all the process keyrings for a key */
rcu_read_lock();
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index e73ec040e250..ecba39c93fd9 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -66,6 +66,9 @@ static void request_key_auth_describe(const struct key *key,
{
struct request_key_auth *rka = dereference_key_rcu(key);
+ if (!rka)
+ return;
+
seq_puts(m, "key:");
seq_puts(m, key->description);
if (key_is_positive(key))
@@ -83,6 +86,9 @@ static long request_key_auth_read(const struct key *key,
size_t datalen;
long ret;
+ if (!rka)
+ return -EKEYREVOKED;
+
datalen = rka->callout_len;
ret = datalen;
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 9a94672e7adc..ade699131065 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -1228,24 +1228,11 @@ hashalg_fail:
static int __init init_digests(void)
{
- u8 digest[TPM_MAX_DIGEST_SIZE];
- int ret;
- int i;
-
- ret = tpm_get_random(chip, digest, TPM_MAX_DIGEST_SIZE);
- if (ret < 0)
- return ret;
- if (ret < TPM_MAX_DIGEST_SIZE)
- return -EFAULT;
-
digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),
GFP_KERNEL);
if (!digests)
return -ENOMEM;
- for (i = 0; i < chip->nr_allocated_banks; i++)
- memcpy(digests[i].digest, digest, TPM_MAX_DIGEST_SIZE);
-
return 0;
}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 624ccc6ac744..f8efaa9f647c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -272,6 +272,8 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
return v;
}
+static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap);
+
/*
* Initialize a policy database structure.
*/
@@ -319,8 +321,10 @@ static int policydb_init(struct policydb *p)
out:
hashtab_destroy(p->filename_trans);
hashtab_destroy(p->range_tr);
- for (i = 0; i < SYM_NUM; i++)
+ for (i = 0; i < SYM_NUM; i++) {
+ hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
hashtab_destroy(p->symtab[i].table);
+ }
return rc;
}
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index e63a90ff2728..1f0a6eaa2d6a 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -286,6 +286,11 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context,
++count;
}
+ /* bail out if we already reached max entries */
+ rc = -EOVERFLOW;
+ if (count >= SIDTAB_MAX)
+ goto out_unlock;
+
/* insert context into new entry */
rc = -ENOMEM;
dst = sidtab_do_lookup(s, count, 1);
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 7b977b753a03..7985dd8198b6 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -122,17 +122,12 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
vendor_id);
ret = device_add(&codec->dev);
- if (ret)
- goto err_free_codec;
+ if (ret) {
+ put_device(&codec->dev);
+ return ret;
+ }
return 0;
-err_free_codec:
- of_node_put(codec->dev.of_node);
- put_device(&codec->dev);
- kfree(codec);
- ac97_ctrl->codecs[idx] = NULL;
-
- return ret;
}
unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 99b882158705..41905afada63 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -574,10 +574,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
stream->metadata_set = false;
stream->next_track = false;
- if (stream->direction == SND_COMPRESS_PLAYBACK)
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- else
- stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
} else {
return -EPERM;
}
@@ -693,8 +690,17 @@ static int snd_compr_start(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_SETUP:
+ if (stream->direction != SND_COMPRESS_CAPTURE)
+ return -EPERM;
+ break;
+ case SNDRV_PCM_STATE_PREPARED:
+ break;
+ default:
return -EPERM;
+ }
+
retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
if (!retval)
stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
@@ -705,9 +711,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_SETUP:
+ case SNDRV_PCM_STATE_PREPARED:
return -EPERM;
+ default:
+ break;
+ }
+
retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
if (!retval) {
snd_compr_drain_notify(stream);
@@ -795,9 +807,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_SETUP:
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
return -EPERM;
+ case SNDRV_PCM_STATE_XRUN:
+ return -EPIPE;
+ default:
+ break;
+ }
retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
if (retval) {
@@ -817,6 +837,10 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
return -EPERM;
+ /* next track doesn't have any meaning for capture streams */
+ if (stream->direction == SND_COMPRESS_CAPTURE)
+ return -EPERM;
+
/* you can signal next track if this is intended to be a gapless stream
* and current track metadata is set
*/
@@ -834,9 +858,23 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
static int snd_compr_partial_drain(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_SETUP:
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
+ return -EPERM;
+ case SNDRV_PCM_STATE_XRUN:
+ return -EPIPE;
+ default:
+ break;
+ }
+
+ /* partial drain doesn't have any meaning for capture streams */
+ if (stream->direction == SND_COMPRESS_CAPTURE)
return -EPERM;
+
/* stream can be drained only when next track has been signalled */
if (stream->next_track == false)
return -EPERM;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 860543a4c840..703857aab00f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -77,7 +77,7 @@ void snd_pcm_group_init(struct snd_pcm_group *group)
spin_lock_init(&group->lock);
mutex_init(&group->mutex);
INIT_LIST_HEAD(&group->substreams);
- refcount_set(&group->refs, 0);
+ refcount_set(&group->refs, 1);
}
/* define group lock helpers */
@@ -1096,8 +1096,7 @@ static void snd_pcm_group_unref(struct snd_pcm_group *group,
if (!group)
return;
- do_free = refcount_dec_and_test(&group->refs) &&
- list_empty(&group->substreams);
+ do_free = refcount_dec_and_test(&group->refs);
snd_pcm_group_unlock(group, substream->pcm->nonatomic);
if (do_free)
kfree(group);
@@ -1874,6 +1873,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
if (!to_check)
break; /* all drained */
init_waitqueue_entry(&wait, current);
+ set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&to_check->sleep, &wait);
snd_pcm_stream_unlock_irq(substream);
if (runtime->no_period_wakeup)
@@ -1886,7 +1886,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
}
tout = msecs_to_jiffies(tout * 1000);
}
- tout = schedule_timeout_interruptible(tout);
+ tout = schedule_timeout(tout);
snd_pcm_stream_lock_irq(substream);
group = snd_pcm_stream_group_ref(substream);
@@ -2020,6 +2020,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
snd_pcm_group_lock_irq(target_group, nonatomic);
snd_pcm_stream_lock(substream1);
snd_pcm_group_assign(substream1, target_group);
+ refcount_inc(&target_group->refs);
snd_pcm_stream_unlock(substream1);
snd_pcm_group_unlock_irq(target_group, nonatomic);
_end:
@@ -2056,13 +2057,14 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
snd_pcm_group_lock_irq(group, nonatomic);
relink_to_local(substream);
+ refcount_dec(&group->refs);
/* detach the last stream, too */
if (list_is_singular(&group->substreams)) {
relink_to_local(list_first_entry(&group->substreams,
struct snd_pcm_substream,
link_list));
- do_free = !refcount_read(&group->refs);
+ do_free = refcount_dec_and_test(&group->refs);
}
snd_pcm_group_unlock_irq(group, nonatomic);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 7737b2670064..6d9592f0ae1d 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1835,8 +1835,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
if (cptr->type == USER_CLIENT) {
info->input_pool = cptr->data.user.fifo_pool_size;
info->input_free = info->input_pool;
- if (cptr->data.user.fifo)
- info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
+ info->input_free = snd_seq_fifo_unused_cells(cptr->data.user.fifo);
} else {
info->input_pool = 0;
info->input_free = 0;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index ea69261f269a..eaaa8b5830bb 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -263,3 +263,20 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
return 0;
}
+
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f)
+{
+ unsigned long flags;
+ int cells;
+
+ if (!f)
+ return 0;
+
+ snd_use_lock_use(&f->use_lock);
+ spin_lock_irqsave(&f->lock, flags);
+ cells = snd_seq_unused_cells(f->pool);
+ spin_unlock_irqrestore(&f->lock, flags);
+ snd_use_lock_free(&f->use_lock);
+ return cells;
+}
diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h
index edc68743943d..b56a7b897c9c 100644
--- a/sound/core/seq/seq_fifo.h
+++ b/sound/core/seq/seq_fifo.h
@@ -53,5 +53,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table
/* resize pool in fifo */
int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize);
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f);
#endif
diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c
index 9ea39348cdf5..7c6d1c277d4d 100644
--- a/sound/firewire/oxfw/oxfw-pcm.c
+++ b/sound/firewire/oxfw/oxfw-pcm.c
@@ -248,7 +248,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
unsigned int channels = params_channels(hw_params);
mutex_lock(&oxfw->mutex);
- err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
+ err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
rate, channels);
if (err >= 0)
++oxfw->substreams_count;
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
index 0d35359d25cd..0ecafd0c6722 100644
--- a/sound/firewire/packets-buffer.c
+++ b/sound/firewire/packets-buffer.c
@@ -37,7 +37,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
packets_per_page = PAGE_SIZE / packet_size;
if (WARN_ON(!packets_per_page)) {
err = -EINVAL;
- goto error;
+ goto err_packets;
}
pages = DIV_ROUND_UP(count, packets_per_page);
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 1192c7561d62..3c2db3816029 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -136,10 +136,12 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
if (!acomp)
return -ENODEV;
if (!acomp->ops) {
- request_module("i915");
- /* 60s timeout */
- wait_for_completion_timeout(&bind_complete,
- msecs_to_jiffies(60 * 1000));
+ if (!IS_ENABLED(CONFIG_MODULES) ||
+ !request_module("i915")) {
+ /* 60s timeout */
+ wait_for_completion_timeout(&bind_complete,
+ msecs_to_jiffies(60 * 1000));
+ }
}
if (!acomp->ops) {
dev_info(bus->dev, "couldn't bind with audio component\n");
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 92390d457567..18e6546b4467 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -824,6 +824,8 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
while (id >= 0) {
const struct hda_fixup *fix = codec->fixup_list + id;
+ if (++depth > 10)
+ break;
if (fix->chained_before)
apply_fixup(codec, fix->chain_id, action, depth + 1);
@@ -863,8 +865,6 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
}
if (!fix->chained || fix->chained_before)
break;
- if (++depth > 10)
- break;
id = fix->chain_id;
}
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e30e86ca6b72..51f10ed9bc43 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2942,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev)
static int hda_codec_force_resume(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
- bool forced_resume = !codec->relaxed_resume;
+ bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used;
int ret;
/* The get/put pair below enforces the runtime resume even if the
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index c8d1b4316245..48d863736b3c 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -598,11 +598,9 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
}
runtime->private_data = azx_dev;
- if (chip->gts_present)
- azx_pcm_hw.info = azx_pcm_hw.info |
- SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
-
runtime->hw = azx_pcm_hw;
+ if (chip->gts_present)
+ runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
runtime->hw.channels_min = hinfo->channels_min;
runtime->hw.channels_max = hinfo->channels_max;
runtime->hw.formats = hinfo->formats;
@@ -615,6 +613,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
20,
178000000);
+ /* by some reason, the playback stream stalls on PulseAudio with
+ * tsched=1 when a capture stream triggers. Until we figure out the
+ * real cause, disable tsched mode by telling the PCM info flag.
+ */
+ if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND)
+ runtime->hw.info |= SNDRV_PCM_INFO_BATCH;
+
if (chip->align_buffer_size)
/* constrain buffer sizes to be multiple of 128
bytes. This is more efficient in terms of memory
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index baa15374fbcb..f2a6df5e6bcb 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -31,7 +31,7 @@
/* 14 unused */
#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
-/* 17 unused */
+#define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */
#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 485edaba0037..10d502328b76 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -6009,7 +6009,8 @@ int snd_hda_gen_init(struct hda_codec *codec)
if (spec->init_hook)
spec->init_hook(codec);
- snd_hda_apply_verbs(codec);
+ if (!spec->skip_verbs)
+ snd_hda_apply_verbs(codec);
init_multi_out(codec);
init_extra_out(codec);
@@ -6051,6 +6052,24 @@ void snd_hda_gen_free(struct hda_codec *codec)
}
EXPORT_SYMBOL_GPL(snd_hda_gen_free);
+/**
+ * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
+ * @codec: the HDA codec
+ *
+ * This can be put as patch_ops reboot_notify function.
+ */
+void snd_hda_gen_reboot_notify(struct hda_codec *codec)
+{
+ /* Make the codec enter D3 to avoid spurious noises from the internal
+ * speaker during (and after) reboot
+ */
+ snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+ snd_hda_codec_write(codec, codec->core.afg, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ msleep(10);
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
+
#ifdef CONFIG_PM
/**
* snd_hda_gen_check_power_status - check the loopback power save state
@@ -6078,6 +6097,7 @@ static const struct hda_codec_ops generic_patch_ops = {
.init = snd_hda_gen_init,
.free = snd_hda_gen_free,
.unsol_event = snd_hda_jack_unsol_event,
+ .reboot_notify = snd_hda_gen_reboot_notify,
#ifdef CONFIG_PM
.check_power_status = snd_hda_gen_check_power_status,
#endif
@@ -6100,7 +6120,7 @@ static int snd_hda_parse_generic_codec(struct hda_codec *codec)
err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
if (err < 0)
- return err;
+ goto error;
err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
if (err < 0)
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 35a670a71c42..fb9f1a90238b 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -243,6 +243,7 @@ struct hda_gen_spec {
unsigned int indep_hp_enabled:1; /* independent HP enabled */
unsigned int have_aamix_ctl:1;
unsigned int hp_mic_jack_modes:1;
+ unsigned int skip_verbs:1; /* don't apply verbs at snd_hda_gen_init() */
/* additional mute flags (only effective with auto_mute_via_amp=1) */
u64 mute_bits;
@@ -332,6 +333,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
struct auto_pin_cfg *cfg);
int snd_hda_gen_build_controls(struct hda_codec *codec);
int snd_hda_gen_build_pcms(struct hda_codec *codec);
+void snd_hda_gen_reboot_notify(struct hda_codec *codec);
/* standard jack event callbacks */
void snd_hda_gen_hp_automute(struct hda_codec *codec,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cb8b0945547c..99fc0917339b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -64,6 +64,7 @@ enum {
POS_FIX_VIACOMBO,
POS_FIX_COMBO,
POS_FIX_SKL,
+ POS_FIX_FIFO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -135,7 +136,7 @@ module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
MODULE_PARM_DESC(position_fix, "DMA pointer read method."
- "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+).");
+ "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
module_param_array(bdl_pos_adj, int, NULL, 0644);
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
module_param_array(probe_mask, int, NULL, 0444);
@@ -313,11 +314,10 @@ enum {
#define AZX_DCAPS_INTEL_SKYLAKE \
(AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
+ AZX_DCAPS_SYNC_WRITE |\
AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
-#define AZX_DCAPS_INTEL_BROXTON \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
- AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
+#define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -333,6 +333,11 @@ enum {
#define AZX_DCAPS_PRESET_ATI_HDMI_NS \
(AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
+/* quirks for AMD SB */
+#define AZX_DCAPS_PRESET_AMD_SB \
+ (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\
+ AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME)
+
/* quirks for Nvidia */
#define AZX_DCAPS_PRESET_NVIDIA \
(AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
@@ -842,6 +847,49 @@ static unsigned int azx_via_get_position(struct azx *chip,
return bound_pos + mod_dma_pos;
}
+#define AMD_FIFO_SIZE 32
+
+/* get the current DMA position with FIFO size correction */
+static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
+{
+ struct snd_pcm_substream *substream = azx_dev->core.substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int pos, delay;
+
+ pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
+ if (!runtime)
+ return pos;
+
+ runtime->delay = AMD_FIFO_SIZE;
+ delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
+ if (azx_dev->insufficient) {
+ if (pos < delay) {
+ delay = pos;
+ runtime->delay = bytes_to_frames(runtime, pos);
+ } else {
+ azx_dev->insufficient = 0;
+ }
+ }
+
+ /* correct the DMA position for capture stream */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (pos < delay)
+ pos += azx_dev->core.bufsize;
+ pos -= delay;
+ }
+
+ return pos;
+}
+
+static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
+ unsigned int pos)
+{
+ struct snd_pcm_substream *substream = azx_dev->core.substream;
+
+ /* just read back the calculated value in the above */
+ return substream->runtime->delay;
+}
+
static unsigned int azx_skl_get_dpib_pos(struct azx *chip,
struct azx_dev *azx_dev)
{
@@ -1418,6 +1466,7 @@ static int check_position_fix(struct azx *chip, int fix)
case POS_FIX_VIACOMBO:
case POS_FIX_COMBO:
case POS_FIX_SKL:
+ case POS_FIX_FIFO:
return fix;
}
@@ -1434,6 +1483,10 @@ static int check_position_fix(struct azx *chip, int fix)
dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
return POS_FIX_VIACOMBO;
}
+ if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
+ dev_dbg(chip->card->dev, "Using FIFO position fix\n");
+ return POS_FIX_FIFO;
+ }
if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
dev_dbg(chip->card->dev, "Using LPIB position fix\n");
return POS_FIX_LPIB;
@@ -1454,6 +1507,7 @@ static void assign_position_fix(struct azx *chip, int fix)
[POS_FIX_VIACOMBO] = azx_via_get_position,
[POS_FIX_COMBO] = azx_get_pos_lpib,
[POS_FIX_SKL] = azx_get_pos_skl,
+ [POS_FIX_FIFO] = azx_get_pos_fifo,
};
chip->get_position[0] = chip->get_position[1] = callbacks[fix];
@@ -1468,6 +1522,9 @@ static void assign_position_fix(struct azx *chip, int fix)
azx_get_delay_from_lpib;
}
+ if (fix == POS_FIX_FIFO)
+ chip->get_delay[0] = chip->get_delay[1] =
+ azx_get_delay_from_fifo;
}
/*
@@ -2448,6 +2505,12 @@ static const struct pci_device_id azx_ids[] = {
/* AMD Hudson */
{ PCI_DEVICE(0x1022, 0x780d),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
+ /* AMD, X370 & co */
+ { PCI_DEVICE(0x1022, 0x1457),
+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
+ /* AMD, X570 & co */
+ { PCI_DEVICE(0x1022, 0x1487),
+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
/* AMD Stoney */
{ PCI_DEVICE(0x1022, 0x157a),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 0d51823d7270..6d1fb7c11f17 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -1175,6 +1175,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
+ SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 4f8d0845ee1e..968d3caab6ac 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -163,23 +163,10 @@ static void cx_auto_reboot_notify(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- switch (codec->core.vendor_id) {
- case 0x14f12008: /* CX8200 */
- case 0x14f150f2: /* CX20722 */
- case 0x14f150f4: /* CX20724 */
- break;
- default:
- return;
- }
-
/* Turn the problematic codec into D3 to avoid spurious noises
from the internal speaker during (and after) reboot */
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-
- snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- msleep(10);
+ snd_hda_gen_reboot_notify(codec);
}
static void cx_auto_free(struct hda_codec *codec)
@@ -624,18 +611,20 @@ static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
/* update LED status via GPIO */
static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask,
- bool enabled)
+ bool led_on)
{
struct conexant_spec *spec = codec->spec;
unsigned int oldval = spec->gpio_led;
if (spec->mute_led_polarity)
- enabled = !enabled;
+ led_on = !led_on;
- if (enabled)
- spec->gpio_led &= ~mask;
- else
+ if (led_on)
spec->gpio_led |= mask;
+ else
+ spec->gpio_led &= ~mask;
+ codec_dbg(codec, "mask:%d enabled:%d gpio_led:%d\n",
+ mask, led_on, spec->gpio_led);
if (spec->gpio_led != oldval)
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
spec->gpio_led);
@@ -646,8 +635,8 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
{
struct hda_codec *codec = private_data;
struct conexant_spec *spec = codec->spec;
-
- cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled);
+ /* muted -> LED on */
+ cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, !enabled);
}
/* turn on/off mic-mute LED via GPIO per capture hook */
@@ -669,7 +658,6 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03 },
{}
};
- codec_info(codec, "action: %d gpio_led: %d\n", action, spec->gpio_led);
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
@@ -1083,6 +1071,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
*/
static const struct hda_device_id snd_hda_id_conexant[] = {
+ HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index de224cbea7a0..c1ddfd2fac52 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -837,9 +837,11 @@ static int alc_init(struct hda_codec *codec)
if (spec->init_hook)
spec->init_hook(codec);
+ spec->gen.skip_verbs = 1; /* applied in below */
snd_hda_gen_init(codec);
alc_fix_pll(codec);
alc_auto_init_amp(codec, spec->init_amp);
+ snd_hda_apply_verbs(codec); /* apply verbs here after own init */
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
@@ -869,15 +871,6 @@ static void alc_reboot_notify(struct hda_codec *codec)
alc_shutup(codec);
}
-/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
-static void alc_d3_at_reboot(struct hda_codec *codec)
-{
- snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- msleep(10);
-}
-
#define alc_free snd_hda_gen_free
#ifdef CONFIG_PM
@@ -5152,7 +5145,7 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
+ spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
codec->power_save_node = 0; /* avoid click noises */
snd_hda_apply_pincfgs(codec, pincfgs);
@@ -5806,6 +5799,7 @@ enum {
ALC286_FIXUP_ACER_AIO_HEADSET_MIC,
ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
ALC299_FIXUP_PREDATOR_SPK,
+ ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -6846,6 +6840,16 @@ static const struct hda_fixup alc269_fixups[] = {
{ }
}
},
+ [ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x14, 0x411111f0 }, /* disable confusing internal speaker */
+ { 0x19, 0x04a11150 }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6987,6 +6991,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -7003,6 +7009,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
@@ -7080,6 +7087,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x312a, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
+ SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@ -8954,6 +8962,7 @@ static int patch_alc680(struct hda_codec *codec)
static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index a4ade6bb5beb..bc4dfafdfcd1 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -31,8 +31,8 @@ struct i2s_stream_instance {
u16 num_pages;
u16 channels;
u32 xfer_resolution;
- struct page *pg;
u64 bytescount;
+ dma_addr_t dma_addr;
void __iomem *acp3x_base;
};
@@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
{
u16 page_idx;
- u64 addr;
u32 low, high, val, acp_fifo_addr;
- struct page *pg = rtd->pg;
+ dma_addr_t addr = rtd->dma_addr;
/* 8 scratch registers used to map one 64 bit address */
if (direction == SNDRV_PCM_STREAM_PLAYBACK)
@@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
/* Load the low address of page int ACP SRAM through SRBM */
- addr = page_to_phys(pg);
low = lower_32_bits(addr);
high = upper_32_bits(addr);
@@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
+ 4);
/* Move to next physically contiguos page */
val += 8;
- pg++;
+ addr += PAGE_SIZE;
}
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
{
int status;
u64 size;
- struct page *pg;
struct snd_pcm_runtime *runtime = substream->runtime;
struct i2s_stream_instance *rtd = runtime->private_data;
@@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
return status;
memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
- pg = virt_to_page(substream->dma_buffer.area);
- if (pg) {
- rtd->pg = pg;
+ if (substream->dma_buffer.area) {
+ rtd->dma_addr = substream->dma_buffer.addr;
rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
config_acp3x_dma(rtd, substream->stream);
status = 0;
@@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
+ DRV_NAME);
+ struct device *parent = component->dev->parent;
snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
- rtd->pcm->card->dev,
- MIN_BUFFER, MAX_BUFFER);
+ parent, MIN_BUFFER, MAX_BUFFER);
return 0;
}
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index 6203f54d9f25..5b049fcdba20 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -47,6 +47,7 @@ struct cs42xx8_priv {
unsigned long sysclk;
u32 tx_channels;
struct gpio_desc *gpiod_reset;
+ u32 rate[2];
};
/* -127.5dB to 0dB with step of 0.5dB */
@@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
};
struct cs42xx8_ratios {
- unsigned int ratio;
- unsigned char speed;
- unsigned char mclk;
+ unsigned int mfreq;
+ unsigned int min_mclk;
+ unsigned int max_mclk;
+ unsigned int ratio[3];
};
+/*
+ * According to reference mannual, define the cs42xx8_ratio struct
+ * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM |
+ * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 |
+ * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 |
+ * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 |
+ * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 |
+ * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 |
+ */
static const struct cs42xx8_ratios cs42xx8_ratios[] = {
- { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
- { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
- { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
- { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
- { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
- { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
- { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
- { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
- { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+ { 0, 1029000, 12800000, {256, 128, 64} },
+ { 2, 1536000, 19200000, {384, 192, 96} },
+ { 4, 2048000, 25600000, {512, 256, 128} },
+ { 6, 3072000, 38400000, {768, 384, 192} },
+ { 8, 4096000, 51200000, {1024, 512, 256} },
};
static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component;
struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- u32 ratio = cs42xx8->sysclk / params_rate(params);
- u32 i, fm, val, mask;
+ u32 ratio[2];
+ u32 rate[2];
+ u32 fm[2];
+ u32 i, val, mask;
+ bool condition1, condition2;
if (tx)
cs42xx8->tx_channels = params_channels(params);
+ rate[tx] = params_rate(params);
+ rate[!tx] = cs42xx8->rate[!tx];
+
+ ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0;
+ ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0;
+
+ /* Get functional mode for tx and rx according to rate */
+ for (i = 0; i < 2; i++) {
+ if (cs42xx8->slave_mode) {
+ fm[i] = CS42XX8_FM_AUTO;
+ } else {
+ if (rate[i] < 50000) {
+ fm[i] = CS42XX8_FM_SINGLE;
+ } else if (rate[i] > 50000 && rate[i] < 100000) {
+ fm[i] = CS42XX8_FM_DOUBLE;
+ } else if (rate[i] > 100000 && rate[i] < 200000) {
+ fm[i] = CS42XX8_FM_QUAD;
+ } else {
+ dev_err(component->dev,
+ "unsupported sample rate\n");
+ return -EINVAL;
+ }
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
- if (cs42xx8_ratios[i].ratio == ratio)
+ /* Is the ratio[tx] valid ? */
+ condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ?
+ (cs42xx8_ratios[i].ratio[0] == ratio[tx] ||
+ cs42xx8_ratios[i].ratio[1] == ratio[tx] ||
+ cs42xx8_ratios[i].ratio[2] == ratio[tx]) :
+ (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) &&
+ cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
+ cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk;
+
+ if (!ratio[tx])
+ condition1 = true;
+
+ /* Is the ratio[!tx] valid ? */
+ condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ?
+ (cs42xx8_ratios[i].ratio[0] == ratio[!tx] ||
+ cs42xx8_ratios[i].ratio[1] == ratio[!tx] ||
+ cs42xx8_ratios[i].ratio[2] == ratio[!tx]) :
+ (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx]));
+
+ if (!ratio[!tx])
+ condition2 = true;
+
+ /*
+ * Both ratio[tx] and ratio[!tx] is valid, then we get
+ * a proper MFreq.
+ */
+ if (condition1 && condition2)
break;
}
@@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- mask = CS42XX8_FUNCMOD_MFREQ_MASK;
- val = cs42xx8_ratios[i].mclk;
+ cs42xx8->rate[tx] = params_rate(params);
- fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+ mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+ val = cs42xx8_ratios[i].mfreq;
regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
- CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
+ CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val);
+
+ return 0;
+}
+
+static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ /* Clear stored rate */
+ cs42xx8->rate[tx] = 0;
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+ CS42XX8_FUNCMOD_xC_FM_MASK(tx),
+ CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
return 0;
}
@@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
.set_fmt = cs42xx8_set_dai_fmt,
.set_sysclk = cs42xx8_set_dai_sysclk,
.hw_params = cs42xx8_hw_params,
+ .hw_free = cs42xx8_hw_free,
.digital_mute = cs42xx8_digital_mute,
};
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 6f0e28f903bf..16313b973eaa 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -20,20 +20,10 @@
#include <sound/soc-dapm.h>
struct max98357a_priv {
- struct delayed_work enable_sdmode_work;
struct gpio_desc *sdmode;
unsigned int sdmode_delay;
};
-static void max98357a_enable_sdmode_work(struct work_struct *work)
-{
- struct max98357a_priv *max98357a =
- container_of(work, struct max98357a_priv,
- enable_sdmode_work.work);
-
- gpiod_set_value(max98357a->sdmode, 1);
-}
-
static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- queue_delayed_work(system_power_efficient_wq,
- &max98357a->enable_sdmode_work,
- msecs_to_jiffies(max98357a->sdmode_delay));
+ mdelay(max98357a->sdmode_delay);
+ gpiod_set_value(max98357a->sdmode, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- cancel_delayed_work_sync(&max98357a->enable_sdmode_work);
gpiod_set_value(max98357a->sdmode, 0);
break;
}
@@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev)
int ret;
max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL);
-
if (!max98357a)
return -ENOMEM;
max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev,
"sdmode", GPIOD_OUT_LOW);
-
if (IS_ERR(max98357a->sdmode))
return PTR_ERR(max98357a->sdmode);
ret = device_property_read_u32(&pdev->dev, "sdmode-delay",
&max98357a->sdmode_delay);
-
if (ret) {
max98357a->sdmode_delay = 0;
dev_dbg(&pdev->dev,
- "no optional property 'sdmode-delay' found, default: no delay\n");
+ "no optional property 'sdmode-delay' found, "
+ "default: no delay\n");
}
dev_set_drvdata(&pdev->dev, max98357a);
- INIT_DELAYED_WORK(&max98357a->enable_sdmode_work,
- max98357a_enable_sdmode_work);
-
return devm_snd_soc_register_component(&pdev->dev,
&max98357a_component_driver,
&max98357a_dai_driver, 1);
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c
index 528695cd6a1c..8c601a3ebc27 100644
--- a/sound/soc/codecs/max98373.c
+++ b/sound/soc/codecs/max98373.c
@@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
case 48000:
sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
break;
+ case 88200:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_88200;
+ break;
+ case 96000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_96000;
+ break;
default:
dev_err(component->dev, "rate %d not supported\n",
params_rate(params));
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h
index f6a37aa02f26..a59e51355a84 100644
--- a/sound/soc/codecs/max98373.h
+++ b/sound/soc/codecs/max98373.h
@@ -130,6 +130,8 @@
#define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
#define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
#define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
+#define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0)
+#define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0)
/* MAX98373_R2028_PCM_SR_SETUP_2 */
#define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c
index cdc8314882bc..abcdeb922201 100644
--- a/sound/soc/codecs/pcm3060-i2c.c
+++ b/sound/soc/codecs/pcm3060-i2c.c
@@ -2,7 +2,7 @@
//
// PCM3060 I2C driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
#include <linux/i2c.h>
#include <linux/module.h>
@@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
module_i2c_driver(pcm3060_i2c_driver);
MODULE_DESCRIPTION("PCM3060 I2C driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c
index f6f19fa80932..3b79734b832b 100644
--- a/sound/soc/codecs/pcm3060-spi.c
+++ b/sound/soc/codecs/pcm3060-spi.c
@@ -2,7 +2,7 @@
//
// PCM3060 SPI driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
#include <linux/module.h>
#include <linux/spi/spi.h>
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
module_spi_driver(pcm3060_spi_driver);
MODULE_DESCRIPTION("PCM3060 SPI driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c
index 32b26f1c2282..b2358069cf9b 100644
--- a/sound/soc/codecs/pcm3060.c
+++ b/sound/soc/codecs/pcm3060.c
@@ -2,7 +2,7 @@
//
// PCM3060 codec driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
#include <linux/module.h>
#include <sound/pcm_params.h>
@@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev)
EXPORT_SYMBOL(pcm3060_probe);
MODULE_DESCRIPTION("PCM3060 codec driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h
index 75931c9a9d85..18d51e5dac2c 100644
--- a/sound/soc/codecs/pcm3060.h
+++ b/sound/soc/codecs/pcm3060.h
@@ -2,7 +2,7 @@
/*
* PCM3060 codec driver
*
- * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+ * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
*/
#ifndef _SND_SOC_PCM3060_H
diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c
index 5605b660f4bf..0a6ff13d76e1 100644
--- a/sound/soc/codecs/rt1011.c
+++ b/sound/soc/codecs/rt1011.c
@@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = {
{ RT1011_POWER_9, 0xa840 },
{ RT1011_ADC_SET_5, 0x0a20 },
- { RT1011_DAC_SET_2, 0xa232 },
+ { RT1011_DAC_SET_2, 0xa032 },
{ RT1011_ADC_SET_1, 0x2925 },
{ RT1011_SPK_PRO_DC_DET_1, 0xb00c },
@@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component,
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_2, 0x0000);
snd_soc_component_write(component,
- RT1011_SYSTEM_RESET_3, 0x0000);
+ RT1011_SYSTEM_RESET_3, 0x0001);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_1, 0x003f);
snd_soc_component_write(component,
diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c
index d673506c7c39..d673506c7c39 100755..100644
--- a/sound/soc/codecs/rt1308.c
+++ b/sound/soc/codecs/rt1308.c
diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h
index c330aae1d527..c330aae1d527 100755..100644
--- a/sound/soc/codecs/rt1308.h
+++ b/sound/soc/codecs/rt1308.h
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 30a4e8399ec3..288df245b2f0 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -63,6 +63,7 @@ static int graph_get_dai_id(struct device_node *ep)
struct device_node *endpoint;
struct of_endpoint info;
int i, id;
+ const u32 *reg;
int ret;
/* use driver specified DAI ID if exist */
@@ -83,8 +84,9 @@ static int graph_get_dai_id(struct device_node *ep)
return info.id;
node = of_get_parent(ep);
+ reg = of_get_property(node, "reg", NULL);
of_node_put(node);
- if (of_get_property(node, "reg", NULL))
+ if (reg)
return info.port;
}
node = of_graph_get_port_parent(ep);
@@ -208,10 +210,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
- of_node_put(ports);
- of_node_put(port);
- of_node_put(node);
-
if (li->cpu) {
int is_single_links = 0;
@@ -229,17 +227,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links);
if (ret)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link,
"fe.%s",
cpus->dai_name);
if (ret < 0)
- return ret;
+ goto out_put_node;
/* card->num_links includes Codec */
asoc_simple_canonicalize_cpu(dai_link, is_single_links);
@@ -263,17 +261,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_codec(ep, dai_link);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link,
"be.%s",
codecs->dai_name);
if (ret < 0)
- return ret;
+ goto out_put_node;
/* check "prefix" from top node */
snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -293,19 +291,23 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_tdm(ep, dai);
if (ret)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
NULL, &dai_link->dai_fmt);
if (ret < 0)
- return ret;
+ goto out_put_node;
dai_link->dpcm_playback = 1;
dai_link->dpcm_capture = 1;
dai_link->ops = &graph_ops;
dai_link->init = asoc_simple_dai_init;
- return 0;
+out_put_node:
+ of_node_put(ports);
+ of_node_put(port);
+ of_node_put(node);
+ return ret;
}
static int graph_dai_link_of(struct asoc_simple_priv *priv,
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index ac8678fe55ff..556b1a789629 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -349,6 +349,13 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link)
/* Assumes platform == cpu */
if (!dai_link->platforms->of_node)
dai_link->platforms->of_node = dai_link->cpus->of_node;
+
+ /*
+ * DPCM BE can be no platform.
+ * Alloced memory will be waste, but not leak.
+ */
+ if (!dai_link->platforms->of_node)
+ dai_link->num_platforms = 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform);
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index e5cde0d5e63c..ef849151ba56 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -124,8 +124,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
li->link++;
- of_node_put(node);
-
/* For single DAI link & old style of DT node */
if (is_top)
prefix = PREFIX;
@@ -147,17 +145,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
if (ret)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link,
"fe.%s",
cpus->dai_name);
if (ret < 0)
- return ret;
+ goto out_put_node;
asoc_simple_canonicalize_cpu(dai_link, is_single_links);
} else {
@@ -180,17 +178,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_codec(np, dai_link);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
if (ret < 0)
- return ret;
+ goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link,
"be.%s",
codecs->dai_name);
if (ret < 0)
- return ret;
+ goto out_put_node;
/* check "prefix" from top node */
snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -208,19 +206,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
ret = asoc_simple_parse_tdm(np, dai);
if (ret)
- return ret;
+ goto out_put_node;
ret = asoc_simple_parse_daifmt(dev, node, codec,
prefix, &dai_link->dai_fmt);
if (ret < 0)
- return ret;
+ goto out_put_node;
dai_link->dpcm_playback = 1;
dai_link->dpcm_capture = 1;
dai_link->ops = &simple_ops;
dai_link->init = asoc_simple_dai_init;
- return 0;
+out_put_node:
+ of_node_put(node);
+ return ret;
}
static int simple_dai_link_of(struct asoc_simple_priv *priv,
@@ -364,8 +364,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
goto error;
}
- of_node_put(codec);
-
/* get convert-xxx property */
memset(&adata, 0, sizeof(adata));
for_each_child_of_node(node, np)
@@ -387,11 +385,13 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
ret = func_noml(priv, np, codec, li, is_top);
if (ret < 0) {
+ of_node_put(codec);
of_node_put(np);
goto error;
}
}
+ of_node_put(codec);
node = of_get_next_child(top, node);
} while (!is_top && node);
diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
index 54ac2fd41925..67f06c95eec5 100644
--- a/sound/soc/intel/boards/bytcht_cx2072x.c
+++ b/sound/soc/intel/boards/bytcht_cx2072x.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/device.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index fac09be3cade..46612331f5ea 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -437,6 +437,14 @@ static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
/* Please keep this list alphabetically sorted */
static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
+ { /* Irbis NB41 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NB41"),
+ },
+ .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN2_MAP
+ | BYT_CHT_ES8316_JD_INVERTED),
+ },
{ /* Teclast X98 Plus II */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index 33eb72545be6..05db311b579e 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -12,6 +12,7 @@
*/
#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index 4977b5a65eb8..9d657421730a 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -8,6 +8,7 @@
* Mengdong Lin <mengdong.lin@intel.com>
*/
+#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 229e39586868..4a5adae1d785 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
+ * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
index b94b482ac34f..1cc801ba92eb 100644
--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration.
+ * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration.
*
* Copyright (c) 2017, Intel Corporation.
*/
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index b7f11f6be1cf..d0fb43c2b9f6 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration.
+ * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration.
*
* Copyright (c) 2017, Intel Corporation.
*/
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index c36c0aa4f683..771b0ef21051 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
+ * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index 616eb09e78a0..60dea358fa04 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration.
+ * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
index 68ae43f7b4b2..cc972d2ac691 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
@@ -2,7 +2,7 @@
// Copyright (c) 2018, Intel Corporation.
/*
- * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
+ * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
*
*/
diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
index d27853e7a369..34eb0baaa951 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
+ * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
*
* Copyright (c) 2017, Intel Corporation.
*/
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
index 0b430b9b3673..38977669b576 100644
--- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration.
+ * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index 4b331058e807..e200baa11011 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
+ * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
index 0c9c0edd35b3..42fa40a8d932 100644
--- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * soc-apci-intel-skl-match.c - tables and support for SKL ACPI enumeration.
+ * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration.
*
* Copyright (c) 2018, Intel Corporation.
*
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index f60a71990f66..ac75838bbfab 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -150,17 +150,17 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
link = data->dai_link;
- dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
- if (!dlc)
- return ERR_PTR(-ENOMEM);
+ for_each_child_of_node(node, np) {
+ dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+ if (!dlc)
+ return ERR_PTR(-ENOMEM);
- link->cpus = &dlc[0];
- link->platforms = &dlc[1];
+ link->cpus = &dlc[0];
+ link->platforms = &dlc[1];
- link->num_cpus = 1;
- link->num_platforms = 1;
+ link->num_cpus = 1;
+ link->num_platforms = 1;
- for_each_child_of_node(node, np) {
cpu = of_get_child_by_name(np, "cpu");
codec = of_get_child_by_name(np, "codec");
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 0a34d0eb8dba..88ebaf6e1880 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -326,7 +326,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
val |= I2S_CHN_4;
break;
case 2:
- case 1:
val |= I2S_CHN_2;
break;
default:
@@ -459,7 +458,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
},
.capture = {
.stream_name = "Capture",
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S8 |
@@ -659,7 +658,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
}
if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
- if (val >= 1 && val <= 8)
+ if (val >= 2 && val <= 8)
soc_dai->capture.channels_max = val;
}
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..782e534d4c0d 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -61,6 +61,37 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
};
+static int rk_jack_event(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+ struct snd_soc_dapm_context *dapm = &jack->card->dapm;
+
+ if (event & SND_JACK_MICROPHONE)
+ snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
+ else
+ snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct notifier_block rk_jack_nb = {
+ .notifier_call = rk_jack_event,
+};
+
+static int rk_init(struct snd_soc_pcm_runtime *runtime)
+{
+ /*
+ * The jack has already been created in the rk_98090_headset_init()
+ * function.
+ */
+ snd_soc_jack_notifier_register(&headset_jack, &rk_jack_nb);
+
+ return 0;
+}
+
static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -119,6 +150,7 @@ SND_SOC_DAILINK_DEFS(hifi,
static struct snd_soc_dai_link rk_dailink = {
.name = "max98090",
.stream_name = "Audio",
+ .init = rk_init,
.ops = &rk_aif1_ops,
/* set max98090 as slave */
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c
index dfb6e460e7eb..f0f5fa9c27d3 100644
--- a/sound/soc/samsung/odroid.c
+++ b/sound/soc/samsung/odroid.c
@@ -284,9 +284,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
}
of_node_put(cpu);
- of_node_put(codec);
if (ret < 0)
- return ret;
+ goto err_put_node;
ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link);
if (ret < 0)
@@ -309,7 +308,6 @@ static int odroid_audio_probe(struct platform_device *pdev)
ret = PTR_ERR(priv->clk_i2s_bus);
goto err_put_sclk;
}
- of_node_put(cpu_dai);
ret = devm_snd_soc_register_card(dev, card);
if (ret < 0) {
@@ -317,6 +315,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
goto err_put_clk_i2s;
}
+ of_node_put(cpu_dai);
+ of_node_put(codec);
return 0;
err_put_clk_i2s:
@@ -326,6 +326,8 @@ err_put_sclk:
err_put_cpu_dai:
of_node_put(cpu_dai);
snd_soc_of_put_dai_link_codecs(codec_link);
+err_put_node:
+ of_node_put(codec);
return ret;
}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index fd6eaae6c0ed..44f899b970c2 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1515,8 +1515,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
}
}
- if (dai_link->dai_fmt)
- snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+ if (dai_link->dai_fmt) {
+ ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+ if (ret)
+ return ret;
+ }
ret = soc_post_component_init(rtd, dai_link->name);
if (ret)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f013b24c050a..2790c00735f3 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1157,8 +1157,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
list_add_tail(&widget->work_list, list);
if (custom_stop_condition && custom_stop_condition(widget, dir)) {
- widget->endpoints[dir] = 1;
- return widget->endpoints[dir];
+ list = NULL;
+ custom_stop_condition = NULL;
}
if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {
@@ -1195,8 +1195,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
*
* Optionally, can be supplied with a function acting as a stopping condition.
* This function takes the dapm widget currently being examined and the walk
- * direction as an arguments, it should return true if the walk should be
- * stopped and false otherwise.
+ * direction as an arguments, it should return true if widgets from that point
+ * in the graph onwards should not be added to the widget list.
*/
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
struct list_head *list,
@@ -3706,6 +3706,8 @@ request_failed:
dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
w->name, ret);
+ kfree_const(w->sname);
+ kfree(w);
return ERR_PTR(ret);
}
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index f2b392998f20..ffd8d4394537 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -101,8 +101,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
/*
* This interrupt is not shared so no need to return IRQ_NONE.
*/
- dev_err_ratelimited(sdev->dev,
- "error: nothing to do in IRQ thread\n");
+ dev_dbg_ratelimited(sdev->dev,
+ "nothing to do in IPC IRQ thread\n");
}
/* re-enable IPC interrupt */
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c
index 50244b82600c..2ecba91f5219 100644
--- a/sound/soc/sof/intel/hda-ipc.c
+++ b/sound/soc/sof/intel/hda-ipc.c
@@ -224,8 +224,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
/*
* This interrupt is not shared so no need to return IRQ_NONE.
*/
- dev_err_ratelimited(sdev->dev,
- "error: nothing to do in IRQ thread\n");
+ dev_dbg_ratelimited(sdev->dev,
+ "nothing to do in IPC IRQ thread\n");
}
/* re-enable IPC interrupt */
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 9b2232908b65..7fa5c61169db 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -1002,8 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
.field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
- .get_sr = sun8i_i2s_get_sr_wss,
- .get_wss = sun8i_i2s_get_sr_wss,
+ .get_sr = sun4i_i2s_get_sr,
+ .get_wss = sun4i_i2s_get_wss,
};
static int sun4i_i2s_init_regmap_fields(struct device *dev,
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index ac59b509ead5..bc7bf15ed7a4 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -195,7 +195,7 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
{
u32 bit;
- for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
+ for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AMUTE) {
if (enable)
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
else
@@ -223,6 +223,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
if (mcasp_is_synchronous(mcasp)) {
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+ mcasp_set_clk_pdir(mcasp, true);
}
/* Activate serializer(s) */
@@ -1256,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
return ret;
}
+static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct davinci_mcasp_ruledata *rd = rule->private;
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_mask nfmt;
+ int i, slot_width;
+
+ snd_mask_none(&nfmt);
+ slot_width = rd->mcasp->slot_width;
+
+ for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+ if (snd_mask_test(fmt, i)) {
+ if (snd_pcm_format_width(i) <= slot_width) {
+ snd_mask_set(&nfmt, i);
+ }
+ }
+ }
+
+ return snd_mask_refine(fmt, &nfmt);
+}
+
static const unsigned int davinci_mcasp_dai_rates[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
88200, 96000, 176400, 192000,
@@ -1377,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
struct davinci_mcasp_ruledata *ruledata =
&mcasp->ruledata[substream->stream];
u32 max_channels = 0;
- int i, dir;
+ int i, dir, ret;
int tdm_slots = mcasp->tdm_slots;
/* Do not allow more then one stream per direction */
@@ -1406,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
max_channels++;
}
ruledata->serializers = max_channels;
+ ruledata->mcasp = mcasp;
max_channels *= tdm_slots;
/*
* If the already active stream has less channels than the calculated
@@ -1431,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
0, SNDRV_PCM_HW_PARAM_CHANNELS,
&mcasp->chconstr[substream->stream]);
- if (mcasp->slot_width)
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- 8, mcasp->slot_width);
+ if (mcasp->slot_width) {
+ /* Only allow formats require <= slot_width bits on the bus */
+ ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ davinci_mcasp_hw_rule_slot_width,
+ ruledata,
+ SNDRV_PCM_HW_PARAM_FORMAT, -1);
+ if (ret)
+ return ret;
+ }
/*
* If we rely on implicit BCLK divider setting we should
* set constraints based on what we can provide.
*/
if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
- int ret;
-
- ruledata->mcasp = mcasp;
-
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
davinci_mcasp_hw_rule_rate,
diff --git a/sound/sound_core.c b/sound/sound_core.c
index b730d97c4de6..90d118cd9164 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -275,7 +275,8 @@ retry:
goto retry;
}
spin_unlock(&sound_loader_lock);
- return -EBUSY;
+ r = -EBUSY;
+ goto fail;
}
}
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 71d5f540334a..4c12cc5b53fd 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -72,7 +72,7 @@ int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe)
struct usb_host_endpoint *ep;
ep = usb_pipe_endpoint(dev, pipe);
- if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+ if (!ep || usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
return -EINVAL;
return 0;
}
diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index 14fc1e1d5d13..c406497c5919 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -600,14 +600,13 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
hiface_pcm_out_urb_handler);
if (ret < 0)
- return ret;
+ goto error;
}
ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
if (ret < 0) {
- kfree(rt);
dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
- return ret;
+ goto error;
}
pcm->private_data = rt;
@@ -620,4 +619,10 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
chip->pcm = rt;
return 0;
+
+error:
+ for (i = 0; i < PCM_N_URBS; i++)
+ kfree(rt->out_urbs[i].buffer);
+ kfree(rt);
+ return ret;
}
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 2c03e0f6bf72..f70211e6b174 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -550,6 +550,15 @@ int line6_init_pcm(struct usb_line6 *line6,
line6pcm->volume_monitor = 255;
line6pcm->line6 = line6;
+ spin_lock_init(&line6pcm->out.lock);
+ spin_lock_init(&line6pcm->in.lock);
+ line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
+
+ line6->line6pcm = line6pcm;
+
+ pcm->private_data = line6pcm;
+ pcm->private_free = line6_cleanup_pcm;
+
line6pcm->max_packet_size_in =
usb_maxpacket(line6->usbdev,
usb_rcvisocpipe(line6->usbdev, ep_read), 0);
@@ -562,15 +571,6 @@ int line6_init_pcm(struct usb_line6 *line6,
return -EINVAL;
}
- spin_lock_init(&line6pcm->out.lock);
- spin_lock_init(&line6pcm->in.lock);
- line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
-
- line6->line6pcm = line6pcm;
-
- pcm->private_data = line6pcm;
- pcm->private_free = line6_cleanup_pcm;
-
err = line6_create_audio_out_urbs(line6pcm);
if (err < 0)
return err;
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index f0662bd4e50f..27bf61c177c0 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -368,7 +368,7 @@ static const struct line6_properties podhd_properties_table[] = {
.name = "POD HD500",
.capabilities = LINE6_CAP_PCM
| LINE6_CAP_HWMON,
- .altsetting = 1,
+ .altsetting = 0,
.ep_ctrl_r = 0x81,
.ep_ctrl_w = 0x01,
.ep_audio_r = 0x86,
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
index 0d24c72c155f..ed158f04de80 100644
--- a/sound/usb/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -244,5 +244,5 @@ static struct usb_driver variax_driver = {
module_usb_driver(variax_driver);
-MODULE_DESCRIPTION("Vairax Workbench USB driver");
+MODULE_DESCRIPTION("Variax Workbench USB driver");
MODULE_LICENSE("GPL");
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 7498b5191b68..eceab19766db 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -68,6 +68,7 @@ struct mixer_build {
unsigned char *buffer;
unsigned int buflen;
DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
+ DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
struct usb_audio_term oterm;
const struct usbmix_name_map *map;
const struct usbmix_selector_map *selector_map;
@@ -738,12 +739,13 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc)
{
int mu_channels;
- void *c;
if (desc->bLength < sizeof(*desc))
return -EINVAL;
if (!desc->bNrInPins)
return -EINVAL;
+ if (desc->bLength < sizeof(*desc) + desc->bNrInPins)
+ return -EINVAL;
switch (state->mixer->protocol) {
case UAC_VERSION_1:
@@ -759,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
break;
}
- if (!mu_channels)
- return 0;
-
- c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
- if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
- return 0; /* no bmControls -> skip */
-
return mu_channels;
}
@@ -773,16 +768,25 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
* parse the source unit recursively until it reaches to a terminal
* or a branched unit.
*/
-static int check_input_term(struct mixer_build *state, int id,
+static int __check_input_term(struct mixer_build *state, int id,
struct usb_audio_term *term)
{
int protocol = state->mixer->protocol;
int err;
void *p1;
+ unsigned char *hdr;
memset(term, 0, sizeof(*term));
- while ((p1 = find_audio_control_unit(state, id)) != NULL) {
- unsigned char *hdr = p1;
+ for (;;) {
+ /* a loop in the terminal chain? */
+ if (test_and_set_bit(id, state->termbitmap))
+ return -EINVAL;
+
+ p1 = find_audio_control_unit(state, id);
+ if (!p1)
+ break;
+
+ hdr = p1;
term->id = id;
if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
@@ -800,7 +804,7 @@ static int check_input_term(struct mixer_build *state, int id,
/* call recursively to verify that the
* referenced clock entity is valid */
- err = check_input_term(state, d->bCSourceID, term);
+ err = __check_input_term(state, d->bCSourceID, term);
if (err < 0)
return err;
@@ -834,7 +838,7 @@ static int check_input_term(struct mixer_build *state, int id,
case UAC2_CLOCK_SELECTOR: {
struct uac_selector_unit_descriptor *d = p1;
/* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
+ err = __check_input_term(state, d->baSourceID[0], term);
if (err < 0)
return err;
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -897,7 +901,7 @@ static int check_input_term(struct mixer_build *state, int id,
/* call recursively to verify that the
* referenced clock entity is valid */
- err = check_input_term(state, d->bCSourceID, term);
+ err = __check_input_term(state, d->bCSourceID, term);
if (err < 0)
return err;
@@ -948,7 +952,7 @@ static int check_input_term(struct mixer_build *state, int id,
case UAC3_CLOCK_SELECTOR: {
struct uac_selector_unit_descriptor *d = p1;
/* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
+ err = __check_input_term(state, d->baSourceID[0], term);
if (err < 0)
return err;
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -964,7 +968,7 @@ static int check_input_term(struct mixer_build *state, int id,
return -EINVAL;
/* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
+ err = __check_input_term(state, d->baSourceID[0], term);
if (err < 0)
return err;
@@ -982,6 +986,15 @@ static int check_input_term(struct mixer_build *state, int id,
return -ENODEV;
}
+
+static int check_input_term(struct mixer_build *state, int id,
+ struct usb_audio_term *term)
+{
+ memset(term, 0, sizeof(*term));
+ memset(state->termbitmap, 0, sizeof(state->termbitmap));
+ return __check_input_term(state, id, term);
+}
+
/*
* Feature Unit
*/
@@ -1988,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
* Mixer Unit
*/
+/* check whether the given in/out overflows bmMixerControls matrix */
+static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
+ int protocol, int num_ins, int num_outs)
+{
+ u8 *hdr = (u8 *)desc;
+ u8 *c = uac_mixer_unit_bmControls(desc, protocol);
+ size_t rest; /* remaining bytes after bmMixerControls */
+
+ switch (protocol) {
+ case UAC_VERSION_1:
+ default:
+ rest = 1; /* iMixer */
+ break;
+ case UAC_VERSION_2:
+ rest = 2; /* bmControls + iMixer */
+ break;
+ case UAC_VERSION_3:
+ rest = 6; /* bmControls + wMixerDescrStr */
+ break;
+ }
+
+ /* overflow? */
+ return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
+}
+
/*
* build a mixer unit control
*
@@ -2116,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
if (err < 0)
return err;
num_ins += iterm.channels;
+ if (mixer_bitmap_overflow(desc, state->mixer->protocol,
+ num_ins, num_outs))
+ break;
for (; ich < num_ins; ich++) {
int och, ich_has_controls = 0;
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 199fa157a411..27dcb3743690 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -1155,17 +1155,17 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
{
struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *cval;
- int unitid = 12; /* SamleRate ExtensionUnit ID */
+ int unitid = 12; /* SampleRate ExtensionUnit ID */
list_for_each_entry(mixer, &chip->mixer_list, list) {
- cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
- if (cval) {
+ if (mixer->id_elems[unitid]) {
+ cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
cval->control << 8,
samplerate_id);
snd_usb_mixer_notify_id(mixer, unitid);
+ break;
}
- break;
}
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 75b96929f76c..e4bbf79de956 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -339,6 +339,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
ep = 0x81;
ifnum = 2;
goto add_sync_ep_from_ifnum;
+ case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
ep = 0x81;
ifnum = 1;
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 7ee9d17d0143..e852c7fd6109 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1043,6 +1043,7 @@ found_clock:
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
if (!pd) {
+ kfree(fp->chmap);
kfree(fp->rate_table);
kfree(fp);
return NULL;
diff --git a/tools/Makefile b/tools/Makefile
index 68defd7ecf5d..7e42f7b8bfa7 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -10,6 +10,7 @@ help:
@echo 'Possible targets:'
@echo ''
@echo ' acpi - ACPI tools'
+ @echo ' bpf - misc BPF tools'
@echo ' cgroup - cgroup tools'
@echo ' cpupower - a tool for all things x86 CPU power'
@echo ' debugging - tools for debugging'
@@ -23,12 +24,11 @@ help:
@echo ' kvm_stat - top-like utility for displaying kvm statistics'
@echo ' leds - LEDs tools'
@echo ' liblockdep - user-space wrapper for kernel locking-validator'
- @echo ' bpf - misc BPF tools'
+ @echo ' objtool - an ELF object analysis tool'
@echo ' pci - PCI tools'
@echo ' perf - Linux performance measurement and analysis tool'
@echo ' selftests - various kernel selftests'
@echo ' spi - spi tools'
- @echo ' objtool - an ELF object analysis tool'
@echo ' tmon - thermal monitoring and tuning tool'
@echo ' turbostat - Intel CPU idle stats and freq reporting tool'
@echo ' usb - USB testing tools'
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index 4602464ebdfb..a4217c1a5d01 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -214,6 +214,18 @@ struct kvm_vcpu_events {
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_FW | ((r) & 0xffff))
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
+ /* Higher values mean better protection. */
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2)
+ /* Higher values mean better protection. */
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL 2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
/* Device Control API: ARM VGIC */
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index d819a3e8b552..9a507716ae2f 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -229,6 +229,16 @@ struct kvm_vcpu_events {
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_FW | ((r) & 0xffff))
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL 2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
/* SVE registers */
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
diff --git a/tools/arch/powerpc/include/uapi/asm/mman.h b/tools/arch/powerpc/include/uapi/asm/mman.h
index f33105bc5ca6..8601d824a9c6 100644
--- a/tools/arch/powerpc/include/uapi/asm/mman.h
+++ b/tools/arch/powerpc/include/uapi/asm/mman.h
@@ -4,12 +4,8 @@
#define MAP_DENYWRITE 0x0800
#define MAP_EXECUTABLE 0x1000
#define MAP_GROWSDOWN 0x0100
-#define MAP_HUGETLB 0x40000
#define MAP_LOCKED 0x80
-#define MAP_NONBLOCK 0x10000
#define MAP_NORESERVE 0x40
-#define MAP_POPULATE 0x8000
-#define MAP_STACK 0x20000
#include <uapi/asm-generic/mman-common.h>
/* MAP_32BIT is undefined on powerpc, fix it for perf */
#define MAP_32BIT 0
diff --git a/tools/arch/riscv/include/uapi/asm/perf_regs.h b/tools/arch/riscv/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..196f964bfcb4
--- /dev/null
+++ b/tools/arch/riscv/include/uapi/asm/perf_regs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#ifndef _ASM_RISCV_PERF_REGS_H
+#define _ASM_RISCV_PERF_REGS_H
+
+enum perf_event_riscv_regs {
+ PERF_REG_RISCV_PC,
+ PERF_REG_RISCV_RA,
+ PERF_REG_RISCV_SP,
+ PERF_REG_RISCV_GP,
+ PERF_REG_RISCV_TP,
+ PERF_REG_RISCV_T0,
+ PERF_REG_RISCV_T1,
+ PERF_REG_RISCV_T2,
+ PERF_REG_RISCV_S0,
+ PERF_REG_RISCV_S1,
+ PERF_REG_RISCV_A0,
+ PERF_REG_RISCV_A1,
+ PERF_REG_RISCV_A2,
+ PERF_REG_RISCV_A3,
+ PERF_REG_RISCV_A4,
+ PERF_REG_RISCV_A5,
+ PERF_REG_RISCV_A6,
+ PERF_REG_RISCV_A7,
+ PERF_REG_RISCV_S2,
+ PERF_REG_RISCV_S3,
+ PERF_REG_RISCV_S4,
+ PERF_REG_RISCV_S5,
+ PERF_REG_RISCV_S6,
+ PERF_REG_RISCV_S7,
+ PERF_REG_RISCV_S8,
+ PERF_REG_RISCV_S9,
+ PERF_REG_RISCV_S10,
+ PERF_REG_RISCV_S11,
+ PERF_REG_RISCV_T3,
+ PERF_REG_RISCV_T4,
+ PERF_REG_RISCV_T5,
+ PERF_REG_RISCV_T6,
+ PERF_REG_RISCV_MAX,
+};
+#endif /* _ASM_RISCV_PERF_REGS_H */
diff --git a/tools/arch/sparc/include/uapi/asm/mman.h b/tools/arch/sparc/include/uapi/asm/mman.h
index 38920eed8cbf..7b94dccc843d 100644
--- a/tools/arch/sparc/include/uapi/asm/mman.h
+++ b/tools/arch/sparc/include/uapi/asm/mman.h
@@ -4,12 +4,8 @@
#define MAP_DENYWRITE 0x0800
#define MAP_EXECUTABLE 0x1000
#define MAP_GROWSDOWN 0x0200
-#define MAP_HUGETLB 0x40000
#define MAP_LOCKED 0x100
-#define MAP_NONBLOCK 0x10000
#define MAP_NORESERVE 0x40
-#define MAP_POPULATE 0x8000
-#define MAP_STACK 0x20000
#include <uapi/asm-generic/mman-common.h>
/* MAP_32BIT is undefined on sparc, fix it for perf */
#define MAP_32BIT 0
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 998c2cc08363..5171b9c7ca3e 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -96,7 +96,6 @@
#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */
#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */
#define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */
-#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" MFENCE synchronizes RDTSC */
#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" LFENCE synchronizes RDTSC */
#define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */
#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */
@@ -281,6 +280,8 @@
#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */
#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
+#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
+#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
@@ -394,5 +395,6 @@
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
+#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/arch/x86/include/asm/inat.h
index 877827b7c2c3..877827b7c2c3 100644
--- a/tools/perf/util/intel-pt-decoder/inat.h
+++ b/tools/arch/x86/include/asm/inat.h
diff --git a/tools/objtool/arch/x86/include/asm/inat_types.h b/tools/arch/x86/include/asm/inat_types.h
index b047efa9ddc2..b047efa9ddc2 100644
--- a/tools/objtool/arch/x86/include/asm/inat_types.h
+++ b/tools/arch/x86/include/asm/inat_types.h
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/arch/x86/include/asm/insn.h
index 37a4c390750b..37a4c390750b 100644
--- a/tools/perf/util/intel-pt-decoder/insn.h
+++ b/tools/arch/x86/include/asm/insn.h
diff --git a/tools/objtool/arch/x86/include/asm/orc_types.h b/tools/arch/x86/include/asm/orc_types.h
index 6e060907c163..6e060907c163 100644
--- a/tools/objtool/arch/x86/include/asm/orc_types.h
+++ b/tools/arch/x86/include/asm/orc_types.h
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index d6ab5b4d15e5..503d3f42da16 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -378,10 +378,11 @@ struct kvm_sync_regs {
struct kvm_vcpu_events events;
};
-#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
-#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
-#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
-#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
+#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
+#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
+#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
+#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
+#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
#define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1 /* unused */
@@ -432,4 +433,17 @@ struct kvm_nested_state {
} data;
};
+/* for KVM_CAP_PMU_EVENT_FILTER */
+struct kvm_pmu_event_filter {
+ __u32 action;
+ __u32 nevents;
+ __u32 fixed_counter_bitmap;
+ __u32 flags;
+ __u32 pad[4];
+ __u64 events[0];
+};
+
+#define KVM_PMU_EVENT_ALLOW 0
+#define KVM_PMU_EVENT_DENY 1
+
#endif /* _ASM_X86_KVM_H */
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
index d213ec5c3766..f0b0c90dd398 100644
--- a/tools/arch/x86/include/uapi/asm/vmx.h
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -146,7 +146,6 @@
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
-#define VMX_ABORT_VMCS_CORRUPTED 3
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
#endif /* _UAPIVMX_H */
diff --git a/tools/objtool/arch/x86/lib/inat.c b/tools/arch/x86/lib/inat.c
index 12539fca75c4..4f5ed49e1b4e 100644
--- a/tools/objtool/arch/x86/lib/inat.c
+++ b/tools/arch/x86/lib/inat.c
@@ -4,7 +4,7 @@
*
* Written by Masami Hiramatsu <mhiramat@redhat.com>
*/
-#include <asm/insn.h>
+#include "../include/asm/insn.h"
/* Attribute tables are generated from opcode map */
#include "inat-tables.c"
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/arch/x86/lib/insn.c
index 82783bf43b74..79e048f1d902 100644
--- a/tools/perf/util/intel-pt-decoder/insn.c
+++ b/tools/arch/x86/lib/insn.c
@@ -10,8 +10,8 @@
#else
#include <string.h>
#endif
-#include "inat.h"
-#include "insn.h"
+#include "../include/asm/inat.h"
+#include "../include/asm/insn.h"
/* Verify next sizeof(t) bytes can be on the same instruction */
#define validate_next(t, insn, n) \
diff --git a/tools/objtool/arch/x86/lib/x86-opcode-map.txt b/tools/arch/x86/lib/x86-opcode-map.txt
index e0b85930dd77..e0b85930dd77 100644
--- a/tools/objtool/arch/x86/lib/x86-opcode-map.txt
+++ b/tools/arch/x86/lib/x86-opcode-map.txt
diff --git a/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk b/tools/arch/x86/tools/gen-insn-attr-x86.awk
index b02a36b2c14f..b02a36b2c14f 100644
--- a/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk
+++ b/tools/arch/x86/tools/gen-insn-attr-x86.awk
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 5215e0870bcb..6a71324be628 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -204,7 +204,11 @@ int do_pin_fd(int fd, const char *name)
if (err)
return err;
- return bpf_obj_pin(fd, name);
+ err = bpf_obj_pin(fd, name);
+ if (err)
+ p_err("can't pin the object (%s): %s", name, strerror(errno));
+
+ return err;
}
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
@@ -237,7 +241,7 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
fd = get_fd_by_id(id);
if (fd < 0) {
- p_err("can't get prog by id (%u): %s", id, strerror(errno));
+ p_err("can't open object by id (%u): %s", id, strerror(errno));
return -1;
}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 66f04a4846a5..43fdbbfe41bb 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -363,7 +363,9 @@ static int do_show(int argc, char **argv)
if (fd < 0)
return -1;
- return show_prog(fd);
+ err = show_prog(fd);
+ close(fd);
+ return err;
}
if (argc)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 86b793dffbc4..8a19753cc26a 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -42,6 +42,7 @@ FEATURE_TESTS_BASIC := \
gtk2-infobar \
libaudit \
libbfd \
+ libcap \
libelf \
libelf-getphdrnum \
libelf-gelf_getnote \
@@ -110,6 +111,7 @@ FEATURE_DISPLAY ?= \
gtk2 \
libaudit \
libbfd \
+ libcap \
libelf \
libnuma \
numa_num_possible_cpus \
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 0658b8cd0e53..8499385365c0 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -20,6 +20,7 @@ FILES= \
test-libbfd-liberty.bin \
test-libbfd-liberty-z.bin \
test-cplus-demangle.bin \
+ test-libcap.bin \
test-libelf.bin \
test-libelf-getphdrnum.bin \
test-libelf-gelf_getnote.bin \
@@ -105,6 +106,9 @@ $(OUTPUT)test-fortify-source.bin:
$(OUTPUT)test-bionic.bin:
$(BUILD)
+$(OUTPUT)test-libcap.bin:
+ $(BUILD) -lcap
+
$(OUTPUT)test-libelf.bin:
$(BUILD) -lelf
diff --git a/tools/build/feature/test-libcap.c b/tools/build/feature/test-libcap.c
new file mode 100644
index 000000000000..d2a2e152195f
--- /dev/null
+++ b/tools/build/feature/test-libcap.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <sys/capability.h>
+#include <linux/capability.h>
+
+int main(void)
+{
+ cap_flag_value_t val;
+ cap_t caps = cap_get_proc();
+
+ if (!caps)
+ return 1;
+
+ if (cap_get_flag(caps, CAP_SYS_ADMIN, CAP_EFFECTIVE, &val) != 0)
+ return 1;
+
+ if (cap_free(caps) != 0)
+ return 1;
+
+ return 0;
+}
diff --git a/tools/hv/hv_get_dhcp_info.sh b/tools/hv/hv_get_dhcp_info.sh
index c38686c44656..2f2a3c7df3de 100755
--- a/tools/hv/hv_get_dhcp_info.sh
+++ b/tools/hv/hv_get_dhcp_info.sh
@@ -13,7 +13,7 @@
# the script prints the string "Disabled" to stdout.
#
# Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
# this script can be based on the Network Manager APIs for retrieving DHCP
# information.
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d7e06fe0270e..e9ef4ca6a655 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -700,7 +700,7 @@ static void kvp_get_ipconfig_info(char *if_name,
/*
- * Gather the DNS state.
+ * Gather the DNS state.
* Since there is no standard way to get this information
* across various distributions of interest; we just invoke
* an external script that needs to be ported across distros
@@ -809,7 +809,7 @@ kvp_get_ip_info(int family, char *if_name, int op,
int sn_offset = 0;
int error = 0;
char *buffer;
- struct hv_kvp_ipaddr_value *ip_buffer;
+ struct hv_kvp_ipaddr_value *ip_buffer = NULL;
char cidr_mask[5]; /* /xyz */
int weight;
int i;
@@ -1051,7 +1051,7 @@ static int parse_ip_val_buffer(char *in_buf, int *offset,
char *start;
/*
- * in_buf has sequence of characters that are seperated by
+ * in_buf has sequence of characters that are separated by
* the character ';'. The last sequence does not have the
* terminating ";" character.
*/
@@ -1386,6 +1386,8 @@ int main(int argc, char *argv[])
daemonize = 0;
break;
case 'h':
+ print_usage(argv);
+ exit(0);
default:
print_usage(argv);
exit(EXIT_FAILURE);
@@ -1490,7 +1492,7 @@ int main(int argc, char *argv[])
case KVP_OP_GET_IP_INFO:
kvp_ip_val = &hv_msg->body.kvp_ip_val;
- error = kvp_mac_to_ip(kvp_ip_val);
+ error = kvp_mac_to_ip(kvp_ip_val);
if (error)
hv_msg->error = error;
diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh
index 7ed9f85ef908..d10fe35b7f25 100755
--- a/tools/hv/hv_set_ifconfig.sh
+++ b/tools/hv/hv_set_ifconfig.sh
@@ -12,7 +12,7 @@
# be used to configure the interface.
#
# Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
# this script can be based on the Network Manager APIs for configuring the
# interface.
#
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index efe1e34dd91b..92902a88f671 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -42,7 +42,7 @@ static int vss_do_freeze(char *dir, unsigned int cmd)
* If a partition is mounted more than once, only the first
* FREEZE/THAW can succeed and the later ones will get
* EBUSY/EINVAL respectively: there could be 2 cases:
- * 1) a user may mount the same partition to differnt directories
+ * 1) a user may mount the same partition to different directories
* by mistake or on purpose;
* 2) The subvolume of btrfs appears to have the same partition
* mounted more than once.
@@ -218,6 +218,8 @@ int main(int argc, char *argv[])
daemonize = 0;
break;
case 'h':
+ print_usage(argv);
+ exit(0);
default:
print_usage(argv);
exit(EXIT_FAILURE);
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
index 55e7374bade0..099f2c44dbed 100644
--- a/tools/hv/lsvmbus
+++ b/tools/hv/lsvmbus
@@ -4,10 +4,10 @@
import os
from optparse import OptionParser
+help_msg = "print verbose messages. Try -vv, -vvv for more verbose messages"
parser = OptionParser()
-parser.add_option("-v", "--verbose", dest="verbose",
- help="print verbose messages. Try -vv, -vvv for \
- more verbose messages", action="count")
+parser.add_option(
+ "-v", "--verbose", dest="verbose", help=help_msg, action="count")
(options, args) = parser.parse_args()
@@ -21,27 +21,28 @@ if not os.path.isdir(vmbus_sys_path):
exit(-1)
vmbus_dev_dict = {
- '{0e0b6031-5213-4934-818b-38d90ced39db}' : '[Operating system shutdown]',
- '{9527e630-d0ae-497b-adce-e80ab0175caf}' : '[Time Synchronization]',
- '{57164f39-9115-4e78-ab55-382f3bd5422d}' : '[Heartbeat]',
- '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}' : '[Data Exchange]',
- '{35fa2e29-ea23-4236-96ae-3a6ebacba440}' : '[Backup (volume checkpoint)]',
- '{34d14be3-dee4-41c8-9ae7-6b174977c192}' : '[Guest services]',
- '{525074dc-8985-46e2-8057-a307dc18a502}' : '[Dynamic Memory]',
- '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}' : 'Synthetic mouse',
- '{f912ad6d-2b17-48ea-bd65-f927a61c7684}' : 'Synthetic keyboard',
- '{da0a7802-e377-4aac-8e77-0558eb1073f8}' : 'Synthetic framebuffer adapter',
- '{f8615163-df3e-46c5-913f-f2d2f965ed0e}' : 'Synthetic network adapter',
- '{32412632-86cb-44a2-9b5c-50d1417354f5}' : 'Synthetic IDE Controller',
- '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
- '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
- '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
- '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
- '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
- '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
- '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
+ '{0e0b6031-5213-4934-818b-38d90ced39db}': '[Operating system shutdown]',
+ '{9527e630-d0ae-497b-adce-e80ab0175caf}': '[Time Synchronization]',
+ '{57164f39-9115-4e78-ab55-382f3bd5422d}': '[Heartbeat]',
+ '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}': '[Data Exchange]',
+ '{35fa2e29-ea23-4236-96ae-3a6ebacba440}': '[Backup (volume checkpoint)]',
+ '{34d14be3-dee4-41c8-9ae7-6b174977c192}': '[Guest services]',
+ '{525074dc-8985-46e2-8057-a307dc18a502}': '[Dynamic Memory]',
+ '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}': 'Synthetic mouse',
+ '{f912ad6d-2b17-48ea-bd65-f927a61c7684}': 'Synthetic keyboard',
+ '{da0a7802-e377-4aac-8e77-0558eb1073f8}': 'Synthetic framebuffer adapter',
+ '{f8615163-df3e-46c5-913f-f2d2f965ed0e}': 'Synthetic network adapter',
+ '{32412632-86cb-44a2-9b5c-50d1417354f5}': 'Synthetic IDE Controller',
+ '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}': 'Synthetic SCSI Controller',
+ '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}': 'Synthetic fiber channel adapter',
+ '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}': 'Synthetic RDMA adapter',
+ '{44c4f61d-4444-4400-9d52-802e27ede19f}': 'PCI Express pass-through',
+ '{276aacf4-ac15-426c-98dd-7521ad3f01fe}': '[Reserved system device]',
+ '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}': '[Reserved system device]',
+ '{3375baf4-9e15-4b30-b765-67acb10d607b}': '[Reserved system device]',
}
+
def get_vmbus_dev_attr(dev_name, attr):
try:
f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
@@ -52,6 +53,7 @@ def get_vmbus_dev_attr(dev_name, attr):
return lines
+
class VMBus_Dev:
pass
@@ -66,12 +68,13 @@ for f in os.listdir(vmbus_sys_path):
chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
- chn_vp_mapping = sorted(chn_vp_mapping,
- key = lambda c : int(c.split(':')[0]))
+ chn_vp_mapping = sorted(
+ chn_vp_mapping, key=lambda c: int(c.split(':')[0]))
- chn_vp_mapping = ['\tRel_ID=%s, target_cpu=%s' %
- (c.split(':')[0], c.split(':')[1])
- for c in chn_vp_mapping]
+ chn_vp_mapping = [
+ '\tRel_ID=%s, target_cpu=%s' %
+ (c.split(':')[0], c.split(':')[1]) for c in chn_vp_mapping
+ ]
d = VMBus_Dev()
d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
d.vmbus_id = vmbus_id
@@ -85,7 +88,7 @@ for f in os.listdir(vmbus_sys_path):
vmbus_dev_list.append(d)
-vmbus_dev_list = sorted(vmbus_dev_list, key = lambda d : int(d.vmbus_id))
+vmbus_dev_list = sorted(vmbus_dev_list, key=lambda d: int(d.vmbus_id))
format0 = '%2s: %s'
format1 = '%2s: Class_ID = %s - %s\n%s'
@@ -95,9 +98,15 @@ for d in vmbus_dev_list:
if verbose == 0:
print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc))
elif verbose == 1:
- print (('VMBUS ID ' + format1) % \
- (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping))
+ print(
+ ('VMBUS ID ' + format1) %
+ (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
+ )
else:
- print (('VMBUS ID ' + format2) % \
- (d.vmbus_id, d.class_id, d.dev_desc, \
- d.device_id, d.sysfs_path, d.chn_vp_mapping))
+ print(
+ ('VMBUS ID ' + format2) %
+ (
+ d.vmbus_id, d.class_id, d.dev_desc,
+ d.device_id, d.sysfs_path, d.chn_vp_mapping
+ )
+ )
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 0b0ef3abc966..140c8362f113 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -3,6 +3,7 @@
#define _TOOLS_LINUX_BITOPS_H_
#include <asm/types.h>
+#include <limits.h>
#ifndef __WORDSIZE
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
#endif
diff --git a/tools/include/linux/bits.h b/tools/include/linux/bits.h
index 2b7b532c1d51..669d69441a62 100644
--- a/tools/include/linux/bits.h
+++ b/tools/include/linux/bits.h
@@ -1,13 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_BITS_H
#define __LINUX_BITS_H
+
+#include <linux/const.h>
#include <asm/bitsperlong.h>
-#define BIT(nr) (1UL << (nr))
-#define BIT_ULL(nr) (1ULL << (nr))
-#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT(nr) (UL(1) << (nr))
+#define BIT_ULL(nr) (ULL(1) << (nr))
+#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
-#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
+#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
#define BITS_PER_BYTE 8
@@ -17,10 +19,11 @@
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
#define GENMASK(h, l) \
- (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+ (((~UL(0)) - (UL(1) << (l)) + 1) & \
+ (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
#define GENMASK_ULL(h, l) \
- (((~0ULL) - (1ULL << (l)) + 1) & \
- (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
+ (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
+ (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
#endif /* __LINUX_BITS_H */
diff --git a/tools/include/linux/const.h b/tools/include/linux/const.h
new file mode 100644
index 000000000000..7b55a55f5911
--- /dev/null
+++ b/tools/include/linux/const.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_CONST_H
+#define _LINUX_CONST_H
+
+#include <uapi/linux/const.h>
+
+#define UL(x) (_UL(x))
+#define ULL(x) (_ULL(x))
+
+#endif /* _LINUX_CONST_H */
diff --git a/tools/include/linux/ring_buffer.h b/tools/include/linux/ring_buffer.h
index 9a083ae60473..6c02617377c2 100644
--- a/tools/include/linux/ring_buffer.h
+++ b/tools/include/linux/ring_buffer.h
@@ -2,6 +2,7 @@
#define _TOOLS_LINUX_RING_BUFFER_H_
#include <asm/barrier.h>
+#include <linux/perf_event.h>
/*
* Contract with kernel for walking the perf ring buffer from
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
index abd238d0f7a4..63b1f506ea67 100644
--- a/tools/include/uapi/asm-generic/mman-common.h
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -19,15 +19,18 @@
#define MAP_TYPE 0x0f /* Mask for type of mapping */
#define MAP_FIXED 0x10 /* Interpret addr exactly */
#define MAP_ANONYMOUS 0x20 /* don't use a file */
-#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
-# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */
-#else
-# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
-#endif
-/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
+/* 0x0100 - 0x4000 flags are defined in asm-generic/mman.h */
+#define MAP_POPULATE 0x008000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x010000 /* do not block on IO */
+#define MAP_STACK 0x020000 /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB 0x040000 /* create a huge page mapping */
+#define MAP_SYNC 0x080000 /* perform synchronous page faults for the mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
+ * uninitialized */
+
/*
* Flags for mlock
*/
diff --git a/tools/include/uapi/asm-generic/mman.h b/tools/include/uapi/asm-generic/mman.h
index 36c197fc44a0..406f7718f9ad 100644
--- a/tools/include/uapi/asm-generic/mman.h
+++ b/tools/include/uapi/asm-generic/mman.h
@@ -9,13 +9,11 @@
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
-#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK 0x10000 /* do not block on IO */
-#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
-#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
-#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */
-/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
+/*
+ * Bits [26:31] are reserved, see asm-generic/hugetlb_encode.h
+ * for MAP_HUGETLB usage
+ */
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index a87904daf103..1be0e798e362 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -844,9 +844,15 @@ __SYSCALL(__NR_fsconfig, sys_fsconfig)
__SYSCALL(__NR_fsmount, sys_fsmount)
#define __NR_fspick 433
__SYSCALL(__NR_fspick, sys_fspick)
+#define __NR_pidfd_open 434
+__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
+#ifdef __ARCH_WANT_SYS_CLONE3
+#define __NR_clone3 435
+__SYSCALL(__NR_clone3, sys_clone3)
+#endif
#undef __NR_syscalls
-#define __NR_syscalls 434
+#define __NR_syscalls 436
/*
* 32 bit systems traditionally used different
diff --git a/tools/include/uapi/asm/bitsperlong.h b/tools/include/uapi/asm/bitsperlong.h
index 57aaeaf8e192..edba4d93e9e6 100644
--- a/tools/include/uapi/asm/bitsperlong.h
+++ b/tools/include/uapi/asm/bitsperlong.h
@@ -1,22 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#if defined(__i386__) || defined(__x86_64__)
-#include "../../arch/x86/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/x86/include/uapi/asm/bitsperlong.h"
#elif defined(__aarch64__)
-#include "../../arch/arm64/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/arm64/include/uapi/asm/bitsperlong.h"
#elif defined(__powerpc__)
-#include "../../arch/powerpc/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/powerpc/include/uapi/asm/bitsperlong.h"
#elif defined(__s390__)
-#include "../../arch/s390/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/s390/include/uapi/asm/bitsperlong.h"
#elif defined(__sparc__)
-#include "../../arch/sparc/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/sparc/include/uapi/asm/bitsperlong.h"
#elif defined(__mips__)
-#include "../../arch/mips/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/mips/include/uapi/asm/bitsperlong.h"
#elif defined(__ia64__)
-#include "../../arch/ia64/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/ia64/include/uapi/asm/bitsperlong.h"
#elif defined(__riscv)
-#include "../../arch/riscv/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/riscv/include/uapi/asm/bitsperlong.h"
#elif defined(__alpha__)
-#include "../../arch/alpha/include/uapi/asm/bitsperlong.h"
+#include "../../../arch/alpha/include/uapi/asm/bitsperlong.h"
#else
#include <asm-generic/bitsperlong.h>
#endif
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
index 661d73f9a919..8a5b2f8f8eb9 100644
--- a/tools/include/uapi/drm/drm.h
+++ b/tools/include/uapi/drm/drm.h
@@ -50,6 +50,7 @@ typedef unsigned int drm_handle_t;
#else /* One of the BSDs */
+#include <stdint.h>
#include <sys/ioccom.h>
#include <sys/types.h>
typedef int8_t __s8;
diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h
index 3a73f5316766..328d05e77d9f 100644
--- a/tools/include/uapi/drm/i915_drm.h
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -136,6 +136,8 @@ enum drm_i915_gem_engine_class {
struct i915_engine_class_instance {
__u16 engine_class; /* see enum drm_i915_gem_engine_class */
__u16 engine_instance;
+#define I915_ENGINE_CLASS_INVALID_NONE -1
+#define I915_ENGINE_CLASS_INVALID_VIRTUAL -2
};
/**
@@ -355,6 +357,8 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_PERF_ADD_CONFIG 0x37
#define DRM_I915_PERF_REMOVE_CONFIG 0x38
#define DRM_I915_QUERY 0x39
+#define DRM_I915_GEM_VM_CREATE 0x3a
+#define DRM_I915_GEM_VM_DESTROY 0x3b
/* Must be kept compact -- no holes */
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -415,6 +419,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
+#define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
+#define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -598,6 +604,12 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_MMAP_GTT_COHERENT 52
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
+ * execution through use of explicit fence support.
+ * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
+ */
+#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
/* Must be kept compact -- no holes and well documented */
typedef struct drm_i915_getparam {
@@ -1120,7 +1132,16 @@ struct drm_i915_gem_execbuffer2 {
*/
#define I915_EXEC_FENCE_ARRAY (1<<19)
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
+/*
+ * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
+ * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
+ * the batch.
+ *
+ * Returns -EINVAL if the sync_file fd cannot be found.
+ */
+#define I915_EXEC_FENCE_SUBMIT (1 << 20)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
#define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1464,8 +1485,9 @@ struct drm_i915_gem_context_create_ext {
__u32 ctx_id; /* output: id of new context*/
__u32 flags;
#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0)
+#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE (1u << 1)
#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
- (-(I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1))
+ (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
__u64 extensions;
};
@@ -1507,6 +1529,41 @@ struct drm_i915_gem_context_param {
* On creation, all new contexts are marked as recoverable.
*/
#define I915_CONTEXT_PARAM_RECOVERABLE 0x8
+
+ /*
+ * The id of the associated virtual memory address space (ppGTT) of
+ * this context. Can be retrieved and passed to another context
+ * (on the same fd) for both to use the same ppGTT and so share
+ * address layouts, and avoid reloading the page tables on context
+ * switches between themselves.
+ *
+ * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
+ */
+#define I915_CONTEXT_PARAM_VM 0x9
+
+/*
+ * I915_CONTEXT_PARAM_ENGINES:
+ *
+ * Bind this context to operate on this subset of available engines. Henceforth,
+ * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
+ * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
+ * and upwards. Slots 0...N are filled in using the specified (class, instance).
+ * Use
+ * engine_class: I915_ENGINE_CLASS_INVALID,
+ * engine_instance: I915_ENGINE_CLASS_INVALID_NONE
+ * to specify a gap in the array that can be filled in later, e.g. by a
+ * virtual engine used for load balancing.
+ *
+ * Setting the number of engines bound to the context to 0, by passing a zero
+ * sized argument, will revert back to default settings.
+ *
+ * See struct i915_context_param_engines.
+ *
+ * Extensions:
+ * i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
+ * i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
+ */
+#define I915_CONTEXT_PARAM_ENGINES 0xa
/* Must be kept compact -- no holes and well documented */
__u64 value;
@@ -1540,9 +1597,10 @@ struct drm_i915_gem_context_param_sseu {
struct i915_engine_class_instance engine;
/*
- * Unused for now. Must be cleared to zero.
+ * Unknown flags must be cleared to zero.
*/
__u32 flags;
+#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
/*
* Mask of slices to enable for the context. Valid values are a subset
@@ -1570,12 +1628,115 @@ struct drm_i915_gem_context_param_sseu {
__u32 rsvd;
};
+/*
+ * i915_context_engines_load_balance:
+ *
+ * Enable load balancing across this set of engines.
+ *
+ * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
+ * used will proxy the execbuffer request onto one of the set of engines
+ * in such a way as to distribute the load evenly across the set.
+ *
+ * The set of engines must be compatible (e.g. the same HW class) as they
+ * will share the same logical GPU context and ring.
+ *
+ * To intermix rendering with the virtual engine and direct rendering onto
+ * the backing engines (bypassing the load balancing proxy), the context must
+ * be defined to use a single timeline for all engines.
+ */
+struct i915_context_engines_load_balance {
+ struct i915_user_extension base;
+
+ __u16 engine_index;
+ __u16 num_siblings;
+ __u32 flags; /* all undefined flags must be zero */
+
+ __u64 mbz64; /* reserved for future use; must be zero */
+
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(name__, N__) struct { \
+ struct i915_user_extension base; \
+ __u16 engine_index; \
+ __u16 num_siblings; \
+ __u32 flags; \
+ __u64 mbz64; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+/*
+ * i915_context_engines_bond:
+ *
+ * Constructed bonded pairs for execution within a virtual engine.
+ *
+ * All engines are equal, but some are more equal than others. Given
+ * the distribution of resources in the HW, it may be preferable to run
+ * a request on a given subset of engines in parallel to a request on a
+ * specific engine. We enable this selection of engines within a virtual
+ * engine by specifying bonding pairs, for any given master engine we will
+ * only execute on one of the corresponding siblings within the virtual engine.
+ *
+ * To execute a request in parallel on the master engine and a sibling requires
+ * coordination with a I915_EXEC_FENCE_SUBMIT.
+ */
+struct i915_context_engines_bond {
+ struct i915_user_extension base;
+
+ struct i915_engine_class_instance master;
+
+ __u16 virtual_index; /* index of virtual engine in ctx->engines[] */
+ __u16 num_bonds;
+
+ __u64 flags; /* all undefined flags must be zero */
+ __u64 mbz64[4]; /* reserved for future use; must be zero */
+
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_BOND(name__, N__) struct { \
+ struct i915_user_extension base; \
+ struct i915_engine_class_instance master; \
+ __u16 virtual_index; \
+ __u16 num_bonds; \
+ __u64 flags; \
+ __u64 mbz64[4]; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+struct i915_context_param_engines {
+ __u64 extensions; /* linked chain of extension blocks, 0 terminates */
+#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
+#define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
+ __u64 extensions; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
struct drm_i915_gem_context_create_ext_setparam {
#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
struct i915_user_extension base;
struct drm_i915_gem_context_param param;
};
+struct drm_i915_gem_context_create_ext_clone {
+#define I915_CONTEXT_CREATE_EXT_CLONE 1
+ struct i915_user_extension base;
+ __u32 clone_id;
+ __u32 flags;
+#define I915_CONTEXT_CLONE_ENGINES (1u << 0)
+#define I915_CONTEXT_CLONE_FLAGS (1u << 1)
+#define I915_CONTEXT_CLONE_SCHEDATTR (1u << 2)
+#define I915_CONTEXT_CLONE_SSEU (1u << 3)
+#define I915_CONTEXT_CLONE_TIMELINE (1u << 4)
+#define I915_CONTEXT_CLONE_VM (1u << 5)
+#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_VM << 1)
+ __u64 rsvd;
+};
+
struct drm_i915_gem_context_destroy {
__u32 ctx_id;
__u32 pad;
@@ -1821,6 +1982,7 @@ struct drm_i915_perf_oa_config {
struct drm_i915_query_item {
__u64 query_id;
#define DRM_I915_QUERY_TOPOLOGY_INFO 1
+#define DRM_I915_QUERY_ENGINE_INFO 2
/* Must be kept compact -- no holes and well documented */
/*
@@ -1919,6 +2081,47 @@ struct drm_i915_query_topology_info {
__u8 data[];
};
+/**
+ * struct drm_i915_engine_info
+ *
+ * Describes one engine and it's capabilities as known to the driver.
+ */
+struct drm_i915_engine_info {
+ /** Engine class and instance. */
+ struct i915_engine_class_instance engine;
+
+ /** Reserved field. */
+ __u32 rsvd0;
+
+ /** Engine flags. */
+ __u64 flags;
+
+ /** Capabilities of this engine. */
+ __u64 capabilities;
+#define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0)
+#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1)
+
+ /** Reserved fields. */
+ __u64 rsvd1[4];
+};
+
+/**
+ * struct drm_i915_query_engine_info
+ *
+ * Engine info query enumerates all engines known to the driver by filling in
+ * an array of struct drm_i915_engine_info structures.
+ */
+struct drm_i915_query_engine_info {
+ /** Number of struct drm_i915_engine_info structs following. */
+ __u32 num_engines;
+
+ /** MBZ */
+ __u32 rsvd[3];
+
+ /** Marker for drm_i915_engine_info structures. */
+ struct drm_i915_engine_info engines[];
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4e455018da65..a5aa7d3ac6a1 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1466,8 +1466,8 @@ union bpf_attr {
* If no cookie has been set yet, generate a new cookie. Once
* generated, the socket cookie remains stable for the life of the
* socket. This helper can be useful for monitoring per socket
- * networking traffic statistics as it provides a unique socket
- * identifier per namespace.
+ * networking traffic statistics as it provides a global socket
+ * identifier that can be assumed unique.
* Return
* A 8-byte long non-decreasing number on success, or 0 if the
* socket field is missing inside *skb*.
@@ -1571,8 +1571,11 @@ union bpf_attr {
* but this is only implemented for native XDP (with driver
* support) as of this writing).
*
- * All values for *flags* are reserved for future usage, and must
- * be left at zero.
+ * The lower two bits of *flags* are used as the return code if
+ * the map lookup fails. This is so that the return value can be
+ * one of the XDP program return codes up to XDP_TX, as chosen by
+ * the caller. Any higher bits in the *flags* argument must be
+ * unset.
*
* When used to redirect packets to net devices, this helper
* provides a high performance increase over **bpf_redirect**\ ().
diff --git a/tools/include/uapi/linux/const.h b/tools/include/uapi/linux/const.h
new file mode 100644
index 000000000000..5ed721ad5b19
--- /dev/null
+++ b/tools/include/uapi/linux/const.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* const.h: Macros for dealing with constants. */
+
+#ifndef _UAPI_LINUX_CONST_H
+#define _UAPI_LINUX_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally. We
+ * use the following macros to deal with this.
+ *
+ * Similarly, _AT() will cast an expression with a type in C, but
+ * leave it unchanged in asm.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y) X
+#define _AT(T,X) X
+#else
+#define __AC(X,Y) (X##Y)
+#define _AC(X,Y) __AC(X,Y)
+#define _AT(T,X) ((T)(X))
+#endif
+
+#define _UL(x) (_AC(x, UL))
+#define _ULL(x) (_AC(x, ULL))
+
+#define _BITUL(x) (_UL(1) << (x))
+#define _BITULL(x) (_ULL(1) << (x))
+
+#endif /* _UAPI_LINUX_CONST_H */
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 7d113a9602f0..4a8c02cafa9a 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -695,6 +695,7 @@ enum {
IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */
IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */
IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */
+ IFLA_VF_BROADCAST, /* VF broadcast */
__IFLA_VF_MAX,
};
@@ -705,6 +706,10 @@ struct ifla_vf_mac {
__u8 mac[32]; /* MAX_ADDR_LEN */
};
+struct ifla_vf_broadcast {
+ __u8 broadcast[32];
+};
+
struct ifla_vf_vlan {
__u32 vf;
__u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index c2152f3dd02d..5e3f12d5359e 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -116,7 +116,7 @@ struct kvm_irq_level {
* ACPI gsi notion of irq.
* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
- * For ARM: See Documentation/virtual/kvm/api.txt
+ * For ARM: See Documentation/virt/kvm/api.txt
*/
union {
__u32 irq;
@@ -995,6 +995,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_SVE 170
#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
+#define KVM_CAP_PMU_EVENT_FILTER 173
#ifdef KVM_CAP_IRQ_ROUTING
@@ -1085,7 +1086,7 @@ struct kvm_xen_hvm_config {
*
* KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
* the irqfd to operate in resampling mode for level triggered interrupt
- * emulation. See Documentation/virtual/kvm/api.txt.
+ * emulation. See Documentation/virt/kvm/api.txt.
*/
#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
@@ -1329,6 +1330,8 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
/* Available with KVM_CAP_PPC_GET_CPU_CHAR */
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
+/* Available with KVM_CAP_PMU_EVENT_FILTER */
+#define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter)
/* ioctl for vm fd */
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 7198ddd0c6b1..bb7b271397a6 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -374,7 +374,8 @@ struct perf_event_attr {
namespaces : 1, /* include namespaces data */
ksymbol : 1, /* include ksymbol events */
bpf_event : 1, /* include bpf events */
- __reserved_1 : 33;
+ aux_output : 1, /* generate AUX records instead of events */
+ __reserved_1 : 32;
union {
__u32 wakeup_events; /* wakeup every n events */
diff --git a/tools/include/uapi/linux/sched.h b/tools/include/uapi/linux/sched.h
index ed4ee170bee2..b3105ac1381a 100644
--- a/tools/include/uapi/linux/sched.h
+++ b/tools/include/uapi/linux/sched.h
@@ -2,6 +2,8 @@
#ifndef _UAPI_LINUX_SCHED_H
#define _UAPI_LINUX_SCHED_H
+#include <linux/types.h>
+
/*
* cloning flags:
*/
@@ -32,6 +34,20 @@
#define CLONE_IO 0x80000000 /* Clone io context */
/*
+ * Arguments for the clone3 syscall
+ */
+struct clone_args {
+ __aligned_u64 flags;
+ __aligned_u64 pidfd;
+ __aligned_u64 child_tid;
+ __aligned_u64 parent_tid;
+ __aligned_u64 exit_signal;
+ __aligned_u64 stack;
+ __aligned_u64 stack_size;
+ __aligned_u64 tls;
+};
+
+/*
* Scheduling policies
*/
#define SCHED_NORMAL 0
@@ -51,9 +67,21 @@
#define SCHED_FLAG_RESET_ON_FORK 0x01
#define SCHED_FLAG_RECLAIM 0x02
#define SCHED_FLAG_DL_OVERRUN 0x04
+#define SCHED_FLAG_KEEP_POLICY 0x08
+#define SCHED_FLAG_KEEP_PARAMS 0x10
+#define SCHED_FLAG_UTIL_CLAMP_MIN 0x20
+#define SCHED_FLAG_UTIL_CLAMP_MAX 0x40
+
+#define SCHED_FLAG_KEEP_ALL (SCHED_FLAG_KEEP_POLICY | \
+ SCHED_FLAG_KEEP_PARAMS)
+
+#define SCHED_FLAG_UTIL_CLAMP (SCHED_FLAG_UTIL_CLAMP_MIN | \
+ SCHED_FLAG_UTIL_CLAMP_MAX)
#define SCHED_FLAG_ALL (SCHED_FLAG_RESET_ON_FORK | \
SCHED_FLAG_RECLAIM | \
- SCHED_FLAG_DL_OVERRUN)
+ SCHED_FLAG_DL_OVERRUN | \
+ SCHED_FLAG_KEEP_ALL | \
+ SCHED_FLAG_UTIL_CLAMP)
#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/tools/include/uapi/linux/usbdevice_fs.h b/tools/include/uapi/linux/usbdevice_fs.h
index 964e87217be4..78efe870c2b7 100644
--- a/tools/include/uapi/linux/usbdevice_fs.h
+++ b/tools/include/uapi/linux/usbdevice_fs.h
@@ -76,6 +76,26 @@ struct usbdevfs_connectinfo {
unsigned char slow;
};
+struct usbdevfs_conninfo_ex {
+ __u32 size; /* Size of the structure from the kernel's */
+ /* point of view. Can be used by userspace */
+ /* to determine how much data can be */
+ /* used/trusted. */
+ __u32 busnum; /* USB bus number, as enumerated by the */
+ /* kernel, the device is connected to. */
+ __u32 devnum; /* Device address on the bus. */
+ __u32 speed; /* USB_SPEED_* constants from ch9.h */
+ __u8 num_ports; /* Number of ports the device is connected */
+ /* to on the way to the root hub. It may */
+ /* be bigger than size of 'ports' array so */
+ /* userspace can detect overflows. */
+ __u8 ports[7]; /* List of ports on the way from the root */
+ /* hub to the device. Current limit in */
+ /* USB specification is 7 tiers (root hub, */
+ /* 5 intermediate hubs, device), which */
+ /* gives at most 6 port entries. */
+};
+
#define USBDEVFS_URB_SHORT_NOT_OK 0x01
#define USBDEVFS_URB_ISO_ASAP 0x02
#define USBDEVFS_URB_BULK_CONTINUATION 0x04
@@ -137,6 +157,7 @@ struct usbdevfs_hub_portinfo {
#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10
#define USBDEVFS_CAP_MMAP 0x20
#define USBDEVFS_CAP_DROP_PRIVILEGES 0x40
+#define USBDEVFS_CAP_CONNINFO_EX 0x80
/* USBDEVFS_DISCONNECT_CLAIM flags & struct */
@@ -197,5 +218,10 @@ struct usbdevfs_streams {
#define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams)
#define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32)
#define USBDEVFS_GET_SPEED _IO('U', 31)
+/*
+ * Returns struct usbdevfs_conninfo_ex; length is variable to allow
+ * extending size of the data returned.
+ */
+#define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len)
#endif /* _UAPI_LINUX_USBDEVICE_FS_H */
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 467224feb43b..d821107f55f9 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2018 Facebook */
+#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -419,9 +420,9 @@ done:
static bool btf_check_endianness(const GElf_Ehdr *ehdr)
{
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
return ehdr->e_ident[EI_DATA] == ELFDATA2LSB;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
return ehdr->e_ident[EI_DATA] == ELFDATA2MSB;
#else
# error "Unrecognized __BYTE_ORDER__"
diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
index 03748a742146..bae8879cdf58 100644
--- a/tools/lib/bpf/hashmap.h
+++ b/tools/lib/bpf/hashmap.h
@@ -10,6 +10,11 @@
#include <stdbool.h>
#include <stddef.h>
+#ifdef __GLIBC__
+#include <bits/wordsize.h>
+#else
+#include <bits/reg.h>
+#endif
#include "libbpf_internal.h"
static inline size_t hash_bits(size_t h, int bits)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 794dd5064ae8..2b57d7ea7836 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -20,6 +20,7 @@
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
+#include <endian.h>
#include <fcntl.h>
#include <errno.h>
#include <asm/unistd.h>
@@ -181,7 +182,6 @@ struct bpf_program {
bpf_program_clear_priv_t clear_priv;
enum bpf_attach_type expected_attach_type;
- int btf_fd;
void *func_info;
__u32 func_info_rec_size;
__u32 func_info_cnt;
@@ -312,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog)
prog->instances.nr = -1;
zfree(&prog->instances.fds);
- zclose(prog->btf_fd);
zfree(&prog->func_info);
zfree(&prog->line_info);
}
@@ -391,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
prog->instances.fds = NULL;
prog->instances.nr = -1;
prog->type = BPF_PROG_TYPE_UNSPEC;
- prog->btf_fd = -1;
return 0;
errout:
@@ -612,10 +610,10 @@ errout:
static int bpf_object__check_endianness(struct bpf_object *obj)
{
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
return 0;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
return 0;
#else
@@ -1377,8 +1375,13 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj)
if (!has_datasec && kind == BTF_KIND_VAR) {
/* replace VAR with INT */
t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
- t->size = sizeof(int);
- *(int *)(t+1) = BTF_INT_ENC(0, 0, 32);
+ /*
+ * using size = 1 is the safest choice, 4 will be too
+ * big and cause kernel BTF validation failure if
+ * original variable took less than 4 bytes
+ */
+ t->size = 1;
+ *(int *)(t+1) = BTF_INT_ENC(0, 0, 8);
} else if (!has_datasec && kind == BTF_KIND_DATASEC) {
/* replace DATASEC with STRUCT */
struct btf_var_secinfo *v = (void *)(t + 1);
@@ -1500,6 +1503,12 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
BTF_ELF_SEC, err);
btf__free(obj->btf);
obj->btf = NULL;
+ /* btf_ext can't exist without btf, so free it as well */
+ if (obj->btf_ext) {
+ btf_ext__free(obj->btf_ext);
+ obj->btf_ext = NULL;
+ }
+
if (bpf_object__is_btf_mandatory(obj))
return err;
}
@@ -2276,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
}
- if (!insn_offset)
- prog->btf_fd = btf__fd(obj->btf);
-
return 0;
}
@@ -2451,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
char *cp, errmsg[STRERR_BUFSIZE];
int log_buf_size = BPF_LOG_BUF_SIZE;
char *log_buf;
- int ret;
+ int btf_fd, ret;
if (!insns || !insns_cnt)
return -EINVAL;
@@ -2466,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
load_attr.license = license;
load_attr.kern_version = kern_version;
load_attr.prog_ifindex = prog->prog_ifindex;
- load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
+ /* if .BTF.ext was loaded, kernel supports associated BTF for prog */
+ if (prog->obj->btf_ext)
+ btf_fd = bpf_object__btf_fd(prog->obj);
+ else
+ btf_fd = -1;
+ load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0;
load_attr.func_info = prog->func_info;
load_attr.func_info_rec_size = prog->func_info_rec_size;
load_attr.func_info_cnt = prog->func_info_cnt;
@@ -4507,13 +4518,13 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
const struct perf_buffer_opts *opts)
{
struct perf_buffer_params p = {};
- struct perf_event_attr attr = {
- .config = PERF_COUNT_SW_BPF_OUTPUT,
- .type = PERF_TYPE_SOFTWARE,
- .sample_type = PERF_SAMPLE_RAW,
- .sample_period = 1,
- .wakeup_events = 1,
- };
+ struct perf_event_attr attr = { 0, };
+
+ attr.config = PERF_COUNT_SW_BPF_OUTPUT,
+ attr.type = PERF_TYPE_SOFTWARE;
+ attr.sample_type = PERF_SAMPLE_RAW;
+ attr.sample_period = 1;
+ attr.wakeup_events = 1;
p.attr = &attr;
p.sample_cb = opts ? opts->sample_cb : NULL;
@@ -4988,13 +4999,15 @@ int libbpf_num_possible_cpus(void)
static const char *fcpu = "/sys/devices/system/cpu/possible";
int len = 0, n = 0, il = 0, ir = 0;
unsigned int start = 0, end = 0;
+ int tmp_cpus = 0;
static int cpus;
char buf[128];
int error = 0;
int fd = -1;
- if (cpus > 0)
- return cpus;
+ tmp_cpus = READ_ONCE(cpus);
+ if (tmp_cpus > 0)
+ return tmp_cpus;
fd = open(fcpu, O_RDONLY);
if (fd < 0) {
@@ -5017,7 +5030,7 @@ int libbpf_num_possible_cpus(void)
}
buf[len] = '\0';
- for (ir = 0, cpus = 0; ir <= len; ir++) {
+ for (ir = 0, tmp_cpus = 0; ir <= len; ir++) {
/* Each sub string separated by ',' has format \d+-\d+ or \d+ */
if (buf[ir] == ',' || buf[ir] == '\0') {
buf[ir] = '\0';
@@ -5029,13 +5042,15 @@ int libbpf_num_possible_cpus(void)
} else if (n == 1) {
end = start;
}
- cpus += end - start + 1;
+ tmp_cpus += end - start + 1;
il = ir + 1;
}
}
- if (cpus <= 0) {
- pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu);
+ if (tmp_cpus <= 0) {
+ pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
return -EINVAL;
}
- return cpus;
+
+ WRITE_ONCE(cpus, tmp_cpus);
+ return tmp_cpus;
}
diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
index 5007b5d4fd2c..680e63066cf3 100644
--- a/tools/lib/bpf/xsk.c
+++ b/tools/lib/bpf/xsk.c
@@ -317,17 +317,16 @@ static int xsk_load_xdp_prog(struct xsk_socket *xsk)
static int xsk_get_max_queues(struct xsk_socket *xsk)
{
- struct ethtool_channels channels;
- struct ifreq ifr;
+ struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS };
+ struct ifreq ifr = {};
int fd, err, ret;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return -errno;
- channels.cmd = ETHTOOL_GCHANNELS;
ifr.ifr_data = (void *)&channels;
- strncpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
+ memcpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
err = ioctl(fd, SIOCETHTOOL, &ifr);
if (err && errno != EOPNOTSUPP) {
@@ -335,7 +334,7 @@ static int xsk_get_max_queues(struct xsk_socket *xsk)
goto out;
}
- if (channels.max_combined == 0 || errno == EOPNOTSUPP)
+ if (err || channels.max_combined == 0)
/* If the device says it has no channels, then all traffic
* is sent to a single stream, so max queues = 1.
*/
@@ -517,7 +516,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
err = -errno;
goto out_socket;
}
- strncpy(xsk->ifname, ifname, IFNAMSIZ - 1);
+ memcpy(xsk->ifname, ifname, IFNAMSIZ - 1);
xsk->ifname[IFNAMSIZ - 1] = '\0';
err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 3292c290654f..a39cdd0d890d 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -62,15 +62,15 @@ set_plugin_dir := 1
# Set plugin_dir to preffered global plugin location
# If we install under $HOME directory we go under
-# $(HOME)/.traceevent/plugins
+# $(HOME)/.local/lib/traceevent/plugins
#
# We dont set PLUGIN_DIR in case we install under $HOME
# directory, because by default the code looks under:
-# $(HOME)/.traceevent/plugins by default.
+# $(HOME)/.local/lib/traceevent/plugins by default.
#
ifeq ($(plugin_dir),)
ifeq ($(prefix),$(HOME))
-override plugin_dir = $(HOME)/.traceevent/plugins
+override plugin_dir = $(HOME)/.local/lib/traceevent/plugins
set_plugin_dir := 0
else
override plugin_dir = $(libdir)/traceevent/plugins
@@ -266,8 +266,8 @@ endef
define do_generate_dynamic_list_file
symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \
- xargs echo "U W w" | tr ' ' '\n' | sort -u | xargs echo`;\
- if [ "$$symbol_type" = "U W w" ];then \
+ xargs echo "U w W" | tr 'w ' 'W\n' | sort -u | xargs echo`;\
+ if [ "$$symbol_type" = "U W" ];then \
(echo '{'; \
$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\
echo '};'; \
diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c
index 988587840c80..4faf52a65791 100644
--- a/tools/lib/traceevent/event-parse-api.c
+++ b/tools/lib/traceevent/event-parse-api.c
@@ -303,33 +303,6 @@ void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian)
}
/**
- * tep_is_latency_format - get if the latency output format is configured
- * @tep: a handle to the tep_handle
- *
- * This returns true if the latency output format is configured
- * If @tep is NULL, false is returned.
- */
-bool tep_is_latency_format(struct tep_handle *tep)
-{
- if (tep)
- return (tep->latency_format);
- return false;
-}
-
-/**
- * tep_set_latency_format - set the latency output format
- * @tep: a handle to the tep_handle
- * @lat: non zero for latency output format
- *
- * This sets the latency output format
- */
-void tep_set_latency_format(struct tep_handle *tep, int lat)
-{
- if (tep)
- tep->latency_format = lat;
-}
-
-/**
* tep_is_old_format - get if an old kernel is used
* @tep: a handle to the tep_handle
*
@@ -345,19 +318,6 @@ bool tep_is_old_format(struct tep_handle *tep)
}
/**
- * tep_set_print_raw - set a flag to force print in raw format
- * @tep: a handle to the tep_handle
- * @print_raw: the new value of the print_raw flag
- *
- * This sets a flag to force print in raw format
- */
-void tep_set_print_raw(struct tep_handle *tep, int print_raw)
-{
- if (tep)
- tep->print_raw = print_raw;
-}
-
-/**
* tep_set_test_filters - set a flag to test a filter string
* @tep: a handle to the tep_handle
* @test_filters: the new value of the test_filters flag
diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h
index 09aa142f7fdd..cee469803a34 100644
--- a/tools/lib/traceevent/event-parse-local.h
+++ b/tools/lib/traceevent/event-parse-local.h
@@ -28,8 +28,6 @@ struct tep_handle {
enum tep_endian file_bigendian;
enum tep_endian host_bigendian;
- int latency_format;
-
int old_format;
int cpus;
@@ -70,8 +68,6 @@ struct tep_handle {
int ld_offset;
int ld_size;
- int print_raw;
-
int test_filters;
int flags;
@@ -85,8 +81,6 @@ struct tep_handle {
/* cache */
struct tep_event *last_event;
-
- char *trace_clock;
};
void tep_free_event(struct tep_event *event);
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index b36b536a9fcb..bb22238debfe 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -142,6 +142,25 @@ static int cmdline_cmp(const void *a, const void *b)
return 0;
}
+/* Looking for where to place the key */
+static int cmdline_slot_cmp(const void *a, const void *b)
+{
+ const struct tep_cmdline *ca = a;
+ const struct tep_cmdline *cb = b;
+ const struct tep_cmdline *cb1 = cb + 1;
+
+ if (ca->pid < cb->pid)
+ return -1;
+
+ if (ca->pid > cb->pid) {
+ if (ca->pid <= cb1->pid)
+ return 0;
+ return 1;
+ }
+
+ return 0;
+}
+
struct cmdline_list {
struct cmdline_list *next;
char *comm;
@@ -239,6 +258,7 @@ static int add_new_comm(struct tep_handle *tep,
struct tep_cmdline *cmdline;
struct tep_cmdline key;
char *new_comm;
+ int cnt;
if (!pid)
return 0;
@@ -269,21 +289,43 @@ static int add_new_comm(struct tep_handle *tep,
errno = ENOMEM;
return -1;
}
+ tep->cmdlines = cmdlines;
- cmdlines[tep->cmdline_count].comm = strdup(comm);
- if (!cmdlines[tep->cmdline_count].comm) {
- free(cmdlines);
+ key.comm = strdup(comm);
+ if (!key.comm) {
errno = ENOMEM;
return -1;
}
- cmdlines[tep->cmdline_count].pid = pid;
-
- if (cmdlines[tep->cmdline_count].comm)
+ if (!tep->cmdline_count) {
+ /* no entries yet */
+ tep->cmdlines[0] = key;
tep->cmdline_count++;
+ return 0;
+ }
- qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
- tep->cmdlines = cmdlines;
+ /* Now find where we want to store the new cmdline */
+ cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1,
+ sizeof(*tep->cmdlines), cmdline_slot_cmp);
+
+ cnt = tep->cmdline_count;
+ if (cmdline) {
+ /* cmdline points to the one before the spot we want */
+ cmdline++;
+ cnt -= cmdline - tep->cmdlines;
+
+ } else {
+ /* The new entry is either before or after the list */
+ if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) {
+ tep->cmdlines[tep->cmdline_count++] = key;
+ return 0;
+ }
+ cmdline = &tep->cmdlines[0];
+ }
+ memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline)));
+ *cmdline = key;
+
+ tep->cmdline_count++;
return 0;
}
@@ -351,16 +393,6 @@ int tep_override_comm(struct tep_handle *tep, const char *comm, int pid)
return _tep_register_comm(tep, comm, pid, true);
}
-int tep_register_trace_clock(struct tep_handle *tep, const char *trace_clock)
-{
- tep->trace_clock = strdup(trace_clock);
- if (!tep->trace_clock) {
- errno = ENOMEM;
- return -1;
- }
- return 0;
-}
-
struct func_map {
unsigned long long addr;
char *func;
@@ -5170,24 +5202,20 @@ out_failed:
}
}
-/**
- * tep_data_latency_format - parse the data for the latency format
- * @tep: a handle to the trace event parser context
- * @s: the trace_seq to write to
- * @record: the record to read from
- *
+/*
* This parses out the Latency format (interrupts disabled,
* need rescheduling, in hard/soft interrupt, preempt count
* and lock depth) and places it into the trace_seq.
*/
-void tep_data_latency_format(struct tep_handle *tep,
- struct trace_seq *s, struct tep_record *record)
+static void data_latency_format(struct tep_handle *tep, struct trace_seq *s,
+ char *format, struct tep_record *record)
{
static int check_lock_depth = 1;
static int check_migrate_disable = 1;
static int lock_depth_exists;
static int migrate_disable_exists;
unsigned int lat_flags;
+ struct trace_seq sq;
unsigned int pc;
int lock_depth = 0;
int migrate_disable = 0;
@@ -5195,6 +5223,7 @@ void tep_data_latency_format(struct tep_handle *tep,
int softirq;
void *data = record->data;
+ trace_seq_init(&sq);
lat_flags = parse_common_flags(tep, data);
pc = parse_common_pc(tep, data);
/* lock_depth may not always exist */
@@ -5222,7 +5251,7 @@ void tep_data_latency_format(struct tep_handle *tep,
hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
- trace_seq_printf(s, "%c%c%c",
+ trace_seq_printf(&sq, "%c%c%c",
(lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
(lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
'X' : '.',
@@ -5232,24 +5261,32 @@ void tep_data_latency_format(struct tep_handle *tep,
hardirq ? 'h' : softirq ? 's' : '.');
if (pc)
- trace_seq_printf(s, "%x", pc);
+ trace_seq_printf(&sq, "%x", pc);
else
- trace_seq_putc(s, '.');
+ trace_seq_printf(&sq, ".");
if (migrate_disable_exists) {
if (migrate_disable < 0)
- trace_seq_putc(s, '.');
+ trace_seq_printf(&sq, ".");
else
- trace_seq_printf(s, "%d", migrate_disable);
+ trace_seq_printf(&sq, "%d", migrate_disable);
}
if (lock_depth_exists) {
if (lock_depth < 0)
- trace_seq_putc(s, '.');
+ trace_seq_printf(&sq, ".");
else
- trace_seq_printf(s, "%d", lock_depth);
+ trace_seq_printf(&sq, "%d", lock_depth);
+ }
+
+ if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) {
+ s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
+ return;
}
+ trace_seq_terminate(&sq);
+ trace_seq_puts(s, sq.buffer);
+ trace_seq_destroy(&sq);
trace_seq_terminate(s);
}
@@ -5410,21 +5447,16 @@ int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)
return cmdline->pid;
}
-/**
- * tep_event_info - parse the data into the print format
- * @s: the trace_seq to write to
- * @event: the handle to the event
- * @record: the record to read from
- *
+/*
* This parses the raw @data using the given @event information and
* writes the print format into the trace_seq.
*/
-void tep_event_info(struct trace_seq *s, struct tep_event *event,
- struct tep_record *record)
+static void print_event_info(struct trace_seq *s, char *format, bool raw,
+ struct tep_event *event, struct tep_record *record)
{
int print_pretty = 1;
- if (event->tep->print_raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
+ if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
tep_print_fields(s, record->data, record->size, event);
else {
@@ -5439,20 +5471,6 @@ void tep_event_info(struct trace_seq *s, struct tep_event *event,
trace_seq_terminate(s);
}
-static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
-{
- if (!trace_clock || !use_trace_clock)
- return true;
-
- if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
- || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf")
- || !strncmp(trace_clock, "mono", 4))
- return true;
-
- /* trace_clock is setting in tsc or counter mode */
- return false;
-}
-
/**
* tep_find_event_by_record - return the event from a given record
* @tep: a handle to the trace event parser context
@@ -5476,129 +5494,195 @@ tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)
return tep_find_event(tep, type);
}
-/**
- * tep_print_event_task - Write the event task comm, pid and CPU
- * @tep: a handle to the trace event parser context
- * @s: the trace_seq to write to
- * @event: the handle to the record's event
- * @record: The record to get the event from
- *
- * Writes the tasks comm, pid and CPU to @s.
+/*
+ * Writes the timestamp of the record into @s. Time divisor and precision can be
+ * specified as part of printf @format string. Example:
+ * "%3.1000d" - divide the time by 1000 and print the first 3 digits
+ * before the dot. Thus, the timestamp "123456000" will be printed as
+ * "123.456"
*/
-void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record)
+static void print_event_time(struct tep_handle *tep, struct trace_seq *s,
+ char *format, struct tep_event *event,
+ struct tep_record *record)
+{
+ unsigned long long time;
+ char *divstr;
+ int prec = 0, pr;
+ int div = 0;
+ int p10 = 1;
+
+ if (isdigit(*(format + 1)))
+ prec = atoi(format + 1);
+ divstr = strchr(format, '.');
+ if (divstr && isdigit(*(divstr + 1)))
+ div = atoi(divstr + 1);
+ time = record->ts;
+ if (div)
+ time /= div;
+ pr = prec;
+ while (pr--)
+ p10 *= 10;
+
+ if (p10 > 1 && p10 < time)
+ trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10);
+ else
+ trace_seq_printf(s, "%12llu\n", time);
+}
+
+struct print_event_type {
+ enum {
+ EVENT_TYPE_INT = 1,
+ EVENT_TYPE_STRING,
+ EVENT_TYPE_UNKNOWN,
+ } type;
+ char format[32];
+};
+
+static void print_string(struct tep_handle *tep, struct trace_seq *s,
+ struct tep_record *record, struct tep_event *event,
+ const char *arg, struct print_event_type *type)
{
- void *data = record->data;
const char *comm;
int pid;
- pid = parse_common_pid(tep, data);
- comm = find_cmdline(tep, pid);
+ if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) {
+ data_latency_format(tep, s, type->format, record);
+ } else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) {
+ pid = parse_common_pid(tep, record->data);
+ comm = find_cmdline(tep, pid);
+ trace_seq_printf(s, type->format, comm);
+ } else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) {
+ print_event_info(s, type->format, true, event, record);
+ } else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) {
+ print_event_info(s, type->format, false, event, record);
+ } else if (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) {
+ trace_seq_printf(s, type->format, event->name);
+ } else {
+ trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg);
+ }
- if (tep->latency_format)
- trace_seq_printf(s, "%8.8s-%-5d %3d", comm, pid, record->cpu);
- else
- trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
}
-/**
- * tep_print_event_time - Write the event timestamp
- * @tep: a handle to the trace event parser context
- * @s: the trace_seq to write to
- * @event: the handle to the record's event
- * @record: The record to get the event from
- * @use_trace_clock: Set to parse according to the @tep->trace_clock
- *
- * Writes the timestamp of the record into @s.
- */
-void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record,
- bool use_trace_clock)
+static void print_int(struct tep_handle *tep, struct trace_seq *s,
+ struct tep_record *record, struct tep_event *event,
+ int arg, struct print_event_type *type)
{
- unsigned long secs;
- unsigned long usecs;
- unsigned long nsecs;
- int p;
- bool use_usec_format;
+ int param;
- use_usec_format = is_timestamp_in_us(tep->trace_clock, use_trace_clock);
- if (use_usec_format) {
- secs = record->ts / NSEC_PER_SEC;
- nsecs = record->ts - secs * NSEC_PER_SEC;
+ switch (arg) {
+ case TEP_PRINT_CPU:
+ param = record->cpu;
+ break;
+ case TEP_PRINT_PID:
+ param = parse_common_pid(tep, record->data);
+ break;
+ case TEP_PRINT_TIME:
+ return print_event_time(tep, s, type->format, event, record);
+ default:
+ return;
}
+ trace_seq_printf(s, type->format, param);
+}
- if (tep->latency_format) {
- tep_data_latency_format(tep, s, record);
- }
+static int tep_print_event_param_type(char *format,
+ struct print_event_type *type)
+{
+ char *str = format + 1;
+ int i = 1;
- if (use_usec_format) {
- if (tep->flags & TEP_NSEC_OUTPUT) {
- usecs = nsecs;
- p = 9;
- } else {
- usecs = (nsecs + 500) / NSEC_PER_USEC;
- /* To avoid usecs larger than 1 sec */
- if (usecs >= USEC_PER_SEC) {
- usecs -= USEC_PER_SEC;
- secs++;
- }
- p = 6;
+ type->type = EVENT_TYPE_UNKNOWN;
+ while (*str) {
+ switch (*str) {
+ case 'd':
+ case 'u':
+ case 'i':
+ case 'x':
+ case 'X':
+ case 'o':
+ type->type = EVENT_TYPE_INT;
+ break;
+ case 's':
+ type->type = EVENT_TYPE_STRING;
+ break;
}
-
- trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs);
- } else
- trace_seq_printf(s, " %12llu:", record->ts);
+ str++;
+ i++;
+ if (type->type != EVENT_TYPE_UNKNOWN)
+ break;
+ }
+ memset(type->format, 0, 32);
+ memcpy(type->format, format, i < 32 ? i : 31);
+ return i;
}
/**
- * tep_print_event_data - Write the event data section
+ * tep_print_event - Write various event information
* @tep: a handle to the trace event parser context
* @s: the trace_seq to write to
- * @event: the handle to the record's event
* @record: The record to get the event from
- *
- * Writes the parsing of the record's data to @s.
+ * @format: a printf format string. Supported event fileds:
+ * TEP_PRINT_PID, "%d" - event PID
+ * TEP_PRINT_CPU, "%d" - event CPU
+ * TEP_PRINT_COMM, "%s" - event command string
+ * TEP_PRINT_NAME, "%s" - event name
+ * TEP_PRINT_LATENCY, "%s" - event latency
+ * TEP_PRINT_TIME, %d - event time stamp. A divisor and precision
+ * can be specified as part of this format string:
+ * "%precision.divisord". Example:
+ * "%3.1000d" - divide the time by 1000 and print the first
+ * 3 digits before the dot. Thus, the time stamp
+ * "123456000" will be printed as "123.456"
+ * TEP_PRINT_INFO, "%s" - event information. If any width is specified in
+ * the format string, the event information will be printed
+ * in raw format.
+ * Writes the specified event information into @s.
*/
-void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record)
-{
- static const char *spaces = " "; /* 20 spaces */
- int len;
-
- trace_seq_printf(s, " %s: ", event->name);
-
- /* Space out the event names evenly. */
- len = strlen(event->name);
- if (len < 20)
- trace_seq_printf(s, "%.*s", 20 - len, spaces);
-
- tep_event_info(s, event, record);
-}
-
void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
- struct tep_record *record, bool use_trace_clock)
-{
+ struct tep_record *record, const char *fmt, ...)
+{
+ struct print_event_type type;
+ char *format = strdup(fmt);
+ char *current = format;
+ char *str = format;
+ int offset;
+ va_list args;
struct tep_event *event;
- event = tep_find_event_by_record(tep, record);
- if (!event) {
- int i;
- int type = trace_parse_common_type(tep, record->data);
-
- do_warning("ug! no event found for type %d", type);
- trace_seq_printf(s, "[UNKNOWN TYPE %d]", type);
- for (i = 0; i < record->size; i++)
- trace_seq_printf(s, " %02x",
- ((unsigned char *)record->data)[i]);
+ if (!format)
return;
- }
- tep_print_event_task(tep, s, event, record);
- tep_print_event_time(tep, s, event, record, use_trace_clock);
- tep_print_event_data(tep, s, event, record);
+ event = tep_find_event_by_record(tep, record);
+ va_start(args, fmt);
+ while (*current) {
+ current = strchr(str, '%');
+ if (!current) {
+ trace_seq_puts(s, str);
+ break;
+ }
+ memset(&type, 0, sizeof(type));
+ offset = tep_print_event_param_type(current, &type);
+ *current = '\0';
+ trace_seq_puts(s, str);
+ current += offset;
+ switch (type.type) {
+ case EVENT_TYPE_STRING:
+ print_string(tep, s, record, event,
+ va_arg(args, char*), &type);
+ break;
+ case EVENT_TYPE_INT:
+ print_int(tep, s, record, event,
+ va_arg(args, int), &type);
+ break;
+ case EVENT_TYPE_UNKNOWN:
+ default:
+ trace_seq_printf(s, "[UNKNOWN TYPE]");
+ break;
+ }
+ str = current;
+
+ }
+ va_end(args);
+ free(format);
}
static int events_id_cmp(const void *a, const void *b)
@@ -6963,7 +7047,6 @@ void tep_free(struct tep_handle *tep)
free_handler(handle);
}
- free(tep->trace_clock);
free(tep->events);
free(tep->sort_events);
free(tep->func_resolver);
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 642f68ab5fb2..d438ee44289f 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -435,25 +435,24 @@ int tep_set_function_resolver(struct tep_handle *tep,
void tep_reset_function_resolver(struct tep_handle *tep);
int tep_register_comm(struct tep_handle *tep, const char *comm, int pid);
int tep_override_comm(struct tep_handle *tep, const char *comm, int pid);
-int tep_register_trace_clock(struct tep_handle *tep, const char *trace_clock);
int tep_register_function(struct tep_handle *tep, char *name,
unsigned long long addr, char *mod);
int tep_register_print_string(struct tep_handle *tep, const char *fmt,
unsigned long long addr);
bool tep_is_pid_registered(struct tep_handle *tep, int pid);
-void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record);
-void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record,
- bool use_trace_clock);
-void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s,
- struct tep_event *event,
- struct tep_record *record);
+#define TEP_PRINT_INFO "INFO"
+#define TEP_PRINT_INFO_RAW "INFO_RAW"
+#define TEP_PRINT_COMM "COMM"
+#define TEP_PRINT_LATENCY "LATENCY"
+#define TEP_PRINT_NAME "NAME"
+#define TEP_PRINT_PID 1U
+#define TEP_PRINT_TIME 2U
+#define TEP_PRINT_CPU 3U
+
void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
- struct tep_record *record, bool use_trace_clock);
+ struct tep_record *record, const char *fmt, ...)
+ __attribute__ ((format (printf, 4, 5)));
int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,
int long_size);
@@ -525,8 +524,6 @@ tep_find_event_by_name(struct tep_handle *tep, const char *sys, const char *name
struct tep_event *
tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record);
-void tep_data_latency_format(struct tep_handle *tep,
- struct trace_seq *s, struct tep_record *record);
int tep_data_type(struct tep_handle *tep, struct tep_record *rec);
int tep_data_pid(struct tep_handle *tep, struct tep_record *rec);
int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec);
@@ -541,8 +538,6 @@ void tep_print_field(struct trace_seq *s, void *data,
struct tep_format_field *field);
void tep_print_fields(struct trace_seq *s, void *data,
int size __maybe_unused, struct tep_event *event);
-void tep_event_info(struct trace_seq *s, struct tep_event *event,
- struct tep_record *record);
int tep_strerror(struct tep_handle *tep, enum tep_errno errnum,
char *buf, size_t buflen);
@@ -566,12 +561,9 @@ bool tep_is_file_bigendian(struct tep_handle *tep);
void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian);
bool tep_is_local_bigendian(struct tep_handle *tep);
void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian);
-bool tep_is_latency_format(struct tep_handle *tep);
-void tep_set_latency_format(struct tep_handle *tep, int lat);
int tep_get_header_page_size(struct tep_handle *tep);
int tep_get_header_timestamp_size(struct tep_handle *tep);
bool tep_is_old_format(struct tep_handle *tep);
-void tep_set_print_raw(struct tep_handle *tep, int print_raw);
void tep_set_test_filters(struct tep_handle *tep, int test_filters);
struct tep_handle *tep_alloc(void);
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 8ca28de9337a..e1f7ddd5a6cf 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -18,7 +18,7 @@
#include "event-utils.h"
#include "trace-seq.h"
-#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
+#define LOCAL_PLUGIN_DIR ".local/lib/traceevent/plugins/"
static struct registered_plugin_options {
struct registered_plugin_options *next;
diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
index 68caa9a976d0..488f11f6c588 100644
--- a/tools/memory-model/Documentation/explanation.txt
+++ b/tools/memory-model/Documentation/explanation.txt
@@ -42,7 +42,8 @@ linux-kernel.bell and linux-kernel.cat files that make up the formal
version of the model; they are extremely terse and their meanings are
far from clear.
-This document describes the ideas underlying the LKMM. It is meant
+This document describes the ideas underlying the LKMM, but excluding
+the modeling of bare C (or plain) shared memory accesses. It is meant
for people who want to understand how the model was designed. It does
not go into the details of the code in the .bell and .cat files;
rather, it explains in English what the code expresses symbolically.
@@ -354,31 +355,25 @@ be extremely complex.
Optimizing compilers have great freedom in the way they translate
source code to object code. They are allowed to apply transformations
that add memory accesses, eliminate accesses, combine them, split them
-into pieces, or move them around. Faced with all these possibilities,
-the LKMM basically gives up. It insists that the code it analyzes
-must contain no ordinary accesses to shared memory; all accesses must
-be performed using READ_ONCE(), WRITE_ONCE(), or one of the other
-atomic or synchronization primitives. These primitives prevent a
-large number of compiler optimizations. In particular, it is
-guaranteed that the compiler will not remove such accesses from the
-generated code (unless it can prove the accesses will never be
-executed), it will not change the order in which they occur in the
-code (within limits imposed by the C standard), and it will not
-introduce extraneous accesses.
-
-This explains why the MP and SB examples above used READ_ONCE() and
-WRITE_ONCE() rather than ordinary memory accesses. Thanks to this
-usage, we can be certain that in the MP example, P0's write event to
-buf really is po-before its write event to flag, and similarly for the
-other shared memory accesses in the examples.
-
-Private variables are not subject to this restriction. Since they are
-not shared between CPUs, they can be accessed normally without
-READ_ONCE() or WRITE_ONCE(), and there will be no ill effects. In
-fact, they need not even be stored in normal memory at all -- in
-principle a private variable could be stored in a CPU register (hence
-the convention that these variables have names starting with the
-letter 'r').
+into pieces, or move them around. The use of READ_ONCE(), WRITE_ONCE(),
+or one of the other atomic or synchronization primitives prevents a
+large number of compiler optimizations. In particular, it is guaranteed
+that the compiler will not remove such accesses from the generated code
+(unless it can prove the accesses will never be executed), it will not
+change the order in which they occur in the code (within limits imposed
+by the C standard), and it will not introduce extraneous accesses.
+
+The MP and SB examples above used READ_ONCE() and WRITE_ONCE() rather
+than ordinary memory accesses. Thanks to this usage, we can be certain
+that in the MP example, the compiler won't reorder P0's write event to
+buf and P0's write event to flag, and similarly for the other shared
+memory accesses in the examples.
+
+Since private variables are not shared between CPUs, they can be
+accessed normally without READ_ONCE() or WRITE_ONCE(). In fact, they
+need not even be stored in normal memory at all -- in principle a
+private variable could be stored in a CPU register (hence the convention
+that these variables have names starting with the letter 'r').
A WARNING
@@ -1302,7 +1297,7 @@ followed by an arbitrary number of cumul-fence links, ending with an
rfe link. You can concoct more exotic examples, containing more than
one fence, although this quickly leads to diminishing returns in terms
of complexity. For instance, here's an example containing a coe link
-followed by two fences and an rfe link, utilizing the fact that
+followed by two cumul-fences and an rfe link, utilizing the fact that
release fences are A-cumulative:
int x, y, z;
@@ -1334,10 +1329,10 @@ If x = 2, r0 = 1, and r2 = 1 after this code runs then there is a prop
link from P0's store to its load. This is because P0's store gets
overwritten by P1's store since x = 2 at the end (a coe link), the
smp_wmb() ensures that P1's store to x propagates to P2 before the
-store to y does (the first fence), the store to y propagates to P2
+store to y does (the first cumul-fence), the store to y propagates to P2
before P2's load and store execute, P2's smp_store_release()
guarantees that the stores to x and y both propagate to P0 before the
-store to z does (the second fence), and P0's load executes after the
+store to z does (the second cumul-fence), and P0's load executes after the
store to z has propagated to P0 (an rfe link).
In summary, the fact that the hb relation links memory access events
diff --git a/tools/memory-model/README b/tools/memory-model/README
index 2b87f3971548..fc07b52f2028 100644
--- a/tools/memory-model/README
+++ b/tools/memory-model/README
@@ -167,15 +167,15 @@ scripts Various scripts, see scripts/README.
LIMITATIONS
===========
-The Linux-kernel memory model has the following limitations:
-
-1. Compiler optimizations are not modeled. Of course, the use
- of READ_ONCE() and WRITE_ONCE() limits the compiler's ability
- to optimize, but there is Linux-kernel code that uses bare C
- memory accesses. Handling this code is on the to-do list.
- For more information, see Documentation/explanation.txt (in
- particular, the "THE PROGRAM ORDER RELATION: po AND po-loc"
- and "A WARNING" sections).
+The Linux-kernel memory model (LKMM) has the following limitations:
+
+1. Compiler optimizations are not accurately modeled. Of course,
+ the use of READ_ONCE() and WRITE_ONCE() limits the compiler's
+ ability to optimize, but under some circumstances it is possible
+ for the compiler to undermine the memory model. For more
+ information, see Documentation/explanation.txt (in particular,
+ the "THE PROGRAM ORDER RELATION: po AND po-loc" and "A WARNING"
+ sections).
Note that this limitation in turn limits LKMM's ability to
accurately model address, control, and data dependencies.
diff --git a/tools/memory-model/scripts/checkghlitmus.sh b/tools/memory-model/scripts/checkghlitmus.sh
index 6589fbb6f653..6589fbb6f653 100644..100755
--- a/tools/memory-model/scripts/checkghlitmus.sh
+++ b/tools/memory-model/scripts/checkghlitmus.sh
diff --git a/tools/memory-model/scripts/checklitmushist.sh b/tools/memory-model/scripts/checklitmushist.sh
index 1d210ffb7c8a..1d210ffb7c8a 100644..100755
--- a/tools/memory-model/scripts/checklitmushist.sh
+++ b/tools/memory-model/scripts/checklitmushist.sh
diff --git a/tools/memory-model/scripts/cmplitmushist.sh b/tools/memory-model/scripts/cmplitmushist.sh
index 0f498aeeccf5..0f498aeeccf5 100644..100755
--- a/tools/memory-model/scripts/cmplitmushist.sh
+++ b/tools/memory-model/scripts/cmplitmushist.sh
diff --git a/tools/memory-model/scripts/initlitmushist.sh b/tools/memory-model/scripts/initlitmushist.sh
index 956b6957484d..956b6957484d 100644..100755
--- a/tools/memory-model/scripts/initlitmushist.sh
+++ b/tools/memory-model/scripts/initlitmushist.sh
diff --git a/tools/memory-model/scripts/judgelitmus.sh b/tools/memory-model/scripts/judgelitmus.sh
index 0cc63875e395..0cc63875e395 100644..100755
--- a/tools/memory-model/scripts/judgelitmus.sh
+++ b/tools/memory-model/scripts/judgelitmus.sh
diff --git a/tools/memory-model/scripts/newlitmushist.sh b/tools/memory-model/scripts/newlitmushist.sh
index 991f8f814881..991f8f814881 100644..100755
--- a/tools/memory-model/scripts/newlitmushist.sh
+++ b/tools/memory-model/scripts/newlitmushist.sh
diff --git a/tools/memory-model/scripts/parseargs.sh b/tools/memory-model/scripts/parseargs.sh
index 40f52080fdbd..40f52080fdbd 100644..100755
--- a/tools/memory-model/scripts/parseargs.sh
+++ b/tools/memory-model/scripts/parseargs.sh
diff --git a/tools/memory-model/scripts/runlitmushist.sh b/tools/memory-model/scripts/runlitmushist.sh
index 6ed376f495bb..6ed376f495bb 100644..100755
--- a/tools/memory-model/scripts/runlitmushist.sh
+++ b/tools/memory-model/scripts/runlitmushist.sh
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 88158239622b..d2a19b0bc05a 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -33,9 +33,9 @@ all: $(OBJTOOL)
INCLUDES := -I$(srctree)/tools/include \
-I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \
- -I$(srctree)/tools/objtool/arch/$(ARCH)/include
+ -I$(srctree)/tools/arch/$(ARCH)/include
WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed
-CFLAGS += -Werror $(WARNINGS) $(KBUILD_HOSTCFLAGS) -g $(INCLUDES) $(LIBELF_FLAGS)
+CFLAGS := -Werror $(WARNINGS) $(KBUILD_HOSTCFLAGS) -g $(INCLUDES) $(LIBELF_FLAGS)
LDFLAGS += $(LIBELF_LIBS) $(LIBSUBCMD) $(KBUILD_HOSTLDFLAGS)
# Allow old libelf to be used:
@@ -60,7 +60,7 @@ $(LIBSUBCMD): fixdep FORCE
clean:
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
$(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
- $(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep
+ $(Q)$(RM) $(OUTPUT)arch/x86/inat-tables.c $(OUTPUT)fixdep
FORCE:
diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build
index b998412c017d..7c5004008e97 100644
--- a/tools/objtool/arch/x86/Build
+++ b/tools/objtool/arch/x86/Build
@@ -1,7 +1,7 @@
objtool-y += decode.o
-inat_tables_script = arch/x86/tools/gen-insn-attr-x86.awk
-inat_tables_maps = arch/x86/lib/x86-opcode-map.txt
+inat_tables_script = ../arch/x86/tools/gen-insn-attr-x86.awk
+inat_tables_maps = ../arch/x86/lib/x86-opcode-map.txt
$(OUTPUT)arch/x86/lib/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
$(call rule_mkdir)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 0567c47a91b1..a62e032863a8 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -8,8 +8,8 @@
#define unlikely(cond) (cond)
#include <asm/insn.h>
-#include "lib/inat.c"
-#include "lib/insn.c"
+#include "../../../arch/x86/lib/inat.c"
+#include "../../../arch/x86/lib/insn.c"
#include "../../elf.h"
#include "../../arch.h"
diff --git a/tools/objtool/arch/x86/include/asm/inat.h b/tools/objtool/arch/x86/include/asm/inat.h
deleted file mode 100644
index 4cf2ad521f65..000000000000
--- a/tools/objtool/arch/x86/include/asm/inat.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_X86_INAT_H
-#define _ASM_X86_INAT_H
-/*
- * x86 instruction attributes
- *
- * Written by Masami Hiramatsu <mhiramat@redhat.com>
- */
-#include <asm/inat_types.h>
-
-/*
- * Internal bits. Don't use bitmasks directly, because these bits are
- * unstable. You should use checking functions.
- */
-
-#define INAT_OPCODE_TABLE_SIZE 256
-#define INAT_GROUP_TABLE_SIZE 8
-
-/* Legacy last prefixes */
-#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
-#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
-#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
-/* Other Legacy prefixes */
-#define INAT_PFX_LOCK 4 /* 0xF0 */
-#define INAT_PFX_CS 5 /* 0x2E */
-#define INAT_PFX_DS 6 /* 0x3E */
-#define INAT_PFX_ES 7 /* 0x26 */
-#define INAT_PFX_FS 8 /* 0x64 */
-#define INAT_PFX_GS 9 /* 0x65 */
-#define INAT_PFX_SS 10 /* 0x36 */
-#define INAT_PFX_ADDRSZ 11 /* 0x67 */
-/* x86-64 REX prefix */
-#define INAT_PFX_REX 12 /* 0x4X */
-/* AVX VEX prefixes */
-#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
-#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
-#define INAT_PFX_EVEX 15 /* EVEX prefix */
-
-#define INAT_LSTPFX_MAX 3
-#define INAT_LGCPFX_MAX 11
-
-/* Immediate size */
-#define INAT_IMM_BYTE 1
-#define INAT_IMM_WORD 2
-#define INAT_IMM_DWORD 3
-#define INAT_IMM_QWORD 4
-#define INAT_IMM_PTR 5
-#define INAT_IMM_VWORD32 6
-#define INAT_IMM_VWORD 7
-
-/* Legacy prefix */
-#define INAT_PFX_OFFS 0
-#define INAT_PFX_BITS 4
-#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
-#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
-/* Escape opcodes */
-#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
-#define INAT_ESC_BITS 2
-#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
-#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
-/* Group opcodes (1-16) */
-#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
-#define INAT_GRP_BITS 5
-#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
-#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
-/* Immediates */
-#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
-#define INAT_IMM_BITS 3
-#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
-/* Flags */
-#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
-#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
-#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
-#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
-#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
-#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
-#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
-#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
-#define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7))
-/* Attribute making macros for attribute tables */
-#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
-#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
-#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
-#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
-
-/* Identifiers for segment registers */
-#define INAT_SEG_REG_IGNORE 0
-#define INAT_SEG_REG_DEFAULT 1
-#define INAT_SEG_REG_CS 2
-#define INAT_SEG_REG_SS 3
-#define INAT_SEG_REG_DS 4
-#define INAT_SEG_REG_ES 5
-#define INAT_SEG_REG_FS 6
-#define INAT_SEG_REG_GS 7
-
-/* Attribute search APIs */
-extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
-extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
-extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
- int lpfx_id,
- insn_attr_t esc_attr);
-extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
- int lpfx_id,
- insn_attr_t esc_attr);
-extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
- insn_byte_t vex_m,
- insn_byte_t vex_pp);
-
-/* Attribute checking functions */
-static inline int inat_is_legacy_prefix(insn_attr_t attr)
-{
- attr &= INAT_PFX_MASK;
- return attr && attr <= INAT_LGCPFX_MAX;
-}
-
-static inline int inat_is_address_size_prefix(insn_attr_t attr)
-{
- return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
-}
-
-static inline int inat_is_operand_size_prefix(insn_attr_t attr)
-{
- return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
-}
-
-static inline int inat_is_rex_prefix(insn_attr_t attr)
-{
- return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
-}
-
-static inline int inat_last_prefix_id(insn_attr_t attr)
-{
- if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
- return 0;
- else
- return attr & INAT_PFX_MASK;
-}
-
-static inline int inat_is_vex_prefix(insn_attr_t attr)
-{
- attr &= INAT_PFX_MASK;
- return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 ||
- attr == INAT_PFX_EVEX;
-}
-
-static inline int inat_is_evex_prefix(insn_attr_t attr)
-{
- return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX;
-}
-
-static inline int inat_is_vex3_prefix(insn_attr_t attr)
-{
- return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
-}
-
-static inline int inat_is_escape(insn_attr_t attr)
-{
- return attr & INAT_ESC_MASK;
-}
-
-static inline int inat_escape_id(insn_attr_t attr)
-{
- return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
-}
-
-static inline int inat_is_group(insn_attr_t attr)
-{
- return attr & INAT_GRP_MASK;
-}
-
-static inline int inat_group_id(insn_attr_t attr)
-{
- return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
-}
-
-static inline int inat_group_common_attribute(insn_attr_t attr)
-{
- return attr & ~INAT_GRP_MASK;
-}
-
-static inline int inat_has_immediate(insn_attr_t attr)
-{
- return attr & INAT_IMM_MASK;
-}
-
-static inline int inat_immediate_size(insn_attr_t attr)
-{
- return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
-}
-
-static inline int inat_has_modrm(insn_attr_t attr)
-{
- return attr & INAT_MODRM;
-}
-
-static inline int inat_is_force64(insn_attr_t attr)
-{
- return attr & INAT_FORCE64;
-}
-
-static inline int inat_has_second_immediate(insn_attr_t attr)
-{
- return attr & INAT_SCNDIMM;
-}
-
-static inline int inat_has_moffset(insn_attr_t attr)
-{
- return attr & INAT_MOFFSET;
-}
-
-static inline int inat_has_variant(insn_attr_t attr)
-{
- return attr & INAT_VARIANT;
-}
-
-static inline int inat_accept_vex(insn_attr_t attr)
-{
- return attr & INAT_VEXOK;
-}
-
-static inline int inat_must_vex(insn_attr_t attr)
-{
- return attr & (INAT_VEXONLY | INAT_EVEXONLY);
-}
-
-static inline int inat_must_evex(insn_attr_t attr)
-{
- return attr & INAT_EVEXONLY;
-}
-#endif
diff --git a/tools/objtool/arch/x86/include/asm/insn.h b/tools/objtool/arch/x86/include/asm/insn.h
deleted file mode 100644
index 154f27be8bfc..000000000000
--- a/tools/objtool/arch/x86/include/asm/insn.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_X86_INSN_H
-#define _ASM_X86_INSN_H
-/*
- * x86 instruction analysis
- *
- * Copyright (C) IBM Corporation, 2009
- */
-
-/* insn_attr_t is defined in inat.h */
-#include <asm/inat.h>
-
-struct insn_field {
- union {
- insn_value_t value;
- insn_byte_t bytes[4];
- };
- /* !0 if we've run insn_get_xxx() for this field */
- unsigned char got;
- unsigned char nbytes;
-};
-
-struct insn {
- struct insn_field prefixes; /*
- * Prefixes
- * prefixes.bytes[3]: last prefix
- */
- struct insn_field rex_prefix; /* REX prefix */
- struct insn_field vex_prefix; /* VEX prefix */
- struct insn_field opcode; /*
- * opcode.bytes[0]: opcode1
- * opcode.bytes[1]: opcode2
- * opcode.bytes[2]: opcode3
- */
- struct insn_field modrm;
- struct insn_field sib;
- struct insn_field displacement;
- union {
- struct insn_field immediate;
- struct insn_field moffset1; /* for 64bit MOV */
- struct insn_field immediate1; /* for 64bit imm or off16/32 */
- };
- union {
- struct insn_field moffset2; /* for 64bit MOV */
- struct insn_field immediate2; /* for 64bit imm or seg16 */
- };
-
- insn_attr_t attr;
- unsigned char opnd_bytes;
- unsigned char addr_bytes;
- unsigned char length;
- unsigned char x86_64;
-
- const insn_byte_t *kaddr; /* kernel address of insn to analyze */
- const insn_byte_t *end_kaddr; /* kernel address of last insn in buffer */
- const insn_byte_t *next_byte;
-};
-
-#define MAX_INSN_SIZE 15
-
-#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
-#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
-#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
-
-#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
-#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
-#define X86_SIB_BASE(sib) ((sib) & 0x07)
-
-#define X86_REX_W(rex) ((rex) & 8)
-#define X86_REX_R(rex) ((rex) & 4)
-#define X86_REX_X(rex) ((rex) & 2)
-#define X86_REX_B(rex) ((rex) & 1)
-
-/* VEX bit flags */
-#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
-#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
-#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
-#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
-#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
-/* VEX bit fields */
-#define X86_EVEX_M(vex) ((vex) & 0x03) /* EVEX Byte1 */
-#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
-#define X86_VEX2_M 1 /* VEX2.M always 1 */
-#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
-#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
-#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
-
-extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
-extern void insn_get_prefixes(struct insn *insn);
-extern void insn_get_opcode(struct insn *insn);
-extern void insn_get_modrm(struct insn *insn);
-extern void insn_get_sib(struct insn *insn);
-extern void insn_get_displacement(struct insn *insn);
-extern void insn_get_immediate(struct insn *insn);
-extern void insn_get_length(struct insn *insn);
-
-/* Attribute will be determined after getting ModRM (for opcode groups) */
-static inline void insn_get_attribute(struct insn *insn)
-{
- insn_get_modrm(insn);
-}
-
-/* Instruction uses RIP-relative addressing */
-extern int insn_rip_relative(struct insn *insn);
-
-/* Init insn for kernel text */
-static inline void kernel_insn_init(struct insn *insn,
- const void *kaddr, int buf_len)
-{
-#ifdef CONFIG_X86_64
- insn_init(insn, kaddr, buf_len, 1);
-#else /* CONFIG_X86_32 */
- insn_init(insn, kaddr, buf_len, 0);
-#endif
-}
-
-static inline int insn_is_avx(struct insn *insn)
-{
- if (!insn->prefixes.got)
- insn_get_prefixes(insn);
- return (insn->vex_prefix.value != 0);
-}
-
-static inline int insn_is_evex(struct insn *insn)
-{
- if (!insn->prefixes.got)
- insn_get_prefixes(insn);
- return (insn->vex_prefix.nbytes == 4);
-}
-
-/* Ensure this instruction is decoded completely */
-static inline int insn_complete(struct insn *insn)
-{
- return insn->opcode.got && insn->modrm.got && insn->sib.got &&
- insn->displacement.got && insn->immediate.got;
-}
-
-static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
-{
- if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
- return X86_VEX2_M;
- else if (insn->vex_prefix.nbytes == 3) /* 3 bytes VEX */
- return X86_VEX3_M(insn->vex_prefix.bytes[1]);
- else /* EVEX */
- return X86_EVEX_M(insn->vex_prefix.bytes[1]);
-}
-
-static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
-{
- if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
- return X86_VEX_P(insn->vex_prefix.bytes[1]);
- else
- return X86_VEX_P(insn->vex_prefix.bytes[2]);
-}
-
-/* Get the last prefix id from last prefix or VEX prefix */
-static inline int insn_last_prefix_id(struct insn *insn)
-{
- if (insn_is_avx(insn))
- return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
-
- if (insn->prefixes.bytes[3])
- return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
-
- return 0;
-}
-
-/* Offset of each field from kaddr */
-static inline int insn_offset_rex_prefix(struct insn *insn)
-{
- return insn->prefixes.nbytes;
-}
-static inline int insn_offset_vex_prefix(struct insn *insn)
-{
- return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
-}
-static inline int insn_offset_opcode(struct insn *insn)
-{
- return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
-}
-static inline int insn_offset_modrm(struct insn *insn)
-{
- return insn_offset_opcode(insn) + insn->opcode.nbytes;
-}
-static inline int insn_offset_sib(struct insn *insn)
-{
- return insn_offset_modrm(insn) + insn->modrm.nbytes;
-}
-static inline int insn_offset_displacement(struct insn *insn)
-{
- return insn_offset_sib(insn) + insn->sib.nbytes;
-}
-static inline int insn_offset_immediate(struct insn *insn)
-{
- return insn_offset_displacement(insn) + insn->displacement.nbytes;
-}
-
-#define POP_SS_OPCODE 0x1f
-#define MOV_SREG_OPCODE 0x8e
-
-/*
- * Intel SDM Vol.3A 6.8.3 states;
- * "Any single-step trap that would be delivered following the MOV to SS
- * instruction or POP to SS instruction (because EFLAGS.TF is 1) is
- * suppressed."
- * This function returns true if @insn is MOV SS or POP SS. On these
- * instructions, single stepping is suppressed.
- */
-static inline int insn_masking_exception(struct insn *insn)
-{
- return insn->opcode.bytes[0] == POP_SS_OPCODE ||
- (insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
- X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
-}
-
-#endif /* _ASM_X86_INSN_H */
diff --git a/tools/objtool/arch/x86/lib/insn.c b/tools/objtool/arch/x86/lib/insn.c
deleted file mode 100644
index 0b5862ba6a75..000000000000
--- a/tools/objtool/arch/x86/lib/insn.c
+++ /dev/null
@@ -1,593 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * x86 instruction analysis
- *
- * Copyright (C) IBM Corporation, 2002, 2004, 2009
- */
-
-#ifdef __KERNEL__
-#include <linux/string.h>
-#else
-#include <string.h>
-#endif
-#include <asm/inat.h>
-#include <asm/insn.h>
-
-/* Verify next sizeof(t) bytes can be on the same instruction */
-#define validate_next(t, insn, n) \
- ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
-
-#define __get_next(t, insn) \
- ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
-
-#define __peek_nbyte_next(t, insn, n) \
- ({ t r = *(t*)((insn)->next_byte + n); r; })
-
-#define get_next(t, insn) \
- ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
-
-#define peek_nbyte_next(t, insn, n) \
- ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
-
-#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
-
-/**
- * insn_init() - initialize struct insn
- * @insn: &struct insn to be initialized
- * @kaddr: address (in kernel memory) of instruction (or copy thereof)
- * @x86_64: !0 for 64-bit kernel or 64-bit app
- */
-void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
-{
- /*
- * Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid
- * even if the input buffer is long enough to hold them.
- */
- if (buf_len > MAX_INSN_SIZE)
- buf_len = MAX_INSN_SIZE;
-
- memset(insn, 0, sizeof(*insn));
- insn->kaddr = kaddr;
- insn->end_kaddr = kaddr + buf_len;
- insn->next_byte = kaddr;
- insn->x86_64 = x86_64 ? 1 : 0;
- insn->opnd_bytes = 4;
- if (x86_64)
- insn->addr_bytes = 8;
- else
- insn->addr_bytes = 4;
-}
-
-/**
- * insn_get_prefixes - scan x86 instruction prefix bytes
- * @insn: &struct insn containing instruction
- *
- * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
- * to point to the (first) opcode. No effect if @insn->prefixes.got
- * is already set.
- */
-void insn_get_prefixes(struct insn *insn)
-{
- struct insn_field *prefixes = &insn->prefixes;
- insn_attr_t attr;
- insn_byte_t b, lb;
- int i, nb;
-
- if (prefixes->got)
- return;
-
- nb = 0;
- lb = 0;
- b = peek_next(insn_byte_t, insn);
- attr = inat_get_opcode_attribute(b);
- while (inat_is_legacy_prefix(attr)) {
- /* Skip if same prefix */
- for (i = 0; i < nb; i++)
- if (prefixes->bytes[i] == b)
- goto found;
- if (nb == 4)
- /* Invalid instruction */
- break;
- prefixes->bytes[nb++] = b;
- if (inat_is_address_size_prefix(attr)) {
- /* address size switches 2/4 or 4/8 */
- if (insn->x86_64)
- insn->addr_bytes ^= 12;
- else
- insn->addr_bytes ^= 6;
- } else if (inat_is_operand_size_prefix(attr)) {
- /* oprand size switches 2/4 */
- insn->opnd_bytes ^= 6;
- }
-found:
- prefixes->nbytes++;
- insn->next_byte++;
- lb = b;
- b = peek_next(insn_byte_t, insn);
- attr = inat_get_opcode_attribute(b);
- }
- /* Set the last prefix */
- if (lb && lb != insn->prefixes.bytes[3]) {
- if (unlikely(insn->prefixes.bytes[3])) {
- /* Swap the last prefix */
- b = insn->prefixes.bytes[3];
- for (i = 0; i < nb; i++)
- if (prefixes->bytes[i] == lb)
- prefixes->bytes[i] = b;
- }
- insn->prefixes.bytes[3] = lb;
- }
-
- /* Decode REX prefix */
- if (insn->x86_64) {
- b = peek_next(insn_byte_t, insn);
- attr = inat_get_opcode_attribute(b);
- if (inat_is_rex_prefix(attr)) {
- insn->rex_prefix.value = b;
- insn->rex_prefix.nbytes = 1;
- insn->next_byte++;
- if (X86_REX_W(b))
- /* REX.W overrides opnd_size */
- insn->opnd_bytes = 8;
- }
- }
- insn->rex_prefix.got = 1;
-
- /* Decode VEX prefix */
- b = peek_next(insn_byte_t, insn);
- attr = inat_get_opcode_attribute(b);
- if (inat_is_vex_prefix(attr)) {
- insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
- if (!insn->x86_64) {
- /*
- * In 32-bits mode, if the [7:6] bits (mod bits of
- * ModRM) on the second byte are not 11b, it is
- * LDS or LES or BOUND.
- */
- if (X86_MODRM_MOD(b2) != 3)
- goto vex_end;
- }
- insn->vex_prefix.bytes[0] = b;
- insn->vex_prefix.bytes[1] = b2;
- if (inat_is_evex_prefix(attr)) {
- b2 = peek_nbyte_next(insn_byte_t, insn, 2);
- insn->vex_prefix.bytes[2] = b2;
- b2 = peek_nbyte_next(insn_byte_t, insn, 3);
- insn->vex_prefix.bytes[3] = b2;
- insn->vex_prefix.nbytes = 4;
- insn->next_byte += 4;
- if (insn->x86_64 && X86_VEX_W(b2))
- /* VEX.W overrides opnd_size */
- insn->opnd_bytes = 8;
- } else if (inat_is_vex3_prefix(attr)) {
- b2 = peek_nbyte_next(insn_byte_t, insn, 2);
- insn->vex_prefix.bytes[2] = b2;
- insn->vex_prefix.nbytes = 3;
- insn->next_byte += 3;
- if (insn->x86_64 && X86_VEX_W(b2))
- /* VEX.W overrides opnd_size */
- insn->opnd_bytes = 8;
- } else {
- /*
- * For VEX2, fake VEX3-like byte#2.
- * Makes it easier to decode vex.W, vex.vvvv,
- * vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.
- */
- insn->vex_prefix.bytes[2] = b2 & 0x7f;
- insn->vex_prefix.nbytes = 2;
- insn->next_byte += 2;
- }
- }
-vex_end:
- insn->vex_prefix.got = 1;
-
- prefixes->got = 1;
-
-err_out:
- return;
-}
-
-/**
- * insn_get_opcode - collect opcode(s)
- * @insn: &struct insn containing instruction
- *
- * Populates @insn->opcode, updates @insn->next_byte to point past the
- * opcode byte(s), and set @insn->attr (except for groups).
- * If necessary, first collects any preceding (prefix) bytes.
- * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got
- * is already 1.
- */
-void insn_get_opcode(struct insn *insn)
-{
- struct insn_field *opcode = &insn->opcode;
- insn_byte_t op;
- int pfx_id;
- if (opcode->got)
- return;
- if (!insn->prefixes.got)
- insn_get_prefixes(insn);
-
- /* Get first opcode */
- op = get_next(insn_byte_t, insn);
- opcode->bytes[0] = op;
- opcode->nbytes = 1;
-
- /* Check if there is VEX prefix or not */
- if (insn_is_avx(insn)) {
- insn_byte_t m, p;
- m = insn_vex_m_bits(insn);
- p = insn_vex_p_bits(insn);
- insn->attr = inat_get_avx_attribute(op, m, p);
- if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
- (!inat_accept_vex(insn->attr) &&
- !inat_is_group(insn->attr)))
- insn->attr = 0; /* This instruction is bad */
- goto end; /* VEX has only 1 byte for opcode */
- }
-
- insn->attr = inat_get_opcode_attribute(op);
- while (inat_is_escape(insn->attr)) {
- /* Get escaped opcode */
- op = get_next(insn_byte_t, insn);
- opcode->bytes[opcode->nbytes++] = op;
- pfx_id = insn_last_prefix_id(insn);
- insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
- }
- if (inat_must_vex(insn->attr))
- insn->attr = 0; /* This instruction is bad */
-end:
- opcode->got = 1;
-
-err_out:
- return;
-}
-
-/**
- * insn_get_modrm - collect ModRM byte, if any
- * @insn: &struct insn containing instruction
- *
- * Populates @insn->modrm and updates @insn->next_byte to point past the
- * ModRM byte, if any. If necessary, first collects the preceding bytes
- * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1.
- */
-void insn_get_modrm(struct insn *insn)
-{
- struct insn_field *modrm = &insn->modrm;
- insn_byte_t pfx_id, mod;
- if (modrm->got)
- return;
- if (!insn->opcode.got)
- insn_get_opcode(insn);
-
- if (inat_has_modrm(insn->attr)) {
- mod = get_next(insn_byte_t, insn);
- modrm->value = mod;
- modrm->nbytes = 1;
- if (inat_is_group(insn->attr)) {
- pfx_id = insn_last_prefix_id(insn);
- insn->attr = inat_get_group_attribute(mod, pfx_id,
- insn->attr);
- if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
- insn->attr = 0; /* This is bad */
- }
- }
-
- if (insn->x86_64 && inat_is_force64(insn->attr))
- insn->opnd_bytes = 8;
- modrm->got = 1;
-
-err_out:
- return;
-}
-
-
-/**
- * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
- * @insn: &struct insn containing instruction
- *
- * If necessary, first collects the instruction up to and including the
- * ModRM byte. No effect if @insn->x86_64 is 0.
- */
-int insn_rip_relative(struct insn *insn)
-{
- struct insn_field *modrm = &insn->modrm;
-
- if (!insn->x86_64)
- return 0;
- if (!modrm->got)
- insn_get_modrm(insn);
- /*
- * For rip-relative instructions, the mod field (top 2 bits)
- * is zero and the r/m field (bottom 3 bits) is 0x5.
- */
- return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
-}
-
-/**
- * insn_get_sib() - Get the SIB byte of instruction
- * @insn: &struct insn containing instruction
- *
- * If necessary, first collects the instruction up to and including the
- * ModRM byte.
- */
-void insn_get_sib(struct insn *insn)
-{
- insn_byte_t modrm;
-
- if (insn->sib.got)
- return;
- if (!insn->modrm.got)
- insn_get_modrm(insn);
- if (insn->modrm.nbytes) {
- modrm = (insn_byte_t)insn->modrm.value;
- if (insn->addr_bytes != 2 &&
- X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
- insn->sib.value = get_next(insn_byte_t, insn);
- insn->sib.nbytes = 1;
- }
- }
- insn->sib.got = 1;
-
-err_out:
- return;
-}
-
-
-/**
- * insn_get_displacement() - Get the displacement of instruction
- * @insn: &struct insn containing instruction
- *
- * If necessary, first collects the instruction up to and including the
- * SIB byte.
- * Displacement value is sign-expanded.
- */
-void insn_get_displacement(struct insn *insn)
-{
- insn_byte_t mod, rm, base;
-
- if (insn->displacement.got)
- return;
- if (!insn->sib.got)
- insn_get_sib(insn);
- if (insn->modrm.nbytes) {
- /*
- * Interpreting the modrm byte:
- * mod = 00 - no displacement fields (exceptions below)
- * mod = 01 - 1-byte displacement field
- * mod = 10 - displacement field is 4 bytes, or 2 bytes if
- * address size = 2 (0x67 prefix in 32-bit mode)
- * mod = 11 - no memory operand
- *
- * If address size = 2...
- * mod = 00, r/m = 110 - displacement field is 2 bytes
- *
- * If address size != 2...
- * mod != 11, r/m = 100 - SIB byte exists
- * mod = 00, SIB base = 101 - displacement field is 4 bytes
- * mod = 00, r/m = 101 - rip-relative addressing, displacement
- * field is 4 bytes
- */
- mod = X86_MODRM_MOD(insn->modrm.value);
- rm = X86_MODRM_RM(insn->modrm.value);
- base = X86_SIB_BASE(insn->sib.value);
- if (mod == 3)
- goto out;
- if (mod == 1) {
- insn->displacement.value = get_next(signed char, insn);
- insn->displacement.nbytes = 1;
- } else if (insn->addr_bytes == 2) {
- if ((mod == 0 && rm == 6) || mod == 2) {
- insn->displacement.value =
- get_next(short, insn);
- insn->displacement.nbytes = 2;
- }
- } else {
- if ((mod == 0 && rm == 5) || mod == 2 ||
- (mod == 0 && base == 5)) {
- insn->displacement.value = get_next(int, insn);
- insn->displacement.nbytes = 4;
- }
- }
- }
-out:
- insn->displacement.got = 1;
-
-err_out:
- return;
-}
-
-/* Decode moffset16/32/64. Return 0 if failed */
-static int __get_moffset(struct insn *insn)
-{
- switch (insn->addr_bytes) {
- case 2:
- insn->moffset1.value = get_next(short, insn);
- insn->moffset1.nbytes = 2;
- break;
- case 4:
- insn->moffset1.value = get_next(int, insn);
- insn->moffset1.nbytes = 4;
- break;
- case 8:
- insn->moffset1.value = get_next(int, insn);
- insn->moffset1.nbytes = 4;
- insn->moffset2.value = get_next(int, insn);
- insn->moffset2.nbytes = 4;
- break;
- default: /* opnd_bytes must be modified manually */
- goto err_out;
- }
- insn->moffset1.got = insn->moffset2.got = 1;
-
- return 1;
-
-err_out:
- return 0;
-}
-
-/* Decode imm v32(Iz). Return 0 if failed */
-static int __get_immv32(struct insn *insn)
-{
- switch (insn->opnd_bytes) {
- case 2:
- insn->immediate.value = get_next(short, insn);
- insn->immediate.nbytes = 2;
- break;
- case 4:
- case 8:
- insn->immediate.value = get_next(int, insn);
- insn->immediate.nbytes = 4;
- break;
- default: /* opnd_bytes must be modified manually */
- goto err_out;
- }
-
- return 1;
-
-err_out:
- return 0;
-}
-
-/* Decode imm v64(Iv/Ov), Return 0 if failed */
-static int __get_immv(struct insn *insn)
-{
- switch (insn->opnd_bytes) {
- case 2:
- insn->immediate1.value = get_next(short, insn);
- insn->immediate1.nbytes = 2;
- break;
- case 4:
- insn->immediate1.value = get_next(int, insn);
- insn->immediate1.nbytes = 4;
- break;
- case 8:
- insn->immediate1.value = get_next(int, insn);
- insn->immediate1.nbytes = 4;
- insn->immediate2.value = get_next(int, insn);
- insn->immediate2.nbytes = 4;
- break;
- default: /* opnd_bytes must be modified manually */
- goto err_out;
- }
- insn->immediate1.got = insn->immediate2.got = 1;
-
- return 1;
-err_out:
- return 0;
-}
-
-/* Decode ptr16:16/32(Ap) */
-static int __get_immptr(struct insn *insn)
-{
- switch (insn->opnd_bytes) {
- case 2:
- insn->immediate1.value = get_next(short, insn);
- insn->immediate1.nbytes = 2;
- break;
- case 4:
- insn->immediate1.value = get_next(int, insn);
- insn->immediate1.nbytes = 4;
- break;
- case 8:
- /* ptr16:64 is not exist (no segment) */
- return 0;
- default: /* opnd_bytes must be modified manually */
- goto err_out;
- }
- insn->immediate2.value = get_next(unsigned short, insn);
- insn->immediate2.nbytes = 2;
- insn->immediate1.got = insn->immediate2.got = 1;
-
- return 1;
-err_out:
- return 0;
-}
-
-/**
- * insn_get_immediate() - Get the immediates of instruction
- * @insn: &struct insn containing instruction
- *
- * If necessary, first collects the instruction up to and including the
- * displacement bytes.
- * Basically, most of immediates are sign-expanded. Unsigned-value can be
- * get by bit masking with ((1 << (nbytes * 8)) - 1)
- */
-void insn_get_immediate(struct insn *insn)
-{
- if (insn->immediate.got)
- return;
- if (!insn->displacement.got)
- insn_get_displacement(insn);
-
- if (inat_has_moffset(insn->attr)) {
- if (!__get_moffset(insn))
- goto err_out;
- goto done;
- }
-
- if (!inat_has_immediate(insn->attr))
- /* no immediates */
- goto done;
-
- switch (inat_immediate_size(insn->attr)) {
- case INAT_IMM_BYTE:
- insn->immediate.value = get_next(signed char, insn);
- insn->immediate.nbytes = 1;
- break;
- case INAT_IMM_WORD:
- insn->immediate.value = get_next(short, insn);
- insn->immediate.nbytes = 2;
- break;
- case INAT_IMM_DWORD:
- insn->immediate.value = get_next(int, insn);
- insn->immediate.nbytes = 4;
- break;
- case INAT_IMM_QWORD:
- insn->immediate1.value = get_next(int, insn);
- insn->immediate1.nbytes = 4;
- insn->immediate2.value = get_next(int, insn);
- insn->immediate2.nbytes = 4;
- break;
- case INAT_IMM_PTR:
- if (!__get_immptr(insn))
- goto err_out;
- break;
- case INAT_IMM_VWORD32:
- if (!__get_immv32(insn))
- goto err_out;
- break;
- case INAT_IMM_VWORD:
- if (!__get_immv(insn))
- goto err_out;
- break;
- default:
- /* Here, insn must have an immediate, but failed */
- goto err_out;
- }
- if (inat_has_second_immediate(insn->attr)) {
- insn->immediate2.value = get_next(signed char, insn);
- insn->immediate2.nbytes = 1;
- }
-done:
- insn->immediate.got = 1;
-
-err_out:
- return;
-}
-
-/**
- * insn_get_length() - Get the length of instruction
- * @insn: &struct insn containing instruction
- *
- * If necessary, first collects the instruction up to and including the
- * immediates bytes.
- */
-void insn_get_length(struct insn *insn)
-{
- if (insn->length)
- return;
- if (!insn->immediate.got)
- insn_get_immediate(insn);
- insn->length = (unsigned char)((unsigned long)insn->next_byte
- - (unsigned long)insn->kaddr);
-}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 5f26620f13f5..176f2f084060 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1946,6 +1946,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
struct alternative *alt;
struct instruction *insn, *next_insn;
struct section *sec;
+ u8 visited;
int ret;
insn = first;
@@ -1972,12 +1973,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
return 1;
}
+ visited = 1 << state.uaccess;
if (insn->visited) {
if (!insn->hint && !insn_state_match(insn, &state))
return 1;
- /* If we were here with AC=0, but now have AC=1, go again */
- if (insn->state.uaccess || !state.uaccess)
+ if (insn->visited & visited)
return 0;
}
@@ -2024,7 +2025,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
} else
insn->state = state;
- insn->visited = true;
+ insn->visited |= visited;
if (!insn->ignore_alts) {
bool skip_orig = false;
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index b881fafcf55d..6d875ca6fce0 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -33,8 +33,9 @@ struct instruction {
unsigned int len;
enum insn_type type;
unsigned long immediate;
- bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
+ bool alt_group, dead_end, ignore, hint, save, restore, ignore_alts;
bool retpoline_safe;
+ u8 visited;
struct symbol *call_dest;
struct instruction *jump_dest;
struct instruction *first_jump_src;
diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh
index 1470e74e9d66..0a832e265a50 100755
--- a/tools/objtool/sync-check.sh
+++ b/tools/objtool/sync-check.sh
@@ -2,28 +2,50 @@
# SPDX-License-Identifier: GPL-2.0
FILES='
-arch/x86/lib/insn.c
-arch/x86/lib/inat.c
-arch/x86/lib/x86-opcode-map.txt
-arch/x86/tools/gen-insn-attr-x86.awk
-arch/x86/include/asm/insn.h
-arch/x86/include/asm/inat.h
arch/x86/include/asm/inat_types.h
arch/x86/include/asm/orc_types.h
+arch/x86/lib/x86-opcode-map.txt
+arch/x86/tools/gen-insn-attr-x86.awk
'
-check()
-{
- local file=$1
+check_2 () {
+ file1=$1
+ file2=$2
- diff $file ../../$file > /dev/null ||
- echo "Warning: synced file at 'tools/objtool/$file' differs from latest kernel version at '$file'"
+ shift
+ shift
+
+ cmd="diff $* $file1 $file2 > /dev/null"
+
+ test -f $file2 && {
+ eval $cmd || {
+ echo "Warning: Kernel ABI header at '$file1' differs from latest version at '$file2'" >&2
+ echo diff -u $file1 $file2
+ }
+ }
+}
+
+check () {
+ file=$1
+
+ shift
+
+ check_2 tools/$file $file $*
}
if [ ! -d ../../kernel ] || [ ! -d ../../tools ] || [ ! -d ../objtool ]; then
exit 0
fi
+cd ../..
+
for i in $FILES; do
check $i
done
+
+check arch/x86/include/asm/inat.h '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"'
+check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"'
+check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"'
+check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]"'
+
+cd -
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 3e5135dded16..bf1252dc2cb0 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -34,3 +34,6 @@ arch/*/include/generated/
trace/beauty/generated/
pmu-events/pmu-events.c
pmu-events/jevents
+feature/
+fixdep
+libtraceevent-dynamic-list
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 6d148a40551c..adc5a7e44b98 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -242,7 +242,7 @@ $(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
mv $@+ $@
--include $(OUPTUT)doc.dep
+-include $(OUTPUT)doc.dep
_cmds_txt = cmds-ancillaryinterrogators.txt \
cmds-ancillarymanipulators.txt \
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 50c5b60101bd..e0d9e7dd4f17 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -919,3 +919,18 @@ amended to take the number of elements as a parameter.
Note there is currently no advantage to using Intel PT instead of LBR, but
that may change in the future if greater use is made of the data.
+
+
+PEBS via Intel PT
+=================
+
+Some hardware has the feature to redirect PEBS records to the Intel PT trace.
+Recording is selected by using the aux-output config term e.g.
+
+ perf record -c 10000 -e '{intel_pt/branch=0/,cycles/aux-output/ppp}' uname
+
+Note that currently, software only supports redirecting at most one PEBS event.
+
+To display PEBS events from the Intel PT trace, use the itrace 'o' option e.g.
+
+ perf script --itrace=oe
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index c2182cbabde3..82ff7dad40c2 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -5,6 +5,8 @@
x synthesize transactions events
w synthesize ptwrite events
p synthesize power events
+ o synthesize other events recorded due to the use
+ of aux-output (refer to perf record)
e synthesize error events
d create a debug log
g synthesize a call chain (use with i or x)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index e4aa268d2e38..c599623a1f3d 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -40,6 +40,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
The file '$(sysconfdir)/perfconfig' can be used to
store a system-wide default configuration.
+One an disable reading config files by setting the PERF_CONFIG environment
+variable to /dev/null, or provide an alternate config file by setting that
+variable.
+
When reading or writing, the values are read from the system and user
configuration files by default, and options '--system' and '--user'
can be used to tell the command to read from or write to only that location.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 15e0fa87241b..c6f9f31b6039 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -60,6 +60,8 @@ OPTIONS
- 'name' : User defined event name. Single quotes (') may be used to
escape symbols in the name from parsing by shell and tool
like this: name=\'CPU_CLK_UNHALTED.THREAD:cmask=0x1\'.
+ - 'aux-output': Generate AUX records instead of events. This requires
+ that an AUX area event is also provided.
See the linkperf:perf-list[1] man page for more parameters.
@@ -422,9 +424,14 @@ CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
-S::
--snapshot::
Select AUX area tracing Snapshot Mode. This option is valid only with an
-AUX area tracing event. Optionally the number of bytes to capture per
-snapshot can be specified. In Snapshot Mode, trace data is captured only when
-signal SIGUSR2 is received.
+AUX area tracing event. Optionally, certain snapshot capturing parameters
+can be specified in a string that follows this option:
+ 'e': take one last snapshot on exit; guarantees that there is at least one
+ snapshot in the output file;
+ <size>: if the PMU supports this, specify the desired snapshot size.
+
+In Snapshot Mode trace data is captured only when signal SIGUSR2 is received
+and on exit if the above 'e' option is given.
--proc-map-timeout::
When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 987261d158d4..7315f155803f 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -438,6 +438,23 @@ OPTIONS
perf report --time 0%-10%,30%-40%
+--switch-on EVENT_NAME::
+ Only consider events after this event is found.
+
+ This may be interesting to measure a workload only after some initialization
+ phase is over, i.e. insert a perf probe at that point and then using this
+ option with that probe.
+
+--switch-off EVENT_NAME::
+ Stop considering events after this event is found.
+
+--show-on-off-events::
+ Show the --switch-on/off events too. This has no effect in 'perf report' now
+ but probably we'll make the default not to show the switch-on/off events
+ on the --group mode and if there is only one event besides the off/on ones,
+ go straight to the histogram browser, just like 'perf report' with no events
+ explicitely specified does.
+
--itrace::
Options for decoding instruction tracing data. The options are:
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index d4e2e18a5881..2599b057e47b 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -228,11 +228,11 @@ OPTIONS
With the metric option perf script can compute metrics for
sampling periods, similar to perf stat. This requires
- specifying a group with multiple metrics with the :S option
+ specifying a group with multiple events defining metrics with the :S option
for perf record. perf will sample on the first event, and
- compute metrics for all the events in the group. Please note
+ print computed metrics for all the events in the group. Please note
that the metric computed is averaged over the whole sampling
- period, not just for the sample point.
+ period (since the last sample), not just for the sample point.
For sample events it's possible to display misc field with -F +misc option,
following letters are displayed for each bit:
@@ -384,7 +384,7 @@ include::itrace.txt[]
perf script --time 0%-10%,30%-40%
--max-blocks::
- Set the maximum number of program blocks to print with brstackasm for
+ Set the maximum number of program blocks to print with brstackinsn for
each sample.
--reltime::
@@ -417,6 +417,15 @@ include::itrace.txt[]
For itrace only show specified functions and their callees for
itrace. Multiple functions can be separated by comma.
+--switch-on EVENT_NAME::
+ Only consider events after this event is found.
+
+--switch-off EVENT_NAME::
+ Stop considering events after this event is found.
+
+--show-on-off-events::
+ Show the --switch-on/off events too.
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index cfea87c6f38e..5596129a71cf 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -266,6 +266,44 @@ Default is to monitor all CPUS.
Record events of type PERF_RECORD_NAMESPACES and display it with the
'cgroup_id' sort key.
+--switch-on EVENT_NAME::
+ Only consider events after this event is found.
+
+ E.g.:
+
+ Find out where broadcast packets are handled
+
+ perf probe -L icmp_rcv
+
+ Insert a probe there:
+
+ perf probe icmp_rcv:59
+
+ Start perf top and ask it to only consider the cycles events when a
+ broadcast packet arrives This will show a menu with two entries and
+ will start counting when a broadcast packet arrives:
+
+ perf top -e cycles,probe:icmp_rcv --switch-on=probe:icmp_rcv
+
+ Alternatively one can ask for --group and then two overhead columns
+ will appear, the first for cycles and the second for the switch-on event.
+
+ perf top --group -e cycles,probe:icmp_rcv --switch-on=probe:icmp_rcv
+
+ This may be interesting to measure a workload only after some initialization
+ phase is over, i.e. insert a perf probe at that point and use the above
+ examples replacing probe:icmp_rcv with the just-after-init probe.
+
+--switch-off EVENT_NAME::
+ Stop considering events after this event is found.
+
+--show-on-off-events::
+ Show the --switch-on/off events too. This has no effect in 'perf top' now
+ but probably we'll make the default not to show the switch-on/off events
+ on the --group mode and if there is only one event besides the off/on ones,
+ go straight to the histogram browser, just like 'perf top' with no events
+ explicitely specified does.
+
INTERACTIVE PROMPTING KEYS
--------------------------
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index fc6e43262c41..25b74fdb36fa 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -176,6 +176,15 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
only at exit time or when a syscall is interrupted, i.e. in those cases this
option is equivalent to the number of lines printed.
+--switch-on EVENT_NAME::
+ Only consider events after this event is found.
+
+--switch-off EVENT_NAME::
+ Stop considering events after this event is found.
+
+--show-on-off-events::
+ Show the --switch-on/off events too.
+
--max-stack::
Set the stack depth limit when parsing the callchain, anything
beyond the specified depth will be ignored. Note that at this point
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index 5f54feb19977..b0152e1095c5 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -126,7 +126,7 @@ vendor,family,model,stepping. For example: GenuineIntel,6,69,1
HEADER_TOTAL_MEM = 10,
-An uint64_t with the total memory in bytes.
+An uint64_t with the total memory in kilobytes.
HEADER_CMDLINE = 11,
@@ -298,16 +298,21 @@ Physical memory map and its node assignments.
The format of data in MEM_TOPOLOGY is as follows:
- 0 - version | for future changes
- 8 - block_size_bytes | /sys/devices/system/memory/block_size_bytes
- 16 - count | number of nodes
-
-For each node we store map of physical indexes:
-
- 32 - node id | node index
- 40 - size | size of bitmap
- 48 - bitmap | bitmap of memory indexes that belongs to node
- | /sys/devices/system/node/node<NODE>/memory<INDEX>
+ u64 version; // Currently 1
+ u64 block_size_bytes; // /sys/devices/system/memory/block_size_bytes
+ u64 count; // number of nodes
+
+struct memory_node {
+ u64 node_id; // node index
+ u64 size; // size of bitmap
+ struct bitmap {
+ /* size of bitmap again */
+ u64 bitmapsize;
+ /* bitmap of memory indexes that belongs to node */
+ /* /sys/devices/system/node/node<NODE>/memory<INDEX> */
+ u64 entries[(bitmapsize/64)+1];
+ }
+}[count];
The MEM_TOPOLOGY can be displayed with following command:
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 89ac5a1f1550..a269d78456b6 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -60,6 +60,10 @@ ifeq ($(SRCARCH),arm64)
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
endif
+ifeq ($(SRCARCH),riscv)
+ NO_PERF_REGS := 0
+endif
+
ifeq ($(SRCARCH),csky)
NO_PERF_REGS := 0
endif
@@ -82,7 +86,7 @@ endif
# Disable it on all other architectures in case libdw unwind
# support is detected in system. Add supported architectures
# to the check.
-ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390 csky))
+ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390 csky riscv))
NO_LIBDW_DWARF_UNWIND := 1
endif
@@ -277,11 +281,12 @@ ifeq ($(DEBUG),0)
endif
endif
+INC_FLAGS += -I$(src-perf)/lib/include
INC_FLAGS += -I$(src-perf)/util/include
INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include
-INC_FLAGS += -I$(srctree)/tools/include/uapi
INC_FLAGS += -I$(srctree)/tools/include/
INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/include/uapi
INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/
INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/
@@ -823,6 +828,17 @@ ifndef NO_LIBZSTD
endif
endif
+ifndef NO_LIBCAP
+ ifeq ($(feature-libcap), 1)
+ CFLAGS += -DHAVE_LIBCAP_SUPPORT
+ EXTLIBS += -lcap
+ $(call detected,CONFIG_LIBCAP)
+ else
+ msg := $(warning No libcap found, disables capability support, please install libcap-devel/libcap-dev);
+ NO_LIBCAP := 1
+ endif
+endif
+
ifndef NO_BACKTRACE
ifeq ($(feature-backtrace), 1)
CFLAGS += -DHAVE_BACKTRACE_SUPPORT
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0fffd2bb6cd9..f9807d8c005b 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -88,6 +88,8 @@ include ../scripts/utilities.mak
#
# Define NO_LIBBPF if you do not want BPF support
#
+# Define NO_LIBCAP if you do not want process capabilities considered by perf
+#
# Define NO_SDT if you do not want to define SDT event in perf tools,
# note that it doesn't disable SDT scanning support.
#
@@ -224,6 +226,7 @@ LIB_DIR = $(srctree)/tools/lib/api/
TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
BPF_DIR = $(srctree)/tools/lib/bpf/
SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
+LIBPERF_DIR = $(srctree)/tools/perf/lib/
# Set FEATURE_TESTS to 'all' so all possible feature checkers are executed.
# Without this setting the output feature dump file misses some features, for
@@ -272,6 +275,7 @@ ifneq ($(OUTPUT),)
TE_PATH=$(OUTPUT)
BPF_PATH=$(OUTPUT)
SUBCMD_PATH=$(OUTPUT)
+ LIBPERF_PATH=$(OUTPUT)
ifneq ($(subdir),)
API_PATH=$(OUTPUT)/../lib/api/
else
@@ -282,6 +286,7 @@ else
API_PATH=$(LIB_DIR)
BPF_PATH=$(BPF_DIR)
SUBCMD_PATH=$(SUBCMD_DIR)
+ LIBPERF_PATH=$(LIBPERF_DIR)
endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -303,6 +308,9 @@ LIBBPF = $(BPF_PATH)libbpf.a
LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a
+LIBPERF = $(LIBPERF_PATH)libperf.a
+export LIBPERF
+
# python extension build directories
PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -348,9 +356,7 @@ endif
export PERL_PATH
-LIBPERF_A=$(OUTPUT)libperf.a
-
-PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
+PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD) $(LIBPERF)
ifndef NO_LIBBPF
PERFLIBS += $(LIBBPF)
endif
@@ -583,8 +589,6 @@ JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o
PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o
-LIBPERF_IN := $(OUTPUT)libperf-in.o
-
export JEVENTS
build := -f $(srctree)/tools/build/Makefile.build dir=. obj
@@ -601,12 +605,9 @@ $(JEVENTS): $(JEVENTS_IN)
$(PMU_EVENTS_IN): $(JEVENTS) FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events
-$(LIBPERF_IN): prepare FORCE
- $(Q)$(MAKE) $(build)=libperf
-
-$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
+$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
- $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBS) -o $@
+ $(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@
$(GTK_IN): FORCE
$(Q)$(MAKE) $(build)=gtk
@@ -727,9 +728,6 @@ endif
$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
-$(LIBPERF_A): $(LIBPERF_IN)
- $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
-
LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)'
$(LIBTRACEEVENT): FORCE
@@ -762,6 +760,13 @@ $(LIBBPF)-clean:
$(call QUIET_CLEAN, libbpf)
$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
+$(LIBPERF): FORCE
+ $(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) $(OUTPUT)libperf.a
+
+$(LIBPERF)-clean:
+ $(call QUIET_CLEAN, libperf)
+ $(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) clean >/dev/null
+
$(LIBSUBCMD): FORCE
$(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a
@@ -948,7 +953,7 @@ config-clean:
python-clean:
$(python-clean)
-clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean
+clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBPERF)-clean config-clean fixdep-clean python-clean
$(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(Q)$(RM) $(OUTPUT).config-detected
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
index c7d1a69b894f..e1d4b484cc4b 100644
--- a/tools/perf/arch/arm/annotate/instructions.c
+++ b/tools/perf/arch/arm/annotate/instructions.c
@@ -3,6 +3,7 @@
#include <linux/zalloc.h>
#include <sys/types.h>
#include <regex.h>
+#include <stdlib.h>
struct arm_annotate {
regex_t call_insn,
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index 02014740a1aa..0a6e75b8777a 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -9,6 +9,7 @@
#include <linux/zalloc.h>
#include "../../util/auxtrace.h"
+#include "../../util/debug.h"
#include "../../util/evlist.h"
#include "../../util/pmu.h"
#include "cs-etm.h"
@@ -50,10 +51,10 @@ static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err)
}
struct auxtrace_record
-*auxtrace_record__init(struct perf_evlist *evlist, int *err)
+*auxtrace_record__init(struct evlist *evlist, int *err)
{
struct perf_pmu *cs_etm_pmu;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool found_etm = false;
bool found_spe = false;
static struct perf_pmu **arm_spe_pmus = NULL;
@@ -70,14 +71,14 @@ struct auxtrace_record
evlist__for_each_entry(evlist, evsel) {
if (cs_etm_pmu &&
- evsel->attr.type == cs_etm_pmu->type)
+ evsel->core.attr.type == cs_etm_pmu->type)
found_etm = true;
if (!nr_spes)
continue;
for (i = 0; i < nr_spes; i++) {
- if (evsel->attr.type == arm_spe_pmus[i]->type) {
+ if (evsel->core.attr.type == arm_spe_pmus[i]->type) {
found_spe = true;
break;
}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 4208974c24f8..c32db09baf0d 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -11,19 +11,22 @@
#include <linux/coresight-pmu.h>
#include <linux/kernel.h>
#include <linux/log2.h>
+#include <linux/string.h>
#include <linux/types.h>
#include <linux/zalloc.h>
#include "cs-etm.h"
-#include "../../perf.h"
+#include "../../util/debug.h"
+#include "../../util/record.h"
#include "../../util/auxtrace.h"
#include "../../util/cpumap.h"
+#include "../../util/event.h"
#include "../../util/evlist.h"
#include "../../util/evsel.h"
#include "../../util/pmu.h"
-#include "../../util/thread_map.h"
#include "../../util/cs-etm.h"
#include "../../util/util.h"
+#include "../../util/session.h"
#include <errno.h>
#include <stdlib.h>
@@ -32,7 +35,7 @@
struct cs_etm_recording {
struct auxtrace_record itr;
struct perf_pmu *cs_etm_pmu;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
int wrapped_cnt;
bool *wrapped;
bool snapshot_mode;
@@ -55,7 +58,7 @@ static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
static int cs_etm_set_context_id(struct auxtrace_record *itr,
- struct perf_evsel *evsel, int cpu)
+ struct evsel *evsel, int cpu)
{
struct cs_etm_recording *ptr;
struct perf_pmu *cs_etm_pmu;
@@ -95,7 +98,7 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
}
/* All good, let the kernel know */
- evsel->attr.config |= (1 << ETM_OPT_CTXTID);
+ evsel->core.attr.config |= (1 << ETM_OPT_CTXTID);
err = 0;
out:
@@ -104,7 +107,7 @@ out:
}
static int cs_etm_set_timestamp(struct auxtrace_record *itr,
- struct perf_evsel *evsel, int cpu)
+ struct evsel *evsel, int cpu)
{
struct cs_etm_recording *ptr;
struct perf_pmu *cs_etm_pmu;
@@ -144,7 +147,7 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr,
}
/* All good, let the kernel know */
- evsel->attr.config |= (1 << ETM_OPT_TS);
+ evsel->core.attr.config |= (1 << ETM_OPT_TS);
err = 0;
out:
@@ -152,11 +155,11 @@ out:
}
static int cs_etm_set_option(struct auxtrace_record *itr,
- struct perf_evsel *evsel, u32 option)
+ struct evsel *evsel, u32 option)
{
int i, err = -EINVAL;
- struct cpu_map *event_cpus = evsel->evlist->cpus;
- struct cpu_map *online_cpus = cpu_map__new(NULL);
+ struct perf_cpu_map *event_cpus = evsel->evlist->core.cpus;
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
/* Set option of each CPU we have */
for (i = 0; i < cpu__max_cpu(); i++) {
@@ -181,7 +184,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr,
err = 0;
out:
- cpu_map__put(online_cpus);
+ perf_cpu_map__put(online_cpus);
return err;
}
@@ -208,14 +211,14 @@ static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
}
static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
char msg[BUFSIZ], path[PATH_MAX], *sink;
struct perf_evsel_config_term *term;
int ret = -EINVAL;
u32 hash;
- if (evsel->attr.config2 & GENMASK(31, 0))
+ if (evsel->core.attr.config2 & GENMASK(31, 0))
return 0;
list_for_each_entry(term, &evsel->config_terms, list) {
@@ -233,7 +236,7 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
return ret;
}
- evsel->attr.config2 |= hash;
+ evsel->core.attr.config2 |= hash;
return 0;
}
@@ -245,16 +248,16 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
}
static int cs_etm_recording_options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts)
{
int ret;
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
- struct perf_evsel *evsel, *cs_etm_evsel = NULL;
- struct cpu_map *cpus = evlist->cpus;
- bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
+ struct evsel *evsel, *cs_etm_evsel = NULL;
+ struct perf_cpu_map *cpus = evlist->core.cpus;
+ bool privileged = perf_event_paranoid_check(-1);
int err = 0;
ptr->evlist = evlist;
@@ -264,14 +267,14 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
opts->record_switch_events = true;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == cs_etm_pmu->type) {
+ if (evsel->core.attr.type == cs_etm_pmu->type) {
if (cs_etm_evsel) {
pr_err("There may be only one %s event\n",
CORESIGHT_ETM_PMU_NAME);
return -EINVAL;
}
- evsel->attr.freq = 0;
- evsel->attr.sample_period = 1;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = 1;
cs_etm_evsel = evsel;
opts->full_auxtrace = true;
}
@@ -396,7 +399,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
* AUX event. We also need the contextID in order to be notified
* when a context switch happened.
*/
- if (!cpu_map__empty(cpus)) {
+ if (!perf_cpu_map__empty(cpus)) {
perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
err = cs_etm_set_option(itr, cs_etm_evsel,
@@ -407,7 +410,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
/* Add dummy event to keep tracking */
if (opts->full_auxtrace) {
- struct perf_evsel *tracking_evsel;
+ struct evsel *tracking_evsel;
err = parse_events(evlist, "dummy:u", NULL);
if (err)
@@ -416,11 +419,11 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
tracking_evsel = perf_evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
- tracking_evsel->attr.freq = 0;
- tracking_evsel->attr.sample_period = 1;
+ tracking_evsel->core.attr.freq = 0;
+ tracking_evsel->core.attr.sample_period = 1;
/* In per-cpu case, always need the time of mmap events etc */
- if (!cpu_map__empty(cpus))
+ if (!perf_cpu_map__empty(cpus))
perf_evsel__set_sample_bit(tracking_evsel, TIME);
}
@@ -434,11 +437,11 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr)
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
- struct perf_evlist *evlist = ptr->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = ptr->evlist;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == cs_etm_pmu->type) {
+ if (evsel->core.attr.type == cs_etm_pmu->type) {
/*
* Variable perf_event_attr::config is assigned to
* ETMv3/PTM. The bit fields have been made to match
@@ -447,7 +450,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr)
* drivers/hwtracing/coresight/coresight-perf.c for
* details.
*/
- config = evsel->attr.config;
+ config = evsel->core.attr.config;
break;
}
}
@@ -485,15 +488,15 @@ static u64 cs_etmv4_get_config(struct auxtrace_record *itr)
static size_t
cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
int i;
int etmv3 = 0, etmv4 = 0;
- struct cpu_map *event_cpus = evlist->cpus;
- struct cpu_map *online_cpus = cpu_map__new(NULL);
+ struct perf_cpu_map *event_cpus = evlist->core.cpus;
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
/* cpu map is not empty, we have specific CPUs to work with */
- if (!cpu_map__empty(event_cpus)) {
+ if (!perf_cpu_map__empty(event_cpus)) {
for (i = 0; i < cpu__max_cpu(); i++) {
if (!cpu_map__has(event_cpus, i) ||
!cpu_map__has(online_cpus, i))
@@ -517,7 +520,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
}
}
- cpu_map__put(online_cpus);
+ perf_cpu_map__put(online_cpus);
return (CS_ETM_HEADER_SIZE +
(etmv4 * CS_ETMV4_PRIV_SIZE) +
@@ -564,7 +567,7 @@ static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
static void cs_etm_get_metadata(int cpu, u32 *offset,
struct auxtrace_record *itr,
- struct auxtrace_info_event *info)
+ struct perf_record_auxtrace_info *info)
{
u32 increment;
u64 magic;
@@ -629,15 +632,15 @@ static void cs_etm_get_metadata(int cpu, u32 *offset,
static int cs_etm_info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *info,
+ struct perf_record_auxtrace_info *info,
size_t priv_size)
{
int i;
u32 offset;
u64 nr_cpu, type;
- struct cpu_map *cpu_map;
- struct cpu_map *event_cpus = session->evlist->cpus;
- struct cpu_map *online_cpus = cpu_map__new(NULL);
+ struct perf_cpu_map *cpu_map;
+ struct perf_cpu_map *event_cpus = session->evlist->core.cpus;
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -649,11 +652,11 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
return -EINVAL;
/* If the cpu_map is empty all online CPUs are involved */
- if (cpu_map__empty(event_cpus)) {
+ if (perf_cpu_map__empty(event_cpus)) {
cpu_map = online_cpus;
} else {
/* Make sure all specified CPUs are online */
- for (i = 0; i < cpu_map__nr(event_cpus); i++) {
+ for (i = 0; i < perf_cpu_map__nr(event_cpus); i++) {
if (cpu_map__has(event_cpus, i) &&
!cpu_map__has(online_cpus, i))
return -EINVAL;
@@ -662,7 +665,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
cpu_map = event_cpus;
}
- nr_cpu = cpu_map__nr(cpu_map);
+ nr_cpu = perf_cpu_map__nr(cpu_map);
/* Get PMU type as dynamically assigned by the core */
type = cs_etm_pmu->type;
@@ -679,7 +682,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
if (cpu_map__has(cpu_map, i))
cs_etm_get_metadata(i, &offset, itr, info);
- cpu_map__put(online_cpus);
+ perf_cpu_map__put(online_cpus);
return 0;
}
@@ -817,11 +820,11 @@ static int cs_etm_snapshot_start(struct auxtrace_record *itr)
{
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
- return perf_evsel__disable(evsel);
+ if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
+ return evsel__disable(evsel);
}
return -EINVAL;
}
@@ -830,11 +833,11 @@ static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
{
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
- return perf_evsel__enable(evsel);
+ if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
+ return evsel__enable(evsel);
}
return -EINVAL;
}
@@ -858,10 +861,10 @@ static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
{
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
+ if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
return perf_evlist__enable_event_idx(ptr->evlist,
evsel, idx);
}
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 8f70a1b282df..43aa93ed8414 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -2,6 +2,7 @@
#include <linux/compiler.h>
#include <sys/types.h>
#include <regex.h>
+#include <stdlib.h>
struct arm64_annotate {
regex_t call_insn,
diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c
index 2c009aa74633..4b364692da67 100644
--- a/tools/perf/arch/arm64/util/arm-spe.c
+++ b/tools/perf/arch/arm64/util/arm-spe.c
@@ -12,6 +12,7 @@
#include <time.h>
#include "../../util/cpumap.h"
+#include "../../util/event.h"
#include "../../util/evsel.h"
#include "../../util/evlist.h"
#include "../../util/session.h"
@@ -19,6 +20,7 @@
#include "../../util/pmu.h"
#include "../../util/debug.h"
#include "../../util/auxtrace.h"
+#include "../../util/record.h"
#include "../../util/arm-spe.h"
#define KiB(x) ((x) * 1024)
@@ -27,19 +29,19 @@
struct arm_spe_recording {
struct auxtrace_record itr;
struct perf_pmu *arm_spe_pmu;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
};
static size_t
arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return ARM_SPE_AUXTRACE_PRIV_SIZE;
}
static int arm_spe_info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size)
{
struct arm_spe_recording *sper =
@@ -59,27 +61,27 @@ static int arm_spe_info_fill(struct auxtrace_record *itr,
}
static int arm_spe_recording_options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts)
{
struct arm_spe_recording *sper =
container_of(itr, struct arm_spe_recording, itr);
struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
- struct perf_evsel *evsel, *arm_spe_evsel = NULL;
- bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
- struct perf_evsel *tracking_evsel;
+ struct evsel *evsel, *arm_spe_evsel = NULL;
+ bool privileged = perf_event_paranoid_check(-1);
+ struct evsel *tracking_evsel;
int err;
sper->evlist = evlist;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == arm_spe_pmu->type) {
+ if (evsel->core.attr.type == arm_spe_pmu->type) {
if (arm_spe_evsel) {
pr_err("There may be only one " ARM_SPE_PMU_NAME "x event\n");
return -EINVAL;
}
- evsel->attr.freq = 0;
- evsel->attr.sample_period = 1;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = 1;
arm_spe_evsel = evsel;
opts->full_auxtrace = true;
}
@@ -130,8 +132,8 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
tracking_evsel = perf_evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
- tracking_evsel->attr.freq = 0;
- tracking_evsel->attr.sample_period = 1;
+ tracking_evsel->core.attr.freq = 0;
+ tracking_evsel->core.attr.sample_period = 1;
perf_evsel__set_sample_bit(tracking_evsel, TIME);
perf_evsel__set_sample_bit(tracking_evsel, CPU);
perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
@@ -160,10 +162,10 @@ static int arm_spe_read_finish(struct auxtrace_record *itr, int idx)
{
struct arm_spe_recording *sper =
container_of(itr, struct arm_spe_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(sper->evlist, evsel) {
- if (evsel->attr.type == sper->arm_spe_pmu->type)
+ if (evsel->core.attr.type == sper->arm_spe_pmu->type)
return perf_evlist__enable_event_idx(sper->evlist,
evsel, idx);
}
diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c
index 534cd2507d83..e41defaaa2e6 100644
--- a/tools/perf/arch/arm64/util/header.c
+++ b/tools/perf/arch/arm64/util/header.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <api/fs/fs.h>
+#include "debug.h"
#include "header.h"
#define MIDR "/regs/identification/midr_el1"
@@ -16,7 +17,7 @@ char *get_cpuid_str(struct perf_pmu *pmu)
const char *sysfs = sysfs__mountpoint();
int cpu;
u64 midr = 0;
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
FILE *file;
if (!sysfs || !pmu || !pmu->cpus)
@@ -27,7 +28,7 @@ char *get_cpuid_str(struct perf_pmu *pmu)
return NULL;
/* read midr from list of cpus mapped to this pmu */
- cpus = cpu_map__get(pmu->cpus);
+ cpus = perf_cpu_map__get(pmu->cpus);
for (cpu = 0; cpu < cpus->nr; cpu++) {
scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
sysfs, cpus->map[cpu]);
@@ -60,6 +61,6 @@ char *get_cpuid_str(struct perf_pmu *pmu)
buf = NULL;
}
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
return buf;
}
diff --git a/tools/perf/arch/arm64/util/sym-handling.c b/tools/perf/arch/arm64/util/sym-handling.c
index 27fcf24d6850..5df788985130 100644
--- a/tools/perf/arch/arm64/util/sym-handling.c
+++ b/tools/perf/arch/arm64/util/sym-handling.c
@@ -4,11 +4,9 @@
* Copyright (C) 2015 Naveen N. Rao, IBM Corporation
*/
-#include "debug.h"
-#include "symbol.h"
-#include "map.h"
-#include "probe-event.h"
-#include "probe-file.h"
+#include "symbol.h" // for the elf__needs_adjust_symbols() prototype
+#include <stdbool.h>
+#include <gelf.h>
#ifdef HAVE_LIBELF_SUPPORT
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 1a9e22f78c22..59dd875fd5e4 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "common.h"
#include "../util/env.h"
#include "../util/debug.h"
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index c298a446d1f6..e965ed8bb328 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -2,7 +2,9 @@
#ifndef ARCH_PERF_COMMON_H
#define ARCH_PERF_COMMON_H
-#include "../util/env.h"
+#include <stdbool.h>
+
+struct perf_env;
int perf_env__lookup_objdump(struct perf_env *env, const char **path);
bool perf_env__single_address_space(struct perf_env *env);
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index db3bbb8744af..43f736ed47f2 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -20,7 +20,9 @@
10 common unlink sys_unlink
11 nospu execve sys_execve compat_sys_execve
12 common chdir sys_chdir
-13 common time sys_time compat_sys_time
+13 32 time sys_time32
+13 64 time sys_time
+13 spu time sys_time
14 common mknod sys_mknod
15 common chmod sys_chmod
16 common lchown sys_lchown
@@ -36,14 +38,17 @@
22 spu umount sys_ni_syscall
23 common setuid sys_setuid
24 common getuid sys_getuid
-25 common stime sys_stime compat_sys_stime
+25 32 stime sys_stime32
+25 64 stime sys_stime
+25 spu stime sys_stime
26 nospu ptrace sys_ptrace compat_sys_ptrace
27 common alarm sys_alarm
28 32 oldfstat sys_fstat sys_ni_syscall
28 64 oldfstat sys_ni_syscall
28 spu oldfstat sys_ni_syscall
29 nospu pause sys_pause
-30 nospu utime sys_utime compat_sys_utime
+30 32 utime sys_utime32
+30 64 utime sys_utime
31 common stty sys_ni_syscall
32 common gtty sys_ni_syscall
33 common access sys_access
@@ -157,7 +162,9 @@
121 common setdomainname sys_setdomainname
122 common uname sys_newuname
123 common modify_ldt sys_ni_syscall
-124 common adjtimex sys_adjtimex compat_sys_adjtimex
+124 32 adjtimex sys_adjtimex_time32
+124 64 adjtimex sys_adjtimex
+124 spu adjtimex sys_adjtimex
125 common mprotect sys_mprotect
126 32 sigprocmask sys_sigprocmask compat_sys_sigprocmask
126 64 sigprocmask sys_ni_syscall
@@ -198,8 +205,12 @@
158 common sched_yield sys_sched_yield
159 common sched_get_priority_max sys_sched_get_priority_max
160 common sched_get_priority_min sys_sched_get_priority_min
-161 common sched_rr_get_interval sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
-162 common nanosleep sys_nanosleep compat_sys_nanosleep
+161 32 sched_rr_get_interval sys_sched_rr_get_interval_time32
+161 64 sched_rr_get_interval sys_sched_rr_get_interval
+161 spu sched_rr_get_interval sys_sched_rr_get_interval
+162 32 nanosleep sys_nanosleep_time32
+162 64 nanosleep sys_nanosleep
+162 spu nanosleep sys_nanosleep
163 common mremap sys_mremap
164 common setresuid sys_setresuid
165 common getresuid sys_getresuid
@@ -213,7 +224,8 @@
173 nospu rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
174 nospu rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
175 nospu rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
-176 nospu rt_sigtimedwait sys_rt_sigtimedwait compat_sys_rt_sigtimedwait
+176 32 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32
+176 64 rt_sigtimedwait sys_rt_sigtimedwait
177 nospu rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
178 nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
179 common pread64 sys_pread64 compat_sys_pread64
@@ -260,7 +272,9 @@
218 common removexattr sys_removexattr
219 common lremovexattr sys_lremovexattr
220 common fremovexattr sys_fremovexattr
-221 common futex sys_futex compat_sys_futex
+221 32 futex sys_futex_time32
+221 64 futex sys_futex
+221 spu futex sys_futex
222 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
223 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
# 224 unused
@@ -268,7 +282,9 @@
226 32 sendfile64 sys_sendfile64 compat_sys_sendfile64
227 common io_setup sys_io_setup compat_sys_io_setup
228 common io_destroy sys_io_destroy
-229 common io_getevents sys_io_getevents compat_sys_io_getevents
+229 32 io_getevents sys_io_getevents_time32
+229 64 io_getevents sys_io_getevents
+229 spu io_getevents sys_io_getevents
230 common io_submit sys_io_submit compat_sys_io_submit
231 common io_cancel sys_io_cancel
232 nospu set_tid_address sys_set_tid_address
@@ -280,19 +296,33 @@
238 common epoll_wait sys_epoll_wait
239 common remap_file_pages sys_remap_file_pages
240 common timer_create sys_timer_create compat_sys_timer_create
-241 common timer_settime sys_timer_settime compat_sys_timer_settime
-242 common timer_gettime sys_timer_gettime compat_sys_timer_gettime
+241 32 timer_settime sys_timer_settime32
+241 64 timer_settime sys_timer_settime
+241 spu timer_settime sys_timer_settime
+242 32 timer_gettime sys_timer_gettime32
+242 64 timer_gettime sys_timer_gettime
+242 spu timer_gettime sys_timer_gettime
243 common timer_getoverrun sys_timer_getoverrun
244 common timer_delete sys_timer_delete
-245 common clock_settime sys_clock_settime compat_sys_clock_settime
-246 common clock_gettime sys_clock_gettime compat_sys_clock_gettime
-247 common clock_getres sys_clock_getres compat_sys_clock_getres
-248 common clock_nanosleep sys_clock_nanosleep compat_sys_clock_nanosleep
+245 32 clock_settime sys_clock_settime32
+245 64 clock_settime sys_clock_settime
+245 spu clock_settime sys_clock_settime
+246 32 clock_gettime sys_clock_gettime32
+246 64 clock_gettime sys_clock_gettime
+246 spu clock_gettime sys_clock_gettime
+247 32 clock_getres sys_clock_getres_time32
+247 64 clock_getres sys_clock_getres
+247 spu clock_getres sys_clock_getres
+248 32 clock_nanosleep sys_clock_nanosleep_time32
+248 64 clock_nanosleep sys_clock_nanosleep
+248 spu clock_nanosleep sys_clock_nanosleep
249 32 swapcontext ppc_swapcontext ppc32_swapcontext
249 64 swapcontext ppc64_swapcontext
249 spu swapcontext sys_ni_syscall
250 common tgkill sys_tgkill
-251 common utimes sys_utimes compat_sys_utimes
+251 32 utimes sys_utimes_time32
+251 64 utimes sys_utimes
+251 spu utimes sys_utimes
252 common statfs64 sys_statfs64 compat_sys_statfs64
253 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
254 32 fadvise64_64 ppc_fadvise64_64
@@ -308,8 +338,10 @@
261 nospu set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
262 nospu mq_open sys_mq_open compat_sys_mq_open
263 nospu mq_unlink sys_mq_unlink
-264 nospu mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend
-265 nospu mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive
+264 32 mq_timedsend sys_mq_timedsend_time32
+264 64 mq_timedsend sys_mq_timedsend
+265 32 mq_timedreceive sys_mq_timedreceive_time32
+265 64 mq_timedreceive sys_mq_timedreceive
266 nospu mq_notify sys_mq_notify compat_sys_mq_notify
267 nospu mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
268 nospu kexec_load sys_kexec_load compat_sys_kexec_load
@@ -324,8 +356,10 @@
277 nospu inotify_rm_watch sys_inotify_rm_watch
278 nospu spu_run sys_spu_run
279 nospu spu_create sys_spu_create
-280 nospu pselect6 sys_pselect6 compat_sys_pselect6
-281 nospu ppoll sys_ppoll compat_sys_ppoll
+280 32 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32
+280 64 pselect6 sys_pselect6
+281 32 ppoll sys_ppoll_time32 compat_sys_ppoll_time32
+281 64 ppoll sys_ppoll
282 common unshare sys_unshare
283 common splice sys_splice
284 common tee sys_tee
@@ -334,7 +368,9 @@
287 common mkdirat sys_mkdirat
288 common mknodat sys_mknodat
289 common fchownat sys_fchownat
-290 common futimesat sys_futimesat compat_sys_futimesat
+290 32 futimesat sys_futimesat_time32
+290 64 futimesat sys_futimesat
+290 spu utimesat sys_futimesat
291 32 fstatat64 sys_fstatat64
291 64 newfstatat sys_newfstatat
291 spu newfstatat sys_newfstatat
@@ -350,15 +386,21 @@
301 common move_pages sys_move_pages compat_sys_move_pages
302 common getcpu sys_getcpu
303 nospu epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
-304 common utimensat sys_utimensat compat_sys_utimensat
+304 32 utimensat sys_utimensat_time32
+304 64 utimensat sys_utimensat
+304 spu utimensat sys_utimensat
305 common signalfd sys_signalfd compat_sys_signalfd
306 common timerfd_create sys_timerfd_create
307 common eventfd sys_eventfd
308 common sync_file_range2 sys_sync_file_range2 compat_sys_sync_file_range2
309 nospu fallocate sys_fallocate compat_sys_fallocate
310 nospu subpage_prot sys_subpage_prot
-311 common timerfd_settime sys_timerfd_settime compat_sys_timerfd_settime
-312 common timerfd_gettime sys_timerfd_gettime compat_sys_timerfd_gettime
+311 32 timerfd_settime sys_timerfd_settime32
+311 64 timerfd_settime sys_timerfd_settime
+311 spu timerfd_settime sys_timerfd_settime
+312 32 timerfd_gettime sys_timerfd_gettime32
+312 64 timerfd_gettime sys_timerfd_gettime
+312 spu timerfd_gettime sys_timerfd_gettime
313 common signalfd4 sys_signalfd4 compat_sys_signalfd4
314 common eventfd2 sys_eventfd2
315 common epoll_create1 sys_epoll_create1
@@ -389,11 +431,15 @@
340 common getsockopt sys_getsockopt compat_sys_getsockopt
341 common sendmsg sys_sendmsg compat_sys_sendmsg
342 common recvmsg sys_recvmsg compat_sys_recvmsg
-343 common recvmmsg sys_recvmmsg compat_sys_recvmmsg
+343 32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32
+343 64 recvmmsg sys_recvmmsg
+343 spu recvmmsg sys_recvmmsg
344 common accept4 sys_accept4
345 common name_to_handle_at sys_name_to_handle_at
346 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
-347 common clock_adjtime sys_clock_adjtime compat_sys_clock_adjtime
+347 32 clock_adjtime sys_clock_adjtime32
+347 64 clock_adjtime sys_clock_adjtime
+347 spu clock_adjtime sys_clock_adjtime
348 common syncfs sys_syncfs
349 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
350 common setns sys_setns
@@ -414,6 +460,7 @@
363 spu switch_endian sys_ni_syscall
364 common userfaultfd sys_userfaultfd
365 common membarrier sys_membarrier
+# 366-377 originally left for IPC, now unused
378 nospu mlock2 sys_mlock2
379 nospu copy_file_range sys_copy_file_range
380 common preadv2 sys_preadv2 compat_sys_preadv2
@@ -424,4 +471,49 @@
385 nospu pkey_free sys_pkey_free
386 nospu pkey_mprotect sys_pkey_mprotect
387 nospu rseq sys_rseq
-388 nospu io_pgetevents sys_io_pgetevents compat_sys_io_pgetevents
+388 32 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents
+388 64 io_pgetevents sys_io_pgetevents
+# room for arch specific syscalls
+392 64 semtimedop sys_semtimedop
+393 common semget sys_semget
+394 common semctl sys_semctl compat_sys_semctl
+395 common shmget sys_shmget
+396 common shmctl sys_shmctl compat_sys_shmctl
+397 common shmat sys_shmat compat_sys_shmat
+398 common shmdt sys_shmdt
+399 common msgget sys_msgget
+400 common msgsnd sys_msgsnd compat_sys_msgsnd
+401 common msgrcv sys_msgrcv compat_sys_msgrcv
+402 common msgctl sys_msgctl compat_sys_msgctl
+403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime
+404 32 clock_settime64 sys_clock_settime sys_clock_settime
+405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime
+406 32 clock_getres_time64 sys_clock_getres sys_clock_getres
+407 32 clock_nanosleep_time64 sys_clock_nanosleep sys_clock_nanosleep
+408 32 timer_gettime64 sys_timer_gettime sys_timer_gettime
+409 32 timer_settime64 sys_timer_settime sys_timer_settime
+410 32 timerfd_gettime64 sys_timerfd_gettime sys_timerfd_gettime
+411 32 timerfd_settime64 sys_timerfd_settime sys_timerfd_settime
+412 32 utimensat_time64 sys_utimensat sys_utimensat
+413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64
+414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64
+416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents
+417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64
+418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend
+419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive
+420 32 semtimedop_time64 sys_semtimedop sys_semtimedop
+421 32 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64
+422 32 futex_time64 sys_futex sys_futex
+423 32 sched_rr_get_interval_time64 sys_sched_rr_get_interval sys_sched_rr_get_interval
+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 nospu clone3 ppc_clone3
diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c
index f9db341c47b6..f0dbf7b075c8 100644
--- a/tools/perf/arch/powerpc/util/kvm-stat.c
+++ b/tools/perf/arch/powerpc/util/kvm-stat.c
@@ -32,7 +32,7 @@ const char *ppc_book3s_hv_kvm_tp[] = {
const char *kvm_events_tp[NR_TPS + 1];
const char *kvm_exit_reason;
-static void hcall_event_get_key(struct perf_evsel *evsel,
+static void hcall_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -55,14 +55,14 @@ static const char *get_hcall_exit_reason(u64 exit_code)
return "UNKNOWN";
}
-static bool hcall_event_end(struct perf_evsel *evsel,
+static bool hcall_event_end(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
return (!strcmp(evsel->name, kvm_events_tp[3]));
}
-static bool hcall_event_begin(struct perf_evsel *evsel,
+static bool hcall_event_begin(struct evsel *evsel,
struct perf_sample *sample, struct event_key *key)
{
if (!strcmp(evsel->name, kvm_events_tp[2])) {
@@ -106,7 +106,7 @@ const char * const kvm_skip_events[] = {
};
-static int is_tracepoint_available(const char *str, struct perf_evlist *evlist)
+static int is_tracepoint_available(const char *str, struct evlist *evlist)
{
struct parse_events_error err;
int ret;
@@ -119,7 +119,7 @@ static int is_tracepoint_available(const char *str, struct perf_evlist *evlist)
}
static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
const char **events_ptr;
int i, nr_tp = 0, err = -1;
@@ -146,7 +146,7 @@ static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm,
/* Wrapper to setup kvm tracepoints */
static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm)
{
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evlist *evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
diff --git a/tools/perf/arch/powerpc/util/mem-events.c b/tools/perf/arch/powerpc/util/mem-events.c
index d08311f04e95..07fb5e049488 100644
--- a/tools/perf/arch/powerpc/util/mem-events.c
+++ b/tools/perf/arch/powerpc/util/mem-events.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "map_symbol.h"
#include "mem-events.h"
/* PowerPC does not support 'ldlat' parameter. */
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index f14102b85509..e9c436eeffc9 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -4,7 +4,6 @@
#include <regex.h>
#include <linux/zalloc.h>
-#include "../../perf.h"
#include "../../util/perf_regs.h"
#include "../../util/debug.h"
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index b0a67eaf2ce8..8a4b717e0a53 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -5,6 +5,7 @@
*/
#include "debug.h"
+#include "dso.h"
#include "symbol.h"
#include "map.h"
#include "probe-event.h"
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c b/tools/perf/arch/powerpc/util/unwind-libdw.c
index 7a1f05ef2fc0..abf2dbc7f829 100644
--- a/tools/perf/arch/powerpc/util/unwind-libdw.c
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
+#include <linux/kernel.h>
#include "../../util/unwind-libdw.h"
#include "../../util/perf_regs.h"
#include "../../util/event.h"
diff --git a/tools/perf/arch/riscv/Build b/tools/perf/arch/riscv/Build
new file mode 100644
index 000000000000..e4e5f33c84d8
--- /dev/null
+++ b/tools/perf/arch/riscv/Build
@@ -0,0 +1 @@
+perf-y += util/
diff --git a/tools/perf/arch/riscv/Makefile b/tools/perf/arch/riscv/Makefile
new file mode 100644
index 000000000000..1aa9dd772489
--- /dev/null
+++ b/tools/perf/arch/riscv/Makefile
@@ -0,0 +1,4 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+endif
+PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
diff --git a/tools/perf/arch/riscv/include/perf_regs.h b/tools/perf/arch/riscv/include/perf_regs.h
new file mode 100644
index 000000000000..7a8bcde7a2b1
--- /dev/null
+++ b/tools/perf/arch/riscv/include/perf_regs.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <stdlib.h>
+#include <linux/types.h>
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK ((1ULL << PERF_REG_RISCV_MAX) - 1)
+#define PERF_REGS_MAX PERF_REG_RISCV_MAX
+#if __riscv_xlen == 64
+#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
+#else
+#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
+#endif
+
+#define PERF_REG_IP PERF_REG_RISCV_PC
+#define PERF_REG_SP PERF_REG_RISCV_SP
+
+static inline const char *perf_reg_name(int id)
+{
+ switch (id) {
+ case PERF_REG_RISCV_PC:
+ return "pc";
+ case PERF_REG_RISCV_RA:
+ return "ra";
+ case PERF_REG_RISCV_SP:
+ return "sp";
+ case PERF_REG_RISCV_GP:
+ return "gp";
+ case PERF_REG_RISCV_TP:
+ return "tp";
+ case PERF_REG_RISCV_T0:
+ return "t0";
+ case PERF_REG_RISCV_T1:
+ return "t1";
+ case PERF_REG_RISCV_T2:
+ return "t2";
+ case PERF_REG_RISCV_S0:
+ return "s0";
+ case PERF_REG_RISCV_S1:
+ return "s1";
+ case PERF_REG_RISCV_A0:
+ return "a0";
+ case PERF_REG_RISCV_A1:
+ return "a1";
+ case PERF_REG_RISCV_A2:
+ return "a2";
+ case PERF_REG_RISCV_A3:
+ return "a3";
+ case PERF_REG_RISCV_A4:
+ return "a4";
+ case PERF_REG_RISCV_A5:
+ return "a5";
+ case PERF_REG_RISCV_A6:
+ return "a6";
+ case PERF_REG_RISCV_A7:
+ return "a7";
+ case PERF_REG_RISCV_S2:
+ return "s2";
+ case PERF_REG_RISCV_S3:
+ return "s3";
+ case PERF_REG_RISCV_S4:
+ return "s4";
+ case PERF_REG_RISCV_S5:
+ return "s5";
+ case PERF_REG_RISCV_S6:
+ return "s6";
+ case PERF_REG_RISCV_S7:
+ return "s7";
+ case PERF_REG_RISCV_S8:
+ return "s8";
+ case PERF_REG_RISCV_S9:
+ return "s9";
+ case PERF_REG_RISCV_S10:
+ return "s10";
+ case PERF_REG_RISCV_S11:
+ return "s11";
+ case PERF_REG_RISCV_T3:
+ return "t3";
+ case PERF_REG_RISCV_T4:
+ return "t4";
+ case PERF_REG_RISCV_T5:
+ return "t5";
+ case PERF_REG_RISCV_T6:
+ return "t6";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/riscv/util/Build b/tools/perf/arch/riscv/util/Build
new file mode 100644
index 000000000000..1160bb2332ba
--- /dev/null
+++ b/tools/perf/arch/riscv/util/Build
@@ -0,0 +1,2 @@
+perf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/riscv/util/dwarf-regs.c b/tools/perf/arch/riscv/util/dwarf-regs.c
new file mode 100644
index 000000000000..cd0504c02e2e
--- /dev/null
+++ b/tools/perf/arch/riscv/util/dwarf-regs.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+ * Mapping of DWARF debug register numbers into register names.
+ */
+
+#include <stddef.h>
+#include <errno.h> /* for EINVAL */
+#include <string.h> /* for strcmp */
+#include <dwarf-regs.h>
+
+struct pt_regs_dwarfnum {
+ const char *name;
+ unsigned int dwarfnum;
+};
+
+#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
+#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
+
+struct pt_regs_dwarfnum riscv_dwarf_regs_table[] = {
+ REG_DWARFNUM_NAME("%zero", 0),
+ REG_DWARFNUM_NAME("%ra", 1),
+ REG_DWARFNUM_NAME("%sp", 2),
+ REG_DWARFNUM_NAME("%gp", 3),
+ REG_DWARFNUM_NAME("%tp", 4),
+ REG_DWARFNUM_NAME("%t0", 5),
+ REG_DWARFNUM_NAME("%t1", 6),
+ REG_DWARFNUM_NAME("%t2", 7),
+ REG_DWARFNUM_NAME("%s0", 8),
+ REG_DWARFNUM_NAME("%s1", 9),
+ REG_DWARFNUM_NAME("%a0", 10),
+ REG_DWARFNUM_NAME("%a1", 11),
+ REG_DWARFNUM_NAME("%a2", 12),
+ REG_DWARFNUM_NAME("%a3", 13),
+ REG_DWARFNUM_NAME("%a4", 14),
+ REG_DWARFNUM_NAME("%a5", 15),
+ REG_DWARFNUM_NAME("%a6", 16),
+ REG_DWARFNUM_NAME("%a7", 17),
+ REG_DWARFNUM_NAME("%s2", 18),
+ REG_DWARFNUM_NAME("%s3", 19),
+ REG_DWARFNUM_NAME("%s4", 20),
+ REG_DWARFNUM_NAME("%s5", 21),
+ REG_DWARFNUM_NAME("%s6", 22),
+ REG_DWARFNUM_NAME("%s7", 23),
+ REG_DWARFNUM_NAME("%s8", 24),
+ REG_DWARFNUM_NAME("%s9", 25),
+ REG_DWARFNUM_NAME("%s10", 26),
+ REG_DWARFNUM_NAME("%s11", 27),
+ REG_DWARFNUM_NAME("%t3", 28),
+ REG_DWARFNUM_NAME("%t4", 29),
+ REG_DWARFNUM_NAME("%t5", 30),
+ REG_DWARFNUM_NAME("%t6", 31),
+ REG_DWARFNUM_END,
+};
+
+#define RISCV_MAX_REGS ((sizeof(riscv_dwarf_regs_table) / \
+ sizeof(riscv_dwarf_regs_table[0])) - 1)
+
+const char *get_arch_regstr(unsigned int n)
+{
+ return (n < RISCV_MAX_REGS) ? riscv_dwarf_regs_table[n].name : NULL;
+}
+
+int regs_query_register_offset(const char *name)
+{
+ const struct pt_regs_dwarfnum *roff;
+
+ for (roff = riscv_dwarf_regs_table; roff->name; roff++)
+ if (!strcmp(roff->name, name))
+ return roff->dwarfnum;
+ return -EINVAL;
+}
diff --git a/tools/perf/arch/riscv/util/unwind-libdw.c b/tools/perf/arch/riscv/util/unwind-libdw.c
new file mode 100644
index 000000000000..19536e172850
--- /dev/null
+++ b/tools/perf/arch/riscv/util/unwind-libdw.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
+
+#include <elfutils/libdwfl.h>
+#include "../../util/unwind-libdw.h"
+#include "../../util/perf_regs.h"
+#include "../../util/event.h"
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
+{
+ struct unwind_info *ui = arg;
+ struct regs_dump *user_regs = &ui->sample->user_regs;
+ Dwarf_Word dwarf_regs[32];
+
+#define REG(r) ({ \
+ Dwarf_Word val = 0; \
+ perf_reg_value(&val, user_regs, PERF_REG_RISCV_##r); \
+ val; \
+})
+
+ dwarf_regs[0] = 0;
+ dwarf_regs[1] = REG(RA);
+ dwarf_regs[2] = REG(SP);
+ dwarf_regs[3] = REG(GP);
+ dwarf_regs[4] = REG(TP);
+ dwarf_regs[5] = REG(T0);
+ dwarf_regs[6] = REG(T1);
+ dwarf_regs[7] = REG(T2);
+ dwarf_regs[8] = REG(S0);
+ dwarf_regs[9] = REG(S1);
+ dwarf_regs[10] = REG(A0);
+ dwarf_regs[11] = REG(A1);
+ dwarf_regs[12] = REG(A2);
+ dwarf_regs[13] = REG(A3);
+ dwarf_regs[14] = REG(A4);
+ dwarf_regs[15] = REG(A5);
+ dwarf_regs[16] = REG(A6);
+ dwarf_regs[17] = REG(A7);
+ dwarf_regs[18] = REG(S2);
+ dwarf_regs[19] = REG(S3);
+ dwarf_regs[20] = REG(S4);
+ dwarf_regs[21] = REG(S5);
+ dwarf_regs[22] = REG(S6);
+ dwarf_regs[23] = REG(S7);
+ dwarf_regs[24] = REG(S8);
+ dwarf_regs[25] = REG(S9);
+ dwarf_regs[26] = REG(S10);
+ dwarf_regs[27] = REG(S11);
+ dwarf_regs[28] = REG(T3);
+ dwarf_regs[29] = REG(T4);
+ dwarf_regs[30] = REG(T5);
+ dwarf_regs[31] = REG(T6);
+ dwfl_thread_state_register_pc(thread, REG(PC));
+
+ return dwfl_thread_state_registers(thread, 0, PERF_REG_RISCV_MAX,
+ dwarf_regs);
+}
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
index 0fe1be93f375..b0fb70e38960 100644
--- a/tools/perf/arch/s390/util/auxtrace.c
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -8,6 +8,7 @@
#include "../../util/evlist.h"
#include "../../util/auxtrace.h"
#include "../../util/evsel.h"
+#include "../../util/record.h"
#define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */
#define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */
@@ -20,7 +21,7 @@ static void cpumsf_free(struct auxtrace_record *itr)
}
static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return 0;
}
@@ -28,7 +29,7 @@ static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
static int
cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
struct perf_session *session __maybe_unused,
- struct auxtrace_info_event *auxtrace_info __maybe_unused,
+ struct perf_record_auxtrace_info *auxtrace_info __maybe_unused,
size_t priv_size __maybe_unused)
{
auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF;
@@ -43,7 +44,7 @@ cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
static int
cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
struct record_opts *opts)
{
unsigned int factor = 1;
@@ -82,19 +83,19 @@ cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
* auxtrace_record__init is called when perf record
* check if the event really need auxtrace
*/
-struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
+struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
int *err)
{
struct auxtrace_record *aux;
- struct perf_evsel *pos;
+ struct evsel *pos;
int diagnose = 0;
*err = 0;
- if (evlist->nr_entries == 0)
+ if (evlist->core.nr_entries == 0)
return NULL;
evlist__for_each_entry(evlist, pos) {
- if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) {
+ if (pos->core.attr.config == PERF_EVENT_CPUM_SF_DIAG) {
diagnose = 1;
break;
}
diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c
index f852f2a77e0a..0fd4e9f49ed0 100644
--- a/tools/perf/arch/s390/util/kvm-stat.c
+++ b/tools/perf/arch/s390/util/kvm-stat.c
@@ -7,6 +7,7 @@
*/
#include <errno.h>
+#include <string.h>
#include "../../util/kvm-stat.h"
#include "../../util/evsel.h"
#include <asm/sie.h>
@@ -23,7 +24,7 @@ const char *kvm_exit_reason = "icptcode";
const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter";
const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit";
-static void event_icpt_insn_get_key(struct perf_evsel *evsel,
+static void event_icpt_insn_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -34,7 +35,7 @@ static void event_icpt_insn_get_key(struct perf_evsel *evsel,
key->exit_reasons = sie_icpt_insn_codes;
}
-static void event_sigp_get_key(struct perf_evsel *evsel,
+static void event_sigp_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -42,7 +43,7 @@ static void event_sigp_get_key(struct perf_evsel *evsel,
key->exit_reasons = sie_sigp_order_codes;
}
-static void event_diag_get_key(struct perf_evsel *evsel,
+static void event_diag_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -50,7 +51,7 @@ static void event_diag_get_key(struct perf_evsel *evsel,
key->exit_reasons = sie_diagnose_codes;
}
-static void event_icpt_prog_get_key(struct perf_evsel *evsel,
+static void event_icpt_prog_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c
index a19690a17291..c8c86a0c9b79 100644
--- a/tools/perf/arch/s390/util/machine.c
+++ b/tools/perf/arch/s390/util/machine.c
@@ -6,8 +6,9 @@
#include "machine.h"
#include "api/fs/fs.h"
#include "debug.h"
+#include "symbol.h"
-int arch__fix_module_text_start(u64 *start, const char *name)
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
{
u64 m_start = *start;
char path[PATH_MAX];
@@ -17,7 +18,35 @@ int arch__fix_module_text_start(u64 *start, const char *name)
if (sysfs__read_ull(path, (unsigned long long *)start) < 0) {
pr_debug2("Using module %s start:%#lx\n", path, m_start);
*start = m_start;
+ } else {
+ /* Successful read of the modules segment text start address.
+ * Calculate difference between module start address
+ * in memory and module text segment start address.
+ * For example module load address is 0x3ff8011b000
+ * (from /proc/modules) and module text segment start
+ * address is 0x3ff8011b870 (from file above).
+ *
+ * Adjust the module size and subtract the GOT table
+ * size located at the beginning of the module.
+ */
+ *size -= (*start - m_start);
}
return 0;
}
+
+/* On s390 kernel text segment start is located at very low memory addresses,
+ * for example 0x10000. Modules are located at very high memory addresses,
+ * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment
+ * and beginning of first module's text segment is very big.
+ * Therefore do not fill this gap and do not assign it to the kernel dso map.
+ */
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+ if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
+ /* Last kernel symbol mapped to end of page */
+ p->end = roundup(p->end, page_size);
+ else
+ p->end = c->start;
+ pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end);
+}
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index b4e6f9e6204a..c29976eca4a8 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -355,6 +355,8 @@
431 common fsconfig __x64_sys_fsconfig
432 common fsmount __x64_sys_fsmount
433 common fspick __x64_sys_fspick
+434 common pidfd_open __x64_sys_pidfd_open
+435 common clone3 __x64_sys_clone3/ptregs
#
# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/tools/perf/arch/x86/tests/bp-modify.c b/tools/perf/arch/x86/tests/bp-modify.c
index f53e4406709f..adcacf1b6609 100644
--- a/tools/perf/arch/x86/tests/bp-modify.c
+++ b/tools/perf/arch/x86/tests/bp-modify.c
@@ -7,6 +7,7 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <errno.h>
diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
index c3e5f4ab0d3e..745f29adb14b 100644
--- a/tools/perf/arch/x86/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
+#include "../../../../arch/x86/include/asm/insn.h"
+#include <string.h>
#include "debug.h"
#include "tests/tests.h"
#include "arch-tests.h"
-#include "intel-pt-decoder/insn.h"
#include "intel-pt-decoder/intel-pt-insn-decoder.h"
struct test_data {
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index 94aa0b673b7f..3b5cc3373821 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "tests/tests.h"
-#include "perf.h"
#include "cloexec.h"
#include "debug.h"
#include "evlist.h"
@@ -40,8 +39,8 @@ static pid_t spawn(void)
*/
int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel = NULL;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel = NULL;
struct perf_event_attr pe;
int i, fd[2], flag, ret;
size_t mmap_len;
@@ -51,7 +50,7 @@ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subt
flag = perf_event_open_cloexec_flag();
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
pr_debug("perf_evlist__new failed\n");
return TEST_FAIL;
@@ -124,6 +123,6 @@ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subt
kill(pid, SIGKILL);
wait(NULL);
out:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 7a7721604b86..eb3635941c2b 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -1,16 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/types.h>
#include <sys/prctl.h>
+#include <perf/cpumap.h>
+#include <perf/evlist.h>
+#include "debug.h"
#include "parse-events.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
#include "cpumap.h"
+#include "record.h"
#include "tsc.h"
#include "tests/tests.h"
@@ -49,10 +55,10 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
},
.sample_time = true,
};
- struct thread_map *threads = NULL;
- struct cpu_map *cpus = NULL;
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel = NULL;
+ struct perf_thread_map *threads = NULL;
+ struct perf_cpu_map *cpus = NULL;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel = NULL;
int err = -1, ret, i;
const char *comm1, *comm2;
struct perf_tsc_conversion tc;
@@ -65,13 +71,13 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads);
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
CHECK_NOT_NULL__(cpus);
- evlist = perf_evlist__new();
+ evlist = evlist__new();
CHECK_NOT_NULL__(evlist);
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
CHECK__(parse_events(evlist, "cycles:u", NULL));
@@ -79,11 +85,11 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
evsel = perf_evlist__first(evlist);
- evsel->attr.comm = 1;
- evsel->attr.disabled = 1;
- evsel->attr.enable_on_exec = 0;
+ evsel->core.attr.comm = 1;
+ evsel->core.attr.disabled = 1;
+ evsel->core.attr.enable_on_exec = 0;
- CHECK__(perf_evlist__open(evlist));
+ CHECK__(evlist__open(evlist));
CHECK__(perf_evlist__mmap(evlist, UINT_MAX));
@@ -97,7 +103,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
goto out_err;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
comm1 = "Test COMM 1";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0));
@@ -107,7 +113,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
comm2 = "Test COMM 2";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0));
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
for (i = 0; i < evlist->nr_mmaps; i++) {
md = &evlist->mmap[i];
@@ -163,6 +169,6 @@ next_event:
err = 0;
out_err:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index 7a11f02d6c6c..6e67cee792b1 100644
--- a/tools/perf/arch/x86/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -6,11 +6,13 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <linux/string.h>
#include <linux/types.h>
-#include "perf.h"
+#include "perf-sys.h"
#include "debug.h"
#include "tests/tests.h"
#include "cloexec.h"
+#include "event.h"
#include "util.h"
#include "arch-tests.h"
diff --git a/tools/perf/arch/x86/util/archinsn.c b/tools/perf/arch/x86/util/archinsn.c
index 4237bb2e7fa2..9876c7a7ed7c 100644
--- a/tools/perf/arch/x86/util/archinsn.c
+++ b/tools/perf/arch/x86/util/archinsn.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
+#include "../../../../arch/x86/include/asm/insn.h"
#include "archinsn.h"
-#include "util/intel-pt-decoder/insn.h"
#include "machine.h"
#include "thread.h"
#include "symbol.h"
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index d711268af330..96f4a2c11893 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -16,12 +16,12 @@
#include "../../util/evlist.h"
static
-struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
+struct auxtrace_record *auxtrace_record__init_intel(struct evlist *evlist,
int *err)
{
struct perf_pmu *intel_pt_pmu;
struct perf_pmu *intel_bts_pmu;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool found_pt = false;
bool found_bts = false;
@@ -29,9 +29,9 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
evlist__for_each_entry(evlist, evsel) {
- if (intel_pt_pmu && evsel->attr.type == intel_pt_pmu->type)
+ if (intel_pt_pmu && evsel->core.attr.type == intel_pt_pmu->type)
found_pt = true;
- if (intel_bts_pmu && evsel->attr.type == intel_bts_pmu->type)
+ if (intel_bts_pmu && evsel->core.attr.type == intel_bts_pmu->type)
found_bts = true;
}
@@ -50,7 +50,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
return NULL;
}
-struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
+struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
int *err)
{
char buffer[64];
diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
index af9a9f2600be..662ecf84a421 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <regex.h>
+#include "../../util/debug.h"
#include "../../util/header.h"
static inline void
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index ec5c1bb84095..d263430c045f 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -12,14 +12,17 @@
#include <linux/zalloc.h>
#include "../../util/cpumap.h"
+#include "../../util/event.h"
#include "../../util/evsel.h"
#include "../../util/evlist.h"
#include "../../util/session.h"
#include "../../util/pmu.h"
#include "../../util/debug.h"
+#include "../../util/record.h"
#include "../../util/tsc.h"
#include "../../util/auxtrace.h"
#include "../../util/intel-bts.h"
+#include "../../util/util.h"
#define KiB(x) ((x) * 1024)
#define MiB(x) ((x) * 1024 * 1024)
@@ -35,7 +38,7 @@ struct intel_bts_snapshot_ref {
struct intel_bts_recording {
struct auxtrace_record itr;
struct perf_pmu *intel_bts_pmu;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
bool snapshot_mode;
size_t snapshot_size;
int snapshot_ref_cnt;
@@ -50,14 +53,14 @@ struct branch {
static size_t
intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return INTEL_BTS_AUXTRACE_PRIV_SIZE;
}
static int intel_bts_info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size)
{
struct intel_bts_recording *btsr =
@@ -99,27 +102,27 @@ static int intel_bts_info_fill(struct auxtrace_record *itr,
}
static int intel_bts_recording_options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts)
{
struct intel_bts_recording *btsr =
container_of(itr, struct intel_bts_recording, itr);
struct perf_pmu *intel_bts_pmu = btsr->intel_bts_pmu;
- struct perf_evsel *evsel, *intel_bts_evsel = NULL;
- const struct cpu_map *cpus = evlist->cpus;
- bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
+ struct evsel *evsel, *intel_bts_evsel = NULL;
+ const struct perf_cpu_map *cpus = evlist->core.cpus;
+ bool privileged = perf_event_paranoid_check(-1);
btsr->evlist = evlist;
btsr->snapshot_mode = opts->auxtrace_snapshot_mode;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == intel_bts_pmu->type) {
+ if (evsel->core.attr.type == intel_bts_pmu->type) {
if (intel_bts_evsel) {
pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n");
return -EINVAL;
}
- evsel->attr.freq = 0;
- evsel->attr.sample_period = 1;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = 1;
intel_bts_evsel = evsel;
opts->full_auxtrace = true;
}
@@ -133,7 +136,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
if (!opts->full_auxtrace)
return 0;
- if (opts->full_auxtrace && !cpu_map__empty(cpus)) {
+ if (opts->full_auxtrace && !perf_cpu_map__empty(cpus)) {
pr_err(INTEL_BTS_PMU_NAME " does not support per-cpu recording\n");
return -EINVAL;
}
@@ -214,13 +217,13 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
* In the case of per-cpu mmaps, we need the CPU on the
* AUX event.
*/
- if (!cpu_map__empty(cpus))
+ if (!perf_cpu_map__empty(cpus))
perf_evsel__set_sample_bit(intel_bts_evsel, CPU);
}
/* Add dummy event to keep tracking */
if (opts->full_auxtrace) {
- struct perf_evsel *tracking_evsel;
+ struct evsel *tracking_evsel;
int err;
err = parse_events(evlist, "dummy:u", NULL);
@@ -231,8 +234,8 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
perf_evlist__set_tracking_event(evlist, tracking_evsel);
- tracking_evsel->attr.freq = 0;
- tracking_evsel->attr.sample_period = 1;
+ tracking_evsel->core.attr.freq = 0;
+ tracking_evsel->core.attr.sample_period = 1;
}
return 0;
@@ -313,11 +316,11 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr)
{
struct intel_bts_recording *btsr =
container_of(itr, struct intel_bts_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(btsr->evlist, evsel) {
- if (evsel->attr.type == btsr->intel_bts_pmu->type)
- return perf_evsel__disable(evsel);
+ if (evsel->core.attr.type == btsr->intel_bts_pmu->type)
+ return evsel__disable(evsel);
}
return -EINVAL;
}
@@ -326,11 +329,11 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr)
{
struct intel_bts_recording *btsr =
container_of(itr, struct intel_bts_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(btsr->evlist, evsel) {
- if (evsel->attr.type == btsr->intel_bts_pmu->type)
- return perf_evsel__enable(evsel);
+ if (evsel->core.attr.type == btsr->intel_bts_pmu->type)
+ return evsel__enable(evsel);
}
return -EINVAL;
}
@@ -408,10 +411,10 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx)
{
struct intel_bts_recording *btsr =
container_of(itr, struct intel_bts_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(btsr->evlist, evsel) {
- if (evsel->attr.type == btsr->intel_bts_pmu->type)
+ if (evsel->core.attr.type == btsr->intel_bts_pmu->type)
return perf_evlist__enable_event_idx(btsr->evlist,
evsel, idx);
}
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 609088c01e3a..cb7cf16af79c 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -13,7 +13,6 @@
#include <linux/zalloc.h>
#include <cpuid.h>
-#include "../../perf.h"
#include "../../util/session.h"
#include "../../util/event.h"
#include "../../util/evlist.h"
@@ -24,7 +23,10 @@
#include "../../util/pmu.h"
#include "../../util/debug.h"
#include "../../util/auxtrace.h"
+#include "../../util/record.h"
+#include "../../util/target.h"
#include "../../util/tsc.h"
+#include "../../util/util.h"
#include "../../util/intel-pt.h"
#define KiB(x) ((x) * 1024)
@@ -44,7 +46,7 @@ struct intel_pt_recording {
struct auxtrace_record itr;
struct perf_pmu *intel_pt_pmu;
int have_sched_switch;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
bool snapshot_mode;
bool snapshot_init_done;
size_t snapshot_size;
@@ -110,9 +112,9 @@ static u64 intel_pt_masked_bits(u64 mask, u64 bits)
}
static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
- struct perf_evlist *evlist, u64 *res)
+ struct evlist *evlist, u64 *res)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u64 mask;
*res = 0;
@@ -122,8 +124,8 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
return -EINVAL;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == intel_pt_pmu->type) {
- *res = intel_pt_masked_bits(mask, evsel->attr.config);
+ if (evsel->core.attr.type == intel_pt_pmu->type) {
+ *res = intel_pt_masked_bits(mask, evsel->core.attr.config);
return 0;
}
}
@@ -132,7 +134,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
}
static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
u64 val;
int err, topa_multiple_entries;
@@ -268,13 +270,13 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
return attr;
}
-static const char *intel_pt_find_filter(struct perf_evlist *evlist,
+static const char *intel_pt_find_filter(struct evlist *evlist,
struct perf_pmu *intel_pt_pmu)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == intel_pt_pmu->type)
+ if (evsel->core.attr.type == intel_pt_pmu->type)
return evsel->filter;
}
@@ -289,7 +291,7 @@ static size_t intel_pt_filter_bytes(const char *filter)
}
static size_t
-intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
+intel_pt_info_priv_size(struct auxtrace_record *itr, struct evlist *evlist)
{
struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr);
@@ -312,7 +314,7 @@ static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
static int intel_pt_info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size)
{
struct intel_pt_recording *ptr =
@@ -326,7 +328,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
unsigned long max_non_turbo_ratio;
size_t filter_str_len;
const char *filter;
- u64 *info;
+ __u64 *info;
int err;
if (priv_size != ptr->priv_size)
@@ -365,7 +367,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
ui__warning("Intel Processor Trace: TSC not available\n");
}
- per_cpu_mmaps = !cpu_map__empty(session->evlist->cpus);
+ per_cpu_mmaps = !perf_cpu_map__empty(session->evlist->core.cpus);
auxtrace_info->type = PERF_AUXTRACE_INTEL_PT;
auxtrace_info->priv[INTEL_PT_PMU_TYPE] = intel_pt_pmu->type;
@@ -398,10 +400,10 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
return 0;
}
-static int intel_pt_track_switches(struct perf_evlist *evlist)
+static int intel_pt_track_switches(struct evlist *evlist)
{
const char *sched_switch = "sched:sched_switch";
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err;
if (!perf_evlist__can_select_event(evlist, sched_switch))
@@ -513,7 +515,7 @@ out_err:
}
static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
int err;
char c;
@@ -526,39 +528,59 @@ static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu,
* sets pt=0, which avoids senseless kernel errors.
*/
if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
- !(evsel->attr.config & 1)) {
+ !(evsel->core.attr.config & 1)) {
pr_warning("pt=0 doesn't make sense, forcing pt=1\n");
- evsel->attr.config |= 1;
+ evsel->core.attr.config |= 1;
}
err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds",
"cyc_thresh", "caps/psb_cyc",
- evsel->attr.config);
+ evsel->core.attr.config);
if (err)
return err;
err = intel_pt_val_config_term(intel_pt_pmu, "caps/mtc_periods",
"mtc_period", "caps/mtc",
- evsel->attr.config);
+ evsel->core.attr.config);
if (err)
return err;
return intel_pt_val_config_term(intel_pt_pmu, "caps/psb_periods",
"psb_period", "caps/psb_cyc",
- evsel->attr.config);
+ evsel->core.attr.config);
+}
+
+/*
+ * Currently, there is not enough information to disambiguate different PEBS
+ * events, so only allow one.
+ */
+static bool intel_pt_too_many_aux_output(struct evlist *evlist)
+{
+ struct evsel *evsel;
+ int aux_output_cnt = 0;
+
+ evlist__for_each_entry(evlist, evsel)
+ aux_output_cnt += !!evsel->core.attr.aux_output;
+
+ if (aux_output_cnt > 1) {
+ pr_err(INTEL_PT_PMU_NAME " supports at most one event with aux-output\n");
+ return true;
+ }
+
+ return false;
}
static int intel_pt_recording_options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts)
{
struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr);
struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
bool have_timing_info, need_immediate = false;
- struct perf_evsel *evsel, *intel_pt_evsel = NULL;
- const struct cpu_map *cpus = evlist->cpus;
- bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
+ struct evsel *evsel, *intel_pt_evsel = NULL;
+ const struct perf_cpu_map *cpus = evlist->core.cpus;
+ bool privileged = perf_event_paranoid_check(-1);
u64 tsc_bit;
int err;
@@ -566,13 +588,13 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == intel_pt_pmu->type) {
+ if (evsel->core.attr.type == intel_pt_pmu->type) {
if (intel_pt_evsel) {
pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n");
return -EINVAL;
}
- evsel->attr.freq = 0;
- evsel->attr.sample_period = 1;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = 1;
intel_pt_evsel = evsel;
opts->full_auxtrace = true;
}
@@ -588,6 +610,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
return -EINVAL;
}
+ if (intel_pt_too_many_aux_output(evlist))
+ return -EINVAL;
+
if (!opts->full_auxtrace)
return 0;
@@ -670,7 +695,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
- if (opts->full_auxtrace && (intel_pt_evsel->attr.config & tsc_bit))
+ if (opts->full_auxtrace && (intel_pt_evsel->core.attr.config & tsc_bit))
have_timing_info = true;
else
have_timing_info = false;
@@ -679,13 +704,13 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
* Per-cpu recording needs sched_switch events to distinguish different
* threads.
*/
- if (have_timing_info && !cpu_map__empty(cpus)) {
+ if (have_timing_info && !perf_cpu_map__empty(cpus)) {
if (perf_can_record_switch_events()) {
bool cpu_wide = !target__none(&opts->target) &&
!target__has_task(&opts->target);
if (!cpu_wide && perf_can_record_cpu_wide()) {
- struct perf_evsel *switch_evsel;
+ struct evsel *switch_evsel;
err = parse_events(evlist, "dummy:u", NULL);
if (err)
@@ -693,9 +718,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
switch_evsel = perf_evlist__last(evlist);
- switch_evsel->attr.freq = 0;
- switch_evsel->attr.sample_period = 1;
- switch_evsel->attr.context_switch = 1;
+ switch_evsel->core.attr.freq = 0;
+ switch_evsel->core.attr.sample_period = 1;
+ switch_evsel->core.attr.context_switch = 1;
switch_evsel->system_wide = true;
switch_evsel->no_aux_samples = true;
@@ -737,13 +762,13 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
* In the case of per-cpu mmaps, we need the CPU on the
* AUX event.
*/
- if (!cpu_map__empty(cpus))
+ if (!perf_cpu_map__empty(cpus))
perf_evsel__set_sample_bit(intel_pt_evsel, CPU);
}
/* Add dummy event to keep tracking */
if (opts->full_auxtrace) {
- struct perf_evsel *tracking_evsel;
+ struct evsel *tracking_evsel;
err = parse_events(evlist, "dummy:u", NULL);
if (err)
@@ -753,15 +778,15 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
perf_evlist__set_tracking_event(evlist, tracking_evsel);
- tracking_evsel->attr.freq = 0;
- tracking_evsel->attr.sample_period = 1;
+ tracking_evsel->core.attr.freq = 0;
+ tracking_evsel->core.attr.sample_period = 1;
tracking_evsel->no_aux_samples = true;
if (need_immediate)
tracking_evsel->immediate = true;
/* In per-cpu case, always need the time of mmap events etc */
- if (!cpu_map__empty(cpus)) {
+ if (!perf_cpu_map__empty(cpus)) {
perf_evsel__set_sample_bit(tracking_evsel, TIME);
/* And the CPU for switch events */
perf_evsel__set_sample_bit(tracking_evsel, CPU);
@@ -773,7 +798,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
* Warn the user when we do not have enough information to decode i.e.
* per-cpu with no sched_switch (except workload-only).
*/
- if (!ptr->have_sched_switch && !cpu_map__empty(cpus) &&
+ if (!ptr->have_sched_switch && !perf_cpu_map__empty(cpus) &&
!target__none(&opts->target))
ui__warning("Intel Processor Trace decoding will not be possible except for kernel tracing!\n");
@@ -784,11 +809,11 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
{
struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->intel_pt_pmu->type)
- return perf_evsel__disable(evsel);
+ if (evsel->core.attr.type == ptr->intel_pt_pmu->type)
+ return evsel__disable(evsel);
}
return -EINVAL;
}
@@ -797,11 +822,11 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
{
struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->intel_pt_pmu->type)
- return perf_evsel__enable(evsel);
+ if (evsel->core.attr.type == ptr->intel_pt_pmu->type)
+ return evsel__enable(evsel);
}
return -EINVAL;
}
@@ -1070,10 +1095,10 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
{
struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr);
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->attr.type == ptr->intel_pt_pmu->type)
+ if (evsel->core.attr.type == ptr->intel_pt_pmu->type)
return perf_evlist__enable_event_idx(ptr->evlist, evsel,
idx);
}
diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c
index 865a9762f22e..c0775c39227f 100644
--- a/tools/perf/arch/x86/util/kvm-stat.c
+++ b/tools/perf/arch/x86/util/kvm-stat.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
-#include "../../util/kvm-stat.h"
-#include "../../util/evsel.h"
+#include <string.h>
+#include "../../../util/kvm-stat.h"
+#include "../../../util/evsel.h"
#include <asm/svm.h>
#include <asm/vmx.h>
#include <asm/kvm.h>
@@ -27,7 +28,7 @@ const char *kvm_exit_trace = "kvm:kvm_exit";
* the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
* the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
*/
-static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
+static void mmio_event_get_key(struct evsel *evsel, struct perf_sample *sample,
struct event_key *key)
{
key->key = perf_evsel__intval(evsel, sample, "gpa");
@@ -38,7 +39,7 @@ static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sam
#define KVM_TRACE_MMIO_READ 1
#define KVM_TRACE_MMIO_WRITE 2
-static bool mmio_event_begin(struct perf_evsel *evsel,
+static bool mmio_event_begin(struct evsel *evsel,
struct perf_sample *sample, struct event_key *key)
{
/* MMIO read begin event in kernel. */
@@ -55,7 +56,7 @@ static bool mmio_event_begin(struct perf_evsel *evsel,
return false;
}
-static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
+static bool mmio_event_end(struct evsel *evsel, struct perf_sample *sample,
struct event_key *key)
{
/* MMIO write end event in kernel. */
@@ -89,7 +90,7 @@ static struct kvm_events_ops mmio_events = {
};
/* The time of emulation pio access is from kvm_pio to kvm_entry. */
-static void ioport_event_get_key(struct perf_evsel *evsel,
+static void ioport_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -97,7 +98,7 @@ static void ioport_event_get_key(struct perf_evsel *evsel,
key->info = perf_evsel__intval(evsel, sample, "rw");
}
-static bool ioport_event_begin(struct perf_evsel *evsel,
+static bool ioport_event_begin(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -109,7 +110,7 @@ static bool ioport_event_begin(struct perf_evsel *evsel,
return false;
}
-static bool ioport_event_end(struct perf_evsel *evsel,
+static bool ioport_event_end(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index 0d7b77ff0ae6..c218b83e063b 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -2,11 +2,13 @@
#include <errno.h>
#include <string.h>
#include <regex.h>
+#include <linux/kernel.h>
#include <linux/zalloc.h>
-#include "../../perf.h"
+#include "../../perf-sys.h"
#include "../../util/perf_regs.h"
#include "../../util/debug.h"
+#include "../../util/event.h"
const struct sample_reg sample_reg_masks[] = {
SMPL_REG(AX, PERF_REG_X86_AX),
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 950539f9a4f7..c5197a15119b 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -5,10 +5,10 @@
#include <linux/stddef.h>
#include <linux/perf_event.h>
-#include "../../perf.h"
#include <linux/types.h>
-#include "../../util/debug.h"
-#include "../../util/tsc.h"
+#include <asm/barrier.h>
+#include "../../../util/debug.h"
+#include "../../../util/tsc.h"
int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
struct perf_tsc_conversion *tc)
@@ -57,7 +57,7 @@ int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
.time_conv = {
.header = {
.type = PERF_RECORD_TIME_CONV,
- .size = sizeof(struct time_conv_event),
+ .size = sizeof(struct perf_record_time_conv),
},
},
};
diff --git a/tools/perf/bench/epoll-ctl.c b/tools/perf/bench/epoll-ctl.c
index 2af067859966..d1caa4a0a12a 100644
--- a/tools/perf/bench/epoll-ctl.c
+++ b/tools/perf/bench/epoll-ctl.c
@@ -14,12 +14,14 @@
#include <inttypes.h>
#include <signal.h>
#include <stdlib.h>
+#include <unistd.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
+#include <perf/cpumap.h>
#include "../util/stat.h"
#include <subcmd/parse-options.h>
@@ -219,7 +221,7 @@ static void init_fdmaps(struct worker *w, int pct)
}
}
-static int do_threads(struct worker *worker, struct cpu_map *cpu)
+static int do_threads(struct worker *worker, struct perf_cpu_map *cpu)
{
pthread_attr_t thread_attr, *attrp = NULL;
cpu_set_t cpuset;
@@ -301,7 +303,7 @@ int bench_epoll_ctl(int argc, const char **argv)
int j, ret = 0;
struct sigaction act;
struct worker *worker = NULL;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
struct rlimit rl, prevrl;
unsigned int i;
@@ -315,7 +317,7 @@ int bench_epoll_ctl(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
goto errmem;
diff --git a/tools/perf/bench/epoll-wait.c b/tools/perf/bench/epoll-wait.c
index fe85448abd45..f6b4472847d2 100644
--- a/tools/perf/bench/epoll-wait.c
+++ b/tools/perf/bench/epoll-wait.c
@@ -63,6 +63,7 @@
/* For the CLR_() macros */
#include <string.h>
#include <pthread.h>
+#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
@@ -75,6 +76,7 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/types.h>
+#include <perf/cpumap.h>
#include "../util/stat.h"
#include <subcmd/parse-options.h>
@@ -288,7 +290,7 @@ static void print_summary(void)
(int) runtime.tv_sec);
}
-static int do_threads(struct worker *worker, struct cpu_map *cpu)
+static int do_threads(struct worker *worker, struct perf_cpu_map *cpu)
{
pthread_attr_t thread_attr, *attrp = NULL;
cpu_set_t cpuset;
@@ -415,7 +417,7 @@ int bench_epoll_wait(int argc, const char **argv)
struct sigaction act;
unsigned int i;
struct worker *worker = NULL;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
pthread_t wthread;
struct rlimit rl, prevrl;
@@ -429,7 +431,7 @@ int bench_epoll_wait(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
goto errmem;
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index a80797763e1f..80e138904c66 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>
#include <sys/time.h>
+#include <perf/cpumap.h>
#include "../util/stat.h"
#include <subcmd/parse-options.h>
@@ -124,7 +125,7 @@ int bench_futex_hash(int argc, const char **argv)
unsigned int i;
pthread_attr_t thread_attr;
struct worker *worker = NULL;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0);
if (argc) {
@@ -132,7 +133,7 @@ int bench_futex_hash(int argc, const char **argv)
exit(EXIT_FAILURE);
}
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
goto errmem;
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index d02330a69745..c5d6d0abbaa9 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>
#include <errno.h>
+#include <perf/cpumap.h>
#include "bench.h"
#include "futex.h"
#include "cpumap.h"
@@ -116,7 +117,7 @@ static void *workerfn(void *arg)
}
static void create_threads(struct worker *w, pthread_attr_t thread_attr,
- struct cpu_map *cpu)
+ struct perf_cpu_map *cpu)
{
cpu_set_t cpuset;
unsigned int i;
@@ -150,13 +151,13 @@ int bench_futex_lock_pi(int argc, const char **argv)
unsigned int i;
struct sigaction act;
pthread_attr_t thread_attr;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0);
if (argc)
goto err;
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index fc692efa0c05..75d3418c1a88 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/time64.h>
#include <errno.h>
+#include <perf/cpumap.h>
#include "bench.h"
#include "futex.h"
#include "cpumap.h"
@@ -84,7 +85,7 @@ static void *workerfn(void *arg __maybe_unused)
}
static void block_threads(pthread_t *w,
- pthread_attr_t thread_attr, struct cpu_map *cpu)
+ pthread_attr_t thread_attr, struct perf_cpu_map *cpu)
{
cpu_set_t cpuset;
unsigned int i;
@@ -117,13 +118,13 @@ int bench_futex_requeue(int argc, const char **argv)
unsigned int i, j;
struct sigaction act;
pthread_attr_t thread_attr;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0);
if (argc)
goto err;
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "cpu_map__new");
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 69d8fdc87315..163fe16c275a 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -138,7 +138,7 @@ static void *blocked_workerfn(void *arg __maybe_unused)
}
static void block_threads(pthread_t *w, pthread_attr_t thread_attr,
- struct cpu_map *cpu)
+ struct perf_cpu_map *cpu)
{
cpu_set_t cpuset;
unsigned int i;
@@ -224,7 +224,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
struct sigaction act;
pthread_attr_t thread_attr;
struct thread_data *waking_worker;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
argc = parse_options(argc, argv, options,
bench_futex_wake_parallel_usage, 0);
@@ -237,7 +237,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index e8181ad7d088..77dcdc13618a 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/time64.h>
#include <errno.h>
+#include <perf/cpumap.h>
#include "bench.h"
#include "futex.h"
#include "cpumap.h"
@@ -90,7 +91,7 @@ static void print_summary(void)
}
static void block_threads(pthread_t *w,
- pthread_attr_t thread_attr, struct cpu_map *cpu)
+ pthread_attr_t thread_attr, struct perf_cpu_map *cpu)
{
cpu_set_t cpuset;
unsigned int i;
@@ -123,7 +124,7 @@ int bench_futex_wake(int argc, const char **argv)
unsigned int i, j;
struct sigaction act;
pthread_attr_t thread_attr;
- struct cpu_map *cpu;
+ struct perf_cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0);
if (argc) {
@@ -131,7 +132,7 @@ int bench_futex_wake(int argc, const char **argv)
exit(EXIT_FAILURE);
}
- cpu = cpu_map__new(NULL);
+ cpu = perf_cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 64dc994c72ea..9235b76501be 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -8,7 +8,7 @@
*/
#include "debug.h"
-#include "../perf.h"
+#include "../perf-sys.h"
#include <subcmd/parse-options.h>
#include "../util/header.h"
#include "../util/cloexec.h"
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include <linux/time64.h>
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index a640ca7aaada..62b8ef4bcb1f 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -9,7 +9,6 @@
/* For the CLR_() macros */
#include <pthread.h>
-#include "../perf.h"
#include "../builtin.h"
#include <subcmd/parse-options.h>
#include "../util/cloexec.h"
@@ -379,8 +378,10 @@ static u8 *alloc_data(ssize_t bytes0, int map_flags,
/* Allocate and initialize all memory on CPU#0: */
if (init_cpu0) {
- orig_mask = bind_to_node(0);
- bind_to_memnode(0);
+ int node = numa_node_of_cpu(0);
+
+ orig_mask = bind_to_node(node);
+ bind_to_memnode(node);
}
bytes = bytes0 + HPSIZE;
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index f9d7641ae833..c63eb9a46346 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -10,7 +10,6 @@
*
*/
-#include "../perf.h"
#include "../util/util.h"
#include <subcmd/parse-options.h>
#include "../builtin.h"
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 0591be008f2a..35b07f197d48 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -9,7 +9,6 @@
* http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
* Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
*/
-#include "../perf.h"
#include "../util/util.h"
#include <subcmd/parse-options.h>
#include "../builtin.h"
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e0aa14faf2b5..4e4d2e76232e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -24,15 +24,17 @@
#include "util/event.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
-#include "util/thread.h"
#include "util/sort.h"
#include "util/hist.h"
+#include "util/dso.h"
#include "util/map.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/data.h"
#include "arch/common.h"
#include "util/block-range.h"
+#include "util/map_symbol.h"
+#include "util/branch.h"
#include <dlfcn.h>
#include <errno.h>
@@ -156,7 +158,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
struct hist_entry *he = iter->he;
struct branch_info *bi;
struct perf_sample *sample = iter->sample;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
int err;
bi = he->branch_info;
@@ -171,7 +173,7 @@ out:
return err;
}
-static int process_branch_callback(struct perf_evsel *evsel,
+static int process_branch_callback(struct evsel *evsel,
struct perf_sample *sample,
struct addr_location *al __maybe_unused,
struct perf_annotate *ann,
@@ -208,7 +210,7 @@ static bool has_annotation(struct perf_annotate *ann)
return ui__has_annotation() || ann->use_stdio2;
}
-static int perf_evsel__add_sample(struct perf_evsel *evsel,
+static int perf_evsel__add_sample(struct evsel *evsel,
struct perf_sample *sample,
struct addr_location *al,
struct perf_annotate *ann,
@@ -257,7 +259,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
@@ -293,7 +295,7 @@ static int process_feature_event(struct perf_session *session,
}
static int hist_entry__tty_annotate(struct hist_entry *he,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_annotate *ann)
{
if (!ann->use_stdio2)
@@ -303,7 +305,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
}
static void hists__find_annotations(struct hists *hists,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_annotate *ann)
{
struct rb_node *nd = rb_first_cached(&hists->entries), *next;
@@ -333,7 +335,7 @@ find_next:
if (use_browser == 2) {
int ret;
int (*annotate)(struct hist_entry *he,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt);
annotate = dlsym(perf_gtk_handle,
@@ -387,7 +389,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
{
int ret;
struct perf_session *session = ann->session;
- struct perf_evsel *pos;
+ struct evsel *pos;
u64 total_nr_samples;
if (ann->cpu_list) {
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b8e7c38ef221..c06fe21c8613 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -16,7 +16,6 @@
* futex ... Futex performance
* epoll ... Event poll performance
*/
-#include "perf.h"
#include <subcmd/parse-options.h>
#include "builtin.h"
#include "bench/bench.h"
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 10457b10e568..1a69eb565dc0 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -14,18 +14,20 @@
#include <errno.h>
#include <unistd.h>
#include "builtin.h"
-#include "perf.h"
#include "namespaces.h"
-#include "util/cache.h"
#include "util/debug.h"
#include "util/header.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/strlist.h"
#include "util/build-id.h"
#include "util/session.h"
+#include "util/dso.h"
#include "util/symbol.h"
#include "util/time-utils.h"
+#include "util/util.h"
#include "util/probe-file.h"
+#include <linux/string.h>
static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
{
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index f403e19488b5..5a0d8b378cb5 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0
/*
* builtin-buildid-list.c
*
@@ -11,8 +10,9 @@
#include "builtin.h"
#include "perf.h"
#include "util/build-id.h"
-#include "util/cache.h"
#include "util/debug.h"
+#include "util/dso.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/session.h"
#include "util/symbol.h"
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index e3776f5c2e01..b09b12e0976b 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -20,12 +20,15 @@
#include <sys/param.h>
#include "debug.h"
#include "builtin.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
+#include "map_symbol.h"
#include "mem-events.h"
#include "session.h"
#include "hist.h"
#include "sort.h"
#include "tool.h"
+#include "cacheline.h"
#include "data.h"
#include "event.h"
#include "evlist.h"
@@ -34,6 +37,9 @@
#include "thread.h"
#include "mem2node.h"
#include "symbol.h"
+#include "ui/ui.h"
+#include "ui/progress.h"
+#include "../perf.h"
struct c2c_hists {
struct hists hists;
@@ -248,7 +254,7 @@ static void compute_stats(struct c2c_hist_entry *c2c_he,
static int process_sample_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct c2c_hists *c2c_hists = &c2c.hists;
@@ -1106,7 +1112,7 @@ node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
break;
case 1:
{
- int num = bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt);
+ int num = bitmap_weight(set, c2c.cpus_cnt);
struct c2c_stats *stats = &c2c_he->node_stats[node];
ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
@@ -2027,7 +2033,7 @@ static int setup_nodes(struct perf_session *session)
c2c.node_info = 2;
c2c.nodes_cnt = session->header.env.nr_numa_nodes;
- c2c.cpus_cnt = session->header.env.nr_cpus_online;
+ c2c.cpus_cnt = session->header.env.nr_cpus_avail;
n = session->header.env.numa_nodes;
if (!n)
@@ -2049,7 +2055,7 @@ static int setup_nodes(struct perf_session *session)
c2c.cpu2node = cpu2node;
for (node = 0; node < c2c.nodes_cnt; node++) {
- struct cpu_map *map = n[node].map;
+ struct perf_cpu_map *map = n[node].map;
unsigned long *set;
set = bitmap_alloc(c2c.cpus_cnt);
@@ -2059,7 +2065,7 @@ static int setup_nodes(struct perf_session *session)
nodes[node] = set;
/* empty node, skip */
- if (cpu_map__empty(map))
+ if (perf_cpu_map__empty(map))
continue;
for (cpu = 0; cpu < map->nr; cpu++) {
@@ -2236,8 +2242,8 @@ static void print_pareto(FILE *out)
static void print_c2c_info(FILE *out, struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel;
bool first = true;
fprintf(out, "=================================================\n");
@@ -2567,7 +2573,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
return parse_callchain_report_opt(arg);
}
-static int setup_callchain(struct perf_evlist *evlist)
+static int setup_callchain(struct evlist *evlist)
{
u64 sample_type = perf_evlist__combined_sample_type(evlist);
enum perf_call_graph_mode mode = CALLCHAIN_NONE;
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 6c1284c87aaa..42d8157e047a 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -7,14 +7,13 @@
*/
#include "builtin.h"
-#include "perf.h"
-
#include "util/cache.h"
#include <subcmd/parse-options.h>
#include "util/util.h"
#include "util/debug.h"
#include "util/config.h"
#include <linux/string.h>
+#include <stdio.h>
#include <stdlib.h>
static bool use_system_config, use_user_config;
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index dde25d4ca56d..ca2fb44874e4 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
+#include <stdio.h>
+#include <string.h>
#include "builtin.h"
#include "perf.h"
#include "debug.h"
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index f6f5dd15bea7..827e4800d862 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -6,6 +6,7 @@
* DSOs and symbol information, sort them and produce a diff.
*/
#include "builtin.h"
+#include "perf.h"
#include "util/debug.h"
#include "util/event.h"
@@ -15,6 +16,7 @@
#include "util/session.h"
#include "util/tool.h"
#include "util/sort.h"
+#include "util/srcline.h"
#include "util/symbol.h"
#include "util/data.h"
#include "util/config.h"
@@ -22,6 +24,8 @@
#include "util/annotate.h"
#include "util/map.h"
#include <linux/zalloc.h>
+#include <subcmd/pager.h>
+#include <subcmd/parse-options.h>
#include <errno.h>
#include <inttypes.h>
@@ -376,7 +380,7 @@ struct hist_entry_ops block_hist_ops = {
static int diff__process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool);
@@ -448,10 +452,10 @@ static struct perf_diff pdiff = {
},
};
-static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
- struct perf_evlist *evlist)
+static struct evsel *evsel_match(struct evsel *evsel,
+ struct evlist *evlist)
{
- struct perf_evsel *e;
+ struct evsel *e;
evlist__for_each_entry(evlist, e) {
if (perf_evsel__match2(evsel, e))
@@ -461,9 +465,9 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
return NULL;
}
-static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
+static void perf_evlist__collapse_resort(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
struct hists *hists = evsel__hists(evsel);
@@ -1009,8 +1013,8 @@ static void data__fprintf(void)
static void data_process(void)
{
- struct perf_evlist *evlist_base = data__files[0].session->evlist;
- struct perf_evsel *evsel_base;
+ struct evlist *evlist_base = data__files[0].session->evlist;
+ struct evsel *evsel_base;
bool first = true;
evlist__for_each_entry(evlist_base, evsel_base) {
@@ -1019,8 +1023,8 @@ static void data_process(void)
int i;
data__for_each_file_new(i, d) {
- struct perf_evlist *evlist = d->session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = d->session->evlist;
+ struct evsel *evsel;
struct hists *hists;
evsel = evsel_match(evsel_base, evlist);
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 6e4f63b0da4a..238fa3876805 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -21,7 +21,7 @@
static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
{
struct perf_session *session;
- struct perf_evsel *pos;
+ struct evsel *pos;
struct perf_data data = {
.path = file_name,
.mode = PERF_DATA_MODE_READ,
@@ -36,7 +36,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
evlist__for_each_entry(session->evlist, pos) {
perf_evsel__fprintf(pos, details, stdout);
- if (pos->attr.type == PERF_TYPE_TRACEPOINT)
+ if (pos->core.attr.type == PERF_TYPE_TRACEPOINT)
has_tracepoint = true;
}
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 66d5a6658daf..d5adc417a4ca 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -6,28 +6,31 @@
*/
#include "builtin.h"
-#include "perf.h"
#include <errno.h>
#include <unistd.h>
#include <signal.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <poll.h>
+#include <linux/capability.h>
+#include <linux/string.h>
#include "debug.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include <api/fs/tracing_path.h>
#include "evlist.h"
#include "target.h"
#include "cpumap.h"
#include "thread_map.h"
+#include "util/cap.h"
#include "util/config.h"
-
#define DEFAULT_TRACER "function_graph"
struct perf_ftrace {
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct target target;
const char *tracer;
struct list_head filters;
@@ -156,16 +159,16 @@ static int set_tracing_pid(struct perf_ftrace *ftrace)
if (target__has_cpu(&ftrace->target))
return 0;
- for (i = 0; i < thread_map__nr(ftrace->evlist->threads); i++) {
+ for (i = 0; i < perf_thread_map__nr(ftrace->evlist->core.threads); i++) {
scnprintf(buf, sizeof(buf), "%d",
- ftrace->evlist->threads->map[i]);
+ ftrace->evlist->core.threads->map[i]);
if (append_tracing_file("set_ftrace_pid", buf) < 0)
return -1;
}
return 0;
}
-static int set_tracing_cpumask(struct cpu_map *cpumap)
+static int set_tracing_cpumask(struct perf_cpu_map *cpumap)
{
char *cpumask;
size_t mask_size;
@@ -173,7 +176,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap)
int last_cpu;
last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1);
- mask_size = (last_cpu + 3) / 4 + 1;
+ mask_size = last_cpu / 4 + 2; /* one more byte for EOS */
mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
cpumask = malloc(mask_size);
@@ -192,7 +195,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap)
static int set_tracing_cpu(struct perf_ftrace *ftrace)
{
- struct cpu_map *cpumap = ftrace->evlist->cpus;
+ struct perf_cpu_map *cpumap = ftrace->evlist->core.cpus;
if (!target__has_cpu(&ftrace->target))
return 0;
@@ -202,11 +205,11 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace)
static int reset_tracing_cpu(void)
{
- struct cpu_map *cpumap = cpu_map__new(NULL);
+ struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
int ret;
ret = set_tracing_cpumask(cpumap);
- cpu_map__put(cpumap);
+ perf_cpu_map__put(cpumap);
return ret;
}
@@ -281,8 +284,14 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
.events = POLLIN,
};
- if (geteuid() != 0) {
- pr_err("ftrace only works for root!\n");
+ if (!perf_cap__capable(CAP_SYS_ADMIN)) {
+ pr_err("ftrace only works for %s!\n",
+#ifdef HAVE_LIBCAP_SUPPORT
+ "users with the SYS_ADMIN capability"
+#else
+ "root"
+#endif
+ );
return -1;
}
@@ -495,7 +504,7 @@ int cmd_ftrace(int argc, const char **argv)
goto out_delete_filters;
}
- ftrace.evlist = perf_evlist__new();
+ ftrace.evlist = evlist__new();
if (ftrace.evlist == NULL) {
ret = -ENOMEM;
goto out_delete_filters;
@@ -508,7 +517,7 @@ int cmd_ftrace(int argc, const char **argv)
ret = __cmd_ftrace(&ftrace, argc, argv);
out_delete_evlist:
- perf_evlist__delete(ftrace.evlist);
+ evlist__delete(ftrace.evlist);
out_delete_filters:
delete_filter_func(&ftrace.filters);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index a83af92fb0d1..3976aebe3677 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -4,8 +4,9 @@
*
* Builtin help command
*/
-#include "perf.h"
+#include "util/cache.h"
#include "util/config.h"
+#include "util/strbuf.h"
#include "builtin.h"
#include <subcmd/exec-cmd.h>
#include "common-cmds.h"
@@ -14,10 +15,12 @@
#include <subcmd/help.h>
#include "util/debug.h"
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f4591a1438b4..c14f40b858bc 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -8,8 +8,8 @@
*/
#include "builtin.h"
-#include "perf.h"
#include "util/color.h"
+#include "util/dso.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/map.h"
@@ -96,7 +96,7 @@ static int perf_event__repipe_op2_synth(struct perf_session *session,
static int perf_event__repipe_attr(struct perf_tool *tool,
union perf_event *event,
- struct perf_evlist **pevlist)
+ struct evlist **pevlist)
{
struct perf_inject *inject = container_of(tool, struct perf_inject,
tool);
@@ -215,13 +215,13 @@ static int perf_event__drop_aux(struct perf_tool *tool,
typedef int (*inject_handler)(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine);
static int perf_event__repipe_sample(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
if (evsel && evsel->handler) {
@@ -424,7 +424,7 @@ static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
static int perf_event__inject_buildid(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine)
{
struct addr_location al;
@@ -465,7 +465,7 @@ repipe:
static int perf_inject__sched_process_exit(struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine __maybe_unused)
{
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
@@ -485,7 +485,7 @@ static int perf_inject__sched_process_exit(struct perf_tool *tool,
static int perf_inject__sched_switch(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
@@ -509,7 +509,7 @@ static int perf_inject__sched_switch(struct perf_tool *tool,
static int perf_inject__sched_stat(struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct event_entry *ent;
@@ -530,8 +530,8 @@ found:
sample_sw.period = sample->period;
sample_sw.time = sample->time;
- perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
- evsel->attr.read_format, &sample_sw);
+ perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type,
+ evsel->core.attr.read_format, &sample_sw);
build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
return perf_event__repipe(tool, event_sw, &sample_sw, machine);
}
@@ -541,10 +541,10 @@ static void sig_handler(int sig __maybe_unused)
session_done = 1;
}
-static int perf_evsel__check_stype(struct perf_evsel *evsel,
+static int perf_evsel__check_stype(struct evsel *evsel,
u64 sample_type, const char *sample_msg)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
const char *name = perf_evsel__name(evsel);
if (!(attr->sample_type & sample_type)) {
@@ -559,7 +559,7 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
static int drop_sample(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine __maybe_unused)
{
return 0;
@@ -567,8 +567,8 @@ static int drop_sample(struct perf_tool *tool __maybe_unused,
static void strip_init(struct perf_inject *inject)
{
- struct perf_evlist *evlist = inject->session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = inject->session->evlist;
+ struct evsel *evsel;
inject->tool.context_switch = perf_event__drop;
@@ -576,10 +576,10 @@ static void strip_init(struct perf_inject *inject)
evsel->handler = drop_sample;
}
-static bool has_tracking(struct perf_evsel *evsel)
+static bool has_tracking(struct evsel *evsel)
{
- return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm ||
- evsel->attr.task;
+ return evsel->core.attr.mmap || evsel->core.attr.mmap2 || evsel->core.attr.comm ||
+ evsel->core.attr.task;
}
#define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
@@ -590,10 +590,10 @@ static bool has_tracking(struct perf_evsel *evsel)
* their selected event to exist, except if there is only 1 selected event left
* and it has a compatible sample type.
*/
-static bool ok_to_remove(struct perf_evlist *evlist,
- struct perf_evsel *evsel_to_remove)
+static bool ok_to_remove(struct evlist *evlist,
+ struct evsel *evsel_to_remove)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int cnt = 0;
bool ok = false;
@@ -603,8 +603,8 @@ static bool ok_to_remove(struct perf_evlist *evlist,
evlist__for_each_entry(evlist, evsel) {
if (evsel->handler != drop_sample) {
cnt += 1;
- if ((evsel->attr.sample_type & COMPAT_MASK) ==
- (evsel_to_remove->attr.sample_type & COMPAT_MASK))
+ if ((evsel->core.attr.sample_type & COMPAT_MASK) ==
+ (evsel_to_remove->core.attr.sample_type & COMPAT_MASK))
ok = true;
}
}
@@ -614,16 +614,16 @@ static bool ok_to_remove(struct perf_evlist *evlist,
static void strip_fini(struct perf_inject *inject)
{
- struct perf_evlist *evlist = inject->session->evlist;
- struct perf_evsel *evsel, *tmp;
+ struct evlist *evlist = inject->session->evlist;
+ struct evsel *evsel, *tmp;
/* Remove non-synthesized evsels if possible */
evlist__for_each_entry_safe(evlist, tmp, evsel) {
if (evsel->handler == drop_sample &&
ok_to_remove(evlist, evsel)) {
pr_debug("Deleting %s\n", perf_evsel__name(evsel));
- perf_evlist__remove(evlist, evsel);
- perf_evsel__delete(evsel);
+ evlist__remove(evlist, evsel);
+ evsel__delete(evsel);
}
}
}
@@ -651,7 +651,7 @@ static int __cmd_inject(struct perf_inject *inject)
if (inject->build_ids) {
inject->tool.sample = perf_event__inject_buildid;
} else if (inject->sched_stat) {
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(session->evlist, evsel) {
const char *name = perf_evsel__name(evsel);
@@ -712,7 +712,7 @@ static int __cmd_inject(struct perf_inject *inject)
* remove the evsel.
*/
if (inject->itrace_synth_opts.set) {
- struct perf_evsel *evsel;
+ struct evsel *evsel;
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
@@ -724,8 +724,8 @@ static int __cmd_inject(struct perf_inject *inject)
if (evsel) {
pr_debug("Deleting %s\n",
perf_evsel__name(evsel));
- perf_evlist__remove(session->evlist, evsel);
- perf_evsel__delete(evsel);
+ evlist__remove(session->evlist, evsel);
+ evsel__delete(evsel);
}
if (inject->strip)
strip_fini(inject);
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
index c1a44671b0b5..c08ee81529e8 100644
--- a/tools/perf/builtin-kallsyms.c
+++ b/tools/perf/builtin-kallsyms.c
@@ -11,6 +11,7 @@
#include <linux/compiler.h>
#include <subcmd/parse-options.h>
#include "debug.h"
+#include "dso.h"
#include "machine.h"
#include "map.h"
#include "symbol.h"
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 9e5e60898083..b5682beaad72 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -2,6 +2,7 @@
#include "builtin.h"
#include "perf.h"
+#include "util/dso.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/config.h"
@@ -14,6 +15,7 @@
#include "util/callchain.h"
#include "util/time-utils.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
#include "util/data.h"
@@ -166,7 +168,7 @@ static int insert_caller_stat(unsigned long call_site,
return 0;
}
-static int perf_evsel__process_alloc_event(struct perf_evsel *evsel,
+static int perf_evsel__process_alloc_event(struct evsel *evsel,
struct perf_sample *sample)
{
unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"),
@@ -185,7 +187,7 @@ static int perf_evsel__process_alloc_event(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel,
+static int perf_evsel__process_alloc_node_event(struct evsel *evsel,
struct perf_sample *sample)
{
int ret = perf_evsel__process_alloc_event(evsel, sample);
@@ -229,7 +231,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
return NULL;
}
-static int perf_evsel__process_free_event(struct perf_evsel *evsel,
+static int perf_evsel__process_free_event(struct evsel *evsel,
struct perf_sample *sample)
{
unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr");
@@ -381,7 +383,7 @@ static int build_alloc_func_list(void)
* Find first non-memory allocation function from callchain.
* The allocation functions are in the 'alloc_func_list'.
*/
-static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
+static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
{
struct addr_location al;
struct machine *machine = &kmem_session->machines.host;
@@ -728,7 +730,7 @@ static char *compact_gfp_string(unsigned long gfp_flags)
return NULL;
}
-static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
+static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
unsigned int gfp_flags)
{
struct tep_record record = {
@@ -749,7 +751,8 @@ static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
}
trace_seq_init(&seq);
- tep_event_info(&seq, evsel->tp_format, &record);
+ tep_print_event(evsel->tp_format->tep,
+ &seq, &record, "%s", TEP_PRINT_INFO);
str = strtok_r(seq.buffer, " ", &pos);
while (str) {
@@ -779,7 +782,7 @@ static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
return 0;
}
-static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
+static int perf_evsel__process_page_alloc_event(struct evsel *evsel,
struct perf_sample *sample)
{
u64 page;
@@ -852,7 +855,7 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
+static int perf_evsel__process_page_free_event(struct evsel *evsel,
struct perf_sample *sample)
{
u64 page;
@@ -930,13 +933,13 @@ static bool perf_kmem__skip_sample(struct perf_sample *sample)
return false;
}
-typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
+typedef int (*tracepoint_handler)(struct evsel *evsel,
struct perf_sample *sample);
static int process_sample_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
int err = 0;
@@ -1363,8 +1366,8 @@ static void sort_result(void)
static int __cmd_kmem(struct perf_session *session)
{
int err = -EINVAL;
- struct perf_evsel *evsel;
- const struct perf_evsel_str_handler kmem_tracepoints[] = {
+ struct evsel *evsel;
+ const struct evsel_str_handler kmem_tracepoints[] = {
/* slab allocator */
{ "kmem:kmalloc", perf_evsel__process_alloc_event, },
{ "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
@@ -1967,7 +1970,7 @@ int cmd_kmem(int argc, const char **argv)
}
if (kmem_page) {
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"kmem:mm_page_alloc");
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b33c83489120..0a4fcbe32bf6 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -2,15 +2,16 @@
#include "builtin.h"
#include "perf.h"
+#include "util/build-id.h"
#include "util/evsel.h"
#include "util/evlist.h"
#include "util/term.h"
-#include "util/cache.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/header.h"
#include "util/session.h"
#include "util/intlist.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
#include "util/debug.h"
@@ -19,6 +20,7 @@
#include "util/top.h"
#include "util/data.h"
#include "util/ordered-events.h"
+#include "ui/ui.h"
#include <sys/prctl.h>
#ifdef HAVE_TIMERFD_SUPPORT
@@ -30,6 +32,7 @@
#include <fcntl.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
#include <errno.h>
@@ -57,7 +60,7 @@ static const char *get_filename_for_perf_kvm(void)
#ifdef HAVE_KVM_STAT_SUPPORT
#include "util/kvm-stat.h"
-void exit_event_get_key(struct perf_evsel *evsel,
+void exit_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -65,12 +68,12 @@ void exit_event_get_key(struct perf_evsel *evsel,
key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason);
}
-bool kvm_exit_event(struct perf_evsel *evsel)
+bool kvm_exit_event(struct evsel *evsel)
{
return !strcmp(evsel->name, kvm_exit_trace);
}
-bool exit_event_begin(struct perf_evsel *evsel,
+bool exit_event_begin(struct evsel *evsel,
struct perf_sample *sample, struct event_key *key)
{
if (kvm_exit_event(evsel)) {
@@ -81,12 +84,12 @@ bool exit_event_begin(struct perf_evsel *evsel,
return false;
}
-bool kvm_entry_event(struct perf_evsel *evsel)
+bool kvm_entry_event(struct evsel *evsel)
{
return !strcmp(evsel->name, kvm_entry_trace);
}
-bool exit_event_end(struct perf_evsel *evsel,
+bool exit_event_end(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
@@ -286,7 +289,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
}
static bool is_child_event(struct perf_kvm_stat *kvm,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@@ -396,7 +399,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
static
struct vcpu_event_record *per_vcpu_record(struct thread *thread,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
/* Only kvm_entry records vcpu id. */
@@ -419,7 +422,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
static bool handle_kvm_event(struct perf_kvm_stat *kvm,
struct thread *thread,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
struct vcpu_event_record *vcpu_record;
@@ -672,7 +675,7 @@ static bool skip_sample(struct perf_kvm_stat *kvm,
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
int err = 0;
@@ -743,7 +746,7 @@ static bool verify_vcpu(int vcpu)
static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
u64 *mmap_time)
{
- struct perf_evlist *evlist = kvm->evlist;
+ struct evlist *evlist = kvm->evlist;
union perf_event *event;
struct perf_mmap *md;
u64 timestamp;
@@ -972,7 +975,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
goto out;
/* everything is good - enable the events and process */
- perf_evlist__enable(kvm->evlist);
+ evlist__enable(kvm->evlist);
while (!done) {
struct fdarray *fda = &kvm->evlist->pollfd;
@@ -993,7 +996,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
err = fdarray__poll(fda, 100);
}
- perf_evlist__disable(kvm->evlist);
+ evlist__disable(kvm->evlist);
if (err == 0) {
sort_result(kvm);
@@ -1011,8 +1014,8 @@ out:
static int kvm_live_open_events(struct perf_kvm_stat *kvm)
{
int err, rc = -1;
- struct perf_evsel *pos;
- struct perf_evlist *evlist = kvm->evlist;
+ struct evsel *pos;
+ struct evlist *evlist = kvm->evlist;
char sbuf[STRERR_BUFSIZE];
perf_evlist__config(evlist, &kvm->opts, NULL);
@@ -1022,7 +1025,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
* This command processes KVM tracepoints from host only
*/
evlist__for_each_entry(evlist, pos) {
- struct perf_event_attr *attr = &pos->attr;
+ struct perf_event_attr *attr = &pos->core.attr;
/* make sure these *are* set */
perf_evsel__set_sample_bit(pos, TID);
@@ -1048,7 +1051,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
attr->disabled = 1;
}
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
printf("Couldn't create the events: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -1058,7 +1061,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
ui__error("Failed to mmap the events: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
- perf_evlist__close(evlist);
+ evlist__close(evlist);
goto out;
}
@@ -1283,14 +1286,14 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
}
#ifdef HAVE_TIMERFD_SUPPORT
-static struct perf_evlist *kvm_live_event_list(void)
+static struct evlist *kvm_live_event_list(void)
{
- struct perf_evlist *evlist;
+ struct evlist *evlist;
char *tp, *name, *sys;
int err = -1;
const char * const *events_tp;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (evlist == NULL)
return NULL;
@@ -1325,7 +1328,7 @@ static struct perf_evlist *kvm_live_event_list(void)
out:
if (err) {
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
evlist = NULL;
}
@@ -1450,7 +1453,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
perf_session__set_id_hdr_size(kvm->session);
ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
- kvm->evlist->threads, false, 1);
+ kvm->evlist->core.threads, false, 1);
err = kvm_live_open_events(kvm);
if (err)
goto out;
@@ -1460,7 +1463,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
out:
perf_session__delete(kvm->session);
kvm->session = NULL;
- perf_evlist__delete(kvm->evlist);
+ evlist__delete(kvm->evlist);
return err;
}
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index e0312a1c4792..e290f6b348d8 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -10,14 +10,13 @@
*/
#include "builtin.h"
-#include "perf.h"
-
#include "util/parse-events.h"
-#include "util/cache.h"
#include "util/pmu.h"
#include "util/debug.h"
#include "util/metricgroup.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
+#include <stdio.h>
static bool desc_flag = true;
static bool details_flag;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 574e30ec6d7c..4c2b7f437cdf 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -4,13 +4,13 @@
#include "builtin.h"
#include "perf.h"
-#include "util/evlist.h"
+#include "util/evlist.h" // for struct evsel_str_handler
#include "util/evsel.h"
-#include "util/cache.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/header.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
@@ -347,16 +347,16 @@ alloc_failed:
}
struct trace_lock_handler {
- int (*acquire_event)(struct perf_evsel *evsel,
+ int (*acquire_event)(struct evsel *evsel,
struct perf_sample *sample);
- int (*acquired_event)(struct perf_evsel *evsel,
+ int (*acquired_event)(struct evsel *evsel,
struct perf_sample *sample);
- int (*contended_event)(struct perf_evsel *evsel,
+ int (*contended_event)(struct evsel *evsel,
struct perf_sample *sample);
- int (*release_event)(struct perf_evsel *evsel,
+ int (*release_event)(struct evsel *evsel,
struct perf_sample *sample);
};
@@ -396,7 +396,7 @@ enum acquire_flags {
READ_LOCK = 2,
};
-static int report_lock_acquire_event(struct perf_evsel *evsel,
+static int report_lock_acquire_event(struct evsel *evsel,
struct perf_sample *sample)
{
void *addr;
@@ -468,7 +468,7 @@ end:
return 0;
}
-static int report_lock_acquired_event(struct perf_evsel *evsel,
+static int report_lock_acquired_event(struct evsel *evsel,
struct perf_sample *sample)
{
void *addr;
@@ -531,7 +531,7 @@ end:
return 0;
}
-static int report_lock_contended_event(struct perf_evsel *evsel,
+static int report_lock_contended_event(struct evsel *evsel,
struct perf_sample *sample)
{
void *addr;
@@ -586,7 +586,7 @@ end:
return 0;
}
-static int report_lock_release_event(struct perf_evsel *evsel,
+static int report_lock_release_event(struct evsel *evsel,
struct perf_sample *sample)
{
void *addr;
@@ -656,7 +656,7 @@ static struct trace_lock_handler report_lock_ops = {
static struct trace_lock_handler *trace_handler;
-static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel,
+static int perf_evsel__process_lock_acquire(struct evsel *evsel,
struct perf_sample *sample)
{
if (trace_handler->acquire_event)
@@ -664,7 +664,7 @@ static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel,
+static int perf_evsel__process_lock_acquired(struct evsel *evsel,
struct perf_sample *sample)
{
if (trace_handler->acquired_event)
@@ -672,7 +672,7 @@ static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__process_lock_contended(struct perf_evsel *evsel,
+static int perf_evsel__process_lock_contended(struct evsel *evsel,
struct perf_sample *sample)
{
if (trace_handler->contended_event)
@@ -680,7 +680,7 @@ static int perf_evsel__process_lock_contended(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__process_lock_release(struct perf_evsel *evsel,
+static int perf_evsel__process_lock_release(struct evsel *evsel,
struct perf_sample *sample)
{
if (trace_handler->release_event)
@@ -806,13 +806,13 @@ static int dump_info(void)
return rc;
}
-typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
+typedef int (*tracepoint_handler)(struct evsel *evsel,
struct perf_sample *sample);
static int process_sample_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
int err = 0;
@@ -847,7 +847,7 @@ static void sort_result(void)
}
}
-static const struct perf_evsel_str_handler lock_tracepoints[] = {
+static const struct evsel_str_handler lock_tracepoints[] = {
{ "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
{ "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
{ "lock:lock_contended", perf_evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index f45c8b502f63..27d2bde943a8 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -11,8 +11,10 @@
#include "util/tool.h"
#include "util/session.h"
#include "util/data.h"
+#include "util/map_symbol.h"
#include "util/mem-events.h"
#include "util/debug.h"
+#include "util/dso.h"
#include "util/map.h"
#include "util/symbol.h"
@@ -230,7 +232,7 @@ out_put:
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine)
{
return dump_raw_samples(tool, event, sample, machine);
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 6418782951a4..26bc5923e6b5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -16,17 +16,18 @@
#include <stdlib.h>
#include <string.h>
-#include "perf.h"
#include "builtin.h"
#include "namespaces.h"
+#include "util/build-id.h"
#include "util/strlist.h"
#include "util/strfilter.h"
-#include "util/symbol.h"
+#include "util/symbol_conf.h"
#include "util/debug.h"
#include <subcmd/parse-options.h>
#include "util/probe-finder.h"
#include "util/probe-event.h"
#include "util/probe-file.h"
+#include <linux/string.h>
#include <linux/zalloc.h>
#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
@@ -698,6 +699,16 @@ __cmd_probe(int argc, const char **argv)
ret = perf_add_probe_events(params.events, params.nevents);
if (ret < 0) {
+
+ /*
+ * When perf_add_probe_events() fails it calls
+ * cleanup_perf_probe_events(pevs, npevs), i.e.
+ * cleanup_perf_probe_events(params.events, params.nevents), which
+ * will call clear_perf_probe_event(), so set nevents to zero
+ * to avoid cleanup_params() to call clear_perf_probe_event() again
+ * on the same pevs.
+ */
+ params.nevents = 0;
pr_err_with_code(" Error: Failed to add events.", ret);
return ret;
}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8779cee58185..1447004eee8a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -8,8 +8,6 @@
*/
#include "builtin.h"
-#include "perf.h"
-
#include "util/build-id.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
@@ -22,9 +20,11 @@
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/debug.h"
+#include "util/target.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/symbol.h"
+#include "util/record.h"
#include "util/cpumap.h"
#include "util/thread_map.h"
#include "util/data.h"
@@ -42,6 +42,7 @@
#include "util/units.h"
#include "util/bpf-event.h"
#include "asm/bug.h"
+#include "perf.h"
#include <errno.h>
#include <inttypes.h>
@@ -52,6 +53,7 @@
#include <signal.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <linux/string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
@@ -73,7 +75,7 @@ struct record {
u64 bytes_written;
struct perf_data data;
struct auxtrace_record *itr;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct perf_session *session;
int realtime_prio;
bool no_buildid;
@@ -346,7 +348,7 @@ static void record__aio_set_pos(int trace_fd, off_t pos)
static void record__aio_mmap_read_sync(struct record *rec)
{
int i;
- struct perf_evlist *evlist = rec->evlist;
+ struct evlist *evlist = rec->evlist;
struct perf_mmap *maps = evlist->mmap;
if (!record__aio_enabled(rec))
@@ -613,19 +615,35 @@ out:
return rc;
}
-static void record__read_auxtrace_snapshot(struct record *rec)
+static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
{
pr_debug("Recording AUX area tracing snapshot\n");
if (record__auxtrace_read_snapshot_all(rec) < 0) {
trigger_error(&auxtrace_snapshot_trigger);
} else {
- if (auxtrace_record__snapshot_finish(rec->itr))
+ if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
trigger_error(&auxtrace_snapshot_trigger);
else
trigger_ready(&auxtrace_snapshot_trigger);
}
}
+static int record__auxtrace_snapshot_exit(struct record *rec)
+{
+ if (trigger_is_error(&auxtrace_snapshot_trigger))
+ return 0;
+
+ if (!auxtrace_record__snapshot_started &&
+ auxtrace_record__snapshot_start(rec->itr))
+ return -1;
+
+ record__read_auxtrace_snapshot(rec, true);
+ if (trigger_is_error(&auxtrace_snapshot_trigger))
+ return -1;
+
+ return 0;
+}
+
static int record__auxtrace_init(struct record *rec)
{
int err;
@@ -654,7 +672,8 @@ int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
}
static inline
-void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
+void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
+ bool on_exit __maybe_unused)
{
}
@@ -664,6 +683,12 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
return 0;
}
+static inline
+int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
+{
+ return 0;
+}
+
static int record__auxtrace_init(struct record *rec __maybe_unused)
{
return 0;
@@ -672,7 +697,7 @@ static int record__auxtrace_init(struct record *rec __maybe_unused)
#endif
static int record__mmap_evlist(struct record *rec,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
struct record_opts *opts = &rec->opts;
char msg[512];
@@ -713,8 +738,8 @@ static int record__mmap(struct record *rec)
static int record__open(struct record *rec)
{
char msg[BUFSIZ];
- struct perf_evsel *pos;
- struct perf_evlist *evlist = rec->evlist;
+ struct evsel *pos;
+ struct evlist *evlist = rec->evlist;
struct perf_session *session = rec->session;
struct record_opts *opts = &rec->opts;
int rc = 0;
@@ -732,14 +757,14 @@ static int record__open(struct record *rec)
pos->tracking = 0;
pos = perf_evlist__last(evlist);
pos->tracking = 1;
- pos->attr.enable_on_exec = 1;
+ pos->core.attr.enable_on_exec = 1;
}
perf_evlist__config(evlist, opts, &callchain_param);
evlist__for_each_entry(evlist, pos) {
try_again:
- if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
+ if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
if (verbose > 0)
ui__warning("%s\n", msg);
@@ -782,7 +807,7 @@ out:
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct record *rec = container_of(tool, struct record, tool);
@@ -875,7 +900,7 @@ static void record__adjust_affinity(struct record *rec, struct perf_mmap *map)
static size_t process_comp_header(void *record, size_t increment)
{
- struct compressed_event *event = record;
+ struct perf_record_compressed *event = record;
size_t size = sizeof(*event);
if (increment) {
@@ -893,7 +918,7 @@ static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_
void *src, size_t src_size)
{
size_t compressed;
- size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct compressed_event) - 1;
+ size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1;
compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size,
max_record_size, process_comp_header);
@@ -904,7 +929,7 @@ static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_
return compressed;
}
-static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
+static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
bool overwrite, bool synch)
{
u64 bytes_written = rec->bytes_written;
@@ -1002,7 +1027,7 @@ static void record__init_features(struct record *rec)
if (rec->no_buildid)
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
- if (!have_tracepoints(&rec->evlist->entries))
+ if (!have_tracepoints(&rec->evlist->core.entries))
perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
if (!rec->opts.branch_stack)
@@ -1047,7 +1072,7 @@ record__finish_output(struct record *rec)
static int record__synthesize_workload(struct record *rec, bool tail)
{
int err;
- struct thread_map *thread_map;
+ struct perf_thread_map *thread_map;
if (rec->opts.tail_synthesize != tail)
return 0;
@@ -1060,7 +1085,7 @@ static int record__synthesize_workload(struct record *rec, bool tail)
process_synthesized_event,
&rec->session->machines.host,
rec->opts.sample_address);
- thread_map__put(thread_map);
+ perf_thread_map__put(thread_map);
return err;
}
@@ -1165,7 +1190,7 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused
}
static const struct perf_event_mmap_page *
-perf_evlist__pick_pc(struct perf_evlist *evlist)
+perf_evlist__pick_pc(struct evlist *evlist)
{
if (evlist) {
if (evlist->mmap && evlist->mmap[0].base)
@@ -1218,7 +1243,7 @@ static int record__synthesize(struct record *rec, bool tail)
return err;
}
- if (have_tracepoints(&rec->evlist->entries)) {
+ if (have_tracepoints(&rec->evlist->core.entries)) {
/*
* FIXME err <= 0 here actually means that
* there were no tracepoints so its not really
@@ -1275,7 +1300,7 @@ static int record__synthesize(struct record *rec, bool tail)
if (err)
goto out;
- err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads,
+ err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads,
process_synthesized_event,
NULL);
if (err < 0) {
@@ -1283,7 +1308,7 @@ static int record__synthesize(struct record *rec, bool tail)
return err;
}
- err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus,
+ err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus,
process_synthesized_event, NULL);
if (err < 0) {
pr_err("Couldn't synthesize cpu map.\n");
@@ -1295,7 +1320,7 @@ static int record__synthesize(struct record *rec, bool tail)
if (err < 0)
pr_warning("Couldn't synthesize bpf events.\n");
- err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
+ err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads,
process_synthesized_event, opts->sample_address,
1);
out:
@@ -1313,7 +1338,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
struct perf_data *data = &rec->data;
struct perf_session *session;
bool disabled = false, draining = false;
- struct perf_evlist *sb_evlist = NULL;
+ struct evlist *sb_evlist = NULL;
int fd;
float ratio = 0;
@@ -1375,7 +1400,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
* because we synthesize event name through the pipe
* and need the id for that.
*/
- if (data->is_pipe && rec->evlist->nr_entries == 1)
+ if (data->is_pipe && rec->evlist->core.nr_entries == 1)
rec->opts.sample_id = true;
if (record__open(rec) != 0) {
@@ -1453,7 +1478,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
* so don't spoil it by prematurely enabling them.
*/
if (!target__none(&opts->target) && !opts->initial_delay)
- perf_evlist__enable(rec->evlist);
+ evlist__enable(rec->evlist);
/*
* Let the child rip
@@ -1506,7 +1531,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
if (opts->initial_delay) {
usleep(opts->initial_delay * USEC_PER_MSEC);
- perf_evlist__enable(rec->evlist);
+ evlist__enable(rec->evlist);
}
trigger_ready(&auxtrace_snapshot_trigger);
@@ -1536,7 +1561,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
if (auxtrace_record__snapshot_started) {
auxtrace_record__snapshot_started = 0;
if (!trigger_is_error(&auxtrace_snapshot_trigger))
- record__read_auxtrace_snapshot(rec);
+ record__read_auxtrace_snapshot(rec, false);
if (trigger_is_error(&auxtrace_snapshot_trigger)) {
pr_err("AUX area tracing snapshot failed\n");
err = -1;
@@ -1605,13 +1630,17 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
*/
if (done && !disabled && !target__none(&opts->target)) {
trigger_off(&auxtrace_snapshot_trigger);
- perf_evlist__disable(rec->evlist);
+ evlist__disable(rec->evlist);
disabled = true;
}
}
+
trigger_off(&auxtrace_snapshot_trigger);
trigger_off(&switch_output_trigger);
+ if (opts->auxtrace_snapshot_on_exit)
+ record__auxtrace_snapshot_exit(rec);
+
if (forks && workload_exec_errno) {
char msg[STRERR_BUFSIZE];
const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -2265,7 +2294,7 @@ int cmd_record(int argc, const char **argv)
CPU_ZERO(&rec->affinity_mask);
rec->opts.affinity = PERF_AFFINITY_SYS;
- rec->evlist = perf_evlist__new();
+ rec->evlist = evlist__new();
if (rec->evlist == NULL)
return -ENOMEM;
@@ -2345,7 +2374,7 @@ int cmd_record(int argc, const char **argv)
if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist))
pr_warning(
"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
-"check /proc/sys/kernel/kptr_restrict.\n\n"
+"check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
"file is not found in the buildid cache or in the vmlinux path.\n\n"
"Samples in kernel modules won't be resolved at all.\n\n"
@@ -2386,7 +2415,7 @@ int cmd_record(int argc, const char **argv)
if (record.opts.overwrite)
record.opts.tail_synthesize = true;
- if (rec->evlist->nr_entries == 0 &&
+ if (rec->evlist->core.nr_entries == 0 &&
__perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
pr_err("Not enough memory for event selector list\n");
goto out;
@@ -2449,7 +2478,7 @@ int cmd_record(int argc, const char **argv)
err = __cmd_record(&record, argc, argv);
out:
- perf_evlist__delete(rec->evlist);
+ evlist__delete(rec->evlist);
symbol__exit();
auxtrace_record__free(rec->itr);
return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index abf0b9b8f566..b18fab94d38d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -12,12 +12,16 @@
#include "util/annotate.h"
#include "util/color.h"
+#include "util/dso.h"
#include <linux/list.h>
#include <linux/rbtree.h>
#include <linux/err.h>
#include <linux/zalloc.h>
#include "util/map.h"
#include "util/symbol.h"
+#include "util/map_symbol.h"
+#include "util/mem-events.h"
+#include "util/branch.h"
#include "util/callchain.h"
#include "util/values.h"
@@ -25,8 +29,10 @@
#include "util/debug.h"
#include "util/evlist.h"
#include "util/evsel.h"
+#include "util/evswitch.h"
#include "util/header.h"
#include "util/session.h"
+#include "util/srcline.h"
#include "util/tool.h"
#include <subcmd/parse-options.h>
@@ -42,6 +48,9 @@
#include "util/auxtrace.h"
#include "util/units.h"
#include "util/branch.h"
+#include "util/util.h"
+#include "ui/ui.h"
+#include "ui/progress.h"
#include <dlfcn.h>
#include <errno.h>
@@ -50,6 +59,7 @@
#include <linux/ctype.h>
#include <signal.h>
#include <linux/bitmap.h>
+#include <linux/string.h>
#include <linux/stringify.h>
#include <linux/time64.h>
#include <sys/types.h>
@@ -60,6 +70,7 @@
struct report {
struct perf_tool tool;
struct perf_session *session;
+ struct evswitch evswitch;
bool use_tui, use_gtk, use_stdio;
bool show_full_info;
bool show_threads;
@@ -128,7 +139,7 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
int err = 0;
struct report *rep = arg;
struct hist_entry *he = iter->he;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct perf_sample *sample = iter->sample;
struct mem_info *mi;
struct branch_info *bi;
@@ -172,7 +183,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
struct report *rep = arg;
struct branch_info *bi;
struct perf_sample *sample = iter->sample;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
int err;
if (!ui__has_annotation() && !rep->symbol_ipc)
@@ -193,7 +204,7 @@ out:
}
static void setup_forced_leader(struct report *report,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
if (report->group_set)
perf_evlist__force_leader(evlist);
@@ -208,7 +219,7 @@ static int process_feature_event(struct perf_session *session,
return perf_event__process_feature(session, event);
if (event->feat.feat_id != HEADER_LAST_FEATURE) {
- pr_err("failed: wrong feature ID: %" PRIu64 "\n",
+ pr_err("failed: wrong feature ID: %" PRI_lu64 "\n",
event->feat.feat_id);
return -1;
}
@@ -225,7 +236,7 @@ static int process_feature_event(struct perf_session *session,
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct report *rep = container_of(tool, struct report, tool);
@@ -243,6 +254,9 @@ static int process_sample_event(struct perf_tool *tool,
return 0;
}
+ if (evswitch__discard(&rep->evswitch, evsel))
+ return 0;
+
if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
@@ -292,7 +306,7 @@ out_put:
static int process_read_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine __maybe_unused)
{
struct report *rep = container_of(tool, struct report, tool);
@@ -400,7 +414,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
char unit;
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
u64 nr_events = hists->stats.total_period;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
char buf[512];
size_t size = sizeof(buf);
int socked_id = hists->socket_filter;
@@ -414,7 +428,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
}
if (perf_evsel__is_group_event(evsel)) {
- struct perf_evsel *pos;
+ struct evsel *pos;
perf_evsel__group_desc(evsel, buf, size);
evname = buf;
@@ -436,7 +450,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
if (evname != NULL) {
ret += fprintf(fp, " of event%s '%s'",
- evsel->nr_members > 1 ? "s" : "", evname);
+ evsel->core.nr_members > 1 ? "s" : "", evname);
}
if (rep->time_str)
@@ -459,11 +473,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
return ret + fprintf(fp, "\n#\n");
}
-static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
+static int perf_evlist__tty_browse_hists(struct evlist *evlist,
struct report *rep,
const char *help)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
if (!quiet) {
fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n",
@@ -532,7 +546,7 @@ static void report__warn_kptr_restrict(const struct report *rep)
static int report__gtk_browse_hists(struct report *rep, const char *help)
{
- int (*hist_browser)(struct perf_evlist *evlist, const char *help,
+ int (*hist_browser)(struct evlist *evlist, const char *help,
struct hist_browser_timer *timer, float min_pcnt);
hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
@@ -549,7 +563,7 @@ static int report__browse_hists(struct report *rep)
{
int ret;
struct perf_session *session = rep->session;
- struct perf_evlist *evlist = session->evlist;
+ struct evlist *evlist = session->evlist;
const char *help = perf_tip(system_path(TIPDIR));
if (help == NULL) {
@@ -586,7 +600,7 @@ static int report__browse_hists(struct report *rep)
static int report__collapse_hists(struct report *rep)
{
struct ui_progress prog;
- struct perf_evsel *pos;
+ struct evsel *pos;
int ret = 0;
ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
@@ -623,7 +637,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
struct symbol *sym = he->ms.sym;
if (rep->symbol_ipc && sym && !sym->annotate2) {
- struct perf_evsel *evsel = hists_to_evsel(he->hists);
+ struct evsel *evsel = hists_to_evsel(he->hists);
symbol__annotate2(sym, he->ms.map, evsel,
&annotation__default_options, NULL);
@@ -635,7 +649,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
static void report__output_resort(struct report *rep)
{
struct ui_progress prog;
- struct perf_evsel *pos;
+ struct evsel *pos;
ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
@@ -818,7 +832,7 @@ static int __cmd_report(struct report *rep)
{
int ret;
struct perf_session *session = rep->session;
- struct perf_evsel *pos;
+ struct evsel *pos;
struct perf_data *data = session->data;
signal(SIGINT, sig_handler);
@@ -1189,6 +1203,7 @@ int cmd_report(int argc, const char **argv)
OPT_CALLBACK(0, "time-quantum", &symbol_conf.time_quantum, "time (ms|us|ns|s)",
"Set time quantum for time sort key (default 100ms)",
parse_time_quantum),
+ OPTS_EVSWITCH(&report.evswitch),
OPT_END()
};
struct perf_data data = {
@@ -1257,6 +1272,10 @@ repeat:
if (session == NULL)
return -1;
+ ret = evswitch__init(&report.evswitch, session->evlist, stderr);
+ if (ret)
+ return ret;
+
if (zstd_init(&(session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
@@ -1271,6 +1290,8 @@ repeat:
has_br_stack = perf_header__has_feat(&session->header,
HEADER_BRANCH_STACK);
+ if (perf_evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER)
+ has_br_stack = false;
setup_forced_leader(&report, session->evlist);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 56d1907b1215..ec96d64aec69 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include "builtin.h"
#include "perf.h"
+#include "perf-sys.h"
#include "util/evlist.h"
-#include "util/cache.h"
#include "util/evsel.h"
#include "util/symbol.h"
#include "util/thread.h"
@@ -18,6 +18,7 @@
#include "util/callchain.h"
#include "util/time-utils.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
@@ -133,13 +134,13 @@ typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *);
struct perf_sched;
struct trace_sched_handler {
- int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel,
+ int (*switch_event)(struct perf_sched *sched, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
- int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel,
+ int (*runtime_event)(struct perf_sched *sched, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
- int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel,
+ int (*wakeup_event)(struct perf_sched *sched, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
/* PERF_RECORD_FORK event, not sched_process_fork tracepoint */
@@ -147,7 +148,7 @@ struct trace_sched_handler {
struct machine *machine);
int (*migrate_task_event)(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
};
@@ -159,11 +160,11 @@ struct perf_sched_map {
DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS);
int *comp_cpus;
bool comp;
- struct thread_map *color_pids;
+ struct perf_thread_map *color_pids;
const char *color_pids_str;
- struct cpu_map *color_cpus;
+ struct perf_cpu_map *color_cpus;
const char *color_cpus_str;
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
const char *cpus_str;
};
@@ -799,7 +800,7 @@ static void test_calibrations(struct perf_sched *sched)
static int
replay_wakeup_event(struct perf_sched *sched,
- struct perf_evsel *evsel, struct perf_sample *sample,
+ struct evsel *evsel, struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
const char *comm = perf_evsel__strval(evsel, sample, "comm");
@@ -820,7 +821,7 @@ replay_wakeup_event(struct perf_sched *sched,
}
static int replay_switch_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
@@ -1093,7 +1094,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
}
static int latency_switch_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1163,7 +1164,7 @@ out_put:
}
static int latency_runtime_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1198,7 +1199,7 @@ out_put:
}
static int latency_wakeup_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1259,7 +1260,7 @@ out_put:
}
static int latency_migrate_task_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1470,7 +1471,7 @@ again:
}
static int process_sched_wakeup_event(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1514,7 +1515,7 @@ map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid
return thread;
}
-static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
+static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine)
{
const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
@@ -1655,7 +1656,7 @@ out:
}
static int process_sched_switch_event(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1681,7 +1682,7 @@ static int process_sched_switch_event(struct perf_tool *tool,
}
static int process_sched_runtime_event(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1711,7 +1712,7 @@ static int perf_sched__process_fork_event(struct perf_tool *tool,
}
static int process_sched_migrate_task_event(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -1724,14 +1725,14 @@ static int process_sched_migrate_task_event(struct perf_tool *tool,
}
typedef int (*tracepoint_handler)(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
int err = 0;
@@ -1777,7 +1778,7 @@ static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused,
static int perf_sched__read_events(struct perf_sched *sched)
{
- const struct perf_evsel_str_handler handlers[] = {
+ const struct evsel_str_handler handlers[] = {
{ "sched:sched_switch", process_sched_switch_event, },
{ "sched:sched_stat_runtime", process_sched_runtime_event, },
{ "sched:sched_wakeup", process_sched_wakeup_event, },
@@ -1839,7 +1840,7 @@ static inline void print_sched_time(unsigned long long nsecs, int width)
* returns runtime data for event, allocating memory for it the
* first time it is used.
*/
-static struct evsel_runtime *perf_evsel__get_runtime(struct perf_evsel *evsel)
+static struct evsel_runtime *perf_evsel__get_runtime(struct evsel *evsel)
{
struct evsel_runtime *r = evsel->priv;
@@ -1854,7 +1855,7 @@ static struct evsel_runtime *perf_evsel__get_runtime(struct perf_evsel *evsel)
/*
* save last time event was seen per cpu
*/
-static void perf_evsel__save_time(struct perf_evsel *evsel,
+static void perf_evsel__save_time(struct evsel *evsel,
u64 timestamp, u32 cpu)
{
struct evsel_runtime *r = perf_evsel__get_runtime(evsel);
@@ -1881,7 +1882,7 @@ static void perf_evsel__save_time(struct perf_evsel *evsel,
}
/* returns last time this event was seen on the given cpu */
-static u64 perf_evsel__get_time(struct perf_evsel *evsel, u32 cpu)
+static u64 perf_evsel__get_time(struct evsel *evsel, u32 cpu)
{
struct evsel_runtime *r = perf_evsel__get_runtime(evsel);
@@ -1988,7 +1989,7 @@ static char task_state_char(struct thread *thread, int state)
}
static void timehist_print_sample(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct addr_location *al,
struct thread *thread,
@@ -2121,7 +2122,7 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
}
static bool is_idle_sample(struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
/* pid 0 == swapper == idle task */
if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0)
@@ -2132,7 +2133,7 @@ static bool is_idle_sample(struct perf_sample *sample,
static void save_task_callchain(struct perf_sched *sched,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct callchain_cursor *cursor = &callchain_cursor;
@@ -2286,7 +2287,7 @@ static void save_idle_callchain(struct perf_sched *sched,
static struct thread *timehist_get_thread(struct perf_sched *sched,
struct perf_sample *sample,
struct machine *machine,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
struct thread *thread;
@@ -2332,7 +2333,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
static bool timehist_skip_sample(struct perf_sched *sched,
struct thread *thread,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
bool rc = false;
@@ -2354,7 +2355,7 @@ static bool timehist_skip_sample(struct perf_sched *sched,
}
static void timehist_print_wakeup_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine,
struct thread *awakened)
@@ -2389,7 +2390,7 @@ static void timehist_print_wakeup_event(struct perf_sched *sched,
static int timehist_sched_wakeup_event(struct perf_tool *tool,
union perf_event *event __maybe_unused,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -2419,7 +2420,7 @@ static int timehist_sched_wakeup_event(struct perf_tool *tool,
}
static void timehist_print_migration_event(struct perf_sched *sched,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine,
struct thread *migrated)
@@ -2473,7 +2474,7 @@ static void timehist_print_migration_event(struct perf_sched *sched,
static int timehist_migrate_task_event(struct perf_tool *tool,
union perf_event *event __maybe_unused,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -2501,7 +2502,7 @@ static int timehist_migrate_task_event(struct perf_tool *tool,
static int timehist_sched_change_event(struct perf_tool *tool,
union perf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -2627,7 +2628,7 @@ out:
static int timehist_sched_switch_event(struct perf_tool *tool,
union perf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
@@ -2643,7 +2644,7 @@ static int process_lost(struct perf_tool *tool __maybe_unused,
timestamp__scnprintf_usec(sample->time, tstr, sizeof(tstr));
printf("%15s ", tstr);
- printf("lost %" PRIu64 " events on cpu %d\n", event->lost.lost, sample->cpu);
+ printf("lost %" PRI_lu64 " events on cpu %d\n", event->lost.lost, sample->cpu);
return 0;
}
@@ -2897,14 +2898,14 @@ static void timehist_print_summary(struct perf_sched *sched,
typedef int (*sched_handler)(struct perf_tool *tool,
union perf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
static int perf_timehist__process_sample(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
@@ -2924,12 +2925,12 @@ static int perf_timehist__process_sample(struct perf_tool *tool,
}
static int timehist_check_attr(struct perf_sched *sched,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct evsel_runtime *er;
- list_for_each_entry(evsel, &evlist->entries, node) {
+ list_for_each_entry(evsel, &evlist->core.entries, core.node) {
er = perf_evsel__get_runtime(evsel);
if (er == NULL) {
pr_err("Failed to allocate memory for evsel runtime data\n");
@@ -2948,12 +2949,12 @@ static int timehist_check_attr(struct perf_sched *sched,
static int perf_sched__timehist(struct perf_sched *sched)
{
- const struct perf_evsel_str_handler handlers[] = {
+ const struct evsel_str_handler handlers[] = {
{ "sched:sched_switch", timehist_sched_switch_event, },
{ "sched:sched_wakeup", timehist_sched_wakeup_event, },
{ "sched:sched_wakeup_new", timehist_sched_wakeup_event, },
};
- const struct perf_evsel_str_handler migrate_handlers[] = {
+ const struct evsel_str_handler migrate_handlers[] = {
{ "sched:sched_migrate_task", timehist_migrate_task_event, },
};
struct perf_data data = {
@@ -2963,7 +2964,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
};
struct perf_session *session;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
int err = -1;
/*
@@ -3170,7 +3171,7 @@ static int perf_sched__lat(struct perf_sched *sched)
static int setup_map_cpus(struct perf_sched *sched)
{
- struct cpu_map *map;
+ struct perf_cpu_map *map;
sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
@@ -3183,7 +3184,7 @@ static int setup_map_cpus(struct perf_sched *sched)
if (!sched->map.cpus_str)
return 0;
- map = cpu_map__new(sched->map.cpus_str);
+ map = perf_cpu_map__new(sched->map.cpus_str);
if (!map) {
pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
return -1;
@@ -3195,7 +3196,7 @@ static int setup_map_cpus(struct perf_sched *sched)
static int setup_color_pids(struct perf_sched *sched)
{
- struct thread_map *map;
+ struct perf_thread_map *map;
if (!sched->map.color_pids_str)
return 0;
@@ -3212,12 +3213,12 @@ static int setup_color_pids(struct perf_sched *sched)
static int setup_color_cpus(struct perf_sched *sched)
{
- struct cpu_map *map;
+ struct perf_cpu_map *map;
if (!sched->map.color_cpus_str)
return 0;
- map = cpu_map__new(sched->map.color_cpus_str);
+ map = perf_cpu_map__new(sched->map.color_cpus_str);
if (!map) {
pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
return -1;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 8f24865596af..e079b34201f2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include "builtin.h"
-#include "perf.h"
-#include "util/cache.h"
+#include "util/counts.h"
#include "util/debug.h"
+#include "util/dso.h"
#include <subcmd/exec-cmd.h>
#include "util/header.h"
#include <subcmd/parse-options.h>
@@ -11,11 +11,13 @@
#include "util/session.h"
#include "util/tool.h"
#include "util/map.h"
+#include "util/srcline.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/trace-event.h"
#include "util/evlist.h"
#include "util/evsel.h"
+#include "util/evswitch.h"
#include "util/sort.h"
#include "util/data.h"
#include "util/auxtrace.h"
@@ -27,6 +29,7 @@
#include "util/thread-stack.h"
#include "util/time-utils.h"
#include "util/path.h"
+#include "ui/ui.h"
#include "print_binary.h"
#include "archinsn.h"
#include <linux/bitmap.h>
@@ -48,6 +51,10 @@
#include <fcntl.h>
#include <unistd.h>
#include <subcmd/pager.h>
+#include <perf/evlist.h>
+#include "util/record.h"
+#include "util/util.h"
+#include "perf.h"
#include <linux/ctype.h>
@@ -242,7 +249,7 @@ static struct {
},
};
-struct perf_evsel_script {
+struct evsel_script {
char *filename;
FILE *fp;
u64 samples;
@@ -251,15 +258,15 @@ struct perf_evsel_script {
int gnum;
};
-static inline struct perf_evsel_script *evsel_script(struct perf_evsel *evsel)
+static inline struct evsel_script *evsel_script(struct evsel *evsel)
{
- return (struct perf_evsel_script *)evsel->priv;
+ return (struct evsel_script *)evsel->priv;
}
-static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
+static struct evsel_script *perf_evsel_script__new(struct evsel *evsel,
struct perf_data *data)
{
- struct perf_evsel_script *es = zalloc(sizeof(*es));
+ struct evsel_script *es = zalloc(sizeof(*es));
if (es != NULL) {
if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
@@ -277,7 +284,7 @@ out_free:
return NULL;
}
-static void perf_evsel_script__delete(struct perf_evsel_script *es)
+static void perf_evsel_script__delete(struct evsel_script *es)
{
zfree(&es->filename);
fclose(es->fp);
@@ -285,7 +292,7 @@ static void perf_evsel_script__delete(struct perf_evsel_script *es)
free(es);
}
-static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
+static int perf_evsel_script__fprintf(struct evsel_script *es, FILE *fp)
{
struct stat st;
@@ -340,12 +347,12 @@ static const char *output_field2str(enum perf_output_field field)
#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
-static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
+static int perf_evsel__do_check_stype(struct evsel *evsel,
u64 sample_type, const char *sample_msg,
enum perf_output_field field,
bool allow_user_set)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
int type = output_type(attr->type);
const char *evname;
@@ -372,7 +379,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
return 0;
}
-static int perf_evsel__check_stype(struct perf_evsel *evsel,
+static int perf_evsel__check_stype(struct evsel *evsel,
u64 sample_type, const char *sample_msg,
enum perf_output_field field)
{
@@ -380,10 +387,10 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
false);
}
-static int perf_evsel__check_attr(struct perf_evsel *evsel,
+static int perf_evsel__check_attr(struct evsel *evsel,
struct perf_session *session)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
bool allow_user_set;
if (perf_header__has_feat(&session->header, HEADER_STAT))
@@ -418,7 +425,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
return -EINVAL;
if (PRINT_FIELD(SYM) &&
- !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
pr_err("Display of symbols requested but neither sample IP nor "
"sample address\navailable. Hence, no addresses to convert "
"to symbols.\n");
@@ -430,7 +437,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
return -EINVAL;
}
if (PRINT_FIELD(DSO) &&
- !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
pr_err("Display of DSO requested but no address to convert.\n");
return -EINVAL;
}
@@ -507,7 +514,7 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
static int perf_session__check_output_opt(struct perf_session *session)
{
unsigned int j;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
evsel = perf_session__find_first_evtype(session, attr_type(j));
@@ -531,7 +538,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
if (evsel == NULL)
continue;
- set_print_ip_opts(&evsel->attr);
+ set_print_ip_opts(&evsel->core.attr);
}
if (!no_callchain) {
@@ -558,7 +565,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
j = PERF_TYPE_TRACEPOINT;
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.type != j)
+ if (evsel->core.attr.type != j)
continue;
if (evsel__has_callchain(evsel)) {
@@ -566,7 +573,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
output[j].fields |= PERF_OUTPUT_SYM;
output[j].fields |= PERF_OUTPUT_SYMOFFSET;
output[j].fields |= PERF_OUTPUT_DSO;
- set_print_ip_opts(&evsel->attr);
+ set_print_ip_opts(&evsel->core.attr);
goto out;
}
}
@@ -614,10 +621,10 @@ static int perf_sample__fprintf_uregs(struct perf_sample *sample,
static int perf_sample__fprintf_start(struct perf_sample *sample,
struct thread *thread,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
u32 type, FILE *fp)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
unsigned long secs;
unsigned long long nsecs;
int printed = 0;
@@ -1059,7 +1066,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
if (ip == end) {
- printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
+ printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, ++insn, fp,
&total_cycles);
if (PRINT_FIELD(SRCCODE))
printed += print_srccode(thread, x.cpumode, ip);
@@ -1162,13 +1169,13 @@ out:
}
static const char *resolve_branch_sym(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct thread *thread,
struct addr_location *al,
u64 *ip)
{
struct addr_location addr_al;
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
const char *name = NULL;
if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
@@ -1191,11 +1198,11 @@ static const char *resolve_branch_sym(struct perf_sample *sample,
}
static int perf_sample__fprintf_callindent(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct thread *thread,
struct addr_location *al, FILE *fp)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
size_t depth = thread_stack__depth(thread, sample->cpu);
const char *name = NULL;
static int spacing;
@@ -1285,12 +1292,12 @@ static int perf_sample__fprintf_ipc(struct perf_sample *sample,
}
static int perf_sample__fprintf_bts(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct thread *thread,
struct addr_location *al,
struct machine *machine, FILE *fp)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
unsigned int type = output_type(attr->type);
bool print_srcline_last = false;
int printed = 0;
@@ -1322,7 +1329,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
/* print branch_to information */
if (PRINT_FIELD(ADDR) ||
- ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
+ ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
!output[type].user_set)) {
printed += fprintf(fp, " => ");
printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
@@ -1593,9 +1600,9 @@ static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp)
}
static int perf_sample__fprintf_synth(struct perf_sample *sample,
- struct perf_evsel *evsel, FILE *fp)
+ struct evsel *evsel, FILE *fp)
{
- switch (evsel->attr.config) {
+ switch (evsel->core.attr.config) {
case PERF_SYNTH_INTEL_PTWRITE:
return perf_sample__fprintf_synth_ptwrite(sample, fp);
case PERF_SYNTH_INTEL_MWAIT:
@@ -1627,8 +1634,9 @@ struct perf_script {
bool show_bpf_events;
bool allocated;
bool per_event_dump;
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct evswitch evswitch;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
int name_width;
const char *time_str;
struct perf_time_interval *ptime_range;
@@ -1636,9 +1644,9 @@ struct perf_script {
int range_num;
};
-static int perf_evlist__max_name_len(struct perf_evlist *evlist)
+static int perf_evlist__max_name_len(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int max = 0;
evlist__for_each_entry(evlist, evsel) {
@@ -1670,7 +1678,7 @@ static int data_src__fprintf(u64 data_src, FILE *fp)
struct metric_ctx {
struct perf_sample *sample;
struct thread *thread;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
FILE *fp;
};
@@ -1705,7 +1713,7 @@ static void script_new_line(struct perf_stat_config *config __maybe_unused,
static void perf_sample__fprint_metric(struct perf_script *script,
struct thread *thread,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
FILE *fp)
{
@@ -1720,7 +1728,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
},
.force_header = false,
};
- struct perf_evsel *ev2;
+ struct evsel *ev2;
u64 val;
if (!evsel->stats)
@@ -1733,7 +1741,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
sample->cpu,
&rt_stat);
evsel_script(evsel)->val = val;
- if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
+ if (evsel_script(evsel->leader)->gnum == evsel->leader->core.nr_members) {
for_each_group_member (ev2, evsel->leader) {
perf_stat__print_shadow_stats(&stat_config, ev2,
evsel_script(ev2)->val,
@@ -1747,7 +1755,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
}
static bool show_event(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
@@ -1788,14 +1796,14 @@ static bool show_event(struct perf_sample *sample,
}
static void process_event(struct perf_script *script,
- struct perf_sample *sample, struct perf_evsel *evsel,
+ struct perf_sample *sample, struct evsel *evsel,
struct addr_location *al,
struct machine *machine)
{
struct thread *thread = al->thread;
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
unsigned int type = output_type(attr->type);
- struct perf_evsel_script *es = evsel->priv;
+ struct evsel_script *es = evsel->priv;
FILE *fp = es->fp;
if (output[type].fields == 0)
@@ -1804,6 +1812,9 @@ static void process_event(struct perf_script *script,
if (!show_event(sample, evsel, thread, al))
return;
+ if (evswitch__discard(&script->evswitch, evsel))
+ return;
+
++es->samples;
perf_sample__fprintf_start(sample, thread, evsel,
@@ -1897,9 +1908,9 @@ static void process_event(struct perf_script *script,
static struct scripting_ops *scripting_ops;
-static void __process_stat(struct perf_evsel *counter, u64 tstamp)
+static void __process_stat(struct evsel *counter, u64 tstamp)
{
- int nthreads = thread_map__nr(counter->threads);
+ int nthreads = perf_thread_map__nr(counter->core.threads);
int ncpus = perf_evsel__nr_cpus(counter);
int cpu, thread;
static int header_printed;
@@ -1920,8 +1931,8 @@ static void __process_stat(struct perf_evsel *counter, u64 tstamp)
counts = perf_counts(counter->counts, cpu, thread);
printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
- counter->cpus->map[cpu],
- thread_map__pid(counter->threads, thread),
+ counter->core.cpus->map[cpu],
+ perf_thread_map__pid(counter->core.threads, thread),
counts->val,
counts->ena,
counts->run,
@@ -1931,7 +1942,7 @@ static void __process_stat(struct perf_evsel *counter, u64 tstamp)
}
}
-static void process_stat(struct perf_evsel *counter, u64 tstamp)
+static void process_stat(struct evsel *counter, u64 tstamp)
{
if (scripting_ops && scripting_ops->process_stat)
scripting_ops->process_stat(&stat_config, counter, tstamp);
@@ -1973,7 +1984,7 @@ static bool filter_cpu(struct perf_sample *sample)
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct perf_script *scr = container_of(tool, struct perf_script, tool);
@@ -2018,13 +2029,13 @@ out_put:
}
static int process_attr(struct perf_tool *tool, union perf_event *event,
- struct perf_evlist **pevlist)
+ struct evlist **pevlist)
{
struct perf_script *scr = container_of(tool, struct perf_script, tool);
- struct perf_evlist *evlist;
- struct perf_evsel *evsel, *pos;
+ struct evlist *evlist;
+ struct evsel *evsel, *pos;
int err;
- static struct perf_evsel_script *es;
+ static struct evsel_script *es;
err = perf_event__process_attr(tool, event, pevlist);
if (err)
@@ -2046,18 +2057,18 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
}
}
- if (evsel->attr.type >= PERF_TYPE_MAX &&
- evsel->attr.type != PERF_TYPE_SYNTH)
+ if (evsel->core.attr.type >= PERF_TYPE_MAX &&
+ evsel->core.attr.type != PERF_TYPE_SYNTH)
return 0;
evlist__for_each_entry(evlist, pos) {
- if (pos->attr.type == evsel->attr.type && pos != evsel)
+ if (pos->core.attr.type == evsel->core.attr.type && pos != evsel)
return 0;
}
- set_print_ip_opts(&evsel->attr);
+ set_print_ip_opts(&evsel->core.attr);
- if (evsel->attr.sample_type)
+ if (evsel->core.attr.sample_type)
err = perf_evsel__check_attr(evsel, scr->session);
return err;
@@ -2071,7 +2082,7 @@ static int process_comm_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
int ret = -1;
thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
@@ -2083,7 +2094,7 @@ static int process_comm_event(struct perf_tool *tool,
if (perf_event__process_comm(tool, event, sample, machine) < 0)
goto out;
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = 0;
sample->tid = event->comm.tid;
@@ -2108,7 +2119,7 @@ static int process_namespaces_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
int ret = -1;
thread = machine__findnew_thread(machine, event->namespaces.pid,
@@ -2121,7 +2132,7 @@ static int process_namespaces_event(struct perf_tool *tool,
if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
goto out;
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = 0;
sample->tid = event->namespaces.tid;
@@ -2146,7 +2157,7 @@ static int process_fork_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (perf_event__process_fork(tool, event, sample, machine) < 0)
return -1;
@@ -2157,7 +2168,7 @@ static int process_fork_event(struct perf_tool *tool,
return -1;
}
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = event->fork.time;
sample->tid = event->fork.tid;
@@ -2181,7 +2192,7 @@ static int process_exit_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
if (thread == NULL) {
@@ -2189,7 +2200,7 @@ static int process_exit_event(struct perf_tool *tool,
return -1;
}
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = 0;
sample->tid = event->fork.tid;
@@ -2216,7 +2227,7 @@ static int process_mmap_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (perf_event__process_mmap(tool, event, sample, machine) < 0)
return -1;
@@ -2227,7 +2238,7 @@ static int process_mmap_event(struct perf_tool *tool,
return -1;
}
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = 0;
sample->tid = event->mmap.tid;
@@ -2250,7 +2261,7 @@ static int process_mmap2_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
return -1;
@@ -2261,7 +2272,7 @@ static int process_mmap2_event(struct perf_tool *tool,
return -1;
}
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = 0;
sample->tid = event->mmap2.tid;
@@ -2284,7 +2295,7 @@ static int process_switch_event(struct perf_tool *tool,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (perf_event__process_switch(tool, event, sample, machine) < 0)
return -1;
@@ -2319,7 +2330,7 @@ process_lost_event(struct perf_tool *tool,
{
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
struct thread *thread;
thread = machine__findnew_thread(machine, sample->pid,
@@ -2355,12 +2366,12 @@ process_bpf_events(struct perf_tool *tool __maybe_unused,
struct thread *thread;
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (machine__process_ksymbol(machine, event, sample) < 0)
return -1;
- if (!evsel->attr.sample_id_all) {
+ if (!evsel->core.attr.sample_id_all) {
perf_event__fprintf(event, stdout);
return 0;
}
@@ -2388,8 +2399,8 @@ static void sig_handler(int sig __maybe_unused)
static void perf_script__fclose_per_event_dump(struct perf_script *script)
{
- struct perf_evlist *evlist = script->session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = script->session->evlist;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (!evsel->priv)
@@ -2401,7 +2412,7 @@ static void perf_script__fclose_per_event_dump(struct perf_script *script)
static int perf_script__fopen_per_event_dump(struct perf_script *script)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(script->session->evlist, evsel) {
/*
@@ -2428,8 +2439,8 @@ out_err_fclose:
static int perf_script__setup_per_event_dump(struct perf_script *script)
{
- struct perf_evsel *evsel;
- static struct perf_evsel_script es_stdout;
+ struct evsel *evsel;
+ static struct evsel_script es_stdout;
if (script->per_event_dump)
return perf_script__fopen_per_event_dump(script);
@@ -2444,10 +2455,10 @@ static int perf_script__setup_per_event_dump(struct perf_script *script)
static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(script->session->evlist, evsel) {
- struct perf_evsel_script *es = evsel->priv;
+ struct evsel_script *es = evsel->priv;
perf_evsel_script__fprintf(es, stdout);
perf_evsel_script__delete(es);
@@ -2484,8 +2495,8 @@ static int __cmd_script(struct perf_script *script)
script->tool.finished_round = process_finished_round_event;
}
if (script->show_bpf_events) {
- script->tool.ksymbol = process_bpf_events;
- script->tool.bpf_event = process_bpf_events;
+ script->tool.ksymbol = process_bpf_events;
+ script->tool.bpf = process_bpf_events;
}
if (perf_script__setup_per_event_dump(script)) {
@@ -3003,7 +3014,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
{
char filename[MAXPATHLEN], evname[128];
char line[BUFSIZ], *p;
- struct perf_evsel *pos;
+ struct evsel *pos;
int match, len;
FILE *fp;
@@ -3235,8 +3246,8 @@ static void script__setup_sample_type(struct perf_script *script)
static int process_stat_round_event(struct perf_session *session,
union perf_event *event)
{
- struct stat_round_event *round = &event->stat_round;
- struct perf_evsel *counter;
+ struct perf_record_stat_round *round = &event->stat_round;
+ struct evsel *counter;
evlist__for_each_entry(session->evlist, counter) {
perf_stat_process_counter(&stat_config, counter);
@@ -3256,7 +3267,7 @@ static int process_stat_config_event(struct perf_session *session __maybe_unused
static int set_maps(struct perf_script *script)
{
- struct perf_evlist *evlist = script->session->evlist;
+ struct evlist *evlist = script->session->evlist;
if (!script->cpus || !script->threads)
return 0;
@@ -3264,7 +3275,7 @@ static int set_maps(struct perf_script *script)
if (WARN_ONCE(script->allocated, "stats double allocation\n"))
return -EINVAL;
- perf_evlist__set_maps(evlist, script->cpus, script->threads);
+ perf_evlist__set_maps(&evlist->core, script->cpus, script->threads);
if (perf_evlist__alloc_stats(evlist, true))
return -ENOMEM;
@@ -3537,6 +3548,7 @@ int cmd_script(int argc, const char **argv)
"file", "file saving guest os /proc/kallsyms"),
OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
"file", "file saving guest os /proc/modules"),
+ OPTS_EVSWITCH(&script.evswitch),
OPT_END()
};
const char * const script_subcommands[] = { "record", "report", NULL };
@@ -3861,6 +3873,10 @@ int cmd_script(int argc, const char **argv)
script.range_num);
}
+ err = evswitch__init(&script.evswitch, session->evlist, stderr);
+ if (err)
+ goto out_delete;
+
err = __cmd_script(&script);
flush_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b55a534b4de0..7e17bf9f700a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -40,8 +40,8 @@
* Jaswinder Singh Rajput <jaswinder@kernel.org>
*/
-#include "perf.h"
#include "builtin.h"
+#include "perf.h"
#include "util/cgroup.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
@@ -54,7 +54,6 @@
#include "util/stat.h"
#include "util/header.h"
#include "util/cpumap.h"
-#include "util/thread.h"
#include "util/thread_map.h"
#include "util/counts.h"
#include "util/group.h"
@@ -62,6 +61,8 @@
#include "util/tool.h"
#include "util/string2.h"
#include "util/metricgroup.h"
+#include "util/target.h"
+#include "util/time-utils.h"
#include "util/top.h"
#include "asm/bug.h"
@@ -83,6 +84,7 @@
#include <sys/resource.h>
#include <linux/ctype.h>
+#include <perf/evlist.h>
#define DEFAULT_SEPARATOR " "
#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"
@@ -130,7 +132,7 @@ static const char *smi_cost_attrs = {
"}"
};
-static struct perf_evlist *evsel_list;
+static struct evlist *evsel_list;
static struct target target = {
.uid = UINT_MAX,
@@ -164,8 +166,8 @@ struct perf_stat {
u64 bytes_written;
struct perf_tool tool;
bool maps_allocated;
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
enum aggr_mode aggr_mode;
};
@@ -234,7 +236,7 @@ static int write_stat_round_event(u64 tm, u64 type)
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
static int
-perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
+perf_evsel__write_stat_event(struct evsel *counter, u32 cpu, u32 thread,
struct perf_counts_values *count)
{
struct perf_sample_id *sid = SID(counter, cpu, thread);
@@ -243,7 +245,7 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
process_synthesized_event, NULL);
}
-static int read_single_counter(struct perf_evsel *counter, int cpu,
+static int read_single_counter(struct evsel *counter, int cpu,
int thread, struct timespec *rs)
{
if (counter->tool_event == PERF_TOOL_DURATION_TIME) {
@@ -261,9 +263,9 @@ static int read_single_counter(struct perf_evsel *counter, int cpu,
* Read out the results of a single counter:
* do not aggregate counts across CPUs in system-wide mode
*/
-static int read_counter(struct perf_evsel *counter, struct timespec *rs)
+static int read_counter(struct evsel *counter, struct timespec *rs)
{
- int nthreads = thread_map__nr(evsel_list->threads);
+ int nthreads = perf_thread_map__nr(evsel_list->core.threads);
int ncpus, cpu, thread;
if (target__has_cpu(&target) && !target__has_per_thread(&target))
@@ -287,7 +289,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs)
* The leader's group read loads data into its group members
* (via perf_evsel__read_counter) and sets threir count->loaded.
*/
- if (!count->loaded &&
+ if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
read_single_counter(counter, cpu, thread, rs)) {
counter->counts->scaled = -1;
perf_counts(counter->counts, cpu, thread)->ena = 0;
@@ -295,7 +297,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs)
return -1;
}
- count->loaded = false;
+ perf_counts__set_loaded(counter->counts, cpu, thread, false);
if (STAT_RECORD) {
if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
@@ -319,7 +321,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs)
static void read_counters(struct timespec *rs)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
int ret;
evlist__for_each_entry(evsel_list, counter) {
@@ -362,7 +364,7 @@ static void enable_counters(void)
* - we have initial delay configured
*/
if (!target__none(&target) || stat_config.initial_delay)
- perf_evlist__enable(evsel_list);
+ evlist__enable(evsel_list);
}
static void disable_counters(void)
@@ -373,7 +375,7 @@ static void disable_counters(void)
* from counting before reading their constituent counters.
*/
if (!target__none(&target))
- perf_evlist__disable(evsel_list);
+ evlist__disable(evsel_list);
}
static volatile int workload_exec_errno;
@@ -389,13 +391,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
workload_exec_errno = info->si_value.sival_int;
}
-static bool perf_evsel__should_store_id(struct perf_evsel *counter)
+static bool perf_evsel__should_store_id(struct evsel *counter)
{
- return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
+ return STAT_RECORD || counter->core.attr.read_format & PERF_FORMAT_ID;
}
static bool is_target_alive(struct target *_target,
- struct thread_map *threads)
+ struct perf_thread_map *threads)
{
struct stat st;
int i;
@@ -423,7 +425,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
int timeout = stat_config.timeout;
char msg[BUFSIZ];
unsigned long long t0, t1;
- struct perf_evsel *counter;
+ struct evsel *counter;
struct timespec ts;
size_t l;
int status = 0;
@@ -478,22 +480,22 @@ try_again:
counter->supported = false;
if ((counter->leader != counter) ||
- !(counter->leader->nr_members > 1))
+ !(counter->leader->core.nr_members > 1))
continue;
} else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
if (verbose > 0)
ui__warning("%s\n", msg);
goto try_again;
} else if (target__has_per_thread(&target) &&
- evsel_list->threads &&
- evsel_list->threads->err_thread != -1) {
+ evsel_list->core.threads &&
+ evsel_list->core.threads->err_thread != -1) {
/*
* For global --per-thread case, skip current
* error thread.
*/
- if (!thread_map__remove(evsel_list->threads,
- evsel_list->threads->err_thread)) {
- evsel_list->threads->err_thread = -1;
+ if (!thread_map__remove(evsel_list->core.threads,
+ evsel_list->core.threads->err_thread)) {
+ evsel_list->core.threads->err_thread = -1;
goto try_again;
}
}
@@ -579,7 +581,7 @@ try_again:
enable_counters();
while (!done) {
nanosleep(&ts, NULL);
- if (!is_target_alive(&target, evsel_list->threads))
+ if (!is_target_alive(&target, evsel_list->core.threads))
break;
if (timeout)
break;
@@ -607,7 +609,13 @@ try_again:
* group leaders.
*/
read_counters(&(struct timespec) { .tv_nsec = t1-t0 });
- perf_evlist__close(evsel_list);
+
+ /*
+ * We need to keep evsel_list alive, because it's processed
+ * later the evsel_list will be closed after.
+ */
+ if (!STAT_RECORD)
+ evlist__close(evsel_list);
return WEXITSTATUS(status);
}
@@ -797,24 +805,24 @@ static struct option stat_options[] = {
};
static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int cpu)
+ struct perf_cpu_map *map, int cpu)
{
return cpu_map__get_socket(map, cpu, NULL);
}
static int perf_stat__get_die(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int cpu)
+ struct perf_cpu_map *map, int cpu)
{
return cpu_map__get_die(map, cpu, NULL);
}
static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int cpu)
+ struct perf_cpu_map *map, int cpu)
{
return cpu_map__get_core(map, cpu, NULL);
}
-static int cpu_map__get_max(struct cpu_map *map)
+static int cpu_map__get_max(struct perf_cpu_map *map)
{
int i, max = -1;
@@ -827,7 +835,7 @@ static int cpu_map__get_max(struct cpu_map *map)
}
static int perf_stat__get_aggr(struct perf_stat_config *config,
- aggr_get_id_t get_id, struct cpu_map *map, int idx)
+ aggr_get_id_t get_id, struct perf_cpu_map *map, int idx)
{
int cpu;
@@ -843,26 +851,26 @@ static int perf_stat__get_aggr(struct perf_stat_config *config,
}
static int perf_stat__get_socket_cached(struct perf_stat_config *config,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
}
static int perf_stat__get_die_cached(struct perf_stat_config *config,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_stat__get_aggr(config, perf_stat__get_die, map, idx);
}
static int perf_stat__get_core_cached(struct perf_stat_config *config,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
}
static bool term_percore_set(void)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
evlist__for_each_entry(evsel_list, counter) {
if (counter->percore)
@@ -878,21 +886,21 @@ static int perf_stat_init_aggr_mode(void)
switch (stat_config.aggr_mode) {
case AGGR_SOCKET:
- if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) {
+ if (cpu_map__build_socket_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build socket map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_socket_cached;
break;
case AGGR_DIE:
- if (cpu_map__build_die_map(evsel_list->cpus, &stat_config.aggr_map)) {
+ if (cpu_map__build_die_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build die map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_die_cached;
break;
case AGGR_CORE:
- if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) {
+ if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
@@ -900,7 +908,7 @@ static int perf_stat_init_aggr_mode(void)
break;
case AGGR_NONE:
if (term_percore_set()) {
- if (cpu_map__build_core_map(evsel_list->cpus,
+ if (cpu_map__build_core_map(evsel_list->core.cpus,
&stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
@@ -920,20 +928,20 @@ static int perf_stat_init_aggr_mode(void)
* taking the highest cpu number to be the size of
* the aggregation translate cpumap.
*/
- nr = cpu_map__get_max(evsel_list->cpus);
- stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1);
+ nr = cpu_map__get_max(evsel_list->core.cpus);
+ stat_config.cpus_aggr_map = perf_cpu_map__empty_new(nr + 1);
return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
}
static void perf_stat__exit_aggr_mode(void)
{
- cpu_map__put(stat_config.aggr_map);
- cpu_map__put(stat_config.cpus_aggr_map);
+ perf_cpu_map__put(stat_config.aggr_map);
+ perf_cpu_map__put(stat_config.cpus_aggr_map);
stat_config.aggr_map = NULL;
stat_config.cpus_aggr_map = NULL;
}
-static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
+static inline int perf_env__get_cpu(struct perf_env *env, struct perf_cpu_map *map, int idx)
{
int cpu;
@@ -948,7 +956,7 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, i
return cpu;
}
-static int perf_env__get_socket(struct cpu_map *map, int idx, void *data)
+static int perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data)
{
struct perf_env *env = data;
int cpu = perf_env__get_cpu(env, map, idx);
@@ -956,7 +964,7 @@ static int perf_env__get_socket(struct cpu_map *map, int idx, void *data)
return cpu == -1 ? -1 : env->cpu[cpu].socket_id;
}
-static int perf_env__get_die(struct cpu_map *map, int idx, void *data)
+static int perf_env__get_die(struct perf_cpu_map *map, int idx, void *data)
{
struct perf_env *env = data;
int die_id = -1, cpu = perf_env__get_cpu(env, map, idx);
@@ -980,7 +988,7 @@ static int perf_env__get_die(struct cpu_map *map, int idx, void *data)
return die_id;
}
-static int perf_env__get_core(struct cpu_map *map, int idx, void *data)
+static int perf_env__get_core(struct perf_cpu_map *map, int idx, void *data)
{
struct perf_env *env = data;
int core = -1, cpu = perf_env__get_cpu(env, map, idx);
@@ -1010,37 +1018,37 @@ static int perf_env__get_core(struct cpu_map *map, int idx, void *data)
return core;
}
-static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus,
- struct cpu_map **sockp)
+static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus,
+ struct perf_cpu_map **sockp)
{
return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
}
-static int perf_env__build_die_map(struct perf_env *env, struct cpu_map *cpus,
- struct cpu_map **diep)
+static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus,
+ struct perf_cpu_map **diep)
{
return cpu_map__build_map(cpus, diep, perf_env__get_die, env);
}
-static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
- struct cpu_map **corep)
+static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus,
+ struct perf_cpu_map **corep)
{
return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
}
static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
}
static int perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_env__get_die(map, idx, &perf_stat.session->header.env);
}
static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
- struct cpu_map *map, int idx)
+ struct perf_cpu_map *map, int idx)
{
return perf_env__get_core(map, idx, &perf_stat.session->header.env);
}
@@ -1051,21 +1059,21 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
switch (stat_config.aggr_mode) {
case AGGR_SOCKET:
- if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
+ if (perf_env__build_socket_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build socket map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_socket_file;
break;
case AGGR_DIE:
- if (perf_env__build_die_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
+ if (perf_env__build_die_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build die map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_die_file;
break;
case AGGR_CORE:
- if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
+ if (perf_env__build_core_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
@@ -1360,7 +1368,7 @@ static int add_default_attributes(void)
free(str);
}
- if (!evsel_list->nr_entries) {
+ if (!evsel_list->core.nr_entries) {
if (target__has_cpu(&target))
default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
@@ -1455,8 +1463,8 @@ static int __cmd_record(int argc, const char **argv)
static int process_stat_round_event(struct perf_session *session,
union perf_event *event)
{
- struct stat_round_event *stat_round = &event->stat_round;
- struct perf_evsel *counter;
+ struct perf_record_stat_round *stat_round = &event->stat_round;
+ struct evsel *counter;
struct timespec tsh, *ts = NULL;
const char **argv = session->header.env.cmdline_argv;
int argc = session->header.env.nr_cmdline;
@@ -1486,7 +1494,7 @@ int process_stat_config_event(struct perf_session *session,
perf_event__read_stat_config(&stat_config, &event->stat_config);
- if (cpu_map__empty(st->cpus)) {
+ if (perf_cpu_map__empty(st->cpus)) {
if (st->aggr_mode != AGGR_UNSET)
pr_warning("warning: processing task data, aggregation mode not set\n");
return 0;
@@ -1511,7 +1519,7 @@ static int set_maps(struct perf_stat *st)
if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
return -EINVAL;
- perf_evlist__set_maps(evsel_list, st->cpus, st->threads);
+ perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
if (perf_evlist__alloc_stats(evsel_list, true))
return -ENOMEM;
@@ -1545,7 +1553,7 @@ int process_cpu_map_event(struct perf_session *session,
{
struct perf_tool *tool = session->tool;
struct perf_stat *st = container_of(tool, struct perf_stat, tool);
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
if (st->cpus) {
pr_warning("Extra cpu map event, ignoring.\n");
@@ -1670,14 +1678,14 @@ static void setup_system_wide(int forks)
if (!forks)
target.system_wide = true;
else {
- struct perf_evsel *counter;
+ struct evsel *counter;
evlist__for_each_entry(evsel_list, counter) {
if (!counter->system_wide)
return;
}
- if (evsel_list->nr_entries)
+ if (evsel_list->core.nr_entries)
target.system_wide = true;
}
}
@@ -1696,7 +1704,7 @@ int cmd_stat(int argc, const char **argv)
setlocale(LC_ALL, "");
- evsel_list = perf_evlist__new();
+ evsel_list = evlist__new();
if (evsel_list == NULL)
return -ENOMEM;
@@ -1883,10 +1891,10 @@ int cmd_stat(int argc, const char **argv)
* so we could print it out on output.
*/
if (stat_config.aggr_mode == AGGR_THREAD) {
- thread_map__read_comms(evsel_list->threads);
+ thread_map__read_comms(evsel_list->core.threads);
if (target.system_wide) {
if (runtime_stat_new(&stat_config,
- thread_map__nr(evsel_list->threads))) {
+ perf_thread_map__nr(evsel_list->core.threads))) {
goto out;
}
}
@@ -1997,6 +2005,7 @@ int cmd_stat(int argc, const char **argv)
perf_session__write_header(perf_stat.session, evsel_list, fd, true);
}
+ evlist__close(evsel_list);
perf_session__delete(perf_stat.session);
}
@@ -2008,7 +2017,7 @@ out:
if (smi_cost && smi_reset)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
- perf_evlist__delete(evsel_list);
+ evlist__delete(evsel_list);
runtime_stat_delete(&stat_config);
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 4bde3fa245d1..e0e822695a29 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -10,13 +10,11 @@
#include <errno.h>
#include <inttypes.h>
-#include <traceevent/event-parse.h>
#include "builtin.h"
#include "util/color.h"
#include <linux/list.h>
-#include "util/cache.h"
-#include "util/evlist.h"
+#include "util/evlist.h" // for struct evsel_str_handler
#include "util/evsel.h"
#include <linux/kernel.h>
#include <linux/rbtree.h>
@@ -28,6 +26,7 @@
#include "perf.h"
#include "util/header.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
#include "util/event.h"
@@ -545,19 +544,19 @@ exit:
}
typedef int (*tracepoint_handler)(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace);
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
struct timechart *tchart = container_of(tool, struct timechart, tool);
- if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
+ if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) {
if (!tchart->first_time || tchart->first_time > sample->time)
tchart->first_time = sample->time;
if (tchart->last_time < sample->time)
@@ -575,7 +574,7 @@ static int process_sample_event(struct perf_tool *tool,
static int
process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
@@ -591,7 +590,7 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
static int
process_sample_cpu_frequency(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
@@ -604,7 +603,7 @@ process_sample_cpu_frequency(struct timechart *tchart,
static int
process_sample_sched_wakeup(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace)
{
@@ -618,7 +617,7 @@ process_sample_sched_wakeup(struct timechart *tchart,
static int
process_sample_sched_switch(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace)
{
@@ -634,7 +633,7 @@ process_sample_sched_switch(struct timechart *tchart,
#ifdef SUPPORT_OLD_POWER_EVENTS
static int
process_sample_power_start(struct timechart *tchart __maybe_unused,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
@@ -647,7 +646,7 @@ process_sample_power_start(struct timechart *tchart __maybe_unused,
static int
process_sample_power_end(struct timechart *tchart,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
@@ -657,7 +656,7 @@ process_sample_power_end(struct timechart *tchart,
static int
process_sample_power_frequency(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
@@ -840,7 +839,7 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
static int
process_enter_read(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -850,7 +849,7 @@ process_enter_read(struct timechart *tchart,
static int
process_exit_read(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -860,7 +859,7 @@ process_exit_read(struct timechart *tchart,
static int
process_enter_write(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -870,7 +869,7 @@ process_enter_write(struct timechart *tchart,
static int
process_exit_write(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -880,7 +879,7 @@ process_exit_write(struct timechart *tchart,
static int
process_enter_sync(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -890,7 +889,7 @@ process_enter_sync(struct timechart *tchart,
static int
process_exit_sync(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -900,7 +899,7 @@ process_exit_sync(struct timechart *tchart,
static int
process_enter_tx(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -910,7 +909,7 @@ process_enter_tx(struct timechart *tchart,
static int
process_exit_tx(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -920,7 +919,7 @@ process_exit_tx(struct timechart *tchart,
static int
process_enter_rx(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -930,7 +929,7 @@ process_enter_rx(struct timechart *tchart,
static int
process_exit_rx(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -940,7 +939,7 @@ process_exit_rx(struct timechart *tchart,
static int
process_enter_poll(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long fd = perf_evsel__intval(evsel, sample, "fd");
@@ -950,7 +949,7 @@ process_enter_poll(struct timechart *tchart,
static int
process_exit_poll(struct timechart *tchart,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
long ret = perf_evsel__intval(evsel, sample, "ret");
@@ -1518,10 +1517,7 @@ static int process_header(struct perf_file_section *section __maybe_unused,
if (!tchart->topology)
break;
- if (svg_build_topology_map(ph->env.sibling_cores,
- ph->env.nr_sibling_cores,
- ph->env.sibling_threads,
- ph->env.nr_sibling_threads))
+ if (svg_build_topology_map(&ph->env))
fprintf(stderr, "problem building topology\n");
break;
@@ -1534,7 +1530,7 @@ static int process_header(struct perf_file_section *section __maybe_unused,
static int __cmd_timechart(struct timechart *tchart, const char *output_name)
{
- const struct perf_evsel_str_handler power_tracepoints[] = {
+ const struct evsel_str_handler power_tracepoints[] = {
{ "power:cpu_idle", process_sample_cpu_idle },
{ "power:cpu_frequency", process_sample_cpu_frequency },
{ "sched:sched_wakeup", process_sample_sched_wakeup },
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b46b3c9f57a0..726e3f2dd8c7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -24,6 +24,7 @@
#include "util/bpf-event.h"
#include "util/config.h"
#include "util/color.h"
+#include "util/dso.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/event.h"
@@ -31,20 +32,20 @@
#include "util/map.h"
#include "util/session.h"
#include "util/symbol.h"
-#include "util/thread.h"
-#include "util/thread_map.h"
#include "util/top.h"
+#include "util/util.h"
#include <linux/rbtree.h>
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
+#include "util/callchain.h"
#include "util/cpumap.h"
-#include "util/xyarray.h"
#include "util/sort.h"
#include "util/string2.h"
#include "util/term.h"
#include "util/intlist.h"
#include "util/parse-branch-options.h"
#include "arch/common.h"
+#include "ui/ui.h"
#include "util/debug.h"
#include "util/ordered-events.h"
@@ -101,7 +102,7 @@ static void perf_top__resize(struct perf_top *top)
static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct symbol *sym;
struct annotation *notes;
struct map *map;
@@ -129,7 +130,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
notes = symbol__annotation(sym);
pthread_mutex_lock(&notes->lock);
- if (!symbol__hists(sym, top->evlist->nr_entries)) {
+ if (!symbol__hists(sym, top->evlist->core.nr_entries)) {
pthread_mutex_unlock(&notes->lock);
pr_err("Not enough memory for annotating '%s' symbol!\n",
sym->name);
@@ -186,7 +187,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
static void perf_top__record_precise_ip(struct perf_top *top,
struct hist_entry *he,
struct perf_sample *sample,
- struct perf_evsel *evsel, u64 ip)
+ struct evsel *evsel, u64 ip)
{
struct annotation *notes;
struct symbol *sym = he->ms.sym;
@@ -228,7 +229,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
static void perf_top__show_details(struct perf_top *top)
{
struct hist_entry *he = top->sym_filter_entry;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct annotation *notes;
struct symbol *symbol;
int more;
@@ -265,12 +266,52 @@ out_unlock:
pthread_mutex_unlock(&notes->lock);
}
+static void perf_top__resort_hists(struct perf_top *t)
+{
+ struct evlist *evlist = t->evlist;
+ struct evsel *pos;
+
+ evlist__for_each_entry(evlist, pos) {
+ struct hists *hists = evsel__hists(pos);
+
+ /*
+ * unlink existing entries so that they can be linked
+ * in a correct order in hists__match() below.
+ */
+ hists__unlink(hists);
+
+ if (evlist->enabled) {
+ if (t->zero) {
+ hists__delete_entries(hists);
+ } else {
+ hists__decay_entries(hists, t->hide_user_symbols,
+ t->hide_kernel_symbols);
+ }
+ }
+
+ hists__collapse_resort(hists, NULL);
+
+ /* Non-group events are considered as leader */
+ if (symbol_conf.event_group &&
+ !perf_evsel__is_group_leader(pos)) {
+ struct hists *leader_hists = evsel__hists(pos->leader);
+
+ hists__match(leader_hists, hists);
+ hists__link(leader_hists, hists);
+ }
+ }
+
+ evlist__for_each_entry(evlist, pos) {
+ perf_evsel__output_resort(pos, NULL);
+ }
+}
+
static void perf_top__print_sym_table(struct perf_top *top)
{
char bf[160];
int printed = 0;
const int win_width = top->winsize.ws_col - 1;
- struct perf_evsel *evsel = top->sym_evsel;
+ struct evsel *evsel = top->sym_evsel;
struct hists *hists = evsel__hists(evsel);
puts(CONSOLE_CLEAR);
@@ -296,17 +337,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
return;
}
- if (top->evlist->enabled) {
- if (top->zero) {
- hists__delete_entries(hists);
- } else {
- hists__decay_entries(hists, top->hide_user_symbols,
- top->hide_kernel_symbols);
- }
- }
-
- hists__collapse_resort(hists, NULL);
- perf_evsel__output_resort(evsel, NULL);
+ perf_top__resort_hists(top);
hists__output_recalc_col_len(hists, top->print_entries - printed);
putchar('\n');
@@ -404,7 +435,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top->delay_secs);
fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
- if (top->evlist->nr_entries > 1)
+ if (top->evlist->core.nr_entries > 1)
fprintf(stdout, "\t[E] active event counter. \t(%s)\n", perf_evsel__name(top->sym_evsel));
fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
@@ -439,7 +470,7 @@ static int perf_top__key_mapped(struct perf_top *top, int c)
case 'S':
return 1;
case 'E':
- return top->evlist->nr_entries > 1 ? 1 : 0;
+ return top->evlist->core.nr_entries > 1 ? 1 : 0;
default:
break;
}
@@ -485,7 +516,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
}
break;
case 'E':
- if (top->evlist->nr_entries > 1) {
+ if (top->evlist->core.nr_entries > 1) {
/* Select 0 as the default event: */
int counter = 0;
@@ -496,7 +527,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
prompt_integer(&counter, "Enter details event counter");
- if (counter >= top->evlist->nr_entries) {
+ if (counter >= top->evlist->core.nr_entries) {
top->sym_evsel = perf_evlist__first(top->evlist);
fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
sleep(1);
@@ -554,25 +585,11 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
static void perf_top__sort_new_samples(void *arg)
{
struct perf_top *t = arg;
- struct perf_evsel *evsel = t->sym_evsel;
- struct hists *hists;
if (t->evlist->selected != NULL)
t->sym_evsel = t->evlist->selected;
- hists = evsel__hists(evsel);
-
- if (t->evlist->enabled) {
- if (t->zero) {
- hists__delete_entries(hists);
- } else {
- hists__decay_entries(hists, t->hide_user_symbols,
- t->hide_kernel_symbols);
- }
- }
-
- hists__collapse_resort(hists, NULL);
- perf_evsel__output_resort(evsel, NULL);
+ perf_top__resort_hists(t);
if (t->lost || t->drop)
pr_warning("Too slow to read ring buffer (change period (-c/-F) or limit CPUs (-C)\n");
@@ -586,7 +603,7 @@ static void stop_top(void)
static void *display_thread_tui(void *arg)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
struct perf_top *top = arg;
const char *help = "For a higher level overview, try: perf top --sort comm,dso";
struct hist_browser_timer hbt = {
@@ -602,6 +619,8 @@ static void *display_thread_tui(void *arg)
*/
unshare(CLONE_FS);
+ prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0);
+
perf_top__sort_new_samples(top);
/*
@@ -652,6 +671,8 @@ static void *display_thread(void *arg)
*/
unshare(CLONE_FS);
+ prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0);
+
display_setup_sig();
pthread__unblock_sigwinch();
repeat:
@@ -693,7 +714,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
{
struct perf_top *top = arg;
struct hist_entry *he = iter->he;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
if (perf_hpp_list.sym && single)
perf_top__record_precise_ip(top, he, iter->sample, evsel, al->addr);
@@ -705,7 +726,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
static void perf_event__process_sample(struct perf_tool *tool,
const union perf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@@ -745,7 +766,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (!perf_evlist__exclude_kernel(top->session->evlist)) {
ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
-"Check /proc/sys/kernel/kptr_restrict.\n\n"
+"Check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
"Kernel%s samples will not be resolved.\n",
al.map && map__has_symbols(al.map) ?
" modules" : "");
@@ -813,7 +834,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
static void
perf_top__process_lost(struct perf_top *top, union perf_event *event,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
struct hists *hists = evsel__hists(evsel);
@@ -825,7 +846,7 @@ perf_top__process_lost(struct perf_top *top, union perf_event *event,
static void
perf_top__process_lost_samples(struct perf_top *top,
union perf_event *event,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
struct hists *hists = evsel__hists(evsel);
@@ -839,7 +860,7 @@ static u64 last_timestamp;
static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
{
struct record_opts *opts = &top->record_opts;
- struct perf_evlist *evlist = top->evlist;
+ struct evlist *evlist = top->evlist;
struct perf_mmap *md;
union perf_event *event;
@@ -874,7 +895,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
static void perf_top__mmap_read(struct perf_top *top)
{
bool overwrite = top->record_opts.overwrite;
- struct perf_evlist *evlist = top->evlist;
+ struct evlist *evlist = top->evlist;
int i;
if (overwrite)
@@ -909,10 +930,10 @@ static void perf_top__mmap_read(struct perf_top *top)
static int perf_top__overwrite_check(struct perf_top *top)
{
struct record_opts *opts = &top->record_opts;
- struct perf_evlist *evlist = top->evlist;
+ struct evlist *evlist = top->evlist;
struct perf_evsel_config_term *term;
struct list_head *config_terms;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int set, overwrite = -1;
evlist__for_each_entry(evlist, evsel) {
@@ -952,11 +973,11 @@ static int perf_top__overwrite_check(struct perf_top *top)
}
static int perf_top_overwrite_fallback(struct perf_top *top,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
struct record_opts *opts = &top->record_opts;
- struct perf_evlist *evlist = top->evlist;
- struct perf_evsel *counter;
+ struct evlist *evlist = top->evlist;
+ struct evsel *counter;
if (!opts->overwrite)
return 0;
@@ -966,7 +987,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top,
return 0;
evlist__for_each_entry(evlist, counter)
- counter->attr.write_backward = false;
+ counter->core.attr.write_backward = false;
opts->overwrite = false;
pr_debug2("fall back to non-overwrite mode\n");
return 1;
@@ -975,8 +996,8 @@ static int perf_top_overwrite_fallback(struct perf_top *top,
static int perf_top__start_counters(struct perf_top *top)
{
char msg[BUFSIZ];
- struct perf_evsel *counter;
- struct perf_evlist *evlist = top->evlist;
+ struct evsel *counter;
+ struct evlist *evlist = top->evlist;
struct record_opts *opts = &top->record_opts;
if (perf_top__overwrite_check(top)) {
@@ -989,8 +1010,8 @@ static int perf_top__start_counters(struct perf_top *top)
evlist__for_each_entry(evlist, counter) {
try_again:
- if (perf_evsel__open(counter, top->evlist->cpus,
- top->evlist->threads) < 0) {
+ if (evsel__open(counter, top->evlist->core.cpus,
+ top->evlist->core.threads) < 0) {
/*
* Specially handle overwrite fall back.
@@ -1100,11 +1121,11 @@ static int deliver_event(struct ordered_events *qe,
struct ordered_event *qevent)
{
struct perf_top *top = qe->data;
- struct perf_evlist *evlist = top->evlist;
+ struct evlist *evlist = top->evlist;
struct perf_session *session = top->session;
union perf_event *event = qevent->event;
struct perf_sample sample;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct machine *machine;
int ret = -1;
@@ -1123,8 +1144,11 @@ static int deliver_event(struct ordered_events *qe,
evsel = perf_evlist__id2evsel(session->evlist, sample.id);
assert(evsel != NULL);
- if (event->header.type == PERF_RECORD_SAMPLE)
+ if (event->header.type == PERF_RECORD_SAMPLE) {
+ if (evswitch__discard(&top->evswitch, evsel))
+ return 0;
++top->samples;
+ }
switch (sample.cpumode) {
case PERF_RECORD_MISC_USER:
@@ -1222,7 +1246,7 @@ static int __cmd_top(struct perf_top *top)
pr_debug("Couldn't synthesize BPF events: Pre-existing BPF programs won't have symbols resolved.\n");
machine__synthesize_threads(&top->session->machines.host, &opts->target,
- top->evlist->threads, false,
+ top->evlist->core.threads, false,
top->nr_threads_synthesize);
if (top->nr_threads_synthesize > 1)
@@ -1255,7 +1279,7 @@ static int __cmd_top(struct perf_top *top)
* so leave the check here.
*/
if (!target__none(&opts->target))
- perf_evlist__enable(top->evlist);
+ evlist__enable(top->evlist);
ret = -1;
if (pthread_create(&thread_process, NULL, process_thread, top)) {
@@ -1509,9 +1533,10 @@ int cmd_top(int argc, const char **argv)
"number of thread to run event synthesize"),
OPT_BOOLEAN(0, "namespaces", &opts->record_namespaces,
"Record namespaces events"),
+ OPTS_EVSWITCH(&top.evswitch),
OPT_END()
};
- struct perf_evlist *sb_evlist = NULL;
+ struct evlist *sb_evlist = NULL;
const char * const top_usage[] = {
"perf top [<options>]",
NULL
@@ -1524,7 +1549,7 @@ int cmd_top(int argc, const char **argv)
top.annotation_opts.min_pcnt = 5;
top.annotation_opts.context = 4;
- top.evlist = perf_evlist__new();
+ top.evlist = evlist__new();
if (top.evlist == NULL)
return -ENOMEM;
@@ -1536,12 +1561,16 @@ int cmd_top(int argc, const char **argv)
if (argc)
usage_with_options(top_usage, options);
- if (!top.evlist->nr_entries &&
+ if (!top.evlist->core.nr_entries &&
perf_evlist__add_default(top.evlist) < 0) {
pr_err("Not enough memory for event selector list\n");
goto out_delete_evlist;
}
+ status = evswitch__init(&top.evswitch, top.evlist, stderr);
+ if (status)
+ goto out_delete_evlist;
+
if (symbol_conf.report_hierarchy) {
/* disable incompatible options */
symbol_conf.event_group = false;
@@ -1661,7 +1690,7 @@ int cmd_top(int argc, const char **argv)
perf_evlist__stop_sb_thread(sb_evlist);
out_delete_evlist:
- perf_evlist__delete(top.evlist);
+ evlist__delete(top.evlist);
perf_session__delete(top.session);
return status;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4f0bbffee05f..0f633f0d6be8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0-only
/*
* builtin-trace.c
*
@@ -15,6 +14,7 @@
* http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
*/
+#include "util/record.h"
#include <traceevent/event-parse.h>
#include <api/fs/tracing_path.h>
#include <bpf/bpf.h>
@@ -25,9 +25,12 @@
#include "util/color.h"
#include "util/config.h"
#include "util/debug.h"
+#include "util/dso.h"
#include "util/env.h"
#include "util/event.h"
#include "util/evlist.h"
+#include "util/evswitch.h"
+#include <subcmd/pager.h>
#include <subcmd/exec-cmd.h>
#include "util/machine.h"
#include "util/map.h"
@@ -40,6 +43,8 @@
#include "util/intlist.h"
#include "util/thread_map.h"
#include "util/stat.h"
+#include "util/tool.h"
+#include "util/util.h"
#include "trace/beauty/beauty.h"
#include "trace-event.h"
#include "util/parse-events.h"
@@ -49,6 +54,7 @@
#include "string2.h"
#include "syscalltbl.h"
#include "rb_resort.h"
+#include "../perf.h"
#include <errno.h>
#include <inttypes.h>
@@ -80,28 +86,34 @@ struct trace {
struct perf_tool tool;
struct syscalltbl *sctbl;
struct {
- int max;
struct syscall *table;
struct bpf_map *map;
+ struct { // per syscall BPF_MAP_TYPE_PROG_ARRAY
+ struct bpf_map *sys_enter,
+ *sys_exit;
+ } prog_array;
struct {
- struct perf_evsel *sys_enter,
+ struct evsel *sys_enter,
*sys_exit,
*augmented;
} events;
+ struct bpf_program *unaugmented_prog;
} syscalls;
struct {
struct bpf_map *map;
} dump;
struct record_opts opts;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct machine *host;
struct thread *current;
+ struct bpf_object *bpf_obj;
struct cgroup *cgroup;
u64 base_time;
FILE *output;
unsigned long nr_events;
unsigned long nr_events_printed;
unsigned long max_events;
+ struct evswitch evswitch;
struct strlist *ev_qualifier;
struct {
size_t nr;
@@ -122,6 +134,7 @@ struct trace {
unsigned int min_stack;
int raw_augmented_syscalls_args_size;
bool raw_augmented_syscalls;
+ bool fd_path_disabled;
bool sort_events;
bool not_ev_qualifier;
bool live;
@@ -237,7 +250,7 @@ struct syscall_tp {
};
};
-static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
+static int perf_evsel__init_tp_uint_field(struct evsel *evsel,
struct tp_field *field,
const char *name)
{
@@ -253,7 +266,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
({ struct syscall_tp *sc = evsel->priv;\
perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
-static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
+static int perf_evsel__init_tp_ptr_field(struct evsel *evsel,
struct tp_field *field,
const char *name)
{
@@ -269,13 +282,13 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
({ struct syscall_tp *sc = evsel->priv;\
perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
-static void perf_evsel__delete_priv(struct perf_evsel *evsel)
+static void evsel__delete_priv(struct evsel *evsel)
{
zfree(&evsel->priv);
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
}
-static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel)
+static int perf_evsel__init_syscall_tp(struct evsel *evsel)
{
struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
@@ -292,7 +305,7 @@ out_delete:
return -ENOENT;
}
-static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel, struct perf_evsel *tp)
+static int perf_evsel__init_augmented_syscall_tp(struct evsel *evsel, struct evsel *tp)
{
struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
@@ -314,21 +327,21 @@ out_delete:
return -EINVAL;
}
-static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
+static int perf_evsel__init_augmented_syscall_tp_args(struct evsel *evsel)
{
struct syscall_tp *sc = evsel->priv;
return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
}
-static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel)
+static int perf_evsel__init_augmented_syscall_tp_ret(struct evsel *evsel)
{
struct syscall_tp *sc = evsel->priv;
return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap);
}
-static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
+static int perf_evsel__init_raw_syscall_tp(struct evsel *evsel, void *handler)
{
evsel->priv = malloc(sizeof(struct syscall_tp));
if (evsel->priv != NULL) {
@@ -346,9 +359,9 @@ out_delete:
return -ENOENT;
}
-static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler)
+static struct evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler)
{
- struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
+ struct evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
if (IS_ERR(evsel))
@@ -363,7 +376,7 @@ static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, v
return evsel;
out_delete:
- perf_evsel__delete_priv(evsel);
+ evsel__delete_priv(evsel);
return NULL;
}
@@ -688,6 +701,10 @@ struct syscall_arg_fmt {
static struct syscall_fmt {
const char *name;
const char *alias;
+ struct {
+ const char *sys_enter,
+ *sys_exit;
+ } bpf_prog_name;
struct syscall_arg_fmt arg[6];
u8 nr_args;
bool errpid;
@@ -700,7 +717,9 @@ static struct syscall_fmt {
.arg = { [0] = { .scnprintf = SCA_X86_ARCH_PRCTL_CODE, /* code */ },
[1] = { .scnprintf = SCA_PTR, /* arg2 */ }, }, },
{ .name = "bind",
- .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, },
+ .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ },
+ [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ },
+ [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, },
{ .name = "bpf",
.arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
{ .name = "brk", .hexret = true,
@@ -716,7 +735,9 @@ static struct syscall_fmt {
{ .name = "close",
.arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
{ .name = "connect",
- .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, },
+ .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ },
+ [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ },
+ [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, },
{ .name = "epoll_ctl",
.arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
{ .name = "eventfd2",
@@ -882,6 +903,7 @@ static struct syscall_fmt {
.arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
[1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
{ .name = "select", .timeout = true, },
+ { .name = "sendfile", .alias = "sendfile64", },
{ .name = "sendmmsg",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "sendmsg",
@@ -960,13 +982,19 @@ static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
* is_exit: is this "exit" or "exit_group"?
* is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
* args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
+ * nonexistent: Just a hole in the syscall table, syscall id not allocated
*/
struct syscall {
struct tep_event *tp_format;
int nr_args;
int args_size;
+ struct {
+ struct bpf_program *sys_enter,
+ *sys_exit;
+ } bpf_prog;
bool is_exit;
bool is_open;
+ bool nonexistent;
struct tep_format_field *args;
const char *name;
struct syscall_fmt *fmt;
@@ -1163,7 +1191,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
{
struct thread_trace *ttrace = thread__priv(thread);
- if (ttrace == NULL)
+ if (ttrace == NULL || trace->fd_path_disabled)
return NULL;
if (fd < 0)
@@ -1359,7 +1387,7 @@ static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long l
if (symbol_conf.kptr_restrict) {
pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
- "Check /proc/sys/kernel/kptr_restrict.\n\n"
+ "Check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
"Kernel samples will not be resolved.\n");
machine->kptr_restrict_warned = true;
return NULL;
@@ -1368,7 +1396,7 @@ static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long l
return machine__resolve_kernel_addr(vmachine, addrp, modp);
}
-static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
+static int trace__symbols_init(struct trace *trace, struct evlist *evlist)
{
int err = symbol__init(NULL);
@@ -1384,7 +1412,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
goto out;
err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
- evlist->threads, trace__tool_process, false,
+ evlist->core.threads, trace__tool_process, false,
1);
out:
if (err)
@@ -1471,29 +1499,22 @@ static int trace__read_syscall_info(struct trace *trace, int id)
struct syscall *sc;
const char *name = syscalltbl__name(trace->sctbl, id);
- if (name == NULL)
- return -1;
-
- if (id > trace->syscalls.max) {
- struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
-
- if (nsyscalls == NULL)
- return -1;
+ if (trace->syscalls.table == NULL) {
+ trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
+ if (trace->syscalls.table == NULL)
+ return -ENOMEM;
+ }
- if (trace->syscalls.max != -1) {
- memset(nsyscalls + trace->syscalls.max + 1, 0,
- (id - trace->syscalls.max) * sizeof(*sc));
- } else {
- memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
- }
+ sc = trace->syscalls.table + id;
+ if (sc->nonexistent)
+ return 0;
- trace->syscalls.table = nsyscalls;
- trace->syscalls.max = id;
+ if (name == NULL) {
+ sc->nonexistent = true;
+ return 0;
}
- sc = trace->syscalls.table + id;
sc->name = name;
-
sc->fmt = syscall_fmt__find(sc->name);
snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
@@ -1505,10 +1526,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
}
if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
- return -1;
+ return -ENOMEM;
if (IS_ERR(sc->tp_format))
- return -1;
+ return PTR_ERR(sc->tp_format);
sc->args = sc->tp_format->format.fields;
/*
@@ -1527,6 +1548,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
return syscall__set_arg_fmts(sc);
}
+static int intcmp(const void *a, const void *b)
+{
+ const int *one = a, *another = b;
+
+ return *one - *another;
+}
+
static int trace__validate_ev_qualifier(struct trace *trace)
{
int err = 0;
@@ -1590,6 +1618,7 @@ matches:
}
trace->ev_qualifier_ids.nr = nr_used;
+ qsort(trace->ev_qualifier_ids.entries, nr_used, sizeof(int), intcmp);
out:
if (printed_invalid_prefix)
pr_debug("\n");
@@ -1600,6 +1629,22 @@ out_free:
goto out;
}
+static __maybe_unused bool trace__syscall_enabled(struct trace *trace, int id)
+{
+ bool in_ev_qualifier;
+
+ if (trace->ev_qualifier_ids.nr == 0)
+ return true;
+
+ in_ev_qualifier = bsearch(&id, trace->ev_qualifier_ids.entries,
+ trace->ev_qualifier_ids.nr, sizeof(int), intcmp) != NULL;
+
+ if (in_ev_qualifier)
+ return !trace->not_ev_qualifier;
+
+ return trace->not_ev_qualifier;
+}
+
/*
* args is to be interpreted as a series of longs but we need to handle
* 8-byte unaligned accesses. args points to raw_data within the event
@@ -1738,13 +1783,14 @@ next_arg:
return printed;
}
-typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
+typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
union perf_event *event,
struct perf_sample *sample);
static struct syscall *trace__syscall_info(struct trace *trace,
- struct perf_evsel *evsel, int id)
+ struct evsel *evsel, int id)
{
+ int err = 0;
if (id < 0) {
@@ -1766,19 +1812,28 @@ static struct syscall *trace__syscall_info(struct trace *trace,
return NULL;
}
- if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
- trace__read_syscall_info(trace, id))
+ err = -EINVAL;
+
+ if (id > trace->sctbl->syscalls.max_id)
+ goto out_cant_read;
+
+ if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
+ (err = trace__read_syscall_info(trace, id)) != 0)
goto out_cant_read;
- if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
+ if (trace->syscalls.table[id].name == NULL) {
+ if (trace->syscalls.table[id].nonexistent)
+ return NULL;
goto out_cant_read;
+ }
return &trace->syscalls.table[id];
out_cant_read:
if (verbose > 0) {
- fprintf(trace->output, "Problems reading syscall %d", id);
- if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
+ char sbuf[STRERR_BUFSIZE];
+ fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
+ if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
fputs(" information\n", trace->output);
}
@@ -1839,7 +1894,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
return printed;
}
-static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
+static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel,
struct perf_sample *sample, struct thread *thread)
{
int printed = 0;
@@ -1882,7 +1937,7 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
return augmented_args;
}
-static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
+static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -1961,7 +2016,7 @@ out_put:
return err;
}
-static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evsel,
+static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
struct perf_sample *sample)
{
struct thread_trace *ttrace;
@@ -1994,13 +2049,13 @@ out_put:
return err;
}
-static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
+static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel,
struct perf_sample *sample,
struct callchain_cursor *cursor)
{
struct addr_location al;
- int max_stack = evsel->attr.sample_max_stack ?
- evsel->attr.sample_max_stack :
+ int max_stack = evsel->core.attr.sample_max_stack ?
+ evsel->core.attr.sample_max_stack :
trace->max_stack;
int err;
@@ -2022,7 +2077,7 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam
return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
}
-static const char *errno_to_name(struct perf_evsel *evsel, int err)
+static const char *errno_to_name(struct evsel *evsel, int err)
{
struct perf_env *env = perf_evsel__env(evsel);
const char *arch_name = perf_env__arch(env);
@@ -2030,7 +2085,7 @@ static const char *errno_to_name(struct perf_evsel *evsel, int err)
return arch_syscalls__strerrno(arch_name, err);
}
-static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
+static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -2058,7 +2113,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
- if (sc->is_open && ret >= 0 && ttrace->filename.pending_open) {
+ if (!trace->fd_path_disabled && sc->is_open && ret >= 0 && ttrace->filename.pending_open) {
trace__set_fd_pathname(thread, ret, ttrace->filename.name);
ttrace->filename.pending_open = false;
++trace->stats.vfs_getname;
@@ -2164,7 +2219,7 @@ out_put:
return err;
}
-static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
+static int trace__vfs_getname(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -2225,7 +2280,7 @@ out:
return 0;
}
-static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
+static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -2287,7 +2342,7 @@ static void bpf_output__fprintf(struct trace *trace,
++trace->nr_events_printed;
}
-static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
+static int trace__event_handler(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -2353,8 +2408,8 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
++trace->nr_events_printed;
if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) {
- perf_evsel__disable(evsel);
- perf_evsel__close(evsel);
+ evsel__disable(evsel);
+ evsel__close(evsel);
}
}
}
@@ -2389,7 +2444,7 @@ static void print_location(FILE *f, struct perf_sample *sample,
}
static int trace__pgfault(struct trace *trace,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@@ -2415,7 +2470,7 @@ static int trace__pgfault(struct trace *trace,
if (ttrace == NULL)
goto out_put;
- if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
+ if (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
ttrace->pfmaj++;
else
ttrace->pfmin++;
@@ -2428,7 +2483,7 @@ static int trace__pgfault(struct trace *trace,
trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output);
fprintf(trace->output, "%sfault [",
- evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
+ evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
"maj" : "min");
print_location(trace->output, sample, &al, false, true);
@@ -2464,7 +2519,7 @@ out_put:
}
static void trace__set_base_time(struct trace *trace,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
/*
@@ -2476,14 +2531,14 @@ static void trace__set_base_time(struct trace *trace,
* appears in our event stream (vfs_getname comes to mind).
*/
if (trace->base_time == 0 && !trace->full_time &&
- (evsel->attr.sample_type & PERF_SAMPLE_TIME))
+ (evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
trace->base_time = sample->time;
}
static int trace__process_sample(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine __maybe_unused)
{
struct trace *trace = container_of(tool, struct trace, tool);
@@ -2569,10 +2624,10 @@ static int trace__record(struct trace *trace, int argc, const char **argv)
static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
-static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
+static bool evlist__add_vfs_getname(struct evlist *evlist)
{
bool found = false;
- struct perf_evsel *evsel, *tmp;
+ struct evsel *evsel, *tmp;
struct parse_events_error err = { .idx = 0, };
int ret = parse_events(evlist, "probe:vfs_getname*", &err);
@@ -2589,17 +2644,17 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
continue;
}
- list_del_init(&evsel->node);
+ list_del_init(&evsel->core.node);
evsel->evlist = NULL;
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
}
return found;
}
-static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
+static struct evsel *perf_evsel__new_pgfault(u64 config)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.mmap_data = 1,
@@ -2610,7 +2665,7 @@ static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
event_attr_init(&attr);
- evsel = perf_evsel__new(&attr);
+ evsel = evsel__new(&attr);
if (evsel)
evsel->handler = trace__pgfault;
@@ -2620,7 +2675,7 @@ static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
{
const u32 type = event->header.type;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (type != PERF_RECORD_SAMPLE) {
trace__process_event(trace, trace->host, event, sample);
@@ -2633,9 +2688,12 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
return;
}
+ if (evswitch__discard(&trace->evswitch, evsel))
+ return;
+
trace__set_base_time(trace, evsel, sample);
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT &&
sample->raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample->tid,
@@ -2652,8 +2710,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
static int trace__add_syscall_newtp(struct trace *trace)
{
int ret = -1;
- struct perf_evlist *evlist = trace->evlist;
- struct perf_evsel *sys_enter, *sys_exit;
+ struct evlist *evlist = trace->evlist;
+ struct evsel *sys_enter, *sys_exit;
sys_enter = perf_evsel__raw_syscall_newtp("sys_enter", trace__sys_enter);
if (sys_enter == NULL)
@@ -2672,8 +2730,8 @@ static int trace__add_syscall_newtp(struct trace *trace)
perf_evsel__config_callchain(sys_enter, &trace->opts, &callchain_param);
perf_evsel__config_callchain(sys_exit, &trace->opts, &callchain_param);
- perf_evlist__add(evlist, sys_enter);
- perf_evlist__add(evlist, sys_exit);
+ evlist__add(evlist, sys_enter);
+ evlist__add(evlist, sys_exit);
if (callchain_param.enabled && !trace->kernel_syscallchains) {
/*
@@ -2681,7 +2739,7 @@ static int trace__add_syscall_newtp(struct trace *trace)
* leading to the syscall, allow overriding that for
* debugging reasons using --kernel_syscall_callchains
*/
- sys_exit->attr.exclude_callchain_kernel = 1;
+ sys_exit->core.attr.exclude_callchain_kernel = 1;
}
trace->syscalls.events.sys_enter = sys_enter;
@@ -2692,16 +2750,16 @@ out:
return ret;
out_delete_sys_exit:
- perf_evsel__delete_priv(sys_exit);
+ evsel__delete_priv(sys_exit);
out_delete_sys_enter:
- perf_evsel__delete_priv(sys_enter);
+ evsel__delete_priv(sys_enter);
goto out;
}
static int trace__set_ev_qualifier_tp_filter(struct trace *trace)
{
int err = -1;
- struct perf_evsel *sys_exit;
+ struct evsel *sys_exit;
char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
trace->ev_qualifier_ids.nr,
trace->ev_qualifier_ids.entries);
@@ -2724,6 +2782,70 @@ out_enomem:
}
#ifdef HAVE_LIBBPF_SUPPORT
+static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
+{
+ if (trace->bpf_obj == NULL)
+ return NULL;
+
+ return bpf_object__find_program_by_title(trace->bpf_obj, name);
+}
+
+static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc,
+ const char *prog_name, const char *type)
+{
+ struct bpf_program *prog;
+
+ if (prog_name == NULL) {
+ char default_prog_name[256];
+ scnprintf(default_prog_name, sizeof(default_prog_name), "!syscalls:sys_%s_%s", type, sc->name);
+ prog = trace__find_bpf_program_by_title(trace, default_prog_name);
+ if (prog != NULL)
+ goto out_found;
+ if (sc->fmt && sc->fmt->alias) {
+ scnprintf(default_prog_name, sizeof(default_prog_name), "!syscalls:sys_%s_%s", type, sc->fmt->alias);
+ prog = trace__find_bpf_program_by_title(trace, default_prog_name);
+ if (prog != NULL)
+ goto out_found;
+ }
+ goto out_unaugmented;
+ }
+
+ prog = trace__find_bpf_program_by_title(trace, prog_name);
+
+ if (prog != NULL) {
+out_found:
+ return prog;
+ }
+
+ pr_debug("Couldn't find BPF prog \"%s\" to associate with syscalls:sys_%s_%s, not augmenting it\n",
+ prog_name, type, sc->name);
+out_unaugmented:
+ return trace->syscalls.unaugmented_prog;
+}
+
+static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
+{
+ struct syscall *sc = trace__syscall_info(trace, NULL, id);
+
+ if (sc == NULL)
+ return;
+
+ sc->bpf_prog.sys_enter = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_enter : NULL, "enter");
+ sc->bpf_prog.sys_exit = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit : NULL, "exit");
+}
+
+static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
+{
+ struct syscall *sc = trace__syscall_info(trace, NULL, id);
+ return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->syscalls.unaugmented_prog);
+}
+
+static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
+{
+ struct syscall *sc = trace__syscall_info(trace, NULL, id);
+ return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->syscalls.unaugmented_prog);
+}
+
static void trace__init_bpf_map_syscall_args(struct trace *trace, int id, struct bpf_map_syscall_entry *entry)
{
struct syscall *sc = trace__syscall_info(trace, NULL, id);
@@ -2755,8 +2877,10 @@ static int trace__set_ev_qualifier_bpf_filter(struct trace *trace)
for (i = 0; i < trace->ev_qualifier_ids.nr; ++i) {
int key = trace->ev_qualifier_ids.entries[i];
- if (value.enabled)
+ if (value.enabled) {
trace__init_bpf_map_syscall_args(trace, key, &value);
+ trace__init_syscall_bpf_progs(trace, key);
+ }
err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
if (err)
@@ -2795,6 +2919,186 @@ static int trace__init_syscalls_bpf_map(struct trace *trace)
return __trace__init_syscalls_bpf_map(trace, enabled);
}
+
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
+{
+ struct tep_format_field *field, *candidate_field;
+ int id;
+
+ /*
+ * We're only interested in syscalls that have a pointer:
+ */
+ for (field = sc->args; field; field = field->next) {
+ if (field->flags & TEP_FIELD_IS_POINTER)
+ goto try_to_find_pair;
+ }
+
+ return NULL;
+
+try_to_find_pair:
+ for (id = 0; id < trace->sctbl->syscalls.nr_entries; ++id) {
+ struct syscall *pair = trace__syscall_info(trace, NULL, id);
+ struct bpf_program *pair_prog;
+ bool is_candidate = false;
+
+ if (pair == NULL || pair == sc ||
+ pair->bpf_prog.sys_enter == trace->syscalls.unaugmented_prog)
+ continue;
+
+ for (field = sc->args, candidate_field = pair->args;
+ field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
+ bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
+ candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
+
+ if (is_pointer) {
+ if (!candidate_is_pointer) {
+ // The candidate just doesn't copies our pointer arg, might copy other pointers we want.
+ continue;
+ }
+ } else {
+ if (candidate_is_pointer) {
+ // The candidate might copy a pointer we don't have, skip it.
+ goto next_candidate;
+ }
+ continue;
+ }
+
+ if (strcmp(field->type, candidate_field->type))
+ goto next_candidate;
+
+ is_candidate = true;
+ }
+
+ if (!is_candidate)
+ goto next_candidate;
+
+ /*
+ * Check if the tentative pair syscall augmenter has more pointers, if it has,
+ * then it may be collecting that and we then can't use it, as it would collect
+ * more than what is common to the two syscalls.
+ */
+ if (candidate_field) {
+ for (candidate_field = candidate_field->next; candidate_field; candidate_field = candidate_field->next)
+ if (candidate_field->flags & TEP_FIELD_IS_POINTER)
+ goto next_candidate;
+ }
+
+ pair_prog = pair->bpf_prog.sys_enter;
+ /*
+ * If the pair isn't enabled, then its bpf_prog.sys_enter will not
+ * have been searched for, so search it here and if it returns the
+ * unaugmented one, then ignore it, otherwise we'll reuse that BPF
+ * program for a filtered syscall on a non-filtered one.
+ *
+ * For instance, we have "!syscalls:sys_enter_renameat" and that is
+ * useful for "renameat2".
+ */
+ if (pair_prog == NULL) {
+ pair_prog = trace__find_syscall_bpf_prog(trace, pair, pair->fmt ? pair->fmt->bpf_prog_name.sys_enter : NULL, "enter");
+ if (pair_prog == trace->syscalls.unaugmented_prog)
+ goto next_candidate;
+ }
+
+ pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name);
+ return pair_prog;
+ next_candidate:
+ continue;
+ }
+
+ return NULL;
+}
+
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
+{
+ int map_enter_fd = bpf_map__fd(trace->syscalls.prog_array.sys_enter),
+ map_exit_fd = bpf_map__fd(trace->syscalls.prog_array.sys_exit);
+ int err = 0, key;
+
+ for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) {
+ int prog_fd;
+
+ if (!trace__syscall_enabled(trace, key))
+ continue;
+
+ trace__init_syscall_bpf_progs(trace, key);
+
+ // It'll get at least the "!raw_syscalls:unaugmented"
+ prog_fd = trace__bpf_prog_sys_enter_fd(trace, key);
+ err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
+ if (err)
+ break;
+ prog_fd = trace__bpf_prog_sys_exit_fd(trace, key);
+ err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
+ if (err)
+ break;
+ }
+
+ /*
+ * Now lets do a second pass looking for enabled syscalls without
+ * an augmenter that have a signature that is a superset of another
+ * syscall with an augmenter so that we can auto-reuse it.
+ *
+ * I.e. if we have an augmenter for the "open" syscall that has
+ * this signature:
+ *
+ * int open(const char *pathname, int flags, mode_t mode);
+ *
+ * I.e. that will collect just the first string argument, then we
+ * can reuse it for the 'creat' syscall, that has this signature:
+ *
+ * int creat(const char *pathname, mode_t mode);
+ *
+ * and for:
+ *
+ * int stat(const char *pathname, struct stat *statbuf);
+ * int lstat(const char *pathname, struct stat *statbuf);
+ *
+ * Because the 'open' augmenter will collect the first arg as a string,
+ * and leave alone all the other args, which already helps with
+ * beautifying 'stat' and 'lstat''s pathname arg.
+ *
+ * Then, in time, when 'stat' gets an augmenter that collects both
+ * first and second arg (this one on the raw_syscalls:sys_exit prog
+ * array tail call, then that one will be used.
+ */
+ for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) {
+ struct syscall *sc = trace__syscall_info(trace, NULL, key);
+ struct bpf_program *pair_prog;
+ int prog_fd;
+
+ if (sc == NULL || sc->bpf_prog.sys_enter == NULL)
+ continue;
+
+ /*
+ * For now we're just reusing the sys_enter prog, and if it
+ * already has an augmenter, we don't need to find one.
+ */
+ if (sc->bpf_prog.sys_enter != trace->syscalls.unaugmented_prog)
+ continue;
+
+ /*
+ * Look at all the other syscalls for one that has a signature
+ * that is close enough that we can share:
+ */
+ pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
+ if (pair_prog == NULL)
+ continue;
+
+ sc->bpf_prog.sys_enter = pair_prog;
+
+ /*
+ * Update the BPF_MAP_TYPE_PROG_SHARED for raw_syscalls:sys_enter
+ * with the fd for the program we're reusing:
+ */
+ prog_fd = bpf_program__fd(sc->bpf_prog.sys_enter);
+ err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
+ if (err)
+ break;
+ }
+
+
+ return err;
+}
#else
static int trace__set_ev_qualifier_bpf_filter(struct trace *trace __maybe_unused)
{
@@ -2805,6 +3109,17 @@ static int trace__init_syscalls_bpf_map(struct trace *trace __maybe_unused)
{
return 0;
}
+
+static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace __maybe_unused,
+ const char *name __maybe_unused)
+{
+ return NULL;
+}
+
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace __maybe_unused)
+{
+ return 0;
+}
#endif // HAVE_LIBBPF_SUPPORT
static int trace__set_ev_qualifier_filter(struct trace *trace)
@@ -2879,7 +3194,7 @@ static int trace__set_filter_pids(struct trace *trace)
err = bpf_map__set_filter_pids(trace->filter_pids.map, trace->filter_pids.nr,
trace->filter_pids.entries);
}
- } else if (thread_map__pid(trace->evlist->threads, 0) == -1) {
+ } else if (perf_thread_map__pid(trace->evlist->core.threads, 0) == -1) {
err = trace__set_filter_loop_pids(trace);
}
@@ -2888,7 +3203,7 @@ static int trace__set_filter_pids(struct trace *trace)
static int __trace__deliver_event(struct trace *trace, union perf_event *event)
{
- struct perf_evlist *evlist = trace->evlist;
+ struct evlist *evlist = trace->evlist;
struct perf_sample sample;
int err;
@@ -2946,8 +3261,8 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
static int trace__run(struct trace *trace, int argc, const char **argv)
{
- struct perf_evlist *evlist = trace->evlist;
- struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
+ struct evlist *evlist = trace->evlist;
+ struct evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
int err = -1, i;
unsigned long before;
const bool forks = argc > 0;
@@ -2960,7 +3275,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out_error_raw_syscalls;
if (trace->trace_syscalls)
- trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
+ trace->vfs_getname = evlist__add_vfs_getname(evlist);
}
if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
@@ -2968,7 +3283,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (pgfault_maj == NULL)
goto out_error_mem;
perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
- perf_evlist__add(evlist, pgfault_maj);
+ evlist__add(evlist, pgfault_maj);
}
if ((trace->trace_pgfaults & TRACE_PFMIN)) {
@@ -2976,7 +3291,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (pgfault_min == NULL)
goto out_error_mem;
perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
- perf_evlist__add(evlist, pgfault_min);
+ evlist__add(evlist, pgfault_min);
}
if (trace->sched &&
@@ -3038,7 +3353,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
}
}
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0)
goto out_error_open;
@@ -3059,6 +3374,9 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (trace->syscalls.map)
trace__init_syscalls_bpf_map(trace);
+ if (trace->syscalls.prog_array.sys_enter)
+ trace__init_syscalls_bpf_prog_array_maps(trace);
+
if (trace->ev_qualifier_ids.nr > 0) {
err = trace__set_ev_qualifier_filter(trace);
if (err < 0)
@@ -3070,6 +3388,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
}
}
+ /*
+ * If the "close" syscall is not traced, then we will not have the
+ * opportunity to, in syscall_arg__scnprintf_close_fd() invalidate the
+ * fd->pathname table and were ending up showing the last value set by
+ * syscalls opening a pathname and associating it with a descriptor or
+ * reading it from /proc/pid/fd/ in cases where that doesn't make
+ * sense.
+ *
+ * So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is
+ * not in use.
+ */
+ trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close"));
+
err = perf_evlist__apply_filters(evlist, &evsel);
if (err < 0)
goto out_error_apply_filters;
@@ -3082,30 +3413,30 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out_error_mmap;
if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
if (forks)
perf_evlist__start_workload(evlist);
if (trace->opts.initial_delay) {
usleep(trace->opts.initial_delay * 1000);
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
}
- trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
- evlist->threads->nr > 1 ||
- perf_evlist__first(evlist)->attr.inherit;
+ trace->multiple_threads = perf_thread_map__pid(evlist->core.threads, 0) == -1 ||
+ evlist->core.threads->nr > 1 ||
+ perf_evlist__first(evlist)->core.attr.inherit;
/*
- * Now that we already used evsel->attr to ask the kernel to setup the
- * events, lets reuse evsel->attr.sample_max_stack as the limit in
+ * Now that we already used evsel->core.attr to ask the kernel to setup the
+ * events, lets reuse evsel->core.attr.sample_max_stack as the limit in
* trace__resolve_callchain(), allowing per-event max-stack settings
* to override an explicitly set --max-stack global setting.
*/
evlist__for_each_entry(evlist, evsel) {
if (evsel__has_callchain(evsel) &&
- evsel->attr.sample_max_stack == 0)
- evsel->attr.sample_max_stack = trace->max_stack;
+ evsel->core.attr.sample_max_stack == 0)
+ evsel->core.attr.sample_max_stack = trace->max_stack;
}
again:
before = trace->nr_events;
@@ -3131,7 +3462,7 @@ again:
goto out_disable;
if (done && !draining) {
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
draining = true;
}
}
@@ -3157,7 +3488,7 @@ again:
out_disable:
thread__zput(trace->current);
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
if (trace->sort_events)
ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL);
@@ -3178,7 +3509,7 @@ out_disable:
out_delete_evlist:
trace__symbols__exit(trace);
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
cgroup__put(trace->cgroup);
trace->evlist = NULL;
trace->live = false;
@@ -3223,7 +3554,7 @@ out_errno:
static int trace__replay(struct trace *trace)
{
- const struct perf_evsel_str_handler handlers[] = {
+ const struct evsel_str_handler handlers[] = {
{ "probe:vfs_getname", trace__vfs_getname, },
};
struct perf_data data = {
@@ -3232,7 +3563,7 @@ static int trace__replay(struct trace *trace)
.force = trace->force,
};
struct perf_session *session;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err = -1;
trace->tool.sample = trace__process_sample;
@@ -3298,10 +3629,10 @@ static int trace__replay(struct trace *trace)
}
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
- (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
- evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
- evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
+ if (evsel->core.attr.type == PERF_TYPE_SOFTWARE &&
+ (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
+ evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
+ evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS))
evsel->handler = trace__pgfault;
}
@@ -3523,17 +3854,17 @@ static int parse_pagefaults(const struct option *opt, const char *str,
return 0;
}
-static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
+static void evlist__set_evsel_handler(struct evlist *evlist, void *handler)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel)
evsel->handler = handler;
}
-static int evlist__set_syscall_tp_fields(struct perf_evlist *evlist)
+static int evlist__set_syscall_tp_fields(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (evsel->priv || !evsel->tp_format)
@@ -3660,7 +3991,7 @@ static int trace__parse_cgroups(const struct option *opt, const char *str, int u
{
struct trace *trace = opt->value;
- if (!list_empty(&trace->evlist->entries))
+ if (!list_empty(&trace->evlist->core.entries))
return parse_cgroups(opt, str, unset);
trace->cgroup = evlist__findnew_cgroup(trace->evlist, str);
@@ -3668,28 +3999,24 @@ static int trace__parse_cgroups(const struct option *opt, const char *str, int u
return 0;
}
-static struct bpf_map *bpf__find_map_by_name(const char *name)
+static struct bpf_map *trace__find_bpf_map_by_name(struct trace *trace, const char *name)
{
- struct bpf_object *obj, *tmp;
-
- bpf_object__for_each_safe(obj, tmp) {
- struct bpf_map *map = bpf_object__find_map_by_name(obj, name);
- if (map)
- return map;
-
- }
+ if (trace->bpf_obj == NULL)
+ return NULL;
- return NULL;
+ return bpf_object__find_map_by_name(trace->bpf_obj, name);
}
static void trace__set_bpf_map_filtered_pids(struct trace *trace)
{
- trace->filter_pids.map = bpf__find_map_by_name("pids_filtered");
+ trace->filter_pids.map = trace__find_bpf_map_by_name(trace, "pids_filtered");
}
static void trace__set_bpf_map_syscalls(struct trace *trace)
{
- trace->syscalls.map = bpf__find_map_by_name("syscalls");
+ trace->syscalls.map = trace__find_bpf_map_by_name(trace, "syscalls");
+ trace->syscalls.prog_array.sys_enter = trace__find_bpf_map_by_name(trace, "syscalls_sys_enter");
+ trace->syscalls.prog_array.sys_exit = trace__find_bpf_map_by_name(trace, "syscalls_sys_exit");
}
static int trace__config(const char *var, const char *value, void *arg)
@@ -3745,9 +4072,6 @@ int cmd_trace(int argc, const char **argv)
NULL
};
struct trace trace = {
- .syscalls = {
- . max = -1,
- },
.opts = {
.target = {
.uid = UINT_MAX,
@@ -3844,11 +4168,12 @@ int cmd_trace(int argc, const char **argv)
OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
"ms to wait before starting measurement after program "
"start"),
+ OPTS_EVSWITCH(&trace.evswitch),
OPT_END()
};
bool __maybe_unused max_stack_user_set = true;
bool mmap_pages_user_set = true;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
const char * const trace_subcommands[] = { "record", NULL };
int err = -1;
char bf[BUFSIZ];
@@ -3856,7 +4181,7 @@ int cmd_trace(int argc, const char **argv)
signal(SIGSEGV, sighandler_dump_stack);
signal(SIGFPE, sighandler_dump_stack);
- trace.evlist = perf_evlist__new();
+ trace.evlist = evlist__new();
trace.sctbl = syscalltbl__new();
if (trace.evlist == NULL || trace.sctbl == NULL) {
@@ -3895,8 +4220,23 @@ int cmd_trace(int argc, const char **argv)
if (evsel) {
trace.syscalls.events.augmented = evsel;
+
+ evsel = perf_evlist__find_tracepoint_by_name(trace.evlist, "raw_syscalls:sys_enter");
+ if (evsel == NULL) {
+ pr_err("ERROR: raw_syscalls:sys_enter not found in the augmented BPF object\n");
+ goto out;
+ }
+
+ if (evsel->bpf_obj == NULL) {
+ pr_err("ERROR: raw_syscalls:sys_enter not associated to a BPF object\n");
+ goto out;
+ }
+
+ trace.bpf_obj = evsel->bpf_obj;
+
trace__set_bpf_map_filtered_pids(&trace);
trace__set_bpf_map_syscalls(&trace);
+ trace.syscalls.unaugmented_prog = trace__find_bpf_program_by_title(&trace, "!raw_syscalls:unaugmented");
}
err = bpf__setup_stdout(trace.evlist);
@@ -3909,7 +4249,7 @@ int cmd_trace(int argc, const char **argv)
err = -1;
if (map_dump_str) {
- trace.dump.map = bpf__find_map_by_name(map_dump_str);
+ trace.dump.map = trace__find_bpf_map_by_name(&trace, map_dump_str);
if (trace.dump.map == NULL) {
pr_err("ERROR: BPF map \"%s\" not found\n", map_dump_str);
goto out;
@@ -3942,7 +4282,7 @@ int cmd_trace(int argc, const char **argv)
symbol_conf.use_callchain = true;
}
- if (trace.evlist->nr_entries > 0) {
+ if (trace.evlist->core.nr_entries > 0) {
evlist__set_evsel_handler(trace.evlist, trace__event_handler);
if (evlist__set_syscall_tp_fields(trace.evlist)) {
perror("failed to set syscalls:* tracepoint fields");
@@ -3977,11 +4317,26 @@ int cmd_trace(int argc, const char **argv)
if (trace.syscalls.events.augmented->priv == NULL &&
strstr(perf_evsel__name(evsel), "syscalls:sys_enter")) {
- struct perf_evsel *augmented = trace.syscalls.events.augmented;
+ struct evsel *augmented = trace.syscalls.events.augmented;
if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) ||
perf_evsel__init_augmented_syscall_tp_args(augmented))
goto out;
+ /*
+ * Augmented is __augmented_syscalls__ BPF_OUTPUT event
+ * Above we made sure we can get from the payload the tp fields
+ * that we get from syscalls:sys_enter tracefs format file.
+ */
augmented->handler = trace__sys_enter;
+ /*
+ * Now we do the same for the *syscalls:sys_enter event so that
+ * if we handle it directly, i.e. if the BPF prog returns 0 so
+ * as not to filter it, then we'll handle it just like we would
+ * for the BPF_OUTPUT one:
+ */
+ if (perf_evsel__init_augmented_syscall_tp(evsel, evsel) ||
+ perf_evsel__init_augmented_syscall_tp_args(evsel))
+ goto out;
+ evsel->handler = trace__sys_enter;
}
if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {
@@ -4025,7 +4380,7 @@ init_augmented_syscall_tp:
trace.summary = trace.summary_only;
if (!trace.trace_syscalls && !trace.trace_pgfaults &&
- trace.evlist->nr_entries == 0 /* Was --events used? */) {
+ trace.evlist->core.nr_entries == 0 /* Was --events used? */) {
trace.trace_syscalls = true;
}
@@ -4037,6 +4392,10 @@ init_augmented_syscall_tp:
}
}
+ err = evswitch__init(&trace.evswitch, trace.evlist, stderr);
+ if (err)
+ goto out_close;
+
err = target__validate(&trace.opts.target);
if (err) {
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
index bf114ca9ca87..05cf2af9e2c2 100644
--- a/tools/perf/builtin-version.c
+++ b/tools/perf/builtin-version.c
@@ -2,8 +2,8 @@
#include "builtin.h"
#include "perf.h"
#include "color.h"
-#include <linux/compiler.h>
#include <tools/config.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <subcmd/parse-options.h>
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 999fe9170122..14a2db622a7b 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -2,8 +2,6 @@
#ifndef BUILTIN_H
#define BUILTIN_H
-#include "util/util.h"
-
extern const char perf_usage_string[];
extern const char perf_more_info_string[];
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index f211c015cb76..e2e0f06c97d0 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -1,7 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-HEADERS='
+FILES='
+include/uapi/linux/const.h
include/uapi/drm/drm.h
include/uapi/drm/i915_drm.h
include/uapi/linux/fadvise.h
@@ -19,12 +20,16 @@ include/uapi/linux/usbdevice_fs.h
include/uapi/linux/vhost.h
include/uapi/sound/asound.h
include/linux/bits.h
+include/linux/const.h
include/linux/hash.h
include/uapi/linux/hw_breakpoint.h
arch/x86/include/asm/disabled-features.h
arch/x86/include/asm/required-features.h
arch/x86/include/asm/cpufeatures.h
+arch/x86/include/asm/inat_types.h
arch/x86/include/uapi/asm/prctl.h
+arch/x86/lib/x86-opcode-map.txt
+arch/x86/tools/gen-insn-attr-x86.awk
arch/arm/include/uapi/asm/perf_regs.h
arch/arm64/include/uapi/asm/perf_regs.h
arch/powerpc/include/uapi/asm/perf_regs.h
@@ -96,7 +101,7 @@ test -d ../../include || exit 0
cd ../..
# simple diff check
-for i in $HEADERS; do
+for i in $FILES; do
check $i -B
done
@@ -107,6 +112,10 @@ check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman
check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"'
check include/linux/ctype.h '-I "isdigit("'
check lib/ctype.c '-I "^EXPORT_SYMBOL" -I "^#include <linux/export.h>" -B'
+check arch/x86/include/asm/inat.h '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"'
+check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"'
+check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"'
+check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]"'
# diff non-symmetric files
check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c
index 2f822bb51717..b80437971d80 100644
--- a/tools/perf/examples/bpf/augmented_raw_syscalls.c
+++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c
@@ -16,6 +16,7 @@
#include <unistd.h>
#include <linux/limits.h>
+#include <linux/socket.h>
#include <pid_filter.h>
/* bpf-output associated map */
@@ -33,6 +34,20 @@ struct syscall {
bpf_map(syscalls, ARRAY, int, struct syscall, 512);
+/*
+ * What to augment at entry?
+ *
+ * Pointer arg payloads (filenames, etc) passed from userspace to the kernel
+ */
+bpf_map(syscalls_sys_enter, PROG_ARRAY, u32, u32, 512);
+
+/*
+ * What to augment at exit?
+ *
+ * Pointer arg payloads returned from the kernel (struct stat, etc) to userspace.
+ */
+bpf_map(syscalls_sys_exit, PROG_ARRAY, u32, u32, 512);
+
struct syscall_enter_args {
unsigned long long common_tp_fields;
long syscall_nr;
@@ -45,7 +60,7 @@ struct syscall_exit_args {
long ret;
};
-struct augmented_filename {
+struct augmented_arg {
unsigned int size;
int err;
char value[PATH_MAX];
@@ -53,45 +68,176 @@ struct augmented_filename {
pid_filter(pids_filtered);
-struct augmented_args_filename {
+struct augmented_args_payload {
struct syscall_enter_args args;
- struct augmented_filename filename;
+ union {
+ struct {
+ struct augmented_arg arg, arg2;
+ };
+ struct sockaddr_storage saddr;
+ };
};
-bpf_map(augmented_filename_map, PERCPU_ARRAY, int, struct augmented_args_filename, 1);
+// We need more tmp space than the BPF stack can give us
+bpf_map(augmented_args_tmp, PERCPU_ARRAY, int, struct augmented_args_payload, 1);
+
+static inline struct augmented_args_payload *augmented_args_payload(void)
+{
+ int key = 0;
+ return bpf_map_lookup_elem(&augmented_args_tmp, &key);
+}
+
+static inline int augmented__output(void *ctx, struct augmented_args_payload *args, int len)
+{
+ /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */
+ return perf_event_output(ctx, &__augmented_syscalls__, BPF_F_CURRENT_CPU, args, len);
+}
static inline
-unsigned int augmented_filename__read(struct augmented_filename *augmented_filename,
- const void *filename_arg, unsigned int filename_len)
+unsigned int augmented_arg__read_str(struct augmented_arg *augmented_arg, const void *arg, unsigned int arg_len)
{
- unsigned int len = sizeof(*augmented_filename);
- int size = probe_read_str(&augmented_filename->value, filename_len, filename_arg);
+ unsigned int augmented_len = sizeof(*augmented_arg);
+ int string_len = probe_read_str(&augmented_arg->value, arg_len, arg);
- augmented_filename->size = augmented_filename->err = 0;
+ augmented_arg->size = augmented_arg->err = 0;
/*
* probe_read_str may return < 0, e.g. -EFAULT
- * So we leave that in the augmented_filename->size that userspace will
+ * So we leave that in the augmented_arg->size that userspace will
*/
- if (size > 0) {
- len -= sizeof(augmented_filename->value) - size;
- len &= sizeof(augmented_filename->value) - 1;
- augmented_filename->size = size;
+ if (string_len > 0) {
+ augmented_len -= sizeof(augmented_arg->value) - string_len;
+ augmented_len &= sizeof(augmented_arg->value) - 1;
+ augmented_arg->size = string_len;
} else {
/*
* So that username notice the error while still being able
* to skip this augmented arg record
*/
- augmented_filename->err = size;
- len = offsetof(struct augmented_filename, value);
+ augmented_arg->err = string_len;
+ augmented_len = offsetof(struct augmented_arg, value);
}
- return len;
+ return augmented_len;
+}
+
+SEC("!raw_syscalls:unaugmented")
+int syscall_unaugmented(struct syscall_enter_args *args)
+{
+ return 1;
+}
+
+/*
+ * These will be tail_called from SEC("raw_syscalls:sys_enter"), so will find in
+ * augmented_args_tmp what was read by that raw_syscalls:sys_enter and go
+ * on from there, reading the first syscall arg as a string, i.e. open's
+ * filename.
+ */
+SEC("!syscalls:sys_enter_connect")
+int sys_enter_connect(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *sockaddr_arg = (const void *)args->args[1];
+ unsigned int socklen = args->args[2];
+ unsigned int len = sizeof(augmented_args->args);
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ if (socklen > sizeof(augmented_args->saddr))
+ socklen = sizeof(augmented_args->saddr);
+
+ probe_read(&augmented_args->saddr, socklen, sockaddr_arg);
+
+ return augmented__output(args, augmented_args, len + socklen);
+}
+
+SEC("!syscalls:sys_enter_sendto")
+int sys_enter_sendto(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *sockaddr_arg = (const void *)args->args[4];
+ unsigned int socklen = args->args[5];
+ unsigned int len = sizeof(augmented_args->args);
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ if (socklen > sizeof(augmented_args->saddr))
+ socklen = sizeof(augmented_args->saddr);
+
+ probe_read(&augmented_args->saddr, socklen, sockaddr_arg);
+
+ return augmented__output(args, augmented_args, len + socklen);
+}
+
+SEC("!syscalls:sys_enter_open")
+int sys_enter_open(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *filename_arg = (const void *)args->args[0];
+ unsigned int len = sizeof(augmented_args->args);
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ len += augmented_arg__read_str(&augmented_args->arg, filename_arg, sizeof(augmented_args->arg.value));
+
+ return augmented__output(args, augmented_args, len);
+}
+
+SEC("!syscalls:sys_enter_openat")
+int sys_enter_openat(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *filename_arg = (const void *)args->args[1];
+ unsigned int len = sizeof(augmented_args->args);
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ len += augmented_arg__read_str(&augmented_args->arg, filename_arg, sizeof(augmented_args->arg.value));
+
+ return augmented__output(args, augmented_args, len);
+}
+
+SEC("!syscalls:sys_enter_rename")
+int sys_enter_rename(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *oldpath_arg = (const void *)args->args[0],
+ *newpath_arg = (const void *)args->args[1];
+ unsigned int len = sizeof(augmented_args->args), oldpath_len;
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ oldpath_len = augmented_arg__read_str(&augmented_args->arg, oldpath_arg, sizeof(augmented_args->arg.value));
+ len += oldpath_len + augmented_arg__read_str((void *)(&augmented_args->arg) + oldpath_len, newpath_arg, sizeof(augmented_args->arg.value));
+
+ return augmented__output(args, augmented_args, len);
+}
+
+SEC("!syscalls:sys_enter_renameat")
+int sys_enter_renameat(struct syscall_enter_args *args)
+{
+ struct augmented_args_payload *augmented_args = augmented_args_payload();
+ const void *oldpath_arg = (const void *)args->args[1],
+ *newpath_arg = (const void *)args->args[3];
+ unsigned int len = sizeof(augmented_args->args), oldpath_len;
+
+ if (augmented_args == NULL)
+ return 1; /* Failure: don't filter */
+
+ oldpath_len = augmented_arg__read_str(&augmented_args->arg, oldpath_arg, sizeof(augmented_args->arg.value));
+ len += oldpath_len + augmented_arg__read_str((void *)(&augmented_args->arg) + oldpath_len, newpath_arg, sizeof(augmented_args->arg.value));
+
+ return augmented__output(args, augmented_args, len);
}
SEC("raw_syscalls:sys_enter")
int sys_enter(struct syscall_enter_args *args)
{
- struct augmented_args_filename *augmented_args;
+ struct augmented_args_payload *augmented_args;
/*
* We start len, the amount of data that will be in the perf ring
* buffer, if this is not filtered out by one of pid_filter__has(),
@@ -103,142 +249,46 @@ int sys_enter(struct syscall_enter_args *args)
*/
unsigned int len = sizeof(augmented_args->args);
struct syscall *syscall;
- int key = 0;
-
- augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
- if (augmented_args == NULL)
- return 1;
if (pid_filter__has(&pids_filtered, getpid()))
return 0;
+ augmented_args = augmented_args_payload();
+ if (augmented_args == NULL)
+ return 1;
+
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
- syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
- if (syscall == NULL || !syscall->enabled)
- return 0;
/*
- * Yonghong and Edward Cree sayz:
- *
- * https://www.spinics.net/lists/netdev/msg531645.html
- *
- * >> R0=inv(id=0) R1=inv2 R6=ctx(id=0,off=0,imm=0) R7=inv64 R10=fp0,call_-1
- * >> 10: (bf) r1 = r6
- * >> 11: (07) r1 += 16
- * >> 12: (05) goto pc+2
- * >> 15: (79) r3 = *(u64 *)(r1 +0)
- * >> dereference of modified ctx ptr R1 off=16 disallowed
- * > Aha, we at least got a different error message this time.
- * > And indeed llvm has done that optimisation, rather than the more obvious
- * > 11: r3 = *(u64 *)(r1 +16)
- * > because it wants to have lots of reads share a single insn. You may be able
- * > to defeat that optimisation by adding compiler barriers, idk. Maybe someone
- * > with llvm knowledge can figure out how to stop it (ideally, llvm would know
- * > when it's generating for bpf backend and not do that). -O0? ¯\_(ツ)_/¯
- *
- * The optimization mostly likes below:
- *
- * br1:
- * ...
- * r1 += 16
- * goto merge
- * br2:
- * ...
- * r1 += 20
- * goto merge
- * merge:
- * *(u64 *)(r1 + 0)
- *
- * The compiler tries to merge common loads. There is no easy way to
- * stop this compiler optimization without turning off a lot of other
- * optimizations. The easiest way is to add barriers:
- *
- * __asm__ __volatile__("": : :"memory")
- *
- * after the ctx memory access to prevent their down stream merging.
+ * Jump to syscall specific augmenter, even if the default one,
+ * "!raw_syscalls:unaugmented" that will just return 1 to return the
+ * unagmented tracepoint payload.
*/
- /*
- * For now copy just the first string arg, we need to improve the protocol
- * and have more than one.
- *
- * Using the unrolled loop is not working, only when we do it manually,
- * check this out later...
-
- u8 arg;
-#pragma clang loop unroll(full)
- for (arg = 0; arg < 6; ++arg) {
- if (syscall->string_args_len[arg] != 0) {
- filename_len = syscall->string_args_len[arg];
- filename_arg = (const void *)args->args[arg];
- __asm__ __volatile__("": : :"memory");
- break;
- }
- }
-
- verifier log:
-
-; if (syscall->string_args_len[arg] != 0) {
-37: (69) r3 = *(u16 *)(r0 +2)
- R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1_w=inv0 R2_w=map_value(id=0,off=2,ks=4,vs=14,imm=0) R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm
-; if (syscall->string_args_len[arg] != 0) {
-38: (55) if r3 != 0x0 goto pc+5
- R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1=inv0 R2=map_value(id=0,off=2,ks=4,vs=14,imm=0) R3=inv0 R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm
-39: (b7) r1 = 1
-; if (syscall->string_args_len[arg] != 0) {
-40: (bf) r2 = r0
-41: (07) r2 += 4
-42: (69) r3 = *(u16 *)(r0 +4)
- R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1_w=inv1 R2_w=map_value(id=0,off=4,ks=4,vs=14,imm=0) R3_w=inv0 R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm
-; if (syscall->string_args_len[arg] != 0) {
-43: (15) if r3 == 0x0 goto pc+32
- R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1=inv1 R2=map_value(id=0,off=4,ks=4,vs=14,imm=0) R3=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm
-; filename_arg = (const void *)args->args[arg];
-44: (67) r1 <<= 3
-45: (bf) r3 = r6
-46: (0f) r3 += r1
-47: (b7) r5 = 64
-48: (79) r3 = *(u64 *)(r3 +16)
-dereference of modified ctx ptr R3 off=8 disallowed
-processed 46 insns (limit 1000000) max_states_per_insn 0 total_states 12 peak_states 12 mark_read 7
- */
-
-#define __loop_iter(arg) \
- if (syscall->string_args_len[arg] != 0) { \
- unsigned int filename_len = syscall->string_args_len[arg]; \
- const void *filename_arg = (const void *)args->args[arg]; \
- if (filename_len <= sizeof(augmented_args->filename.value)) \
- len += augmented_filename__read(&augmented_args->filename, filename_arg, filename_len);
-#define loop_iter_first() __loop_iter(0); }
-#define loop_iter(arg) else __loop_iter(arg); }
-#define loop_iter_last(arg) else __loop_iter(arg); __asm__ __volatile__("": : :"memory"); }
-
- loop_iter_first()
- loop_iter(1)
- loop_iter(2)
- loop_iter(3)
- loop_iter(4)
- loop_iter_last(5)
+ bpf_tail_call(args, &syscalls_sys_enter, augmented_args->args.syscall_nr);
- /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */
- return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len);
+ // If not found on the PROG_ARRAY syscalls map, then we're filtering it:
+ return 0;
}
SEC("raw_syscalls:sys_exit")
int sys_exit(struct syscall_exit_args *args)
{
struct syscall_exit_args exit_args;
- struct syscall *syscall;
if (pid_filter__has(&pids_filtered, getpid()))
return 0;
probe_read(&exit_args, sizeof(exit_args), args);
-
- syscall = bpf_map_lookup_elem(&syscalls, &exit_args.syscall_nr);
- if (syscall == NULL || !syscall->enabled)
- return 0;
-
- return 1;
+ /*
+ * Jump to syscall specific return augmenter, even if the default one,
+ * "!raw_syscalls:unaugmented" that will just return 1 to return the
+ * unagmented tracepoint payload.
+ */
+ bpf_tail_call(args, &syscalls_sys_exit, exit_args.syscall_nr);
+ /*
+ * If not found on the PROG_ARRAY syscalls map, then we're filtering it:
+ */
+ return 0;
}
license(GPL);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
index 2eac6d804b2d..b422aeef5339 100644
--- a/tools/perf/include/bpf/bpf.h
+++ b/tools/perf/include/bpf/bpf.h
@@ -45,6 +45,8 @@ struct ____btf_map_##name __attribute__((section(".maps." #name), used)) \
static int (*bpf_map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags) = (void *)BPF_FUNC_map_update_elem;
static void *(*bpf_map_lookup_elem)(struct bpf_map *map, void *key) = (void *)BPF_FUNC_map_lookup_elem;
+static void (*bpf_tail_call)(void *ctx, void *map, int index) = (void *)BPF_FUNC_tail_call;
+
#define SEC(NAME) __attribute__((section(NAME), used))
#define probe(function, vars) \
diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build
new file mode 100644
index 000000000000..c31f1c111f8f
--- /dev/null
+++ b/tools/perf/lib/Build
@@ -0,0 +1,12 @@
+libperf-y += core.o
+libperf-y += cpumap.o
+libperf-y += threadmap.o
+libperf-y += evsel.o
+libperf-y += evlist.o
+libperf-y += zalloc.o
+libperf-y += xyarray.o
+libperf-y += lib.o
+
+$(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE
+ $(call rule_mkdir)
+ $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/lib/Documentation/Makefile b/tools/perf/lib/Documentation/Makefile
new file mode 100644
index 000000000000..586425a88795
--- /dev/null
+++ b/tools/perf/lib/Documentation/Makefile
@@ -0,0 +1,7 @@
+all:
+ rst2man man/libperf.rst > man/libperf.7
+ rst2pdf tutorial/tutorial.rst
+
+clean:
+ rm -f man/libperf.7
+ rm -f tutorial/tutorial.pdf
diff --git a/tools/perf/lib/Documentation/man/libperf.rst b/tools/perf/lib/Documentation/man/libperf.rst
new file mode 100644
index 000000000000..09a270fccb9c
--- /dev/null
+++ b/tools/perf/lib/Documentation/man/libperf.rst
@@ -0,0 +1,100 @@
+.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+libperf
+
+The libperf library provides an API to access the linux kernel perf
+events subsystem. It provides the following high level objects:
+
+ - struct perf_cpu_map
+ - struct perf_thread_map
+ - struct perf_evlist
+ - struct perf_evsel
+
+reference
+=========
+Function reference by header files:
+
+perf/core.h
+-----------
+.. code-block:: c
+
+ typedef int (\*libperf_print_fn_t)(enum libperf_print_level level,
+ const char \*, va_list ap);
+
+ void libperf_set_print(libperf_print_fn_t fn);
+
+perf/cpumap.h
+-------------
+.. code-block:: c
+
+ struct perf_cpu_map \*perf_cpu_map__dummy_new(void);
+ struct perf_cpu_map \*perf_cpu_map__new(const char \*cpu_list);
+ struct perf_cpu_map \*perf_cpu_map__read(FILE \*file);
+ struct perf_cpu_map \*perf_cpu_map__get(struct perf_cpu_map \*map);
+ void perf_cpu_map__put(struct perf_cpu_map \*map);
+ int perf_cpu_map__cpu(const struct perf_cpu_map \*cpus, int idx);
+ int perf_cpu_map__nr(const struct perf_cpu_map \*cpus);
+ perf_cpu_map__for_each_cpu(cpu, idx, cpus)
+
+perf/threadmap.h
+----------------
+.. code-block:: c
+
+ struct perf_thread_map \*perf_thread_map__new_dummy(void);
+ void perf_thread_map__set_pid(struct perf_thread_map \*map, int thread, pid_t pid);
+ char \*perf_thread_map__comm(struct perf_thread_map \*map, int thread);
+ struct perf_thread_map \*perf_thread_map__get(struct perf_thread_map \*map);
+ void perf_thread_map__put(struct perf_thread_map \*map);
+
+perf/evlist.h
+-------------
+.. code-block::
+
+ void perf_evlist__init(struct perf_evlist \*evlist);
+ void perf_evlist__add(struct perf_evlist \*evlist,
+ struct perf_evsel \*evsel);
+ void perf_evlist__remove(struct perf_evlist \*evlist,
+ struct perf_evsel \*evsel);
+ struct perf_evlist \*perf_evlist__new(void);
+ void perf_evlist__delete(struct perf_evlist \*evlist);
+ struct perf_evsel\* perf_evlist__next(struct perf_evlist \*evlist,
+ struct perf_evsel \*evsel);
+ int perf_evlist__open(struct perf_evlist \*evlist);
+ void perf_evlist__close(struct perf_evlist \*evlist);
+ void perf_evlist__enable(struct perf_evlist \*evlist);
+ void perf_evlist__disable(struct perf_evlist \*evlist);
+ perf_evlist__for_each_evsel(evlist, pos)
+ void perf_evlist__set_maps(struct perf_evlist \*evlist,
+ struct perf_cpu_map \*cpus,
+ struct perf_thread_map \*threads);
+
+perf/evsel.h
+------------
+.. code-block:: c
+
+ struct perf_counts_values {
+ union {
+ struct {
+ uint64_t val;
+ uint64_t ena;
+ uint64_t run;
+ };
+ uint64_t values[3];
+ };
+ };
+
+ void perf_evsel__init(struct perf_evsel \*evsel,
+ struct perf_event_attr \*attr);
+ struct perf_evsel \*perf_evsel__new(struct perf_event_attr \*attr);
+ void perf_evsel__delete(struct perf_evsel \*evsel);
+ int perf_evsel__open(struct perf_evsel \*evsel, struct perf_cpu_map \*cpus,
+ struct perf_thread_map \*threads);
+ void perf_evsel__close(struct perf_evsel \*evsel);
+ int perf_evsel__read(struct perf_evsel \*evsel, int cpu, int thread,
+ struct perf_counts_values \*count);
+ int perf_evsel__enable(struct perf_evsel \*evsel);
+ int perf_evsel__disable(struct perf_evsel \*evsel);
+ int perf_evsel__apply_filter(struct perf_evsel \*evsel, const char \*filter);
+ struct perf_cpu_map \*perf_evsel__cpus(struct perf_evsel \*evsel);
+ struct perf_thread_map \*perf_evsel__threads(struct perf_evsel \*evsel);
+ struct perf_event_attr \*perf_evsel__attr(struct perf_evsel \*evsel);
diff --git a/tools/perf/lib/Documentation/tutorial/tutorial.rst b/tools/perf/lib/Documentation/tutorial/tutorial.rst
new file mode 100644
index 000000000000..7be7bc27b385
--- /dev/null
+++ b/tools/perf/lib/Documentation/tutorial/tutorial.rst
@@ -0,0 +1,123 @@
+.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+libperf tutorial
+================
+
+Compile and install libperf from kernel sources
+===============================================
+.. code-block:: bash
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+ cd linux/tools/perf/lib
+ make
+ sudo make install prefix=/usr
+
+Libperf object
+==============
+The libperf library provides several high level objects:
+
+struct perf_cpu_map
+ Provides a cpu list abstraction.
+
+struct perf_thread_map
+ Provides a thread list abstraction.
+
+struct perf_evsel
+ Provides an abstraction for single a perf event.
+
+struct perf_evlist
+ Gathers several struct perf_evsel object and performs functions on all of them.
+
+The exported API binds these objects together,
+for full reference see the libperf.7 man page.
+
+Examples
+========
+Examples aim to explain libperf functionality on simple use cases.
+They are based in on a checked out linux kernel git tree:
+
+.. code-block:: bash
+
+ $ cd tools/perf/lib/Documentation/tutorial/
+ $ ls -d ex-*
+ ex-1-compile ex-2-evsel-stat ex-3-evlist-stat
+
+ex-1-compile example
+====================
+This example shows the basic usage of *struct perf_cpu_map*,
+how to create it and display its cpus:
+
+.. code-block:: bash
+
+ $ cd ex-1-compile/
+ $ make
+ gcc -o test test.c -lperf
+ $ ./test
+ 0 1 2 3 4 5 6 7
+
+
+The full code listing is here:
+
+.. code-block:: c
+
+ 1 #include <perf/cpumap.h>
+ 2
+ 3 int main(int argc, char **Argv)
+ 4 {
+ 5 struct perf_cpu_map *cpus;
+ 6 int cpu, tmp;
+ 7
+ 8 cpus = perf_cpu_map__new(NULL);
+ 9
+ 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus)
+ 11 fprintf(stdout, "%d ", cpu);
+ 12
+ 13 fprintf(stdout, "\n");
+ 14
+ 15 perf_cpu_map__put(cpus);
+ 16 return 0;
+ 17 }
+
+
+First you need to include the proper header to have *struct perf_cpumap*
+declaration and functions:
+
+.. code-block:: c
+
+ 1 #include <perf/cpumap.h>
+
+
+The *struct perf_cpumap* object is created by *perf_cpu_map__new* call.
+The *NULL* argument asks it to populate the object with the current online CPUs list:
+
+.. code-block:: c
+
+ 8 cpus = perf_cpu_map__new(NULL);
+
+This is paired with a *perf_cpu_map__put*, that drops its reference at the end, possibly deleting it.
+
+.. code-block:: c
+
+ 15 perf_cpu_map__put(cpus);
+
+The iteration through the *struct perf_cpumap* CPUs is done using the *perf_cpu_map__for_each_cpu*
+macro which requires 3 arguments:
+
+- cpu - the cpu numer
+- tmp - iteration helper variable
+- cpus - the *struct perf_cpumap* object
+
+.. code-block:: c
+
+ 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus)
+ 11 fprintf(stdout, "%d ", cpu);
+
+ex-2-evsel-stat example
+=======================
+
+TBD
+
+ex-3-evlist-stat example
+========================
+
+TBD
diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
new file mode 100644
index 000000000000..a67efb8d9d39
--- /dev/null
+++ b/tools/perf/lib/Makefile
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+# Most of this file is copied from tools/lib/bpf/Makefile
+
+LIBPERF_VERSION = 0
+LIBPERF_PATCHLEVEL = 0
+LIBPERF_EXTRAVERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+include $(srctree)/tools/scripts/Makefile.include
+include $(srctree)/tools/scripts/Makefile.arch
+
+ifeq ($(LP64), 1)
+ libdir_relative = lib64
+else
+ libdir_relative = lib
+endif
+
+prefix ?=
+libdir = $(prefix)/$(libdir_relative)
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
+
+ifeq ("$(origin V)", "command line")
+ VERBOSE = $(V)
+endif
+ifndef VERBOSE
+ VERBOSE = 0
+endif
+
+ifeq ($(VERBOSE),1)
+ Q =
+else
+ Q = @
+endif
+
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+ CFLAGS := $(EXTRA_CFLAGS)
+else
+ CFLAGS := -g -Wall
+endif
+
+INCLUDES = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(SRCARCH)/include/ -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi -I$(srctree)/tools/include/uapi
+
+# Append required CFLAGS
+override CFLAGS += $(EXTRA_WARNINGS)
+override CFLAGS += -Werror -Wall
+override CFLAGS += -fPIC
+override CFLAGS += $(INCLUDES)
+override CFLAGS += -fvisibility=hidden
+
+all:
+
+export srctree OUTPUT CC LD CFLAGS V
+export DESTDIR DESTDIR_SQ
+
+include $(srctree)/tools/build/Makefile.include
+
+VERSION_SCRIPT := libperf.map
+
+PATCHLEVEL = $(LIBPERF_PATCHLEVEL)
+EXTRAVERSION = $(LIBPERF_EXTRAVERSION)
+VERSION = $(LIBPERF_VERSION).$(LIBPERF_PATCHLEVEL).$(LIBPERF_EXTRAVERSION)
+
+LIBPERF_SO := $(OUTPUT)libperf.so.$(VERSION)
+LIBPERF_A := $(OUTPUT)libperf.a
+LIBPERF_IN := $(OUTPUT)libperf-in.o
+LIBPERF_PC := $(OUTPUT)libperf.pc
+
+LIBPERF_ALL := $(LIBPERF_A) $(OUTPUT)libperf.so*
+
+$(LIBPERF_IN): FORCE
+ $(Q)$(MAKE) $(build)=libperf
+
+$(LIBPERF_A): $(LIBPERF_IN)
+ $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN)
+
+$(LIBPERF_SO): $(LIBPERF_IN)
+ $(QUIET_LINK)$(CC) --shared -Wl,-soname,libperf.so \
+ -Wl,--version-script=$(VERSION_SCRIPT) $^ -o $@
+ @ln -sf $(@F) $(OUTPUT)libperf.so
+ @ln -sf $(@F) $(OUTPUT)libperf.so.$(LIBPERF_VERSION)
+
+
+libs: $(LIBPERF_A) $(LIBPERF_SO) $(LIBPERF_PC)
+
+all: fixdep
+ $(Q)$(MAKE) libs
+
+clean:
+ $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \
+ *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS $(LIBPERF_PC)
+ $(Q)$(MAKE) -C tests clean
+
+tests:
+ $(Q)$(MAKE) -C tests
+ $(Q)$(MAKE) -C tests run
+
+$(LIBPERF_PC):
+ $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \
+ -e "s|@LIBDIR@|$(libdir_SQ)|" \
+ -e "s|@VERSION@|$(VERSION)|" \
+ < libperf.pc.template > $@
+
+define do_install_mkdir
+ if [ ! -d '$(DESTDIR_SQ)$1' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \
+ fi
+endef
+
+define do_install
+ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+ fi; \
+ $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: libs
+ $(call QUIET_INSTALL, $(LIBPERF_ALL)) \
+ $(call do_install_mkdir,$(libdir_SQ)); \
+ cp -fpR $(LIBPERF_ALL) $(DESTDIR)$(libdir_SQ)
+
+install_headers:
+ $(call QUIET_INSTALL, headers) \
+ $(call do_install,include/perf/core.h,$(prefix)/include/perf,644); \
+ $(call do_install,include/perf/cpumap.h,$(prefix)/include/perf,644); \
+ $(call do_install,include/perf/threadmap.h,$(prefix)/include/perf,644); \
+ $(call do_install,include/perf/evlist.h,$(prefix)/include/perf,644); \
+ $(call do_install,include/perf/evsel.h,$(prefix)/include/perf,644);
+
+install_pkgconfig: $(LIBPERF_PC)
+ $(call QUIET_INSTALL, $(LIBPERF_PC)) \
+ $(call do_install,$(LIBPERF_PC),$(libdir_SQ)/pkgconfig,644)
+
+install: install_lib install_headers install_pkgconfig
+
+FORCE:
+
+.PHONY: all install clean tests FORCE
diff --git a/tools/perf/lib/core.c b/tools/perf/lib/core.c
new file mode 100644
index 000000000000..29d5e3348718
--- /dev/null
+++ b/tools/perf/lib/core.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define __printf(a, b) __attribute__((format(printf, a, b)))
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <perf/core.h>
+#include "internal.h"
+
+static int __base_pr(enum libperf_print_level level, const char *format,
+ va_list args)
+{
+ return vfprintf(stderr, format, args);
+}
+
+static libperf_print_fn_t __libperf_pr = __base_pr;
+
+void libperf_set_print(libperf_print_fn_t fn)
+{
+ __libperf_pr = fn;
+}
+
+__printf(2, 3)
+void libperf_print(enum libperf_print_level level, const char *format, ...)
+{
+ va_list args;
+
+ if (!__libperf_pr)
+ return;
+
+ va_start(args, format);
+ __libperf_pr(level, format, args);
+ va_end(args);
+}
diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c
new file mode 100644
index 000000000000..1f0e6f334237
--- /dev/null
+++ b/tools/perf/lib/cpumap.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <perf/cpumap.h>
+#include <stdlib.h>
+#include <linux/refcount.h>
+#include <internal/cpumap.h>
+#include <asm/bug.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <limits.h>
+
+struct perf_cpu_map *perf_cpu_map__dummy_new(void)
+{
+ struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
+
+ if (cpus != NULL) {
+ cpus->nr = 1;
+ cpus->map[0] = -1;
+ refcount_set(&cpus->refcnt, 1);
+ }
+
+ return cpus;
+}
+
+static void cpu_map__delete(struct perf_cpu_map *map)
+{
+ if (map) {
+ WARN_ONCE(refcount_read(&map->refcnt) != 0,
+ "cpu_map refcnt unbalanced\n");
+ free(map);
+ }
+}
+
+struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map)
+{
+ if (map)
+ refcount_inc(&map->refcnt);
+ return map;
+}
+
+void perf_cpu_map__put(struct perf_cpu_map *map)
+{
+ if (map && refcount_dec_and_test(&map->refcnt))
+ cpu_map__delete(map);
+}
+
+static struct perf_cpu_map *cpu_map__default_new(void)
+{
+ struct perf_cpu_map *cpus;
+ int nr_cpus;
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ if (nr_cpus < 0)
+ return NULL;
+
+ cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
+ if (cpus != NULL) {
+ int i;
+
+ for (i = 0; i < nr_cpus; ++i)
+ cpus->map[i] = i;
+
+ cpus->nr = nr_cpus;
+ refcount_set(&cpus->refcnt, 1);
+ }
+
+ return cpus;
+}
+
+static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
+{
+ size_t payload_size = nr_cpus * sizeof(int);
+ struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+
+ if (cpus != NULL) {
+ cpus->nr = nr_cpus;
+ memcpy(cpus->map, tmp_cpus, payload_size);
+ refcount_set(&cpus->refcnt, 1);
+ }
+
+ return cpus;
+}
+
+struct perf_cpu_map *perf_cpu_map__read(FILE *file)
+{
+ struct perf_cpu_map *cpus = NULL;
+ int nr_cpus = 0;
+ int *tmp_cpus = NULL, *tmp;
+ int max_entries = 0;
+ int n, cpu, prev;
+ char sep;
+
+ sep = 0;
+ prev = -1;
+ for (;;) {
+ n = fscanf(file, "%u%c", &cpu, &sep);
+ if (n <= 0)
+ break;
+ if (prev >= 0) {
+ int new_max = nr_cpus + cpu - prev - 1;
+
+ WARN_ONCE(new_max >= MAX_NR_CPUS, "Perf can support %d CPUs. "
+ "Consider raising MAX_NR_CPUS\n", MAX_NR_CPUS);
+
+ if (new_max >= max_entries) {
+ max_entries = new_max + MAX_NR_CPUS / 2;
+ tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+ if (tmp == NULL)
+ goto out_free_tmp;
+ tmp_cpus = tmp;
+ }
+
+ while (++prev < cpu)
+ tmp_cpus[nr_cpus++] = prev;
+ }
+ if (nr_cpus == max_entries) {
+ max_entries += MAX_NR_CPUS;
+ tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+ if (tmp == NULL)
+ goto out_free_tmp;
+ tmp_cpus = tmp;
+ }
+
+ tmp_cpus[nr_cpus++] = cpu;
+ if (n == 2 && sep == '-')
+ prev = cpu;
+ else
+ prev = -1;
+ if (n == 1 || sep == '\n')
+ break;
+ }
+
+ if (nr_cpus > 0)
+ cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+ else
+ cpus = cpu_map__default_new();
+out_free_tmp:
+ free(tmp_cpus);
+ return cpus;
+}
+
+static struct perf_cpu_map *cpu_map__read_all_cpu_map(void)
+{
+ struct perf_cpu_map *cpus = NULL;
+ FILE *onlnf;
+
+ onlnf = fopen("/sys/devices/system/cpu/online", "r");
+ if (!onlnf)
+ return cpu_map__default_new();
+
+ cpus = perf_cpu_map__read(onlnf);
+ fclose(onlnf);
+ return cpus;
+}
+
+struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
+{
+ struct perf_cpu_map *cpus = NULL;
+ unsigned long start_cpu, end_cpu = 0;
+ char *p = NULL;
+ int i, nr_cpus = 0;
+ int *tmp_cpus = NULL, *tmp;
+ int max_entries = 0;
+
+ if (!cpu_list)
+ return cpu_map__read_all_cpu_map();
+
+ /*
+ * must handle the case of empty cpumap to cover
+ * TOPOLOGY header for NUMA nodes with no CPU
+ * ( e.g., because of CPU hotplug)
+ */
+ if (!isdigit(*cpu_list) && *cpu_list != '\0')
+ goto out;
+
+ while (isdigit(*cpu_list)) {
+ p = NULL;
+ start_cpu = strtoul(cpu_list, &p, 0);
+ if (start_cpu >= INT_MAX
+ || (*p != '\0' && *p != ',' && *p != '-'))
+ goto invalid;
+
+ if (*p == '-') {
+ cpu_list = ++p;
+ p = NULL;
+ end_cpu = strtoul(cpu_list, &p, 0);
+
+ if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
+ goto invalid;
+
+ if (end_cpu < start_cpu)
+ goto invalid;
+ } else {
+ end_cpu = start_cpu;
+ }
+
+ WARN_ONCE(end_cpu >= MAX_NR_CPUS, "Perf can support %d CPUs. "
+ "Consider raising MAX_NR_CPUS\n", MAX_NR_CPUS);
+
+ for (; start_cpu <= end_cpu; start_cpu++) {
+ /* check for duplicates */
+ for (i = 0; i < nr_cpus; i++)
+ if (tmp_cpus[i] == (int)start_cpu)
+ goto invalid;
+
+ if (nr_cpus == max_entries) {
+ max_entries += MAX_NR_CPUS;
+ tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+ if (tmp == NULL)
+ goto invalid;
+ tmp_cpus = tmp;
+ }
+ tmp_cpus[nr_cpus++] = (int)start_cpu;
+ }
+ if (*p)
+ ++p;
+
+ cpu_list = p;
+ }
+
+ if (nr_cpus > 0)
+ cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+ else if (*cpu_list != '\0')
+ cpus = cpu_map__default_new();
+ else
+ cpus = perf_cpu_map__dummy_new();
+invalid:
+ free(tmp_cpus);
+out:
+ return cpus;
+}
+
+int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx)
+{
+ if (idx < cpus->nr)
+ return cpus->map[idx];
+
+ return -1;
+}
+
+int perf_cpu_map__nr(const struct perf_cpu_map *cpus)
+{
+ return cpus ? cpus->nr : 1;
+}
+
+bool perf_cpu_map__empty(const struct perf_cpu_map *map)
+{
+ return map ? map->map[0] == -1 : true;
+}
+
+int perf_cpu_map__idx(struct perf_cpu_map *cpus, int cpu)
+{
+ int i;
+
+ for (i = 0; i < cpus->nr; ++i) {
+ if (cpus->map[i] == cpu)
+ return i;
+ }
+
+ return -1;
+}
diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
new file mode 100644
index 000000000000..f4dc9a208332
--- /dev/null
+++ b/tools/perf/lib/evlist.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <perf/evlist.h>
+#include <perf/evsel.h>
+#include <linux/list.h>
+#include <internal/evlist.h>
+#include <internal/evsel.h>
+#include <linux/zalloc.h>
+#include <stdlib.h>
+#include <perf/cpumap.h>
+#include <perf/threadmap.h>
+
+void perf_evlist__init(struct perf_evlist *evlist)
+{
+ INIT_LIST_HEAD(&evlist->entries);
+ evlist->nr_entries = 0;
+}
+
+static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
+ struct perf_evsel *evsel)
+{
+ /*
+ * We already have cpus for evsel (via PMU sysfs) so
+ * keep it, if there's no target cpu list defined.
+ */
+ if (!evsel->own_cpus || evlist->has_user_cpus) {
+ perf_cpu_map__put(evsel->cpus);
+ evsel->cpus = perf_cpu_map__get(evlist->cpus);
+ } else if (evsel->cpus != evsel->own_cpus) {
+ perf_cpu_map__put(evsel->cpus);
+ evsel->cpus = perf_cpu_map__get(evsel->own_cpus);
+ }
+
+ perf_thread_map__put(evsel->threads);
+ evsel->threads = perf_thread_map__get(evlist->threads);
+}
+
+static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ perf_evlist__for_each_evsel(evlist, evsel)
+ __perf_evlist__propagate_maps(evlist, evsel);
+}
+
+void perf_evlist__add(struct perf_evlist *evlist,
+ struct perf_evsel *evsel)
+{
+ list_add_tail(&evsel->node, &evlist->entries);
+ evlist->nr_entries += 1;
+ __perf_evlist__propagate_maps(evlist, evsel);
+}
+
+void perf_evlist__remove(struct perf_evlist *evlist,
+ struct perf_evsel *evsel)
+{
+ list_del_init(&evsel->node);
+ evlist->nr_entries -= 1;
+}
+
+struct perf_evlist *perf_evlist__new(void)
+{
+ struct perf_evlist *evlist = zalloc(sizeof(*evlist));
+
+ if (evlist != NULL)
+ perf_evlist__init(evlist);
+
+ return evlist;
+}
+
+struct perf_evsel *
+perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *prev)
+{
+ struct perf_evsel *next;
+
+ if (!prev) {
+ next = list_first_entry(&evlist->entries,
+ struct perf_evsel,
+ node);
+ } else {
+ next = list_next_entry(prev, node);
+ }
+
+ /* Empty list is noticed here so don't need checking on entry. */
+ if (&next->node == &evlist->entries)
+ return NULL;
+
+ return next;
+}
+
+void perf_evlist__delete(struct perf_evlist *evlist)
+{
+ free(evlist);
+}
+
+void perf_evlist__set_maps(struct perf_evlist *evlist,
+ struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
+{
+ /*
+ * Allow for the possibility that one or another of the maps isn't being
+ * changed i.e. don't put it. Note we are assuming the maps that are
+ * being applied are brand new and evlist is taking ownership of the
+ * original reference count of 1. If that is not the case it is up to
+ * the caller to increase the reference count.
+ */
+ if (cpus != evlist->cpus) {
+ perf_cpu_map__put(evlist->cpus);
+ evlist->cpus = perf_cpu_map__get(cpus);
+ }
+
+ if (threads != evlist->threads) {
+ perf_thread_map__put(evlist->threads);
+ evlist->threads = perf_thread_map__get(threads);
+ }
+
+ perf_evlist__propagate_maps(evlist);
+}
+
+int perf_evlist__open(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+ int err;
+
+ perf_evlist__for_each_entry(evlist, evsel) {
+ err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
+ if (err < 0)
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ perf_evlist__close(evlist);
+ return err;
+}
+
+void perf_evlist__close(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ perf_evlist__for_each_entry_reverse(evlist, evsel)
+ perf_evsel__close(evsel);
+}
+
+void perf_evlist__enable(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ perf_evlist__for_each_entry(evlist, evsel)
+ perf_evsel__enable(evsel);
+}
+
+void perf_evlist__disable(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ perf_evlist__for_each_entry(evlist, evsel)
+ perf_evsel__disable(evsel);
+}
diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c
new file mode 100644
index 000000000000..24abc80dd767
--- /dev/null
+++ b/tools/perf/lib/evsel.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <perf/evsel.h>
+#include <perf/cpumap.h>
+#include <perf/threadmap.h>
+#include <linux/list.h>
+#include <internal/evsel.h>
+#include <linux/zalloc.h>
+#include <stdlib.h>
+#include <internal/xyarray.h>
+#include <internal/cpumap.h>
+#include <internal/threadmap.h>
+#include <internal/lib.h>
+#include <linux/string.h>
+#include <sys/ioctl.h>
+
+void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr)
+{
+ INIT_LIST_HEAD(&evsel->node);
+ evsel->attr = *attr;
+}
+
+struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
+{
+ struct perf_evsel *evsel = zalloc(sizeof(*evsel));
+
+ if (evsel != NULL)
+ perf_evsel__init(evsel, attr);
+
+ return evsel;
+}
+
+void perf_evsel__delete(struct perf_evsel *evsel)
+{
+ free(evsel);
+}
+
+#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
+
+int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+ evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
+
+ if (evsel->fd) {
+ int cpu, thread;
+ for (cpu = 0; cpu < ncpus; cpu++) {
+ for (thread = 0; thread < nthreads; thread++) {
+ FD(evsel, cpu, thread) = -1;
+ }
+ }
+ }
+
+ return evsel->fd != NULL ? 0 : -ENOMEM;
+}
+
+static int
+sys_perf_event_open(struct perf_event_attr *attr,
+ pid_t pid, int cpu, int group_fd,
+ unsigned long flags)
+{
+ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
+{
+ int cpu, thread, err = 0;
+
+ if (cpus == NULL) {
+ static struct perf_cpu_map *empty_cpu_map;
+
+ if (empty_cpu_map == NULL) {
+ empty_cpu_map = perf_cpu_map__dummy_new();
+ if (empty_cpu_map == NULL)
+ return -ENOMEM;
+ }
+
+ cpus = empty_cpu_map;
+ }
+
+ if (threads == NULL) {
+ static struct perf_thread_map *empty_thread_map;
+
+ if (empty_thread_map == NULL) {
+ empty_thread_map = perf_thread_map__new_dummy();
+ if (empty_thread_map == NULL)
+ return -ENOMEM;
+ }
+
+ threads = empty_thread_map;
+ }
+
+ if (evsel->fd == NULL &&
+ perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
+ return -ENOMEM;
+
+ for (cpu = 0; cpu < cpus->nr; cpu++) {
+ for (thread = 0; thread < threads->nr; thread++) {
+ int fd;
+
+ fd = sys_perf_event_open(&evsel->attr,
+ threads->map[thread].pid,
+ cpus->map[cpu], -1, 0);
+
+ if (fd < 0)
+ return -errno;
+
+ FD(evsel, cpu, thread) = fd;
+ }
+ }
+
+ return err;
+}
+
+void perf_evsel__close_fd(struct perf_evsel *evsel)
+{
+ int cpu, thread;
+
+ for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
+ for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
+ close(FD(evsel, cpu, thread));
+ FD(evsel, cpu, thread) = -1;
+ }
+}
+
+void perf_evsel__free_fd(struct perf_evsel *evsel)
+{
+ xyarray__delete(evsel->fd);
+ evsel->fd = NULL;
+}
+
+void perf_evsel__close(struct perf_evsel *evsel)
+{
+ if (evsel->fd == NULL)
+ return;
+
+ perf_evsel__close_fd(evsel);
+ perf_evsel__free_fd(evsel);
+}
+
+int perf_evsel__read_size(struct perf_evsel *evsel)
+{
+ u64 read_format = evsel->attr.read_format;
+ int entry = sizeof(u64); /* value */
+ int size = 0;
+ int nr = 1;
+
+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+ size += sizeof(u64);
+
+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+ size += sizeof(u64);
+
+ if (read_format & PERF_FORMAT_ID)
+ entry += sizeof(u64);
+
+ if (read_format & PERF_FORMAT_GROUP) {
+ nr = evsel->nr_members;
+ size += sizeof(u64);
+ }
+
+ size += entry * nr;
+ return size;
+}
+
+int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
+ struct perf_counts_values *count)
+{
+ size_t size = perf_evsel__read_size(evsel);
+
+ memset(count, 0, sizeof(*count));
+
+ if (FD(evsel, cpu, thread) < 0)
+ return -EINVAL;
+
+ if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
+ return -errno;
+
+ return 0;
+}
+
+static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
+ int ioc, void *arg)
+{
+ int cpu, thread;
+
+ for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
+ for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
+ int fd = FD(evsel, cpu, thread),
+ err = ioctl(fd, ioc, arg);
+
+ if (err)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+int perf_evsel__enable(struct perf_evsel *evsel)
+{
+ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+}
+
+int perf_evsel__disable(struct perf_evsel *evsel)
+{
+ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+}
+
+int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
+{
+ return perf_evsel__run_ioctl(evsel,
+ PERF_EVENT_IOC_SET_FILTER,
+ (void *)filter);
+}
+
+struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+{
+ return evsel->cpus;
+}
+
+struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel)
+{
+ return evsel->threads;
+}
+
+struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel)
+{
+ return &evsel->attr;
+}
diff --git a/tools/perf/lib/include/internal/cpumap.h b/tools/perf/lib/include/internal/cpumap.h
new file mode 100644
index 000000000000..840d4032587b
--- /dev/null
+++ b/tools/perf/lib/include/internal/cpumap.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_CPUMAP_H
+#define __LIBPERF_INTERNAL_CPUMAP_H
+
+#include <linux/refcount.h>
+
+struct perf_cpu_map {
+ refcount_t refcnt;
+ int nr;
+ int map[];
+};
+
+#ifndef MAX_NR_CPUS
+#define MAX_NR_CPUS 2048
+#endif
+
+int perf_cpu_map__idx(struct perf_cpu_map *cpus, int cpu);
+
+#endif /* __LIBPERF_INTERNAL_CPUMAP_H */
diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h
new file mode 100644
index 000000000000..448891f06e3e
--- /dev/null
+++ b/tools/perf/lib/include/internal/evlist.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_EVLIST_H
+#define __LIBPERF_INTERNAL_EVLIST_H
+
+#include <linux/list.h>
+
+struct perf_cpu_map;
+struct perf_thread_map;
+
+struct perf_evlist {
+ struct list_head entries;
+ int nr_entries;
+ bool has_user_cpus;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
+};
+
+/**
+ * __perf_evlist__for_each_entry - iterate thru all the evsels
+ * @list: list_head instance to iterate
+ * @evsel: struct perf_evsel iterator
+ */
+#define __perf_evlist__for_each_entry(list, evsel) \
+ list_for_each_entry(evsel, list, node)
+
+/**
+ * evlist__for_each_entry - iterate thru all the evsels
+ * @evlist: perf_evlist instance to iterate
+ * @evsel: struct perf_evsel iterator
+ */
+#define perf_evlist__for_each_entry(evlist, evsel) \
+ __perf_evlist__for_each_entry(&(evlist)->entries, evsel)
+
+/**
+ * __perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
+ * @list: list_head instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define __perf_evlist__for_each_entry_reverse(list, evsel) \
+ list_for_each_entry_reverse(evsel, list, node)
+
+/**
+ * perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define perf_evlist__for_each_entry_reverse(evlist, evsel) \
+ __perf_evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
+
+#endif /* __LIBPERF_INTERNAL_EVLIST_H */
diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h
new file mode 100644
index 000000000000..8b854d1c9b45
--- /dev/null
+++ b/tools/perf/lib/include/internal/evsel.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_EVSEL_H
+#define __LIBPERF_INTERNAL_EVSEL_H
+
+#include <linux/types.h>
+#include <linux/perf_event.h>
+
+struct perf_cpu_map;
+struct perf_thread_map;
+
+struct perf_evsel {
+ struct list_head node;
+ struct perf_event_attr attr;
+ struct perf_cpu_map *cpus;
+ struct perf_cpu_map *own_cpus;
+ struct perf_thread_map *threads;
+ struct xyarray *fd;
+
+ /* parse modifier helper */
+ int nr_members;
+};
+
+int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
+void perf_evsel__close_fd(struct perf_evsel *evsel);
+void perf_evsel__free_fd(struct perf_evsel *evsel);
+int perf_evsel__read_size(struct perf_evsel *evsel);
+int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter);
+
+#endif /* __LIBPERF_INTERNAL_EVSEL_H */
diff --git a/tools/perf/lib/include/internal/lib.h b/tools/perf/lib/include/internal/lib.h
new file mode 100644
index 000000000000..0b56f1201dc9
--- /dev/null
+++ b/tools/perf/lib/include/internal/lib.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_LIB_H
+#define __LIBPERF_INTERNAL_LIB_H
+
+#include <unistd.h>
+
+ssize_t readn(int fd, void *buf, size_t n);
+ssize_t writen(int fd, const void *buf, size_t n);
+
+#endif /* __LIBPERF_INTERNAL_CPUMAP_H */
diff --git a/tools/perf/lib/include/internal/tests.h b/tools/perf/lib/include/internal/tests.h
new file mode 100644
index 000000000000..b7a20cd24ee1
--- /dev/null
+++ b/tools/perf/lib/include/internal/tests.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_TESTS_H
+#define __LIBPERF_INTERNAL_TESTS_H
+
+#include <stdio.h>
+
+#define __T_START fprintf(stdout, "- running %s...", __FILE__)
+#define __T_OK fprintf(stdout, "OK\n")
+#define __T_FAIL fprintf(stdout, "FAIL\n")
+
+#define __T(text, cond) \
+do { \
+ if (!(cond)) { \
+ fprintf(stderr, "FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+ return -1; \
+ } \
+} while (0)
+
+#endif /* __LIBPERF_INTERNAL_TESTS_H */
diff --git a/tools/perf/lib/include/internal/threadmap.h b/tools/perf/lib/include/internal/threadmap.h
new file mode 100644
index 000000000000..df748baf9eda
--- /dev/null
+++ b/tools/perf/lib/include/internal/threadmap.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_THREADMAP_H
+#define __LIBPERF_INTERNAL_THREADMAP_H
+
+#include <linux/refcount.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct thread_map_data {
+ pid_t pid;
+ char *comm;
+};
+
+struct perf_thread_map {
+ refcount_t refcnt;
+ int nr;
+ int err_thread;
+ struct thread_map_data map[];
+};
+
+struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr);
+
+#endif /* __LIBPERF_INTERNAL_THREADMAP_H */
diff --git a/tools/perf/util/xyarray.h b/tools/perf/lib/include/internal/xyarray.h
index 7ffe562e7ae7..51e35d6c8ec4 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/lib/include/internal/xyarray.h
@@ -1,7 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _PERF_XYARRAY_H_
-#define _PERF_XYARRAY_H_ 1
+#ifndef __LIBPERF_INTERNAL_XYARRAY_H
+#define __LIBPERF_INTERNAL_XYARRAY_H
+#include <linux/compiler.h>
#include <sys/types.h>
struct xyarray {
@@ -10,7 +11,7 @@ struct xyarray {
size_t entries;
size_t max_x;
size_t max_y;
- char contents[];
+ char contents[] __aligned(8);
};
struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
@@ -32,4 +33,4 @@ static inline int xyarray__max_x(struct xyarray *xy)
return xy->max_x;
}
-#endif /* _PERF_XYARRAY_H_ */
+#endif /* __LIBPERF_INTERNAL_XYARRAY_H */
diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h
new file mode 100644
index 000000000000..c341a7b2c874
--- /dev/null
+++ b/tools/perf/lib/include/perf/core.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_CORE_H
+#define __LIBPERF_CORE_H
+
+#include <stdarg.h>
+
+#ifndef LIBPERF_API
+#define LIBPERF_API __attribute__((visibility("default")))
+#endif
+
+enum libperf_print_level {
+ LIBPERF_WARN,
+ LIBPERF_INFO,
+ LIBPERF_DEBUG,
+};
+
+typedef int (*libperf_print_fn_t)(enum libperf_print_level level,
+ const char *, va_list ap);
+
+LIBPERF_API void libperf_set_print(libperf_print_fn_t fn);
+
+#endif /* __LIBPERF_CORE_H */
diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h
new file mode 100644
index 000000000000..8aa995c59498
--- /dev/null
+++ b/tools/perf/lib/include/perf/cpumap.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_CPUMAP_H
+#define __LIBPERF_CPUMAP_H
+
+#include <perf/core.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+struct perf_cpu_map;
+
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
+LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
+LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
+LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
+LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map);
+
+#define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \
+ for ((idx) = 0, (cpu) = perf_cpu_map__cpu(cpus, idx); \
+ (idx) < perf_cpu_map__nr(cpus); \
+ (idx)++, (cpu) = perf_cpu_map__cpu(cpus, idx))
+
+#endif /* __LIBPERF_CPUMAP_H */
diff --git a/tools/perf/lib/include/perf/event.h b/tools/perf/lib/include/perf/event.h
new file mode 100644
index 000000000000..18106899cb4e
--- /dev/null
+++ b/tools/perf/lib/include/perf/event.h
@@ -0,0 +1,385 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_EVENT_H
+#define __LIBPERF_EVENT_H
+
+#include <linux/perf_event.h>
+#include <linux/types.h>
+#include <linux/limits.h>
+#include <linux/bpf.h>
+#include <sys/types.h> /* pid_t */
+
+struct perf_record_mmap {
+ struct perf_event_header header;
+ __u32 pid, tid;
+ __u64 start;
+ __u64 len;
+ __u64 pgoff;
+ char filename[PATH_MAX];
+};
+
+struct perf_record_mmap2 {
+ struct perf_event_header header;
+ __u32 pid, tid;
+ __u64 start;
+ __u64 len;
+ __u64 pgoff;
+ __u32 maj;
+ __u32 min;
+ __u64 ino;
+ __u64 ino_generation;
+ __u32 prot;
+ __u32 flags;
+ char filename[PATH_MAX];
+};
+
+struct perf_record_comm {
+ struct perf_event_header header;
+ __u32 pid, tid;
+ char comm[16];
+};
+
+struct perf_record_namespaces {
+ struct perf_event_header header;
+ __u32 pid, tid;
+ __u64 nr_namespaces;
+ struct perf_ns_link_info link_info[];
+};
+
+struct perf_record_fork {
+ struct perf_event_header header;
+ __u32 pid, ppid;
+ __u32 tid, ptid;
+ __u64 time;
+};
+
+struct perf_record_lost {
+ struct perf_event_header header;
+ __u64 id;
+ __u64 lost;
+};
+
+struct perf_record_lost_samples {
+ struct perf_event_header header;
+ __u64 lost;
+};
+
+/*
+ * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
+ */
+struct perf_record_read {
+ struct perf_event_header header;
+ __u32 pid, tid;
+ __u64 value;
+ __u64 time_enabled;
+ __u64 time_running;
+ __u64 id;
+};
+
+struct perf_record_throttle {
+ struct perf_event_header header;
+ __u64 time;
+ __u64 id;
+ __u64 stream_id;
+};
+
+#ifndef KSYM_NAME_LEN
+#define KSYM_NAME_LEN 256
+#endif
+
+struct perf_record_ksymbol {
+ struct perf_event_header header;
+ __u64 addr;
+ __u32 len;
+ __u16 ksym_type;
+ __u16 flags;
+ char name[KSYM_NAME_LEN];
+};
+
+struct perf_record_bpf_event {
+ struct perf_event_header header;
+ __u16 type;
+ __u16 flags;
+ __u32 id;
+
+ /* for bpf_prog types */
+ __u8 tag[BPF_TAG_SIZE]; // prog tag
+};
+
+struct perf_record_sample {
+ struct perf_event_header header;
+ __u64 array[];
+};
+
+struct perf_record_switch {
+ struct perf_event_header header;
+ __u32 next_prev_pid;
+ __u32 next_prev_tid;
+};
+
+struct perf_record_header_attr {
+ struct perf_event_header header;
+ struct perf_event_attr attr;
+ __u64 id[];
+};
+
+enum {
+ PERF_CPU_MAP__CPUS = 0,
+ PERF_CPU_MAP__MASK = 1,
+};
+
+struct cpu_map_entries {
+ __u16 nr;
+ __u16 cpu[];
+};
+
+struct perf_record_record_cpu_map {
+ __u16 nr;
+ __u16 long_size;
+ unsigned long mask[];
+};
+
+struct perf_record_cpu_map_data {
+ __u16 type;
+ char data[];
+};
+
+struct perf_record_cpu_map {
+ struct perf_event_header header;
+ struct perf_record_cpu_map_data data;
+};
+
+enum {
+ PERF_EVENT_UPDATE__UNIT = 0,
+ PERF_EVENT_UPDATE__SCALE = 1,
+ PERF_EVENT_UPDATE__NAME = 2,
+ PERF_EVENT_UPDATE__CPUS = 3,
+};
+
+struct perf_record_event_update_cpus {
+ struct perf_record_cpu_map_data cpus;
+};
+
+struct perf_record_event_update_scale {
+ double scale;
+};
+
+struct perf_record_event_update {
+ struct perf_event_header header;
+ __u64 type;
+ __u64 id;
+ char data[];
+};
+
+#define MAX_EVENT_NAME 64
+
+struct perf_trace_event_type {
+ __u64 event_id;
+ char name[MAX_EVENT_NAME];
+};
+
+struct perf_record_header_event_type {
+ struct perf_event_header header;
+ struct perf_trace_event_type event_type;
+};
+
+struct perf_record_header_tracing_data {
+ struct perf_event_header header;
+ __u32 size;
+};
+
+struct perf_record_header_build_id {
+ struct perf_event_header header;
+ pid_t pid;
+ __u8 build_id[24];
+ char filename[];
+};
+
+struct id_index_entry {
+ __u64 id;
+ __u64 idx;
+ __u64 cpu;
+ __u64 tid;
+};
+
+struct perf_record_id_index {
+ struct perf_event_header header;
+ __u64 nr;
+ struct id_index_entry entries[0];
+};
+
+struct perf_record_auxtrace_info {
+ struct perf_event_header header;
+ __u32 type;
+ __u32 reserved__; /* For alignment */
+ __u64 priv[];
+};
+
+struct perf_record_auxtrace {
+ struct perf_event_header header;
+ __u64 size;
+ __u64 offset;
+ __u64 reference;
+ __u32 idx;
+ __u32 tid;
+ __u32 cpu;
+ __u32 reserved__; /* For alignment */
+};
+
+#define MAX_AUXTRACE_ERROR_MSG 64
+
+struct perf_record_auxtrace_error {
+ struct perf_event_header header;
+ __u32 type;
+ __u32 code;
+ __u32 cpu;
+ __u32 pid;
+ __u32 tid;
+ __u32 fmt;
+ __u64 ip;
+ __u64 time;
+ char msg[MAX_AUXTRACE_ERROR_MSG];
+};
+
+struct perf_record_aux {
+ struct perf_event_header header;
+ __u64 aux_offset;
+ __u64 aux_size;
+ __u64 flags;
+};
+
+struct perf_record_itrace_start {
+ struct perf_event_header header;
+ __u32 pid;
+ __u32 tid;
+};
+
+struct perf_record_thread_map_entry {
+ __u64 pid;
+ char comm[16];
+};
+
+struct perf_record_thread_map {
+ struct perf_event_header header;
+ __u64 nr;
+ struct perf_record_thread_map_entry entries[];
+};
+
+enum {
+ PERF_STAT_CONFIG_TERM__AGGR_MODE = 0,
+ PERF_STAT_CONFIG_TERM__INTERVAL = 1,
+ PERF_STAT_CONFIG_TERM__SCALE = 2,
+ PERF_STAT_CONFIG_TERM__MAX = 3,
+};
+
+struct perf_record_stat_config_entry {
+ __u64 tag;
+ __u64 val;
+};
+
+struct perf_record_stat_config {
+ struct perf_event_header header;
+ __u64 nr;
+ struct perf_record_stat_config_entry data[];
+};
+
+struct perf_record_stat {
+ struct perf_event_header header;
+
+ __u64 id;
+ __u32 cpu;
+ __u32 thread;
+
+ union {
+ struct {
+ __u64 val;
+ __u64 ena;
+ __u64 run;
+ };
+ __u64 values[3];
+ };
+};
+
+struct perf_record_stat_round {
+ struct perf_event_header header;
+ __u64 type;
+ __u64 time;
+};
+
+struct perf_record_time_conv {
+ struct perf_event_header header;
+ __u64 time_shift;
+ __u64 time_mult;
+ __u64 time_zero;
+};
+
+struct perf_record_header_feature {
+ struct perf_event_header header;
+ __u64 feat_id;
+ char data[];
+};
+
+struct perf_record_compressed {
+ struct perf_event_header header;
+ char data[];
+};
+
+enum perf_user_event_type { /* above any possible kernel type */
+ PERF_RECORD_USER_TYPE_START = 64,
+ PERF_RECORD_HEADER_ATTR = 64,
+ PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
+ PERF_RECORD_HEADER_TRACING_DATA = 66,
+ PERF_RECORD_HEADER_BUILD_ID = 67,
+ PERF_RECORD_FINISHED_ROUND = 68,
+ PERF_RECORD_ID_INDEX = 69,
+ PERF_RECORD_AUXTRACE_INFO = 70,
+ PERF_RECORD_AUXTRACE = 71,
+ PERF_RECORD_AUXTRACE_ERROR = 72,
+ PERF_RECORD_THREAD_MAP = 73,
+ PERF_RECORD_CPU_MAP = 74,
+ PERF_RECORD_STAT_CONFIG = 75,
+ PERF_RECORD_STAT = 76,
+ PERF_RECORD_STAT_ROUND = 77,
+ PERF_RECORD_EVENT_UPDATE = 78,
+ PERF_RECORD_TIME_CONV = 79,
+ PERF_RECORD_HEADER_FEATURE = 80,
+ PERF_RECORD_COMPRESSED = 81,
+ PERF_RECORD_HEADER_MAX
+};
+
+union perf_event {
+ struct perf_event_header header;
+ struct perf_record_mmap mmap;
+ struct perf_record_mmap2 mmap2;
+ struct perf_record_comm comm;
+ struct perf_record_namespaces namespaces;
+ struct perf_record_fork fork;
+ struct perf_record_lost lost;
+ struct perf_record_lost_samples lost_samples;
+ struct perf_record_read read;
+ struct perf_record_throttle throttle;
+ struct perf_record_sample sample;
+ struct perf_record_bpf_event bpf;
+ struct perf_record_ksymbol ksymbol;
+ struct perf_record_header_attr attr;
+ struct perf_record_event_update event_update;
+ struct perf_record_header_event_type event_type;
+ struct perf_record_header_tracing_data tracing_data;
+ struct perf_record_header_build_id build_id;
+ struct perf_record_id_index id_index;
+ struct perf_record_auxtrace_info auxtrace_info;
+ struct perf_record_auxtrace auxtrace;
+ struct perf_record_auxtrace_error auxtrace_error;
+ struct perf_record_aux aux;
+ struct perf_record_itrace_start itrace_start;
+ struct perf_record_switch context_switch;
+ struct perf_record_thread_map thread_map;
+ struct perf_record_cpu_map cpu_map;
+ struct perf_record_stat_config stat_config;
+ struct perf_record_stat stat;
+ struct perf_record_stat_round stat_round;
+ struct perf_record_time_conv time_conv;
+ struct perf_record_header_feature feat;
+ struct perf_record_compressed pack;
+};
+
+#endif /* __LIBPERF_EVENT_H */
diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h
new file mode 100644
index 000000000000..38365f8f3fba
--- /dev/null
+++ b/tools/perf/lib/include/perf/evlist.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_EVLIST_H
+#define __LIBPERF_EVLIST_H
+
+#include <perf/core.h>
+
+struct perf_evlist;
+struct perf_evsel;
+struct perf_cpu_map;
+struct perf_thread_map;
+
+LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist);
+LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist,
+ struct perf_evsel *evsel);
+LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist,
+ struct perf_evsel *evsel);
+LIBPERF_API struct perf_evlist *perf_evlist__new(void);
+LIBPERF_API void perf_evlist__delete(struct perf_evlist *evlist);
+LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist,
+ struct perf_evsel *evsel);
+LIBPERF_API int perf_evlist__open(struct perf_evlist *evlist);
+LIBPERF_API void perf_evlist__close(struct perf_evlist *evlist);
+LIBPERF_API void perf_evlist__enable(struct perf_evlist *evlist);
+LIBPERF_API void perf_evlist__disable(struct perf_evlist *evlist);
+
+#define perf_evlist__for_each_evsel(evlist, pos) \
+ for ((pos) = perf_evlist__next((evlist), NULL); \
+ (pos) != NULL; \
+ (pos) = perf_evlist__next((evlist), (pos)))
+
+LIBPERF_API void perf_evlist__set_maps(struct perf_evlist *evlist,
+ struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads);
+
+#endif /* __LIBPERF_EVLIST_H */
diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h
new file mode 100644
index 000000000000..4388667f265c
--- /dev/null
+++ b/tools/perf/lib/include/perf/evsel.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_EVSEL_H
+#define __LIBPERF_EVSEL_H
+
+#include <stdint.h>
+#include <perf/core.h>
+
+struct perf_evsel;
+struct perf_event_attr;
+struct perf_cpu_map;
+struct perf_thread_map;
+
+struct perf_counts_values {
+ union {
+ struct {
+ uint64_t val;
+ uint64_t ena;
+ uint64_t run;
+ };
+ uint64_t values[3];
+ };
+};
+
+LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel,
+ struct perf_event_attr *attr);
+LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
+LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads);
+LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
+ struct perf_counts_values *count);
+LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
+LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
+LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
+LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
+
+#endif /* __LIBPERF_EVSEL_H */
diff --git a/tools/perf/lib/include/perf/threadmap.h b/tools/perf/lib/include/perf/threadmap.h
new file mode 100644
index 000000000000..a7c50de8d010
--- /dev/null
+++ b/tools/perf/lib/include/perf/threadmap.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_THREADMAP_H
+#define __LIBPERF_THREADMAP_H
+
+#include <perf/core.h>
+#include <sys/types.h>
+
+struct perf_thread_map;
+
+LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
+
+LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
+LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
+LIBPERF_API int perf_thread_map__nr(struct perf_thread_map *threads);
+LIBPERF_API pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread);
+
+LIBPERF_API struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map);
+LIBPERF_API void perf_thread_map__put(struct perf_thread_map *map);
+
+#endif /* __LIBPERF_THREADMAP_H */
diff --git a/tools/perf/lib/internal.h b/tools/perf/lib/internal.h
new file mode 100644
index 000000000000..dc92f241732e
--- /dev/null
+++ b/tools/perf/lib/internal.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LIBPERF_INTERNAL_H
+#define __LIBPERF_INTERNAL_H
+
+void libperf_print(enum libperf_print_level level,
+ const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#define __pr(level, fmt, ...) \
+do { \
+ libperf_print(level, "libperf: " fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define pr_warning(fmt, ...) __pr(LIBPERF_WARN, fmt, ##__VA_ARGS__)
+#define pr_info(fmt, ...) __pr(LIBPERF_INFO, fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...) __pr(LIBPERF_DEBUG, fmt, ##__VA_ARGS__)
+
+#endif /* __LIBPERF_INTERNAL_H */
diff --git a/tools/perf/lib/lib.c b/tools/perf/lib/lib.c
new file mode 100644
index 000000000000..2a81819c3b8c
--- /dev/null
+++ b/tools/perf/lib/lib.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <unistd.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <linux/kernel.h>
+#include <internal/lib.h>
+
+static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
+{
+ void *buf_start = buf;
+ size_t left = n;
+
+ while (left) {
+ /* buf must be treated as const if !is_read. */
+ ssize_t ret = is_read ? read(fd, buf, left) :
+ write(fd, buf, left);
+
+ if (ret < 0 && errno == EINTR)
+ continue;
+ if (ret <= 0)
+ return ret;
+
+ left -= ret;
+ buf += ret;
+ }
+
+ BUG_ON((size_t)(buf - buf_start) != n);
+ return n;
+}
+
+/*
+ * Read exactly 'n' bytes or return an error.
+ */
+ssize_t readn(int fd, void *buf, size_t n)
+{
+ return ion(true, fd, buf, n);
+}
+
+/*
+ * Write exactly 'n' bytes or return an error.
+ */
+ssize_t writen(int fd, const void *buf, size_t n)
+{
+ /* ion does not modify buf. */
+ return ion(false, fd, (void *)buf, n);
+}
diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map
new file mode 100644
index 000000000000..dc4d66363bc4
--- /dev/null
+++ b/tools/perf/lib/libperf.map
@@ -0,0 +1,43 @@
+LIBPERF_0.0.1 {
+ global:
+ libperf_set_print;
+ perf_cpu_map__dummy_new;
+ perf_cpu_map__get;
+ perf_cpu_map__put;
+ perf_cpu_map__new;
+ perf_cpu_map__read;
+ perf_cpu_map__nr;
+ perf_cpu_map__cpu;
+ perf_cpu_map__empty;
+ perf_thread_map__new_dummy;
+ perf_thread_map__set_pid;
+ perf_thread_map__comm;
+ perf_thread_map__nr;
+ perf_thread_map__pid;
+ perf_thread_map__get;
+ perf_thread_map__put;
+ perf_evsel__new;
+ perf_evsel__delete;
+ perf_evsel__enable;
+ perf_evsel__disable;
+ perf_evsel__init;
+ perf_evsel__open;
+ perf_evsel__close;
+ perf_evsel__read;
+ perf_evsel__cpus;
+ perf_evsel__threads;
+ perf_evsel__attr;
+ perf_evlist__new;
+ perf_evlist__delete;
+ perf_evlist__open;
+ perf_evlist__close;
+ perf_evlist__enable;
+ perf_evlist__disable;
+ perf_evlist__init;
+ perf_evlist__add;
+ perf_evlist__remove;
+ perf_evlist__next;
+ perf_evlist__set_maps;
+ local:
+ *;
+};
diff --git a/tools/perf/lib/libperf.pc.template b/tools/perf/lib/libperf.pc.template
new file mode 100644
index 000000000000..117e4a237b55
--- /dev/null
+++ b/tools/perf/lib/libperf.pc.template
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+prefix=@PREFIX@
+libdir=@LIBDIR@
+includedir=${prefix}/include
+
+Name: libperf
+Description: perf library
+Version: @VERSION@
+Libs: -L${libdir} -lperf
+Cflags: -I${includedir}
diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
new file mode 100644
index 000000000000..1ee4e9ba848b
--- /dev/null
+++ b/tools/perf/lib/tests/Makefile
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+TESTS = test-cpumap test-threadmap test-evlist test-evsel
+
+TESTS_SO := $(addsuffix -so,$(TESTS))
+TESTS_A := $(addsuffix -a,$(TESTS))
+
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+ CFLAGS := $(EXTRA_CFLAGS)
+else
+ CFLAGS := -g -Wall
+endif
+
+all:
+
+include $(srctree)/tools/scripts/Makefile.include
+
+INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include
+
+$(TESTS_A): FORCE
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a
+
+$(TESTS_SO): FORCE
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) -lperf
+
+all: $(TESTS_A) $(TESTS_SO)
+
+run:
+ @echo "running static:"
+ @for i in $(TESTS_A); do ./$$i; done
+ @echo "running dynamic:"
+ @for i in $(TESTS_SO); do LD_LIBRARY_PATH=../ ./$$i; done
+
+clean:
+ $(call QUIET_CLEAN, tests)$(RM) $(TESTS_A) $(TESTS_SO)
+
+.PHONY: all clean FORCE
diff --git a/tools/perf/lib/tests/test-cpumap.c b/tools/perf/lib/tests/test-cpumap.c
new file mode 100644
index 000000000000..76a43cfb83a1
--- /dev/null
+++ b/tools/perf/lib/tests/test-cpumap.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <perf/cpumap.h>
+#include <internal/tests.h>
+
+int main(int argc, char **argv)
+{
+ struct perf_cpu_map *cpus;
+
+ __T_START;
+
+ cpus = perf_cpu_map__dummy_new();
+ if (!cpus)
+ return -1;
+
+ perf_cpu_map__get(cpus);
+ perf_cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
+
+ __T_OK;
+ return 0;
+}
diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
new file mode 100644
index 000000000000..4e1407f20ffd
--- /dev/null
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/perf_event.h>
+#include <perf/cpumap.h>
+#include <perf/threadmap.h>
+#include <perf/evlist.h>
+#include <perf/evsel.h>
+#include <internal/tests.h>
+
+static int test_stat_cpu(void)
+{
+ struct perf_cpu_map *cpus;
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr1 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ };
+ struct perf_event_attr attr2 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ };
+ int err, cpu, tmp;
+
+ cpus = perf_cpu_map__new(NULL);
+ __T("failed to create cpus", cpus);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr1);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ evsel = perf_evsel__new(&attr2);
+ __T("failed to create evsel2", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, cpus, NULL);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evsel", err == 0);
+
+ perf_evlist__for_each_evsel(evlist, evsel) {
+ cpus = perf_evsel__cpus(evsel);
+
+ perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
+ struct perf_counts_values counts = { .val = 0 };
+
+ perf_evsel__read(evsel, cpu, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+ }
+ }
+
+ perf_evlist__close(evlist);
+ perf_evlist__delete(evlist);
+
+ perf_cpu_map__put(cpus);
+ return 0;
+}
+
+static int test_stat_thread(void)
+{
+ struct perf_counts_values counts = { .val = 0 };
+ struct perf_thread_map *threads;
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr1 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ };
+ struct perf_event_attr attr2 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ };
+ int err;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr1);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ evsel = perf_evsel__new(&attr2);
+ __T("failed to create evsel2", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, NULL, threads);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evsel", err == 0);
+
+ perf_evlist__for_each_evsel(evlist, evsel) {
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+ }
+
+ perf_evlist__close(evlist);
+ perf_evlist__delete(evlist);
+
+ perf_thread_map__put(threads);
+ return 0;
+}
+
+static int test_stat_thread_enable(void)
+{
+ struct perf_counts_values counts = { .val = 0 };
+ struct perf_thread_map *threads;
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr1 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ .disabled = 1,
+ };
+ struct perf_event_attr attr2 = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ .disabled = 1,
+ };
+ int err;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr1);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ evsel = perf_evsel__new(&attr2);
+ __T("failed to create evsel2", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, NULL, threads);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evsel", err == 0);
+
+ perf_evlist__for_each_evsel(evlist, evsel) {
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val == 0);
+ }
+
+ perf_evlist__enable(evlist);
+
+ perf_evlist__for_each_evsel(evlist, evsel) {
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+ }
+
+ perf_evlist__disable(evlist);
+
+ perf_evlist__close(evlist);
+ perf_evlist__delete(evlist);
+
+ perf_thread_map__put(threads);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ __T_START;
+
+ test_stat_cpu();
+ test_stat_thread();
+ test_stat_thread_enable();
+
+ __T_OK;
+ return 0;
+}
diff --git a/tools/perf/lib/tests/test-evsel.c b/tools/perf/lib/tests/test-evsel.c
new file mode 100644
index 000000000000..2c648fe5617e
--- /dev/null
+++ b/tools/perf/lib/tests/test-evsel.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/perf_event.h>
+#include <perf/cpumap.h>
+#include <perf/threadmap.h>
+#include <perf/evsel.h>
+#include <internal/tests.h>
+
+static int test_stat_cpu(void)
+{
+ struct perf_cpu_map *cpus;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ };
+ int err, cpu, tmp;
+
+ cpus = perf_cpu_map__new(NULL);
+ __T("failed to create cpus", cpus);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel", evsel);
+
+ err = perf_evsel__open(evsel, cpus, NULL);
+ __T("failed to open evsel", err == 0);
+
+ perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
+ struct perf_counts_values counts = { .val = 0 };
+
+ perf_evsel__read(evsel, cpu, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+ }
+
+ perf_evsel__close(evsel);
+ perf_evsel__delete(evsel);
+
+ perf_cpu_map__put(cpus);
+ return 0;
+}
+
+static int test_stat_thread(void)
+{
+ struct perf_counts_values counts = { .val = 0 };
+ struct perf_thread_map *threads;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ };
+ int err;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel", evsel);
+
+ err = perf_evsel__open(evsel, NULL, threads);
+ __T("failed to open evsel", err == 0);
+
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+
+ perf_evsel__close(evsel);
+ perf_evsel__delete(evsel);
+
+ perf_thread_map__put(threads);
+ return 0;
+}
+
+static int test_stat_thread_enable(void)
+{
+ struct perf_counts_values counts = { .val = 0 };
+ struct perf_thread_map *threads;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ .disabled = 1,
+ };
+ int err;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel", evsel);
+
+ err = perf_evsel__open(evsel, NULL, threads);
+ __T("failed to open evsel", err == 0);
+
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val == 0);
+
+ err = perf_evsel__enable(evsel);
+ __T("failed to enable evsel", err == 0);
+
+ perf_evsel__read(evsel, 0, 0, &counts);
+ __T("failed to read value for evsel", counts.val != 0);
+
+ err = perf_evsel__disable(evsel);
+ __T("failed to enable evsel", err == 0);
+
+ perf_evsel__close(evsel);
+ perf_evsel__delete(evsel);
+
+ perf_thread_map__put(threads);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ __T_START;
+
+ test_stat_cpu();
+ test_stat_thread();
+ test_stat_thread_enable();
+
+ __T_OK;
+ return 0;
+}
diff --git a/tools/perf/lib/tests/test-threadmap.c b/tools/perf/lib/tests/test-threadmap.c
new file mode 100644
index 000000000000..10a4f4cbbdd5
--- /dev/null
+++ b/tools/perf/lib/tests/test-threadmap.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <perf/threadmap.h>
+#include <internal/tests.h>
+
+int main(int argc, char **argv)
+{
+ struct perf_thread_map *threads;
+
+ __T_START;
+
+ threads = perf_thread_map__new_dummy();
+ if (!threads)
+ return -1;
+
+ perf_thread_map__get(threads);
+ perf_thread_map__put(threads);
+ perf_thread_map__put(threads);
+
+ __T_OK;
+ return 0;
+}
diff --git a/tools/perf/lib/threadmap.c b/tools/perf/lib/threadmap.c
new file mode 100644
index 000000000000..e92c368b0a6c
--- /dev/null
+++ b/tools/perf/lib/threadmap.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <perf/threadmap.h>
+#include <stdlib.h>
+#include <linux/refcount.h>
+#include <internal/threadmap.h>
+#include <string.h>
+#include <asm/bug.h>
+#include <stdio.h>
+
+static void perf_thread_map__reset(struct perf_thread_map *map, int start, int nr)
+{
+ size_t size = (nr - start) * sizeof(map->map[0]);
+
+ memset(&map->map[start], 0, size);
+ map->err_thread = -1;
+}
+
+struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr)
+{
+ size_t size = sizeof(*map) + sizeof(map->map[0]) * nr;
+ int start = map ? map->nr : 0;
+
+ map = realloc(map, size);
+ /*
+ * We only realloc to add more items, let's reset new items.
+ */
+ if (map)
+ perf_thread_map__reset(map, start, nr);
+
+ return map;
+}
+
+#define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr)
+
+void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid)
+{
+ map->map[thread].pid = pid;
+}
+
+char *perf_thread_map__comm(struct perf_thread_map *map, int thread)
+{
+ return map->map[thread].comm;
+}
+
+struct perf_thread_map *perf_thread_map__new_dummy(void)
+{
+ struct perf_thread_map *threads = thread_map__alloc(1);
+
+ if (threads != NULL) {
+ perf_thread_map__set_pid(threads, 0, -1);
+ threads->nr = 1;
+ refcount_set(&threads->refcnt, 1);
+ }
+ return threads;
+}
+
+static void perf_thread_map__delete(struct perf_thread_map *threads)
+{
+ if (threads) {
+ int i;
+
+ WARN_ONCE(refcount_read(&threads->refcnt) != 0,
+ "thread map refcnt unbalanced\n");
+ for (i = 0; i < threads->nr; i++)
+ free(perf_thread_map__comm(threads, i));
+ free(threads);
+ }
+}
+
+struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map)
+{
+ if (map)
+ refcount_inc(&map->refcnt);
+ return map;
+}
+
+void perf_thread_map__put(struct perf_thread_map *map)
+{
+ if (map && refcount_dec_and_test(&map->refcnt))
+ perf_thread_map__delete(map);
+}
+
+int perf_thread_map__nr(struct perf_thread_map *threads)
+{
+ return threads ? threads->nr : 1;
+}
+
+pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread)
+{
+ return map->map[thread].pid;
+}
diff --git a/tools/perf/lib/xyarray.c b/tools/perf/lib/xyarray.c
new file mode 100644
index 000000000000..dcd901d154bb
--- /dev/null
+++ b/tools/perf/lib/xyarray.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <internal/xyarray.h>
+#include <linux/zalloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
+{
+ size_t row_size = ylen * entry_size;
+ struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size);
+
+ if (xy != NULL) {
+ xy->entry_size = entry_size;
+ xy->row_size = row_size;
+ xy->entries = xlen * ylen;
+ xy->max_x = xlen;
+ xy->max_y = ylen;
+ }
+
+ return xy;
+}
+
+void xyarray__reset(struct xyarray *xy)
+{
+ size_t n = xy->entries * xy->entry_size;
+
+ memset(xy->contents, 0, n);
+}
+
+void xyarray__delete(struct xyarray *xy)
+{
+ free(xy);
+}
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 3eb7a39169f6..63e4349a772a 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -5,54 +5,17 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
-#include <linux/types.h>
#include <linux/compiler.h>
-#include <linux/perf_event.h>
-#include <asm/barrier.h>
-#ifdef __powerpc__
-#define CPUINFO_PROC {"cpu"}
-#endif
-
-#ifdef __s390__
-#define CPUINFO_PROC {"vendor_id"}
-#endif
-
-#ifdef __sh__
-#define CPUINFO_PROC {"cpu type"}
-#endif
+struct perf_event_attr;
-#ifdef __hppa__
-#define CPUINFO_PROC {"cpu"}
-#endif
-
-#ifdef __sparc__
-#define CPUINFO_PROC {"cpu"}
-#endif
-
-#ifdef __alpha__
-#define CPUINFO_PROC {"cpu model"}
-#endif
+extern bool test_attr__enabled;
+void test_attr__ready(void);
+void test_attr__init(void);
+void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
+ int fd, int group_fd, unsigned long flags);
-#ifdef __arm__
-#define CPUINFO_PROC {"model name", "Processor"}
-#endif
-
-#ifdef __mips__
-#define CPUINFO_PROC {"cpu model"}
-#endif
-
-#ifdef __arc__
-#define CPUINFO_PROC {"Processor"}
-#endif
-
-#ifdef __xtensa__
-#define CPUINFO_PROC {"core ID"}
-#endif
-
-#ifndef CPUINFO_PROC
-#define CPUINFO_PROC { "model name", }
-#endif
+#define HAVE_ATTR_TEST
static inline int
sys_perf_event_open(struct perf_event_attr *attr,
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 97e2628ea5dd..1193b923e801 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0
/*
* perf.c
*
@@ -8,7 +7,10 @@
* perf top, perf record, perf report, etc.) are started.
*/
#include "builtin.h"
+#include "perf.h"
+#include "util/build-id.h"
+#include "util/cache.h"
#include "util/env.h"
#include <subcmd/exec-cmd.h>
#include "util/config.h"
@@ -18,6 +20,9 @@
#include "util/bpf-loader.h"
#include "util/debug.h"
#include "util/event.h"
+#include "util/util.h"
+#include "ui/ui.h"
+#include "perf-sys.h"
#include <api/fs/fs.h>
#include <api/fs/tracing_path.h>
#include <errno.h>
@@ -29,6 +34,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
const char perf_usage_string[] =
@@ -441,6 +447,9 @@ int main(int argc, const char **argv)
srandom(time(NULL));
+ /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
+ config_exclusive_filename = getenv("PERF_CONFIG");
+
err = perf_config(perf_default_config, NULL);
if (err)
return err;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 74d0124d38f3..74014033df60 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -2,28 +2,7 @@
#ifndef _PERF_PERF_H
#define _PERF_PERF_H
-#include <time.h>
#include <stdbool.h>
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/perf_event.h>
-
-extern bool test_attr__enabled;
-void test_attr__ready(void);
-void test_attr__init(void);
-void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
- int fd, int group_fd, unsigned long flags);
-
-#define HAVE_ATTR_TEST
-#include "perf-sys.h"
-
-static inline unsigned long long rdclock(void)
-{
- struct timespec ts;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
-}
#ifndef MAX_NR_CPUS
#define MAX_NR_CPUS 2048
@@ -35,62 +14,6 @@ extern const char perf_version_string[];
void pthread__unblock_sigwinch(void);
-#include "util/target.h"
-
-struct record_opts {
- struct target target;
- bool group;
- bool inherit_stat;
- bool no_buffering;
- bool no_inherit;
- bool no_inherit_set;
- bool no_samples;
- bool raw_samples;
- bool sample_address;
- bool sample_phys_addr;
- bool sample_weight;
- bool sample_time;
- bool sample_time_set;
- bool sample_cpu;
- bool period;
- bool period_set;
- bool running_time;
- bool full_auxtrace;
- bool auxtrace_snapshot_mode;
- bool record_namespaces;
- bool record_switch_events;
- bool all_kernel;
- bool all_user;
- bool kernel_callchains;
- bool user_callchains;
- bool tail_synthesize;
- bool overwrite;
- bool ignore_missing_thread;
- bool strict_freq;
- bool sample_id;
- bool no_bpf_event;
- unsigned int freq;
- unsigned int mmap_pages;
- unsigned int auxtrace_mmap_pages;
- unsigned int user_freq;
- u64 branch_stack;
- u64 sample_intr_regs;
- u64 sample_user_regs;
- u64 default_interval;
- u64 user_interval;
- size_t auxtrace_snapshot_size;
- const char *auxtrace_snapshot_opts;
- bool sample_transaction;
- unsigned initial_delay;
- bool use_clockid;
- clockid_t clockid;
- u64 clockid_res_ns;
- int nr_cblocks;
- int affinity;
- int mmap_flush;
- unsigned int comp_level;
-};
-
enum perf_affinity {
PERF_AFFINITY_SYS = 0,
PERF_AFFINITY_NODE,
@@ -98,10 +21,5 @@ enum perf_affinity {
PERF_AFFINITY_MAX
};
-struct option;
-extern const char * const *record_usage;
-extern struct option *record_options;
extern int version_verbose;
-
-int record__parse_freq(const struct option *opt, const char *str, int unset);
#endif
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
index 2e2ebc700c74..c3bb283e37e9 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/memory.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
@@ -52,7 +52,7 @@
{,
"EventCode": "0x4D02C",
"EventName": "PM_PMC1_REWIND",
- "BriefDescription": ""
+ "BriefDescription": "PMC1 rewind event"
},
{,
"EventCode": "0x15158",
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 48cf4f920b3f..62b864269623 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -237,7 +237,7 @@
{,
"EventCode": "0xD0B0",
"EventName": "PM_HWSYNC",
- "BriefDescription": ""
+ "BriefDescription": "A hwsync instruction was decoded and transferred"
},
{,
"EventCode": "0x168B0",
@@ -1232,7 +1232,7 @@
{,
"EventCode": "0xD8AC",
"EventName": "PM_LWSYNC",
- "BriefDescription": ""
+ "BriefDescription": "An lwsync instruction was decoded and transferred"
},
{,
"EventCode": "0x2094",
@@ -1747,7 +1747,7 @@
{,
"EventCode": "0xD8B0",
"EventName": "PM_PTESYNC",
- "BriefDescription": ""
+ "BriefDescription": "A ptesync instruction was counted when the instruction is decoded and transmitted"
},
{,
"EventCode": "0x26086",
@@ -2107,7 +2107,7 @@
{,
"EventCode": "0xF080",
"EventName": "PM_LSU_STCX_FAIL",
- "BriefDescription": ""
+ "BriefDescription": "The LSU detects the condition that a stcx instruction failed. No requirement to wait for a response from the nest"
},
{,
"EventCode": "0x30038",
diff --git a/tools/perf/pmu-events/arch/x86/icelake/cache.json b/tools/perf/pmu-events/arch/x86/icelake/cache.json
new file mode 100644
index 000000000000..3529fc338c17
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/cache.json
@@ -0,0 +1,552 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read miss L2, no rejects"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts L2 cache misses when fetching instructions.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts demand requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x27",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests that miss L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Software prefetch requests that miss the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x28",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.SWPF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "SW prefetch requests that miss L2 cache."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of demand Data Read requests initiated by load instructions that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Software prefetch requests that hit the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.SWPF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "SW prefetch requests that hit L2 cache."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the total number of L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts demand requests to L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe7",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests to L2 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of L1D misses that are outstanding in each cycle, that is each cycle the number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch. Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of L1D misses that are outstanding"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailablability."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.FB_FULL_PERIODS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability.",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of cycles a demand request has waited due to L1D due to lack of L2 resources. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.L2_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles a demand request has waited due to L1D due to lack of L2 resources."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of cache lines replaced in L1 data cache."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Any memory transaction that reached the SQ."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions that true miss the STLB.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions that miss the STLB.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired store instructions that true miss the STLB.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store instructions that miss the STLB.",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with locked access.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load instructions with locked access.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all retired load instructions. This event accounts for SW prefetch instructions for loads.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load instructions.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all retired store instructions. This event account for SW prefetch instructions and PREFETCHW instruction for stores.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_INST_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store instructions.",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with L2 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L3_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions missed L1 cache as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions missed L2 cache as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load instructions missed L2 cache as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.L3_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load instructions missed L3 cache as data sources",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_RETIRED.FB_HIT",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of completed demand load requests that missed the L1, but hit the FB(fill buffer), because a preceding miss to the same cacheline initiated the line to be brought into L1, but data is not yet ready in L1.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "EventCode": "0xd2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "EventCode": "0xd2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions whose data sources were HitM responses from shared L3.",
+ "EventCode": "0xd2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions whose data sources were HitM responses from shared L3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired load instructions whose data sources were hits in L3 without snoops required.",
+ "EventCode": "0xd2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions whose data sources were hits in L3 without snoops required",
+ "Data_LA": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the cycles for which the thread is active and the superQ cannot take any more entries.",
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "SQ_MISC.SQ_FULL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles the thread is active and superQ cannot take any more entries."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/floating-point.json b/tools/perf/pmu-events/arch/x86/icelake/floating-point.json
new file mode 100644
index 000000000000..594c5551f610
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/floating-point.json
@@ -0,0 +1,102 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all microcode Floating Point assists.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "ASSISTS.FP",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all microcode FP assists.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/frontend.json b/tools/perf/pmu-events/arch/x86/icelake/frontend.json
new file mode 100644
index 000000000000..9c3cfbfcec0f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/frontend.json
@@ -0,0 +1,424 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MITE_CYCLES_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering optimal number of Uops",
+ "CounterMask": "5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MITE_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.DSB_CYCLES_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles DSB is delivering optimal number of Uops",
+ "CounterMask": "5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.DSB_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB or MITE to the MS",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to IDQ while MS is busy"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "IDQ.MS_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to IDQ while MS is busy",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE_16B.IFDATA_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.",
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE_64B.IFTAG_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.",
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE_64B.IFTAG_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE_64B.IFTAG_STALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "EventCode": "0x9c",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled",
+ "CounterMask": "5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Decode Stream Buffer (DSB) is a Uop-cache that holds translations of previously fetched instructions that were decoded by the legacy x86 decode pipeline (MITE). This event counts fetch penalty cycles when a transition occurs from DSB to MITE.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "DSB-to-MITE switch true penalty cycles."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x11",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced DSB miss.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Instructions who experienced Instruction L1 Cache true miss.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x12",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.L1I_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Instructions who experienced Instruction L2 Cache true miss.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x13",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.L2_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x14",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.ITLB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x15",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.STLB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x500206",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x500406",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x500806",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x501006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x502006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x504006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x508006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x510006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x520006",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
+ "EventCode": "0xC6",
+ "MSRValue": "0x100206",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/memory.json b/tools/perf/pmu-events/arch/x86/icelake/memory.json
new file mode 100644
index 000000000000..f158366b9dd6
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/memory.json
@@ -0,0 +1,410 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a TSX line had a cache conflict.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Speculatively counts the number Transactional Synchronization Extensions (TSX) Aborts due to a data capacity limitation for transactional writes.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculatively counts the number TSX Aborts due to a data capacity limitation for transactional writes."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times we could not allocate Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "TX_EXEC.MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed inside a transactional region"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "TX_EXEC.MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an instruction execution caused the transactional nest count supported to be exceeded"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
+ "CounterMask": "2"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "CounterMask": "6"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests who miss L3 cache"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of Machine Clears detected dye to memory ordering. Memory Ordering Machine Clears may apply when a memory read may not conform to the memory ordering rules of the x86 architecture",
+ "EventCode": "0xc3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears due to memory ordering conflicts."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times we entered an HLE region. Does not count nested transactions.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution started."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times HLE commit succeeded.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution successfully committed",
+ "Data_LA": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times HLE abort was triggered.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "HLE_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times we entered an RTM region. Does not count nested transactions.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution started."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times RTM commit succeeded.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution successfully committed"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times RTM abort was triggered.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted.",
+ "Data_LA": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to incompatible memory type.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RTM_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x8",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x10",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x20",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x40",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x80",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x100",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "TakenAlone": "1"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xcd",
+ "MSRValue": "0x200",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "TakenAlone": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/other.json b/tools/perf/pmu-events/arch/x86/icelake/other.json
new file mode 100644
index 000000000000..f8dfdb847224
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/other.json
@@ -0,0 +1,121 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core. Software can use this event as the denominator for the top-level metrics of the Top-down Microarchitecture Analysis method. This event is counted on a designated fixed counter (Fixed Counter 3) and is an architectural event.",
+ "Counter": "35",
+ "UMask": "0x4",
+ "PEBScounters": "35",
+ "EventName": "TOPDOWN.SLOTS",
+ "SampleAfterValue": "10000003",
+ "BriefDescription": "Counts the number of available slots for an unhalted logical processor."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CORE_POWER.LVL0_TURBO_LICENSE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CORE_POWER.LVL1_TURBO_LICENSE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server microarchtecture). This includes high current AVX 512-bit instructions.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of PREFETCHNTA instructions executed.",
+ "EventCode": "0x32",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "SW_PREFETCH_ACCESS.NTA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of PREFETCHNTA instructions executed."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of PREFETCHT0 instructions executed.",
+ "EventCode": "0x32",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "SW_PREFETCH_ACCESS.T0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of PREFETCHT0 instructions executed."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of PREFETCHT1 or PREFETCHT2 instructions executed.",
+ "EventCode": "0x32",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "SW_PREFETCH_ACCESS.T1_T2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of PREFETCHW instructions executed.",
+ "EventCode": "0x32",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of PREFETCHW instructions executed."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core.",
+ "EventCode": "0xa4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "TOPDOWN.SLOTS_P",
+ "SampleAfterValue": "10000003",
+ "BriefDescription": "Counts the number of available slots for an unhalted logical processor."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "TOPDOWN.BACKEND_BOUND_SLOTS",
+ "SampleAfterValue": "10000003",
+ "BriefDescription": "Issue slots where no uops were being issued due to lack of back end resources."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of occurrences where a microcode assist is invoked by hardware Examples include AD (page Access Dirty), FP and AVX related assists.",
+ "EventCode": "0xc1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x7",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "ASSISTS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/pipeline.json b/tools/perf/pmu-events/arch/x86/icelake/pipeline.json
new file mode 100644
index 000000000000..6d8311e634aa
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/pipeline.json
@@ -0,0 +1,892 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.",
+ "Counter": "32",
+ "UMask": "0x1",
+ "PEBScounters": "32",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. Fixed Counter - architectural event"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "3",
+ "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled. Use on Fixed Counter 0.",
+ "Counter": "32",
+ "UMask": "0x1",
+ "PEBScounters": "32",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with a reduced effect of PEBS shadow in IP distribution"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "Counter": "33",
+ "UMask": "0x2",
+ "PEBScounters": "33",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "Counter": "34",
+ "UMask": "0x3",
+ "PEBScounters": "34",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when: a. preceding store conflicts with the load (incomplete overlap),b. store forwarding is impossible due to u-arch limitations, c. preceding lock RMW operations are not forwarded, d. store has the no-forward bit set (uncacheable/page-split/masked stores), e. all-blocking stores are used (mostly, fences and port I/O), and others. The most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events. See the table of not supported store forwards in the Optimization Guide.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times a load got blocked due to false dependencies in MOB due to partial compare on address.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts core cycles when the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x3",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "INT_MISC.ALL_RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.",
+ "EventCode": "0x0d",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that RAT issues to RS"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when RAT does not issue Uops to RS for the thread",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x9",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "ARITH.DIVIDER_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts core crystal clock cycles when the thread is unhalted.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "25003",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Core crystal clock cycles when current thread is unhalted and the other thread is halted.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "25003",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.",
+ "EventCode": "0x4c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LOAD_HIT_PREFETCH.SWPF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for this logical processor. This is usually caused when the front-end pipeline runs into stravation periods (e.g. branch mispredictions or i-cache misses)",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to closely sample on front-end latency issues (see the FRONTEND_RETIRED event of designated precise events)",
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty.",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 0"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 2 and 3.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_2_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 2 and 3"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 5 and 9.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_4_9",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 4 and 9"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 6"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 7 and 8.",
+ "EventCode": "0xa1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_DISPATCHED.PORT_7_8",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on port 7 and 8"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xa2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RESOURCE_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles where the pipeline is stalled due to serializing operations."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls.",
+ "CounterMask": "4"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "CounterMask": "5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "16"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x14",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "20"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xa6",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xa6",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles where the Store Buffer was full and no loads caused an execution stall.",
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where the Store Buffer was full and no loads caused an execution stall.",
+ "CounterMask": "2"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xa6",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the cycles when optimal number of uops is delivered by the LSD (Loop-stream detector).",
+ "EventCode": "0xa8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LSD.CYCLES_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles optimal number of Uops delivered by the LSD, but did not come from the decoder.",
+ "CounterMask": "5"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CounterMask": "2"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CounterMask": "3"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "CounterMask": "4"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of uops executed from any thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least 1 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least 2 micro-ops are executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least 3 micro-ops are executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least 4 micro-ops are executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of x87 uops executed.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_EXECUTED.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of x87 uops dispatched."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of cycles using always true condition (uops_ret &amp;lt; 16) applied to non PEBS uops retired event.",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the retirement slots used each cycle.",
+ "EventCode": "0xc2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "UOPS_RETIRED.SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of machine clears (nukes) of any type.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts taken conditional branch instructions retired.",
+ "EventCode": "0xc4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.COND_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken conditional branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts both direct and indirect near call instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.COND_NTAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts conditional branch instructions retired.",
+ "EventCode": "0xc4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x11",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.COND",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts far branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "EventCode": "0xc4",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_INST_RETIRED.INDIRECT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "All indirect branch instructions retired (excluding RETs. TSX aborts are considered indirect branch)."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted branch instructions retired.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts taken conditional mispredicted branch instructions retired.",
+ "EventCode": "0xc5",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_MISP_RETIRED.COND_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "number of branch instructions retired that were mispredicted and taken. Non PEBS",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted conditional branch instructions retired.",
+ "EventCode": "0xc5",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x11",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_MISP_RETIRED.COND",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts number of near branch instructions retired that were mispredicted and taken.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts all miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x80",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "BR_MISP_RETIRED.INDIRECT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "All miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "Data_LA": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
+ "EventCode": "0xcc",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "MISC_RETIRED.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Increments whenever there is an update to the LBR array."
+ },
+ {
+ "PublicDescription": "Counts number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted).",
+ "EventCode": "0xcc",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x40",
+ "EventName": "MISC_RETIRED.PAUSE_INST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of retired PAUSE instructions."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "This event distributes cycle counts between active hyperthreads, i.e., those in C0. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If all other hyperthreads are inactive (or disabled or do not exist), all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.",
+ "EventCode": "0xec",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "EventName": "CPU_CLK_UNHALTED.DISTRIBUTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle counts are evenly distributed between active threads in the Core."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json
new file mode 100644
index 000000000000..7180a900c175
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json
@@ -0,0 +1,236 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walks completed due to a demand data load to a 4K page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walks completed due to a demand data load to a 2M/4M page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts demand data loads that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of page walks outstanding for a demand load in the PMH (Page Miss Handler) each cycle.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of page walks outstanding for a demand load in the PMH each cycle."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a demand load.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a demand load.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Loads that miss the DTLB and hit the STLB."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Page walks completed due to a demand data store to a 4K page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Page walks completed due to a demand data store to a 2M/4M page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts demand data stores that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of page walks outstanding for a store in the PMH (Page Miss Handler) each cycle.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of page walks outstanding for a store in the PMH each cycle."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Stores that miss the DTLB and hit the STLB."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts completed page walks (4K page size) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts code misses in all ITLB (Instruction TLB) levels that caused a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts completed page walks (2M and 4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of page walks outstanding for an outstanding code (instruction fetch) request in the PMH (Page Miss Handler) each cycle.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of page walks outstanding for an outstanding code request in the PMH each cycle."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a code (instruction fetch) request.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request.",
+ "CounterMask": "1"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts instruction fetch requests that miss the ITLB (Instruction TLB) and hit the STLB (Second-level TLB).",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index d6984a3017e0..745ced083844 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -33,4 +33,7 @@ GenuineIntel-6-25,v2,westmereep-sp,core
GenuineIntel-6-2F,v2,westmereex,core
GenuineIntel-6-55-[01234],v1,skylakex,core
GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core
+GenuineIntel-6-7D,v1,icelake,core
+GenuineIntel-6-7E,v1,icelake,core
+GenuineIntel-6-86,v1,tremontx,core
AuthenticAMD-23-[[:xdigit:]]+,v1,amdfam17h,core
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/cache.json b/tools/perf/pmu-events/arch/x86/tremontx/cache.json
new file mode 100644
index 000000000000..f88040171b4d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/cache.json
@@ -0,0 +1,111 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cacheable memory requests that miss in the the Last Level Cache. Requests include Demand Loads, Reads for Ownership(RFO), Instruction fetches and L1 HW prefetches. If the platform has an L3 cache, last level cache is the L3, otherwise it is the L2.",
+ "EventCode": "0x2e",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts memory requests originating from the core that miss in the last level cache. If the platform has an L3 cache, last level cache is the L3, otherwise it is the L2."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts cacheable memory requests that access the Last Level Cache. Requests include Demand Loads, Reads for Ownership(RFO), Instruction fetches and L1 HW prefetches. If the platform has an L3 cache, last level cache is the L3, otherwise it is the L2.",
+ "EventCode": "0x2e",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts memory requests originating from the core that reference a cache line in the last level cache. If the platform has an L3 cache, last level cache is the L3, otherwise it is the L2."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of load uops retired. This event is Precise Event capable",
+ "EventCode": "0xd0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of store uops retired. This event is Precise Event capable",
+ "EventCode": "0xd0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of store uops retired.",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired that hit the level 1 data cache",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired that hit in the level 2 cache",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired that miss in the level 3 cache"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired that miss in the level 1 data cache",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xd1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load uops retired that miss in the level 2 cache",
+ "Data_LA": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/frontend.json b/tools/perf/pmu-events/arch/x86/tremontx/frontend.json
new file mode 100644
index 000000000000..73b0a1ed5756
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is not in the ICache (miss). The event strives to count on a cache line basis, so that multiple accesses which miss in a single cache line count as one ICACHE.MISS. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is not in the ICache.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE.MISSES",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in a cache line and they do not hit in the ICache (miss)."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line. The event strives to count on a cache line basis, so that multiple fetches to a single cache line count as one ICACHE.ACCESS. Specifically, the event counts when accesses from straight line code crosses the cache line boundary, or when a branch target is to a new line.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ICACHE.ACCESSES",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes cache Line."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/memory.json b/tools/perf/pmu-events/arch/x86/tremontx/memory.json
new file mode 100644
index 000000000000..65469e84f35b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/memory.json
@@ -0,0 +1,26 @@
+[
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0XB7",
+ "MSRValue": "0x000000003F04000001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that was not supplied by the L3 cache.",
+ "Offcore": "1"
+ },
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0XB7",
+ "MSRValue": "0x000000003F04000002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand reads for ownership (RFO) requests and software based prefetches for exclusive ownership (PREFETCHW) that was not supplied by the L3 cache.",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/other.json b/tools/perf/pmu-events/arch/x86/tremontx/other.json
new file mode 100644
index 000000000000..85bf3c8f3914
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/other.json
@@ -0,0 +1,26 @@
+[
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0XB7",
+ "MSRValue": "0x000000000000010001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0XB7",
+ "MSRValue": "0x000000000000010002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand reads for ownership (RFO) requests and software based prefetches for exclusive ownership (PREFETCHW) that have any response type.",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/pipeline.json b/tools/perf/pmu-events/arch/x86/tremontx/pipeline.json
new file mode 100644
index 000000000000..05a8f6a7d9c0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/pipeline.json
@@ -0,0 +1,111 @@
+[
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of instructions that retire. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The counter continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses fixed counter 0.",
+ "Counter": "32",
+ "UMask": "0x1",
+ "PEBScounters": "32",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of instructions retired. (Fixed event)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. The core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses fixed counter 1.",
+ "Counter": "33",
+ "UMask": "0x2",
+ "PEBScounters": "33",
+ "EventName": "CPU_CLK_UNHALTED.CORE",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted core clock cycles. (Fixed event)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. The core frequency may change from time. This event is not affected by core frequency changes and at a fixed frequency. This event uses fixed counter 2.",
+ "Counter": "34",
+ "UMask": "0x3",
+ "PEBScounters": "34",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted reference clock cycles at TSC frequency. (Fixed event)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. The core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses a programmable general purpose performance counter.",
+ "EventCode": "0x3c",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.CORE_P",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted core clock cycles."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts reference cycles (at TSC frequency) when core is not halted. This event uses a programmable general purpose perfmon counter.",
+ "EventCode": "0x3c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted reference clock cycles at TSC frequency."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The event continues counting during hardware interrupts, traps, and inside interrupt handlers. This is an architectural performance event. This event uses a Programmable general purpose perfmon counter. *This event is Precise Event capable: The EventingRIP field in the PEBS record is precise to the address of the instruction which caused the event.",
+ "EventCode": "0xc0",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of instructions retired."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xc3",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.ANY",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "20003",
+ "BriefDescription": "Counts all machine clears due to, but not limited to memory ordering, memory disambiguation, SMC, page faults and FP assist."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts branch instructions retired for all branch types. This event is Precise Event capable. This is an architectural event.",
+ "EventCode": "0xc4",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired for all branch types."
+ },
+ {
+ "PEBS": "1",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted branch instructions retired for all branch types. This event is Precise Event capable. This is an architectural event.",
+ "EventCode": "0xc5",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "EventCode": "0xcd",
+ "Counter": "0,1,2,3",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "CYCLES_DIV_BUSY.ANY",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles the floating point divider or integer divider or both are busy. Does not imply a stall waiting for either divider."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/uncore-memory.json b/tools/perf/pmu-events/arch/x86/tremontx/uncore-memory.json
new file mode 100644
index 000000000000..15376f2cf052
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/uncore-memory.json
@@ -0,0 +1,73 @@
+[
+ {
+ "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x04",
+ "EventName": "LLC_MISSES.MEM_READ",
+ "PerPkg": "1",
+ "ScaleUnit": "64Bytes",
+ "UMask": "0x0f",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x04",
+ "EventName": "LLC_MISSES.MEM_WRITE",
+ "PerPkg": "1",
+ "ScaleUnit": "64Bytes",
+ "UMask": "0x30",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "Memory controller clock ticks",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventName": "UNC_M_CLOCKTICKS",
+ "PerPkg": "1",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "Pre-charge for reads",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x02",
+ "EventName": "UNC_M_PRE_COUNT.RD",
+ "PerPkg": "1",
+ "UMask": "0x04",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "Pre-charge for writes",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x02",
+ "EventName": "UNC_M_PRE_COUNT.WR",
+ "PerPkg": "1",
+ "UMask": "0x08",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "Precharge due to read on page miss, write on page miss or PGT",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x02",
+ "EventName": "UNC_M_PRE_COUNT.ALL",
+ "PerPkg": "1",
+ "UMask": "0x1c",
+ "Unit": "iMC"
+ },
+ {
+ "BriefDescription": "DRAM Precharge commands. : Precharge due to page table",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x02",
+ "EventName": "UNC_M_PRE_COUNT.PGT",
+ "PerPkg": "1",
+ "PublicDescription": "DRAM Precharge commands. : Precharge due to page table : Counts the number of DRAM Precharge commands sent on this channel.",
+ "UMask": "0x10",
+ "Unit": "iMC"
+ }
+]
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/uncore-other.json b/tools/perf/pmu-events/arch/x86/tremontx/uncore-other.json
new file mode 100644
index 000000000000..6deff1fe89e3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/uncore-other.json
@@ -0,0 +1,431 @@
+[
+ {
+ "BriefDescription": "Uncore cache clock ticks",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventName": "UNC_CHA_CLOCKTICKS",
+ "PerPkg": "1",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_cha_tor_inserts.ia_miss",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "LLC_MISSES.UNCACHEABLE",
+ "Filter": "config1=0x40e33",
+ "PerPkg": "1",
+ "UMask": "0xC001FE01",
+ "UMaskExt": "0xC001FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "MMIO reads. Derived from unc_cha_tor_inserts.ia_miss",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "LLC_MISSES.MMIO_READ",
+ "Filter": "config1=0x40040e33",
+ "PerPkg": "1",
+ "UMask": "0xC001FE01",
+ "UMaskExt": "0xC001FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "MMIO writes. Derived from unc_cha_tor_inserts.ia_miss",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "LLC_MISSES.MMIO_WRITE",
+ "Filter": "config1=0x40041e33",
+ "PerPkg": "1",
+ "UMask": "0xC001FE01",
+ "UMaskExt": "0xC001FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "Streaming stores (full cache line). Derived from unc_cha_tor_inserts.ia_miss",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "LLC_REFERENCES.STREAMING_FULL",
+ "Filter": "config1=0x41833",
+ "PerPkg": "1",
+ "ScaleUnit": "64Bytes",
+ "UMask": "0xC001FE01",
+ "UMaskExt": "0xC001FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "Streaming stores (partial cache line). Derived from unc_cha_tor_inserts.ia_miss",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
+ "Filter": "config1=0x41a33",
+ "PerPkg": "1",
+ "ScaleUnit": "64Bytes",
+ "UMask": "0xC001FE01",
+ "UMaskExt": "0xC001FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth reading at IIO. Derived from unc_iio_data_req_of_cpu.mem_read.part0",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "LLC_MISSES.PCIE_READ",
+ "FCMask": "0x07",
+ "Filter": "ch_mask=0x1f",
+ "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 +UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 +UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 +UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3",
+ "MetricName": "LLC_MISSES.PCIE_READ",
+ "PerPkg": "1",
+ "PortMask": "0x01",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth writing at IIO. Derived from unc_iio_data_req_of_cpu.mem_write.part0",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "LLC_MISSES.PCIE_WRITE",
+ "FCMask": "0x07",
+ "Filter": "ch_mask=0x1f",
+ "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3",
+ "MetricName": "LLC_MISSES.PCIE_WRITE",
+ "PerPkg": "1",
+ "PortMask": "0x01",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth writing at IIO, part 1",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x02",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth writing at IIO, part 2",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x04",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth writing at IIO, part 3",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x08",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth reading at IIO, part 1",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x02",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth reading at IIO, part 2",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x04",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCI Express bandwidth reading at IIO, part 3",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x08",
+ "ScaleUnit": "4Bytes",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "TOR Inserts; CRd misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Code read from local IA that misses in the snoop filter",
+ "UMask": "0xC80FFE01",
+ "UMaskExt": "0xC80FFE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; CRd Pref misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Code read prefetch from local IA that misses in the snoop filter",
+ "UMask": "0xC88FFE01",
+ "UMaskExt": "0xC88FFE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; DRd Opt misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Data read opt from local IA that misses in the snoop filter",
+ "UMask": "0xC827FE01",
+ "UMaskExt": "0xC827FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; DRd Opt Pref misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Data read opt prefetch from local IA that misses in the snoop filter",
+ "UMask": "0xC8A7FE01",
+ "UMaskExt": "0xC8A7FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; RFO misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Read for ownership from local IA that misses in the snoop filter",
+ "UMask": "0xC807FE01",
+ "UMaskExt": "0xC807FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; RFO pref misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that misses in the snoop filter",
+ "UMask": "0xC887FE01",
+ "UMaskExt": "0xC887FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; WCiL misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Data read from local IA that misses in the snoop filter",
+ "UMask": "0xC86FFE01",
+ "UMaskExt": "0xC86FFE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "TOR Inserts; WCiLF misses from local IA",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x35",
+ "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF",
+ "PerPkg": "1",
+ "PublicDescription": "TOR Inserts; Data read from local IA that misses in the snoop filter",
+ "UMask": "0xC867FE01",
+ "UMaskExt": "0xC867FE",
+ "Unit": "CHA"
+ },
+ {
+ "BriefDescription": "Clockticks of the integrated IO (IIO) traffic controller",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x01",
+ "EventName": "UNC_IIO_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks of the integrated IO (IIO) traffic controller",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card reading from DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART4",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x10",
+ "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card reading from DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART5",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x20",
+ "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card reading from DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART6",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x40",
+ "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card reading from DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART7",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x80",
+ "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card writing to DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART4",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x10",
+ "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card writing to DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART5",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x20",
+ "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card writing to DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART6",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x40",
+ "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Data requested of the CPU : Card writing to DRAM",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x83",
+ "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART7",
+ "FCMask": "0x07",
+ "PerPkg": "1",
+ "PortMask": "0x80",
+ "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "Clockticks of the IO coherency tracker (IRP)",
+ "Counter": "0,1",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x01",
+ "EventName": "UNC_I_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks of the IO coherency tracker (IRP)",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Clockticks of the mesh to memory (M2M)",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventName": "UNC_M2M_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks of the mesh to memory (M2M)",
+ "Unit": "M2M"
+ },
+ {
+ "BriefDescription": "Clockticks of the mesh to PCI (M2P)",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventCode": "0x01",
+ "EventName": "UNC_M2P_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks of the mesh to PCI (M2P)",
+ "Unit": "M2PCIe"
+ },
+ {
+ "BriefDescription": "Clockticks in the UBOX using a dedicated 48-bit Fixed Counter",
+ "Counter": "FIXED",
+ "CounterType": "PGMABLE",
+ "EventCode": "0xff",
+ "EventName": "UNC_U_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks in the UBOX using a dedicated 48-bit Fixed Counter",
+ "Unit": "UBOX"
+ }
+]
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/uncore-power.json b/tools/perf/pmu-events/arch/x86/tremontx/uncore-power.json
new file mode 100644
index 000000000000..ea62c092b43f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/uncore-power.json
@@ -0,0 +1,11 @@
+[
+ {
+ "BriefDescription": "Clockticks of the power control unit (PCU)",
+ "Counter": "0,1,2,3",
+ "CounterType": "PGMABLE",
+ "EventName": "UNC_P_CLOCKTICKS",
+ "PerPkg": "1",
+ "PublicDescription": "Clockticks of the power control unit (PCU)",
+ "Unit": "PCU"
+ }
+]
diff --git a/tools/perf/pmu-events/arch/x86/tremontx/virtual-memory.json b/tools/perf/pmu-events/arch/x86/tremontx/virtual-memory.json
new file mode 100644
index 000000000000..93e407a0f645
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tremontx/virtual-memory.json
@@ -0,0 +1,86 @@
+[
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Page walk completed due to a demand load to a 4K page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Page walk completed due to a demand load to a 2M or 4M page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walk completed due to a demand data store to a 4K page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walk completed due to a demand data store to a 2M or 4M page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) and new translation was filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.",
+ "EventCode": "0x81",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB.FILLS",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times there was an ITLB miss and a new translation was filled into the ITLB."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walk completed due to an instruction fetch in a 4K page."
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "PEBScounters": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Page walk completed due to an instruction fetch in a 2M or 4M page."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index 1a91a197cafb..d413761621b0 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -453,6 +453,7 @@ static struct fixed {
{ "inst_retired.any_p", "event=0xc0" },
{ "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" },
{ "cpu_clk_unhalted.thread", "event=0x3c" },
+ { "cpu_clk_unhalted.core", "event=0x3c" },
{ "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" },
{ NULL, NULL},
};
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index ead521dd8d79..25c47d23a130 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -19,7 +19,6 @@
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
-#include "../../../perf.h"
#include "../../../util/trace-event.h"
#ifndef PERL_UNUSED_VAR
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 217568bc29ce..0b7096847991 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -6,7 +6,6 @@
*/
#include <Python.h>
-#include "../../../perf.h"
#include "../../../util/trace-event.h"
#if PY_MAJOR_VERSION < 3
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index d8426547219b..a9599ab8c471 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -30,8 +30,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include "../perf.h"
+#include "../perf-sys.h"
#include <subcmd/exec-cmd.h>
+#include "event.h"
#include "tests.h"
#define ENV "PERF_TEST_ATTR"
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 1a9c3becf5ff..a637a4a90760 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -4,12 +4,14 @@
* beginning
*/
-#include <perf.h>
#include <evlist.h>
#include <sys/prctl.h>
+#include "record.h"
#include "tests.h"
#include "debug.h"
+#include "parse-events.h"
#include <errno.h>
+#include <linux/string.h>
#define NR_ITERS 111
@@ -25,7 +27,7 @@ static void testcase(void)
}
}
-static int count_samples(struct perf_evlist *evlist, int *sample_count,
+static int count_samples(struct evlist *evlist, int *sample_count,
int *comm_count)
{
int i;
@@ -55,7 +57,7 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
return TEST_OK;
}
-static int do_test(struct perf_evlist *evlist, int mmap_pages,
+static int do_test(struct evlist *evlist, int mmap_pages,
int *sample_count, int *comm_count)
{
int err;
@@ -68,9 +70,9 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
return TEST_FAIL;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
testcase();
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
err = count_samples(evlist, sample_count, comm_count);
perf_evlist__munmap(evlist);
@@ -82,8 +84,8 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
{
int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
char pid[16], sbuf[STRERR_BUFSIZE];
- struct perf_evlist *evlist;
- struct perf_evsel *evsel __maybe_unused;
+ struct evlist *evlist;
+ struct evsel *evsel __maybe_unused;
struct parse_events_error parse_error;
struct record_opts opts = {
.target = {
@@ -99,7 +101,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
pid[sizeof(pid) - 1] = '\0';
opts.target.tid = opts.target.pid = pid;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
pr_debug("Not enough memory to create evlist\n");
return TEST_FAIL;
@@ -125,7 +127,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
perf_evlist__config(evlist, &opts, NULL);
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -150,6 +152,6 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
ret = TEST_OK;
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return ret;
}
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
index 96e7fc1ad3f9..db2aadff3708 100644
--- a/tools/perf/tests/bitmap.c
+++ b/tools/perf/tests/bitmap.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <linux/bitmap.h>
+#include <perf/cpumap.h>
#include "tests.h"
#include "cpumap.h"
#include "debug.h"
@@ -9,7 +10,7 @@
static unsigned long *get_bitmap(const char *str, int nbits)
{
- struct cpu_map *map = cpu_map__new(str);
+ struct perf_cpu_map *map = perf_cpu_map__new(str);
unsigned long *bm = NULL;
int i;
@@ -21,7 +22,7 @@ static unsigned long *get_bitmap(const char *str, int nbits)
}
if (map)
- cpu_map__put(map);
+ perf_cpu_map__put(map);
return bm;
}
diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
index 153624e2d0f5..016bba2c142d 100644
--- a/tools/perf/tests/bp_account.c
+++ b/tools/perf/tests/bp_account.c
@@ -19,7 +19,8 @@
#include "tests.h"
#include "debug.h"
-#include "perf.h"
+#include "event.h"
+#include "../perf-sys.h"
#include "cloexec.h"
volatile long the_var;
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index 910e25e64188..c1c2c13de254 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -25,7 +25,8 @@
#include "tests.h"
#include "debug.h"
-#include "perf.h"
+#include "event.h"
+#include "perf-sys.h"
#include "cloexec.h"
static int fd1;
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
index ca962559e845..eb4dbbddf4ff 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -24,7 +24,8 @@
#include "tests.h"
#include "debug.h"
-#include "perf.h"
+#include "event.h"
+#include "../perf-sys.h"
#include "cloexec.h"
static int overflows;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index c9e4cdc4c9c8..fc102e4f403e 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -5,17 +5,20 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <util/record.h>
#include <util/util.h>
#include <util/bpf-loader.h>
#include <util/evlist.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <api/fs/fs.h>
#include <bpf/bpf.h>
#include "tests.h"
#include "llvm.h"
#include "debug.h"
+#include "parse-events.h"
#define NR_ITERS 111
#define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test"
@@ -118,7 +121,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
char pid[16];
char sbuf[STRERR_BUFSIZE];
- struct perf_evlist *evlist;
+ struct evlist *evlist;
int i, ret = TEST_FAIL, err = 0, count = 0;
struct parse_events_state parse_state;
@@ -140,7 +143,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
opts.target.tid = opts.target.pid = pid;
/* Instead of perf_evlist__new_default, don't add default events */
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
pr_debug("Not enough memory to create evlist\n");
return TEST_FAIL;
@@ -157,7 +160,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
perf_evlist__config(evlist, &opts, NULL);
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -171,9 +174,9 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
goto out_delete_evlist;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
(*func)();
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
for (i = 0; i < evlist->nr_mmaps; i++) {
union perf_event *event;
@@ -200,7 +203,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
ret = TEST_OK;
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return ret;
}
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index c3bec9d2c201..55774baffc2a 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/wait.h>
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index aa6df122b175..c1c29e08e7fb 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -8,8 +8,14 @@
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
+#include <perf/cpumap.h>
+#include <perf/evlist.h>
+#include "debug.h"
+#include "dso.h"
+#include "env.h"
#include "parse-events.h"
+#include "trace-event.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
@@ -18,6 +24,7 @@
#include "map.h"
#include "symbol.h"
#include "event.h"
+#include "record.h"
#include "thread.h"
#include "tests.h"
@@ -362,7 +369,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
}
static int process_sample_event(struct machine *machine,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
union perf_event *event, struct state *state)
{
struct perf_sample sample;
@@ -385,7 +392,7 @@ static int process_sample_event(struct machine *machine,
return ret;
}
-static int process_event(struct machine *machine, struct perf_evlist *evlist,
+static int process_event(struct machine *machine, struct evlist *evlist,
union perf_event *event, struct state *state)
{
if (event->header.type == PERF_RECORD_SAMPLE)
@@ -408,7 +415,7 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist,
return 0;
}
-static int process_events(struct machine *machine, struct perf_evlist *evlist,
+static int process_events(struct machine *machine, struct evlist *evlist,
struct state *state)
{
union perf_event *event;
@@ -491,6 +498,10 @@ static void fs_something(void)
}
}
+#ifdef __s390x__
+#include "header.h" // for get_cpuid()
+#endif
+
static const char *do_determine_event(bool excl_kernel)
{
const char *event = excl_kernel ? "cycles:u" : "cycles";
@@ -552,10 +563,10 @@ static int do_test_code_reading(bool try_kcore)
struct state state = {
.done_cnt = 0,
};
- struct thread_map *threads = NULL;
- struct cpu_map *cpus = NULL;
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel = NULL;
+ struct perf_thread_map *threads = NULL;
+ struct perf_cpu_map *cpus = NULL;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel = NULL;
int err = -1, ret;
pid_t pid;
struct map *map;
@@ -613,22 +624,22 @@ static int do_test_code_reading(bool try_kcore)
goto out_put;
}
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (!cpus) {
- pr_debug("cpu_map__new failed\n");
+ pr_debug("perf_cpu_map__new failed\n");
goto out_put;
}
while (1) {
const char *str;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
pr_debug("perf_evlist__new failed\n");
goto out_put;
}
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
str = do_determine_event(excl_kernel);
pr_debug("Parsing event '%s'\n", str);
@@ -642,11 +653,11 @@ static int do_test_code_reading(bool try_kcore)
evsel = perf_evlist__first(evlist);
- evsel->attr.comm = 1;
- evsel->attr.disabled = 1;
- evsel->attr.enable_on_exec = 0;
+ evsel->core.attr.comm = 1;
+ evsel->core.attr.disabled = 1;
+ evsel->core.attr.enable_on_exec = 0;
- ret = perf_evlist__open(evlist);
+ ret = evlist__open(evlist);
if (ret < 0) {
if (!excl_kernel) {
excl_kernel = true;
@@ -655,10 +666,10 @@ static int do_test_code_reading(bool try_kcore)
* and will be freed by following perf_evlist__set_maps
* call. Getting refference to keep them alive.
*/
- cpu_map__get(cpus);
- thread_map__get(threads);
- perf_evlist__set_maps(evlist, NULL, NULL);
- perf_evlist__delete(evlist);
+ perf_cpu_map__get(cpus);
+ perf_thread_map__get(threads);
+ perf_evlist__set_maps(&evlist->core, NULL, NULL);
+ evlist__delete(evlist);
evlist = NULL;
continue;
}
@@ -680,11 +691,11 @@ static int do_test_code_reading(bool try_kcore)
goto out_put;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
do_something();
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
ret = process_events(machine, evlist, &state);
if (ret < 0)
@@ -703,10 +714,10 @@ out_put:
out_err:
if (evlist) {
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
} else {
- cpu_map__put(cpus);
- thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ perf_thread_map__put(threads);
}
machine__delete_threads(machine);
machine__delete(machine);
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index e78b897677bd..39493de50117 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -5,6 +5,7 @@
#include "event.h"
#include <string.h>
#include <linux/bitops.h>
+#include <perf/cpumap.h>
#include "debug.h"
struct machine;
@@ -14,17 +15,17 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct cpu_map_event *map_event = &event->cpu_map;
- struct cpu_map_mask *mask;
- struct cpu_map_data *data;
- struct cpu_map *map;
+ struct perf_record_cpu_map *map_event = &event->cpu_map;
+ struct perf_record_record_cpu_map *mask;
+ struct perf_record_cpu_map_data *data;
+ struct perf_cpu_map *map;
int i;
data = &map_event->data;
TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
- mask = (struct cpu_map_mask *)data->data;
+ mask = (struct perf_record_record_cpu_map *)data->data;
TEST_ASSERT_VAL("wrong nr", mask->nr == 1);
@@ -39,7 +40,7 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
TEST_ASSERT_VAL("wrong cpu", map->map[i] == i);
}
- cpu_map__put(map);
+ perf_cpu_map__put(map);
return 0;
}
@@ -48,10 +49,10 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct cpu_map_event *map_event = &event->cpu_map;
+ struct perf_record_cpu_map *map_event = &event->cpu_map;
struct cpu_map_entries *cpus;
- struct cpu_map_data *data;
- struct cpu_map *map;
+ struct perf_record_cpu_map_data *data;
+ struct perf_cpu_map *map;
data = &map_event->data;
@@ -68,36 +69,36 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1);
TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256);
TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1);
- cpu_map__put(map);
+ perf_cpu_map__put(map);
return 0;
}
int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
/* This one is better stores in mask. */
- cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
+ cpus = perf_cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
TEST_ASSERT_VAL("failed to synthesize map",
!perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL));
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
/* This one is better stores in cpu values. */
- cpus = cpu_map__new("1,256");
+ cpus = perf_cpu_map__new("1,256");
TEST_ASSERT_VAL("failed to synthesize map",
!perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL));
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
return 0;
}
static int cpu_map_print(const char *str)
{
- struct cpu_map *map = cpu_map__new(str);
+ struct perf_cpu_map *map = perf_cpu_map__new(str);
char buf[100];
if (!map)
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 946ab4b63acd..a4874d4ce7ef 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -9,6 +9,7 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <api/fs/fs.h>
+#include "dso.h"
#include "util.h"
#include "machine.h"
#include "symbol.h"
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index f33709a79335..4125255ff637 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/zalloc.h>
#include <inttypes.h>
+#include <limits.h>
#include <unistd.h>
#include "tests.h"
#include "debug.h"
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 1a2686f1fcf0..d824a726906c 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -1,20 +1,23 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
+#include <linux/string.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#include <sys/wait.h>
+#include <perf/cpumap.h>
#include "tests.h"
#include "evlist.h"
#include "evsel.h"
#include "util.h"
#include "debug.h"
+#include "parse-events.h"
#include "thread_map.h"
#include "target.h"
-static int attach__enable_on_exec(struct perf_evlist *evlist)
+static int attach__enable_on_exec(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
+ struct evsel *evsel = perf_evlist__last(evlist);
struct target target = {
.uid = UINT_MAX,
};
@@ -36,9 +39,9 @@ static int attach__enable_on_exec(struct perf_evlist *evlist)
return err;
}
- evsel->attr.enable_on_exec = 1;
+ evsel->core.attr.enable_on_exec = 1;
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -48,16 +51,16 @@ static int attach__enable_on_exec(struct perf_evlist *evlist)
return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
}
-static int detach__enable_on_exec(struct perf_evlist *evlist)
+static int detach__enable_on_exec(struct evlist *evlist)
{
waitpid(evlist->workload.pid, NULL, 0);
return 0;
}
-static int attach__current_disabled(struct perf_evlist *evlist)
+static int attach__current_disabled(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
- struct thread_map *threads;
+ struct evsel *evsel = perf_evlist__last(evlist);
+ struct perf_thread_map *threads;
int err;
pr_debug("attaching to current thread as disabled\n");
@@ -68,7 +71,7 @@ static int attach__current_disabled(struct perf_evlist *evlist)
return -1;
}
- evsel->attr.disabled = 1;
+ evsel->core.attr.disabled = 1;
err = perf_evsel__open_per_thread(evsel, threads);
if (err) {
@@ -76,14 +79,14 @@ static int attach__current_disabled(struct perf_evlist *evlist)
return err;
}
- thread_map__put(threads);
- return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
+ perf_thread_map__put(threads);
+ return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
}
-static int attach__current_enabled(struct perf_evlist *evlist)
+static int attach__current_enabled(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
- struct thread_map *threads;
+ struct evsel *evsel = perf_evlist__last(evlist);
+ struct perf_thread_map *threads;
int err;
pr_debug("attaching to current thread as enabled\n");
@@ -96,32 +99,32 @@ static int attach__current_enabled(struct perf_evlist *evlist)
err = perf_evsel__open_per_thread(evsel, threads);
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return err == 0 ? TEST_OK : TEST_FAIL;
}
-static int detach__disable(struct perf_evlist *evlist)
+static int detach__disable(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
+ struct evsel *evsel = perf_evlist__last(evlist);
- return perf_evsel__enable(evsel);
+ return evsel__enable(evsel);
}
-static int attach__cpu_disabled(struct perf_evlist *evlist)
+static int attach__cpu_disabled(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
- struct cpu_map *cpus;
+ struct evsel *evsel = perf_evlist__last(evlist);
+ struct perf_cpu_map *cpus;
int err;
pr_debug("attaching to CPU 0 as enabled\n");
- cpus = cpu_map__new("0");
+ cpus = perf_cpu_map__new("0");
if (cpus == NULL) {
- pr_debug("failed to call cpu_map__new\n");
+ pr_debug("failed to call perf_cpu_map__new\n");
return -1;
}
- evsel->attr.disabled = 1;
+ evsel->core.attr.disabled = 1;
err = perf_evsel__open_per_cpu(evsel, cpus);
if (err) {
@@ -132,21 +135,21 @@ static int attach__cpu_disabled(struct perf_evlist *evlist)
return err;
}
- cpu_map__put(cpus);
- return perf_evsel__enable(evsel);
+ perf_cpu_map__put(cpus);
+ return evsel__enable(evsel);
}
-static int attach__cpu_enabled(struct perf_evlist *evlist)
+static int attach__cpu_enabled(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__last(evlist);
- struct cpu_map *cpus;
+ struct evsel *evsel = perf_evlist__last(evlist);
+ struct perf_cpu_map *cpus;
int err;
pr_debug("attaching to CPU 0 as enabled\n");
- cpus = cpu_map__new("0");
+ cpus = perf_cpu_map__new("0");
if (cpus == NULL) {
- pr_debug("failed to call cpu_map__new\n");
+ pr_debug("failed to call perf_cpu_map__new\n");
return -1;
}
@@ -154,19 +157,19 @@ static int attach__cpu_enabled(struct perf_evlist *evlist)
if (err == -EACCES)
return TEST_SKIP;
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
return err ? TEST_FAIL : TEST_OK;
}
-static int test_times(int (attach)(struct perf_evlist *),
- int (detach)(struct perf_evlist *))
+static int test_times(int (attach)(struct evlist *),
+ int (detach)(struct evlist *))
{
struct perf_counts_values count;
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel;
int err = -1, i;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
pr_debug("failed to create event list\n");
goto out_err;
@@ -179,7 +182,7 @@ static int test_times(int (attach)(struct perf_evlist *),
}
evsel = perf_evlist__last(evlist);
- evsel->attr.read_format |=
+ evsel->core.attr.read_format |=
PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
@@ -195,7 +198,7 @@ static int test_times(int (attach)(struct perf_evlist *),
TEST_ASSERT_VAL("failed to detach", !detach(evlist));
- perf_evsel__read(evsel, 0, 0, &count);
+ perf_evsel__read(&evsel->core, 0, 0, &count);
err = !(count.ena == count.run);
@@ -204,7 +207,7 @@ static int test_times(int (attach)(struct perf_evlist *),
count.ena, count.run);
out_err:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return !err ? TEST_OK : TEST_FAIL;
}
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index f14dcd613438..cac4290e233a 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -1,8 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
+#include <perf/cpumap.h>
+#include <string.h>
#include "evlist.h"
#include "evsel.h"
+#include "header.h"
#include "machine.h"
+#include "tool.h"
#include "tests.h"
#include "debug.h"
@@ -11,7 +15,7 @@ static int process_event_unit(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct event_update_event *ev = (struct event_update_event *) event;
+ struct perf_record_event_update *ev = (struct perf_record_event_update *)event;
TEST_ASSERT_VAL("wrong id", ev->id == 123);
TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__UNIT);
@@ -24,10 +28,10 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct event_update_event *ev = (struct event_update_event *) event;
- struct event_update_event_scale *ev_data;
+ struct perf_record_event_update *ev = (struct perf_record_event_update *)event;
+ struct perf_record_event_update_scale *ev_data;
- ev_data = (struct event_update_event_scale *) ev->data;
+ ev_data = (struct perf_record_event_update_scale *)ev->data;
TEST_ASSERT_VAL("wrong id", ev->id == 123);
TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
@@ -46,7 +50,7 @@ static int process_event_name(struct perf_tool *tool,
struct machine *machine __maybe_unused)
{
struct event_name *tmp = container_of(tool, struct event_name, tool);
- struct event_update_event *ev = (struct event_update_event*) event;
+ struct perf_record_event_update *ev = (struct perf_record_event_update *)event;
TEST_ASSERT_VAL("wrong id", ev->id == 123);
TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__NAME);
@@ -59,11 +63,11 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct event_update_event *ev = (struct event_update_event*) event;
- struct event_update_event_cpus *ev_data;
- struct cpu_map *map;
+ struct perf_record_event_update *ev = (struct perf_record_event_update *)event;
+ struct perf_record_event_update_cpus *ev_data;
+ struct perf_cpu_map *map;
- ev_data = (struct event_update_event_cpus*) ev->data;
+ ev_data = (struct perf_record_event_update_cpus *) ev->data;
map = cpu_map__new_data(&ev_data->cpus);
@@ -73,14 +77,14 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
TEST_ASSERT_VAL("wrong cpus", map->map[0] == 1);
TEST_ASSERT_VAL("wrong cpus", map->map[1] == 2);
TEST_ASSERT_VAL("wrong cpus", map->map[2] == 3);
- cpu_map__put(map);
+ perf_cpu_map__put(map);
return 0;
}
int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct perf_evlist *evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist;
+ struct evsel *evsel;
struct event_name tmp;
evlist = perf_evlist__new_default();
@@ -108,11 +112,11 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
TEST_ASSERT_VAL("failed to synthesize attr update name",
!perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
- evsel->own_cpus = cpu_map__new("1,2,3");
+ evsel->core.own_cpus = perf_cpu_map__new("1,2,3");
TEST_ASSERT_VAL("failed to synthesize attr update cpus",
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
- cpu_map__put(evsel->own_cpus);
+ perf_cpu_map__put(evsel->core.own_cpus);
return 0;
}
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index a104728ebf25..5330f106a6ee 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -11,8 +11,8 @@ static int perf_evsel__roundtrip_cache_name_test(void)
{
char name[128];
int type, op, err = 0, ret = 0, i, idx;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel;
+ struct evlist *evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
@@ -60,15 +60,15 @@ static int perf_evsel__roundtrip_cache_name_test(void)
}
}
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return ret;
}
static int __perf_evsel__name_array_test(const char *names[], int nr_names)
{
int i, err;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel;
+ struct evlist *evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
@@ -91,7 +91,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
}
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 71f60c0f9faa..261e6eaaee99 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -5,7 +5,7 @@
#include "tests.h"
#include "debug.h"
-static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
+static int perf_evsel__test_field(struct evsel *evsel, const char *name,
int size, bool should_be_signed)
{
struct tep_format_field *field = perf_evsel__field(evsel, name);
@@ -35,7 +35,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
+ struct evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
int ret = 0;
if (IS_ERR(evsel)) {
@@ -64,7 +64,7 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes
if (perf_evsel__test_field(evsel, "next_prio", 4, true))
ret = -1;
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
evsel = perf_evsel__newtp("sched", "sched_wakeup");
@@ -85,6 +85,6 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes
if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
ret = -1;
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
return ret;
}
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index ee1d88650e69..87843af4c118 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -3,6 +3,7 @@
#include "util/expr.h"
#include "tests.h"
#include <stdlib.h>
+#include <string.h>
#include <linux/zalloc.h>
static int test(struct parse_ctx *ctx, const char *e, double val2)
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index 469958cd7fe0..de110d8f169b 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
#include <inttypes.h>
-#include "perf.h"
#include "util/debug.h"
+#include "util/dso.h"
#include "util/map.h"
#include "util/symbol.h"
#include "util/sort.h"
#include "util/evsel.h"
-#include "util/evlist.h"
#include "util/machine.h"
#include "util/thread.h"
#include "tests/hists_common.h"
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 7a2eed6c783e..fa55b7bad3af 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
#include "util/debug.h"
+#include "util/dso.h"
#include "util/event.h"
#include "util/map.h"
#include "util/symbol.h"
@@ -80,7 +80,7 @@ static u64 fake_callchains[][10] = {
static int add_hist_entries(struct hists *hists, struct machine *machine)
{
struct addr_location al;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
struct perf_sample sample = { .period = 1000, };
size_t i;
@@ -147,7 +147,7 @@ static void del_hist_entries(struct hists *hists)
}
}
-typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
+typedef int (*test_fn_t)(struct evsel *, struct machine *);
#define COMM(he) (thread__comm_str(he->thread))
#define DSO(he) (he->ms.map->dso->short_name)
@@ -247,7 +247,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
}
/* NO callchain + NO children */
-static int test1(struct perf_evsel *evsel, struct machine *machine)
+static int test1(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -298,7 +298,7 @@ out:
}
/* callcain + NO children */
-static int test2(struct perf_evsel *evsel, struct machine *machine)
+static int test2(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -446,7 +446,7 @@ out:
}
/* NO callchain + children */
-static int test3(struct perf_evsel *evsel, struct machine *machine)
+static int test3(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -503,7 +503,7 @@ out:
}
/* callchain + children */
-static int test4(struct perf_evsel *evsel, struct machine *machine)
+static int test4(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -694,8 +694,8 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u
int err = TEST_FAIL;
struct machines machines;
struct machine *machine;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel;
+ struct evlist *evlist = evlist__new();
size_t i;
test_fn_t testcases[] = {
test1,
@@ -731,7 +731,7 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u
out:
/* tear down everything */
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
machines__exit(&machines);
return err;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 975844807fe2..618b51ffcc01 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
#include "util/debug.h"
#include "util/map.h"
#include "util/symbol.h"
@@ -8,7 +7,6 @@
#include "util/event.h"
#include "util/evlist.h"
#include "util/machine.h"
-#include "util/thread.h"
#include "util/parse-events.h"
#include "tests/tests.h"
#include "tests/hists_common.h"
@@ -47,10 +45,10 @@ static struct sample fake_samples[] = {
{ .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
};
-static int add_hist_entries(struct perf_evlist *evlist,
+static int add_hist_entries(struct evlist *evlist,
struct machine *machine)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct addr_location al;
struct perf_sample sample = { .period = 100, };
size_t i;
@@ -108,8 +106,8 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu
int err = TEST_FAIL;
struct machines machines;
struct machine *machine;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel;
+ struct evlist *evlist = evlist__new();
TEST_ASSERT_VAL("No memory", evlist);
@@ -321,7 +319,7 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu
out:
/* tear down everything */
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
reset_output_field();
machines__exit(&machines);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index af633db63f4d..8be4d0b61e3a 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
#include "tests.h"
#include "debug.h"
#include "symbol.h"
@@ -7,7 +6,6 @@
#include "evsel.h"
#include "evlist.h"
#include "machine.h"
-#include "thread.h"
#include "parse-events.h"
#include "hists_common.h"
#include <errno.h>
@@ -62,9 +60,9 @@ static struct sample fake_samples[][5] = {
},
};
-static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
+static int add_hist_entries(struct evlist *evlist, struct machine *machine)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct addr_location al;
struct hist_entry *he;
struct perf_sample sample = { .period = 1, .weight = 1, };
@@ -271,8 +269,8 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse
struct hists *hists, *first_hists;
struct machines machines;
struct machine *machine = NULL;
- struct perf_evsel *evsel, *first;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel, *first;
+ struct evlist *evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
@@ -334,7 +332,7 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse
out:
/* tear down everything */
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
reset_output_field();
machines__exit(&machines);
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 0a510c524a5d..3f6dfa212260 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
#include "util/debug.h"
+#include "util/dso.h"
#include "util/event.h"
#include "util/map.h"
#include "util/symbol.h"
@@ -50,7 +50,7 @@ static struct sample fake_samples[] = {
static int add_hist_entries(struct hists *hists, struct machine *machine)
{
struct addr_location al;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
struct perf_sample sample = { .period = 100, };
size_t i;
@@ -113,7 +113,7 @@ static void del_hist_entries(struct hists *hists)
}
}
-typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
+typedef int (*test_fn_t)(struct evsel *, struct machine *);
#define COMM(he) (thread__comm_str(he->thread))
#define DSO(he) (he->ms.map->dso->short_name)
@@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
#define PID(he) (he->thread->tid)
/* default sort keys (no field) */
-static int test1(struct perf_evsel *evsel, struct machine *machine)
+static int test1(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -224,7 +224,7 @@ out:
}
/* mixed fields and sort keys */
-static int test2(struct perf_evsel *evsel, struct machine *machine)
+static int test2(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -280,7 +280,7 @@ out:
}
/* fields only (no sort key) */
-static int test3(struct perf_evsel *evsel, struct machine *machine)
+static int test3(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -354,7 +354,7 @@ out:
}
/* handle duplicate 'dso' field */
-static int test4(struct perf_evsel *evsel, struct machine *machine)
+static int test4(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -456,7 +456,7 @@ out:
}
/* full sort keys w/o overhead field */
-static int test5(struct perf_evsel *evsel, struct machine *machine)
+static int test5(struct evsel *evsel, struct machine *machine)
{
int err;
struct hists *hists = evsel__hists(evsel);
@@ -580,8 +580,8 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu
int err = TEST_FAIL;
struct machines machines;
struct machine *machine;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evsel *evsel;
+ struct evlist *evlist = evlist__new();
size_t i;
test_fn_t testcases[] = {
test1,
@@ -618,7 +618,7 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu
out:
/* tear down everything */
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
machines__exit(&machines);
return err;
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 17c46f3e6f1e..9f0762d987fa 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -1,11 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
+#include <limits.h>
#include <unistd.h>
#include <sys/prctl.h>
+#include <perf/cpumap.h>
+#include <perf/evlist.h>
+#include "debug.h"
#include "parse-events.h"
#include "evlist.h"
#include "evsel.h"
+#include "record.h"
#include "thread_map.h"
#include "cpumap.h"
#include "tests.h"
@@ -24,7 +29,7 @@
} \
}
-static int find_comm(struct perf_evlist *evlist, const char *comm)
+static int find_comm(struct evlist *evlist, const char *comm)
{
union perf_event *event;
struct perf_mmap *md;
@@ -65,23 +70,23 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
.uses_mmap = true,
},
};
- struct thread_map *threads = NULL;
- struct cpu_map *cpus = NULL;
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel = NULL;
+ struct perf_thread_map *threads = NULL;
+ struct perf_cpu_map *cpus = NULL;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel = NULL;
int found, err = -1;
const char *comm;
threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads);
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
CHECK_NOT_NULL__(cpus);
- evlist = perf_evlist__new();
+ evlist = evlist__new();
CHECK_NOT_NULL__(evlist);
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
CHECK__(parse_events(evlist, "dummy:u", NULL));
CHECK__(parse_events(evlist, "cycles:u", NULL));
@@ -90,11 +95,11 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
evsel = perf_evlist__first(evlist);
- evsel->attr.comm = 1;
- evsel->attr.disabled = 1;
- evsel->attr.enable_on_exec = 0;
+ evsel->core.attr.comm = 1;
+ evsel->core.attr.disabled = 1;
+ evsel->core.attr.enable_on_exec = 0;
- if (perf_evlist__open(evlist) < 0) {
+ if (evlist__open(evlist) < 0) {
pr_debug("Unable to open dummy and cycles event\n");
err = TEST_SKIP;
goto out_err;
@@ -107,12 +112,12 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
* enabled.
*/
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
comm = "Test COMM 1";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
found = find_comm(evlist, comm);
if (found != 1) {
@@ -125,16 +130,16 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
* disabled with the dummy event still enabled.
*/
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
evsel = perf_evlist__last(evlist);
- CHECK__(perf_evsel__disable(evsel));
+ CHECK__(evsel__disable(evsel));
comm = "Test COMM 2";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
found = find_comm(evlist, comm);
if (found != 1) {
@@ -146,11 +151,11 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
out_err:
if (evlist) {
- perf_evlist__disable(evlist);
- perf_evlist__delete(evlist);
+ evlist__disable(evlist);
+ evlist__delete(evlist);
} else {
- cpu_map__put(cpus);
- thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ perf_thread_map__put(threads);
}
return err;
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 0579a70bbbff..e483210b176b 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
#include "tests.h"
#include "dso.h"
#include "debug.h"
+#include "event.h"
static int test(const char *path, bool alloc_name, bool kmod,
int comp, const char *name)
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index ca5a5f94ce79..022e4c9cf092 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <bpf/libbpf.h>
#include <util/llvm-utils.h>
-#include <util/cache.h>
#include "llvm.h"
#include "tests.h"
#include "debug.h"
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 5363a12a8b9b..70c48475896d 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -108,6 +108,7 @@ make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1
+make_minimal += NO_LIBCAP=1
# $(run) contains all available tests
run := make_pure
diff --git a/tools/perf/tests/mem.c b/tools/perf/tests/mem.c
index efe3397824d2..673a11a6cd1b 100644
--- a/tools/perf/tests/mem.c
+++ b/tools/perf/tests/mem.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "util/map_symbol.h"
#include "util/mem-events.h"
#include "util/symbol.h"
#include "linux/perf_event.h"
diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c
index 520cc91af256..7672ade70f20 100644
--- a/tools/perf/tests/mem2node.c
+++ b/tools/perf/tests/mem2node.c
@@ -1,8 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <linux/bitmap.h>
+#include <linux/kernel.h>
#include <linux/zalloc.h>
+#include <perf/cpumap.h>
#include "cpumap.h"
+#include "debug.h"
+#include "env.h"
#include "mem2node.h"
#include "tests.h"
@@ -19,7 +23,7 @@ static struct node {
static unsigned long *get_bitmap(const char *str, int nbits)
{
- struct cpu_map *map = cpu_map__new(str);
+ struct perf_cpu_map *map = perf_cpu_map__new(str);
unsigned long *bm = NULL;
int i;
@@ -32,7 +36,7 @@ static unsigned long *get_bitmap(const char *str, int nbits)
}
if (map)
- cpu_map__put(map);
+ perf_cpu_map__put(map);
else
free(bm);
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 0919b0793e5b..85e1d7337dc0 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -3,7 +3,10 @@
#include <inttypes.h>
/* For the CLR_() macros */
#include <pthread.h>
+#include <stdlib.h>
+#include <perf/cpumap.h>
+#include "debug.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
@@ -11,6 +14,8 @@
#include "tests.h"
#include <linux/err.h>
#include <linux/kernel.h>
+#include <linux/string.h>
+#include <perf/evlist.h>
/*
* This test will generate random numbers of calls to some getpid syscalls,
@@ -27,16 +32,16 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
{
int err = -1;
union perf_event *event;
- struct thread_map *threads;
- struct cpu_map *cpus;
- struct perf_evlist *evlist;
+ struct perf_thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct evlist *evlist;
cpu_set_t cpu_set;
const char *syscall_names[] = { "getsid", "getppid", "getpgid", };
pid_t (*syscalls[])(void) = { (void *)getsid, getppid, (void*)getpgid };
#define nsyscalls ARRAY_SIZE(syscall_names)
unsigned int nr_events[nsyscalls],
expected_nr_events[nsyscalls], i, j;
- struct perf_evsel *evsels[nsyscalls], *evsel;
+ struct evsel *evsels[nsyscalls], *evsel;
char sbuf[STRERR_BUFSIZE];
struct perf_mmap *md;
@@ -46,7 +51,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
return -1;
}
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (cpus == NULL) {
pr_debug("cpu_map__new\n");
goto out_free_threads;
@@ -61,13 +66,13 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
goto out_free_cpus;
}
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (evlist == NULL) {
pr_debug("perf_evlist__new\n");
goto out_free_cpus;
}
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
for (i = 0; i < nsyscalls; ++i) {
char name[64];
@@ -79,12 +84,12 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
goto out_delete_evlist;
}
- evsels[i]->attr.wakeup_events = 1;
+ evsels[i]->core.attr.wakeup_events = 1;
perf_evsel__set_sample_id(evsels[i], false);
- perf_evlist__add(evlist, evsels[i]);
+ evlist__add(evlist, evsels[i]);
- if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
+ if (evsel__open(evsels[i], cpus, threads) < 0) {
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -151,12 +156,12 @@ out_init:
}
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
cpus = NULL;
threads = NULL;
out_free_cpus:
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
out_free_threads:
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return err;
}
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 0a4301a5155c..360d70deb855 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -138,7 +138,7 @@ static int synth_all(struct machine *machine)
static int synth_process(struct machine *machine)
{
- struct thread_map *map;
+ struct perf_thread_map *map;
int err;
map = thread_map__new_by_pid(getpid());
@@ -147,7 +147,7 @@ static int synth_process(struct machine *machine)
perf_event__process,
machine, 0);
- thread_map__put(map);
+ perf_thread_map__put(map);
return err;
}
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 493ecb611540..9171f77cd9cd 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <api/fs/fs.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <api/fs/tracing_path.h>
#include "evsel.h"
#include "tests.h"
@@ -16,15 +17,16 @@
#include "cpumap.h"
#include "debug.h"
#include "stat.h"
+#include "util/counts.h"
int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
{
int err = -1, fd, cpu;
- struct cpu_map *cpus;
- struct perf_evsel *evsel;
+ struct perf_cpu_map *cpus;
+ struct evsel *evsel;
unsigned int nr_openat_calls = 111, i;
cpu_set_t cpu_set;
- struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
+ struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
char sbuf[STRERR_BUFSIZE];
char errbuf[BUFSIZ];
@@ -33,7 +35,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int
return -1;
}
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (cpus == NULL) {
pr_debug("cpu_map__new\n");
goto out_thread_map_delete;
@@ -48,7 +50,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int
goto out_cpu_map_delete;
}
- if (perf_evsel__open(evsel, cpus, threads) < 0) {
+ if (evsel__open(evsel, cpus, threads) < 0) {
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -116,12 +118,12 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int
perf_evsel__free_counts(evsel);
out_close_fd:
- perf_evsel__close_fd(evsel);
+ perf_evsel__close_fd(&evsel->core);
out_evsel_delete:
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
out_cpu_map_delete:
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
out_thread_map_delete:
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return err;
}
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 344dc3ac2469..b71167b43dda 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
+#include <stdbool.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include "perf.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
+#include "record.h"
#include "tests.h"
#include "debug.h"
#include <errno.h>
@@ -32,8 +34,8 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
};
const char *filename = "/etc/passwd";
int flags = O_RDONLY | O_DIRECTORY;
- struct perf_evlist *evlist = perf_evlist__new();
- struct perf_evsel *evsel;
+ struct evlist *evlist = evlist__new();
+ struct evsel *evsel;
int err = -1, i, nr_events = 0, nr_polls = 0;
char sbuf[STRERR_BUFSIZE];
@@ -48,7 +50,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
goto out_delete_evlist;
}
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
err = perf_evlist__create_maps(evlist, &opts.target);
if (err < 0) {
@@ -58,9 +60,9 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
perf_evsel__config(evsel, &opts, NULL);
- thread_map__set_pid(evlist->threads, 0, getpid());
+ perf_thread_map__set_pid(evlist->core.threads, 0, getpid());
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -74,7 +76,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
goto out_delete_evlist;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
/*
* Generate the event:
@@ -134,7 +136,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
out_ok:
err = 0;
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
out:
return err;
}
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 00cd63f90b92..5ebffae18605 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <api/fs/tracing_path.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -10,13 +11,14 @@
#include "evsel.h"
#include "debug.h"
#include "tests.h"
+#include "util/counts.h"
int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused)
{
int err = -1, fd;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
unsigned int nr_openat_calls = 111, i;
- struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
+ struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
char sbuf[STRERR_BUFSIZE];
char errbuf[BUFSIZ];
@@ -57,10 +59,10 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __m
err = 0;
out_close_fd:
- perf_evsel__close_fd(evsel);
+ perf_evsel__close_fd(&evsel->core);
out_evsel_delete:
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
out_thread_map_delete:
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return err;
}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 8f3c80e13584..02ba696fb87f 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -5,6 +5,7 @@
#include <api/fs/fs.h>
#include "tests.h"
#include "debug.h"
+#include "pmu.h"
#include "util.h"
#include <dirent.h>
#include <errno.h>
@@ -44,549 +45,549 @@ static bool kvm_s390_create_vm_valid(void)
}
#endif
-static int test__checkevent_tracepoint(struct perf_evlist *evlist)
+static int test__checkevent_tracepoint(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
+ PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period);
return 0;
}
-static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
+static int test__checkevent_tracepoint_multi(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
- TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+ TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1);
TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
evlist__for_each_entry(evlist, evsel) {
TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ PERF_TYPE_TRACEPOINT == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
+ PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type);
TEST_ASSERT_VAL("wrong sample_period",
- 1 == evsel->attr.sample_period);
+ 1 == evsel->core.attr.sample_period);
}
return 0;
}
-static int test__checkevent_raw(struct perf_evlist *evlist)
+static int test__checkevent_raw(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_numeric(struct perf_evlist *evlist)
+static int test__checkevent_numeric(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
+static int test__checkevent_symbolic_name(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
+static int test__checkevent_symbolic_name_config(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
/*
* The period value gets configured within perf_evlist__config,
* while this test executes only parse events method.
*/
TEST_ASSERT_VAL("wrong period",
- 0 == evsel->attr.sample_period);
+ 0 == evsel->core.attr.sample_period);
TEST_ASSERT_VAL("wrong config1",
- 0 == evsel->attr.config1);
+ 0 == evsel->core.attr.config1);
TEST_ASSERT_VAL("wrong config2",
- 1 == evsel->attr.config2);
+ 1 == evsel->core.attr.config2);
return 0;
}
-static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
+static int test__checkevent_symbolic_alias(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
+ PERF_COUNT_SW_PAGE_FAULTS == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_genhw(struct perf_evlist *evlist)
+static int test__checkevent_genhw(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_breakpoint(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
- evsel->attr.bp_type);
+ evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
- evsel->attr.bp_len);
+ evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_x(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_X == evsel->attr.bp_type);
- TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
+ HW_BREAKPOINT_X == evsel->core.attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_r(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_R == evsel->attr.bp_type);
+ HW_BREAKPOINT_R == evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len",
- HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_w(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_W == evsel->attr.bp_type);
+ HW_BREAKPOINT_W == evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len",
- HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_rw(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type",
- (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
+ (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len",
- HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
+static int test__checkevent_tracepoint_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_tracepoint(evlist);
}
static int
-test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
+test__checkevent_tracepoint_multi_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
- TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+ TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1);
evlist__for_each_entry(evlist, evsel) {
TEST_ASSERT_VAL("wrong exclude_user",
- !evsel->attr.exclude_user);
+ !evsel->core.attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel",
- evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
}
return test__checkevent_tracepoint_multi(evlist);
}
-static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
+static int test__checkevent_raw_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
return test__checkevent_raw(evlist);
}
-static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
+static int test__checkevent_numeric_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
return test__checkevent_numeric(evlist);
}
-static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
+static int test__checkevent_symbolic_name_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_symbolic_name(evlist);
}
-static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
+static int test__checkevent_exclude_host_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
return test__checkevent_symbolic_name(evlist);
}
-static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
+static int test__checkevent_exclude_guest_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
return test__checkevent_symbolic_name(evlist);
}
-static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
+static int test__checkevent_symbolic_alias_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_symbolic_alias(evlist);
}
-static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
+static int test__checkevent_genhw_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
return test__checkevent_genhw(evlist);
}
-static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist)
+static int test__checkevent_exclude_idle_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_symbolic_name(evlist);
}
-static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist)
+static int test__checkevent_exclude_idle_modifier_1(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_symbolic_name(evlist);
}
-static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "mem:0:u"));
return test__checkevent_breakpoint(evlist);
}
-static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_x_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "mem:0:x:k"));
return test__checkevent_breakpoint_x(evlist);
}
-static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_r_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "mem:0:r:hp"));
return test__checkevent_breakpoint_r(evlist);
}
-static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_w_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "mem:0:w:up"));
return test__checkevent_breakpoint_w(evlist);
}
-static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_rw_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "mem:0:rw:kp"));
return test__checkevent_breakpoint_rw(evlist);
}
-static int test__checkevent_pmu(struct perf_evlist *evlist)
+static int test__checkevent_pmu(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1);
- TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 10 == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1);
+ TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2);
/*
* The period value gets configured within perf_evlist__config,
* while this test executes only parse events method.
*/
- TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period);
return 0;
}
-static int test__checkevent_list(struct perf_evlist *evlist)
+static int test__checkevent_list(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries);
/* r1 */
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
- TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1);
+ TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
/* syscalls:sys_enter_openat:k */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
/* 1:1:hp */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
return 0;
}
-static int test__checkevent_pmu_name(struct perf_evlist *evlist)
+static int test__checkevent_pmu_name(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
/* cpu/config=1,name=krava/u */
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
/* cpu/config=2/u" */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong name",
!strcmp(perf_evsel__name(evsel), "cpu/config=2/u"));
return 0;
}
-static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlist)
+static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
/* cpu/config=1,call-graph=fp,time,period=100000/ */
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config);
/*
* The period, time and callgraph value gets configured
* within perf_evlist__config,
* while this test executes only parse events method.
*/
- TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period);
TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel));
- TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
+ TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type));
/* cpu/config=2,call-graph=no,time=0,period=2000/ */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config);
/*
* The period, time and callgraph value gets configured
* within perf_evlist__config,
* while this test executes only parse events method.
*/
- TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period);
TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel));
- TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
+ TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type));
return 0;
}
-static int test__checkevent_pmu_events(struct perf_evlist *evlist)
+static int test__checkevent_pmu_events(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong exclude_user",
- !evsel->attr.exclude_user);
+ !evsel->core.attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel",
- evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
+ evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
+ TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
return 0;
}
-static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist)
+static int test__checkevent_pmu_events_mix(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
/* pmu-event:u */
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong exclude_user",
- !evsel->attr.exclude_user);
+ !evsel->core.attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel",
- evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
+ evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
+ TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
/* cpu/pmu-event/u*/
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong exclude_user",
- !evsel->attr.exclude_user);
+ !evsel->core.attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel",
- evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
+ evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
+ TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
return 0;
}
@@ -634,41 +635,41 @@ static int test__checkterms_simple(struct list_head *terms)
return 0;
}
-static int test__group1(struct perf_evlist *evlist)
+static int test__group1(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* instructions:k */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* cycles:upp */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
/* use of precise requires exclude_guest */
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
@@ -676,99 +677,99 @@ static int test__group1(struct perf_evlist *evlist)
return 0;
}
-static int test__group2(struct perf_evlist *evlist)
+static int test__group2(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* faults + :ku modifier */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_SW_PAGE_FAULTS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* cache-references + :u modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_REFERENCES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* cycles:k */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
return 0;
}
-static int test__group3(struct perf_evlist *evlist __maybe_unused)
+static int test__group3(struct evlist *evlist __maybe_unused)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
/* group1 syscalls:sys_enter_openat:H */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group1"));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* group1 cycles:kppp */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
/* use of precise requires exclude_guest */
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 3);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
@@ -776,90 +777,90 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
/* group2 cycles + G modifier */
evsel = leader = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group2"));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* group2 1:3 + G modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 3 == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* instructions:u */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
return 0;
}
-static int test__group4(struct perf_evlist *evlist __maybe_unused)
+static int test__group4(struct evlist *evlist __maybe_unused)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* cycles:u + p */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
/* use of precise requires exclude_guest */
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 1);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* instructions:kp + p */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
/* use of precise requires exclude_guest */
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
@@ -867,298 +868,298 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
return 0;
}
-static int test__group5(struct perf_evlist *evlist __maybe_unused)
+static int test__group5(struct evlist *evlist __maybe_unused)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
/* cycles + G */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* instructions + G */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* cycles:G */
evsel = leader = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
/* instructions:G */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
/* cycles */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
return 0;
}
-static int test__group_gh1(struct perf_evlist *evlist)
+static int test__group_gh1(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* cycles + :H group modifier */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
/* cache-misses:G + :H group modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
return 0;
}
-static int test__group_gh2(struct perf_evlist *evlist)
+static int test__group_gh2(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* cycles + :G group modifier */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
/* cache-misses:H + :G group modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
return 0;
}
-static int test__group_gh3(struct perf_evlist *evlist)
+static int test__group_gh3(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* cycles:G + :u group modifier */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
/* cache-misses:H + :u group modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
return 0;
}
-static int test__group_gh4(struct perf_evlist *evlist)
+static int test__group_gh4(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
/* cycles:G + :uG group modifier */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
- TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+ TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
/* cache-misses:H + :uG group modifier */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
return 0;
}
-static int test__leader_sample1(struct perf_evlist *evlist)
+static int test__leader_sample1(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries);
/* cycles - sampling group leader */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
/* cache-misses - not sampling */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
/* branch-misses - not sampling */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
@@ -1166,38 +1167,38 @@ static int test__leader_sample1(struct perf_evlist *evlist)
return 0;
}
-static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused)
+static int test__leader_sample2(struct evlist *evlist __maybe_unused)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
/* instructions - sampling group leader */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
/* branch-misses - not sampling */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
@@ -1205,131 +1206,131 @@ static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused)
return 0;
}
-static int test__checkevent_pinned_modifier(struct perf_evlist *evlist)
+static int test__checkevent_pinned_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip);
+ TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned);
return test__checkevent_symbolic_name(evlist);
}
-static int test__pinned_group(struct perf_evlist *evlist)
+static int test__pinned_group(struct evlist *evlist)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries);
/* cycles - group leader */
evsel = leader = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
- TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned);
+ TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned);
/* cache-misses - can not be pinned, but will go on with the leader */
evsel = perf_evsel__next(evsel);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
+ PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
/* branch-misses - ditto */
evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
+ PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config);
+ TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned);
return 0;
}
-static int test__checkevent_breakpoint_len(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_len(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
- evsel->attr.bp_type);
+ evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 ==
- evsel->attr.bp_len);
+ evsel->core.attr.bp_len);
return 0;
}
-static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist)
+static int test__checkevent_breakpoint_len_w(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config);
TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W ==
- evsel->attr.bp_type);
+ evsel->core.attr.bp_type);
TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 ==
- evsel->attr.bp_len);
+ evsel->core.attr.bp_len);
return 0;
}
static int
-test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist)
+test__checkevent_breakpoint_len_rw_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip);
return test__checkevent_breakpoint_rw(evlist);
}
-static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist)
+static int test__checkevent_precise_max_modifier(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config);
+ PERF_COUNT_SW_TASK_CLOCK == evsel->core.attr.config);
return 0;
}
-static int test__checkevent_config_symbol(struct perf_evlist *evlist)
+static int test__checkevent_config_symbol(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "insn") == 0);
return 0;
}
-static int test__checkevent_config_raw(struct perf_evlist *evlist)
+static int test__checkevent_config_raw(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "rawpmu") == 0);
return 0;
}
-static int test__checkevent_config_num(struct perf_evlist *evlist)
+static int test__checkevent_config_num(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "numpmu") == 0);
return 0;
}
-static int test__checkevent_config_cache(struct perf_evlist *evlist)
+static int test__checkevent_config_cache(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "cachepmu") == 0);
return 0;
@@ -1340,39 +1341,39 @@ static bool test__intel_pt_valid(void)
return !!perf_pmu__find("intel_pt");
}
-static int test__intel_pt(struct perf_evlist *evlist)
+static int test__intel_pt(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "intel_pt//u") == 0);
return 0;
}
-static int test__checkevent_complex_name(struct perf_evlist *evlist)
+static int test__checkevent_complex_name(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong complex name parsing", strcmp(evsel->name, "COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks") == 0);
return 0;
}
-static int test__sym_event_slash(struct perf_evlist *evlist)
+static int test__sym_event_slash(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE);
- TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE);
+ TEST_ASSERT_VAL("wrong config", evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
return 0;
}
-static int test__sym_event_dc(struct perf_evlist *evlist)
+static int test__sym_event_dc(struct evlist *evlist)
{
- struct perf_evsel *evsel = perf_evlist__first(evlist);
+ struct evsel *evsel = perf_evlist__first(evlist);
- TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE);
- TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE);
+ TEST_ASSERT_VAL("wrong config", evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
return 0;
}
@@ -1422,10 +1423,10 @@ static int count_tracepoints(void)
return cnt;
}
-static int test__all_tracepoints(struct perf_evlist *evlist)
+static int test__all_tracepoints(struct evlist *evlist)
{
TEST_ASSERT_VAL("wrong events count",
- count_tracepoints() == evlist->nr_entries);
+ count_tracepoints() == evlist->core.nr_entries);
return test__checkevent_tracepoint_multi(evlist);
}
@@ -1435,7 +1436,7 @@ struct evlist_test {
__u32 type;
const int id;
bool (*valid)(void);
- int (*check)(struct perf_evlist *evlist);
+ int (*check)(struct evlist *evlist);
};
static struct evlist_test test__events[] = {
@@ -1769,7 +1770,7 @@ static struct terms_test test__terms[] = {
static int test_event(struct evlist_test *e)
{
struct parse_events_error err = { .idx = 0, };
- struct perf_evlist *evlist;
+ struct evlist *evlist;
int ret;
if (e->valid && !e->valid()) {
@@ -1777,7 +1778,7 @@ static int test_event(struct evlist_test *e)
return 0;
}
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
@@ -1790,7 +1791,7 @@ static int test_event(struct evlist_test *e)
ret = e->check(evlist);
}
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return ret;
}
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 2196d1497c0c..8284752a60c8 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -11,7 +11,7 @@
#include "util.h"
#include "debug.h"
-static int process_event(struct perf_evlist **pevlist, union perf_event *event)
+static int process_event(struct evlist **pevlist, union perf_event *event)
{
struct perf_sample sample;
@@ -39,14 +39,14 @@ static int process_event(struct perf_evlist **pevlist, union perf_event *event)
static int process_events(union perf_event **events, size_t count)
{
- struct perf_evlist *evlist = NULL;
+ struct evlist *evlist = NULL;
int err = 0;
size_t i;
for (i = 0; i < count && !err; i++)
err = process_event(&evlist, events[i]);
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
@@ -87,10 +87,10 @@ int test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest _
},
.id = 2,
};
- struct mmap_event event3 = {
+ struct perf_record_mmap event3 = {
.header = {
.type = PERF_RECORD_MMAP,
- .size = sizeof(struct mmap_event),
+ .size = sizeof(struct perf_record_mmap),
},
};
union perf_event *events[] = {
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 07f6bd8ed719..e1b42292cf7f 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -1,14 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <inttypes.h>
+#include <linux/string.h>
/* For the CLR_() macros */
#include <pthread.h>
#include <sched.h>
#include "evlist.h"
#include "evsel.h"
-#include "perf.h"
#include "debug.h"
+#include "record.h"
#include "tests.h"
static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
@@ -50,8 +51,8 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
};
cpu_set_t cpu_mask;
size_t cpu_mask_size = sizeof(cpu_mask);
- struct perf_evlist *evlist = perf_evlist__new_dummy();
- struct perf_evsel *evsel;
+ struct evlist *evlist = perf_evlist__new_dummy();
+ struct evsel *evsel;
struct perf_sample sample;
const char *cmd = "sleep";
const char *argv[] = { cmd, "1", NULL, };
@@ -130,7 +131,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
* Call sys_perf_event_open on all the fds on all the evsels,
* grouping them if asked to.
*/
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
@@ -153,7 +154,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
* Now that all is properly set up, enable the events, they will
* count just on workload.pid, which will start...
*/
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
/*
* Now!
@@ -325,7 +326,7 @@ found_exit:
++errs;
}
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
out:
return (err < 0 || errs > 0) ? -1 : 0;
}
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 361714e2583c..5fcc06817076 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -2,10 +2,12 @@
#include <stdbool.h>
#include <inttypes.h>
#include <stdlib.h>
+#include <string.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include "map_symbol.h"
#include "branch.h"
#include "util.h"
#include "event.h"
@@ -153,11 +155,13 @@ static bool samples_same(const struct perf_sample *s1,
static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
{
- struct perf_evsel evsel = {
+ struct evsel evsel = {
.needs_swap = false,
- .attr = {
- .sample_type = sample_type,
- .read_format = read_format,
+ .core = {
+ . attr = {
+ .sample_type = sample_type,
+ .read_format = read_format,
+ },
},
};
union perf_event *event;
@@ -221,10 +225,10 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
int err, ret = -1;
if (sample_type & PERF_SAMPLE_REGS_USER)
- evsel.attr.sample_regs_user = sample_regs;
+ evsel.core.attr.sample_regs_user = sample_regs;
if (sample_type & PERF_SAMPLE_REGS_INTR)
- evsel.attr.sample_regs_intr = sample_regs;
+ evsel.core.attr.sample_regs_intr = sample_regs;
for (i = 0; i < sizeof(regs); i++)
*(i + (u8 *)regs) = i & 0xfe;
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index 8bfaa630389c..cf1bd57d3023 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -1,14 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/epoll.h>
-#include <util/evlist.h>
#include <util/symbol.h>
#include <linux/filter.h>
#include "tests.h"
#include "debug.h"
#include "probe-file.h"
#include "build-id.h"
+#include "util.h"
/* To test SDT event, we need libelf support to scan elf binary */
#if defined(HAVE_SDT_EVENT) && defined(HAVE_LIBELF_SUPPORT)
diff --git a/tools/perf/tests/shell/record+zstd_comp_decomp.sh b/tools/perf/tests/shell/record+zstd_comp_decomp.sh
index 899604d17b85..63a91ec473bb 100755
--- a/tools/perf/tests/shell/record+zstd_comp_decomp.sh
+++ b/tools/perf/tests/shell/record+zstd_comp_decomp.sh
@@ -13,7 +13,7 @@ skip_if_no_z_record() {
collect_z_record() {
echo "Collecting compressed record file:"
$perf_tool record -o $trace_file -g -z -F 5000 -- \
- dd count=500 if=/dev/random of=/dev/null
+ dd count=500 if=/dev/urandom of=/dev/null
}
check_compressed_stats() {
diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
index 45d269b0157e..11cc2af13f2b 100755
--- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
@@ -32,6 +32,10 @@ if [ $err -ne 0 ] ; then
exit $err
fi
+# Do not use whatever ~/.perfconfig file, it may change the output
+# via trace.{show_timestamp,show_prefix,etc}
+export PERF_CONFIG=/dev/null
+
trace_open_vfs_getname
err=$?
rm -f ${file}
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 94250024684a..cc10b4116c9f 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -6,7 +6,7 @@
#include "counts.h"
#include "debug.h"
-static bool has_term(struct stat_config_event *config,
+static bool has_term(struct perf_record_stat_config *config,
u64 tag, u64 val)
{
unsigned i;
@@ -25,7 +25,7 @@ static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct stat_config_event *config = &event->stat_config;
+ struct perf_record_stat_config *config = &event->stat_config;
struct perf_stat_config stat_config;
#define HAS(term, val) \
@@ -65,7 +65,7 @@ static int process_stat_event(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct stat_event *st = &event->stat;
+ struct perf_record_stat *st = &event->stat;
TEST_ASSERT_VAL("wrong cpu", st->cpu == 1);
TEST_ASSERT_VAL("wrong thread", st->thread == 2);
@@ -95,7 +95,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct stat_round_event *stat_round = &event->stat_round;
+ struct perf_record_stat_round *stat_round = &event->stat_round;
TEST_ASSERT_VAL("wrong time", stat_round->time == 0xdeadbeef);
TEST_ASSERT_VAL("wrong type", stat_round->type == PERF_STAT_ROUND_TYPE__INTERVAL);
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index f9490b237893..97694a040986 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -5,12 +5,15 @@
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
+#include <linux/string.h>
#include "tests.h"
+#include "util/debug.h"
#include "util/evsel.h"
#include "util/evlist.h"
#include "util/cpumap.h"
#include "util/thread_map.h"
+#include <perf/evlist.h>
#define NR_LOOPS 10000000
@@ -27,8 +30,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
int nr_samples = 0;
char sbuf[STRERR_BUFSIZE];
union perf_event *event;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist;
+ struct evsel *evsel;
+ struct evlist *evlist;
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = clock_id,
@@ -37,26 +40,26 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
.disabled = 1,
.freq = 1,
};
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
struct perf_mmap *md;
attr.sample_freq = 500;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (evlist == NULL) {
- pr_debug("perf_evlist__new\n");
+ pr_debug("evlist__new\n");
return -1;
}
- evsel = perf_evsel__new(&attr);
+ evsel = evsel__new(&attr);
if (evsel == NULL) {
pr_debug("perf_evsel__new\n");
goto out_delete_evlist;
}
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
- cpus = cpu_map__dummy_new();
+ cpus = perf_cpu_map__dummy_new();
threads = thread_map__new_by_tid(getpid());
if (!cpus || !threads) {
err = -ENOMEM;
@@ -64,12 +67,12 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
goto out_free_maps;
}
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
cpus = NULL;
threads = NULL;
- if (perf_evlist__open(evlist)) {
+ if (evlist__open(evlist)) {
const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate";
err = -errno;
@@ -86,13 +89,13 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
goto out_delete_evlist;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
/* collect samples */
for (i = 0; i < NR_LOOPS; i++)
tmp++;
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
md = &evlist->mmap[0];
if (perf_mmap__read_init(md) < 0)
@@ -125,10 +128,10 @@ out_init:
}
out_free_maps:
- cpu_map__put(cpus);
- thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ perf_thread_map__put(threads);
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 6cdab5f4812a..1a60fa1219f5 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -2,15 +2,20 @@
#include <sys/time.h>
#include <sys/prctl.h>
#include <errno.h>
+#include <limits.h>
#include <time.h>
#include <stdlib.h>
#include <linux/zalloc.h>
+#include <perf/cpumap.h>
+#include <perf/evlist.h>
+#include "debug.h"
#include "parse-events.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
#include "cpumap.h"
+#include "record.h"
#include "tests.h"
static int spin_sleep(void)
@@ -52,8 +57,8 @@ static int spin_sleep(void)
}
struct switch_tracking {
- struct perf_evsel *switch_evsel;
- struct perf_evsel *cycles_evsel;
+ struct evsel *switch_evsel;
+ struct evsel *cycles_evsel;
pid_t *tids;
int nr_tids;
int comm_seen[4];
@@ -113,12 +118,12 @@ static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
return 0;
}
-static int process_sample_event(struct perf_evlist *evlist,
+static int process_sample_event(struct evlist *evlist,
union perf_event *event,
struct switch_tracking *switch_tracking)
{
struct perf_sample sample;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
pid_t next_tid, prev_tid;
int cpu, err;
@@ -163,7 +168,7 @@ static int process_sample_event(struct perf_evlist *evlist,
return 0;
}
-static int process_event(struct perf_evlist *evlist, union perf_event *event,
+static int process_event(struct evlist *evlist, union perf_event *event,
struct switch_tracking *switch_tracking)
{
if (event->header.type == PERF_RECORD_SAMPLE)
@@ -203,7 +208,7 @@ struct event_node {
u64 event_time;
};
-static int add_event(struct perf_evlist *evlist, struct list_head *events,
+static int add_event(struct evlist *evlist, struct list_head *events,
union perf_event *event)
{
struct perf_sample sample;
@@ -252,7 +257,7 @@ static int compar(const void *a, const void *b)
return cmp;
}
-static int process_events(struct perf_evlist *evlist,
+static int process_events(struct evlist *evlist,
struct switch_tracking *switch_tracking)
{
union perf_event *event;
@@ -327,11 +332,11 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
.uses_mmap = true,
},
};
- struct thread_map *threads = NULL;
- struct cpu_map *cpus = NULL;
- struct perf_evlist *evlist = NULL;
- struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
- struct perf_evsel *switch_evsel, *tracking_evsel;
+ struct perf_thread_map *threads = NULL;
+ struct perf_cpu_map *cpus = NULL;
+ struct evlist *evlist = NULL;
+ struct evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
+ struct evsel *switch_evsel, *tracking_evsel;
const char *comm;
int err = -1;
@@ -341,19 +346,19 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err;
}
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (!cpus) {
- pr_debug("cpu_map__new failed!\n");
+ pr_debug("perf_cpu_map__new failed!\n");
goto out_err;
}
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist) {
- pr_debug("perf_evlist__new failed!\n");
+ pr_debug("evlist__new failed!\n");
goto out_err;
}
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
/* First event */
err = parse_events(evlist, "cpu-clock:u", NULL);
@@ -420,8 +425,8 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
perf_evlist__set_tracking_event(evlist, tracking_evsel);
- tracking_evsel->attr.freq = 0;
- tracking_evsel->attr.sample_period = 1;
+ tracking_evsel->core.attr.freq = 0;
+ tracking_evsel->core.attr.sample_period = 1;
perf_evsel__set_sample_bit(tracking_evsel, TIME);
@@ -435,7 +440,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
}
/* Check tracking event is tracking */
- if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) {
+ if (!tracking_evsel->core.attr.mmap || !tracking_evsel->core.attr.comm) {
pr_debug("Tracking event not tracking\n");
goto out_err;
}
@@ -443,14 +448,14 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
/* Check non-tracking events are not tracking */
evlist__for_each_entry(evlist, evsel) {
if (evsel != tracking_evsel) {
- if (evsel->attr.mmap || evsel->attr.comm) {
+ if (evsel->core.attr.mmap || evsel->core.attr.comm) {
pr_debug("Non-tracking event is tracking\n");
goto out_err;
}
}
}
- if (perf_evlist__open(evlist) < 0) {
+ if (evlist__open(evlist) < 0) {
pr_debug("Not supported\n");
err = 0;
goto out;
@@ -462,9 +467,9 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err;
}
- perf_evlist__enable(evlist);
+ evlist__enable(evlist);
- err = perf_evsel__disable(cpu_clocks_evsel);
+ err = evsel__disable(cpu_clocks_evsel);
if (err) {
pr_debug("perf_evlist__disable_event failed!\n");
goto out_err;
@@ -483,7 +488,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err;
}
- err = perf_evsel__disable(cycles_evsel);
+ err = evsel__disable(cycles_evsel);
if (err) {
pr_debug("perf_evlist__disable_event failed!\n");
goto out_err;
@@ -509,7 +514,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err;
}
- err = perf_evsel__enable(cycles_evsel);
+ err = evsel__enable(cycles_evsel);
if (err) {
pr_debug("perf_evlist__disable_event failed!\n");
goto out_err;
@@ -528,7 +533,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err;
}
- perf_evlist__disable(evlist);
+ evlist__disable(evlist);
switch_tracking.switch_evsel = switch_evsel;
switch_tracking.cycles_evsel = cycles_evsel;
@@ -566,11 +571,11 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
}
out:
if (evlist) {
- perf_evlist__disable(evlist);
- perf_evlist__delete(evlist);
+ evlist__disable(evlist);
+ evlist__delete(evlist);
} else {
- cpu_map__put(cpus);
- thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ perf_thread_map__put(threads);
}
return err;
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index e92fa6029ac7..f610e8c0a083 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -1,12 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
#include "evlist.h"
#include "evsel.h"
+#include "target.h"
#include "thread_map.h"
#include "cpumap.h"
#include "tests.h"
#include <errno.h>
#include <signal.h>
+#include <linux/string.h>
+#include <perf/evlist.h>
static int exited;
static int nr_exit;
@@ -37,16 +41,16 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
{
int err = -1;
union perf_event *event;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist;
+ struct evsel *evsel;
+ struct evlist *evlist;
struct target target = {
.uid = UINT_MAX,
.uses_mmap = true,
};
const char *argv[] = { "true", NULL };
char sbuf[STRERR_BUFSIZE];
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
struct perf_mmap *md;
signal(SIGCHLD, sig_handler);
@@ -63,7 +67,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
* perf_evlist__prepare_workload we'll fill in the only thread
* we're monitoring, the one forked there.
*/
- cpus = cpu_map__dummy_new();
+ cpus = perf_cpu_map__dummy_new();
threads = thread_map__new_by_tid(-1);
if (!cpus || !threads) {
err = -ENOMEM;
@@ -71,7 +75,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
goto out_free_maps;
}
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
cpus = NULL;
threads = NULL;
@@ -84,18 +88,18 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
}
evsel = perf_evlist__first(evlist);
- evsel->attr.task = 1;
+ evsel->core.attr.task = 1;
#ifdef __s390x__
- evsel->attr.sample_freq = 1000000;
+ evsel->core.attr.sample_freq = 1000000;
#else
- evsel->attr.sample_freq = 1;
+ evsel->core.attr.sample_freq = 1;
#endif
- evsel->attr.inherit = 0;
- evsel->attr.watermark = 0;
- evsel->attr.wakeup_events = 1;
- evsel->attr.exclude_kernel = 1;
+ evsel->core.attr.inherit = 0;
+ evsel->core.attr.watermark = 0;
+ evsel->core.attr.wakeup_events = 1;
+ evsel->core.attr.exclude_kernel = 1;
- err = perf_evlist__open(evlist);
+ err = evlist__open(evlist);
if (err < 0) {
pr_debug("Couldn't open the evlist: %s\n",
str_error_r(-err, sbuf, sizeof(sbuf)));
@@ -135,9 +139,9 @@ out_init:
}
out_free_maps:
- cpu_map__put(cpus);
- thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ perf_thread_map__put(threads);
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index ccc17aced49e..39168c57943b 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -1,19 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/prctl.h>
#include "tests.h"
#include "thread_map.h"
#include "debug.h"
+#include "event.h"
#include <linux/zalloc.h>
+#include <perf/event.h>
+
+struct perf_sample;
+struct perf_tool;
+struct machine;
#define NAME (const char *) "perf"
#define NAMEUL (unsigned long) NAME
int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct thread_map *map;
+ struct perf_thread_map *map;
TEST_ASSERT_VAL("failed to set process name",
!prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
@@ -26,28 +33,28 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse
TEST_ASSERT_VAL("wrong nr", map->nr == 1);
TEST_ASSERT_VAL("wrong pid",
- thread_map__pid(map, 0) == getpid());
+ perf_thread_map__pid(map, 0) == getpid());
TEST_ASSERT_VAL("wrong comm",
- thread_map__comm(map, 0) &&
- !strcmp(thread_map__comm(map, 0), NAME));
+ perf_thread_map__comm(map, 0) &&
+ !strcmp(perf_thread_map__comm(map, 0), NAME));
TEST_ASSERT_VAL("wrong refcnt",
refcount_read(&map->refcnt) == 1);
- thread_map__put(map);
+ perf_thread_map__put(map);
/* test dummy pid */
- map = thread_map__new_dummy();
+ map = perf_thread_map__new_dummy();
TEST_ASSERT_VAL("failed to alloc map", map);
thread_map__read_comms(map);
TEST_ASSERT_VAL("wrong nr", map->nr == 1);
- TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1);
+ TEST_ASSERT_VAL("wrong pid", perf_thread_map__pid(map, 0) == -1);
TEST_ASSERT_VAL("wrong comm",
- thread_map__comm(map, 0) &&
- !strcmp(thread_map__comm(map, 0), "dummy"));
+ perf_thread_map__comm(map, 0) &&
+ !strcmp(perf_thread_map__comm(map, 0), "dummy"));
TEST_ASSERT_VAL("wrong refcnt",
refcount_read(&map->refcnt) == 1);
- thread_map__put(map);
+ perf_thread_map__put(map);
return 0;
}
@@ -56,8 +63,8 @@ static int process_event(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
- struct thread_map_event *map = &event->thread_map;
- struct thread_map *threads;
+ struct perf_record_thread_map *map = &event->thread_map;
+ struct perf_thread_map *threads;
TEST_ASSERT_VAL("wrong nr", map->nr == 1);
TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid());
@@ -68,19 +75,19 @@ static int process_event(struct perf_tool *tool __maybe_unused,
TEST_ASSERT_VAL("wrong nr", threads->nr == 1);
TEST_ASSERT_VAL("wrong pid",
- thread_map__pid(threads, 0) == getpid());
+ perf_thread_map__pid(threads, 0) == getpid());
TEST_ASSERT_VAL("wrong comm",
- thread_map__comm(threads, 0) &&
- !strcmp(thread_map__comm(threads, 0), NAME));
+ perf_thread_map__comm(threads, 0) &&
+ !strcmp(perf_thread_map__comm(threads, 0), NAME));
TEST_ASSERT_VAL("wrong refcnt",
refcount_read(&threads->refcnt) == 1);
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return 0;
}
int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct thread_map *threads;
+ struct perf_thread_map *threads;
TEST_ASSERT_VAL("failed to set process name",
!prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
@@ -99,7 +106,7 @@ int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __
int test__thread_map_remove(struct test *test __maybe_unused, int subtest __maybe_unused)
{
- struct thread_map *threads;
+ struct perf_thread_map *threads;
char *str;
int i;
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index b1d1bbafe7ae..cbac71716dec 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -2,7 +2,6 @@
#include "tests.h"
#include "machine.h"
#include "thread.h"
-#include "map.h"
#include "debug.h"
int test__thread_mg_share(struct test *test __maybe_unused, int subtest __maybe_unused)
diff --git a/tools/perf/tests/time-utils-test.c b/tools/perf/tests/time-utils-test.c
index 4f53006233a1..fe57ca3b6e54 100644
--- a/tools/perf/tests/time-utils-test.c
+++ b/tools/perf/tests/time-utils-test.c
@@ -69,7 +69,7 @@ struct test_data {
static bool test__perf_time__parse_for_ranges(struct test_data *d)
{
- struct perf_evlist evlist = {
+ struct evlist evlist = {
.first_sample_time = d->first,
.last_sample_time = d->last,
};
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 9497d02f69e6..a4f9f5182b47 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <perf/cpumap.h>
#include "tests.h"
#include "util.h"
#include "session.h"
@@ -57,7 +58,7 @@ static int session_write_header(char *path)
return 0;
}
-static int check_cpu_topology(char *path, struct cpu_map *map)
+static int check_cpu_topology(char *path, struct perf_cpu_map *map)
{
struct perf_session *session;
struct perf_data data = {
@@ -116,7 +117,7 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
{
char path[PATH_MAX];
- struct cpu_map *map;
+ struct perf_cpu_map *map;
int ret = TEST_FAIL;
TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
@@ -126,14 +127,14 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
if (session_write_header(path))
goto free_path;
- map = cpu_map__new(NULL);
+ map = perf_cpu_map__new(NULL);
if (map == NULL) {
pr_debug("failed to get system cpumap\n");
goto free_path;
}
ret = check_cpu_topology(path, map);
- cpu_map__put(map);
+ perf_cpu_map__put(map);
free_path:
unlink(path);
diff --git a/tools/perf/tests/unit_number__scnprintf.c b/tools/perf/tests/unit_number__scnprintf.c
index 2bb8cb0039c1..3721757435da 100644
--- a/tools/perf/tests/unit_number__scnprintf.c
+++ b/tools/perf/tests/unit_number__scnprintf.c
@@ -2,6 +2,7 @@
#include <inttypes.h>
#include <linux/compiler.h>
#include <linux/types.h>
+#include <string.h>
#include "tests.h"
#include "units.h"
#include "debug.h"
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 5e8834fc7dec..01f434c067c6 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -4,6 +4,7 @@
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
+#include "dso.h"
#include "map.h"
#include "symbol.h"
#include "util.h"
diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c
index f89e6806557b..d262d6639829 100644
--- a/tools/perf/tests/wp.c
+++ b/tools/perf/tests/wp.c
@@ -1,10 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/hw_breakpoint.h>
+#include <linux/kernel.h>
#include "tests.h"
#include "debug.h"
+#include "event.h"
#include "cloexec.h"
+#include "../perf-sys.h"
#define WP_TEST_ASSERT_VAL(fd, text, val) \
do { \
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
index 52242fa4072b..e19eb6ea361d 100644
--- a/tools/perf/trace/beauty/ioctl.c
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -21,7 +21,7 @@
static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
{
static const char *ioctl_tty_cmd[] = {
- "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
+ [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
"TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
"TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
"TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
diff --git a/tools/perf/trace/beauty/usbdevfs_ioctl.sh b/tools/perf/trace/beauty/usbdevfs_ioctl.sh
index 930b80f422e8..aa597ae53747 100755
--- a/tools/perf/trace/beauty/usbdevfs_ioctl.sh
+++ b/tools/perf/trace/beauty/usbdevfs_ioctl.sh
@@ -3,10 +3,13 @@
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
+# also as:
+# #define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len)
+
printf "static const char *usbdevfs_ioctl_cmds[] = {\n"
-regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
-egrep $regex ${header_dir}/usbdevice_fs.h | egrep -v 'USBDEVFS_\w+32[[:space:]]' | \
- sed -r "s/$regex/\2 \1/g" | \
+regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)(\(\w+\))?[[:space:]]+_IO[CWR]{0,2}\([[:space:]]*(_IOC_\w+,[[:space:]]*)?'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
+egrep "$regex" ${header_dir}/usbdevice_fs.h | egrep -v 'USBDEVFS_\w+32[[:space:]]' | \
+ sed -r "s/$regex/\4 \1/g" | \
sort | xargs printf "\t[%s] = \"%s\",\n"
printf "};\n\n"
printf "#if 0\n"
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index f80c51d53565..f93d40b1c203 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../string2.h"
-#include "../config.h"
-#include "../../perf.h"
+#include "../util/util.h"
+#include "../util/string2.h"
+#include "../util/config.h"
#include "libslang.h"
#include "ui.h"
#include "util.h"
@@ -14,7 +14,7 @@
#include "browser.h"
#include "helpline.h"
#include "keysyms.h"
-#include "../color.h"
+#include "../util/color.h"
#include <linux/ctype.h>
#include <linux/zalloc.h>
@@ -346,6 +346,8 @@ static int __ui_browser__refresh(struct ui_browser *browser)
SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x,
browser->rows - row, width, ' ');
+ if (browser->nr_entries == 0 && browser->no_samples_msg)
+ __ui__info_window(NULL, browser->no_samples_msg, NULL);
return 0;
}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index dc1444136658..3678eb88f119 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -23,6 +23,7 @@ struct ui_browser {
void *priv;
const char *title;
char *helpline;
+ const char *no_samples_msg;
void (*refresh_dimensions)(struct ui_browser *browser);
unsigned int (*refresh)(struct ui_browser *browser);
void (*write)(struct ui_browser *browser, void *entry, int row);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index e67880bf1efe..ac74ed2c23a0 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -4,6 +4,8 @@
#include "../ui.h"
#include "../util.h"
#include "../../util/annotate.h"
+#include "../../util/debug.h"
+#include "../../util/dso.h"
#include "../../util/hist.h"
#include "../../util/sort.h"
#include "../../util/map.h"
@@ -299,7 +301,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
}
static void annotate_browser__calc_percent(struct annotate_browser *browser,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
struct map_symbol *ms = browser->b.priv;
struct symbol *sym = ms->sym;
@@ -406,7 +408,7 @@ static int sym_title(struct symbol *sym, struct map *map, char *title,
* to the calling function.
*/
static bool annotate_browser__callq(struct annotate_browser *browser,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt)
{
struct map_symbol *ms = browser->b.priv;
@@ -422,7 +424,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
notes = symbol__annotation(dl->ops.target.sym);
pthread_mutex_lock(&notes->lock);
- if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) {
+ if (!symbol__hists(dl->ops.target.sym, evsel->evlist->core.nr_entries)) {
pthread_mutex_unlock(&notes->lock);
ui__warning("Not enough memory for annotating '%s' symbol!\n",
dl->ops.target.sym->name);
@@ -455,7 +457,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows
}
static bool annotate_browser__jump(struct annotate_browser *browser,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt)
{
struct disasm_line *dl = disasm_line(browser->selection);
@@ -656,7 +658,7 @@ switch_percent_type(struct annotation_options *opts, bool base)
}
static int annotate_browser__run(struct annotate_browser *browser,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt)
{
struct rb_node *nd = NULL;
@@ -869,14 +871,14 @@ out:
return key;
}
-int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *opts)
{
return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts);
}
-int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
+int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *opts)
{
@@ -888,7 +890,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
}
int symbol__tui_annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *opts)
{
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index 5aeb663dd184..0f59a7001479 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "util/cache.h"
#include "util/debug.h"
#include "ui/browser.h"
#include "ui/keysyms.h"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a94eb0755e8b..589168ca9f62 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -11,17 +11,23 @@
#include <linux/time64.h>
#include <linux/zalloc.h>
+#include "../../util/debug.h"
+#include "../../util/dso.h"
#include "../../util/callchain.h"
#include "../../util/evsel.h"
#include "../../util/evlist.h"
+#include "../../util/header.h"
#include "../../util/hist.h"
#include "../../util/map.h"
#include "../../util/symbol.h"
+#include "../../util/map_symbol.h"
+#include "../../util/branch.h"
#include "../../util/pstack.h"
#include "../../util/sort.h"
#include "../../util/top.h"
#include "../../util/thread.h"
#include "../../arch/common.h"
+#include "../../perf.h"
#include "../browsers/hists.h"
#include "../helpline.h"
@@ -2187,7 +2193,7 @@ struct hist_browser *hist_browser__new(struct hists *hists)
}
static struct hist_browser *
-perf_evsel_browser__new(struct perf_evsel *evsel,
+perf_evsel_browser__new(struct evsel *evsel,
struct hist_browser_timer *hbt,
struct perf_env *env,
struct annotation_options *annotation_opts)
@@ -2352,7 +2358,7 @@ struct popup_action {
struct thread *thread;
struct map_symbol ms;
int socket;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
enum rstype rstype;
int (*fn)(struct hist_browser *browser, struct popup_action *act);
@@ -2361,7 +2367,7 @@ struct popup_action {
static int
do_annotate(struct hist_browser *browser, struct popup_action *act)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct annotation *notes;
struct hist_entry *he;
int err;
@@ -2596,7 +2602,7 @@ static int
add_script_opt_2(struct hist_browser *browser __maybe_unused,
struct popup_action *act, char **optstr,
struct thread *thread, struct symbol *sym,
- struct perf_evsel *evsel, const char *tstr)
+ struct evsel *evsel, const char *tstr)
{
if (thread) {
@@ -2623,7 +2629,7 @@ static int
add_script_opt(struct hist_browser *browser,
struct popup_action *act, char **optstr,
struct thread *thread, struct symbol *sym,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
int n, j;
struct hist_entry *he;
@@ -2653,7 +2659,7 @@ static int
add_res_sample_opt(struct hist_browser *browser __maybe_unused,
struct popup_action *act, char **optstr,
struct res_sample *res_sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
enum rstype type)
{
if (!res_sample)
@@ -2814,7 +2820,7 @@ next:
}
}
-static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
+static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events,
const char *helpline,
bool left_exits,
struct hist_browser_timer *hbt,
@@ -2894,6 +2900,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (symbol_conf.col_width_list_str)
perf_hpp__set_user_width(symbol_conf.col_width_list_str);
+ if (!is_report_browser(hbt))
+ browser->b.no_samples_msg = "Collecting samples...";
+
while (1) {
struct thread *thread = NULL;
struct map *map = NULL;
@@ -3198,9 +3207,9 @@ out:
return key;
}
-struct perf_evsel_menu {
+struct evsel_menu {
struct ui_browser b;
- struct perf_evsel *selection;
+ struct evsel *selection;
struct annotation_options *annotation_opts;
bool lost_events, lost_events_warned;
float min_pcnt;
@@ -3210,9 +3219,9 @@ struct perf_evsel_menu {
static void perf_evsel_menu__write(struct ui_browser *browser,
void *entry, int row)
{
- struct perf_evsel_menu *menu = container_of(browser,
- struct perf_evsel_menu, b);
- struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+ struct evsel_menu *menu = container_of(browser,
+ struct evsel_menu, b);
+ struct evsel *evsel = list_entry(entry, struct evsel, core.node);
struct hists *hists = evsel__hists(evsel);
bool current_entry = ui_browser__is_current_entry(browser, row);
unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
@@ -3225,7 +3234,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
HE_COLORSET_NORMAL);
if (perf_evsel__is_group_event(evsel)) {
- struct perf_evsel *pos;
+ struct evsel *pos;
ev_name = perf_evsel__group_name(evsel);
@@ -3257,13 +3266,13 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
menu->selection = evsel;
}
-static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
+static int perf_evsel_menu__run(struct evsel_menu *menu,
int nr_events, const char *help,
struct hist_browser_timer *hbt,
bool warn_lost_event)
{
- struct perf_evlist *evlist = menu->b.priv;
- struct perf_evsel *pos;
+ struct evlist *evlist = menu->b.priv;
+ struct evsel *pos;
const char *title = "Available samples";
int delay_secs = hbt ? hbt->refresh : 0;
int key;
@@ -3309,13 +3318,13 @@ browse_hists:
ui_browser__show_title(&menu->b, title);
switch (key) {
case K_TAB:
- if (pos->node.next == &evlist->entries)
+ if (pos->core.node.next == &evlist->core.entries)
pos = perf_evlist__first(evlist);
else
pos = perf_evsel__next(pos);
goto browse_hists;
case K_UNTAB:
- if (pos->node.prev == &evlist->entries)
+ if (pos->core.node.prev == &evlist->core.entries)
pos = perf_evlist__last(evlist);
else
pos = perf_evsel__prev(pos);
@@ -3351,7 +3360,7 @@ out:
static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
void *entry)
{
- struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+ struct evsel *evsel = list_entry(entry, struct evsel, core.node);
if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
return true;
@@ -3359,7 +3368,7 @@ static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
return false;
}
-static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
+static int __perf_evlist__tui_browse_hists(struct evlist *evlist,
int nr_entries, const char *help,
struct hist_browser_timer *hbt,
float min_pcnt,
@@ -3367,10 +3376,10 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
bool warn_lost_event,
struct annotation_options *annotation_opts)
{
- struct perf_evsel *pos;
- struct perf_evsel_menu menu = {
+ struct evsel *pos;
+ struct evsel_menu menu = {
.b = {
- .entries = &evlist->entries,
+ .entries = &evlist->core.entries,
.refresh = ui_browser__list_head_refresh,
.seek = ui_browser__list_head_seek,
.write = perf_evsel_menu__write,
@@ -3397,18 +3406,18 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
hbt, warn_lost_event);
}
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
+int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
struct hist_browser_timer *hbt,
float min_pcnt,
struct perf_env *env,
bool warn_lost_event,
struct annotation_options *annotation_opts)
{
- int nr_entries = evlist->nr_entries;
+ int nr_entries = evlist->core.nr_entries;
single_entry:
if (nr_entries == 1) {
- struct perf_evsel *first = perf_evlist__first(evlist);
+ struct evsel *first = perf_evlist__first(evlist);
return perf_evsel__hists_browse(first, nr_entries, help,
false, hbt, min_pcnt,
@@ -3417,7 +3426,7 @@ single_entry:
}
if (symbol_conf.event_group) {
- struct perf_evsel *pos;
+ struct evsel *pos;
nr_entries = 0;
evlist__for_each_entry(evlist, pos) {
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 4c545b92e20d..893b065971f6 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -8,6 +8,7 @@
#include "../../util/util.h"
#include "../../util/debug.h"
#include "../../util/map.h"
+#include "../../util/dso.h"
#include "../../util/symbol.h"
#include "../browser.h"
#include "../helpline.h"
diff --git a/tools/perf/ui/browsers/res_sample.c b/tools/perf/ui/browsers/res_sample.c
index 8aa3547bb9ff..f16a38fea45e 100644
--- a/tools/perf/ui/browsers/res_sample.c
+++ b/tools/perf/ui/browsers/res_sample.c
@@ -6,6 +6,11 @@
#include "sort.h"
#include "config.h"
#include "time-utils.h"
+#include "../util.h"
+#include "../../util/util.h"
+#include "../../perf.h"
+#include <stdlib.h>
+#include <string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
@@ -24,7 +29,7 @@ void res_sample_init(void)
}
int res_sample_browse(struct res_sample *res_samples, int num_res,
- struct perf_evsel *evsel, enum rstype rstype)
+ struct evsel *evsel, enum rstype rstype)
{
char **names;
int i, n;
@@ -66,7 +71,7 @@ int res_sample_browse(struct res_sample *res_samples, int num_res,
timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample);
- attr_to_script(extra_format, &evsel->attr);
+ attr_to_script(extra_format, &evsel->core.attr);
if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s",
perf,
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 4d565cc14076..586a21acc13d 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -1,12 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../../util/sort.h"
+#include "../../builtin.h"
+#include "../../perf.h"
+#include "../../util/util.h"
#include "../../util/hist.h"
#include "../../util/debug.h"
#include "../../util/symbol.h"
#include "../browser.h"
#include "../libslang.h"
#include "config.h"
+#include <linux/string.h>
#include <linux/zalloc.h>
+#include <stdlib.h>
#define SCRIPT_NAMELEN 128
#define SCRIPT_MAX_NO 64
@@ -78,7 +82,7 @@ static int scripts_config(const char *var, const char *value, void *data)
* Return -1 on failure.
*/
static int list_scripts(char *script_name, bool *custom,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
char *buf, *paths[SCRIPT_MAX_NO], *names[SCRIPT_MAX_NO];
int i, num, choice;
@@ -100,7 +104,7 @@ static int list_scripts(char *script_name, bool *custom,
return -1;
if (evsel)
- attr_to_script(scriptc.extra_format, &evsel->attr);
+ attr_to_script(scriptc.extra_format, &evsel->core.attr);
add_script_option("Show individual samples", "", &scriptc);
add_script_option("Show individual samples with assembler", "-F +insn --xed",
&scriptc);
@@ -131,8 +135,10 @@ static int list_scripts(char *script_name, bool *custom,
int key = ui_browser__input_window("perf script command",
"Enter perf script command line (without perf script prefix)",
script_args, "", 0);
- if (key != K_ENTER)
- return -1;
+ if (key != K_ENTER) {
+ ret = -1;
+ goto out;
+ }
sprintf(script_name, "%s script %s", perf, script_args);
} else if (choice < num + max_std) {
strcpy(script_name, paths[choice]);
@@ -162,7 +168,7 @@ void run_script(char *cmd)
SLsmg_refresh();
}
-int script_browse(const char *script_opt, struct perf_evsel *evsel)
+int script_browse(const char *script_opt, struct evsel *evsel)
{
char *cmd, script_name[SCRIPT_FULLPATH_LEN];
bool custom = false;
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 3af87c18a914..8e744af24f7c 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -5,6 +5,7 @@
#include "util/annotate.h"
#include "util/evsel.h"
#include "util/map.h"
+#include "util/dso.h"
#include "util/symbol.h"
#include "ui/helpline.h"
#include <inttypes.h>
@@ -91,7 +92,7 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
}
static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
- struct map *map, struct perf_evsel *evsel,
+ struct map *map, struct evsel *evsel,
struct hist_browser_timer *hbt __maybe_unused)
{
struct disasm_line *pos, *n;
@@ -129,7 +130,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
gtk_list_store_append(store, &iter);
if (perf_evsel__is_group_event(evsel)) {
- for (i = 0; i < evsel->nr_members; i++) {
+ for (i = 0; i < evsel->core.nr_members; i++) {
ret += perf_gtk__get_percent(s + ret,
sizeof(s) - ret,
sym, pos,
@@ -160,7 +161,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
}
static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt)
{
GtkWidget *window;
@@ -238,7 +239,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
}
int hist_entry__gtk_annotate(struct hist_entry *he,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt)
{
return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 4820e25ac68d..8f3e43d148a8 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -1,6 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../evlist.h"
-#include "../cache.h"
#include "../evsel.h"
#include "../sort.h"
#include "../hist.h"
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 9846ea5c831b..a9563932fa04 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -52,16 +52,16 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void)
}
#endif
-struct perf_evsel;
-struct perf_evlist;
+struct evsel;
+struct evlist;
struct hist_entry;
struct hist_browser_timer;
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
+int perf_evlist__gtk_browse_hists(struct evlist *evlist, const char *help,
struct hist_browser_timer *hbt,
float min_pcnt);
int hist_entry__gtk_annotate(struct hist_entry *he,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt);
void perf_gtk__show_annotations(void);
diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
index fbf1ea9ce9a2..e166da9ec767 100644
--- a/tools/perf/ui/gtk/helpline.c
+++ b/tools/perf/ui/gtk/helpline.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <string.h>
+#include <linux/kernel.h>
#include "gtk.h"
#include "../ui.h"
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 3955ed1d1bd9..6c2efc10bf5c 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "../evlist.h"
-#include "../cache.h"
#include "../callchain.h"
#include "../evsel.h"
#include "../sort.h"
@@ -590,12 +589,12 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
gtk_container_add(GTK_CONTAINER(window), view);
}
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
+int perf_evlist__gtk_browse_hists(struct evlist *evlist,
const char *help,
struct hist_browser_timer *hbt __maybe_unused,
float min_pcnt)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
GtkWidget *vbox;
GtkWidget *notebook;
GtkWidget *info_bar;
@@ -645,7 +644,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
if (!perf_evsel__is_group_leader(pos))
continue;
- if (pos->nr_members > 1) {
+ if (pos->core.nr_members > 1) {
perf_evsel__group_desc(pos, buf, size);
evname = buf;
}
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 506e73b3834c..1a2616b97b5c 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "gtk.h"
-#include "../../util/cache.h"
#include "../../util/debug.h"
extern struct perf_error_ops perf_gtk_eops;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index c28bdb7517ac..c2c558958b9c 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -3,6 +3,7 @@
#include "../../util/debug.h"
#include "gtk.h"
+#include <stdlib.h>
#include <string.h>
#include <linux/zalloc.h>
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index b3c421429ed4..54bcd08df87e 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -3,10 +3,10 @@
#include <stdlib.h>
#include <string.h>
-#include "../debug.h"
+#include "../util/debug.h"
#include "helpline.h"
#include "ui.h"
-#include "../util.h"
+#include "../util/util.h"
char ui_helpline__current[512];
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 8f775a053ca3..2165a098dee8 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -5,8 +5,6 @@
#include <stdio.h>
#include <stdarg.h>
-#include "../util/cache.h"
-
struct ui_helpline {
void (*pop)(void);
void (*push)(const char *msg);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 412d6f1626e3..3e533de7d852 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -1,14 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
#include <inttypes.h>
#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include <linux/compiler.h>
#include "../util/callchain.h"
+#include "../util/debug.h"
#include "../util/hist.h"
#include "../util/util.h"
#include "../util/sort.h"
#include "../util/evsel.h"
#include "../util/evlist.h"
+#include "../perf.h"
/* hist period print (hpp) functions */
@@ -25,7 +29,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
{
int ret;
struct hists *hists = he->hists;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
char *buf = hpp->buf;
size_t size = hpp->size;
@@ -43,7 +47,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
if (perf_evsel__is_group_event(evsel)) {
int prev_idx, idx_delta;
struct hist_entry *pair;
- int nr_members = evsel->nr_members;
+ int nr_members = evsel->core.nr_members;
prev_idx = perf_evsel__group_idx(evsel);
@@ -153,7 +157,7 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b,
{
s64 ret;
int i, nr_members;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct hist_entry *pair;
u64 *fields_a, *fields_b;
@@ -165,7 +169,7 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b,
if (!perf_evsel__is_group_event(evsel))
return ret;
- nr_members = evsel->nr_members;
+ nr_members = evsel->core.nr_members;
fields_a = calloc(nr_members, sizeof(*fields_a));
fields_b = calloc(nr_members, sizeof(*fields_b));
@@ -223,10 +227,10 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt,
struct hists *hists)
{
int len = fmt->user_len ?: fmt->len;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
if (symbol_conf.event_group)
- len = max(len, evsel->nr_members * fmt->len);
+ len = max(len, evsel->core.nr_members * fmt->len);
if (len < (int)strlen(fmt->name))
len = strlen(fmt->name);
@@ -795,9 +799,9 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
}
int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_hpp_fmt *fmt;
struct hists *hists;
int ret;
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index 8cd3b64c6893..99d60223c74b 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
-#include "../util/cache.h"
#include "progress.h"
static void null_progress__update(struct ui_progress *p __maybe_unused)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 44fe824e96cd..c7a86b4be9f5 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -2,10 +2,11 @@
#include <pthread.h>
#include <dlfcn.h>
-#include "../util/cache.h"
+#include <subcmd/pager.h>
#include "../util/debug.h"
#include "../util/hist.h"
#include "../util/util.h"
+#include "ui.h"
pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
void *perf_gtk_handle;
@@ -89,9 +90,9 @@ void setup_browser(bool fallback_to_pager)
printf("GTK browser requested but could not find %s\n",
PERF_GTK_DSO);
sleep(1);
+ use_browser = 1;
/* fall through */
case 1:
- use_browser = 1;
if (ui__init() == 0)
break;
/* fall through */
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index ee7ea6deed21..832ca6cfbe30 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
+#include <stdlib.h>
#include <linux/string.h>
#include "../../util/callchain.h"
+#include "../../util/debug.h"
#include "../../util/hist.h"
#include "../../util/map.h"
#include "../../util/map_groups.h"
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 93d6b7240285..5f188f678c55 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -3,6 +3,8 @@
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
#include "../../util/debug.h"
#include "../helpline.h"
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index bc134b82829d..3d74af5a7ece 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
-#include "../cache.h"
#include "../progress.h"
#include "../libslang.h"
#include "../ui.h"
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 3ad0d3363ac6..56651a4f5aa0 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <signal.h>
#include <stdbool.h>
@@ -8,9 +7,9 @@
#include <execinfo.h>
#endif
-#include "../../util/cache.h"
#include "../../util/debug.h"
#include "../../util/util.h"
+#include "../../perf.h"
#include "../browser.h"
#include "../helpline.h"
#include "../ui.h"
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index fe5e571816fc..087d9ab054c8 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <sys/ttydefaults.h>
-#include "../../util/cache.h"
#include "../../util/debug.h"
#include "../browser.h"
#include "../keysyms.h"
@@ -162,8 +161,7 @@ next_key:
return key;
}
-int ui__question_window(const char *title, const char *text,
- const char *exit_msg, int delay_secs)
+void __ui__info_window(const char *title, const char *text, const char *exit_msg)
{
int x, y;
int max_len = 0, nr_lines = 0;
@@ -185,10 +183,10 @@ int ui__question_window(const char *title, const char *text,
t = sep + 1;
}
- pthread_mutex_lock(&ui__lock);
-
max_len += 2;
- nr_lines += 4;
+ nr_lines += 2;
+ if (exit_msg)
+ nr_lines += 2;
y = SLtt_Screen_Rows / 2 - nr_lines / 2,
x = SLtt_Screen_Cols / 2 - max_len / 2;
@@ -199,18 +197,34 @@ int ui__question_window(const char *title, const char *text,
SLsmg_write_string((char *)title);
}
SLsmg_gotorc(++y, x);
- nr_lines -= 2;
+ if (exit_msg)
+ nr_lines -= 2;
max_len -= 2;
SLsmg_write_wrapped_string((unsigned char *)text, y, x,
nr_lines, max_len, 1);
- SLsmg_gotorc(y + nr_lines - 2, x);
- SLsmg_write_nstring((char *)" ", max_len);
- SLsmg_gotorc(y + nr_lines - 1, x);
- SLsmg_write_nstring((char *)exit_msg, max_len);
- SLsmg_refresh();
+ if (exit_msg) {
+ SLsmg_gotorc(y + nr_lines - 2, x);
+ SLsmg_write_nstring((char *)" ", max_len);
+ SLsmg_gotorc(y + nr_lines - 1, x);
+ SLsmg_write_nstring((char *)exit_msg, max_len);
+ }
+}
+void ui__info_window(const char *title, const char *text)
+{
+ pthread_mutex_lock(&ui__lock);
+ __ui__info_window(title, text, NULL);
+ SLsmg_refresh();
pthread_mutex_unlock(&ui__lock);
+}
+int ui__question_window(const char *title, const char *text,
+ const char *exit_msg, int delay_secs)
+{
+ pthread_mutex_lock(&ui__lock);
+ __ui__info_window(title, text, exit_msg);
+ SLsmg_refresh();
+ pthread_mutex_unlock(&ui__lock);
return ui__getch(delay_secs);
}
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index 63bf06e80ab9..689b27c34246 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "util.h"
-#include "../debug.h"
-
+#include "../util/debug.h"
+#include <stdio.h>
/*
* Default error logging functions
diff --git a/tools/perf/ui/util.h b/tools/perf/ui/util.h
index 5e44223b56fa..40891942f465 100644
--- a/tools/perf/ui/util.h
+++ b/tools/perf/ui/util.h
@@ -8,6 +8,8 @@ int ui__getch(int delay_secs);
int ui__popup_menu(int argc, char * const argv[]);
int ui__help_window(const char *text);
int ui__dialog_yesno(const char *msg);
+void __ui__info_window(const char *title, const char *text, const char *exit_msg);
+void ui__info_window(const char *title, const char *text);
int ui__question_window(const char *title, const char *text,
const char *exit_msg, int delay_secs);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 14f812bb07a7..0b4d8e0d474c 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -1,6 +1,7 @@
perf-y += annotate.o
perf-y += block-range.o
perf-y += build-id.o
+perf-y += cacheline.o
perf-y += config.o
perf-y += ctype.o
perf-y += db-export.o
@@ -9,6 +10,7 @@ perf-y += event.o
perf-y += evlist.o
perf-y += evsel.o
perf-y += evsel_fprintf.o
+perf-y += evswitch.o
perf-y += find_bit.o
perf-y += get_current_dir_name.o
perf-y += kallsyms.o
@@ -26,7 +28,6 @@ perf-y += rbtree.o
perf-y += libstring.o
perf-y += bitmap.o
perf-y += hweight.o
-perf-y += zalloc.o
perf-y += smt.o
perf-y += strbuf.o
perf-y += string.o
@@ -35,6 +36,7 @@ perf-y += strfilter.o
perf-y += top.o
perf-y += usage.o
perf-y += dso.o
+perf-y += dsos.o
perf-y += symbol.o
perf-y += symbol_fprintf.o
perf-y += color.o
@@ -70,7 +72,6 @@ perf-y += svghelper.o
perf-y += sort.o
perf-y += hist.o
perf-y += util.o
-perf-y += xyarray.o
perf-y += cpumap.o
perf-y += cputopo.o
perf-y += cgroup.o
@@ -150,6 +151,8 @@ perf-$(CONFIG_ZLIB) += zlib.o
perf-$(CONFIG_LZMA) += lzma.o
perf-$(CONFIG_ZSTD) += zstd.o
+perf-$(CONFIG_LIBCAP) += cap.o
+
perf-y += demangle-java.o
perf-y += demangle-rust.o
@@ -243,7 +246,3 @@ $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE
$(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
-
-$(OUTPUT)util/zalloc.o: ../lib/zalloc.c FORCE
- $(call rule_mkdir)
- $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index ac9ad2330f93..1748f528b6e9 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -9,6 +9,7 @@
#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
+#include <stdlib.h>
#include <bpf/bpf.h>
#include <bpf/btf.h>
#include <bpf/libbpf.h>
@@ -19,9 +20,12 @@
#include "build-id.h"
#include "color.h"
#include "config.h"
-#include "cache.h"
+#include "dso.h"
+#include "env.h"
#include "map.h"
+#include "map_groups.h"
#include "symbol.h"
+#include "srcline.h"
#include "units.h"
#include "debug.h"
#include "annotate.h"
@@ -37,6 +41,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <bpf/libbpf.h>
+#include <subcmd/parse-options.h>
/* FIXME: For the HE_COLORSET */
#include "ui/browser.h"
@@ -929,14 +934,14 @@ alloc_histograms:
}
static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel, u64 addr,
+ struct evsel *evsel, u64 addr,
struct perf_sample *sample)
{
struct annotated_source *src;
if (sym == NULL)
return 0;
- src = symbol__hists(sym, evsel->evlist->nr_entries);
+ src = symbol__hists(sym, evsel->evlist->core.nr_entries);
return (src) ? __symbol__inc_addr_samples(sym, map, src, evsel->idx,
addr, sample) : 0;
}
@@ -1080,13 +1085,13 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
}
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
}
int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
- struct perf_evsel *evsel, u64 ip)
+ struct evsel *evsel, u64 ip)
{
return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
}
@@ -1122,7 +1127,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
goto out;
(*rawp)[0] = tmp;
- *rawp = skip_spaces(*rawp);
+ *rawp = strim(*rawp);
return 0;
@@ -1134,7 +1139,7 @@ struct annotate_args {
size_t privsize;
struct arch *arch;
struct map_symbol ms;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct annotation_options *options;
s64 offset;
char *line;
@@ -1165,12 +1170,12 @@ static struct annotation_line *
annotation_line__new(struct annotate_args *args, size_t privsize)
{
struct annotation_line *al;
- struct perf_evsel *evsel = args->evsel;
+ struct evsel *evsel = args->evsel;
size_t size = privsize + sizeof(*al);
int nr = 1;
if (perf_evsel__is_group_event(evsel))
- nr = evsel->nr_members;
+ nr = evsel->core.nr_members;
size += sizeof(al->data[0]) * nr;
@@ -1359,7 +1364,7 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
static int
annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
- struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
+ struct evsel *evsel, u64 len, int min_pcnt, int printed,
int max_lines, struct annotation_line *queue, int addr_fmt_width,
int percent_type)
{
@@ -1448,7 +1453,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
return -1;
if (perf_evsel__is_group_event(evsel))
- width *= evsel->nr_members;
+ width *= evsel->core.nr_members;
if (!*al->line)
printf(" %*s:\n", width, " ");
@@ -2011,10 +2016,10 @@ static void calc_percent(struct sym_hist *sym_hist,
}
static void annotation__calc_percent(struct annotation *notes,
- struct perf_evsel *leader, s64 len)
+ struct evsel *leader, s64 len)
{
struct annotation_line *al, *next;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
list_for_each_entry(al, &notes->src->source, node) {
s64 end;
@@ -2041,7 +2046,7 @@ static void annotation__calc_percent(struct annotation *notes,
}
}
-void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
+void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
{
struct annotation *notes = symbol__annotation(sym);
@@ -2049,7 +2054,7 @@ void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
}
int symbol__annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel, size_t privsize,
+ struct evsel *evsel, size_t privsize,
struct annotation_options *options,
struct arch **parch)
{
@@ -2214,7 +2219,7 @@ static void print_summary(struct rb_root *root, const char *filename)
}
}
-static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
+static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel)
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evsel->idx);
@@ -2241,7 +2246,7 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
}
int symbol__annotate_printf(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct annotation_options *opts)
{
struct dso *dso = map->dso;
@@ -2272,7 +2277,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
len = symbol__size(sym);
if (perf_evsel__is_group_event(evsel)) {
- width *= evsel->nr_members;
+ width *= evsel->core.nr_members;
perf_evsel__group_desc(evsel, buf, sizeof(buf));
evsel_name = buf;
}
@@ -2405,7 +2410,7 @@ static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
return 0;
}
-int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
+int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
struct annotation_options *opts)
{
const char *ev_name = perf_evsel__name(evsel);
@@ -2657,7 +2662,7 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
}
int symbol__tty_annotate2(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct annotation_options *opts)
{
struct dso *dso = map->dso;
@@ -2685,7 +2690,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
}
int symbol__tty_annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct annotation_options *opts)
{
struct dso *dso = map->dso;
@@ -2956,7 +2961,7 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
wops->write_graph);
}
-int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
+int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel,
struct annotation_options *options, struct arch **parch)
{
struct annotation *notes = symbol__annotation(sym);
@@ -2968,7 +2973,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
return -1;
if (perf_evsel__is_group_event(evsel))
- nr_pcnt = evsel->nr_members;
+ nr_pcnt = evsel->core.nr_members;
err = symbol__annotate(sym, map, evsel, 0, options, parch);
if (err)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 5bc0cf655d37..d94be9140e31 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -20,7 +20,7 @@ struct map_symbol;
struct addr_map_symbol;
struct option;
struct perf_sample;
-struct perf_evsel;
+struct evsel;
struct symbol;
struct ins {
@@ -216,12 +216,12 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
int __annotation__scnprintf_samples_period(struct annotation *notes,
char *bf, size_t size,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
bool show_freq);
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name);
size_t disasm__fprintf(struct list_head *head, FILE *fp);
-void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
+void symbol__calc_percent(struct symbol *sym, struct evsel *evsel);
struct sym_hist {
u64 nr_samples;
@@ -245,7 +245,7 @@ struct cyc_hist {
/** struct annotated_source - symbols with hits have this attached as in sannotation
*
* @histograms: Array of addr hit histograms per event being monitored
- * nr_histograms: This may not be the same as evsel->evlist->nr_entries if
+ * nr_histograms: This may not be the same as evsel->evlist->core.nr_entries if
* we have more than a group in a evlist, where we will want
* to see each group separately, that is why symbol__annotate2()
* sets src->nr_histograms to evsel->nr_members.
@@ -335,24 +335,24 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
}
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
- struct perf_evsel *evsel);
+ struct evsel *evsel);
int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
struct addr_map_symbol *start,
unsigned cycles);
int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
- struct perf_evsel *evsel, u64 addr);
+ struct evsel *evsel, u64 addr);
struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel, size_t privsize,
+ struct evsel *evsel, size_t privsize,
struct annotation_options *options,
struct arch **parch);
int symbol__annotate2(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct annotation_options *options,
struct arch **parch);
@@ -378,32 +378,32 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
int errnum, char *buf, size_t buflen);
int symbol__annotate_printf(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct annotation_options *options);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
void annotated_source__purge(struct annotated_source *as);
-int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
+int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
struct annotation_options *opts);
bool ui__has_annotation(void);
int symbol__tty_annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel, struct annotation_options *opts);
+ struct evsel *evsel, struct annotation_options *opts);
int symbol__tty_annotate2(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel, struct annotation_options *opts);
+ struct evsel *evsel, struct annotation_options *opts);
#ifdef HAVE_SLANG_SUPPORT
int symbol__tui_annotate(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *opts);
#else
static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
struct map *map __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct hist_browser_timer *hbt __maybe_unused,
struct annotation_options *opts __maybe_unused)
{
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index a314e5b26e9d..8a7340f6a2a2 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -8,6 +8,8 @@
#include <errno.h>
#include <byteswap.h>
#include <inttypes.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/bitops.h>
@@ -17,10 +19,8 @@
#include "cpumap.h"
#include "color.h"
#include "evsel.h"
-#include "evlist.h"
#include "machine.h"
#include "session.h"
-#include "thread.h"
#include "debug.h"
#include "auxtrace.h"
#include "arm-spe.h"
@@ -181,7 +181,7 @@ static const char * const arm_spe_info_fmts[] = {
[ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n",
};
-static void arm_spe_print_info(u64 *arr)
+static void arm_spe_print_info(__u64 *arr)
{
if (!dump_trace)
return;
@@ -192,12 +192,12 @@ static void arm_spe_print_info(u64 *arr)
int arm_spe_process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
size_t min_sz = sizeof(u64) * ARM_SPE_PMU_TYPE;
struct arm_spe *spe;
int err;
- if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
+ if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
min_sz)
return -EINVAL;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index ec0af36697c4..6f25224a3def 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -26,7 +26,6 @@
#include <linux/list.h>
#include <linux/zalloc.h>
-#include "../perf.h"
#include "evlist.h"
#include "dso.h"
#include "map.h"
@@ -41,6 +40,7 @@
#include <linux/hash.h>
#include "event.h"
+#include "record.h"
#include "session.h"
#include "debug.h"
#include <subcmd/parse-options.h>
@@ -50,6 +50,7 @@
#include "intel-bts.h"
#include "arm-spe.h"
#include "s390-cpumsf.h"
+#include "util.h"
#include <linux/ctype.h>
#include "symbol/kallsyms.h"
@@ -124,20 +125,20 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
}
void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
- struct perf_evlist *evlist, int idx,
+ struct evlist *evlist, int idx,
bool per_cpu)
{
mp->idx = idx;
if (per_cpu) {
- mp->cpu = evlist->cpus->map[idx];
- if (evlist->threads)
- mp->tid = thread_map__pid(evlist->threads, 0);
+ mp->cpu = evlist->core.cpus->map[idx];
+ if (evlist->core.threads)
+ mp->tid = perf_thread_map__pid(evlist->core.threads, 0);
else
mp->tid = -1;
} else {
mp->cpu = -1;
- mp->tid = thread_map__pid(evlist->threads, idx);
+ mp->tid = perf_thread_map__pid(evlist->core.threads, idx);
}
}
@@ -385,7 +386,7 @@ static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
return err;
if (event->header.type == PERF_RECORD_AUXTRACE) {
- if (event->header.size < sizeof(struct auxtrace_event) ||
+ if (event->header.size < sizeof(struct perf_record_auxtrace) ||
event->header.size != sz) {
err = -EINVAL;
goto out;
@@ -503,7 +504,7 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap)
}
size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
if (itr)
return itr->info_priv_size(itr, evlist);
@@ -518,7 +519,7 @@ static int auxtrace_not_supported(void)
int auxtrace_record__info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size)
{
if (itr)
@@ -539,9 +540,9 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
return 0;
}
-int auxtrace_record__snapshot_finish(struct auxtrace_record *itr)
+int auxtrace_record__snapshot_finish(struct auxtrace_record *itr, bool on_exit)
{
- if (itr && itr->snapshot_finish)
+ if (!on_exit && itr && itr->snapshot_finish)
return itr->snapshot_finish(itr);
return 0;
}
@@ -556,7 +557,7 @@ int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
}
int auxtrace_record__options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts)
{
if (itr)
@@ -577,6 +578,16 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
if (!str)
return 0;
+ /* PMU-agnostic options */
+ switch (*str) {
+ case 'e':
+ opts->auxtrace_snapshot_on_exit = true;
+ str++;
+ break;
+ default:
+ break;
+ }
+
if (itr)
return itr->parse_snapshot_options(itr, opts, str);
@@ -585,7 +596,7 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
}
struct auxtrace_record *__weak
-auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
+auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err)
{
*err = 0;
return NULL;
@@ -848,13 +859,13 @@ void auxtrace_buffer__free(struct auxtrace_buffer *buffer)
free(buffer);
}
-void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
+void auxtrace_synth_error(struct perf_record_auxtrace_error *auxtrace_error, int type,
int code, int cpu, pid_t pid, pid_t tid, u64 ip,
const char *msg, u64 timestamp)
{
size_t size;
- memset(auxtrace_error, 0, sizeof(struct auxtrace_error_event));
+ memset(auxtrace_error, 0, sizeof(struct perf_record_auxtrace_error));
auxtrace_error->header.type = PERF_RECORD_AUXTRACE_ERROR;
auxtrace_error->type = type;
@@ -883,12 +894,12 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
pr_debug2("Synthesizing auxtrace information\n");
priv_size = auxtrace_record__info_priv_size(itr, session->evlist);
- ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
+ ev = zalloc(sizeof(struct perf_record_auxtrace_info) + priv_size);
if (!ev)
return -ENOMEM;
ev->auxtrace_info.header.type = PERF_RECORD_AUXTRACE_INFO;
- ev->auxtrace_info.header.size = sizeof(struct auxtrace_info_event) +
+ ev->auxtrace_info.header.size = sizeof(struct perf_record_auxtrace_info) +
priv_size;
err = auxtrace_record__info_fill(itr, session, &ev->auxtrace_info,
priv_size);
@@ -932,7 +943,7 @@ s64 perf_event__process_auxtrace(struct perf_session *session,
s64 err;
if (dump_trace)
- fprintf(stdout, " size: %#"PRIx64" offset: %#"PRIx64" ref: %#"PRIx64" idx: %u tid: %d cpu: %d\n",
+ fprintf(stdout, " size: %#"PRI_lx64" offset: %#"PRI_lx64" ref: %#"PRI_lx64" idx: %u tid: %d cpu: %d\n",
event->auxtrace.size, event->auxtrace.offset,
event->auxtrace.reference, event->auxtrace.idx,
event->auxtrace.tid, event->auxtrace.cpu);
@@ -964,6 +975,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
synth_opts->transactions = true;
synth_opts->ptwrites = true;
synth_opts->pwr_events = true;
+ synth_opts->other_events = true;
synth_opts->errors = true;
if (no_sample) {
synth_opts->period_type = PERF_ITRACE_PERIOD_INSTRUCTIONS;
@@ -1061,6 +1073,9 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
case 'p':
synth_opts->pwr_events = true;
break;
+ case 'o':
+ synth_opts->other_events = true;
+ break;
case 'e':
synth_opts->errors = true;
break;
@@ -1154,7 +1169,7 @@ static const char *auxtrace_error_name(int type)
size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp)
{
- struct auxtrace_error_event *e = &event->auxtrace_error;
+ struct perf_record_auxtrace_error *e = &event->auxtrace_error;
unsigned long long nsecs = e->time;
const char *msg = e->msg;
int ret;
@@ -1174,7 +1189,7 @@ size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp)
if (!e->fmt)
msg = (const char *)&e->time;
- ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRIx64" code %u: %s\n",
+ ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRI_lx64" code %u: %s\n",
e->cpu, e->pid, e->tid, e->ip, e->code, msg);
return ret;
}
@@ -1182,7 +1197,7 @@ size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp)
void perf_session__auxtrace_error_inc(struct perf_session *session,
union perf_event *event)
{
- struct auxtrace_error_event *e = &event->auxtrace_error;
+ struct perf_record_auxtrace_error *e = &event->auxtrace_error;
if (e->type < PERF_AUXTRACE_ERROR_MAX)
session->evlist->stats.nr_auxtrace_errors[e->type] += 1;
@@ -2084,7 +2099,7 @@ static char *addr_filter__to_str(struct addr_filter *filt)
return err < 0 ? NULL : filter;
}
-static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
+static int parse_addr_filter(struct evsel *evsel, const char *filter,
int max_nr)
{
struct addr_filters filts;
@@ -2135,19 +2150,19 @@ out_exit:
return err;
}
-static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
+static struct perf_pmu *perf_evsel__find_pmu(struct evsel *evsel)
{
struct perf_pmu *pmu = NULL;
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
- if (pmu->type == evsel->attr.type)
+ if (pmu->type == evsel->core.attr.type)
break;
}
return pmu;
}
-static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
+static int perf_evsel__nr_addr_filter(struct evsel *evsel)
{
struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
int nr_addr_filters = 0;
@@ -2160,9 +2175,9 @@ static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
return nr_addr_filters;
}
-int auxtrace_parse_filters(struct perf_evlist *evlist)
+int auxtrace_parse_filters(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
char *filter;
int err, max_nr;
@@ -2181,3 +2196,36 @@ int auxtrace_parse_filters(struct perf_evlist *evlist)
return 0;
}
+
+int auxtrace__process_event(struct perf_session *session, union perf_event *event,
+ struct perf_sample *sample, struct perf_tool *tool)
+{
+ if (!session->auxtrace)
+ return 0;
+
+ return session->auxtrace->process_event(session, event, sample, tool);
+}
+
+int auxtrace__flush_events(struct perf_session *session, struct perf_tool *tool)
+{
+ if (!session->auxtrace)
+ return 0;
+
+ return session->auxtrace->flush_events(session, tool);
+}
+
+void auxtrace__free_events(struct perf_session *session)
+{
+ if (!session->auxtrace)
+ return;
+
+ return session->auxtrace->free_events(session);
+}
+
+void auxtrace__free(struct perf_session *session)
+{
+ if (!session->auxtrace)
+ return;
+
+ return session->auxtrace->free(session);
+}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index e9b4c5edf78b..37e70dc01436 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -15,22 +15,25 @@
#include <linux/perf_event.h>
#include <linux/types.h>
#include <asm/bitsperlong.h>
+#include <asm/barrier.h>
-#include "../perf.h"
#include "event.h"
-#include "session.h"
-#include "debug.h"
union perf_event;
struct perf_session;
-struct perf_evlist;
+struct evlist;
struct perf_tool;
struct perf_mmap;
struct option;
struct record_opts;
-struct auxtrace_info_event;
+struct perf_record_auxtrace_info;
struct events_stats;
+enum auxtrace_error_type {
+ PERF_AUXTRACE_ERROR_ITRACE = 1,
+ PERF_AUXTRACE_ERROR_MAX
+};
+
/* Auxtrace records must have the same alignment as perf event records */
#define PERF_AUXTRACE_RECORD_ALIGNMENT 8
@@ -60,6 +63,8 @@ enum itrace_period_type {
* @transactions: whether to synthesize events for transactions
* @ptwrites: whether to synthesize events for ptwrites
* @pwr_events: whether to synthesize power events
+ * @other_events: whether to synthesize other events recorded due to the use of
+ * aux_output
* @errors: whether to synthesize decoder error events
* @dont_decode: whether to skip decoding entirely
* @log: write a decoding log
@@ -86,6 +91,7 @@ struct itrace_synth_opts {
bool transactions;
bool ptwrites;
bool pwr_events;
+ bool other_events;
bool errors;
bool dont_decode;
bool log;
@@ -309,13 +315,13 @@ struct auxtrace_mmap_params {
*/
struct auxtrace_record {
int (*recording_options)(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts);
size_t (*info_priv_size)(struct auxtrace_record *itr,
- struct perf_evlist *evlist);
+ struct evlist *evlist);
int (*info_fill)(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size);
void (*free)(struct auxtrace_record *itr);
int (*snapshot_start)(struct auxtrace_record *itr);
@@ -373,6 +379,8 @@ struct addr_filters {
int cnt;
};
+struct auxtrace_cache;
+
#ifdef HAVE_AUXTRACE_SUPPORT
/*
@@ -432,7 +440,7 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
unsigned int auxtrace_pages,
bool auxtrace_overwrite);
void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
- struct perf_evlist *evlist, int idx,
+ struct evlist *evlist, int idx,
bool per_cpu);
typedef int (*process_auxtrace_t)(struct perf_tool *tool,
@@ -482,24 +490,24 @@ int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
struct auxtrace_cache_entry *entry);
void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
-struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
+struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
int *err);
int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
struct record_opts *opts,
const char *str);
int auxtrace_record__options(struct auxtrace_record *itr,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct record_opts *opts);
size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
- struct perf_evlist *evlist);
+ struct evlist *evlist);
int auxtrace_record__info_fill(struct auxtrace_record *itr,
struct perf_session *session,
- struct auxtrace_info_event *auxtrace_info,
+ struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size);
void auxtrace_record__free(struct auxtrace_record *itr);
int auxtrace_record__snapshot_start(struct auxtrace_record *itr);
-int auxtrace_record__snapshot_finish(struct auxtrace_record *itr);
+int auxtrace_record__snapshot_finish(struct auxtrace_record *itr, bool on_exit);
int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
struct auxtrace_mmap *mm,
unsigned char *data, u64 *head, u64 *old);
@@ -512,7 +520,7 @@ int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
bool needs_swap);
void auxtrace_index__free(struct list_head *head);
-void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
+void auxtrace_synth_error(struct perf_record_auxtrace_error *auxtrace_error, int type,
int code, int cpu, pid_t pid, pid_t tid, u64 ip,
const char *msg, u64 timestamp);
@@ -540,43 +548,13 @@ void addr_filters__init(struct addr_filters *filts);
void addr_filters__exit(struct addr_filters *filts);
int addr_filters__parse_bare_filter(struct addr_filters *filts,
const char *filter);
-int auxtrace_parse_filters(struct perf_evlist *evlist);
-
-static inline int auxtrace__process_event(struct perf_session *session,
- union perf_event *event,
- struct perf_sample *sample,
- struct perf_tool *tool)
-{
- if (!session->auxtrace)
- return 0;
-
- return session->auxtrace->process_event(session, event, sample, tool);
-}
-
-static inline int auxtrace__flush_events(struct perf_session *session,
- struct perf_tool *tool)
-{
- if (!session->auxtrace)
- return 0;
-
- return session->auxtrace->flush_events(session, tool);
-}
+int auxtrace_parse_filters(struct evlist *evlist);
-static inline void auxtrace__free_events(struct perf_session *session)
-{
- if (!session->auxtrace)
- return;
-
- return session->auxtrace->free_events(session);
-}
-
-static inline void auxtrace__free(struct perf_session *session)
-{
- if (!session->auxtrace)
- return;
-
- return session->auxtrace->free(session);
-}
+int auxtrace__process_event(struct perf_session *session, union perf_event *event,
+ struct perf_sample *sample, struct perf_tool *tool);
+int auxtrace__flush_events(struct perf_session *session, struct perf_tool *tool);
+void auxtrace__free_events(struct perf_session *session);
+void auxtrace__free(struct perf_session *session);
#define ITRACE_HELP \
" i: synthesize instructions events\n" \
@@ -611,9 +589,10 @@ void itrace_synth_opts__clear_time_range(struct itrace_synth_opts *opts)
}
#else
+#include "debug.h"
static inline struct auxtrace_record *
-auxtrace_record__init(struct perf_evlist *evlist __maybe_unused,
+auxtrace_record__init(struct evlist *evlist __maybe_unused,
int *err)
{
*err = 0;
@@ -636,7 +615,7 @@ perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused,
static inline
int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
struct record_opts *opts __maybe_unused)
{
return 0;
@@ -733,7 +712,7 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
}
static inline
-int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
+int auxtrace_parse_filters(struct evlist *evlist __maybe_unused)
{
return 0;
}
@@ -747,7 +726,7 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
unsigned int auxtrace_pages,
bool auxtrace_overwrite);
void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
- struct perf_evlist *evlist, int idx,
+ struct evlist *evlist, int idx,
bool per_cpu);
#define ITRACE_HELP ""
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
index 2a4a0da35632..7a3d4b125323 100644
--- a/tools/perf/util/bpf-event.c
+++ b/tools/perf/util/bpf-event.c
@@ -8,12 +8,14 @@
#include <linux/err.h>
#include "bpf-event.h"
#include "debug.h"
+#include "dso.h"
#include "symbol.h"
#include "machine.h"
#include "env.h"
#include "session.h"
#include "map.h"
#include "evlist.h"
+#include "record.h"
#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
@@ -34,7 +36,7 @@ static int machine__process_bpf_event_load(struct machine *machine,
struct bpf_prog_info_linear *info_linear;
struct bpf_prog_info_node *info_node;
struct perf_env *env = machine->env;
- int id = event->bpf_event.id;
+ int id = event->bpf.id;
unsigned int i;
/* perf-record, no need to handle bpf-event */
@@ -63,14 +65,13 @@ static int machine__process_bpf_event_load(struct machine *machine,
return 0;
}
-int machine__process_bpf_event(struct machine *machine __maybe_unused,
- union perf_event *event,
- struct perf_sample *sample __maybe_unused)
+int machine__process_bpf(struct machine *machine, union perf_event *event,
+ struct perf_sample *sample)
{
if (dump_trace)
- perf_event__fprintf_bpf_event(event, stdout);
+ perf_event__fprintf_bpf(event, stdout);
- switch (event->bpf_event.type) {
+ switch (event->bpf.type) {
case PERF_BPF_EVENT_PROG_LOAD:
return machine__process_bpf_event_load(machine, event, sample);
@@ -82,8 +83,7 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused,
*/
break;
default:
- pr_debug("unexpected bpf_event type of %d\n",
- event->bpf_event.type);
+ pr_debug("unexpected bpf event type of %d\n", event->bpf.type);
break;
}
return 0;
@@ -160,8 +160,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
union perf_event *event,
struct record_opts *opts)
{
- struct ksymbol_event *ksymbol_event = &event->ksymbol_event;
- struct bpf_event *bpf_event = &event->bpf_event;
+ struct perf_record_ksymbol *ksymbol_event = &event->ksymbol;
+ struct perf_record_bpf_event *bpf_event = &event->bpf;
struct bpf_prog_info_linear *info_linear;
struct perf_tool *tool = session->tool;
struct bpf_prog_info_node *info_node;
@@ -229,10 +229,10 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
__u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms);
int name_len;
- *ksymbol_event = (struct ksymbol_event){
+ *ksymbol_event = (struct perf_record_ksymbol) {
.header = {
.type = PERF_RECORD_KSYMBOL,
- .size = offsetof(struct ksymbol_event, name),
+ .size = offsetof(struct perf_record_ksymbol, name),
},
.addr = prog_addrs[i],
.len = prog_lens[i],
@@ -253,10 +253,10 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
if (!opts->no_bpf_event) {
/* Synthesize PERF_RECORD_BPF_EVENT */
- *bpf_event = (struct bpf_event){
+ *bpf_event = (struct perf_record_bpf_event) {
.header = {
.type = PERF_RECORD_BPF_EVENT,
- .size = sizeof(struct bpf_event),
+ .size = sizeof(struct perf_record_bpf_event),
},
.type = PERF_BPF_EVENT_PROG_LOAD,
.flags = 0,
@@ -301,7 +301,7 @@ int perf_event__synthesize_bpf_events(struct perf_session *session,
int err;
int fd;
- event = malloc(sizeof(event->bpf_event) + KSYM_NAME_LEN + machine->id_hdr_size);
+ event = malloc(sizeof(event->bpf) + KSYM_NAME_LEN + machine->id_hdr_size);
if (!event)
return -1;
while (true) {
@@ -398,9 +398,9 @@ static int bpf_event__sb_cb(union perf_event *event, void *data)
if (event->header.type != PERF_RECORD_BPF_EVENT)
return -1;
- switch (event->bpf_event.type) {
+ switch (event->bpf.type) {
case PERF_BPF_EVENT_PROG_LOAD:
- perf_env__add_bpf_info(env, event->bpf_event.id);
+ perf_env__add_bpf_info(env, event->bpf.id);
case PERF_BPF_EVENT_PROG_UNLOAD:
/*
@@ -410,15 +410,14 @@ static int bpf_event__sb_cb(union perf_event *event, void *data)
*/
break;
default:
- pr_debug("unexpected bpf_event type of %d\n",
- event->bpf_event.type);
+ pr_debug("unexpected bpf event type of %d\n", event->bpf.type);
break;
}
return 0;
}
-int bpf_event__add_sb_event(struct perf_evlist **evlist,
+int bpf_event__add_sb_event(struct evlist **evlist,
struct perf_env *env)
{
struct perf_event_attr attr = {
diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h
index 04c33b3bfe28..a01c2fd68c03 100644
--- a/tools/perf/util/bpf-event.h
+++ b/tools/perf/util/bpf-event.h
@@ -13,6 +13,7 @@ struct machine;
union perf_event;
struct perf_env;
struct perf_sample;
+struct perf_session;
struct record_opts;
struct evlist;
struct target;
@@ -30,22 +31,22 @@ struct btf_node {
};
#ifdef HAVE_LIBBPF_SUPPORT
-int machine__process_bpf_event(struct machine *machine, union perf_event *event,
- struct perf_sample *sample);
+int machine__process_bpf(struct machine *machine, union perf_event *event,
+ struct perf_sample *sample);
int perf_event__synthesize_bpf_events(struct perf_session *session,
perf_event__handler_t process,
struct machine *machine,
struct record_opts *opts);
-int bpf_event__add_sb_event(struct perf_evlist **evlist,
+int bpf_event__add_sb_event(struct evlist **evlist,
struct perf_env *env);
void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
struct perf_env *env,
FILE *fp);
#else
-static inline int machine__process_bpf_event(struct machine *machine __maybe_unused,
- union perf_event *event __maybe_unused,
- struct perf_sample *sample __maybe_unused)
+static inline int machine__process_bpf(struct machine *machine __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample __maybe_unused)
{
return 0;
}
@@ -58,7 +59,7 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session
return 0;
}
-static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused,
+static inline int bpf_event__add_sb_event(struct evlist **evlist __maybe_unused,
struct perf_env *env __maybe_unused)
{
return 0;
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index c61974a50aa5..37283e865352 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,7 +14,7 @@
#include <linux/string.h>
#include <linux/zalloc.h>
#include <errno.h>
-#include "perf.h"
+#include <stdlib.h>
#include "debug.h"
#include "evlist.h"
#include "bpf-loader.h"
@@ -23,9 +23,12 @@
#include "probe-finder.h" // for MAX_PROBES
#include "parse-events.h"
#include "strfilter.h"
+#include "util.h"
#include "llvm-utils.h"
#include "c++/clang-c.h"
+#include <internal/xyarray.h>
+
static int libbpf_perf_print(enum libbpf_print_level level __attribute__((unused)),
const char *fmt, va_list args)
{
@@ -763,7 +766,7 @@ int bpf__foreach_event(struct bpf_object *obj,
if (priv->is_tp) {
fd = bpf_program__fd(prog);
- err = (*func)(priv->sys_name, priv->evt_name, fd, arg);
+ err = (*func)(priv->sys_name, priv->evt_name, fd, obj, arg);
if (err) {
pr_debug("bpf: tracepoint call back failed, stop iterate\n");
return err;
@@ -788,7 +791,7 @@ int bpf__foreach_event(struct bpf_object *obj,
return fd;
}
- err = (*func)(tev->group, tev->event, fd, arg);
+ err = (*func)(tev->group, tev->event, fd, obj, arg);
if (err) {
pr_debug("bpf: call back failed, stop iterate\n");
return err;
@@ -817,7 +820,7 @@ struct bpf_map_op {
} k;
union {
u64 value;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
} v;
};
@@ -1043,7 +1046,7 @@ __bpf_map__config_value(struct bpf_map *map,
static int
bpf_map__config_value(struct bpf_map *map,
struct parse_events_term *term,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
if (!term->err_val) {
pr_debug("Config value not set\n");
@@ -1061,9 +1064,9 @@ bpf_map__config_value(struct bpf_map *map,
static int
__bpf_map__config_event(struct bpf_map *map,
struct parse_events_term *term,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
const struct bpf_map_def *def;
struct bpf_map_op *op;
const char *map_name = bpf_map__name(map);
@@ -1103,7 +1106,7 @@ __bpf_map__config_event(struct bpf_map *map,
static int
bpf_map__config_event(struct bpf_map *map,
struct parse_events_term *term,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
if (!term->err_val) {
pr_debug("Config value not set\n");
@@ -1121,7 +1124,7 @@ bpf_map__config_event(struct bpf_map *map,
struct bpf_obj_config__map_func {
const char *config_opt;
int (*config_func)(struct bpf_map *, struct parse_events_term *,
- struct perf_evlist *);
+ struct evlist *);
};
struct bpf_obj_config__map_func bpf_obj_config__map_funcs[] = {
@@ -1169,7 +1172,7 @@ config_map_indices_range_check(struct parse_events_term *term,
static int
bpf__obj_config_map(struct bpf_object *obj,
struct parse_events_term *term,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int *key_scan_pos)
{
/* key is "map:<mapname>.<config opt>" */
@@ -1228,7 +1231,7 @@ out:
int bpf__config_obj(struct bpf_object *obj,
struct parse_events_term *term,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int *error_pos)
{
int key_scan_pos = 0;
@@ -1401,9 +1404,9 @@ apply_config_value_for_key(int map_fd, void *pkey,
static int
apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
- struct xyarray *xy = evsel->fd;
+ struct xyarray *xy = evsel->core.fd;
struct perf_event_attr *attr;
unsigned int key, events;
bool check_pass = false;
@@ -1421,7 +1424,7 @@ apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM;
}
- attr = &evsel->attr;
+ attr = &evsel->core.attr;
if (attr->inherit) {
pr_debug("ERROR: Can't put inherit event into map %s\n", name);
return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
@@ -1523,11 +1526,11 @@ int bpf__apply_obj_config(void)
(strcmp(name, \
bpf_map__name(pos)) == 0))
-struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name)
+struct evsel *bpf__setup_output_event(struct evlist *evlist, const char *name)
{
struct bpf_map_priv *tmpl_priv = NULL;
struct bpf_object *obj, *tmp;
- struct perf_evsel *evsel = NULL;
+ struct evsel *evsel = NULL;
struct bpf_map *map;
int err;
bool need_init = false;
@@ -1600,9 +1603,9 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha
return evsel;
}
-int bpf__setup_stdout(struct perf_evlist *evlist)
+int bpf__setup_stdout(struct evlist *evlist)
{
- struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
+ struct evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
return PTR_ERR_OR_ZERO(evsel);
}
@@ -1756,7 +1759,7 @@ int bpf__strerror_load(struct bpf_object *obj,
int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
struct parse_events_term *term __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
int *error_pos __maybe_unused, int err,
char *buf, size_t size)
{
@@ -1780,7 +1783,7 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
return 0;
}
-int bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
+int bpf__strerror_setup_output_event(struct evlist *evlist __maybe_unused,
int err, char *buf, size_t size)
{
bpf__strerror_head(err, buf, size);
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 3f46856e3330..25251d63164c 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -39,14 +39,14 @@ enum bpf_loader_errno {
__BPF_LOADER_ERRNO__END,
};
-struct perf_evsel;
-struct perf_evlist;
+struct evsel;
+struct evlist;
struct bpf_object;
struct parse_events_term;
#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
typedef int (*bpf_prog_iter_callback_t)(const char *group, const char *event,
- int fd, void *arg);
+ int fd, struct bpf_object *obj, void *arg);
#ifdef HAVE_LIBBPF_SUPPORT
struct bpf_object *bpf__prepare_load(const char *filename, bool source);
@@ -70,18 +70,18 @@ int bpf__foreach_event(struct bpf_object *obj,
bpf_prog_iter_callback_t func, void *arg);
int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term,
- struct perf_evlist *evlist, int *error_pos);
+ struct evlist *evlist, int *error_pos);
int bpf__strerror_config_obj(struct bpf_object *obj,
struct parse_events_term *term,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int *error_pos, int err, char *buf,
size_t size);
int bpf__apply_obj_config(void);
int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
-int bpf__setup_stdout(struct perf_evlist *evlist);
-struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name);
-int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size);
+int bpf__setup_stdout(struct evlist *evlist);
+struct evsel *bpf__setup_output_event(struct evlist *evlist, const char *name);
+int bpf__strerror_setup_output_event(struct evlist *evlist, int err, char *buf, size_t size);
#else
#include <errno.h>
#include <string.h>
@@ -119,7 +119,7 @@ bpf__foreach_event(struct bpf_object *obj __maybe_unused,
static inline int
bpf__config_obj(struct bpf_object *obj __maybe_unused,
struct parse_events_term *term __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
int *error_pos __maybe_unused)
{
return 0;
@@ -132,13 +132,13 @@ bpf__apply_obj_config(void)
}
static inline int
-bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
+bpf__setup_stdout(struct evlist *evlist __maybe_unused)
{
return 0;
}
-static inline struct perf_evsel *
-bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused)
+static inline struct evsel *
+bpf__setup_output_event(struct evlist *evlist __maybe_unused, const char *name __maybe_unused)
{
return NULL;
}
@@ -182,7 +182,7 @@ static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
static inline int
bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
struct parse_events_term *term __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
int *error_pos __maybe_unused,
int err __maybe_unused,
char *buf, size_t size)
@@ -198,7 +198,7 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
}
static inline int
-bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
+bpf__strerror_setup_output_event(struct evlist *evlist __maybe_unused,
int err __maybe_unused, char *buf, size_t size)
{
return __bpf_strerror(buf, size);
@@ -206,7 +206,7 @@ bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
#endif
-static inline int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, char *buf, size_t size)
+static inline int bpf__strerror_setup_stdout(struct evlist *evlist, int err, char *buf, size_t size)
{
return bpf__strerror_setup_output_event(evlist, err, buf, size);
}
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 77e4891e17b0..b020a8678eb9 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -8,12 +8,12 @@
*/
#include <bpf/libbpf.h>
-#include "perf.h"
#include "debug.h"
#include "bpf-loader.h"
#include "bpf-prologue.h"
#include "probe-finder.h"
#include <errno.h>
+#include <stdlib.h>
#include <dwarf-regs.h>
#include <linux/filter.h>
diff --git a/tools/perf/util/branch.c b/tools/perf/util/branch.c
index a4fce2729e50..9d1e090084a2 100644
--- a/tools/perf/util/branch.c
+++ b/tools/perf/util/branch.c
@@ -1,7 +1,8 @@
-#include "perf.h"
#include "util/util.h"
#include "util/debug.h"
+#include "util/map_symbol.h"
#include "util/branch.h"
+#include <linux/kernel.h>
static bool cross_area(u64 addr1, u64 addr2, int size)
{
diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h
index 64f96b79f1d7..06f66dad0b79 100644
--- a/tools/perf/util/branch.h
+++ b/tools/perf/util/branch.h
@@ -16,6 +16,14 @@ struct branch_flags {
u64 reserved:40;
};
+struct branch_info {
+ struct addr_map_symbol from;
+ struct addr_map_symbol to;
+ struct branch_flags flags;
+ char *srcline_from;
+ char *srcline_to;
+};
+
struct branch_entry {
u64 from;
u64 to;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index f1abfab7aa8c..e5fb77755d9e 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include "dso.h"
#include "build-id.h"
#include "event.h"
#include "namespaces.h"
@@ -37,7 +38,7 @@ static bool no_buildid_cache;
int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine)
{
struct addr_location al;
@@ -295,7 +296,7 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,
pid_t pid, u16 misc, struct feat_fd *fd)
{
int err;
- struct build_id_event b;
+ struct perf_record_header_build_id b;
size_t len;
len = name_len + 1;
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 93668f38f1ed..aad419bb165c 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -24,7 +24,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
bool is_debug);
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
- struct perf_sample *sample, struct perf_evsel *evsel,
+ struct perf_sample *sample, struct evsel *evsel,
struct machine *machine);
int dsos__hit_all(struct perf_session *session);
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index e513366f2ee0..2df8a45bd088 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -3,7 +3,6 @@
#define PERF_UTIL_CLANG_C_H
#include <stddef.h> /* for size_t */
-#include <util-cxx.h> /* for __maybe_unused */
#ifdef __cplusplus
extern "C" {
@@ -22,6 +21,7 @@ extern int perf_clang__compile_bpf(const char *filename,
#else
#include <errno.h>
+#include <linux/compiler.h> /* for __maybe_unused */
static inline void perf_clang__init(void) { }
static inline void perf_clang__cleanup(void) { }
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 7b042a5ebc68..21b23605f78b 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include "clang.h"
#include "clang-c.h"
+extern "C" {
+#include "../util.h"
+}
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
-#include <util-cxx.h>
#include <tests/llvm.h>
#include <string>
diff --git a/tools/perf/util/cacheline.c b/tools/perf/util/cacheline.c
new file mode 100644
index 000000000000..e98b5250a517
--- /dev/null
+++ b/tools/perf/util/cacheline.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "cacheline.h"
+#include <unistd.h>
+
+#ifdef _SC_LEVEL1_DCACHE_LINESIZE
+#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
+#else
+#include <api/fs/fs.h>
+#include "debug.h"
+static void cache_line_size(int *cacheline_sizep)
+{
+ if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
+ pr_debug("cannot determine cache line size");
+}
+#endif
+
+int cacheline_size(void)
+{
+ static int size;
+
+ if (!size)
+ cache_line_size(&size);
+
+ return size;
+}
diff --git a/tools/perf/util/cacheline.h b/tools/perf/util/cacheline.h
new file mode 100644
index 000000000000..dec8c0fb1f4a
--- /dev/null
+++ b/tools/perf/util/cacheline.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef PERF_CACHELINE_H
+#define PERF_CACHELINE_H
+
+#include <linux/compiler.h>
+
+int __pure cacheline_size(void);
+
+static inline u64 cl_address(u64 address)
+{
+ /* return the cacheline of the address */
+ return (address & ~(cacheline_size() - 1));
+}
+
+static inline u64 cl_offset(u64 address)
+{
+ /* return the cacheline of the address */
+ return (address & (cacheline_size() - 1));
+}
+
+#endif // PERF_CACHELINE_H
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 8d7d8f62fcca..c14646c1f2eb 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -16,10 +16,13 @@
#include <stdbool.h>
#include <errno.h>
#include <math.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include "asm/bug.h"
+#include "debug.h"
+#include "dso.h"
#include "hist.h"
#include "sort.h"
#include "machine.h"
@@ -27,6 +30,7 @@
#include "callchain.h"
#include "branch.h"
#include "symbol.h"
+#include "../perf.h"
#define CALLCHAIN_PARAM_DEFAULT \
.mode = CHAIN_GRAPH_ABS, \
@@ -1077,7 +1081,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
int sample__resolve_callchain(struct perf_sample *sample,
struct callchain_cursor *cursor, struct symbol **parent,
- struct perf_evsel *evsel, struct addr_location *al,
+ struct evsel *evsel, struct addr_location *al,
int max_stack)
{
if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 80e056a3d882..b042ceef4114 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -8,6 +8,7 @@
#include "map_symbol.h"
#include "branch.h"
+struct evsel;
struct map;
#define HELP_PAD "\t\t\t\t"
@@ -236,7 +237,7 @@ int record_opts__parse_callchain(struct record_opts *record,
int sample__resolve_callchain(struct perf_sample *sample,
struct callchain_cursor *cursor, struct symbol **parent,
- struct perf_evsel *evsel, struct addr_location *al,
+ struct evsel *evsel, struct addr_location *al,
int max_stack);
int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
diff --git a/tools/perf/util/cap.c b/tools/perf/util/cap.c
new file mode 100644
index 000000000000..c3ba841bbf37
--- /dev/null
+++ b/tools/perf/util/cap.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Capability utilities
+ */
+
+#ifdef HAVE_LIBCAP_SUPPORT
+
+#include "cap.h"
+#include <stdbool.h>
+#include <sys/capability.h>
+
+bool perf_cap__capable(cap_value_t cap)
+{
+ cap_flag_value_t val;
+ cap_t caps = cap_get_proc();
+
+ if (!caps)
+ return false;
+
+ if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &val) != 0)
+ val = CAP_CLEAR;
+
+ if (cap_free(caps) != 0)
+ return false;
+
+ return val == CAP_SET;
+}
+
+#endif /* HAVE_LIBCAP_SUPPORT */
diff --git a/tools/perf/util/cap.h b/tools/perf/util/cap.h
new file mode 100644
index 000000000000..051dc590ceee
--- /dev/null
+++ b/tools/perf/util/cap.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_CAP_H
+#define __PERF_CAP_H
+
+#include <stdbool.h>
+#include <linux/capability.h>
+#include <linux/compiler.h>
+
+#ifdef HAVE_LIBCAP_SUPPORT
+
+#include <sys/capability.h>
+
+bool perf_cap__capable(cap_value_t cap);
+
+#else
+
+#include <unistd.h>
+#include <sys/types.h>
+
+static inline bool perf_cap__capable(int cap __maybe_unused)
+{
+ return geteuid() == 0;
+}
+
+#endif /* HAVE_LIBCAP_SUPPORT */
+
+/* For older systems */
+#ifndef CAP_SYSLOG
+#define CAP_SYSLOG 34
+#endif
+
+#endif /* __PERF_CAP_H */
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 484c29830a81..4881d4af3381 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../perf.h"
#include <subcmd/parse-options.h>
#include "evsel.h"
#include "cgroup.h"
@@ -9,6 +8,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
int nr_cgroups;
@@ -90,9 +91,9 @@ static int open_cgroup(const char *name)
return fd;
}
-static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str)
+static struct cgroup *evlist__find_cgroup(struct evlist *evlist, const char *str)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
/*
* check if cgrp is already defined, if so we reuse it
*/
@@ -130,16 +131,16 @@ out_err:
return NULL;
}
-struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name)
+struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name)
{
struct cgroup *cgroup = evlist__find_cgroup(evlist, name);
return cgroup ?: cgroup__new(name);
}
-static int add_cgroup(struct perf_evlist *evlist, const char *str)
+static int add_cgroup(struct evlist *evlist, const char *str)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str);
int n;
@@ -184,15 +185,15 @@ struct cgroup *cgroup__get(struct cgroup *cgroup)
return cgroup;
}
-static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup)
+static void evsel__set_default_cgroup(struct evsel *evsel, struct cgroup *cgroup)
{
if (evsel->cgrp == NULL)
evsel->cgrp = cgroup__get(cgroup);
}
-void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup)
+void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel)
evsel__set_default_cgroup(evsel, cgroup);
@@ -201,14 +202,14 @@ void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgrou
int parse_cgroups(const struct option *opt, const char *str,
int unset __maybe_unused)
{
- struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
- struct perf_evsel *counter;
+ struct evlist *evlist = *(struct evlist **)opt->value;
+ struct evsel *counter;
struct cgroup *cgrp = NULL;
const char *p, *e, *eos = str + strlen(str);
char *s;
int ret, i;
- if (list_empty(&evlist->entries)) {
+ if (list_empty(&evlist->core.entries)) {
fprintf(stderr, "must define events before cgroups\n");
return -1;
}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index f033a80c1b14..2ec11f01090d 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -18,11 +18,11 @@ extern int nr_cgroups; /* number of explicit cgroups defined */
struct cgroup *cgroup__get(struct cgroup *cgroup);
void cgroup__put(struct cgroup *cgroup);
-struct perf_evlist;
+struct evlist;
-struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name);
+struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name);
-void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup);
+void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup);
int parse_cgroups(const struct option *opt, const char *str, int unset);
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 06f48312c5ed..4e904fcb2783 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -2,12 +2,14 @@
#include <errno.h>
#include <sched.h>
#include "util.h"
-#include "../perf.h"
+#include "../perf-sys.h"
#include "cloexec.h"
+#include "event.h"
#include "asm/bug.h"
#include "debug.h"
#include <unistd.h>
#include <sys/syscall.h>
+#include <linux/string.h>
static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 39b8c4ec4e2e..bffbdd216a6a 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
-#include "cache.h"
+#include <subcmd/pager.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "color.h"
#include <math.h>
#include <unistd.h>
diff --git a/tools/perf/util/color_config.c b/tools/perf/util/color_config.c
index 817dc56e7e95..dc09ba7cb31e 100644
--- a/tools/perf/util/color_config.c
+++ b/tools/perf/util/color_config.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
-#include "cache.h"
+#include <subcmd/pager.h>
+#include <string.h>
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 042ffbc8c53f..0bc9c4d7fdc5 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -17,9 +17,13 @@
#include "util/event.h" /* proc_map_timeout */
#include "util/hist.h" /* perf_hist_config */
#include "util/llvm-utils.h" /* perf_llvm_config */
+#include "build-id.h"
+#include "debug.h"
#include "config.h"
+#include "debug.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdlib.h>
#include <unistd.h>
#include <linux/string.h>
#include <linux/zalloc.h>
diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c
index 88be9c4365e0..f94e1a23dad6 100644
--- a/tools/perf/util/counts.c
+++ b/tools/perf/util/counts.c
@@ -19,6 +19,15 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)
}
counts->values = values;
+
+ values = xyarray__new(ncpus, nthreads, sizeof(bool));
+ if (!values) {
+ xyarray__delete(counts->values);
+ free(counts);
+ return NULL;
+ }
+
+ counts->loaded = values;
}
return counts;
@@ -27,6 +36,7 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)
void perf_counts__delete(struct perf_counts *counts)
{
if (counts) {
+ xyarray__delete(counts->loaded);
xyarray__delete(counts->values);
free(counts);
}
@@ -34,21 +44,22 @@ void perf_counts__delete(struct perf_counts *counts)
static void perf_counts__reset(struct perf_counts *counts)
{
+ xyarray__reset(counts->loaded);
xyarray__reset(counts->values);
}
-void perf_evsel__reset_counts(struct perf_evsel *evsel)
+void perf_evsel__reset_counts(struct evsel *evsel)
{
perf_counts__reset(evsel->counts);
}
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
+int perf_evsel__alloc_counts(struct evsel *evsel, int ncpus, int nthreads)
{
evsel->counts = perf_counts__new(ncpus, nthreads);
return evsel->counts != NULL ? 0 : -ENOMEM;
}
-void perf_evsel__free_counts(struct perf_evsel *evsel)
+void perf_evsel__free_counts(struct evsel *evsel)
{
perf_counts__delete(evsel->counts);
evsel->counts = NULL;
diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h
index 0d1050ccc586..92196df4945f 100644
--- a/tools/perf/util/counts.h
+++ b/tools/perf/util/counts.h
@@ -2,24 +2,18 @@
#ifndef __PERF_COUNTS_H
#define __PERF_COUNTS_H
-#include "xyarray.h"
-
-struct perf_counts_values {
- union {
- struct {
- u64 val;
- u64 ena;
- u64 run;
- };
- u64 values[3];
- };
- bool loaded;
-};
+#include <linux/types.h>
+#include <internal/xyarray.h>
+#include <perf/evsel.h>
+#include <stdbool.h>
+
+struct evsel;
struct perf_counts {
s8 scaled;
struct perf_counts_values aggr;
struct xyarray *values;
+ struct xyarray *loaded;
};
@@ -29,11 +23,23 @@ perf_counts(struct perf_counts *counts, int cpu, int thread)
return xyarray__entry(counts->values, cpu, thread);
}
+static inline bool
+perf_counts__is_loaded(struct perf_counts *counts, int cpu, int thread)
+{
+ return *((bool *) xyarray__entry(counts->loaded, cpu, thread));
+}
+
+static inline void
+perf_counts__set_loaded(struct perf_counts *counts, int cpu, int thread, bool loaded)
+{
+ *((bool *) xyarray__entry(counts->loaded, cpu, thread)) = loaded;
+}
+
struct perf_counts *perf_counts__new(int ncpus, int nthreads);
void perf_counts__delete(struct perf_counts *counts);
-void perf_evsel__reset_counts(struct perf_evsel *evsel);
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads);
-void perf_evsel__free_counts(struct perf_evsel *evsel);
+void perf_evsel__reset_counts(struct evsel *evsel);
+int perf_evsel__alloc_counts(struct evsel *evsel, int ncpus, int nthreads);
+void perf_evsel__free_counts(struct evsel *evsel);
#endif /* __PERF_COUNTS_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3acfbe34ebaf..a22c1114e880 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
#include <api/fs/fs.h>
-#include "../perf.h"
#include "cpumap.h"
+#include "debug.h"
+#include "event.h"
#include <assert.h>
#include <dirent.h>
#include <stdio.h>
@@ -17,190 +18,11 @@ static int max_present_cpu_num;
static int max_node_num;
static int *cpunode_map;
-static struct cpu_map *cpu_map__default_new(void)
+static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
{
- struct cpu_map *cpus;
- int nr_cpus;
+ struct perf_cpu_map *map;
- nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
- if (nr_cpus < 0)
- return NULL;
-
- cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
- if (cpus != NULL) {
- int i;
- for (i = 0; i < nr_cpus; ++i)
- cpus->map[i] = i;
-
- cpus->nr = nr_cpus;
- refcount_set(&cpus->refcnt, 1);
- }
-
- return cpus;
-}
-
-static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
-{
- size_t payload_size = nr_cpus * sizeof(int);
- struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
-
- if (cpus != NULL) {
- cpus->nr = nr_cpus;
- memcpy(cpus->map, tmp_cpus, payload_size);
- refcount_set(&cpus->refcnt, 1);
- }
-
- return cpus;
-}
-
-struct cpu_map *cpu_map__read(FILE *file)
-{
- struct cpu_map *cpus = NULL;
- int nr_cpus = 0;
- int *tmp_cpus = NULL, *tmp;
- int max_entries = 0;
- int n, cpu, prev;
- char sep;
-
- sep = 0;
- prev = -1;
- for (;;) {
- n = fscanf(file, "%u%c", &cpu, &sep);
- if (n <= 0)
- break;
- if (prev >= 0) {
- int new_max = nr_cpus + cpu - prev - 1;
-
- if (new_max >= max_entries) {
- max_entries = new_max + MAX_NR_CPUS / 2;
- tmp = realloc(tmp_cpus, max_entries * sizeof(int));
- if (tmp == NULL)
- goto out_free_tmp;
- tmp_cpus = tmp;
- }
-
- while (++prev < cpu)
- tmp_cpus[nr_cpus++] = prev;
- }
- if (nr_cpus == max_entries) {
- max_entries += MAX_NR_CPUS;
- tmp = realloc(tmp_cpus, max_entries * sizeof(int));
- if (tmp == NULL)
- goto out_free_tmp;
- tmp_cpus = tmp;
- }
-
- tmp_cpus[nr_cpus++] = cpu;
- if (n == 2 && sep == '-')
- prev = cpu;
- else
- prev = -1;
- if (n == 1 || sep == '\n')
- break;
- }
-
- if (nr_cpus > 0)
- cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
- else
- cpus = cpu_map__default_new();
-out_free_tmp:
- free(tmp_cpus);
- return cpus;
-}
-
-static struct cpu_map *cpu_map__read_all_cpu_map(void)
-{
- struct cpu_map *cpus = NULL;
- FILE *onlnf;
-
- onlnf = fopen("/sys/devices/system/cpu/online", "r");
- if (!onlnf)
- return cpu_map__default_new();
-
- cpus = cpu_map__read(onlnf);
- fclose(onlnf);
- return cpus;
-}
-
-struct cpu_map *cpu_map__new(const char *cpu_list)
-{
- struct cpu_map *cpus = NULL;
- unsigned long start_cpu, end_cpu = 0;
- char *p = NULL;
- int i, nr_cpus = 0;
- int *tmp_cpus = NULL, *tmp;
- int max_entries = 0;
-
- if (!cpu_list)
- return cpu_map__read_all_cpu_map();
-
- /*
- * must handle the case of empty cpumap to cover
- * TOPOLOGY header for NUMA nodes with no CPU
- * ( e.g., because of CPU hotplug)
- */
- if (!isdigit(*cpu_list) && *cpu_list != '\0')
- goto out;
-
- while (isdigit(*cpu_list)) {
- p = NULL;
- start_cpu = strtoul(cpu_list, &p, 0);
- if (start_cpu >= INT_MAX
- || (*p != '\0' && *p != ',' && *p != '-'))
- goto invalid;
-
- if (*p == '-') {
- cpu_list = ++p;
- p = NULL;
- end_cpu = strtoul(cpu_list, &p, 0);
-
- if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
- goto invalid;
-
- if (end_cpu < start_cpu)
- goto invalid;
- } else {
- end_cpu = start_cpu;
- }
-
- for (; start_cpu <= end_cpu; start_cpu++) {
- /* check for duplicates */
- for (i = 0; i < nr_cpus; i++)
- if (tmp_cpus[i] == (int)start_cpu)
- goto invalid;
-
- if (nr_cpus == max_entries) {
- max_entries += MAX_NR_CPUS;
- tmp = realloc(tmp_cpus, max_entries * sizeof(int));
- if (tmp == NULL)
- goto invalid;
- tmp_cpus = tmp;
- }
- tmp_cpus[nr_cpus++] = (int)start_cpu;
- }
- if (*p)
- ++p;
-
- cpu_list = p;
- }
-
- if (nr_cpus > 0)
- cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
- else if (*cpu_list != '\0')
- cpus = cpu_map__default_new();
- else
- cpus = cpu_map__dummy_new();
-invalid:
- free(tmp_cpus);
-out:
- return cpus;
-}
-
-static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
-{
- struct cpu_map *map;
-
- map = cpu_map__empty_new(cpus->nr);
+ map = perf_cpu_map__empty_new(cpus->nr);
if (map) {
unsigned i;
@@ -220,14 +42,14 @@ static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
return map;
}
-static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask)
+static struct perf_cpu_map *cpu_map__from_mask(struct perf_record_record_cpu_map *mask)
{
- struct cpu_map *map;
+ struct perf_cpu_map *map;
int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE;
nr = bitmap_weight(mask->mask, nbits);
- map = cpu_map__empty_new(nr);
+ map = perf_cpu_map__empty_new(nr);
if (map) {
int cpu, i = 0;
@@ -238,15 +60,15 @@ static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask)
}
-struct cpu_map *cpu_map__new_data(struct cpu_map_data *data)
+struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data)
{
if (data->type == PERF_CPU_MAP__CPUS)
return cpu_map__from_entries((struct cpu_map_entries *)data->data);
else
- return cpu_map__from_mask((struct cpu_map_mask *)data->data);
+ return cpu_map__from_mask((struct perf_record_record_cpu_map *)data->data);
}
-size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
+size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp)
{
#define BUFSIZE 1024
char buf[BUFSIZE];
@@ -256,22 +78,9 @@ size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
#undef BUFSIZE
}
-struct cpu_map *cpu_map__dummy_new(void)
-{
- struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
-
- if (cpus != NULL) {
- cpus->nr = 1;
- cpus->map[0] = -1;
- refcount_set(&cpus->refcnt, 1);
- }
-
- return cpus;
-}
-
-struct cpu_map *cpu_map__empty_new(int nr)
+struct perf_cpu_map *perf_cpu_map__empty_new(int nr)
{
- struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr);
+ struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr);
if (cpus != NULL) {
int i;
@@ -286,28 +95,6 @@ struct cpu_map *cpu_map__empty_new(int nr)
return cpus;
}
-static void cpu_map__delete(struct cpu_map *map)
-{
- if (map) {
- WARN_ONCE(refcount_read(&map->refcnt) != 0,
- "cpu_map refcnt unbalanced\n");
- free(map);
- }
-}
-
-struct cpu_map *cpu_map__get(struct cpu_map *map)
-{
- if (map)
- refcount_inc(&map->refcnt);
- return map;
-}
-
-void cpu_map__put(struct cpu_map *map)
-{
- if (map && refcount_dec_and_test(&map->refcnt))
- cpu_map__delete(map);
-}
-
static int cpu__get_topology_int(int cpu, const char *name, int *value)
{
char path[PATH_MAX];
@@ -324,7 +111,7 @@ int cpu_map__get_socket_id(int cpu)
return ret ?: value;
}
-int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
+int cpu_map__get_socket(struct perf_cpu_map *map, int idx, void *data __maybe_unused)
{
int cpu;
@@ -341,11 +128,11 @@ static int cmp_ids(const void *a, const void *b)
return *(int *)a - *(int *)b;
}
-int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
- int (*f)(struct cpu_map *map, int cpu, void *data),
+int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res,
+ int (*f)(struct perf_cpu_map *map, int cpu, void *data),
void *data)
{
- struct cpu_map *c;
+ struct perf_cpu_map *c;
int nr = cpus->nr;
int cpu, s1, s2;
@@ -380,7 +167,7 @@ int cpu_map__get_die_id(int cpu)
return ret ?: value;
}
-int cpu_map__get_die(struct cpu_map *map, int idx, void *data)
+int cpu_map__get_die(struct perf_cpu_map *map, int idx, void *data)
{
int cpu, die_id, s;
@@ -419,7 +206,7 @@ int cpu_map__get_core_id(int cpu)
return ret ?: value;
}
-int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
+int cpu_map__get_core(struct perf_cpu_map *map, int idx, void *data)
{
int cpu, s_die;
@@ -448,17 +235,17 @@ int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
return (s_die << 16) | (cpu & 0xffff);
}
-int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
+int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct perf_cpu_map **sockp)
{
return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL);
}
-int cpu_map__build_die_map(struct cpu_map *cpus, struct cpu_map **diep)
+int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct perf_cpu_map **diep)
{
return cpu_map__build_map(cpus, diep, cpu_map__get_die, NULL);
}
-int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
+int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct perf_cpu_map **corep)
{
return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL);
}
@@ -670,29 +457,17 @@ int cpu__setup_cpunode_map(void)
return 0;
}
-bool cpu_map__has(struct cpu_map *cpus, int cpu)
+bool cpu_map__has(struct perf_cpu_map *cpus, int cpu)
{
- return cpu_map__idx(cpus, cpu) != -1;
+ return perf_cpu_map__idx(cpus, cpu) != -1;
}
-int cpu_map__idx(struct cpu_map *cpus, int cpu)
-{
- int i;
-
- for (i = 0; i < cpus->nr; ++i) {
- if (cpus->map[i] == cpu)
- return i;
- }
-
- return -1;
-}
-
-int cpu_map__cpu(struct cpu_map *cpus, int idx)
+int cpu_map__cpu(struct perf_cpu_map *cpus, int idx)
{
return cpus->map[idx];
}
-size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size)
+size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size)
{
int i, cpu, start = -1;
bool first = true;
@@ -744,14 +519,17 @@ static char hex_char(unsigned char val)
return '?';
}
-size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
+size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size)
{
int i, cpu;
char *ptr = buf;
unsigned char *bitmap;
int last_cpu = cpu_map__cpu(map, map->nr - 1);
- bitmap = zalloc((last_cpu + 7) / 8);
+ if (buf == NULL)
+ return 0;
+
+ bitmap = zalloc(last_cpu / 8 + 1);
if (bitmap == NULL) {
buf[0] = '\0';
return 0;
@@ -781,12 +559,12 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
return ptr - buf;
}
-const struct cpu_map *cpu_map__online(void) /* thread unsafe */
+const struct perf_cpu_map *cpu_map__online(void) /* thread unsafe */
{
- static const struct cpu_map *online = NULL;
+ static const struct perf_cpu_map *online = NULL;
if (!online)
- online = cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */
+ online = perf_cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */
return online;
}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 1265f0e33920..2553bef1279d 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -4,40 +4,28 @@
#include <stdio.h>
#include <stdbool.h>
-#include <linux/refcount.h>
+#include <internal/cpumap.h>
+#include <perf/cpumap.h>
-#include "perf.h"
-#include "util/debug.h"
+struct perf_record_cpu_map_data;
-struct cpu_map {
- refcount_t refcnt;
- int nr;
- int map[];
-};
-
-struct cpu_map *cpu_map__new(const char *cpu_list);
-struct cpu_map *cpu_map__empty_new(int nr);
-struct cpu_map *cpu_map__dummy_new(void);
-struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
-struct cpu_map *cpu_map__read(FILE *file);
-size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size);
-size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size);
-size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
+struct perf_cpu_map *perf_cpu_map__empty_new(int nr);
+struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data);
+size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size);
+size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size);
+size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp);
int cpu_map__get_socket_id(int cpu);
-int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
+int cpu_map__get_socket(struct perf_cpu_map *map, int idx, void *data);
int cpu_map__get_die_id(int cpu);
-int cpu_map__get_die(struct cpu_map *map, int idx, void *data);
+int cpu_map__get_die(struct perf_cpu_map *map, int idx, void *data);
int cpu_map__get_core_id(int cpu);
-int cpu_map__get_core(struct cpu_map *map, int idx, void *data);
-int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
-int cpu_map__build_die_map(struct cpu_map *cpus, struct cpu_map **diep);
-int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
-const struct cpu_map *cpu_map__online(void); /* thread unsafe */
-
-struct cpu_map *cpu_map__get(struct cpu_map *map);
-void cpu_map__put(struct cpu_map *map);
+int cpu_map__get_core(struct perf_cpu_map *map, int idx, void *data);
+int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct perf_cpu_map **sockp);
+int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct perf_cpu_map **diep);
+int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct perf_cpu_map **corep);
+const struct perf_cpu_map *cpu_map__online(void); /* thread unsafe */
-static inline int cpu_map__socket(struct cpu_map *sock, int s)
+static inline int cpu_map__socket(struct perf_cpu_map *sock, int s)
{
if (!sock || s > sock->nr || s < 0)
return 0;
@@ -59,16 +47,6 @@ static inline int cpu_map__id_to_cpu(int id)
return id & 0xffff;
}
-static inline int cpu_map__nr(const struct cpu_map *map)
-{
- return map ? map->nr : 1;
-}
-
-static inline bool cpu_map__empty(const struct cpu_map *map)
-{
- return map ? map->map[0] == -1 : true;
-}
-
int cpu__setup_cpunode_map(void);
int cpu__max_node(void);
@@ -76,11 +54,10 @@ int cpu__max_cpu(void);
int cpu__max_present_cpu(void);
int cpu__get_node(int cpu);
-int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
- int (*f)(struct cpu_map *map, int cpu, void *data),
+int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res,
+ int (*f)(struct perf_cpu_map *map, int cpu, void *data),
void *data);
-int cpu_map__cpu(struct cpu_map *cpus, int idx);
-bool cpu_map__has(struct cpu_map *cpus, int cpu);
-int cpu_map__idx(struct cpu_map *cpus, int cpu);
+int cpu_map__cpu(struct perf_cpu_map *cpus, int idx);
+bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);
#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
index 64336a280967..1b52402a8923 100644
--- a/tools/perf/util/cputopo.c
+++ b/tools/perf/util/cputopo.c
@@ -3,11 +3,14 @@
#include <sys/utsname.h>
#include <inttypes.h>
#include <stdlib.h>
+#include <string.h>
#include <api/fs/fs.h>
#include <linux/zalloc.h>
+#include <perf/cpumap.h>
#include "cputopo.h"
#include "cpumap.h"
+#include "debug.h"
#include "env.h"
#define CORE_SIB_FMT \
@@ -176,13 +179,13 @@ struct cpu_topology *cpu_topology__new(void)
size_t sz;
long ncpus;
int ret = -1;
- struct cpu_map *map;
+ struct perf_cpu_map *map;
bool has_die = has_die_topology();
ncpus = cpu__max_present_cpu();
/* build online CPU map */
- map = cpu_map__new(NULL);
+ map = perf_cpu_map__new(NULL);
if (map == NULL) {
pr_debug("failed to get system cpumap\n");
return NULL;
@@ -219,7 +222,7 @@ struct cpu_topology *cpu_topology__new(void)
}
out_free:
- cpu_map__put(map);
+ perf_cpu_map__put(map);
if (ret) {
cpu_topology__delete(tp);
tp = NULL;
@@ -289,7 +292,7 @@ err:
struct numa_topology *numa_topology__new(void)
{
- struct cpu_map *node_map = NULL;
+ struct perf_cpu_map *node_map = NULL;
struct numa_topology *tp = NULL;
char path[MAXPATHLEN];
char *buf = NULL;
@@ -312,7 +315,7 @@ struct numa_topology *numa_topology__new(void)
if (c)
*c = '\0';
- node_map = cpu_map__new(buf);
+ node_map = perf_cpu_map__new(buf);
if (!node_map)
goto out;
@@ -335,7 +338,7 @@ struct numa_topology *numa_topology__new(void)
out:
free(buf);
fclose(fp);
- cpu_map__put(node_map);
+ perf_cpu_map__put(node_map);
return tp;
}
diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h
index bae2f1d41856..7bf6b811f715 100644
--- a/tools/perf/util/cputopo.h
+++ b/tools/perf/util/cputopo.h
@@ -3,7 +3,6 @@
#define __PERF_CPUTOPO_H
#include <linux/types.h>
-#include "env.h"
struct cpu_topology {
u32 core_sib;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 3d1c34fc4d68..707afdbd9529 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -21,14 +21,18 @@
#include "cs-etm.h"
#include "cs-etm-decoder/cs-etm-decoder.h"
#include "debug.h"
+#include "dso.h"
#include "evlist.h"
#include "intlist.h"
#include "machine.h"
#include "map.h"
#include "perf.h"
+#include "session.h"
+#include "map_symbol.h"
+#include "branch.h"
#include "symbol.h"
+#include "tool.h"
#include "thread.h"
-#include "thread_map.h"
#include "thread-stack.h"
#include <tools/libc_compat.h>
#include "util.h"
@@ -1076,6 +1080,35 @@ bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq)
return !!etmq->etm->timeless_decoding;
}
+static void cs_etm__copy_insn(struct cs_etm_queue *etmq,
+ u64 trace_chan_id,
+ const struct cs_etm_packet *packet,
+ struct perf_sample *sample)
+{
+ /*
+ * It's pointless to read instructions for the CS_ETM_DISCONTINUITY
+ * packet, so directly bail out with 'insn_len' = 0.
+ */
+ if (packet->sample_type == CS_ETM_DISCONTINUITY) {
+ sample->insn_len = 0;
+ return;
+ }
+
+ /*
+ * T32 instruction size might be 32-bit or 16-bit, decide by calling
+ * cs_etm__t32_instr_size().
+ */
+ if (packet->isa == CS_ETM_ISA_T32)
+ sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id,
+ sample->ip);
+ /* Otherwise, A64 and A32 instruction size are always 32-bit. */
+ else
+ sample->insn_len = 4;
+
+ cs_etm__mem_access(etmq, trace_chan_id, sample->ip,
+ sample->insn_len, (void *)sample->insn);
+}
+
static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
struct cs_etm_traceid_queue *tidq,
u64 addr, u64 period)
@@ -1097,9 +1130,10 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
sample.period = period;
sample.cpu = tidq->packet->cpu;
sample.flags = tidq->prev_packet->flags;
- sample.insn_len = 1;
sample.cpumode = event->sample.header.misc;
+ cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample);
+
if (etm->synth_opts.last_branch) {
cs_etm__copy_last_branch_rb(etmq, tidq);
sample.branch_stack = tidq->last_branch;
@@ -1159,6 +1193,9 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq,
sample.flags = tidq->prev_packet->flags;
sample.cpumode = event->sample.header.misc;
+ cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->prev_packet,
+ &sample);
+
/*
* perf report cannot handle events without a branch stack
*/
@@ -1222,15 +1259,15 @@ static int cs_etm__synth_event(struct perf_session *session,
static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel;
struct perf_event_attr attr;
bool found = false;
u64 id;
int err;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == etm->pmu_type) {
+ if (evsel->core.attr.type == etm->pmu_type) {
found = true;
break;
}
@@ -1244,7 +1281,7 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.size = sizeof(struct perf_event_attr);
attr.type = PERF_TYPE_HARDWARE;
- attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK;
+ attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
PERF_SAMPLE_PERIOD;
if (etm->timeless_decoding)
@@ -1252,13 +1289,13 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
else
attr.sample_type |= PERF_SAMPLE_TIME;
- attr.exclude_user = evsel->attr.exclude_user;
- attr.exclude_kernel = evsel->attr.exclude_kernel;
- attr.exclude_hv = evsel->attr.exclude_hv;
- attr.exclude_host = evsel->attr.exclude_host;
- attr.exclude_guest = evsel->attr.exclude_guest;
- attr.sample_id_all = evsel->attr.sample_id_all;
- attr.read_format = evsel->attr.read_format;
+ attr.exclude_user = evsel->core.attr.exclude_user;
+ attr.exclude_kernel = evsel->core.attr.exclude_kernel;
+ attr.exclude_hv = evsel->core.attr.exclude_hv;
+ attr.exclude_host = evsel->core.attr.exclude_host;
+ attr.exclude_guest = evsel->core.attr.exclude_guest;
+ attr.sample_id_all = evsel->core.attr.sample_id_all;
+ attr.read_format = evsel->core.attr.read_format;
/* create new id val to be a fixed offset from evsel id */
id = evsel->id[0] + 1000000000;
@@ -2294,8 +2331,8 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
{
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = etm->session->evlist;
+ struct evsel *evsel;
+ struct evlist *evlist = etm->session->evlist;
bool timeless_decoding = true;
/*
@@ -2303,7 +2340,7 @@ static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
* with the time bit set.
*/
evlist__for_each_entry(evlist, evsel) {
- if ((evsel->attr.sample_type & PERF_SAMPLE_TIME))
+ if ((evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
timeless_decoding = false;
}
@@ -2337,7 +2374,7 @@ static const char * const cs_etmv4_priv_fmts[] = {
[CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %llx\n",
};
-static void cs_etm__print_auxtrace_info(u64 *val, int num)
+static void cs_etm__print_auxtrace_info(__u64 *val, int num)
{
int i, j, cpu = 0;
@@ -2360,7 +2397,7 @@ static void cs_etm__print_auxtrace_info(u64 *val, int num)
int cs_etm__process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
struct cs_etm_auxtrace *etm = NULL;
struct int_node *inode;
unsigned int pmu_type;
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index bc848fd095f4..650ecc2a6349 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -8,9 +8,10 @@
#define INCLUDE__UTIL_PERF_CS_ETM_H__
#include "util/event.h"
-#include "util/session.h"
#include <linux/bits.h>
+struct perf_session;
+
/* Versionning header in case things need tro change in the future. That way
* decoding of old snapshot is still possible.
*/
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index ddbcd59f2d9b..0c268449959c 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -413,7 +413,7 @@ static int add_tracepoint_fields_values(struct ctf_writer *cw,
static int add_tracepoint_values(struct ctf_writer *cw,
struct bt_ctf_event_class *event_class,
struct bt_ctf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
@@ -584,10 +584,10 @@ put_len_type:
static int add_generic_values(struct ctf_writer *cw,
struct bt_ctf_event *event,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample)
{
- u64 type = evsel->attr.sample_type;
+ u64 type = evsel->core.attr.sample_type;
int ret;
/*
@@ -753,11 +753,11 @@ static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
}
static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
int cpu = 0;
- if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
+ if (evsel->core.attr.sample_type & PERF_SAMPLE_CPU)
cpu = sample->cpu;
if (cpu > cw->stream_cnt) {
@@ -785,7 +785,7 @@ static bool is_flush_needed(struct ctf_stream *cs)
static int process_sample_event(struct perf_tool *tool,
union perf_event *_event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine __maybe_unused)
{
struct convert *c = container_of(tool, struct convert, tool);
@@ -795,7 +795,7 @@ static int process_sample_event(struct perf_tool *tool,
struct bt_ctf_event_class *event_class;
struct bt_ctf_event *event;
int ret;
- unsigned long type = evsel->attr.sample_type;
+ unsigned long type = evsel->core.attr.sample_type;
if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
return 0;
@@ -820,7 +820,7 @@ static int process_sample_event(struct perf_tool *tool,
if (ret)
return -1;
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
ret = add_tracepoint_values(cw, event_class, event,
evsel, sample);
if (ret)
@@ -1051,7 +1051,7 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw,
}
static int add_tracepoint_types(struct ctf_writer *cw,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct bt_ctf_event_class *class)
{
struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
@@ -1084,10 +1084,10 @@ static int add_bpf_output_types(struct ctf_writer *cw,
return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
}
-static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
+static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel,
struct bt_ctf_event_class *event_class)
{
- u64 type = evsel->attr.sample_type;
+ u64 type = evsel->core.attr.sample_type;
/*
* missing:
@@ -1150,14 +1150,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
return 0;
}
-static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
+static int add_event(struct ctf_writer *cw, struct evsel *evsel)
{
struct bt_ctf_event_class *event_class;
struct evsel_priv *priv;
const char *name = perf_evsel__name(evsel);
int ret;
- pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
+ pr("Adding event '%s' (type %d)\n", name, evsel->core.attr.type);
event_class = bt_ctf_event_class_create(name);
if (!event_class)
@@ -1167,7 +1167,7 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
if (ret)
goto err;
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
ret = add_tracepoint_types(cw, evsel, event_class);
if (ret)
goto err;
@@ -1201,8 +1201,8 @@ err:
static int setup_events(struct ctf_writer *cw, struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel;
int ret;
evlist__for_each_entry(evlist, evsel) {
@@ -1308,8 +1308,8 @@ static int setup_non_sample_events(struct ctf_writer *cw,
static void cleanup_events(struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
struct evsel_priv *priv;
@@ -1319,7 +1319,7 @@ static void cleanup_events(struct perf_session *session)
zfree(&evsel->priv);
}
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
session->evlist = NULL;
}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1d1b97a92c3f..e75c3a279fe8 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -9,7 +10,6 @@
#include <unistd.h>
#include <string.h>
#include <asm/bug.h>
-#include <sys/types.h>
#include <dirent.h>
#include "data.h"
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index ffbb3e7d3288..752227b265e7 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <stdlib.h>
+#include "dso.h"
#include "evsel.h"
#include "machine.h"
#include "thread.h"
@@ -32,7 +33,7 @@ void db_export__exit(struct db_export *dbe)
dbe->crp = NULL;
}
-int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
+int db_export__evsel(struct db_export *dbe, struct evsel *evsel)
{
if (evsel->db_id)
return 0;
@@ -209,7 +210,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
struct machine *machine,
struct thread *thread,
struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
u64 kernel_start = machine__kernel_start(machine);
struct call_path *current = &dbe->cpr->call_path;
@@ -341,7 +342,7 @@ static int db_export__threads(struct db_export *dbe, struct thread *thread,
}
int db_export__sample(struct db_export *dbe, union perf_event *event,
- struct perf_sample *sample, struct perf_evsel *evsel,
+ struct perf_sample *sample, struct evsel *evsel,
struct addr_location *al)
{
struct thread *thread = al->thread;
@@ -388,8 +389,8 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
}
}
- if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
- sample_addr_correlates_sym(&evsel->attr)) {
+ if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
+ sample_addr_correlates_sym(&evsel->core.attr)) {
struct addr_location addr_al;
thread__resolve(thread, &addr_al, sample);
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index ba1f62a5fe10..9c3d38f5a40d 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -10,7 +10,7 @@
#include <linux/types.h>
#include <linux/list.h>
-struct perf_evsel;
+struct evsel;
struct machine;
struct thread;
struct comm;
@@ -25,7 +25,7 @@ struct call_return;
struct export_sample {
union perf_event *event;
struct perf_sample *sample;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct addr_location *al;
u64 db_id;
u64 comm_db_id;
@@ -39,7 +39,7 @@ struct export_sample {
};
struct db_export {
- int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
+ int (*export_evsel)(struct db_export *dbe, struct evsel *evsel);
int (*export_machine)(struct db_export *dbe, struct machine *machine);
int (*export_thread)(struct db_export *dbe, struct thread *thread,
u64 main_thread_db_id, struct machine *machine);
@@ -79,7 +79,7 @@ struct db_export {
int db_export__init(struct db_export *dbe);
void db_export__exit(struct db_export *dbe);
-int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
+int db_export__evsel(struct db_export *dbe, struct evsel *evsel);
int db_export__machine(struct db_export *dbe, struct machine *machine);
int db_export__thread(struct db_export *dbe, struct thread *thread,
struct machine *machine, struct thread *main_thread);
@@ -96,7 +96,7 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym,
int db_export__branch_type(struct db_export *dbe, u32 branch_type,
const char *name);
int db_export__sample(struct db_export *dbe, union perf_event *event,
- struct perf_sample *sample, struct perf_evsel *evsel,
+ struct perf_sample *sample, struct evsel *evsel,
struct addr_location *al);
int db_export__branch_types(struct db_export *dbe);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 3780fe42453b..a1b59bd35519 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* For general debugging purposes */
-#include "../perf.h"
-
#include <inttypes.h>
#include <string.h>
#include <stdarg.h>
@@ -10,17 +8,19 @@
#include <stdlib.h>
#include <sys/wait.h>
#include <api/debug.h>
+#include <linux/kernel.h>
#include <linux/time64.h>
#ifdef HAVE_BACKTRACE_SUPPORT
#include <execinfo.h>
#endif
-#include "cache.h"
#include "color.h"
#include "event.h"
#include "debug.h"
#include "print_binary.h"
#include "util.h"
#include "target.h"
+#include "ui/helpline.h"
+#include "ui/ui.h"
#include <linux/ctype.h>
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 77445dfc5c7d..b2deee987ffa 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -4,11 +4,7 @@
#define __PERF_DEBUG_H
#include <stdbool.h>
-#include <string.h>
#include <linux/compiler.h>
-#include "event.h"
-#include "../ui/helpline.h"
-#include "../ui/progress.h"
#include "../ui/util.h"
extern int verbose;
@@ -42,6 +38,8 @@ extern int debug_data_convert;
#define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */
+union perf_event;
+
int dump_printf(const char *fmt, ...) __printf(1, 2);
void trace_event(union perf_event *event);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index ebc9d46c15a7..e11ddf86f2b3 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -10,16 +10,18 @@
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
-#include <libgen.h>
+#include <stdlib.h>
#include <bpf/libbpf.h>
#include "bpf-event.h"
#include "compress.h"
+#include "env.h"
#include "namespaces.h"
#include "path.h"
#include "map.h"
#include "symbol.h"
#include "srcline.h"
#include "dso.h"
+#include "dsos.h"
#include "machine.h"
#include "auxtrace.h"
#include "util.h" /* O_CLOEXEC for older systems */
@@ -1094,66 +1096,6 @@ struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
return dso;
}
-/*
- * Find a matching entry and/or link current entry to RB tree.
- * Either one of the dso or name parameter must be non-NULL or the
- * function will not work.
- */
-static struct dso *__dso__findlink_by_longname(struct rb_root *root,
- struct dso *dso, const char *name)
-{
- struct rb_node **p = &root->rb_node;
- struct rb_node *parent = NULL;
-
- if (!name)
- name = dso->long_name;
- /*
- * Find node with the matching name
- */
- while (*p) {
- struct dso *this = rb_entry(*p, struct dso, rb_node);
- int rc = strcmp(name, this->long_name);
-
- parent = *p;
- if (rc == 0) {
- /*
- * In case the new DSO is a duplicate of an existing
- * one, print a one-time warning & put the new entry
- * at the end of the list of duplicates.
- */
- if (!dso || (dso == this))
- return this; /* Find matching dso */
- /*
- * The core kernel DSOs may have duplicated long name.
- * In this case, the short name should be different.
- * Comparing the short names to differentiate the DSOs.
- */
- rc = strcmp(dso->short_name, this->short_name);
- if (rc == 0) {
- pr_err("Duplicated dso name: %s\n", name);
- return NULL;
- }
- }
- if (rc < 0)
- p = &parent->rb_left;
- else
- p = &parent->rb_right;
- }
- if (dso) {
- /* Add new node and rebalance tree */
- rb_link_node(&dso->rb_node, parent, p);
- rb_insert_color(&dso->rb_node, root);
- dso->root = root;
- }
- return NULL;
-}
-
-static inline struct dso *__dso__find_by_longname(struct rb_root *root,
- const char *name)
-{
- return __dso__findlink_by_longname(root, NULL, name);
-}
-
void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
{
struct rb_root *root = dso->root;
@@ -1167,7 +1109,7 @@ void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
if (root) {
rb_erase(&dso->rb_node, root);
/*
- * __dso__findlink_by_longname() isn't guaranteed to add it
+ * __dsos__findnew_link_by_longname() isn't guaranteed to add it
* back, so a clean removal is required here.
*/
RB_CLEAR_NODE(&dso->rb_node);
@@ -1179,7 +1121,7 @@ void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
dso->long_name_allocated = name_allocated;
if (root)
- __dso__findlink_by_longname(root, dso, NULL);
+ __dsos__findnew_link_by_longname(root, dso, NULL);
}
void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
@@ -1195,38 +1137,6 @@ void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
dso->short_name_allocated = name_allocated;
}
-static void dso__set_basename(struct dso *dso)
-{
- char *base, *lname;
- int tid;
-
- if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) {
- if (asprintf(&base, "[JIT] tid %d", tid) < 0)
- return;
- } else {
- /*
- * basename() may modify path buffer, so we must pass
- * a copy.
- */
- lname = strdup(dso->long_name);
- if (!lname)
- return;
-
- /*
- * basename() may return a pointer to internal
- * storage which is reused in subsequent calls
- * so copy the result.
- */
- base = strdup(basename(lname));
-
- free(lname);
-
- if (!base)
- return;
- }
- dso__set_short_name(dso, base, true);
-}
-
int dso__name_len(const struct dso *dso)
{
if (!dso)
@@ -1377,143 +1287,6 @@ int dso__kernel_module_get_build_id(struct dso *dso,
return 0;
}
-bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
-{
- bool have_build_id = false;
- struct dso *pos;
- struct nscookie nsc;
-
- list_for_each_entry(pos, head, node) {
- if (with_hits && !pos->hit && !dso__is_vdso(pos))
- continue;
- if (pos->has_build_id) {
- have_build_id = true;
- continue;
- }
- nsinfo__mountns_enter(pos->nsinfo, &nsc);
- if (filename__read_build_id(pos->long_name, pos->build_id,
- sizeof(pos->build_id)) > 0) {
- have_build_id = true;
- pos->has_build_id = true;
- }
- nsinfo__mountns_exit(&nsc);
- }
-
- return have_build_id;
-}
-
-void __dsos__add(struct dsos *dsos, struct dso *dso)
-{
- list_add_tail(&dso->node, &dsos->head);
- __dso__findlink_by_longname(&dsos->root, dso, NULL);
- /*
- * It is now in the linked list, grab a reference, then garbage collect
- * this when needing memory, by looking at LRU dso instances in the
- * list with atomic_read(&dso->refcnt) == 1, i.e. no references
- * anywhere besides the one for the list, do, under a lock for the
- * list: remove it from the list, then a dso__put(), that probably will
- * be the last and will then call dso__delete(), end of life.
- *
- * That, or at the end of the 'struct machine' lifetime, when all
- * 'struct dso' instances will be removed from the list, in
- * dsos__exit(), if they have no other reference from some other data
- * structure.
- *
- * E.g.: after processing a 'perf.data' file and storing references
- * to objects instantiated while processing events, we will have
- * references to the 'thread', 'map', 'dso' structs all from 'struct
- * hist_entry' instances, but we may not need anything not referenced,
- * so we might as well call machines__exit()/machines__delete() and
- * garbage collect it.
- */
- dso__get(dso);
-}
-
-void dsos__add(struct dsos *dsos, struct dso *dso)
-{
- down_write(&dsos->lock);
- __dsos__add(dsos, dso);
- up_write(&dsos->lock);
-}
-
-struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
-{
- struct dso *pos;
-
- if (cmp_short) {
- list_for_each_entry(pos, &dsos->head, node)
- if (strcmp(pos->short_name, name) == 0)
- return pos;
- return NULL;
- }
- return __dso__find_by_longname(&dsos->root, name);
-}
-
-struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
-{
- struct dso *dso;
- down_read(&dsos->lock);
- dso = __dsos__find(dsos, name, cmp_short);
- up_read(&dsos->lock);
- return dso;
-}
-
-struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
-{
- struct dso *dso = dso__new(name);
-
- if (dso != NULL) {
- __dsos__add(dsos, dso);
- dso__set_basename(dso);
- /* Put dso here because __dsos_add already got it */
- dso__put(dso);
- }
- return dso;
-}
-
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
-{
- struct dso *dso = __dsos__find(dsos, name, false);
-
- return dso ? dso : __dsos__addnew(dsos, name);
-}
-
-struct dso *dsos__findnew(struct dsos *dsos, const char *name)
-{
- struct dso *dso;
- down_write(&dsos->lock);
- dso = dso__get(__dsos__findnew(dsos, name));
- up_write(&dsos->lock);
- return dso;
-}
-
-size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
- bool (skip)(struct dso *dso, int parm), int parm)
-{
- struct dso *pos;
- size_t ret = 0;
-
- list_for_each_entry(pos, head, node) {
- if (skip && skip(pos, parm))
- continue;
- ret += dso__fprintf_buildid(pos, fp);
- ret += fprintf(fp, " %s\n", pos->long_name);
- }
- return ret;
-}
-
-size_t __dsos__fprintf(struct list_head *head, FILE *fp)
-{
- struct dso *pos;
- size_t ret = 0;
-
- list_for_each_entry(pos, head, node) {
- ret += dso__fprintf(pos, fp);
- }
-
- return ret;
-}
-
size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
{
char sbuild_id[SBUILD_ID_SIZE];
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 6e3f63781e51..e4dddb76770d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -2,13 +2,13 @@
#ifndef __PERF_DSO
#define __PERF_DSO
+#include <pthread.h>
#include <linux/refcount.h>
#include <linux/types.h>
#include <linux/rbtree.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
-#include "rwsem.h"
#include <linux/bitops.h>
#include "build-id.h"
@@ -16,6 +16,9 @@ struct machine;
struct map;
struct perf_env;
+#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"
+#define DSO__NAME_KCORE "[kernel.kcore]"
+
enum dso_binary_type {
DSO_BINARY_TYPE__KALLSYMS = 0,
DSO_BINARY_TYPE__GUEST_KALLSYMS,
@@ -126,16 +129,6 @@ struct dso_cache {
char data[0];
};
-/*
- * DSOs are put into both a list for fast iteration and rbtree for fast
- * long name lookup.
- */
-struct dsos {
- struct list_head head;
- struct rb_root root; /* rbtree root sorted by long name */
- struct rw_semaphore lock;
-};
-
struct auxtrace_cache;
struct dso {
@@ -344,21 +337,8 @@ struct map *dso__new_map(const char *name);
struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
const char *short_name, int dso_type);
-void __dsos__add(struct dsos *dsos, struct dso *dso);
-void dsos__add(struct dsos *dsos, struct dso *dso);
-struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
-struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
-struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
-struct dso *dsos__findnew(struct dsos *dsos, const char *name);
-bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
-
void dso__reset_find_symbol_cache(struct dso *dso);
-size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
- bool (skip)(struct dso *dso, int parm), int parm);
-size_t __dsos__fprintf(struct list_head *head, FILE *fp);
-
size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp);
size_t dso__fprintf(struct dso *dso, FILE *fp);
diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
new file mode 100644
index 000000000000..3ea80d203587
--- /dev/null
+++ b/tools/perf/util/dsos.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
+#include "dsos.h"
+#include "dso.h"
+#include "vdso.h"
+#include "namespaces.h"
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <symbol.h> // filename__read_build_id
+
+bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
+{
+ bool have_build_id = false;
+ struct dso *pos;
+ struct nscookie nsc;
+
+ list_for_each_entry(pos, head, node) {
+ if (with_hits && !pos->hit && !dso__is_vdso(pos))
+ continue;
+ if (pos->has_build_id) {
+ have_build_id = true;
+ continue;
+ }
+ nsinfo__mountns_enter(pos->nsinfo, &nsc);
+ if (filename__read_build_id(pos->long_name, pos->build_id,
+ sizeof(pos->build_id)) > 0) {
+ have_build_id = true;
+ pos->has_build_id = true;
+ }
+ nsinfo__mountns_exit(&nsc);
+ }
+
+ return have_build_id;
+}
+
+/*
+ * Find a matching entry and/or link current entry to RB tree.
+ * Either one of the dso or name parameter must be non-NULL or the
+ * function will not work.
+ */
+struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+
+ if (!name)
+ name = dso->long_name;
+ /*
+ * Find node with the matching name
+ */
+ while (*p) {
+ struct dso *this = rb_entry(*p, struct dso, rb_node);
+ int rc = strcmp(name, this->long_name);
+
+ parent = *p;
+ if (rc == 0) {
+ /*
+ * In case the new DSO is a duplicate of an existing
+ * one, print a one-time warning & put the new entry
+ * at the end of the list of duplicates.
+ */
+ if (!dso || (dso == this))
+ return this; /* Find matching dso */
+ /*
+ * The core kernel DSOs may have duplicated long name.
+ * In this case, the short name should be different.
+ * Comparing the short names to differentiate the DSOs.
+ */
+ rc = strcmp(dso->short_name, this->short_name);
+ if (rc == 0) {
+ pr_err("Duplicated dso name: %s\n", name);
+ return NULL;
+ }
+ }
+ if (rc < 0)
+ p = &parent->rb_left;
+ else
+ p = &parent->rb_right;
+ }
+ if (dso) {
+ /* Add new node and rebalance tree */
+ rb_link_node(&dso->rb_node, parent, p);
+ rb_insert_color(&dso->rb_node, root);
+ dso->root = root;
+ }
+ return NULL;
+}
+
+void __dsos__add(struct dsos *dsos, struct dso *dso)
+{
+ list_add_tail(&dso->node, &dsos->head);
+ __dsos__findnew_link_by_longname(&dsos->root, dso, NULL);
+ /*
+ * It is now in the linked list, grab a reference, then garbage collect
+ * this when needing memory, by looking at LRU dso instances in the
+ * list with atomic_read(&dso->refcnt) == 1, i.e. no references
+ * anywhere besides the one for the list, do, under a lock for the
+ * list: remove it from the list, then a dso__put(), that probably will
+ * be the last and will then call dso__delete(), end of life.
+ *
+ * That, or at the end of the 'struct machine' lifetime, when all
+ * 'struct dso' instances will be removed from the list, in
+ * dsos__exit(), if they have no other reference from some other data
+ * structure.
+ *
+ * E.g.: after processing a 'perf.data' file and storing references
+ * to objects instantiated while processing events, we will have
+ * references to the 'thread', 'map', 'dso' structs all from 'struct
+ * hist_entry' instances, but we may not need anything not referenced,
+ * so we might as well call machines__exit()/machines__delete() and
+ * garbage collect it.
+ */
+ dso__get(dso);
+}
+
+void dsos__add(struct dsos *dsos, struct dso *dso)
+{
+ down_write(&dsos->lock);
+ __dsos__add(dsos, dso);
+ up_write(&dsos->lock);
+}
+
+struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
+{
+ struct dso *pos;
+
+ if (cmp_short) {
+ list_for_each_entry(pos, &dsos->head, node)
+ if (strcmp(pos->short_name, name) == 0)
+ return pos;
+ return NULL;
+ }
+ return __dsos__findnew_by_longname(&dsos->root, name);
+}
+
+struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
+{
+ struct dso *dso;
+ down_read(&dsos->lock);
+ dso = __dsos__find(dsos, name, cmp_short);
+ up_read(&dsos->lock);
+ return dso;
+}
+
+static void dso__set_basename(struct dso *dso)
+{
+ char *base, *lname;
+ int tid;
+
+ if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) {
+ if (asprintf(&base, "[JIT] tid %d", tid) < 0)
+ return;
+ } else {
+ /*
+ * basename() may modify path buffer, so we must pass
+ * a copy.
+ */
+ lname = strdup(dso->long_name);
+ if (!lname)
+ return;
+
+ /*
+ * basename() may return a pointer to internal
+ * storage which is reused in subsequent calls
+ * so copy the result.
+ */
+ base = strdup(basename(lname));
+
+ free(lname);
+
+ if (!base)
+ return;
+ }
+ dso__set_short_name(dso, base, true);
+}
+
+struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
+{
+ struct dso *dso = dso__new(name);
+
+ if (dso != NULL) {
+ __dsos__add(dsos, dso);
+ dso__set_basename(dso);
+ /* Put dso here because __dsos_add already got it */
+ dso__put(dso);
+ }
+ return dso;
+}
+
+struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
+{
+ struct dso *dso = __dsos__find(dsos, name, false);
+
+ return dso ? dso : __dsos__addnew(dsos, name);
+}
+
+struct dso *dsos__findnew(struct dsos *dsos, const char *name)
+{
+ struct dso *dso;
+ down_write(&dsos->lock);
+ dso = dso__get(__dsos__findnew(dsos, name));
+ up_write(&dsos->lock);
+ return dso;
+}
+
+size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm)
+{
+ struct dso *pos;
+ size_t ret = 0;
+
+ list_for_each_entry(pos, head, node) {
+ if (skip && skip(pos, parm))
+ continue;
+ ret += dso__fprintf_buildid(pos, fp);
+ ret += fprintf(fp, " %s\n", pos->long_name);
+ }
+ return ret;
+}
+
+size_t __dsos__fprintf(struct list_head *head, FILE *fp)
+{
+ struct dso *pos;
+ size_t ret = 0;
+
+ list_for_each_entry(pos, head, node) {
+ ret += dso__fprintf(pos, fp);
+ }
+
+ return ret;
+}
diff --git a/tools/perf/util/dsos.h b/tools/perf/util/dsos.h
new file mode 100644
index 000000000000..32f1fbee0feb
--- /dev/null
+++ b/tools/perf/util/dsos.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_DSOS
+#define __PERF_DSOS
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include "rwsem.h"
+
+struct dso;
+
+/*
+ * DSOs are put into both a list for fast iteration and rbtree for fast
+ * long name lookup.
+ */
+struct dsos {
+ struct list_head head;
+ struct rb_root root; /* rbtree root sorted by long name */
+ struct rw_semaphore lock;
+};
+
+void __dsos__add(struct dsos *dsos, struct dso *dso);
+void dsos__add(struct dsos *dsos, struct dso *dso);
+struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
+struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
+struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
+struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
+struct dso *dsos__findnew(struct dsos *dsos, const char *name);
+
+struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name);
+
+static inline struct dso *__dsos__findnew_by_longname(struct rb_root *root, const char *name)
+{
+ return __dsos__findnew_link_by_longname(root, NULL, name);
+}
+
+bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
+
+size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm);
+size_t __dsos__fprintf(struct list_head *head, FILE *fp);
+
+#endif /* __PERF_DSOS */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 03b2de1f5a35..df6cee5c071f 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include "debug.h"
#include "dwarf-aux.h"
+#include "strbuf.h"
#include "string2.h"
/**
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 0489b0cf8e2c..f204e5892403 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -10,6 +10,8 @@
#include <elfutils/libdwfl.h>
#include <elfutils/version.h>
+struct strbuf;
+
/* Find the realpath of the target file */
const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 9909ec40c6d2..3baca06786fb 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "cpumap.h"
+#include "debug.h"
#include "env.h"
#include <linux/ctype.h>
#include <linux/zalloc.h>
@@ -8,6 +9,7 @@
#include <sys/utsname.h>
#include <bpf/libbpf.h>
#include <stdlib.h>
+#include <string.h>
struct perf_env perf_env;
@@ -179,7 +181,7 @@ void perf_env__exit(struct perf_env *env)
zfree(&env->cpu);
for (i = 0; i < env->nr_numa_nodes; i++)
- cpu_map__put(env->numa_nodes[i].map);
+ perf_cpu_map__put(env->numa_nodes[i].map);
zfree(&env->numa_nodes);
for (i = 0; i < env->caches_cnt; i++)
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index d5d9865aa812..d8e083d42610 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -27,7 +27,7 @@ struct numa_node {
u32 node;
u64 mem_total;
u64 mem_free;
- struct cpu_map *map;
+ struct perf_cpu_map *map;
};
struct memory_node {
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index f1f4848947ce..f4afbb858ebb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -12,6 +11,7 @@
#include <api/fs/fs.h>
#include <linux/perf_event.h>
#include <linux/zalloc.h>
+#include "dso.h"
#include "event.h"
#include "debug.h"
#include "hist.h"
@@ -21,6 +21,7 @@
#include "strlist.h"
#include "thread.h"
#include "thread_map.h"
+#include "time-utils.h"
#include <linux/ctype.h>
#include "map.h"
#include "symbol.h"
@@ -29,6 +30,8 @@
#include "stat.h"
#include "session.h"
#include "bpf-event.h"
+#include "tool.h"
+#include "../perf.h"
#define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500
@@ -387,7 +390,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
strcpy(execname, "");
/* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
- n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %[^\n]\n",
+ n = sscanf(bf, "%"PRI_lx64"-%"PRI_lx64" %s %"PRI_lx64" %x:%x %u %[^\n]\n",
&event->mmap2.start, &event->mmap2.len, prot,
&event->mmap2.pgoff, &event->mmap2.maj,
&event->mmap2.min,
@@ -616,7 +619,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
}
int perf_event__synthesize_thread_map(struct perf_tool *tool,
- struct thread_map *threads,
+ struct perf_thread_map *threads,
perf_event__handler_t process,
struct machine *machine,
bool mmap_data)
@@ -647,7 +650,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
for (thread = 0; thread < threads->nr; ++thread) {
if (__event__synthesize_thread(comm_event, mmap_event,
fork_event, namespaces_event,
- thread_map__pid(threads, thread), 0,
+ perf_thread_map__pid(threads, thread), 0,
process, tool, machine,
mmap_data)) {
err = -1;
@@ -658,12 +661,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
* comm.pid is set to thread group id by
* perf_event__synthesize_comm
*/
- if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) {
+ if ((int) comm_event->comm.pid != perf_thread_map__pid(threads, thread)) {
bool need_leader = true;
/* is thread group leader in thread_map? */
for (j = 0; j < threads->nr; ++j) {
- if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) {
+ if ((int) comm_event->comm.pid == perf_thread_map__pid(threads, j)) {
need_leader = false;
break;
}
@@ -913,11 +916,13 @@ static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
int err;
union perf_event *event;
- if (symbol_conf.kptr_restrict)
- return -1;
if (map == NULL)
return -1;
+ kmap = map__kmap(map);
+ if (!kmap->ref_reloc_sym)
+ return -1;
+
/*
* We should get this from /sys/kernel/sections/.text, but till that is
* available use this, and after it is use this as a fallback for older
@@ -940,7 +945,6 @@ static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
}
- kmap = map__kmap(map);
size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
"%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
size = PERF_ALIGN(size, sizeof(u64));
@@ -972,7 +976,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
}
int perf_event__synthesize_thread_map2(struct perf_tool *tool,
- struct thread_map *threads,
+ struct perf_thread_map *threads,
perf_event__handler_t process,
struct machine *machine)
{
@@ -991,13 +995,13 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
event->thread_map.nr = threads->nr;
for (i = 0; i < threads->nr; i++) {
- struct thread_map_event_entry *entry = &event->thread_map.entries[i];
- char *comm = thread_map__comm(threads, i);
+ struct perf_record_thread_map_entry *entry = &event->thread_map.entries[i];
+ char *comm = perf_thread_map__comm(threads, i);
if (!comm)
comm = (char *) "";
- entry->pid = thread_map__pid(threads, i);
+ entry->pid = perf_thread_map__pid(threads, i);
strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
}
@@ -1008,7 +1012,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
}
static void synthesize_cpus(struct cpu_map_entries *cpus,
- struct cpu_map *map)
+ struct perf_cpu_map *map)
{
int i;
@@ -1018,8 +1022,8 @@ static void synthesize_cpus(struct cpu_map_entries *cpus,
cpus->cpu[i] = map->map[i];
}
-static void synthesize_mask(struct cpu_map_mask *mask,
- struct cpu_map *map, int max)
+static void synthesize_mask(struct perf_record_record_cpu_map *mask,
+ struct perf_cpu_map *map, int max)
{
int i;
@@ -1030,12 +1034,12 @@ static void synthesize_mask(struct cpu_map_mask *mask,
set_bit(map->map[i], mask->mask);
}
-static size_t cpus_size(struct cpu_map *map)
+static size_t cpus_size(struct perf_cpu_map *map)
{
return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
}
-static size_t mask_size(struct cpu_map *map, int *max)
+static size_t mask_size(struct perf_cpu_map *map, int *max)
{
int i;
@@ -1049,26 +1053,26 @@ static size_t mask_size(struct cpu_map *map, int *max)
*max = bit;
}
- return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long);
+ return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long);
}
-void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max)
+void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max)
{
size_t size_cpus, size_mask;
- bool is_dummy = cpu_map__empty(map);
+ bool is_dummy = perf_cpu_map__empty(map);
/*
* Both array and mask data have variable size based
* on the number of cpus and their actual values.
- * The size of the 'struct cpu_map_data' is:
+ * The size of the 'struct perf_record_cpu_map_data' is:
*
* array = size of 'struct cpu_map_entries' +
* number of cpus * sizeof(u64)
*
- * mask = size of 'struct cpu_map_mask' +
+ * mask = size of 'struct perf_record_record_cpu_map' +
* maximum cpu bit converted to size of longs
*
- * and finaly + the size of 'struct cpu_map_data'.
+ * and finaly + the size of 'struct perf_record_cpu_map_data'.
*/
size_cpus = cpus_size(map);
size_mask = mask_size(map, max);
@@ -1081,12 +1085,12 @@ void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max
*type = PERF_CPU_MAP__MASK;
}
- *size += sizeof(struct cpu_map_data);
+ *size += sizeof(struct perf_record_cpu_map_data);
*size = PERF_ALIGN(*size, sizeof(u64));
return zalloc(*size);
}
-void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
+void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
u16 type, int max)
{
data->type = type;
@@ -1096,16 +1100,16 @@ void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
synthesize_cpus((struct cpu_map_entries *) data->data, map);
break;
case PERF_CPU_MAP__MASK:
- synthesize_mask((struct cpu_map_mask *) data->data, map, max);
+ synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, max);
default:
break;
};
}
-static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
+static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map)
{
- size_t size = sizeof(struct cpu_map_event);
- struct cpu_map_event *event;
+ size_t size = sizeof(struct perf_record_cpu_map);
+ struct perf_record_cpu_map *event;
int max;
u16 type;
@@ -1122,11 +1126,11 @@ static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
}
int perf_event__synthesize_cpu_map(struct perf_tool *tool,
- struct cpu_map *map,
+ struct perf_cpu_map *map,
perf_event__handler_t process,
struct machine *machine)
{
- struct cpu_map_event *event;
+ struct perf_record_cpu_map *event;
int err;
event = cpu_map_event__new(map);
@@ -1144,7 +1148,7 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine)
{
- struct stat_config_event *event;
+ struct perf_record_stat_config *event;
int size, i = 0, err;
size = sizeof(*event);
@@ -1183,7 +1187,7 @@ int perf_event__synthesize_stat(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine)
{
- struct stat_event event;
+ struct perf_record_stat event;
event.header.type = PERF_RECORD_STAT;
event.header.size = sizeof(event);
@@ -1204,7 +1208,7 @@ int perf_event__synthesize_stat_round(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine)
{
- struct stat_round_event event;
+ struct perf_record_stat_round event;
event.header.type = PERF_RECORD_STAT_ROUND;
event.header.size = sizeof(event);
@@ -1217,7 +1221,7 @@ int perf_event__synthesize_stat_round(struct perf_tool *tool,
}
void perf_event__read_stat_config(struct perf_stat_config *config,
- struct stat_config_event *event)
+ struct perf_record_stat_config *event)
{
unsigned i;
@@ -1234,7 +1238,7 @@ void perf_event__read_stat_config(struct perf_stat_config *config,
CASE(INTERVAL, interval)
#undef CASE
default:
- pr_warning("unknown stat config term %" PRIu64 "\n",
+ pr_warning("unknown stat config term %" PRI_lu64 "\n",
event->data[i].tag);
}
}
@@ -1343,17 +1347,17 @@ int perf_event__process_ksymbol(struct perf_tool *tool __maybe_unused,
return machine__process_ksymbol(machine, event, sample);
}
-int perf_event__process_bpf_event(struct perf_tool *tool __maybe_unused,
- union perf_event *event,
- struct perf_sample *sample __maybe_unused,
- struct machine *machine)
+int perf_event__process_bpf(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
{
- return machine__process_bpf_event(machine, event, sample);
+ return machine__process_bpf(machine, event, sample);
}
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{
- return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
+ return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64 "]: %c %s\n",
event->mmap.pid, event->mmap.tid, event->mmap.start,
event->mmap.len, event->mmap.pgoff,
(event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
@@ -1362,8 +1366,8 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
{
- return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
- " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
+ return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
+ " %02x:%02x %"PRI_lu64" %"PRI_lu64"]: %c%c%c%c %s\n",
event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
event->mmap2.min, event->mmap2.ino,
@@ -1377,7 +1381,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
{
- struct thread_map *threads = thread_map__new_event(&event->thread_map);
+ struct perf_thread_map *threads = thread_map__new_event(&event->thread_map);
size_t ret;
ret = fprintf(fp, " nr: ");
@@ -1387,13 +1391,13 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
else
ret += fprintf(fp, "failed to get threads from event\n");
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return ret;
}
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
{
- struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
+ struct perf_cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
size_t ret;
ret = fprintf(fp, ": ");
@@ -1403,7 +1407,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
else
ret += fprintf(fp, "failed to get cpumap from event\n");
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
return ret;
}
@@ -1448,7 +1452,7 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
{
- return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s%s]\n",
+ return fprintf(fp, " offset: %#"PRI_lx64" size: %#"PRI_lx64" flags: %#"PRI_lx64" [%s%s%s]\n",
event->aux.aux_offset, event->aux.aux_size,
event->aux.flags,
event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
@@ -1480,22 +1484,21 @@ size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp)
{
- return fprintf(fp, " lost %" PRIu64 "\n", event->lost.lost);
+ return fprintf(fp, " lost %" PRI_lu64 "\n", event->lost.lost);
}
size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
{
- return fprintf(fp, " addr %" PRIx64 " len %u type %u flags 0x%x name %s\n",
- event->ksymbol_event.addr, event->ksymbol_event.len,
- event->ksymbol_event.ksym_type,
- event->ksymbol_event.flags, event->ksymbol_event.name);
+ return fprintf(fp, " addr %" PRI_lx64 " len %u type %u flags 0x%x name %s\n",
+ event->ksymbol.addr, event->ksymbol.len,
+ event->ksymbol.ksym_type,
+ event->ksymbol.flags, event->ksymbol.name);
}
-size_t perf_event__fprintf_bpf_event(union perf_event *event, FILE *fp)
+size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp)
{
return fprintf(fp, " type %u, flags %u, id %u\n",
- event->bpf_event.type, event->bpf_event.flags,
- event->bpf_event.id);
+ event->bpf.type, event->bpf.flags, event->bpf.id);
}
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -1537,7 +1540,7 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
ret += perf_event__fprintf_ksymbol(event, fp);
break;
case PERF_RECORD_BPF_EVENT:
- ret += perf_event__fprintf_bpf_event(event, fp);
+ ret += perf_event__fprintf_bpf(event, fp);
break;
default:
ret += fprintf(fp, "\n");
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1f1da6082806..47ad81d47b1a 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,114 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PERF_RECORD_H
#define __PERF_RECORD_H
-
-#include <limits.h>
+/*
+ * The linux/stddef.h isn't need here, but is needed for __always_inline used
+ * in files included from uapi/linux/perf_event.h such as
+ * /usr/include/linux/swab.h and /usr/include/linux/byteorder/little_endian.h,
+ * detected in at least musl libc, used in Alpine Linux. -acme
+ */
#include <stdio.h>
-#include <linux/kernel.h>
-#include <linux/bpf.h>
-#include <linux/perf_event.h>
+#include <linux/stddef.h>
+#include <perf/event.h>
+#include <linux/types.h>
-#include "../perf.h"
-#include "build-id.h"
#include "perf_regs.h"
-struct mmap_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
- u64 pgoff;
- char filename[PATH_MAX];
-};
-
-struct mmap2_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
- u64 pgoff;
- u32 maj;
- u32 min;
- u64 ino;
- u64 ino_generation;
- u32 prot;
- u32 flags;
- char filename[PATH_MAX];
-};
-
-struct comm_event {
- struct perf_event_header header;
- u32 pid, tid;
- char comm[16];
-};
-
-struct namespaces_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 nr_namespaces;
- struct perf_ns_link_info link_info[];
-};
-
-struct fork_event {
- struct perf_event_header header;
- u32 pid, ppid;
- u32 tid, ptid;
- u64 time;
-};
-
-struct lost_event {
- struct perf_event_header header;
- u64 id;
- u64 lost;
-};
-
-struct lost_samples_event {
- struct perf_event_header header;
- u64 lost;
-};
+struct dso;
+struct machine;
+struct perf_event_attr;
+#ifdef __LP64__
/*
- * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
+ * /usr/include/inttypes.h uses just 'lu' for PRIu64, but we end up defining
+ * __u64 as long long unsigned int, and then -Werror=format= kicks in and
+ * complains of the mismatched types, so use these two special extra PRI
+ * macros to overcome that.
*/
-struct read_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 value;
- u64 time_enabled;
- u64 time_running;
- u64 id;
-};
-
-struct throttle_event {
- struct perf_event_header header;
- u64 time;
- u64 id;
- u64 stream_id;
-};
-
-#ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 256
+#define PRI_lu64 "l" PRIu64
+#define PRI_lx64 "l" PRIx64
+#define PRI_ld64 "l" PRId64
+#else
+#define PRI_lu64 PRIu64
+#define PRI_lx64 PRIx64
+#define PRI_ld64 PRId64
#endif
-struct ksymbol_event {
- struct perf_event_header header;
- u64 addr;
- u32 len;
- u16 ksym_type;
- u16 flags;
- char name[KSYM_NAME_LEN];
-};
-
-struct bpf_event {
- struct perf_event_header header;
- u16 type;
- u16 flags;
- u32 id;
-
- /* for bpf_prog types */
- u8 tag[BPF_TAG_SIZE]; // prog tag
-};
-
#define PERF_SAMPLE_MASK \
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
@@ -119,11 +44,6 @@ struct bpf_event {
/* perf sample has 16 bits size limit */
#define PERF_SAMPLE_MAX_SIZE (1 << 16)
-struct sample_event {
- struct perf_event_header header;
- u64 array[];
-};
-
struct regs_dump {
u64 abi;
u64 mask;
@@ -231,41 +151,6 @@ struct perf_sample {
PERF_MEM_S(LOCK, NA) |\
PERF_MEM_S(TLB, NA))
-struct build_id_event {
- struct perf_event_header header;
- pid_t pid;
- u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
- char filename[];
-};
-
-enum perf_user_event_type { /* above any possible kernel type */
- PERF_RECORD_USER_TYPE_START = 64,
- PERF_RECORD_HEADER_ATTR = 64,
- PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
- PERF_RECORD_HEADER_TRACING_DATA = 66,
- PERF_RECORD_HEADER_BUILD_ID = 67,
- PERF_RECORD_FINISHED_ROUND = 68,
- PERF_RECORD_ID_INDEX = 69,
- PERF_RECORD_AUXTRACE_INFO = 70,
- PERF_RECORD_AUXTRACE = 71,
- PERF_RECORD_AUXTRACE_ERROR = 72,
- PERF_RECORD_THREAD_MAP = 73,
- PERF_RECORD_CPU_MAP = 74,
- PERF_RECORD_STAT_CONFIG = 75,
- PERF_RECORD_STAT = 76,
- PERF_RECORD_STAT_ROUND = 77,
- PERF_RECORD_EVENT_UPDATE = 78,
- PERF_RECORD_TIME_CONV = 79,
- PERF_RECORD_HEADER_FEATURE = 80,
- PERF_RECORD_COMPRESSED = 81,
- PERF_RECORD_HEADER_MAX
-};
-
-enum auxtrace_error_type {
- PERF_AUXTRACE_ERROR_ITRACE = 1,
- PERF_AUXTRACE_ERROR_MAX
-};
-
/* Attribute type for custom synthesized events */
#define PERF_TYPE_SYNTH (INT_MAX + 1U)
@@ -387,295 +272,16 @@ static inline void *perf_synth__raw_data(void *p)
#define perf_sample__bad_synth_size(s, d) ((s)->raw_size < sizeof(d) - 4)
-/*
- * The kernel collects the number of events it couldn't send in a stretch and
- * when possible sends this number in a PERF_RECORD_LOST event. The number of
- * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
- * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
- * the sum of all struct lost_event.lost fields reported.
- *
- * The kernel discards mixed up samples and sends the number in a
- * PERF_RECORD_LOST_SAMPLES event. The number of lost-samples events is stored
- * in .nr_events[PERF_RECORD_LOST_SAMPLES] while total_lost_samples tells
- * exactly how many samples the kernel in fact dropped, i.e. it is the sum of
- * all struct lost_samples_event.lost fields reported.
- *
- * The total_period is needed because by default auto-freq is used, so
- * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
- * the total number of low level events, it is necessary to to sum all struct
- * sample_event.period and stash the result in total_period.
- */
-struct events_stats {
- u64 total_period;
- u64 total_non_filtered_period;
- u64 total_lost;
- u64 total_lost_samples;
- u64 total_aux_lost;
- u64 total_aux_partial;
- u64 total_invalid_chains;
- u32 nr_events[PERF_RECORD_HEADER_MAX];
- u32 nr_non_filtered_samples;
- u32 nr_lost_warned;
- u32 nr_unknown_events;
- u32 nr_invalid_chains;
- u32 nr_unknown_id;
- u32 nr_unprocessable_samples;
- u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
- u32 nr_proc_map_timeout;
-};
-
-enum {
- PERF_CPU_MAP__CPUS = 0,
- PERF_CPU_MAP__MASK = 1,
-};
-
-struct cpu_map_entries {
- u16 nr;
- u16 cpu[];
-};
-
-struct cpu_map_mask {
- u16 nr;
- u16 long_size;
- unsigned long mask[];
-};
-
-struct cpu_map_data {
- u16 type;
- char data[];
-};
-
-struct cpu_map_event {
- struct perf_event_header header;
- struct cpu_map_data data;
-};
-
-struct attr_event {
- struct perf_event_header header;
- struct perf_event_attr attr;
- u64 id[];
-};
-
-enum {
- PERF_EVENT_UPDATE__UNIT = 0,
- PERF_EVENT_UPDATE__SCALE = 1,
- PERF_EVENT_UPDATE__NAME = 2,
- PERF_EVENT_UPDATE__CPUS = 3,
-};
-
-struct event_update_event_cpus {
- struct cpu_map_data cpus;
-};
-
-struct event_update_event_scale {
- double scale;
-};
-
-struct event_update_event {
- struct perf_event_header header;
- u64 type;
- u64 id;
-
- char data[];
-};
-
-#define MAX_EVENT_NAME 64
-
-struct perf_trace_event_type {
- u64 event_id;
- char name[MAX_EVENT_NAME];
-};
-
-struct event_type_event {
- struct perf_event_header header;
- struct perf_trace_event_type event_type;
-};
-
-struct tracing_data_event {
- struct perf_event_header header;
- u32 size;
-};
-
-struct id_index_entry {
- u64 id;
- u64 idx;
- u64 cpu;
- u64 tid;
-};
-
-struct id_index_event {
- struct perf_event_header header;
- u64 nr;
- struct id_index_entry entries[0];
-};
-
-struct auxtrace_info_event {
- struct perf_event_header header;
- u32 type;
- u32 reserved__; /* For alignment */
- u64 priv[];
-};
-
-struct auxtrace_event {
- struct perf_event_header header;
- u64 size;
- u64 offset;
- u64 reference;
- u32 idx;
- u32 tid;
- u32 cpu;
- u32 reserved__; /* For alignment */
-};
-
-#define MAX_AUXTRACE_ERROR_MSG 64
-
-struct auxtrace_error_event {
- struct perf_event_header header;
- u32 type;
- u32 code;
- u32 cpu;
- u32 pid;
- u32 tid;
- u32 fmt;
- u64 ip;
- u64 time;
- char msg[MAX_AUXTRACE_ERROR_MSG];
-};
-
-struct aux_event {
- struct perf_event_header header;
- u64 aux_offset;
- u64 aux_size;
- u64 flags;
-};
-
-struct itrace_start_event {
- struct perf_event_header header;
- u32 pid, tid;
-};
-
-struct context_switch_event {
- struct perf_event_header header;
- u32 next_prev_pid;
- u32 next_prev_tid;
-};
-
-struct thread_map_event_entry {
- u64 pid;
- char comm[16];
-};
-
-struct thread_map_event {
- struct perf_event_header header;
- u64 nr;
- struct thread_map_event_entry entries[];
-};
-
-enum {
- PERF_STAT_CONFIG_TERM__AGGR_MODE = 0,
- PERF_STAT_CONFIG_TERM__INTERVAL = 1,
- PERF_STAT_CONFIG_TERM__SCALE = 2,
- PERF_STAT_CONFIG_TERM__MAX = 3,
-};
-
-struct stat_config_event_entry {
- u64 tag;
- u64 val;
-};
-
-struct stat_config_event {
- struct perf_event_header header;
- u64 nr;
- struct stat_config_event_entry data[];
-};
-
-struct stat_event {
- struct perf_event_header header;
-
- u64 id;
- u32 cpu;
- u32 thread;
-
- union {
- struct {
- u64 val;
- u64 ena;
- u64 run;
- };
- u64 values[3];
- };
-};
-
enum {
PERF_STAT_ROUND_TYPE__INTERVAL = 0,
PERF_STAT_ROUND_TYPE__FINAL = 1,
};
-struct stat_round_event {
- struct perf_event_header header;
- u64 type;
- u64 time;
-};
-
-struct time_conv_event {
- struct perf_event_header header;
- u64 time_shift;
- u64 time_mult;
- u64 time_zero;
-};
-
-struct feature_event {
- struct perf_event_header header;
- u64 feat_id;
- char data[];
-};
-
-struct compressed_event {
- struct perf_event_header header;
- char data[];
-};
-
-union perf_event {
- struct perf_event_header header;
- struct mmap_event mmap;
- struct mmap2_event mmap2;
- struct comm_event comm;
- struct namespaces_event namespaces;
- struct fork_event fork;
- struct lost_event lost;
- struct lost_samples_event lost_samples;
- struct read_event read;
- struct throttle_event throttle;
- struct sample_event sample;
- struct attr_event attr;
- struct event_update_event event_update;
- struct event_type_event event_type;
- struct tracing_data_event tracing_data;
- struct build_id_event build_id;
- struct id_index_event id_index;
- struct auxtrace_info_event auxtrace_info;
- struct auxtrace_event auxtrace;
- struct auxtrace_error_event auxtrace_error;
- struct aux_event aux;
- struct itrace_start_event itrace_start;
- struct context_switch_event context_switch;
- struct thread_map_event thread_map;
- struct cpu_map_event cpu_map;
- struct stat_config_event stat_config;
- struct stat_event stat;
- struct stat_round_event stat_round;
- struct time_conv_event time_conv;
- struct feature_event feat;
- struct ksymbol_event ksymbol_event;
- struct bpf_event bpf_event;
- struct compressed_event pack;
-};
-
void perf_event__print_totals(void);
struct perf_tool;
-struct thread_map;
-struct cpu_map;
+struct perf_thread_map;
+struct perf_cpu_map;
struct perf_stat_config;
struct perf_counts_values;
@@ -685,15 +291,15 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
struct machine *machine);
int perf_event__synthesize_thread_map(struct perf_tool *tool,
- struct thread_map *threads,
+ struct perf_thread_map *threads,
perf_event__handler_t process,
struct machine *machine, bool mmap_data);
int perf_event__synthesize_thread_map2(struct perf_tool *tool,
- struct thread_map *threads,
+ struct perf_thread_map *threads,
perf_event__handler_t process,
struct machine *machine);
int perf_event__synthesize_cpu_map(struct perf_tool *tool,
- struct cpu_map *cpus,
+ struct perf_cpu_map *cpus,
perf_event__handler_t process,
struct machine *machine);
int perf_event__synthesize_threads(struct perf_tool *tool,
@@ -708,7 +314,7 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
perf_event__handler_t process,
struct machine *machine);
void perf_event__read_stat_config(struct perf_stat_config *config,
- struct stat_config_event *event);
+ struct perf_record_stat_config *event);
int perf_event__synthesize_stat(struct perf_tool *tool,
u32 cpu, u32 thread, u64 id,
struct perf_counts_values *count,
@@ -770,10 +376,10 @@ int perf_event__process_ksymbol(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
-int perf_event__process_bpf_event(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
+int perf_event__process_bpf(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine);
int perf_tool__process_synth_event(struct perf_tool *tool,
union perf_event *event,
struct machine *machine,
@@ -838,19 +444,20 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp);
-size_t perf_event__fprintf_bpf_event(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
int kallsyms__get_function_start(const char *kallsyms_filename,
const char *symbol_name, u64 *addr);
-void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
-void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
+void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max);
+void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
u16 type, int max);
void event_attr_init(struct perf_event_attr *attr);
int perf_event_paranoid(void);
+bool perf_event_paranoid_check(int max_level);
extern int sysctl_perf_event_max_stack;
extern int sysctl_perf_event_max_contexts_per_stack;
diff --git a/tools/perf/util/events_stats.h b/tools/perf/util/events_stats.h
new file mode 100644
index 000000000000..859cb34fcff2
--- /dev/null
+++ b/tools/perf/util/events_stats.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_EVENTS_STATS_
+#define __PERF_EVENTS_STATS_
+
+#include <stdio.h>
+#include <perf/event.h>
+#include <linux/types.h>
+#include "auxtrace.h"
+
+/*
+ * The kernel collects the number of events it couldn't send in a stretch and
+ * when possible sends this number in a PERF_RECORD_LOST event. The number of
+ * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
+ * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
+ * the sum of all struct perf_record_lost.lost fields reported.
+ *
+ * The kernel discards mixed up samples and sends the number in a
+ * PERF_RECORD_LOST_SAMPLES event. The number of lost-samples events is stored
+ * in .nr_events[PERF_RECORD_LOST_SAMPLES] while total_lost_samples tells
+ * exactly how many samples the kernel in fact dropped, i.e. it is the sum of
+ * all struct perf_record_lost_samples.lost fields reported.
+ *
+ * The total_period is needed because by default auto-freq is used, so
+ * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
+ * the total number of low level events, it is necessary to to sum all struct
+ * perf_record_sample.period and stash the result in total_period.
+ */
+struct events_stats {
+ u64 total_period;
+ u64 total_non_filtered_period;
+ u64 total_lost;
+ u64 total_lost_samples;
+ u64 total_aux_lost;
+ u64 total_aux_partial;
+ u64 total_invalid_chains;
+ u32 nr_events[PERF_RECORD_HEADER_MAX];
+ u32 nr_non_filtered_samples;
+ u32 nr_lost_warned;
+ u32 nr_unknown_events;
+ u32 nr_invalid_chains;
+ u32 nr_unknown_id;
+ u32 nr_unprocessable_samples;
+ u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
+ u32 nr_proc_map_timeout;
+};
+
+void events_stats__inc(struct events_stats *stats, u32 type);
+
+size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
+
+#endif /* __PERF_EVENTS_STATS_ */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b0364d923f76..095924aa186b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -16,10 +16,14 @@
#include "evsel.h"
#include "debug.h"
#include "units.h"
+#include "util.h"
+#include "../perf.h"
#include "asm/bug.h"
#include "bpf-event.h"
#include <signal.h>
#include <unistd.h>
+#include <sched.h>
+#include <stdlib.h>
#include "parse-events.h"
#include <subcmd/parse-options.h>
@@ -32,57 +36,63 @@
#include <linux/hash.h>
#include <linux/log2.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
+#include <perf/evlist.h>
+#include <perf/evsel.h>
+#include <perf/cpumap.h>
+
+#include <internal/xyarray.h>
#ifdef LACKS_SIGQUEUE_PROTOTYPE
int sigqueue(pid_t pid, int sig, const union sigval value);
#endif
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
-void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads)
+void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
{
int i;
for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
INIT_HLIST_HEAD(&evlist->heads[i]);
- INIT_LIST_HEAD(&evlist->entries);
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__init(&evlist->core);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
fdarray__init(&evlist->pollfd, 64);
evlist->workload.pid = -1;
evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
}
-struct perf_evlist *perf_evlist__new(void)
+struct evlist *evlist__new(void)
{
- struct perf_evlist *evlist = zalloc(sizeof(*evlist));
+ struct evlist *evlist = zalloc(sizeof(*evlist));
if (evlist != NULL)
- perf_evlist__init(evlist, NULL, NULL);
+ evlist__init(evlist, NULL, NULL);
return evlist;
}
-struct perf_evlist *perf_evlist__new_default(void)
+struct evlist *perf_evlist__new_default(void)
{
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evlist *evlist = evlist__new();
if (evlist && perf_evlist__add_default(evlist)) {
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
evlist = NULL;
}
return evlist;
}
-struct perf_evlist *perf_evlist__new_dummy(void)
+struct evlist *perf_evlist__new_dummy(void)
{
- struct perf_evlist *evlist = perf_evlist__new();
+ struct evlist *evlist = evlist__new();
if (evlist && perf_evlist__add_dummy(evlist)) {
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
evlist = NULL;
}
@@ -96,17 +106,17 @@ struct perf_evlist *perf_evlist__new_dummy(void)
* Events with compatible sample types all have the same id_pos
* and is_pos. For convenience, put a copy on evlist.
*/
-void perf_evlist__set_id_pos(struct perf_evlist *evlist)
+void perf_evlist__set_id_pos(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist);
+ struct evsel *first = perf_evlist__first(evlist);
evlist->id_pos = first->id_pos;
evlist->is_pos = first->is_pos;
}
-static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
+static void perf_evlist__update_id_pos(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel)
perf_evsel__calc_id_pos(evsel);
@@ -114,161 +124,132 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
perf_evlist__set_id_pos(evlist);
}
-static void perf_evlist__purge(struct perf_evlist *evlist)
+static void perf_evlist__purge(struct evlist *evlist)
{
- struct perf_evsel *pos, *n;
+ struct evsel *pos, *n;
evlist__for_each_entry_safe(evlist, n, pos) {
- list_del_init(&pos->node);
+ list_del_init(&pos->core.node);
pos->evlist = NULL;
- perf_evsel__delete(pos);
+ evsel__delete(pos);
}
- evlist->nr_entries = 0;
+ evlist->core.nr_entries = 0;
}
-void perf_evlist__exit(struct perf_evlist *evlist)
+void perf_evlist__exit(struct evlist *evlist)
{
zfree(&evlist->mmap);
zfree(&evlist->overwrite_mmap);
fdarray__exit(&evlist->pollfd);
}
-void perf_evlist__delete(struct perf_evlist *evlist)
+void evlist__delete(struct evlist *evlist)
{
if (evlist == NULL)
return;
perf_evlist__munmap(evlist);
- perf_evlist__close(evlist);
- cpu_map__put(evlist->cpus);
- thread_map__put(evlist->threads);
- evlist->cpus = NULL;
- evlist->threads = NULL;
+ evlist__close(evlist);
+ perf_cpu_map__put(evlist->core.cpus);
+ perf_thread_map__put(evlist->core.threads);
+ evlist->core.cpus = NULL;
+ evlist->core.threads = NULL;
perf_evlist__purge(evlist);
perf_evlist__exit(evlist);
free(evlist);
}
-static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
- struct perf_evsel *evsel)
-{
- /*
- * We already have cpus for evsel (via PMU sysfs) so
- * keep it, if there's no target cpu list defined.
- */
- if (!evsel->own_cpus || evlist->has_user_cpus) {
- cpu_map__put(evsel->cpus);
- evsel->cpus = cpu_map__get(evlist->cpus);
- } else if (evsel->cpus != evsel->own_cpus) {
- cpu_map__put(evsel->cpus);
- evsel->cpus = cpu_map__get(evsel->own_cpus);
- }
-
- thread_map__put(evsel->threads);
- evsel->threads = thread_map__get(evlist->threads);
-}
-
-static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel;
-
- evlist__for_each_entry(evlist, evsel)
- __perf_evlist__propagate_maps(evlist, evsel);
-}
-
-void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
+void evlist__add(struct evlist *evlist, struct evsel *entry)
{
entry->evlist = evlist;
- list_add_tail(&entry->node, &evlist->entries);
- entry->idx = evlist->nr_entries;
+ entry->idx = evlist->core.nr_entries;
entry->tracking = !entry->idx;
- if (!evlist->nr_entries++)
- perf_evlist__set_id_pos(evlist);
+ perf_evlist__add(&evlist->core, &entry->core);
- __perf_evlist__propagate_maps(evlist, entry);
+ if (evlist->core.nr_entries == 1)
+ perf_evlist__set_id_pos(evlist);
}
-void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
+void evlist__remove(struct evlist *evlist, struct evsel *evsel)
{
evsel->evlist = NULL;
- list_del_init(&evsel->node);
- evlist->nr_entries -= 1;
+ perf_evlist__remove(&evlist->core, &evsel->core);
}
-void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
+void perf_evlist__splice_list_tail(struct evlist *evlist,
struct list_head *list)
{
- struct perf_evsel *evsel, *temp;
+ struct evsel *evsel, *temp;
__evlist__for_each_entry_safe(list, temp, evsel) {
- list_del_init(&evsel->node);
- perf_evlist__add(evlist, evsel);
+ list_del_init(&evsel->core.node);
+ evlist__add(evlist, evsel);
}
}
void __perf_evlist__set_leader(struct list_head *list)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
- leader = list_entry(list->next, struct perf_evsel, node);
- evsel = list_entry(list->prev, struct perf_evsel, node);
+ leader = list_entry(list->next, struct evsel, core.node);
+ evsel = list_entry(list->prev, struct evsel, core.node);
- leader->nr_members = evsel->idx - leader->idx + 1;
+ leader->core.nr_members = evsel->idx - leader->idx + 1;
__evlist__for_each_entry(list, evsel) {
evsel->leader = leader;
}
}
-void perf_evlist__set_leader(struct perf_evlist *evlist)
+void perf_evlist__set_leader(struct evlist *evlist)
{
- if (evlist->nr_entries) {
- evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
- __perf_evlist__set_leader(&evlist->entries);
+ if (evlist->core.nr_entries) {
+ evlist->nr_groups = evlist->core.nr_entries > 1 ? 1 : 0;
+ __perf_evlist__set_leader(&evlist->core.entries);
}
}
-int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
+int __perf_evlist__add_default(struct evlist *evlist, bool precise)
{
- struct perf_evsel *evsel = perf_evsel__new_cycles(precise);
+ struct evsel *evsel = perf_evsel__new_cycles(precise);
if (evsel == NULL)
return -ENOMEM;
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
return 0;
}
-int perf_evlist__add_dummy(struct perf_evlist *evlist)
+int perf_evlist__add_dummy(struct evlist *evlist)
{
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_DUMMY,
.size = sizeof(attr), /* to capture ABI version */
};
- struct perf_evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries);
+ struct evsel *evsel = perf_evsel__new_idx(&attr, evlist->core.nr_entries);
if (evsel == NULL)
return -ENOMEM;
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
return 0;
}
-static int perf_evlist__add_attrs(struct perf_evlist *evlist,
+static int evlist__add_attrs(struct evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs)
{
- struct perf_evsel *evsel, *n;
+ struct evsel *evsel, *n;
LIST_HEAD(head);
size_t i;
for (i = 0; i < nr_attrs; i++) {
- evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i);
+ evsel = perf_evsel__new_idx(attrs + i, evlist->core.nr_entries + i);
if (evsel == NULL)
goto out_delete_partial_list;
- list_add_tail(&evsel->node, &head);
+ list_add_tail(&evsel->core.node, &head);
}
perf_evlist__splice_list_tail(evlist, &head);
@@ -277,11 +258,11 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
out_delete_partial_list:
__evlist__for_each_entry_safe(&head, n, evsel)
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
return -1;
}
-int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
+int __perf_evlist__add_default_attrs(struct evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs)
{
size_t i;
@@ -289,31 +270,31 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
for (i = 0; i < nr_attrs; i++)
event_attr_init(attrs + i);
- return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
+ return evlist__add_attrs(evlist, attrs, nr_attrs);
}
-struct perf_evsel *
-perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
+struct evsel *
+perf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
- (int)evsel->attr.config == id)
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT &&
+ (int)evsel->core.attr.config == id)
return evsel;
}
return NULL;
}
-struct perf_evsel *
-perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
+struct evsel *
+perf_evlist__find_tracepoint_by_name(struct evlist *evlist,
const char *name)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
+ if ((evsel->core.attr.type == PERF_TYPE_TRACEPOINT) &&
(strcmp(evsel->name, name) == 0))
return evsel;
}
@@ -321,66 +302,66 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
return NULL;
}
-int perf_evlist__add_newtp(struct perf_evlist *evlist,
+int perf_evlist__add_newtp(struct evlist *evlist,
const char *sys, const char *name, void *handler)
{
- struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
+ struct evsel *evsel = perf_evsel__newtp(sys, name);
if (IS_ERR(evsel))
return -1;
evsel->handler = handler;
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
return 0;
}
-static int perf_evlist__nr_threads(struct perf_evlist *evlist,
- struct perf_evsel *evsel)
+static int perf_evlist__nr_threads(struct evlist *evlist,
+ struct evsel *evsel)
{
if (evsel->system_wide)
return 1;
else
- return thread_map__nr(evlist->threads);
+ return perf_thread_map__nr(evlist->core.threads);
}
-void perf_evlist__disable(struct perf_evlist *evlist)
+void evlist__disable(struct evlist *evlist)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
evlist__for_each_entry(evlist, pos) {
- if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd)
+ if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
continue;
- perf_evsel__disable(pos);
+ evsel__disable(pos);
}
evlist->enabled = false;
}
-void perf_evlist__enable(struct perf_evlist *evlist)
+void evlist__enable(struct evlist *evlist)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
evlist__for_each_entry(evlist, pos) {
- if (!perf_evsel__is_group_leader(pos) || !pos->fd)
+ if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
continue;
- perf_evsel__enable(pos);
+ evsel__enable(pos);
}
evlist->enabled = true;
}
-void perf_evlist__toggle_enable(struct perf_evlist *evlist)
+void perf_evlist__toggle_enable(struct evlist *evlist)
{
- (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
+ (evlist->enabled ? evlist__disable : evlist__enable)(evlist);
}
-static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
- struct perf_evsel *evsel, int cpu)
+static int perf_evlist__enable_event_cpu(struct evlist *evlist,
+ struct evsel *evsel, int cpu)
{
int thread;
int nr_threads = perf_evlist__nr_threads(evlist, evsel);
- if (!evsel->fd)
+ if (!evsel->core.fd)
return -EINVAL;
for (thread = 0; thread < nr_threads; thread++) {
@@ -391,14 +372,14 @@ static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
return 0;
}
-static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
- struct perf_evsel *evsel,
+static int perf_evlist__enable_event_thread(struct evlist *evlist,
+ struct evsel *evsel,
int thread)
{
int cpu;
- int nr_cpus = cpu_map__nr(evlist->cpus);
+ int nr_cpus = perf_cpu_map__nr(evlist->core.cpus);
- if (!evsel->fd)
+ if (!evsel->core.fd)
return -EINVAL;
for (cpu = 0; cpu < nr_cpus; cpu++) {
@@ -409,10 +390,10 @@ static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
return 0;
}
-int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
- struct perf_evsel *evsel, int idx)
+int perf_evlist__enable_event_idx(struct evlist *evlist,
+ struct evsel *evsel, int idx)
{
- bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
+ bool per_cpu_mmaps = !perf_cpu_map__empty(evlist->core.cpus);
if (per_cpu_mmaps)
return perf_evlist__enable_event_cpu(evlist, evsel, idx);
@@ -420,12 +401,12 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
return perf_evlist__enable_event_thread(evlist, evsel, idx);
}
-int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
+int perf_evlist__alloc_pollfd(struct evlist *evlist)
{
- int nr_cpus = cpu_map__nr(evlist->cpus);
- int nr_threads = thread_map__nr(evlist->threads);
+ int nr_cpus = perf_cpu_map__nr(evlist->core.cpus);
+ int nr_threads = perf_thread_map__nr(evlist->core.threads);
int nfds = 0;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (evsel->system_wide)
@@ -441,7 +422,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
return 0;
}
-static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
+static int __perf_evlist__add_pollfd(struct evlist *evlist, int fd,
struct perf_mmap *map, short revent)
{
int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP);
@@ -458,7 +439,7 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
return pos;
}
-int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
+int perf_evlist__add_pollfd(struct evlist *evlist, int fd)
{
return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN);
}
@@ -472,19 +453,19 @@ static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd,
perf_mmap__put(map);
}
-int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
+int perf_evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask)
{
return fdarray__filter(&evlist->pollfd, revents_and_mask,
perf_evlist__munmap_filtered, NULL);
}
-int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
+int perf_evlist__poll(struct evlist *evlist, int timeout)
{
return fdarray__poll(&evlist->pollfd, timeout);
}
-static void perf_evlist__id_hash(struct perf_evlist *evlist,
- struct perf_evsel *evsel,
+static void perf_evlist__id_hash(struct evlist *evlist,
+ struct evsel *evsel,
int cpu, int thread, u64 id)
{
int hash;
@@ -496,15 +477,15 @@ static void perf_evlist__id_hash(struct perf_evlist *evlist,
hlist_add_head(&sid->node, &evlist->heads[hash]);
}
-void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
+void perf_evlist__id_add(struct evlist *evlist, struct evsel *evsel,
int cpu, int thread, u64 id)
{
perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
evsel->id[evsel->ids++] = id;
}
-int perf_evlist__id_add_fd(struct perf_evlist *evlist,
- struct perf_evsel *evsel,
+int perf_evlist__id_add_fd(struct evlist *evlist,
+ struct evsel *evsel,
int cpu, int thread, int fd)
{
u64 read_data[4] = { 0, };
@@ -528,13 +509,13 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist,
if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP)
return -1;
- if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
+ if (!(evsel->core.attr.read_format & PERF_FORMAT_ID) ||
read(fd, &read_data, sizeof(read_data)) == -1)
return -1;
- if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+ if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
++id_idx;
- if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+ if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
++id_idx;
id = read_data[id_idx];
@@ -544,23 +525,23 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist,
return 0;
}
-static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
- struct perf_evsel *evsel, int idx, int cpu,
+static void perf_evlist__set_sid_idx(struct evlist *evlist,
+ struct evsel *evsel, int idx, int cpu,
int thread)
{
struct perf_sample_id *sid = SID(evsel, cpu, thread);
sid->idx = idx;
- if (evlist->cpus && cpu >= 0)
- sid->cpu = evlist->cpus->map[cpu];
+ if (evlist->core.cpus && cpu >= 0)
+ sid->cpu = evlist->core.cpus->map[cpu];
else
sid->cpu = -1;
- if (!evsel->system_wide && evlist->threads && thread >= 0)
- sid->tid = thread_map__pid(evlist->threads, thread);
+ if (!evsel->system_wide && evlist->core.threads && thread >= 0)
+ sid->tid = perf_thread_map__pid(evlist->core.threads, thread);
else
sid->tid = -1;
}
-struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
+struct perf_sample_id *perf_evlist__id2sid(struct evlist *evlist, u64 id)
{
struct hlist_head *head;
struct perf_sample_id *sid;
@@ -576,11 +557,11 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
return NULL;
}
-struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
+struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id)
{
struct perf_sample_id *sid;
- if (evlist->nr_entries == 1 || !id)
+ if (evlist->core.nr_entries == 1 || !id)
return perf_evlist__first(evlist);
sid = perf_evlist__id2sid(evlist, id);
@@ -593,7 +574,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return NULL;
}
-struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+struct evsel *perf_evlist__id2evsel_strict(struct evlist *evlist,
u64 id)
{
struct perf_sample_id *sid;
@@ -608,10 +589,10 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
return NULL;
}
-static int perf_evlist__event2id(struct perf_evlist *evlist,
+static int perf_evlist__event2id(struct evlist *evlist,
union perf_event *event, u64 *id)
{
- const u64 *array = event->sample.array;
+ const __u64 *array = event->sample.array;
ssize_t n;
n = (event->header.size - sizeof(event->header)) >> 3;
@@ -629,19 +610,19 @@ static int perf_evlist__event2id(struct perf_evlist *evlist,
return 0;
}
-struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
+struct evsel *perf_evlist__event2evsel(struct evlist *evlist,
union perf_event *event)
{
- struct perf_evsel *first = perf_evlist__first(evlist);
+ struct evsel *first = perf_evlist__first(evlist);
struct hlist_head *head;
struct perf_sample_id *sid;
int hash;
u64 id;
- if (evlist->nr_entries == 1)
+ if (evlist->core.nr_entries == 1)
return first;
- if (!first->attr.sample_id_all &&
+ if (!first->core.attr.sample_id_all &&
event->header.type != PERF_RECORD_SAMPLE)
return first;
@@ -662,7 +643,7 @@ struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
return NULL;
}
-static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
+static int perf_evlist__set_paused(struct evlist *evlist, bool value)
{
int i;
@@ -682,17 +663,17 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
return 0;
}
-static int perf_evlist__pause(struct perf_evlist *evlist)
+static int perf_evlist__pause(struct evlist *evlist)
{
return perf_evlist__set_paused(evlist, true);
}
-static int perf_evlist__resume(struct perf_evlist *evlist)
+static int perf_evlist__resume(struct evlist *evlist)
{
return perf_evlist__set_paused(evlist, false);
}
-static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
+static void perf_evlist__munmap_nofree(struct evlist *evlist)
{
int i;
@@ -705,22 +686,22 @@ static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
perf_mmap__munmap(&evlist->overwrite_mmap[i]);
}
-void perf_evlist__munmap(struct perf_evlist *evlist)
+void perf_evlist__munmap(struct evlist *evlist)
{
perf_evlist__munmap_nofree(evlist);
zfree(&evlist->mmap);
zfree(&evlist->overwrite_mmap);
}
-static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist,
+static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist,
bool overwrite)
{
int i;
struct perf_mmap *map;
- evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
- if (cpu_map__empty(evlist->cpus))
- evlist->nr_mmaps = thread_map__nr(evlist->threads);
+ evlist->nr_mmaps = perf_cpu_map__nr(evlist->core.cpus);
+ if (perf_cpu_map__empty(evlist->core.cpus))
+ evlist->nr_mmaps = perf_thread_map__nr(evlist->core.threads);
map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
if (!map)
return NULL;
@@ -743,21 +724,21 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist,
}
static bool
-perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
- struct perf_evsel *evsel)
+perf_evlist__should_poll(struct evlist *evlist __maybe_unused,
+ struct evsel *evsel)
{
- if (evsel->attr.write_backward)
+ if (evsel->core.attr.write_backward)
return false;
return true;
}
-static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
+static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx,
struct mmap_params *mp, int cpu_idx,
int thread, int *_output, int *_output_overwrite)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int revent;
- int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
+ int evlist_cpu = cpu_map__cpu(evlist->core.cpus, cpu_idx);
evlist__for_each_entry(evlist, evsel) {
struct perf_mmap *maps = evlist->mmap;
@@ -766,7 +747,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
int cpu;
mp->prot = PROT_READ | PROT_WRITE;
- if (evsel->attr.write_backward) {
+ if (evsel->core.attr.write_backward) {
output = _output_overwrite;
maps = evlist->overwrite_mmap;
@@ -784,7 +765,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
if (evsel->system_wide && thread)
continue;
- cpu = cpu_map__idx(evsel->cpus, evlist_cpu);
+ cpu = perf_cpu_map__idx(evsel->core.cpus, evlist_cpu);
if (cpu == -1)
continue;
@@ -817,7 +798,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
return -1;
}
- if (evsel->attr.read_format & PERF_FORMAT_ID) {
+ if (evsel->core.attr.read_format & PERF_FORMAT_ID) {
if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
fd) < 0)
return -1;
@@ -829,12 +810,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
return 0;
}
-static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
+static int perf_evlist__mmap_per_cpu(struct evlist *evlist,
struct mmap_params *mp)
{
int cpu, thread;
- int nr_cpus = cpu_map__nr(evlist->cpus);
- int nr_threads = thread_map__nr(evlist->threads);
+ int nr_cpus = perf_cpu_map__nr(evlist->core.cpus);
+ int nr_threads = perf_thread_map__nr(evlist->core.threads);
pr_debug2("perf event ring buffer mmapped per cpu\n");
for (cpu = 0; cpu < nr_cpus; cpu++) {
@@ -858,11 +839,11 @@ out_unmap:
return -1;
}
-static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
+static int perf_evlist__mmap_per_thread(struct evlist *evlist,
struct mmap_params *mp)
{
int thread;
- int nr_threads = thread_map__nr(evlist->threads);
+ int nr_threads = perf_thread_map__nr(evlist->core.threads);
pr_debug2("perf event ring buffer mmapped per thread\n");
for (thread = 0; thread < nr_threads; thread++) {
@@ -1006,14 +987,14 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
*
* Return: %0 on success, negative error code otherwise.
*/
-int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
+int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages,
unsigned int auxtrace_pages,
bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush,
int comp_level)
{
- struct perf_evsel *evsel;
- const struct cpu_map *cpus = evlist->cpus;
- const struct thread_map *threads = evlist->threads;
+ struct evsel *evsel;
+ const struct perf_cpu_map *cpus = evlist->core.cpus;
+ const struct perf_thread_map *threads = evlist->core.threads;
/*
* Delay setting mp.prot: set it before calling perf_mmap__mmap.
* Its value is decided by evsel's write_backward.
@@ -1038,28 +1019,28 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
auxtrace_pages, auxtrace_overwrite);
evlist__for_each_entry(evlist, evsel) {
- if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+ if ((evsel->core.attr.read_format & PERF_FORMAT_ID) &&
evsel->sample_id == NULL &&
- perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
+ perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0)
return -ENOMEM;
}
- if (cpu_map__empty(cpus))
+ if (perf_cpu_map__empty(cpus))
return perf_evlist__mmap_per_thread(evlist, &mp);
return perf_evlist__mmap_per_cpu(evlist, &mp);
}
-int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
+int perf_evlist__mmap(struct evlist *evlist, unsigned int pages)
{
return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1, 0);
}
-int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
+int perf_evlist__create_maps(struct evlist *evlist, struct target *target)
{
bool all_threads = (target->per_thread && target->system_wide);
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
/*
* If specify '-a' and '--per-thread' to perf record, perf record
@@ -1086,68 +1067,45 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
return -1;
if (target__uses_dummy_map(target))
- cpus = cpu_map__dummy_new();
+ cpus = perf_cpu_map__dummy_new();
else
- cpus = cpu_map__new(target->cpu_list);
+ cpus = perf_cpu_map__new(target->cpu_list);
if (!cpus)
goto out_delete_threads;
- evlist->has_user_cpus = !!target->cpu_list;
+ evlist->core.has_user_cpus = !!target->cpu_list;
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
return 0;
out_delete_threads:
- thread_map__put(threads);
+ perf_thread_map__put(threads);
return -1;
}
-void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads)
-{
- /*
- * Allow for the possibility that one or another of the maps isn't being
- * changed i.e. don't put it. Note we are assuming the maps that are
- * being applied are brand new and evlist is taking ownership of the
- * original reference count of 1. If that is not the case it is up to
- * the caller to increase the reference count.
- */
- if (cpus != evlist->cpus) {
- cpu_map__put(evlist->cpus);
- evlist->cpus = cpu_map__get(cpus);
- }
-
- if (threads != evlist->threads) {
- thread_map__put(evlist->threads);
- evlist->threads = thread_map__get(threads);
- }
-
- perf_evlist__propagate_maps(evlist);
-}
-
-void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
+void __perf_evlist__set_sample_bit(struct evlist *evlist,
enum perf_event_sample_format bit)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel)
__perf_evsel__set_sample_bit(evsel, bit);
}
-void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
+void __perf_evlist__reset_sample_bit(struct evlist *evlist,
enum perf_event_sample_format bit)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel)
__perf_evsel__reset_sample_bit(evsel, bit);
}
-int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
+int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err = 0;
evlist__for_each_entry(evlist, evsel) {
@@ -1158,7 +1116,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
* filters only work for tracepoint event, which doesn't have cpu limit.
* So evlist and evsel should always be same.
*/
- err = perf_evsel__apply_filter(evsel, evsel->filter);
+ err = perf_evsel__apply_filter(&evsel->core, evsel->filter);
if (err) {
*err_evsel = evsel;
break;
@@ -1168,13 +1126,13 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
return err;
}
-int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter)
+int perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err = 0;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
err = perf_evsel__set_filter(evsel, filter);
@@ -1185,7 +1143,7 @@ int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter)
return err;
}
-int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
+int perf_evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids)
{
char *filter;
int ret = -1;
@@ -1212,16 +1170,16 @@ out_free:
return ret;
}
-int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid)
+int perf_evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid)
{
return perf_evlist__set_tp_filter_pids(evlist, 1, &pid);
}
-bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
+bool perf_evlist__valid_sample_type(struct evlist *evlist)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
- if (evlist->nr_entries == 1)
+ if (evlist->core.nr_entries == 1)
return true;
if (evlist->id_pos < 0 || evlist->is_pos < 0)
@@ -1236,43 +1194,43 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
return true;
}
-u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
+u64 __perf_evlist__combined_sample_type(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (evlist->combined_sample_type)
return evlist->combined_sample_type;
evlist__for_each_entry(evlist, evsel)
- evlist->combined_sample_type |= evsel->attr.sample_type;
+ evlist->combined_sample_type |= evsel->core.attr.sample_type;
return evlist->combined_sample_type;
}
-u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist)
+u64 perf_evlist__combined_sample_type(struct evlist *evlist)
{
evlist->combined_sample_type = 0;
return __perf_evlist__combined_sample_type(evlist);
}
-u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
+u64 perf_evlist__combined_branch_type(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u64 branch_type = 0;
evlist__for_each_entry(evlist, evsel)
- branch_type |= evsel->attr.branch_sample_type;
+ branch_type |= evsel->core.attr.branch_sample_type;
return branch_type;
}
-bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
+bool perf_evlist__valid_read_format(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
- u64 read_format = first->attr.read_format;
- u64 sample_type = first->attr.sample_type;
+ struct evsel *first = perf_evlist__first(evlist), *pos = first;
+ u64 read_format = first->core.attr.read_format;
+ u64 sample_type = first->core.attr.sample_type;
evlist__for_each_entry(evlist, pos) {
- if (read_format != pos->attr.read_format)
+ if (read_format != pos->core.attr.read_format)
return false;
}
@@ -1285,23 +1243,23 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
return true;
}
-u64 perf_evlist__read_format(struct perf_evlist *evlist)
+u64 perf_evlist__read_format(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist);
- return first->attr.read_format;
+ struct evsel *first = perf_evlist__first(evlist);
+ return first->core.attr.read_format;
}
-u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
+u16 perf_evlist__id_hdr_size(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist);
+ struct evsel *first = perf_evlist__first(evlist);
struct perf_sample *data;
u64 sample_type;
u16 size = 0;
- if (!first->attr.sample_id_all)
+ if (!first->core.attr.sample_id_all)
goto out;
- sample_type = first->attr.sample_type;
+ sample_type = first->core.attr.sample_type;
if (sample_type & PERF_SAMPLE_TID)
size += sizeof(data->tid) * 2;
@@ -1324,42 +1282,42 @@ out:
return size;
}
-bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
+bool perf_evlist__valid_sample_id_all(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
+ struct evsel *first = perf_evlist__first(evlist), *pos = first;
evlist__for_each_entry_continue(evlist, pos) {
- if (first->attr.sample_id_all != pos->attr.sample_id_all)
+ if (first->core.attr.sample_id_all != pos->core.attr.sample_id_all)
return false;
}
return true;
}
-bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
+bool perf_evlist__sample_id_all(struct evlist *evlist)
{
- struct perf_evsel *first = perf_evlist__first(evlist);
- return first->attr.sample_id_all;
+ struct evsel *first = perf_evlist__first(evlist);
+ return first->core.attr.sample_id_all;
}
-void perf_evlist__set_selected(struct perf_evlist *evlist,
- struct perf_evsel *evsel)
+void perf_evlist__set_selected(struct evlist *evlist,
+ struct evsel *evsel)
{
evlist->selected = evsel;
}
-void perf_evlist__close(struct perf_evlist *evlist)
+void evlist__close(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry_reverse(evlist, evsel)
- perf_evsel__close(evsel);
+ evsel__close(evsel);
}
-static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
+static int perf_evlist__create_syswide_maps(struct evlist *evlist)
{
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
int err = -ENOMEM;
/*
@@ -1371,32 +1329,32 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
* error, and we may not want to do that fallback to a
* default cpu identity map :-\
*/
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (!cpus)
goto out;
- threads = thread_map__new_dummy();
+ threads = perf_thread_map__new_dummy();
if (!threads)
goto out_put;
- perf_evlist__set_maps(evlist, cpus, threads);
+ perf_evlist__set_maps(&evlist->core, cpus, threads);
out:
return err;
out_put:
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
goto out;
}
-int perf_evlist__open(struct perf_evlist *evlist)
+int evlist__open(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err;
/*
* Default: one fd per CPU, all threads, aka systemwide
* as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
*/
- if (evlist->threads == NULL && evlist->cpus == NULL) {
+ if (evlist->core.threads == NULL && evlist->core.cpus == NULL) {
err = perf_evlist__create_syswide_maps(evlist);
if (err < 0)
goto out_err;
@@ -1405,19 +1363,19 @@ int perf_evlist__open(struct perf_evlist *evlist)
perf_evlist__update_id_pos(evlist);
evlist__for_each_entry(evlist, evsel) {
- err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
+ err = evsel__open(evsel, evsel->core.cpus, evsel->core.threads);
if (err < 0)
goto out_err;
}
return 0;
out_err:
- perf_evlist__close(evlist);
+ evlist__close(evlist);
errno = -err;
return err;
}
-int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
+int perf_evlist__prepare_workload(struct evlist *evlist, struct target *target,
const char *argv[], bool pipe_output,
void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
{
@@ -1499,12 +1457,12 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
}
if (target__none(target)) {
- if (evlist->threads == NULL) {
+ if (evlist->core.threads == NULL) {
fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
__func__, __LINE__);
goto out_close_pipes;
}
- thread_map__set_pid(evlist->threads, 0, evlist->workload.pid);
+ perf_thread_map__set_pid(evlist->core.threads, 0, evlist->workload.pid);
}
close(child_ready_pipe[1]);
@@ -1531,7 +1489,7 @@ out_close_ready_pipe:
return -1;
}
-int perf_evlist__start_workload(struct perf_evlist *evlist)
+int perf_evlist__start_workload(struct evlist *evlist)
{
if (evlist->workload.cork_fd > 0) {
char bf = 0;
@@ -1550,30 +1508,30 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
return 0;
}
-int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
+int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event,
struct perf_sample *sample)
{
- struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
+ struct evsel *evsel = perf_evlist__event2evsel(evlist, event);
if (!evsel)
return -EFAULT;
return perf_evsel__parse_sample(evsel, event, sample);
}
-int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist,
+int perf_evlist__parse_sample_timestamp(struct evlist *evlist,
union perf_event *event,
u64 *timestamp)
{
- struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
+ struct evsel *evsel = perf_evlist__event2evsel(evlist, event);
if (!evsel)
return -EFAULT;
return perf_evsel__parse_sample_timestamp(evsel, event, timestamp);
}
-size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
+size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
size_t printed = 0;
evlist__for_each_entry(evlist, evsel) {
@@ -1584,7 +1542,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
return printed + fprintf(fp, "\n");
}
-int perf_evlist__strerror_open(struct perf_evlist *evlist,
+int perf_evlist__strerror_open(struct evlist *evlist,
int err, char *buf, size_t size)
{
int printed, value;
@@ -1613,20 +1571,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist,
"Hint:\tThe current value is %d.", value);
break;
case EINVAL: {
- struct perf_evsel *first = perf_evlist__first(evlist);
+ struct evsel *first = perf_evlist__first(evlist);
int max_freq;
if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0)
goto out_default;
- if (first->attr.sample_freq < (u64)max_freq)
+ if (first->core.attr.sample_freq < (u64)max_freq)
goto out_default;
printed = scnprintf(buf, size,
"Error:\t%s.\n"
"Hint:\tCheck /proc/sys/kernel/perf_event_max_sample_rate.\n"
"Hint:\tThe current value is %d and %" PRIu64 " is being requested.",
- emsg, max_freq, first->attr.sample_freq);
+ emsg, max_freq, first->core.attr.sample_freq);
break;
}
default:
@@ -1638,7 +1596,7 @@ out_default:
return 0;
}
-int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
+int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size)
{
char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
@@ -1669,10 +1627,10 @@ int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, s
return 0;
}
-void perf_evlist__to_front(struct perf_evlist *evlist,
- struct perf_evsel *move_evsel)
+void perf_evlist__to_front(struct evlist *evlist,
+ struct evsel *move_evsel)
{
- struct perf_evsel *evsel, *n;
+ struct evsel *evsel, *n;
LIST_HEAD(move);
if (move_evsel == perf_evlist__first(evlist))
@@ -1680,16 +1638,16 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
evlist__for_each_entry_safe(evlist, n, evsel) {
if (evsel->leader == move_evsel->leader)
- list_move_tail(&evsel->node, &move);
+ list_move_tail(&evsel->core.node, &move);
}
- list_splice(&move, &evlist->entries);
+ list_splice(&move, &evlist->core.entries);
}
-void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
- struct perf_evsel *tracking_evsel)
+void perf_evlist__set_tracking_event(struct evlist *evlist,
+ struct evsel *tracking_evsel)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (tracking_evsel->tracking)
return;
@@ -1702,11 +1660,11 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
tracking_evsel->tracking = true;
}
-struct perf_evsel *
-perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
+struct evsel *
+perf_evlist__find_evsel_by_str(struct evlist *evlist,
const char *str)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (!evsel->name)
@@ -1718,7 +1676,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
return NULL;
}
-void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
+void perf_evlist__toggle_bkw_mmap(struct evlist *evlist,
enum bkw_mmap_state state)
{
enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
@@ -1776,12 +1734,12 @@ state_err:
return;
}
-bool perf_evlist__exclude_kernel(struct perf_evlist *evlist)
+bool perf_evlist__exclude_kernel(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (!evsel->attr.exclude_kernel)
+ if (!evsel->core.attr.exclude_kernel)
return false;
}
@@ -1793,25 +1751,25 @@ bool perf_evlist__exclude_kernel(struct perf_evlist *evlist)
* the group display. Set the artificial group and set the leader's
* forced_leader flag to notify the display code.
*/
-void perf_evlist__force_leader(struct perf_evlist *evlist)
+void perf_evlist__force_leader(struct evlist *evlist)
{
if (!evlist->nr_groups) {
- struct perf_evsel *leader = perf_evlist__first(evlist);
+ struct evsel *leader = perf_evlist__first(evlist);
perf_evlist__set_leader(evlist);
leader->forced_leader = true;
}
}
-struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
- struct perf_evsel *evsel)
+struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
+ struct evsel *evsel)
{
- struct perf_evsel *c2, *leader;
+ struct evsel *c2, *leader;
bool is_open = true;
leader = evsel->leader;
pr_debug("Weak group for %s/%d failed\n",
- leader->name, leader->nr_members);
+ leader->name, leader->core.nr_members);
/*
* for_each_group_member doesn't work here because it doesn't
@@ -1822,24 +1780,24 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
is_open = false;
if (c2->leader == leader) {
if (is_open)
- perf_evsel__close(c2);
+ evsel__close(c2);
c2->leader = c2;
- c2->nr_members = 0;
+ c2->core.nr_members = 0;
}
}
return leader;
}
-int perf_evlist__add_sb_event(struct perf_evlist **evlist,
+int perf_evlist__add_sb_event(struct evlist **evlist,
struct perf_event_attr *attr,
perf_evsel__sb_cb_t cb,
void *data)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool new_evlist = (*evlist) == NULL;
if (*evlist == NULL)
- *evlist = perf_evlist__new();
+ *evlist = evlist__new();
if (*evlist == NULL)
return -1;
@@ -1848,18 +1806,18 @@ int perf_evlist__add_sb_event(struct perf_evlist **evlist,
attr->sample_id_all = 1;
}
- evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries);
+ evsel = perf_evsel__new_idx(attr, (*evlist)->core.nr_entries);
if (!evsel)
goto out_err;
evsel->side_band.cb = cb;
evsel->side_band.data = data;
- perf_evlist__add(*evlist, evsel);
+ evlist__add(*evlist, evsel);
return 0;
out_err:
if (new_evlist) {
- perf_evlist__delete(*evlist);
+ evlist__delete(*evlist);
*evlist = NULL;
}
return -1;
@@ -1867,9 +1825,17 @@ out_err:
static void *perf_evlist__poll_thread(void *arg)
{
- struct perf_evlist *evlist = arg;
+ struct evlist *evlist = arg;
bool draining = false;
int i, done = 0;
+ /*
+ * In order to read symbols from other namespaces perf to needs to call
+ * setns(2). This isn't permitted if the struct_fs has multiple users.
+ * unshare(2) the fs so that we may continue to setns into namespaces
+ * that we're observing when, for instance, reading the build-ids at
+ * the end of a 'perf record' session.
+ */
+ unshare(CLONE_FS);
while (!done) {
bool got_data = false;
@@ -1887,7 +1853,7 @@ static void *perf_evlist__poll_thread(void *arg)
if (perf_mmap__read_init(map))
continue;
while ((event = perf_mmap__read_event(map)) != NULL) {
- struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
+ struct evsel *evsel = perf_evlist__event2evsel(evlist, event);
if (evsel && evsel->side_band.cb)
evsel->side_band.cb(event, evsel->side_band.data);
@@ -1906,10 +1872,10 @@ static void *perf_evlist__poll_thread(void *arg)
return NULL;
}
-int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
+int perf_evlist__start_sb_thread(struct evlist *evlist,
struct target *target)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
if (!evlist)
return 0;
@@ -1918,8 +1884,8 @@ int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
goto out_delete_evlist;
evlist__for_each_entry(evlist, counter) {
- if (perf_evsel__open(counter, evlist->cpus,
- evlist->threads) < 0)
+ if (evsel__open(counter, evlist->core.cpus,
+ evlist->core.threads) < 0)
goto out_delete_evlist;
}
@@ -1927,7 +1893,7 @@ int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
goto out_delete_evlist;
evlist__for_each_entry(evlist, counter) {
- if (perf_evsel__enable(counter))
+ if (evsel__enable(counter))
goto out_delete_evlist;
}
@@ -1938,16 +1904,16 @@ int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
return 0;
out_delete_evlist:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
evlist = NULL;
return -1;
}
-void perf_evlist__stop_sb_thread(struct perf_evlist *evlist)
+void perf_evlist__stop_sb_thread(struct evlist *evlist)
{
if (!evlist)
return;
evlist->thread.done = 1;
pthread_join(evlist->thread.th, NULL);
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 49354fe24d5f..a55f0f2546e5 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -8,30 +8,27 @@
#include <linux/list.h>
#include <api/fd/array.h>
#include <stdio.h>
-#include "../perf.h"
-#include "event.h"
+#include <internal/evlist.h>
+#include "events_stats.h"
#include "evsel.h"
#include "mmap.h"
-#include "util.h"
#include <signal.h>
#include <unistd.h>
struct pollfd;
struct thread_map;
-struct cpu_map;
+struct perf_cpu_map;
struct record_opts;
#define PERF_EVLIST__HLIST_BITS 8
#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
-struct perf_evlist {
- struct list_head entries;
+struct evlist {
+ struct perf_evlist core;
struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
- int nr_entries;
int nr_groups;
int nr_mmaps;
bool enabled;
- bool has_user_cpus;
size_t mmap_len;
int id_pos;
int is_pos;
@@ -44,12 +41,10 @@ struct perf_evlist {
struct fdarray pollfd;
struct perf_mmap *mmap;
struct perf_mmap *overwrite_mmap;
- struct thread_map *threads;
- struct cpu_map *cpus;
- struct perf_evsel *selected;
+ struct evsel *selected;
struct events_stats stats;
struct perf_env *env;
- void (*trace_event_sample_raw)(struct perf_evlist *evlist,
+ void (*trace_event_sample_raw)(struct evlist *evlist,
union perf_event *event,
struct perf_sample *sample);
u64 first_sample_time;
@@ -60,51 +55,51 @@ struct perf_evlist {
} thread;
};
-struct perf_evsel_str_handler {
+struct evsel_str_handler {
const char *name;
void *handler;
};
-struct perf_evlist *perf_evlist__new(void);
-struct perf_evlist *perf_evlist__new_default(void);
-struct perf_evlist *perf_evlist__new_dummy(void);
-void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads);
-void perf_evlist__exit(struct perf_evlist *evlist);
-void perf_evlist__delete(struct perf_evlist *evlist);
+struct evlist *evlist__new(void);
+struct evlist *perf_evlist__new_default(void);
+struct evlist *perf_evlist__new_dummy(void);
+void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads);
+void perf_evlist__exit(struct evlist *evlist);
+void evlist__delete(struct evlist *evlist);
-void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
-void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
+void evlist__add(struct evlist *evlist, struct evsel *entry);
+void evlist__remove(struct evlist *evlist, struct evsel *evsel);
-int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise);
+int __perf_evlist__add_default(struct evlist *evlist, bool precise);
-static inline int perf_evlist__add_default(struct perf_evlist *evlist)
+static inline int perf_evlist__add_default(struct evlist *evlist)
{
return __perf_evlist__add_default(evlist, true);
}
-int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
+int __perf_evlist__add_default_attrs(struct evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs);
#define perf_evlist__add_default_attrs(evlist, array) \
__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
-int perf_evlist__add_dummy(struct perf_evlist *evlist);
+int perf_evlist__add_dummy(struct evlist *evlist);
-int perf_evlist__add_sb_event(struct perf_evlist **evlist,
+int perf_evlist__add_sb_event(struct evlist **evlist,
struct perf_event_attr *attr,
perf_evsel__sb_cb_t cb,
void *data);
-int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
+int perf_evlist__start_sb_thread(struct evlist *evlist,
struct target *target);
-void perf_evlist__stop_sb_thread(struct perf_evlist *evlist);
+void perf_evlist__stop_sb_thread(struct evlist *evlist);
-int perf_evlist__add_newtp(struct perf_evlist *evlist,
+int perf_evlist__add_newtp(struct evlist *evlist,
const char *sys, const char *name, void *handler);
-void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
+void __perf_evlist__set_sample_bit(struct evlist *evlist,
enum perf_event_sample_format bit);
-void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
+void __perf_evlist__reset_sample_bit(struct evlist *evlist,
enum perf_event_sample_format bit);
#define perf_evlist__set_sample_bit(evlist, bit) \
@@ -113,58 +108,58 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
#define perf_evlist__reset_sample_bit(evlist, bit) \
__perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit)
-int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter);
-int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid);
-int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
+int perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter);
+int perf_evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid);
+int perf_evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids);
-struct perf_evsel *
-perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
+struct evsel *
+perf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id);
-struct perf_evsel *
-perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
+struct evsel *
+perf_evlist__find_tracepoint_by_name(struct evlist *evlist,
const char *name);
-void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
+void perf_evlist__id_add(struct evlist *evlist, struct evsel *evsel,
int cpu, int thread, u64 id);
-int perf_evlist__id_add_fd(struct perf_evlist *evlist,
- struct perf_evsel *evsel,
+int perf_evlist__id_add_fd(struct evlist *evlist,
+ struct evsel *evsel,
int cpu, int thread, int fd);
-int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
-int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
-int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
+int perf_evlist__add_pollfd(struct evlist *evlist, int fd);
+int perf_evlist__alloc_pollfd(struct evlist *evlist);
+int perf_evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask);
-int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
+int perf_evlist__poll(struct evlist *evlist, int timeout);
-struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
-struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id);
+struct evsel *perf_evlist__id2evsel_strict(struct evlist *evlist,
u64 id);
-struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
+struct perf_sample_id *perf_evlist__id2sid(struct evlist *evlist, u64 id);
-void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
+void perf_evlist__toggle_bkw_mmap(struct evlist *evlist, enum bkw_mmap_state state);
-void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
+void perf_evlist__mmap_consume(struct evlist *evlist, int idx);
-int perf_evlist__open(struct perf_evlist *evlist);
-void perf_evlist__close(struct perf_evlist *evlist);
+int evlist__open(struct evlist *evlist);
+void evlist__close(struct evlist *evlist);
struct callchain_param;
-void perf_evlist__set_id_pos(struct perf_evlist *evlist);
+void perf_evlist__set_id_pos(struct evlist *evlist);
bool perf_can_sample_identifier(void);
bool perf_can_record_switch_events(void);
bool perf_can_record_cpu_wide(void);
-void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
+void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
struct callchain_param *callchain);
int record_opts__config(struct record_opts *opts);
-int perf_evlist__prepare_workload(struct perf_evlist *evlist,
+int perf_evlist__prepare_workload(struct evlist *evlist,
struct target *target,
const char *argv[], bool pipe_output,
void (*exec_error)(int signo, siginfo_t *info,
void *ucontext));
-int perf_evlist__start_workload(struct perf_evlist *evlist);
+int perf_evlist__start_workload(struct evlist *evlist);
struct option;
@@ -175,77 +170,75 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
unsigned long perf_event_mlock_kb_in_pages(void);
-int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
+int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages,
unsigned int auxtrace_pages,
bool auxtrace_overwrite, int nr_cblocks,
int affinity, int flush, int comp_level);
-int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages);
-void perf_evlist__munmap(struct perf_evlist *evlist);
+int perf_evlist__mmap(struct evlist *evlist, unsigned int pages);
+void perf_evlist__munmap(struct evlist *evlist);
size_t perf_evlist__mmap_size(unsigned long pages);
-void perf_evlist__disable(struct perf_evlist *evlist);
-void perf_evlist__enable(struct perf_evlist *evlist);
-void perf_evlist__toggle_enable(struct perf_evlist *evlist);
+void evlist__disable(struct evlist *evlist);
+void evlist__enable(struct evlist *evlist);
+void perf_evlist__toggle_enable(struct evlist *evlist);
-int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
- struct perf_evsel *evsel, int idx);
+int perf_evlist__enable_event_idx(struct evlist *evlist,
+ struct evsel *evsel, int idx);
-void perf_evlist__set_selected(struct perf_evlist *evlist,
- struct perf_evsel *evsel);
+void perf_evlist__set_selected(struct evlist *evlist,
+ struct evsel *evsel);
-void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
- struct thread_map *threads);
-int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
-int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
+int perf_evlist__create_maps(struct evlist *evlist, struct target *target);
+int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel);
void __perf_evlist__set_leader(struct list_head *list);
-void perf_evlist__set_leader(struct perf_evlist *evlist);
+void perf_evlist__set_leader(struct evlist *evlist);
-u64 perf_evlist__read_format(struct perf_evlist *evlist);
-u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist);
-u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist);
-u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist);
-bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
-u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
+u64 perf_evlist__read_format(struct evlist *evlist);
+u64 __perf_evlist__combined_sample_type(struct evlist *evlist);
+u64 perf_evlist__combined_sample_type(struct evlist *evlist);
+u64 perf_evlist__combined_branch_type(struct evlist *evlist);
+bool perf_evlist__sample_id_all(struct evlist *evlist);
+u16 perf_evlist__id_hdr_size(struct evlist *evlist);
-int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
+int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event,
struct perf_sample *sample);
-int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist,
+int perf_evlist__parse_sample_timestamp(struct evlist *evlist,
union perf_event *event,
u64 *timestamp);
-bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
-bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
-bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
+bool perf_evlist__valid_sample_type(struct evlist *evlist);
+bool perf_evlist__valid_sample_id_all(struct evlist *evlist);
+bool perf_evlist__valid_read_format(struct evlist *evlist);
-void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
+void perf_evlist__splice_list_tail(struct evlist *evlist,
struct list_head *list);
-static inline bool perf_evlist__empty(struct perf_evlist *evlist)
+static inline bool perf_evlist__empty(struct evlist *evlist)
{
- return list_empty(&evlist->entries);
+ return list_empty(&evlist->core.entries);
}
-static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
+static inline struct evsel *perf_evlist__first(struct evlist *evlist)
{
- return list_entry(evlist->entries.next, struct perf_evsel, node);
+ return list_entry(evlist->core.entries.next, struct evsel, core.node);
}
-static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
+static inline struct evsel *perf_evlist__last(struct evlist *evlist)
{
- return list_entry(evlist->entries.prev, struct perf_evsel, node);
+ return list_entry(evlist->core.entries.prev, struct evsel, core.node);
}
-size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
+size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp);
-int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
-int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
+int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size);
+int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size);
-bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
-void perf_evlist__to_front(struct perf_evlist *evlist,
- struct perf_evsel *move_evsel);
+bool perf_evlist__can_select_event(struct evlist *evlist, const char *str);
+void perf_evlist__to_front(struct evlist *evlist,
+ struct evsel *move_evsel);
/**
* __evlist__for_each_entry - iterate thru all the evsels
@@ -253,7 +246,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_entry(list, evsel) \
- list_for_each_entry(evsel, list, node)
+ list_for_each_entry(evsel, list, core.node)
/**
* evlist__for_each_entry - iterate thru all the evsels
@@ -261,7 +254,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define evlist__for_each_entry(evlist, evsel) \
- __evlist__for_each_entry(&(evlist)->entries, evsel)
+ __evlist__for_each_entry(&(evlist)->core.entries, evsel)
/**
* __evlist__for_each_entry_continue - continue iteration thru all the evsels
@@ -269,7 +262,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_entry_continue(list, evsel) \
- list_for_each_entry_continue(evsel, list, node)
+ list_for_each_entry_continue(evsel, list, core.node)
/**
* evlist__for_each_entry_continue - continue iteration thru all the evsels
@@ -277,7 +270,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define evlist__for_each_entry_continue(evlist, evsel) \
- __evlist__for_each_entry_continue(&(evlist)->entries, evsel)
+ __evlist__for_each_entry_continue(&(evlist)->core.entries, evsel)
/**
* __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
@@ -285,7 +278,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_entry_reverse(list, evsel) \
- list_for_each_entry_reverse(evsel, list, node)
+ list_for_each_entry_reverse(evsel, list, core.node)
/**
* evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
@@ -293,7 +286,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define evlist__for_each_entry_reverse(evlist, evsel) \
- __evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
+ __evlist__for_each_entry_reverse(&(evlist)->core.entries, evsel)
/**
* __evlist__for_each_entry_safe - safely iterate thru all the evsels
@@ -302,7 +295,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_entry_safe(list, tmp, evsel) \
- list_for_each_entry_safe(evsel, tmp, list, node)
+ list_for_each_entry_safe(evsel, tmp, list, core.node)
/**
* evlist__for_each_entry_safe - safely iterate thru all the evsels
@@ -311,21 +304,21 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
* @tmp: struct evsel temp iterator
*/
#define evlist__for_each_entry_safe(evlist, tmp, evsel) \
- __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel)
+ __evlist__for_each_entry_safe(&(evlist)->core.entries, tmp, evsel)
-void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
- struct perf_evsel *tracking_evsel);
+void perf_evlist__set_tracking_event(struct evlist *evlist,
+ struct evsel *tracking_evsel);
-struct perf_evsel *
-perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);
+struct evsel *
+perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str);
-struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
+struct evsel *perf_evlist__event2evsel(struct evlist *evlist,
union perf_event *event);
-bool perf_evlist__exclude_kernel(struct perf_evlist *evlist);
+bool perf_evlist__exclude_kernel(struct evlist *evlist);
-void perf_evlist__force_leader(struct perf_evlist *evlist);
+void perf_evlist__force_leader(struct evlist *evlist);
-struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evlist,
- struct perf_evsel *evsel);
+struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist,
+ struct evsel *evsel);
#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ebb46da4dfe5..85825384f9e8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -22,9 +22,12 @@
#include <sys/resource.h>
#include <sys/types.h>
#include <dirent.h>
+#include <stdlib.h>
+#include <perf/evsel.h>
#include "asm/bug.h"
#include "callchain.h"
#include "cgroup.h"
+#include "counts.h"
#include "event.h"
#include "evsel.h"
#include "evlist.h"
@@ -32,12 +35,16 @@
#include "thread_map.h"
#include "target.h"
#include "perf_regs.h"
+#include "record.h"
#include "debug.h"
#include "trace-event.h"
#include "stat.h"
#include "string2.h"
#include "memswap.h"
+#include "util.h"
+#include "../perf-sys.h"
#include "util/parse-branch-options.h"
+#include <internal/xyarray.h>
#include <linux/ctype.h>
@@ -45,30 +52,30 @@ struct perf_missing_features perf_missing_features;
static clockid_t clockid;
-static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
+static int perf_evsel__no_extra_init(struct evsel *evsel __maybe_unused)
{
return 0;
}
void __weak test_attr__ready(void) { }
-static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
+static void perf_evsel__no_extra_fini(struct evsel *evsel __maybe_unused)
{
}
static struct {
size_t size;
- int (*init)(struct perf_evsel *evsel);
- void (*fini)(struct perf_evsel *evsel);
+ int (*init)(struct evsel *evsel);
+ void (*fini)(struct evsel *evsel);
} perf_evsel__object = {
- .size = sizeof(struct perf_evsel),
+ .size = sizeof(struct evsel),
.init = perf_evsel__no_extra_init,
.fini = perf_evsel__no_extra_fini,
};
int perf_evsel__object_config(size_t object_size,
- int (*init)(struct perf_evsel *evsel),
- void (*fini)(struct perf_evsel *evsel))
+ int (*init)(struct evsel *evsel),
+ void (*fini)(struct evsel *evsel))
{
if (object_size == 0)
@@ -89,7 +96,7 @@ set_methods:
return 0;
}
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
int __perf_evsel__sample_size(u64 sample_type)
{
@@ -113,7 +120,7 @@ int __perf_evsel__sample_size(u64 sample_type)
*
* This function returns the position of the event id (PERF_SAMPLE_ID or
* PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct
- * sample_event.
+ * perf_record_sample.
*/
static int __perf_evsel__calc_id_pos(u64 sample_type)
{
@@ -167,33 +174,33 @@ static int __perf_evsel__calc_is_pos(u64 sample_type)
return idx;
}
-void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
+void perf_evsel__calc_id_pos(struct evsel *evsel)
{
- evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type);
- evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
+ evsel->id_pos = __perf_evsel__calc_id_pos(evsel->core.attr.sample_type);
+ evsel->is_pos = __perf_evsel__calc_is_pos(evsel->core.attr.sample_type);
}
-void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+void __perf_evsel__set_sample_bit(struct evsel *evsel,
enum perf_event_sample_format bit)
{
- if (!(evsel->attr.sample_type & bit)) {
- evsel->attr.sample_type |= bit;
+ if (!(evsel->core.attr.sample_type & bit)) {
+ evsel->core.attr.sample_type |= bit;
evsel->sample_size += sizeof(u64);
perf_evsel__calc_id_pos(evsel);
}
}
-void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+void __perf_evsel__reset_sample_bit(struct evsel *evsel,
enum perf_event_sample_format bit)
{
- if (evsel->attr.sample_type & bit) {
- evsel->attr.sample_type &= ~bit;
+ if (evsel->core.attr.sample_type & bit) {
+ evsel->core.attr.sample_type &= ~bit;
evsel->sample_size -= sizeof(u64);
perf_evsel__calc_id_pos(evsel);
}
}
-void perf_evsel__set_sample_id(struct perf_evsel *evsel,
+void perf_evsel__set_sample_id(struct evsel *evsel,
bool can_sample_identifier)
{
if (can_sample_identifier) {
@@ -202,7 +209,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
} else {
perf_evsel__set_sample_bit(evsel, ID);
}
- evsel->attr.read_format |= PERF_FORMAT_ID;
+ evsel->core.attr.read_format |= PERF_FORMAT_ID;
}
/**
@@ -213,7 +220,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
*
* Return %true if event is function trace event
*/
-bool perf_evsel__is_function_event(struct perf_evsel *evsel)
+bool perf_evsel__is_function_event(struct evsel *evsel)
{
#define FUNCTION_EVENT "ftrace:function"
@@ -223,19 +230,19 @@ bool perf_evsel__is_function_event(struct perf_evsel *evsel)
#undef FUNCTION_EVENT
}
-void perf_evsel__init(struct perf_evsel *evsel,
- struct perf_event_attr *attr, int idx)
+void evsel__init(struct evsel *evsel,
+ struct perf_event_attr *attr, int idx)
{
+ perf_evsel__init(&evsel->core, attr);
evsel->idx = idx;
evsel->tracking = !idx;
- evsel->attr = *attr;
evsel->leader = evsel;
evsel->unit = "";
evsel->scale = 1.0;
evsel->max_events = ULONG_MAX;
evsel->evlist = NULL;
+ evsel->bpf_obj = NULL;
evsel->bpf_fd = -1;
- INIT_LIST_HEAD(&evsel->node);
INIT_LIST_HEAD(&evsel->config_terms);
perf_evsel__object.init(evsel);
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -248,18 +255,18 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->pmu_name = NULL;
}
-struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
+struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
{
- struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
+ struct evsel *evsel = zalloc(perf_evsel__object.size);
if (!evsel)
return NULL;
- perf_evsel__init(evsel, attr, idx);
+ evsel__init(evsel, attr, idx);
if (perf_evsel__is_bpf_output(evsel)) {
- evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
+ evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
- evsel->attr.sample_period = 1;
+ evsel->core.attr.sample_period = 1;
}
if (perf_evsel__is_clock(evsel)) {
@@ -278,17 +285,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
static bool perf_event_can_profile_kernel(void)
{
- return geteuid() == 0 || perf_event_paranoid() == -1;
+ return perf_event_paranoid_check(1);
}
-struct perf_evsel *perf_evsel__new_cycles(bool precise)
+struct evsel *perf_evsel__new_cycles(bool precise)
{
struct perf_event_attr attr = {
.type = PERF_TYPE_HARDWARE,
.config = PERF_COUNT_HW_CPU_CYCLES,
.exclude_kernel = !perf_event_can_profile_kernel(),
};
- struct perf_evsel *evsel;
+ struct evsel *evsel;
event_attr_init(&attr);
@@ -300,7 +307,7 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise)
* to kick in when we return and before perf_evsel__open() is called.
*/
new_event:
- evsel = perf_evsel__new(&attr);
+ evsel = evsel__new(&attr);
if (evsel == NULL)
goto out;
@@ -315,7 +322,7 @@ new_event:
out:
return evsel;
error_free:
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
evsel = NULL;
goto out;
}
@@ -323,9 +330,9 @@ error_free:
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
-struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
+struct evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
- struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
+ struct evsel *evsel = zalloc(perf_evsel__object.size);
int err = -ENOMEM;
if (evsel == NULL) {
@@ -349,7 +356,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
event_attr_init(&attr);
attr.config = evsel->tp_format->id;
attr.sample_period = 1;
- perf_evsel__init(evsel, &attr, idx);
+ evsel__init(evsel, &attr, idx);
}
return evsel;
@@ -382,10 +389,10 @@ static const char *__perf_evsel__hw_name(u64 config)
return "unknown-hardware";
}
-static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size)
{
int colon = 0, r = 0;
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
bool exclude_guest_default = false;
#define MOD_PRINT(context, mod) do { \
@@ -418,9 +425,9 @@ static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t
return r;
}
-static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__hw_name(struct evsel *evsel, char *bf, size_t size)
{
- int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
+ int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->core.attr.config));
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
}
@@ -444,9 +451,9 @@ static const char *__perf_evsel__sw_name(u64 config)
return "unknown-software";
}
-static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__sw_name(struct evsel *evsel, char *bf, size_t size)
{
- int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
+ int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->core.attr.config));
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
}
@@ -468,9 +475,9 @@ static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
return r;
}
-static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__bp_name(struct evsel *evsel, char *bf, size_t size)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
}
@@ -568,15 +575,15 @@ out_err:
return scnprintf(bf, size, "%s", err);
}
-static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__hw_cache_name(struct evsel *evsel, char *bf, size_t size)
{
- int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
+ int ret = __perf_evsel__hw_cache_name(evsel->core.attr.config, bf, size);
return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
}
-static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__raw_name(struct evsel *evsel, char *bf, size_t size)
{
- int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
+ int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->core.attr.config);
return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
}
@@ -586,7 +593,7 @@ static int perf_evsel__tool_name(char *bf, size_t size)
return ret;
}
-const char *perf_evsel__name(struct perf_evsel *evsel)
+const char *perf_evsel__name(struct evsel *evsel)
{
char bf[128];
@@ -596,7 +603,7 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
if (evsel->name)
return evsel->name;
- switch (evsel->attr.type) {
+ switch (evsel->core.attr.type) {
case PERF_TYPE_RAW:
perf_evsel__raw_name(evsel, bf, sizeof(bf));
break;
@@ -626,7 +633,7 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
default:
scnprintf(bf, sizeof(bf), "unknown attr type: %d",
- evsel->attr.type);
+ evsel->core.attr.type);
break;
}
@@ -638,7 +645,7 @@ out_unknown:
return "unknown";
}
-const char *perf_evsel__group_name(struct perf_evsel *evsel)
+const char *perf_evsel__group_name(struct evsel *evsel)
{
return evsel->group_name ?: "anon group";
}
@@ -653,10 +660,10 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel)
* For record -e 'cycles,instructions' and report --group
* 'cycles:u, instructions:u'
*/
-int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
+int perf_evsel__group_desc(struct evsel *evsel, char *buf, size_t size)
{
int ret = 0;
- struct perf_evsel *pos;
+ struct evsel *pos;
const char *group_name = perf_evsel__group_name(evsel);
if (!evsel->forced_leader)
@@ -675,12 +682,12 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
return ret;
}
-static void __perf_evsel__config_callchain(struct perf_evsel *evsel,
+static void __perf_evsel__config_callchain(struct evsel *evsel,
struct record_opts *opts,
struct callchain_param *param)
{
bool function = perf_evsel__is_function_event(evsel);
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
perf_evsel__set_sample_bit(evsel, CALLCHAIN);
@@ -734,7 +741,7 @@ static void __perf_evsel__config_callchain(struct perf_evsel *evsel,
}
}
-void perf_evsel__config_callchain(struct perf_evsel *evsel,
+void perf_evsel__config_callchain(struct evsel *evsel,
struct record_opts *opts,
struct callchain_param *param)
{
@@ -743,10 +750,10 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel,
}
static void
-perf_evsel__reset_callgraph(struct perf_evsel *evsel,
+perf_evsel__reset_callgraph(struct evsel *evsel,
struct callchain_param *param)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
if (param->record_mode == CALLCHAIN_LBR) {
@@ -760,12 +767,12 @@ perf_evsel__reset_callgraph(struct perf_evsel *evsel,
}
}
-static void apply_config_terms(struct perf_evsel *evsel,
+static void apply_config_terms(struct evsel *evsel,
struct record_opts *opts, bool track)
{
struct perf_evsel_config_term *term;
struct list_head *config_terms = &evsel->config_terms;
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
/* callgraph default */
struct callchain_param param = {
.record_mode = callchain_param.record_mode,
@@ -832,6 +839,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
break;
case PERF_EVSEL__CONFIG_TERM_PERCORE:
break;
+ case PERF_EVSEL__CONFIG_TERM_AUX_OUTPUT:
+ attr->aux_output = term->val.aux_output ? 1 : 0;
+ break;
default:
break;
}
@@ -878,17 +888,17 @@ static void apply_config_terms(struct perf_evsel *evsel,
if (sample_address) {
perf_evsel__set_sample_bit(evsel, ADDR);
perf_evsel__set_sample_bit(evsel, DATA_SRC);
- evsel->attr.mmap_data = track;
+ evsel->core.attr.mmap_data = track;
}
perf_evsel__config_callchain(evsel, opts, &param);
}
}
}
-static bool is_dummy_event(struct perf_evsel *evsel)
+static bool is_dummy_event(struct evsel *evsel)
{
- return (evsel->attr.type == PERF_TYPE_SOFTWARE) &&
- (evsel->attr.config == PERF_COUNT_SW_DUMMY);
+ return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
+ (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
}
/*
@@ -919,11 +929,11 @@ static bool is_dummy_event(struct perf_evsel *evsel)
* enable/disable events specifically, as there's no
* initial traced exec call.
*/
-void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
+void perf_evsel__config(struct evsel *evsel, struct record_opts *opts,
struct callchain_param *callchain)
{
- struct perf_evsel *leader = evsel->leader;
- struct perf_event_attr *attr = &evsel->attr;
+ struct evsel *leader = evsel->leader;
+ struct perf_event_attr *attr = &evsel->core.attr;
int track = evsel->tracking;
bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
@@ -947,7 +957,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
* Apply group format only if we belong to group
* with more than one members.
*/
- if (leader->nr_members > 1) {
+ if (leader->core.nr_members > 1) {
attr->read_format |= PERF_FORMAT_GROUP;
attr->inherit = 0;
}
@@ -984,14 +994,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
* event to follow the master sample_type to ease up
* report.
*/
- attr->sample_type = leader->attr.sample_type;
+ attr->sample_type = leader->core.attr.sample_type;
}
if (opts->no_samples)
attr->sample_freq = 0;
if (opts->inherit_stat) {
- evsel->attr.read_format |=
+ evsel->core.attr.read_format |=
PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID;
@@ -1009,7 +1019,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
* fault handler and its overall trickiness nature.
*/
if (perf_evsel__is_function_event(evsel))
- evsel->attr.exclude_callchain_user = 1;
+ evsel->core.attr.exclude_callchain_user = 1;
if (callchain && callchain->enabled && !evsel->no_aux_samples)
perf_evsel__config_callchain(evsel, opts, callchain);
@@ -1065,8 +1075,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
attr->mmap2 = track && !perf_missing_features.mmap2;
attr->comm = track;
attr->ksymbol = track && !perf_missing_features.ksymbol;
- attr->bpf_event = track && !opts->no_bpf_event &&
- !perf_missing_features.bpf_event;
+ attr->bpf_event = track && !opts->no_bpf_event && !perf_missing_features.bpf;
if (opts->record_namespaces)
attr->namespaces = track;
@@ -1078,7 +1087,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
perf_evsel__set_sample_bit(evsel, TRANSACTION);
if (opts->running_time) {
- evsel->attr.read_format |=
+ evsel->core.attr.read_format |=
PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
}
@@ -1124,8 +1133,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
attr->exclude_user = 1;
}
- if (evsel->own_cpus || evsel->unit)
- evsel->attr.read_format |= PERF_FORMAT_ID;
+ if (evsel->core.own_cpus || evsel->unit)
+ evsel->core.attr.read_format |= PERF_FORMAT_ID;
/*
* Apply event specific term settings,
@@ -1152,48 +1161,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
}
-static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
-{
- evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
-
- if (evsel->fd) {
- int cpu, thread;
- for (cpu = 0; cpu < ncpus; cpu++) {
- for (thread = 0; thread < nthreads; thread++) {
- FD(evsel, cpu, thread) = -1;
- }
- }
- }
-
- return evsel->fd != NULL ? 0 : -ENOMEM;
-}
-
-static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
- int ioc, void *arg)
-{
- int cpu, thread;
-
- for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
- for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
- int fd = FD(evsel, cpu, thread),
- err = ioctl(fd, ioc, arg);
-
- if (err)
- return err;
- }
- }
-
- return 0;
-}
-
-int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
-{
- return perf_evsel__run_ioctl(evsel,
- PERF_EVENT_IOC_SET_FILTER,
- (void *)filter);
-}
-
-int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
+int perf_evsel__set_filter(struct evsel *evsel, const char *filter)
{
char *new_filter = strdup(filter);
@@ -1206,7 +1174,7 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
return -1;
}
-static int perf_evsel__append_filter(struct perf_evsel *evsel,
+static int perf_evsel__append_filter(struct evsel *evsel,
const char *fmt, const char *filter)
{
char *new_filter;
@@ -1223,19 +1191,19 @@ static int perf_evsel__append_filter(struct perf_evsel *evsel,
return -1;
}
-int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
+int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter)
{
return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
}
-int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
+int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter)
{
return perf_evsel__append_filter(evsel, "%s,%s", filter);
}
-int perf_evsel__enable(struct perf_evsel *evsel)
+int evsel__enable(struct evsel *evsel)
{
- int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+ int err = perf_evsel__enable(&evsel->core);
if (!err)
evsel->disabled = false;
@@ -1243,9 +1211,9 @@ int perf_evsel__enable(struct perf_evsel *evsel)
return err;
}
-int perf_evsel__disable(struct perf_evsel *evsel)
+int evsel__disable(struct evsel *evsel)
{
- int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+ int err = perf_evsel__disable(&evsel->core);
/*
* We mark it disabled here so that tools that disable a event can
* ignore events after they disable it. I.e. the ring buffer may have
@@ -1258,7 +1226,7 @@ int perf_evsel__disable(struct perf_evsel *evsel)
return err;
}
-int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
+int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads)
{
if (ncpus == 0 || nthreads == 0)
return 0;
@@ -1280,20 +1248,15 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
return 0;
}
-static void perf_evsel__free_fd(struct perf_evsel *evsel)
-{
- xyarray__delete(evsel->fd);
- evsel->fd = NULL;
-}
-
-static void perf_evsel__free_id(struct perf_evsel *evsel)
+static void perf_evsel__free_id(struct evsel *evsel)
{
xyarray__delete(evsel->sample_id);
evsel->sample_id = NULL;
zfree(&evsel->id);
+ evsel->ids = 0;
}
-static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
+static void perf_evsel__free_config_terms(struct evsel *evsel)
{
struct perf_evsel_config_term *term, *h;
@@ -1303,41 +1266,30 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
}
}
-void perf_evsel__close_fd(struct perf_evsel *evsel)
-{
- int cpu, thread;
-
- for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
- for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
- close(FD(evsel, cpu, thread));
- FD(evsel, cpu, thread) = -1;
- }
-}
-
-void perf_evsel__exit(struct perf_evsel *evsel)
+void perf_evsel__exit(struct evsel *evsel)
{
- assert(list_empty(&evsel->node));
+ assert(list_empty(&evsel->core.node));
assert(evsel->evlist == NULL);
perf_evsel__free_counts(evsel);
- perf_evsel__free_fd(evsel);
+ perf_evsel__free_fd(&evsel->core);
perf_evsel__free_id(evsel);
perf_evsel__free_config_terms(evsel);
cgroup__put(evsel->cgrp);
- cpu_map__put(evsel->cpus);
- cpu_map__put(evsel->own_cpus);
- thread_map__put(evsel->threads);
+ perf_cpu_map__put(evsel->core.cpus);
+ perf_cpu_map__put(evsel->core.own_cpus);
+ perf_thread_map__put(evsel->core.threads);
zfree(&evsel->group_name);
zfree(&evsel->name);
perf_evsel__object.fini(evsel);
}
-void perf_evsel__delete(struct perf_evsel *evsel)
+void evsel__delete(struct evsel *evsel)
{
perf_evsel__exit(evsel);
free(evsel);
}
-void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread,
+void perf_evsel__compute_deltas(struct evsel *evsel, int cpu, int thread,
struct perf_counts_values *count)
{
struct perf_counts_values tmp;
@@ -1377,57 +1329,16 @@ void perf_counts_values__scale(struct perf_counts_values *count,
*pscaled = scaled;
}
-static int perf_evsel__read_size(struct perf_evsel *evsel)
-{
- u64 read_format = evsel->attr.read_format;
- int entry = sizeof(u64); /* value */
- int size = 0;
- int nr = 1;
-
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
- size += sizeof(u64);
-
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
- size += sizeof(u64);
-
- if (read_format & PERF_FORMAT_ID)
- entry += sizeof(u64);
-
- if (read_format & PERF_FORMAT_GROUP) {
- nr = evsel->nr_members;
- size += sizeof(u64);
- }
-
- size += entry * nr;
- return size;
-}
-
-int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
- struct perf_counts_values *count)
-{
- size_t size = perf_evsel__read_size(evsel);
-
- memset(count, 0, sizeof(*count));
-
- if (FD(evsel, cpu, thread) < 0)
- return -EINVAL;
-
- if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
- return -errno;
-
- return 0;
-}
-
static int
-perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread)
+perf_evsel__read_one(struct evsel *evsel, int cpu, int thread)
{
struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
- return perf_evsel__read(evsel, cpu, thread, count);
+ return perf_evsel__read(&evsel->core, cpu, thread, count);
}
static void
-perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
+perf_evsel__set_count(struct evsel *counter, int cpu, int thread,
u64 val, u64 ena, u64 run)
{
struct perf_counts_values *count;
@@ -1437,20 +1348,21 @@ perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
count->val = val;
count->ena = ena;
count->run = run;
- count->loaded = true;
+
+ perf_counts__set_loaded(counter->counts, cpu, thread, true);
}
static int
-perf_evsel__process_group_data(struct perf_evsel *leader,
+perf_evsel__process_group_data(struct evsel *leader,
int cpu, int thread, u64 *data)
{
- u64 read_format = leader->attr.read_format;
+ u64 read_format = leader->core.attr.read_format;
struct sample_read_value *v;
u64 nr, ena = 0, run = 0, i;
nr = *data++;
- if (nr != (u64) leader->nr_members)
+ if (nr != (u64) leader->core.nr_members)
return -EINVAL;
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -1465,7 +1377,7 @@ perf_evsel__process_group_data(struct perf_evsel *leader,
v[0].value, ena, run);
for (i = 1; i < nr; i++) {
- struct perf_evsel *counter;
+ struct evsel *counter;
counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
if (!counter)
@@ -1479,11 +1391,11 @@ perf_evsel__process_group_data(struct perf_evsel *leader,
}
static int
-perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
+perf_evsel__read_group(struct evsel *leader, int cpu, int thread)
{
struct perf_stat_evsel *ps = leader->stats;
- u64 read_format = leader->attr.read_format;
- int size = perf_evsel__read_size(leader);
+ u64 read_format = leader->core.attr.read_format;
+ int size = perf_evsel__read_size(&leader->core);
u64 *data = ps->group_data;
if (!(read_format & PERF_FORMAT_ID))
@@ -1509,9 +1421,9 @@ perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
return perf_evsel__process_group_data(leader, cpu, thread, data);
}
-int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
+int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread)
{
- u64 read_format = evsel->attr.read_format;
+ u64 read_format = evsel->core.attr.read_format;
if (read_format & PERF_FORMAT_GROUP)
return perf_evsel__read_group(evsel, cpu, thread);
@@ -1519,7 +1431,7 @@ int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
return perf_evsel__read_one(evsel, cpu, thread);
}
-int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+int __perf_evsel__read_on_cpu(struct evsel *evsel,
int cpu, int thread, bool scale)
{
struct perf_counts_values count;
@@ -1540,9 +1452,9 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
return 0;
}
-static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
+static int get_group_fd(struct evsel *evsel, int cpu, int thread)
{
- struct perf_evsel *leader = evsel->leader;
+ struct evsel *leader = evsel->leader;
int fd;
if (perf_evsel__is_group_leader(evsel))
@@ -1552,7 +1464,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
* Leader must be already processed/open,
* if not it's a bug.
*/
- BUG_ON(!leader->fd);
+ BUG_ON(!leader->core.fd);
fd = FD(leader, cpu, thread);
BUG_ON(fd == -1);
@@ -1683,6 +1595,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
PRINT_ATTRf(namespaces, p_unsigned);
PRINT_ATTRf(ksymbol, p_unsigned);
PRINT_ATTRf(bpf_event, p_unsigned);
+ PRINT_ATTRf(aux_output, p_unsigned);
PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
PRINT_ATTRf(bp_type, p_unsigned);
@@ -1705,7 +1618,7 @@ static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
return fprintf(fp, " %-32s %s\n", name, val);
}
-static void perf_evsel__remove_fd(struct perf_evsel *pos,
+static void perf_evsel__remove_fd(struct evsel *pos,
int nr_cpus, int nr_threads,
int thread_idx)
{
@@ -1714,11 +1627,11 @@ static void perf_evsel__remove_fd(struct perf_evsel *pos,
FD(pos, cpu, thread) = FD(pos, cpu, thread + 1);
}
-static int update_fds(struct perf_evsel *evsel,
+static int update_fds(struct evsel *evsel,
int nr_cpus, int cpu_idx,
int nr_threads, int thread_idx)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
if (cpu_idx >= nr_cpus || thread_idx >= nr_threads)
return -EINVAL;
@@ -1738,12 +1651,12 @@ static int update_fds(struct perf_evsel *evsel,
return 0;
}
-static bool ignore_missing_thread(struct perf_evsel *evsel,
+static bool ignore_missing_thread(struct evsel *evsel,
int nr_cpus, int cpu,
- struct thread_map *threads,
+ struct perf_thread_map *threads,
int thread, int err)
{
- pid_t ignore_pid = thread_map__pid(threads, thread);
+ pid_t ignore_pid = perf_thread_map__pid(threads, thread);
if (!evsel->ignore_missing_thread)
return false;
@@ -1785,18 +1698,18 @@ static void display_attr(struct perf_event_attr *attr)
}
}
-static int perf_event_open(struct perf_evsel *evsel,
+static int perf_event_open(struct evsel *evsel,
pid_t pid, int cpu, int group_fd,
unsigned long flags)
{
- int precise_ip = evsel->attr.precise_ip;
+ int precise_ip = evsel->core.attr.precise_ip;
int fd;
while (1) {
pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
pid, cpu, group_fd, flags);
- fd = sys_perf_event_open(&evsel->attr, pid, cpu, group_fd, flags);
+ fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags);
if (fd >= 0)
break;
@@ -1808,36 +1721,37 @@ static int perf_event_open(struct perf_evsel *evsel,
* We tried all the precise_ip values, and it's
* still failing, so leave it to standard fallback.
*/
- if (!evsel->attr.precise_ip) {
- evsel->attr.precise_ip = precise_ip;
+ if (!evsel->core.attr.precise_ip) {
+ evsel->core.attr.precise_ip = precise_ip;
break;
}
pr_debug2("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
- evsel->attr.precise_ip--;
- pr_debug2("decreasing precise_ip by one (%d)\n", evsel->attr.precise_ip);
- display_attr(&evsel->attr);
+ evsel->core.attr.precise_ip--;
+ pr_debug2("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
+ display_attr(&evsel->core.attr);
}
return fd;
}
-int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads)
+int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
{
int cpu, thread, nthreads;
unsigned long flags = PERF_FLAG_FD_CLOEXEC;
int pid = -1, err;
enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
- if (perf_missing_features.write_backward && evsel->attr.write_backward)
+ if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) ||
+ (perf_missing_features.aux_output && evsel->core.attr.aux_output))
return -EINVAL;
if (cpus == NULL) {
- static struct cpu_map *empty_cpu_map;
+ static struct perf_cpu_map *empty_cpu_map;
if (empty_cpu_map == NULL) {
- empty_cpu_map = cpu_map__dummy_new();
+ empty_cpu_map = perf_cpu_map__dummy_new();
if (empty_cpu_map == NULL)
return -ENOMEM;
}
@@ -1846,7 +1760,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
}
if (threads == NULL) {
- static struct thread_map *empty_thread_map;
+ static struct perf_thread_map *empty_thread_map;
if (empty_thread_map == NULL) {
empty_thread_map = thread_map__new_by_tid(-1);
@@ -1862,8 +1776,8 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
else
nthreads = threads->nr;
- if (evsel->fd == NULL &&
- perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
+ if (evsel->core.fd == NULL &&
+ perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0)
return -ENOMEM;
if (evsel->cgrp) {
@@ -1873,31 +1787,31 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
fallback_missing_features:
if (perf_missing_features.clockid_wrong)
- evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */
+ evsel->core.attr.clockid = CLOCK_MONOTONIC; /* should always work */
if (perf_missing_features.clockid) {
- evsel->attr.use_clockid = 0;
- evsel->attr.clockid = 0;
+ evsel->core.attr.use_clockid = 0;
+ evsel->core.attr.clockid = 0;
}
if (perf_missing_features.cloexec)
flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
if (perf_missing_features.mmap2)
- evsel->attr.mmap2 = 0;
+ evsel->core.attr.mmap2 = 0;
if (perf_missing_features.exclude_guest)
- evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
+ evsel->core.attr.exclude_guest = evsel->core.attr.exclude_host = 0;
if (perf_missing_features.lbr_flags)
- evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
+ evsel->core.attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
PERF_SAMPLE_BRANCH_NO_CYCLES);
- if (perf_missing_features.group_read && evsel->attr.inherit)
- evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
+ if (perf_missing_features.group_read && evsel->core.attr.inherit)
+ evsel->core.attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
if (perf_missing_features.ksymbol)
- evsel->attr.ksymbol = 0;
- if (perf_missing_features.bpf_event)
- evsel->attr.bpf_event = 0;
+ evsel->core.attr.ksymbol = 0;
+ if (perf_missing_features.bpf)
+ evsel->core.attr.bpf_event = 0;
retry_sample_id:
if (perf_missing_features.sample_id_all)
- evsel->attr.sample_id_all = 0;
+ evsel->core.attr.sample_id_all = 0;
- display_attr(&evsel->attr);
+ display_attr(&evsel->core.attr);
for (cpu = 0; cpu < cpus->nr; cpu++) {
@@ -1905,7 +1819,7 @@ retry_sample_id:
int fd, group_fd;
if (!evsel->cgrp && !evsel->system_wide)
- pid = thread_map__pid(threads, thread);
+ pid = perf_thread_map__pid(threads, thread);
group_fd = get_group_fd(evsel, cpu, thread);
retry_open:
@@ -2004,23 +1918,27 @@ try_fallback:
* Must probe features in the order they were added to the
* perf_event_attr interface.
*/
- if (!perf_missing_features.bpf_event && evsel->attr.bpf_event) {
- perf_missing_features.bpf_event = true;
+ if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
+ perf_missing_features.aux_output = true;
+ pr_debug2("Kernel has no attr.aux_output support, bailing out\n");
+ goto out_close;
+ } else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) {
+ perf_missing_features.bpf = true;
pr_debug2("switching off bpf_event\n");
goto fallback_missing_features;
- } else if (!perf_missing_features.ksymbol && evsel->attr.ksymbol) {
+ } else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) {
perf_missing_features.ksymbol = true;
pr_debug2("switching off ksymbol\n");
goto fallback_missing_features;
- } else if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
+ } else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) {
perf_missing_features.write_backward = true;
pr_debug2("switching off write_backward\n");
goto out_close;
- } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
+ } else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) {
perf_missing_features.clockid_wrong = true;
pr_debug2("switching off clockid\n");
goto fallback_missing_features;
- } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
+ } else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) {
perf_missing_features.clockid = true;
pr_debug2("switching off use_clockid\n");
goto fallback_missing_features;
@@ -2028,12 +1946,12 @@ try_fallback:
perf_missing_features.cloexec = true;
pr_debug2("switching off cloexec flag\n");
goto fallback_missing_features;
- } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
+ } else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) {
perf_missing_features.mmap2 = true;
pr_debug2("switching off mmap2\n");
goto fallback_missing_features;
} else if (!perf_missing_features.exclude_guest &&
- (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+ (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
perf_missing_features.exclude_guest = true;
pr_debug2("switching off exclude_guest, exclude_host\n");
goto fallback_missing_features;
@@ -2042,15 +1960,15 @@ try_fallback:
pr_debug2("switching off sample_id_all\n");
goto retry_sample_id;
} else if (!perf_missing_features.lbr_flags &&
- (evsel->attr.branch_sample_type &
+ (evsel->core.attr.branch_sample_type &
(PERF_SAMPLE_BRANCH_NO_CYCLES |
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
perf_missing_features.lbr_flags = true;
pr_debug2("switching off branch sample type no (cycles/flags)\n");
goto fallback_missing_features;
} else if (!perf_missing_features.group_read &&
- evsel->attr.inherit &&
- (evsel->attr.read_format & PERF_FORMAT_GROUP) &&
+ evsel->core.attr.inherit &&
+ (evsel->core.attr.read_format & PERF_FORMAT_GROUP) &&
perf_evsel__is_group_leader(evsel)) {
perf_missing_features.group_read = true;
pr_debug2("switching off group read\n");
@@ -2070,33 +1988,30 @@ out_close:
return err;
}
-void perf_evsel__close(struct perf_evsel *evsel)
+void evsel__close(struct evsel *evsel)
{
- if (evsel->fd == NULL)
- return;
-
- perf_evsel__close_fd(evsel);
- perf_evsel__free_fd(evsel);
+ perf_evsel__close(&evsel->core);
+ perf_evsel__free_id(evsel);
}
-int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus)
+int perf_evsel__open_per_cpu(struct evsel *evsel,
+ struct perf_cpu_map *cpus)
{
- return perf_evsel__open(evsel, cpus, NULL);
+ return evsel__open(evsel, cpus, NULL);
}
-int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads)
+int perf_evsel__open_per_thread(struct evsel *evsel,
+ struct perf_thread_map *threads)
{
- return perf_evsel__open(evsel, NULL, threads);
+ return evsel__open(evsel, NULL, threads);
}
-static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
+static int perf_evsel__parse_id_sample(const struct evsel *evsel,
const union perf_event *event,
struct perf_sample *sample)
{
- u64 type = evsel->attr.sample_type;
- const u64 *array = event->sample.array;
+ u64 type = evsel->core.attr.sample_type;
+ const __u64 *array = event->sample.array;
bool swapped = evsel->needs_swap;
union u64_swap u;
@@ -2181,12 +2096,12 @@ perf_event__check_size(union perf_event *event, unsigned int sample_size)
return 0;
}
-int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
+int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event,
struct perf_sample *data)
{
- u64 type = evsel->attr.sample_type;
+ u64 type = evsel->core.attr.sample_type;
bool swapped = evsel->needs_swap;
- const u64 *array;
+ const __u64 *array;
u16 max_size = event->header.size;
const void *endp = (void *)event + max_size;
u64 sz;
@@ -2200,14 +2115,14 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
memset(data, 0, sizeof(*data));
data->cpu = data->pid = data->tid = -1;
data->stream_id = data->id = data->time = -1ULL;
- data->period = evsel->attr.sample_period;
+ data->period = evsel->core.attr.sample_period;
data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
data->misc = event->header.misc;
data->id = -1ULL;
data->data_src = PERF_MEM_DATA_SRC_NONE;
if (event->header.type != PERF_RECORD_SAMPLE) {
- if (!evsel->attr.sample_id_all)
+ if (!evsel->core.attr.sample_id_all)
return 0;
return perf_evsel__parse_id_sample(evsel, event, data);
}
@@ -2280,7 +2195,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
}
if (type & PERF_SAMPLE_READ) {
- u64 read_format = evsel->attr.read_format;
+ u64 read_format = evsel->core.attr.read_format;
OVERFLOW_CHECK_u64(array);
if (read_format & PERF_FORMAT_GROUP)
@@ -2385,7 +2300,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
if (data->user_regs.abi) {
- u64 mask = evsel->attr.sample_regs_user;
+ u64 mask = evsel->core.attr.sample_regs_user;
sz = hweight64(mask) * sizeof(u64);
OVERFLOW_CHECK(array, sz, max_size);
@@ -2441,7 +2356,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
- u64 mask = evsel->attr.sample_regs_intr;
+ u64 mask = evsel->core.attr.sample_regs_intr;
sz = hweight64(mask) * sizeof(u64);
OVERFLOW_CHECK(array, sz, max_size);
@@ -2460,12 +2375,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
return 0;
}
-int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
+int perf_evsel__parse_sample_timestamp(struct evsel *evsel,
union perf_event *event,
u64 *timestamp)
{
- u64 type = evsel->attr.sample_type;
- const u64 *array;
+ u64 type = evsel->core.attr.sample_type;
+ const __u64 *array;
if (!(type & PERF_SAMPLE_TIME))
return -1;
@@ -2475,7 +2390,7 @@ int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
.time = -1ULL,
};
- if (!evsel->attr.sample_id_all)
+ if (!evsel->core.attr.sample_id_all)
return -1;
if (perf_evsel__parse_id_sample(evsel, event, &data))
return -1;
@@ -2507,7 +2422,7 @@ int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 read_format)
{
- size_t sz, result = sizeof(struct sample_event);
+ size_t sz, result = sizeof(struct perf_record_sample);
if (type & PERF_SAMPLE_IDENTIFIER)
result += sizeof(u64);
@@ -2616,7 +2531,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
u64 read_format,
const struct perf_sample *sample)
{
- u64 *array;
+ __u64 *array;
size_t sz;
/*
* used for cross-endian analysis. See git commit 65014ab3
@@ -2781,12 +2696,12 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
return 0;
}
-struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
+struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name)
{
return tep_find_field(evsel->tp_format, name);
}
-void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
+void *perf_evsel__rawptr(struct evsel *evsel, struct perf_sample *sample,
const char *name)
{
struct tep_format_field *field = perf_evsel__field(evsel, name);
@@ -2844,7 +2759,7 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam
return 0;
}
-u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
+u64 perf_evsel__intval(struct evsel *evsel, struct perf_sample *sample,
const char *name)
{
struct tep_format_field *field = perf_evsel__field(evsel, name);
@@ -2855,14 +2770,14 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
return field ? format_field__intval(field, sample, evsel->needs_swap) : 0;
}
-bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
+bool perf_evsel__fallback(struct evsel *evsel, int err,
char *msg, size_t msgsize)
{
int paranoid;
if ((err == ENOENT || err == ENXIO || err == ENODEV) &&
- evsel->attr.type == PERF_TYPE_HARDWARE &&
- evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) {
+ evsel->core.attr.type == PERF_TYPE_HARDWARE &&
+ evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES) {
/*
* If it's cycles then fall back to hrtimer based
* cpu-clock-tick sw counter, which is always available even if
@@ -2874,12 +2789,12 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
scnprintf(msg, msgsize, "%s",
"The cycles event is not supported, trying to fall back to cpu-clock-ticks");
- evsel->attr.type = PERF_TYPE_SOFTWARE;
- evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
+ evsel->core.attr.type = PERF_TYPE_SOFTWARE;
+ evsel->core.attr.config = PERF_COUNT_SW_CPU_CLOCK;
zfree(&evsel->name);
return true;
- } else if (err == EACCES && !evsel->attr.exclude_kernel &&
+ } else if (err == EACCES && !evsel->core.attr.exclude_kernel &&
(paranoid = perf_event_paranoid()) > 1) {
const char *name = perf_evsel__name(evsel);
char *new_name;
@@ -2898,7 +2813,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
evsel->name = new_name;
scnprintf(msg, msgsize,
"kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples", paranoid);
- evsel->attr.exclude_kernel = 1;
+ evsel->core.attr.exclude_kernel = 1;
return true;
}
@@ -2942,7 +2857,7 @@ static bool find_process(const char *name)
return ret ? false : true;
}
-int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
+int perf_evsel__open_strerror(struct evsel *evsel, struct target *target,
int err, char *msg, size_t size)
{
char sbuf[STRERR_BUFSIZE];
@@ -2995,15 +2910,15 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
"No such device - did you specify an out-of-range profile CPU?");
break;
case EOPNOTSUPP:
- if (evsel->attr.sample_period != 0)
+ if (evsel->core.attr.sample_period != 0)
return scnprintf(msg, size,
"%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'",
perf_evsel__name(evsel));
- if (evsel->attr.precise_ip)
+ if (evsel->core.attr.precise_ip)
return scnprintf(msg, size, "%s",
"\'precise\' request may not be supported. Try removing 'p' modifier.");
#if defined(__i386__) || defined(__x86_64__)
- if (evsel->attr.type == PERF_TYPE_HARDWARE)
+ if (evsel->core.attr.type == PERF_TYPE_HARDWARE)
return scnprintf(msg, size, "%s",
"No hardware sampling interrupt available.\n");
#endif
@@ -3015,12 +2930,14 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
"We found oprofile daemon running, please stop it and try again.");
break;
case EINVAL:
- if (evsel->attr.write_backward && perf_missing_features.write_backward)
+ if (evsel->core.attr.write_backward && perf_missing_features.write_backward)
return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
if (perf_missing_features.clockid)
return scnprintf(msg, size, "clockid feature not supported.");
if (perf_missing_features.clockid_wrong)
return scnprintf(msg, size, "wrong clockid (%d).", clockid);
+ if (perf_missing_features.aux_output)
+ return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel.");
break;
default:
break;
@@ -3033,19 +2950,19 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
perf_evsel__name(evsel));
}
-struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
+struct perf_env *perf_evsel__env(struct evsel *evsel)
{
if (evsel && evsel->evlist)
return evsel->evlist->env;
return NULL;
}
-static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist)
{
int cpu, thread;
- for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
- for (thread = 0; thread < xyarray__max_y(evsel->fd);
+ for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) {
+ for (thread = 0; thread < xyarray__max_y(evsel->core.fd);
thread++) {
int fd = FD(evsel, cpu, thread);
@@ -3058,10 +2975,10 @@ static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
return 0;
}
-int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist)
{
- struct cpu_map *cpus = evsel->cpus;
- struct thread_map *threads = evsel->threads;
+ struct perf_cpu_map *cpus = evsel->core.cpus;
+ struct perf_thread_map *threads = evsel->core.threads;
if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
return -ENOMEM;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index cad54e8ba522..68321d10eb2d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -4,15 +4,18 @@
#include <linux/list.h>
#include <stdbool.h>
-#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
#include <linux/perf_event.h>
#include <linux/types.h>
-#include "xyarray.h"
+#include <internal/evsel.h>
+#include <perf/evsel.h>
#include "symbol_conf.h"
-#include "cpumap.h"
-#include "counts.h"
+#include <internal/cpumap.h>
-struct perf_evsel;
+struct addr_location;
+struct evsel;
+union perf_event;
/*
* Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
@@ -21,7 +24,14 @@ struct perf_evsel;
struct perf_sample_id {
struct hlist_node node;
u64 id;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
+ /*
+ * 'idx' will be used for AUX area sampling. A sample will have AUX area
+ * data that will be queued for decoding, where there are separate
+ * queues for each CPU (per-cpu tracing) or task (per-thread tracing).
+ * The sample ID can be used to lookup 'idx' which is effectively the
+ * queue number.
+ */
int idx;
int cpu;
pid_t tid;
@@ -51,6 +61,7 @@ enum term_type {
PERF_EVSEL__CONFIG_TERM_DRV_CFG,
PERF_EVSEL__CONFIG_TERM_BRANCH,
PERF_EVSEL__CONFIG_TERM_PERCORE,
+ PERF_EVSEL__CONFIG_TERM_AUX_OUTPUT,
};
struct perf_evsel_config_term {
@@ -69,6 +80,7 @@ struct perf_evsel_config_term {
char *branch;
unsigned long max_events;
bool percore;
+ bool aux_output;
} val;
bool weak;
};
@@ -82,28 +94,29 @@ enum perf_tool_event {
PERF_TOOL_DURATION_TIME = 1,
};
-/** struct perf_evsel - event selector
+struct bpf_object;
+struct perf_counts;
+struct xyarray;
+
+/** struct evsel - event selector
*
* @evlist - evlist this evsel is in, if it is in one.
- * @node - To insert it into evlist->entries or in other list_heads, say in
- * the event parsing routines.
+ * @core - libperf evsel object
* @name - Can be set to retain the original event name passed by the user,
* so that when showing results in tools such as 'perf stat', we
* show the name used, not some alias.
* @id_pos: the position of the event id (PERF_SAMPLE_ID or
* PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of
- * struct sample_event
+ * struct perf_record_sample
* @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
* PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
* is used there is an id sample appended to non-sample events
* @priv: And what is in its containing unnamed union are tool specific
*/
-struct perf_evsel {
- struct list_head node;
- struct perf_evlist *evlist;
- struct perf_event_attr attr;
+struct evsel {
+ struct perf_evsel core;
+ struct evlist *evlist;
char *filter;
- struct xyarray *fd;
struct xyarray *sample_id;
u64 *id;
struct perf_counts *counts;
@@ -122,9 +135,6 @@ struct perf_evsel {
u64 db_id;
struct cgroup *cgrp;
void *handler;
- struct cpu_map *cpus;
- struct cpu_map *own_cpus;
- struct thread_map *threads;
unsigned int sample_size;
int id_pos;
int is_pos;
@@ -145,19 +155,20 @@ struct perf_evsel {
bool use_uncore_alias;
/* parse modifier helper */
int exclude_GH;
- int nr_members;
int sample_read;
unsigned long *per_pkg_mask;
- struct perf_evsel *leader;
+ struct evsel *leader;
char *group_name;
bool cmdline_group_boundary;
struct list_head config_terms;
+ struct bpf_object *bpf_obj;
int bpf_fd;
bool auto_merge_stats;
bool merged_stat;
const char * metric_expr;
const char * metric_name;
- struct perf_evsel **metric_events;
+ struct evsel **metric_events;
+ struct evsel *metric_leader;
bool collect_stat;
bool weak_group;
bool percore;
@@ -184,73 +195,73 @@ struct perf_missing_features {
bool write_backward;
bool group_read;
bool ksymbol;
- bool bpf_event;
+ bool bpf;
+ bool aux_output;
};
extern struct perf_missing_features perf_missing_features;
-struct cpu_map;
+struct perf_cpu_map;
struct target;
struct thread_map;
struct record_opts;
-static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+static inline struct perf_cpu_map *evsel__cpus(struct evsel *evsel)
{
- return evsel->cpus;
+ return perf_evsel__cpus(&evsel->core);
}
-static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
+static inline int perf_evsel__nr_cpus(struct evsel *evsel)
{
- return perf_evsel__cpus(evsel)->nr;
+ return evsel__cpus(evsel)->nr;
}
void perf_counts_values__scale(struct perf_counts_values *count,
bool scale, s8 *pscaled);
-void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread,
+void perf_evsel__compute_deltas(struct evsel *evsel, int cpu, int thread,
struct perf_counts_values *count);
int perf_evsel__object_config(size_t object_size,
- int (*init)(struct perf_evsel *evsel),
- void (*fini)(struct perf_evsel *evsel));
+ int (*init)(struct evsel *evsel),
+ void (*fini)(struct evsel *evsel));
-struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
+struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
-static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
+static inline struct evsel *evsel__new(struct perf_event_attr *attr)
{
return perf_evsel__new_idx(attr, 0);
}
-struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);
+struct evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
-static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
+static inline struct evsel *perf_evsel__newtp(const char *sys, const char *name)
{
return perf_evsel__newtp_idx(sys, name, 0);
}
-struct perf_evsel *perf_evsel__new_cycles(bool precise);
+struct evsel *perf_evsel__new_cycles(bool precise);
struct tep_event *event_format__new(const char *sys, const char *name);
-void perf_evsel__init(struct perf_evsel *evsel,
- struct perf_event_attr *attr, int idx);
-void perf_evsel__exit(struct perf_evsel *evsel);
-void perf_evsel__delete(struct perf_evsel *evsel);
+void evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx);
+void perf_evsel__exit(struct evsel *evsel);
+void evsel__delete(struct evsel *evsel);
struct callchain_param;
-void perf_evsel__config(struct perf_evsel *evsel,
+void perf_evsel__config(struct evsel *evsel,
struct record_opts *opts,
struct callchain_param *callchain);
-void perf_evsel__config_callchain(struct perf_evsel *evsel,
+void perf_evsel__config_callchain(struct evsel *evsel,
struct record_opts *opts,
struct callchain_param *callchain);
int __perf_evsel__sample_size(u64 sample_type);
-void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
+void perf_evsel__calc_id_pos(struct evsel *evsel);
bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
@@ -266,17 +277,16 @@ extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX];
extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
char *bf, size_t size);
-const char *perf_evsel__name(struct perf_evsel *evsel);
+const char *perf_evsel__name(struct evsel *evsel);
-const char *perf_evsel__group_name(struct perf_evsel *evsel);
-int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
+const char *perf_evsel__group_name(struct evsel *evsel);
+int perf_evsel__group_desc(struct evsel *evsel, char *buf, size_t size);
-int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
-void perf_evsel__close_fd(struct perf_evsel *evsel);
+int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads);
-void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+void __perf_evsel__set_sample_bit(struct evsel *evsel,
enum perf_event_sample_format bit);
-void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+void __perf_evsel__reset_sample_bit(struct evsel *evsel,
enum perf_event_sample_format bit);
#define perf_evsel__set_sample_bit(evsel, bit) \
@@ -285,33 +295,32 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
#define perf_evsel__reset_sample_bit(evsel, bit) \
__perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)
-void perf_evsel__set_sample_id(struct perf_evsel *evsel,
+void perf_evsel__set_sample_id(struct evsel *evsel,
bool use_sample_identifier);
-int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
-int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
-int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
+int perf_evsel__set_filter(struct evsel *evsel, const char *filter);
+int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter);
+int perf_evsel__append_addr_filter(struct evsel *evsel,
const char *filter);
-int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter);
-int perf_evsel__enable(struct perf_evsel *evsel);
-int perf_evsel__disable(struct perf_evsel *evsel);
-
-int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus);
-int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads);
-int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads);
-void perf_evsel__close(struct perf_evsel *evsel);
+int evsel__enable(struct evsel *evsel);
+int evsel__disable(struct evsel *evsel);
+
+int perf_evsel__open_per_cpu(struct evsel *evsel,
+ struct perf_cpu_map *cpus);
+int perf_evsel__open_per_thread(struct evsel *evsel,
+ struct perf_thread_map *threads);
+int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads);
+void evsel__close(struct evsel *evsel);
struct perf_sample;
-void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
+void *perf_evsel__rawptr(struct evsel *evsel, struct perf_sample *sample,
const char *name);
-u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
+u64 perf_evsel__intval(struct evsel *evsel, struct perf_sample *sample,
const char *name);
-static inline char *perf_evsel__strval(struct perf_evsel *evsel,
+static inline char *perf_evsel__strval(struct evsel *evsel,
struct perf_sample *sample,
const char *name)
{
@@ -322,31 +331,28 @@ struct tep_format_field;
u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap);
-struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
+struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name);
#define perf_evsel__match(evsel, t, c) \
- (evsel->attr.type == PERF_TYPE_##t && \
- evsel->attr.config == PERF_COUNT_##c)
+ (evsel->core.attr.type == PERF_TYPE_##t && \
+ evsel->core.attr.config == PERF_COUNT_##c)
-static inline bool perf_evsel__match2(struct perf_evsel *e1,
- struct perf_evsel *e2)
+static inline bool perf_evsel__match2(struct evsel *e1,
+ struct evsel *e2)
{
- return (e1->attr.type == e2->attr.type) &&
- (e1->attr.config == e2->attr.config);
+ return (e1->core.attr.type == e2->core.attr.type) &&
+ (e1->core.attr.config == e2->core.attr.config);
}
#define perf_evsel__cmp(a, b) \
((a) && \
(b) && \
- (a)->attr.type == (b)->attr.type && \
- (a)->attr.config == (b)->attr.config)
-
-int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
- struct perf_counts_values *count);
+ (a)->core.attr.type == (b)->core.attr.type && \
+ (a)->core.attr.config == (b)->core.attr.config)
-int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread);
+int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread);
-int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+int __perf_evsel__read_on_cpu(struct evsel *evsel,
int cpu, int thread, bool scale);
/**
@@ -356,7 +362,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
* @cpu - CPU of interest
* @thread - thread of interest
*/
-static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+static inline int perf_evsel__read_on_cpu(struct evsel *evsel,
int cpu, int thread)
{
return __perf_evsel__read_on_cpu(evsel, cpu, thread, false);
@@ -369,27 +375,27 @@ static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
* @cpu - CPU of interest
* @thread - thread of interest
*/
-static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
+static inline int perf_evsel__read_on_cpu_scaled(struct evsel *evsel,
int cpu, int thread)
{
return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
}
-int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
+int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event,
struct perf_sample *sample);
-int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
+int perf_evsel__parse_sample_timestamp(struct evsel *evsel,
union perf_event *event,
u64 *timestamp);
-static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
+static inline struct evsel *perf_evsel__next(struct evsel *evsel)
{
- return list_entry(evsel->node.next, struct perf_evsel, node);
+ return list_entry(evsel->core.node.next, struct evsel, core.node);
}
-static inline struct perf_evsel *perf_evsel__prev(struct perf_evsel *evsel)
+static inline struct evsel *perf_evsel__prev(struct evsel *evsel)
{
- return list_entry(evsel->node.prev, struct perf_evsel, node);
+ return list_entry(evsel->core.node.prev, struct evsel, core.node);
}
/**
@@ -399,7 +405,7 @@ static inline struct perf_evsel *perf_evsel__prev(struct perf_evsel *evsel)
*
* Return %true if @evsel is a group leader or a stand-alone event
*/
-static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
+static inline bool perf_evsel__is_group_leader(const struct evsel *evsel)
{
return evsel->leader == evsel;
}
@@ -412,22 +418,22 @@ static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
* Return %true iff event group view is enabled and @evsel is a actual group
* leader which has other members in the group
*/
-static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel)
+static inline bool perf_evsel__is_group_event(struct evsel *evsel)
{
if (!symbol_conf.event_group)
return false;
- return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1;
+ return perf_evsel__is_group_leader(evsel) && evsel->core.nr_members > 1;
}
-bool perf_evsel__is_function_event(struct perf_evsel *evsel);
+bool perf_evsel__is_function_event(struct evsel *evsel);
-static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
+static inline bool perf_evsel__is_bpf_output(struct evsel *evsel)
{
return perf_evsel__match(evsel, SOFTWARE, SW_BPF_OUTPUT);
}
-static inline bool perf_evsel__is_clock(struct perf_evsel *evsel)
+static inline bool perf_evsel__is_clock(struct evsel *evsel)
{
return perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK);
@@ -441,7 +447,7 @@ struct perf_attr_details {
bool trace_fields;
};
-int perf_evsel__fprintf(struct perf_evsel *evsel,
+int perf_evsel__fprintf(struct evsel *evsel,
struct perf_attr_details *details, FILE *fp);
#define EVSEL__PRINT_IP (1<<0)
@@ -464,36 +470,36 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
int left_alignment, unsigned int print_opts,
struct callchain_cursor *cursor, FILE *fp);
-bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
+bool perf_evsel__fallback(struct evsel *evsel, int err,
char *msg, size_t msgsize);
-int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
+int perf_evsel__open_strerror(struct evsel *evsel, struct target *target,
int err, char *msg, size_t size);
-static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
+static inline int perf_evsel__group_idx(struct evsel *evsel)
{
return evsel->idx - evsel->leader->idx;
}
/* Iterates group WITHOUT the leader. */
#define for_each_group_member(_evsel, _leader) \
-for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
+for ((_evsel) = list_entry((_leader)->core.node.next, struct evsel, core.node); \
(_evsel) && (_evsel)->leader == (_leader); \
- (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
+ (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node))
/* Iterates group WITH the leader. */
#define for_each_group_evsel(_evsel, _leader) \
for ((_evsel) = _leader; \
(_evsel) && (_evsel)->leader == (_leader); \
- (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
+ (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node))
-static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
+static inline bool perf_evsel__has_branch_callstack(const struct evsel *evsel)
{
- return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
+ return evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
}
-static inline bool evsel__has_callchain(const struct perf_evsel *evsel)
+static inline bool evsel__has_callchain(const struct evsel *evsel)
{
- return (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0;
+ return (evsel->core.attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0;
}
typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
@@ -501,7 +507,7 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
attr__fprintf_f attr__fprintf, void *priv);
-struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
+struct perf_env *perf_evsel__env(struct evsel *evsel);
-int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
+int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist);
#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 95ea147f9e18..496fec01f5d1 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -33,26 +33,26 @@ static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, vo
return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
}
-int perf_evsel__fprintf(struct perf_evsel *evsel,
+int perf_evsel__fprintf(struct evsel *evsel,
struct perf_attr_details *details, FILE *fp)
{
bool first = true;
int printed = 0;
if (details->event_group) {
- struct perf_evsel *pos;
+ struct evsel *pos;
if (!perf_evsel__is_group_leader(evsel))
return 0;
- if (evsel->nr_members > 1)
+ if (evsel->core.nr_members > 1)
printed += fprintf(fp, "%s{", evsel->group_name ?: "");
printed += fprintf(fp, "%s", perf_evsel__name(evsel));
for_each_group_member(pos, evsel)
printed += fprintf(fp, ",%s", perf_evsel__name(pos));
- if (evsel->nr_members > 1)
+ if (evsel->core.nr_members > 1)
printed += fprintf(fp, "}");
goto out;
}
@@ -60,22 +60,22 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
printed += fprintf(fp, "%s", perf_evsel__name(evsel));
if (details->verbose) {
- printed += perf_event_attr__fprintf(fp, &evsel->attr,
+ printed += perf_event_attr__fprintf(fp, &evsel->core.attr,
__print_attr__fprintf, &first);
} else if (details->freq) {
const char *term = "sample_freq";
- if (!evsel->attr.freq)
+ if (!evsel->core.attr.freq)
term = "sample_period";
printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
- term, (u64)evsel->attr.sample_freq);
+ term, (u64)evsel->core.attr.sample_freq);
}
if (details->trace_fields) {
struct tep_format_field *field;
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
printed += comma_fprintf(fp, &first, " (not a tracepoint)");
goto out;
}
diff --git a/tools/perf/util/evswitch.c b/tools/perf/util/evswitch.c
new file mode 100644
index 000000000000..3ba72f743d3c
--- /dev/null
+++ b/tools/perf/util/evswitch.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+
+#include "evswitch.h"
+#include "evlist.h"
+
+bool evswitch__discard(struct evswitch *evswitch, struct evsel *evsel)
+{
+ if (evswitch->on && evswitch->discarding) {
+ if (evswitch->on != evsel)
+ return true;
+
+ evswitch->discarding = false;
+
+ if (!evswitch->show_on_off_events)
+ return true;
+
+ return false;
+ }
+
+ if (evswitch->off && !evswitch->discarding) {
+ if (evswitch->off != evsel)
+ return false;
+
+ evswitch->discarding = true;
+
+ if (!evswitch->show_on_off_events)
+ return true;
+ }
+
+ return false;
+}
+
+static int evswitch__fprintf_enoent(FILE *fp, const char *evtype, const char *evname)
+{
+ int printed = fprintf(fp, "ERROR: switch-%s event not found (%s)\n", evtype, evname);
+
+ return printed += fprintf(fp, "HINT: use 'perf evlist' to see the available event names\n");
+}
+
+int evswitch__init(struct evswitch *evswitch, struct evlist *evlist, FILE *fp)
+{
+ if (evswitch->on_name) {
+ evswitch->on = perf_evlist__find_evsel_by_str(evlist, evswitch->on_name);
+ if (evswitch->on == NULL) {
+ evswitch__fprintf_enoent(fp, "on", evswitch->on_name);
+ return -ENOENT;
+ }
+ evswitch->discarding = true;
+ }
+
+ if (evswitch->off_name) {
+ evswitch->off = perf_evlist__find_evsel_by_str(evlist, evswitch->off_name);
+ if (evswitch->off == NULL) {
+ evswitch__fprintf_enoent(fp, "off", evswitch->off_name);
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/perf/util/evswitch.h b/tools/perf/util/evswitch.h
new file mode 100644
index 000000000000..fd30460b6218
--- /dev/null
+++ b/tools/perf/util/evswitch.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+#ifndef __PERF_EVSWITCH_H
+#define __PERF_EVSWITCH_H 1
+
+#include <stdbool.h>
+#include <stdio.h>
+
+struct evsel;
+struct evlist;
+
+struct evswitch {
+ struct evsel *on, *off;
+ const char *on_name, *off_name;
+ bool discarding;
+ bool show_on_off_events;
+};
+
+int evswitch__init(struct evswitch *evswitch, struct evlist *evlist, FILE *fp);
+
+bool evswitch__discard(struct evswitch *evswitch, struct evsel *evsel);
+
+#define OPTS_EVSWITCH(evswitch) \
+ OPT_STRING(0, "switch-on", &(evswitch)->on_name, \
+ "event", "Consider events after the ocurrence of this event"), \
+ OPT_STRING(0, "switch-off", &(evswitch)->off_name, \
+ "event", "Stop considering events after the ocurrence of this event"), \
+ OPT_BOOLEAN(0, "show-on-off-events", &(evswitch)->show_on_off_events, \
+ "Show the on/off switch events, used with --switch-on and --switch-off")
+
+#endif /* __PERF_EVSWITCH_H */
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
index 432b8560cf51..f9a20a39b64a 100644
--- a/tools/perf/util/expr.y
+++ b/tools/perf/util/expr.y
@@ -2,9 +2,11 @@
%{
#include "util.h"
#include "util/debug.h"
+#include <stdlib.h> // strtod()
#define IN_EXPR_Y 1
#include "expr.h"
#include "smt.h"
+#include <assert.h>
#include <string.h>
#define MAXIDLEN 256
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
index 7001247ebbd6..f9f18b8b1df9 100644
--- a/tools/perf/util/genelf.c
+++ b/tools/perf/util/genelf.c
@@ -14,6 +14,7 @@
#include <libelf.h>
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
#include <inttypes.h>
#include <limits.h>
#include <fcntl.h>
@@ -22,9 +23,9 @@
#include <dwarf.h>
#endif
-#include "perf.h"
#include "genelf.h"
#include "../util/jitdump.h"
+#include <linux/compiler.h>
#ifndef NT_GNU_BUILD_ID
#define NT_GNU_BUILD_ID 3
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c
index 995e490c17fa..30e9f618f6cd 100644
--- a/tools/perf/util/genelf_debug.c
+++ b/tools/perf/util/genelf_debug.c
@@ -24,7 +24,6 @@
#include <err.h>
#include <dwarf.h>
-#include "perf.h"
#include "genelf.h"
#include "../util/jitdump.h"
diff --git a/tools/perf/util/get_current_dir_name.c b/tools/perf/util/get_current_dir_name.c
index 01f32f26552d..b205d929245f 100644
--- a/tools/perf/util/get_current_dir_name.c
+++ b/tools/perf/util/get_current_dir_name.c
@@ -5,7 +5,6 @@
#include "get_current_dir_name.h"
#include <unistd.h>
#include <stdlib.h>
-#include <stdlib.h>
/* Android's 'bionic' library, for one, doesn't have this */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c24db7f4909c..b0c34dda30a0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -20,12 +20,13 @@
#include <linux/time64.h>
#include <dirent.h>
#include <bpf/libbpf.h>
+#include <perf/cpumap.h>
+#include "dso.h"
#include "evlist.h"
#include "evsel.h"
#include "header.h"
#include "memswap.h"
-#include "../perf.h"
#include "trace-event.h"
#include "session.h"
#include "symbol.h"
@@ -41,6 +42,7 @@
#include "tool.h"
#include "time-utils.h"
#include "units.h"
+#include "util.h"
#include "cputopo.h"
#include "bpf-event.h"
@@ -74,7 +76,7 @@ struct feat_fd {
void *buf; /* Either buf != NULL or fd >= 0 */
ssize_t offset;
size_t size;
- struct perf_evsel *events;
+ struct evsel *events;
};
void perf_header__set_feat(struct perf_header *header, int feat)
@@ -299,16 +301,16 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
}
static int write_tracing_data(struct feat_fd *ff,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
return -1;
- return read_tracing_data(ff->fd, &evlist->entries);
+ return read_tracing_data(ff->fd, &evlist->core.entries);
}
static int write_build_id(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_session *session;
int err;
@@ -332,7 +334,7 @@ static int write_build_id(struct feat_fd *ff,
}
static int write_hostname(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
@@ -345,7 +347,7 @@ static int write_hostname(struct feat_fd *ff,
}
static int write_osrelease(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
@@ -358,7 +360,7 @@ static int write_osrelease(struct feat_fd *ff,
}
static int write_arch(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
@@ -371,7 +373,7 @@ static int write_arch(struct feat_fd *ff,
}
static int write_version(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return do_write_string(ff, perf_version_string);
}
@@ -432,9 +434,27 @@ done:
}
static int write_cpudesc(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
-{
+ struct evlist *evlist __maybe_unused)
+{
+#if defined(__powerpc__) || defined(__hppa__) || defined(__sparc__)
+#define CPUINFO_PROC { "cpu", }
+#elif defined(__s390__)
+#define CPUINFO_PROC { "vendor_id", }
+#elif defined(__sh__)
+#define CPUINFO_PROC { "cpu type", }
+#elif defined(__alpha__) || defined(__mips__)
+#define CPUINFO_PROC { "cpu model", }
+#elif defined(__arm__)
+#define CPUINFO_PROC { "model name", "Processor", }
+#elif defined(__arc__)
+#define CPUINFO_PROC { "Processor", }
+#elif defined(__xtensa__)
+#define CPUINFO_PROC { "core ID", }
+#else
+#define CPUINFO_PROC { "model name", }
+#endif
const char *cpuinfo_procs[] = CPUINFO_PROC;
+#undef CPUINFO_PROC
unsigned int i;
for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
@@ -448,7 +468,7 @@ static int write_cpudesc(struct feat_fd *ff,
static int write_nrcpus(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
long nr;
u32 nrc, nra;
@@ -470,13 +490,13 @@ static int write_nrcpus(struct feat_fd *ff,
}
static int write_event_desc(struct feat_fd *ff,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u32 nre, nri, sz;
int ret;
- nre = evlist->nr_entries;
+ nre = evlist->core.nr_entries;
/*
* write number of events
@@ -488,13 +508,13 @@ static int write_event_desc(struct feat_fd *ff,
/*
* size of perf_event_attr struct
*/
- sz = (u32)sizeof(evsel->attr);
+ sz = (u32)sizeof(evsel->core.attr);
ret = do_write(ff, &sz, sizeof(sz));
if (ret < 0)
return ret;
evlist__for_each_entry(evlist, evsel) {
- ret = do_write(ff, &evsel->attr, sz);
+ ret = do_write(ff, &evsel->core.attr, sz);
if (ret < 0)
return ret;
/*
@@ -526,7 +546,7 @@ static int write_event_desc(struct feat_fd *ff,
}
static int write_cmdline(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
char pbuf[MAXPATHLEN], *buf;
int i, ret, n;
@@ -555,7 +575,7 @@ static int write_cmdline(struct feat_fd *ff,
static int write_cpu_topology(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct cpu_topology *tp;
u32 i;
@@ -627,7 +647,7 @@ done:
static int write_total_mem(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
char *buf = NULL;
FILE *fp;
@@ -656,7 +676,7 @@ static int write_total_mem(struct feat_fd *ff,
}
static int write_numa_topology(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct numa_topology *tp;
int ret = -1;
@@ -710,7 +730,7 @@ err:
*/
static int write_pmu_mappings(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_pmu *pmu = NULL;
u32 pmu_num = 0;
@@ -759,10 +779,10 @@ static int write_pmu_mappings(struct feat_fd *ff,
* };
*/
static int write_group_desc(struct feat_fd *ff,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
u32 nr_groups = evlist->nr_groups;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int ret;
ret = do_write(ff, &nr_groups, sizeof(nr_groups));
@@ -771,10 +791,10 @@ static int write_group_desc(struct feat_fd *ff,
evlist__for_each_entry(evlist, evsel) {
if (perf_evsel__is_group_leader(evsel) &&
- evsel->nr_members > 1) {
+ evsel->core.nr_members > 1) {
const char *name = evsel->group_name ?: "{anon_group}";
u32 leader_idx = evsel->idx;
- u32 nr_members = evsel->nr_members;
+ u32 nr_members = evsel->core.nr_members;
ret = do_write_string(ff, name);
if (ret < 0)
@@ -841,7 +861,7 @@ int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
}
static int write_cpuid(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
char buffer[64];
int ret;
@@ -854,13 +874,13 @@ static int write_cpuid(struct feat_fd *ff,
}
static int write_branch_stack(struct feat_fd *ff __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return 0;
}
static int write_auxtrace(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_session *session;
int err;
@@ -877,14 +897,14 @@ static int write_auxtrace(struct feat_fd *ff,
}
static int write_clockid(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return do_write(ff, &ff->ph->env.clockid_res_ns,
sizeof(ff->ph->env.clockid_res_ns));
}
static int write_dir_format(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_session *session;
struct perf_data *data;
@@ -900,7 +920,7 @@ static int write_dir_format(struct feat_fd *ff,
#ifdef HAVE_LIBBPF_SUPPORT
static int write_bpf_prog_info(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_env *env = &ff->ph->env;
struct rb_root *root;
@@ -942,14 +962,14 @@ out:
}
#else // HAVE_LIBBPF_SUPPORT
static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return 0;
}
#endif // HAVE_LIBBPF_SUPPORT
static int write_bpf_btf(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
struct perf_env *env = &ff->ph->env;
struct rb_root *root;
@@ -1120,16 +1140,17 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
return 0;
}
-#define MAX_CACHES (MAX_NR_CPUS * 4)
+#define MAX_CACHE_LVL 4
static int write_cache(struct feat_fd *ff,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
- struct cpu_cache_level caches[MAX_CACHES];
+ u32 max_caches = cpu__max_cpu() * MAX_CACHE_LVL;
+ struct cpu_cache_level caches[max_caches];
u32 cnt = 0, i, version = 1;
int ret;
- ret = build_caches(caches, MAX_CACHES, &cnt);
+ ret = build_caches(caches, max_caches, &cnt);
if (ret)
goto out;
@@ -1175,13 +1196,13 @@ out:
}
static int write_stat(struct feat_fd *ff __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
return 0;
}
static int write_sample_time(struct feat_fd *ff,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
int ret;
@@ -1315,7 +1336,7 @@ static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp)
* 48 - bitmap | bitmap of memory indexes that belongs to node
*/
static int write_mem_topology(struct feat_fd *ff __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
static struct memory_node nodes[MAX_MEMORY_NODES];
u64 bsize, version = 1, i, nr;
@@ -1365,7 +1386,7 @@ out:
}
static int write_compressed(struct feat_fd *ff __maybe_unused,
- struct perf_evlist *evlist __maybe_unused)
+ struct evlist *evlist __maybe_unused)
{
int ret;
@@ -1568,14 +1589,14 @@ static void print_bpf_btf(struct feat_fd *ff, FILE *fp)
up_read(&env->bpf_progs.lock);
}
-static void free_event_desc(struct perf_evsel *events)
+static void free_event_desc(struct evsel *events)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (!events)
return;
- for (evsel = events; evsel->attr.size; evsel++) {
+ for (evsel = events; evsel->core.attr.size; evsel++) {
zfree(&evsel->name);
zfree(&evsel->id);
}
@@ -1583,9 +1604,9 @@ static void free_event_desc(struct perf_evsel *events)
free(events);
}
-static struct perf_evsel *read_event_desc(struct feat_fd *ff)
+static struct evsel *read_event_desc(struct feat_fd *ff)
{
- struct perf_evsel *evsel, *events = NULL;
+ struct evsel *evsel, *events = NULL;
u64 *id;
void *buf = NULL;
u32 nre, sz, nr, i, j;
@@ -1603,12 +1624,12 @@ static struct perf_evsel *read_event_desc(struct feat_fd *ff)
if (!buf)
goto error;
- /* the last event terminates with evsel->attr.size == 0: */
+ /* the last event terminates with evsel->core.attr.size == 0: */
events = calloc(nre + 1, sizeof(*events));
if (!events)
goto error;
- msz = sizeof(evsel->attr);
+ msz = sizeof(evsel->core.attr);
if (sz < msz)
msz = sz;
@@ -1625,7 +1646,7 @@ static struct perf_evsel *read_event_desc(struct feat_fd *ff)
if (ff->ph->needs_swap)
perf_event__attr_swap(buf);
- memcpy(&evsel->attr, buf, msz);
+ memcpy(&evsel->core.attr, buf, msz);
if (do_read_u32(ff, &nr))
goto error;
@@ -1669,7 +1690,7 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
static void print_event_desc(struct feat_fd *ff, FILE *fp)
{
- struct perf_evsel *evsel, *events;
+ struct evsel *evsel, *events;
u32 j;
u64 *id;
@@ -1683,7 +1704,7 @@ static void print_event_desc(struct feat_fd *ff, FILE *fp)
return;
}
- for (evsel = events; evsel->attr.size; evsel++) {
+ for (evsel = events; evsel->core.attr.size; evsel++) {
fprintf(fp, "# event : name = %s, ", evsel->name);
if (evsel->ids) {
@@ -1696,7 +1717,7 @@ static void print_event_desc(struct feat_fd *ff, FILE *fp)
fprintf(fp, " }");
}
- perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
+ perf_event_attr__fprintf(fp, &evsel->core.attr, __desc_attr__fprintf, NULL);
fputc('\n', fp);
}
@@ -1804,18 +1825,18 @@ error:
static void print_group_desc(struct feat_fd *ff, FILE *fp)
{
struct perf_session *session;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u32 nr = 0;
session = container_of(ff->ph, struct perf_session, header);
evlist__for_each_entry(session->evlist, evsel) {
if (perf_evsel__is_group_leader(evsel) &&
- evsel->nr_members > 1) {
+ evsel->core.nr_members > 1) {
fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
perf_evsel__name(evsel));
- nr = evsel->nr_members - 1;
+ nr = evsel->core.nr_members - 1;
} else if (nr) {
fprintf(fp, ",%s", perf_evsel__name(evsel));
@@ -1876,7 +1897,7 @@ static void print_mem_topology(struct feat_fd *ff, FILE *fp)
}
}
-static int __event_process_build_id(struct build_id_event *bev,
+static int __event_process_build_id(struct perf_record_header_build_id *bev,
char *filename,
struct perf_session *session)
{
@@ -1945,7 +1966,7 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
char filename[0];
} old_bev;
- struct build_id_event bev;
+ struct perf_record_header_build_id bev;
char filename[PATH_MAX];
u64 limit = offset + size;
@@ -1986,7 +2007,7 @@ static int perf_header__read_build_ids(struct perf_header *header,
int input, u64 offset, u64 size)
{
struct perf_session *session = container_of(header, struct perf_session, header);
- struct build_id_event bev;
+ struct perf_record_header_build_id bev;
char filename[PATH_MAX];
u64 limit = offset + size, orig_offset = offset;
int err = -1;
@@ -2008,7 +2029,7 @@ static int perf_header__read_build_ids(struct perf_header *header,
*
* "perf: 'perf kvm' tool for monitoring guest performance from host"
*
- * Added a field to struct build_id_event that broke the file
+ * Added a field to struct perf_record_header_build_id that broke the file
* format.
*
* Since the kernel build-id is the first entry, process the
@@ -2089,10 +2110,10 @@ static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused)
return 0;
}
-static struct perf_evsel *
-perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
+static struct evsel *
+perf_evlist__find_by_index(struct evlist *evlist, int idx)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (evsel->idx == idx)
@@ -2103,10 +2124,10 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
}
static void
-perf_evlist__set_event_name(struct perf_evlist *evlist,
- struct perf_evsel *event)
+perf_evlist__set_event_name(struct evlist *evlist,
+ struct evsel *event)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (!event->name)
return;
@@ -2125,7 +2146,7 @@ static int
process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
{
struct perf_session *session;
- struct perf_evsel *evsel, *events = read_event_desc(ff);
+ struct evsel *evsel, *events = read_event_desc(ff);
if (!events)
return 0;
@@ -2138,7 +2159,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
ff->events = events;
}
- for (evsel = events; evsel->attr.size; evsel++)
+ for (evsel = events; evsel->core.attr.size; evsel++)
perf_evlist__set_event_name(session->evlist, evsel);
if (!session->data->is_pipe)
@@ -2251,8 +2272,10 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
/* On s390 the socket_id number is not related to the numbers of cpus.
* The socket_id number might be higher than the numbers of cpus.
* This depends on the configuration.
+ * AArch64 is the same.
*/
- if (ph->env.arch && !strncmp(ph->env.arch, "s390", 4))
+ if (ph->env.arch && (!strncmp(ph->env.arch, "s390", 4)
+ || !strncmp(ph->env.arch, "aarch64", 7)))
do_core_id_test = false;
for (i = 0; i < (u32)cpu_nr; i++) {
@@ -2348,7 +2371,7 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
if (!str)
goto error;
- n->map = cpu_map__new(str);
+ n->map = perf_cpu_map__new(str);
if (!n->map)
goto error;
@@ -2415,7 +2438,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
size_t ret = -1;
u32 i, nr, nr_groups;
struct perf_session *session;
- struct perf_evsel *evsel, *leader = NULL;
+ struct evsel *evsel, *leader = NULL;
struct group_desc {
char *name;
u32 leader_idx;
@@ -2462,7 +2485,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
evsel->group_name = desc[i].name;
desc[i].name = NULL;
}
- evsel->nr_members = desc[i].nr_members;
+ evsel->core.nr_members = desc[i].nr_members;
if (i >= nr_groups || nr > 0) {
pr_debug("invalid group desc\n");
@@ -2470,7 +2493,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
}
leader = evsel;
- nr = evsel->nr_members - 1;
+ nr = evsel->core.nr_members - 1;
i++;
} else if (nr) {
/* This is a group member */
@@ -2801,7 +2824,7 @@ static int process_compressed(struct feat_fd *ff,
}
struct feature_ops {
- int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
+ int (*write)(struct feat_fd *ff, struct evlist *evlist);
void (*print)(struct feat_fd *ff, FILE *fp);
int (*process)(struct feat_fd *ff, void *data);
const char *name;
@@ -2946,7 +2969,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
static int do_write_feat(struct feat_fd *ff, int type,
struct perf_file_section **p,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
int err;
int ret = 0;
@@ -2976,7 +2999,7 @@ static int do_write_feat(struct feat_fd *ff, int type,
}
static int perf_header__adds_write(struct perf_header *header,
- struct perf_evlist *evlist, int fd)
+ struct evlist *evlist, int fd)
{
int nr_sections;
struct feat_fd ff;
@@ -3044,13 +3067,13 @@ int perf_header__write_pipe(int fd)
}
int perf_session__write_header(struct perf_session *session,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int fd, bool at_exit)
{
struct perf_file_header f_header;
struct perf_file_attr f_attr;
struct perf_header *header = &session->header;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct feat_fd ff;
u64 attr_offset;
int err;
@@ -3071,7 +3094,7 @@ int perf_session__write_header(struct perf_session *session,
evlist__for_each_entry(evlist, evsel) {
f_attr = (struct perf_file_attr){
- .attr = evsel->attr,
+ .attr = evsel->core.attr,
.ids = {
.offset = evsel->id_offset,
.size = evsel->ids * sizeof(u64),
@@ -3100,7 +3123,7 @@ int perf_session__write_header(struct perf_session *session,
.attr_size = sizeof(f_attr),
.attrs = {
.offset = attr_offset,
- .size = evlist->nr_entries * sizeof(f_attr),
+ .size = evlist->core.nr_entries * sizeof(f_attr),
},
.data = {
.offset = header->data_offset,
@@ -3479,7 +3502,7 @@ static int read_attr(int fd, struct perf_header *ph,
return ret <= 0 ? -1 : 0;
}
-static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
+static int perf_evsel__prepare_tracepoint_event(struct evsel *evsel,
struct tep_handle *pevent)
{
struct tep_event *event;
@@ -3494,9 +3517,9 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
return -1;
}
- event = tep_find_event(pevent, evsel->attr.config);
+ event = tep_find_event(pevent, evsel->core.attr.config);
if (event == NULL) {
- pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
+ pr_debug("cannot find event format for %d\n", (int)evsel->core.attr.config);
return -1;
}
@@ -3511,13 +3534,13 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
return 0;
}
-static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
+static int perf_evlist__prepare_tracepoint_events(struct evlist *evlist,
struct tep_handle *pevent)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
evlist__for_each_entry(evlist, pos) {
- if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
+ if (pos->core.attr.type == PERF_TYPE_TRACEPOINT &&
perf_evsel__prepare_tracepoint_event(pos, pevent))
return -1;
}
@@ -3535,7 +3558,7 @@ int perf_session__read_header(struct perf_session *session)
int nr_attrs, nr_ids, i, j;
int fd = perf_data__fd(data);
- session->evlist = perf_evlist__new();
+ session->evlist = evlist__new();
if (session->evlist == NULL)
return -ENOMEM;
@@ -3559,11 +3582,18 @@ int perf_session__read_header(struct perf_session *session)
data->file.path);
}
+ if (f_header.attr_size == 0) {
+ pr_err("ERROR: The %s file's attr size field is 0 which is unexpected.\n"
+ "Was the 'perf record' command properly terminated?\n",
+ data->file.path);
+ return -EINVAL;
+ }
+
nr_attrs = f_header.attrs.size / f_header.attr_size;
lseek(fd, f_header.attrs.offset, SEEK_SET);
for (i = 0; i < nr_attrs; i++) {
- struct perf_evsel *evsel;
+ struct evsel *evsel;
off_t tmp;
if (read_attr(fd, header, &f_attr) < 0)
@@ -3576,7 +3606,7 @@ int perf_session__read_header(struct perf_session *session)
}
tmp = lseek(fd, 0, SEEK_CUR);
- evsel = perf_evsel__new(&f_attr.attr);
+ evsel = evsel__new(&f_attr.attr);
if (evsel == NULL)
goto out_delete_evlist;
@@ -3584,9 +3614,9 @@ int perf_session__read_header(struct perf_session *session)
evsel->needs_swap = header->needs_swap;
/*
* Do it before so that if perf_evsel__alloc_id fails, this
- * entry gets purged too at perf_evlist__delete().
+ * entry gets purged too at evlist__delete().
*/
- perf_evlist__add(session->evlist, evsel);
+ evlist__add(session->evlist, evsel);
nr_ids = f_attr.ids.size / sizeof(u64);
/*
@@ -3621,7 +3651,7 @@ out_errno:
return -errno;
out_delete_evlist:
- perf_evlist__delete(session->evlist);
+ evlist__delete(session->evlist);
session->evlist = NULL;
return -ENOMEM;
}
@@ -3639,7 +3669,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
size += sizeof(struct perf_event_header);
size += ids * sizeof(u64);
- ev = malloc(size);
+ ev = zalloc(size);
if (ev == NULL)
return -ENOMEM;
@@ -3662,12 +3692,12 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
int perf_event__synthesize_features(struct perf_tool *tool,
struct perf_session *session,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process)
{
struct perf_header *header = &session->header;
struct feat_fd ff;
- struct feature_event *fe;
+ struct perf_record_header_feature *fe;
size_t sz, sz_hdr;
int feat, ret;
@@ -3730,7 +3760,7 @@ int perf_event__process_feature(struct perf_session *session,
{
struct perf_tool *tool = session->tool;
struct feat_fd ff = { .fd = 0 };
- struct feature_event *fe = (struct feature_event *)event;
+ struct perf_record_header_feature *fe = (struct perf_record_header_feature *)event;
int type = fe->header.type;
u64 feat = fe->feat_id;
@@ -3747,7 +3777,7 @@ int perf_event__process_feature(struct perf_session *session,
return 0;
ff.buf = (void *)fe->data;
- ff.size = event->header.size - sizeof(event->header);
+ ff.size = event->header.size - sizeof(*fe);
ff.ph = &session->header;
if (feat_ops[feat].process(&ff, NULL))
@@ -3767,10 +3797,10 @@ int perf_event__process_feature(struct perf_session *session,
return 0;
}
-static struct event_update_event *
+static struct perf_record_event_update *
event_update_event__new(size_t size, u64 type, u64 id)
{
- struct event_update_event *ev;
+ struct perf_record_event_update *ev;
size += sizeof(*ev);
size = PERF_ALIGN(size, sizeof(u64));
@@ -3787,10 +3817,10 @@ event_update_event__new(size_t size, u64 type, u64 id)
int
perf_event__synthesize_event_update_unit(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process)
{
- struct event_update_event *ev;
+ struct perf_record_event_update *ev;
size_t size = strlen(evsel->unit);
int err;
@@ -3806,18 +3836,18 @@ perf_event__synthesize_event_update_unit(struct perf_tool *tool,
int
perf_event__synthesize_event_update_scale(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process)
{
- struct event_update_event *ev;
- struct event_update_event_scale *ev_data;
+ struct perf_record_event_update *ev;
+ struct perf_record_event_update_scale *ev_data;
int err;
ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
if (ev == NULL)
return -ENOMEM;
- ev_data = (struct event_update_event_scale *) ev->data;
+ ev_data = (struct perf_record_event_update_scale *)ev->data;
ev_data->scale = evsel->scale;
err = process(tool, (union perf_event*) ev, NULL, NULL);
free(ev);
@@ -3826,10 +3856,10 @@ perf_event__synthesize_event_update_scale(struct perf_tool *tool,
int
perf_event__synthesize_event_update_name(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process)
{
- struct event_update_event *ev;
+ struct perf_record_event_update *ev;
size_t len = strlen(evsel->name);
int err;
@@ -3845,18 +3875,18 @@ perf_event__synthesize_event_update_name(struct perf_tool *tool,
int
perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process)
{
- size_t size = sizeof(struct event_update_event);
- struct event_update_event *ev;
+ size_t size = sizeof(struct perf_record_event_update);
+ struct perf_record_event_update *ev;
int max, err;
u16 type;
- if (!evsel->own_cpus)
+ if (!evsel->core.own_cpus)
return 0;
- ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
+ ev = cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max);
if (!ev)
return -ENOMEM;
@@ -3865,8 +3895,8 @@ perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
ev->type = PERF_EVENT_UPDATE__CPUS;
ev->id = evsel->id[0];
- cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
- evsel->own_cpus,
+ cpu_map_data__synthesize((struct perf_record_cpu_map_data *)ev->data,
+ evsel->core.own_cpus,
type, max);
err = process(tool, (union perf_event*) ev, NULL, NULL);
@@ -3876,17 +3906,17 @@ perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
{
- struct event_update_event *ev = &event->event_update;
- struct event_update_event_scale *ev_scale;
- struct event_update_event_cpus *ev_cpus;
- struct cpu_map *map;
+ struct perf_record_event_update *ev = &event->event_update;
+ struct perf_record_event_update_scale *ev_scale;
+ struct perf_record_event_update_cpus *ev_cpus;
+ struct perf_cpu_map *map;
size_t ret;
- ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id);
+ ret = fprintf(fp, "\n... id: %" PRI_lu64 "\n", ev->id);
switch (ev->type) {
case PERF_EVENT_UPDATE__SCALE:
- ev_scale = (struct event_update_event_scale *) ev->data;
+ ev_scale = (struct perf_record_event_update_scale *)ev->data;
ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
break;
case PERF_EVENT_UPDATE__UNIT:
@@ -3896,7 +3926,7 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
ret += fprintf(fp, "... name: %s\n", ev->data);
break;
case PERF_EVENT_UPDATE__CPUS:
- ev_cpus = (struct event_update_event_cpus *) ev->data;
+ ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
ret += fprintf(fp, "... ");
map = cpu_map__new_data(&ev_cpus->cpus);
@@ -3914,14 +3944,14 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
}
int perf_event__synthesize_attrs(struct perf_tool *tool,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
int err = 0;
evlist__for_each_entry(evlist, evsel) {
- err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
+ err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->ids,
evsel->id, process);
if (err) {
pr_debug("failed to create perf header attribute\n");
@@ -3932,22 +3962,22 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
return err;
}
-static bool has_unit(struct perf_evsel *counter)
+static bool has_unit(struct evsel *counter)
{
return counter->unit && *counter->unit;
}
-static bool has_scale(struct perf_evsel *counter)
+static bool has_scale(struct evsel *counter)
{
return counter->scale != 1;
}
int perf_event__synthesize_extra_attr(struct perf_tool *tool,
- struct perf_evlist *evsel_list,
+ struct evlist *evsel_list,
perf_event__handler_t process,
bool is_pipe)
{
- struct perf_evsel *counter;
+ struct evsel *counter;
int err;
/*
@@ -3977,7 +4007,7 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
}
}
- if (counter->own_cpus) {
+ if (counter->core.own_cpus) {
err = perf_event__synthesize_event_update_cpus(tool, counter, process);
if (err < 0) {
pr_err("Couldn't synthesize evsel cpus.\n");
@@ -4002,23 +4032,23 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
union perf_event *event,
- struct perf_evlist **pevlist)
+ struct evlist **pevlist)
{
u32 i, ids, n_ids;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = *pevlist;
+ struct evsel *evsel;
+ struct evlist *evlist = *pevlist;
if (evlist == NULL) {
- *pevlist = evlist = perf_evlist__new();
+ *pevlist = evlist = evlist__new();
if (evlist == NULL)
return -ENOMEM;
}
- evsel = perf_evsel__new(&event->attr.attr);
+ evsel = evsel__new(&event->attr.attr);
if (evsel == NULL)
return -ENOMEM;
- perf_evlist__add(evlist, evsel);
+ evlist__add(evlist, evsel);
ids = event->header.size;
ids -= (void *)&event->attr.id - (void *)event;
@@ -4040,14 +4070,14 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
union perf_event *event,
- struct perf_evlist **pevlist)
+ struct evlist **pevlist)
{
- struct event_update_event *ev = &event->event_update;
- struct event_update_event_scale *ev_scale;
- struct event_update_event_cpus *ev_cpus;
- struct perf_evlist *evlist;
- struct perf_evsel *evsel;
- struct cpu_map *map;
+ struct perf_record_event_update *ev = &event->event_update;
+ struct perf_record_event_update_scale *ev_scale;
+ struct perf_record_event_update_cpus *ev_cpus;
+ struct evlist *evlist;
+ struct evsel *evsel;
+ struct perf_cpu_map *map;
if (!pevlist || *pevlist == NULL)
return -EINVAL;
@@ -4066,15 +4096,15 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
evsel->name = strdup(ev->data);
break;
case PERF_EVENT_UPDATE__SCALE:
- ev_scale = (struct event_update_event_scale *) ev->data;
+ ev_scale = (struct perf_record_event_update_scale *)ev->data;
evsel->scale = ev_scale->scale;
break;
case PERF_EVENT_UPDATE__CPUS:
- ev_cpus = (struct event_update_event_cpus *) ev->data;
+ ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
map = cpu_map__new_data(&ev_cpus->cpus);
if (map)
- evsel->own_cpus = map;
+ evsel->core.own_cpus = map;
else
pr_err("failed to get event_update cpus\n");
default:
@@ -4085,7 +4115,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
}
int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process)
{
union perf_event ev;
@@ -4105,7 +4135,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
* - write the tracing data from the temp file
* to the pipe
*/
- tdata = tracing_data_get(&evlist->entries, fd, true);
+ tdata = tracing_data_get(&evlist->core.entries, fd, true);
if (!tdata)
return -1;
@@ -4142,7 +4172,7 @@ int perf_event__process_tracing_data(struct perf_session *session,
char buf[BUFSIZ];
/* setup for reading amidst mmap */
- lseek(fd, offset + sizeof(struct tracing_data_event),
+ lseek(fd, offset + sizeof(struct perf_record_header_tracing_data),
SEEK_SET);
size_read = trace_report(fd, &session->tevent,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 5b3abe4172e2..3e48ae3c49b1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -92,12 +92,12 @@ struct perf_header {
struct perf_env env;
};
-struct perf_evlist;
+struct evlist;
struct perf_session;
int perf_session__read_header(struct perf_session *session);
int perf_session__write_header(struct perf_session *session,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int fd, bool at_exit);
int perf_header__write_pipe(int fd);
@@ -117,11 +117,11 @@ int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
int perf_event__synthesize_features(struct perf_tool *tool,
struct perf_session *session,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process);
int perf_event__synthesize_extra_attr(struct perf_tool *tool,
- struct perf_evlist *evsel_list,
+ struct evlist *evsel_list,
perf_event__handler_t process,
bool is_pipe);
@@ -132,29 +132,29 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
struct perf_event_attr *attr, u32 ids, u64 *id,
perf_event__handler_t process);
int perf_event__synthesize_attrs(struct perf_tool *tool,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process);
int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process);
int perf_event__synthesize_event_update_scale(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process);
int perf_event__synthesize_event_update_name(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process);
int perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
perf_event__handler_t process);
int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
- struct perf_evlist **pevlist);
+ struct evlist **pevlist);
int perf_event__process_event_update(struct perf_tool *tool,
union perf_event *event,
- struct perf_evlist **pevlist);
+ struct evlist **pevlist);
size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
int perf_event__synthesize_tracing_data(struct perf_tool *tool,
- int fd, struct perf_evlist *evlist,
+ int fd, struct evlist *evlist,
perf_event__handler_t process);
int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f24fd1954f6c..679a1d75090c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,8 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
#include "callchain.h"
+#include "debug.h"
+#include "dso.h"
#include "build-id.h"
#include "hist.h"
#include "map.h"
+#include "map_symbol.h"
+#include "branch.h"
+#include "mem-events.h"
#include "session.h"
#include "namespaces.h"
#include "sort.h"
@@ -18,6 +23,8 @@
#include <math.h>
#include <inttypes.h>
#include <sys/param.h>
+#include <linux/rbtree.h>
+#include <linux/string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
@@ -193,7 +200,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
- hists__new_col_len(hists, HISTC_TIME, 12);
+ if (symbol_conf.nanosecs)
+ hists__new_col_len(hists, HISTC_TIME, 16);
+ else
+ hists__new_col_len(hists, HISTC_TIME, 12);
if (h->srcline) {
len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header));
@@ -816,7 +826,7 @@ static int
iter_finish_mem_entry(struct hist_entry_iter *iter,
struct addr_location *al __maybe_unused)
{
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct hists *hists = evsel__hists(evsel);
struct hist_entry *he = iter->he;
int err = -EINVAL;
@@ -886,7 +896,7 @@ static int
iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
{
struct branch_info *bi;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct hists *hists = evsel__hists(evsel);
struct perf_sample *sample = iter->sample;
struct hist_entry *he = NULL;
@@ -938,7 +948,7 @@ iter_prepare_normal_entry(struct hist_entry_iter *iter __maybe_unused,
static int
iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location *al)
{
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct perf_sample *sample = iter->sample;
struct hist_entry *he;
@@ -956,7 +966,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
struct addr_location *al __maybe_unused)
{
struct hist_entry *he = iter->he;
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct perf_sample *sample = iter->sample;
if (he == NULL)
@@ -996,7 +1006,7 @@ static int
iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
struct addr_location *al)
{
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct hists *hists = evsel__hists(evsel);
struct perf_sample *sample = iter->sample;
struct hist_entry **he_cache = iter->priv;
@@ -1041,7 +1051,7 @@ static int
iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
struct addr_location *al)
{
- struct perf_evsel *evsel = iter->evsel;
+ struct evsel *evsel = iter->evsel;
struct perf_sample *sample = iter->sample;
struct hist_entry **he_cache = iter->priv;
struct hist_entry *he;
@@ -1873,7 +1883,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
}
}
-void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress *prog,
+void perf_evsel__output_resort_cb(struct evsel *evsel, struct ui_progress *prog,
hists__resort_cb_t cb, void *cb_arg)
{
bool use_callchain;
@@ -1888,7 +1898,7 @@ void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress *
output_resort(evsel__hists(evsel), prog, use_callchain, cb, cb_arg);
}
-void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog)
+void perf_evsel__output_resort(struct evsel *evsel, struct ui_progress *prog)
{
return perf_evsel__output_resort_cb(evsel, prog, NULL, NULL);
}
@@ -2539,6 +2549,25 @@ int hists__link(struct hists *leader, struct hists *other)
return 0;
}
+int hists__unlink(struct hists *hists)
+{
+ struct rb_root_cached *root;
+ struct rb_node *nd;
+ struct hist_entry *pos;
+
+ if (hists__has(hists, need_collapse))
+ root = &hists->entries_collapsed;
+ else
+ root = hists->entries_in;
+
+ for (nd = rb_first_cached(root); nd; nd = rb_next(nd)) {
+ pos = rb_entry(nd, struct hist_entry, rb_node_in);
+ list_del_init(&pos->pairs.node);
+ }
+
+ return 0;
+}
+
void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
struct perf_sample *sample, bool nonany_branch_mode)
{
@@ -2573,9 +2602,9 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
}
}
-size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
+size_t perf_evlist__fprintf_nr_events(struct evlist *evlist, FILE *fp)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
size_t ret = 0;
evlist__for_each_entry(evlist, pos) {
@@ -2602,7 +2631,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh
int socket_id = hists->socket_filter;
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
u64 nr_events = hists->stats.total_period;
- struct perf_evsel *evsel = hists_to_evsel(hists);
+ struct evsel *evsel = hists_to_evsel(hists);
const char *ev_name = perf_evsel__name(evsel);
char buf[512], sample_freq_str[64] = "";
size_t buflen = sizeof(buf);
@@ -2615,7 +2644,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh
}
if (perf_evsel__is_group_event(evsel)) {
- struct perf_evsel *pos;
+ struct evsel *pos;
perf_evsel__group_desc(evsel, buf, buflen);
ev_name = buf;
@@ -2638,12 +2667,12 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh
enable_ref = true;
if (show_freq)
- scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
+ scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->core.attr.sample_freq);
nr_samples = convert_unit(nr_samples, &unit);
printed = scnprintf(bf, size,
"Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
- nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
+ nr_samples, unit, evsel->core.nr_members > 1 ? "s" : "",
ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
@@ -2731,7 +2760,7 @@ static void hists__delete_all_entries(struct hists *hists)
hists__delete_remaining_entries(&hists->entries_collapsed);
}
-static void hists_evsel__exit(struct perf_evsel *evsel)
+static void hists_evsel__exit(struct evsel *evsel)
{
struct hists *hists = evsel__hists(evsel);
struct perf_hpp_fmt *fmt, *pos;
@@ -2749,7 +2778,7 @@ static void hists_evsel__exit(struct perf_evsel *evsel)
}
}
-static int hists_evsel__init(struct perf_evsel *evsel)
+static int hists_evsel__init(struct evsel *evsel)
{
struct hists *hists = evsel__hists(evsel);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 24635f36148d..34803e33dc80 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -6,9 +6,8 @@
#include <linux/types.h>
#include <pthread.h>
#include "evsel.h"
-#include "header.h"
#include "color.h"
-#include "ui/progress.h"
+#include "events_stats.h"
struct hist_entry;
struct hist_entry_ops;
@@ -18,6 +17,7 @@ struct mem_info;
struct branch_info;
struct block_info;
struct symbol;
+struct ui_progress;
enum hist_filter {
HIST_FILTER__DSO,
@@ -116,7 +116,7 @@ struct hist_entry_iter {
bool hide_unresolved;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_sample *sample;
struct hist_entry *he;
struct symbol *parent;
@@ -171,9 +171,9 @@ void hist_entry__delete(struct hist_entry *he);
typedef int (*hists__resort_cb_t)(struct hist_entry *he, void *arg);
-void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress *prog,
+void perf_evsel__output_resort_cb(struct evsel *evsel, struct ui_progress *prog,
hists__resort_cb_t cb, void *cb_arg);
-void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
+void perf_evsel__output_resort(struct evsel *evsel, struct ui_progress *prog);
void hists__output_resort(struct hists *hists, struct ui_progress *prog);
void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
hists__resort_cb_t cb);
@@ -190,13 +190,11 @@ void hists__reset_stats(struct hists *hists);
void hists__inc_stats(struct hists *hists, struct hist_entry *h);
void hists__inc_nr_events(struct hists *hists, u32 type);
void hists__inc_nr_samples(struct hists *hists, bool filtered);
-void events_stats__inc(struct events_stats *stats, u32 type);
-size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
int max_cols, float min_pcnt, FILE *fp,
bool ignore_callchains);
-size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
+size_t perf_evlist__fprintf_nr_events(struct evlist *evlist, FILE *fp);
void hists__filter_by_dso(struct hists *hists);
void hists__filter_by_thread(struct hists *hists);
@@ -217,19 +215,20 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
void hists__match(struct hists *leader, struct hists *other);
int hists__link(struct hists *leader, struct hists *other);
+int hists__unlink(struct hists *hists);
struct hists_evsel {
- struct perf_evsel evsel;
+ struct evsel evsel;
struct hists hists;
};
-static inline struct perf_evsel *hists_to_evsel(struct hists *hists)
+static inline struct evsel *hists_to_evsel(struct hists *hists)
{
struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists);
return &hevsel->evsel;
}
-static inline struct hists *evsel__hists(struct perf_evsel *evsel)
+static inline struct hists *evsel__hists(struct evsel *evsel)
{
struct hists_evsel *hevsel = (struct hists_evsel *)evsel;
return &hevsel->hists;
@@ -367,7 +366,7 @@ void perf_hpp__setup_output_field(struct perf_hpp_list *list);
void perf_hpp__reset_output_field(struct perf_hpp_list *list);
void perf_hpp__append_sort_keys(struct perf_hpp_list *list);
int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
- struct perf_evlist *evlist);
+ struct evlist *evlist);
bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
@@ -432,7 +431,7 @@ static inline size_t perf_hpp__color_overhead(void)
: 0;
}
-struct perf_evlist;
+struct evlist;
struct hist_browser_timer {
void (*timer)(void *arg);
@@ -453,30 +452,30 @@ enum rstype {
#include "../ui/keysyms.h"
void attr_to_script(char *buf, struct perf_event_attr *attr);
-int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *annotation_opts);
-int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
+int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
struct hist_browser_timer *hbt,
struct annotation_options *annotation_opts);
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
+int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
struct hist_browser_timer *hbt,
float min_pcnt,
struct perf_env *env,
bool warn_lost_event,
struct annotation_options *annotation_options);
-int script_browse(const char *script_opt, struct perf_evsel *evsel);
+int script_browse(const char *script_opt, struct evsel *evsel);
void run_script(char *cmd);
int res_sample_browse(struct res_sample *res_samples, int num_res,
- struct perf_evsel *evsel, enum rstype rstype);
+ struct evsel *evsel, enum rstype rstype);
void res_sample_init(void);
#else
static inline
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
+int perf_evlist__tui_browse_hists(struct evlist *evlist __maybe_unused,
const char *help __maybe_unused,
struct hist_browser_timer *hbt __maybe_unused,
float min_pcnt __maybe_unused,
@@ -487,7 +486,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
return 0;
}
static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct hist_browser_timer *hbt __maybe_unused,
struct annotation_options *annotation_options __maybe_unused)
{
@@ -495,7 +494,7 @@ static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
}
static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct hist_browser_timer *hbt __maybe_unused,
struct annotation_options *annotation_opts __maybe_unused)
{
@@ -503,14 +502,14 @@ static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
}
static inline int script_browse(const char *script_opt __maybe_unused,
- struct perf_evsel *evsel __maybe_unused)
+ struct evsel *evsel __maybe_unused)
{
return 0;
}
static inline int res_sample_browse(struct res_sample *res_samples __maybe_unused,
int num_res __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
enum rstype rstype __maybe_unused)
{
return 0;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 5560e95afdda..aacffa2b0362 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -19,9 +19,9 @@
#include "evsel.h"
#include "evlist.h"
#include "machine.h"
-#include "map.h"
#include "symbol.h"
#include "session.h"
+#include "tool.h"
#include "thread.h"
#include "thread-stack.h"
#include "debug.h"
@@ -760,15 +760,15 @@ static int intel_bts_synth_event(struct perf_session *session,
static int intel_bts_synth_events(struct intel_bts *bts,
struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel;
struct perf_event_attr attr;
bool found = false;
u64 id;
int err;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == bts->pmu_type && evsel->ids) {
+ if (evsel->core.attr.type == bts->pmu_type && evsel->ids) {
found = true;
break;
}
@@ -782,18 +782,18 @@ static int intel_bts_synth_events(struct intel_bts *bts,
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.size = sizeof(struct perf_event_attr);
attr.type = PERF_TYPE_HARDWARE;
- attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK;
+ attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
PERF_SAMPLE_PERIOD;
attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
attr.sample_type &= ~(u64)PERF_SAMPLE_CPU;
- attr.exclude_user = evsel->attr.exclude_user;
- attr.exclude_kernel = evsel->attr.exclude_kernel;
- attr.exclude_hv = evsel->attr.exclude_hv;
- attr.exclude_host = evsel->attr.exclude_host;
- attr.exclude_guest = evsel->attr.exclude_guest;
- attr.sample_id_all = evsel->attr.sample_id_all;
- attr.read_format = evsel->attr.read_format;
+ attr.exclude_user = evsel->core.attr.exclude_user;
+ attr.exclude_kernel = evsel->core.attr.exclude_kernel;
+ attr.exclude_hv = evsel->core.attr.exclude_hv;
+ attr.exclude_host = evsel->core.attr.exclude_host;
+ attr.exclude_guest = evsel->core.attr.exclude_guest;
+ attr.sample_id_all = evsel->core.attr.sample_id_all;
+ attr.read_format = evsel->core.attr.read_format;
id = evsel->id[0] + 1000000000;
if (!id)
@@ -818,7 +818,7 @@ static int intel_bts_synth_events(struct intel_bts *bts,
* We only use sample types from PERF_SAMPLE_MASK so we can use
* __perf_evsel__sample_size() here.
*/
- bts->branches_event_size = sizeof(struct sample_event) +
+ bts->branches_event_size = sizeof(struct perf_record_sample) +
__perf_evsel__sample_size(attr.sample_type);
}
@@ -834,7 +834,7 @@ static const char * const intel_bts_info_fmts[] = {
[INTEL_BTS_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n",
};
-static void intel_bts_print_info(u64 *arr, int start, int finish)
+static void intel_bts_print_info(__u64 *arr, int start, int finish)
{
int i;
@@ -848,12 +848,12 @@ static void intel_bts_print_info(u64 *arr, int start, int finish)
int intel_bts_process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
size_t min_sz = sizeof(u64) * INTEL_BTS_SNAPSHOT_MODE;
struct intel_bts *bts;
int err;
- if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
+ if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
min_sz)
return -EINVAL;
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 23bf788f84b9..bc629359826f 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -1,7 +1,7 @@
perf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o intel-pt-log.o intel-pt-decoder.o
-inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk
-inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt
+inat_tables_script = $(srctree)/tools/arch/x86/tools/gen-insn-attr-x86.awk
+inat_tables_maps = $(srctree)/tools/arch/x86/lib/x86-opcode-map.txt
$(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
$(call rule_mkdir)
@@ -9,23 +9,7 @@ $(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_table
# Busybox's diff doesn't have -I, avoid warning in the case
-$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
- @(diff -I 2>&1 | grep -q 'option requires an argument' && \
- test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
- ((diff -B -I'^#include' util/intel-pt-decoder/insn.c ../../arch/x86/lib/insn.c >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder C file at 'tools/perf/util/intel-pt-decoder/insn.c' differs from latest version at 'arch/x86/lib/insn.c'" >&2)) && \
- ((diff -B -I'^#include' util/intel-pt-decoder/inat.c ../../arch/x86/lib/inat.c >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder C file at 'tools/perf/util/intel-pt-decoder/inat.c' differs from latest version at 'arch/x86/lib/inat.c'" >&2)) && \
- ((diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder map file at 'tools/perf/util/intel-pt-decoder/x86-opcode-map.txt' differs from latest version at 'arch/x86/lib/x86-opcode-map.txt'" >&2)) && \
- ((diff -B util/intel-pt-decoder/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder script at 'tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk' differs from latest version at 'arch/x86/tools/gen-insn-attr-x86.awk'" >&2)) && \
- ((diff -B -I'^#include' util/intel-pt-decoder/insn.h ../../arch/x86/include/asm/insn.h >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder header at 'tools/perf/util/intel-pt-decoder/insn.h' differs from latest version at 'arch/x86/include/asm/insn.h'" >&2)) && \
- ((diff -B -I'^#include' util/intel-pt-decoder/inat.h ../../arch/x86/include/asm/inat.h >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder header at 'tools/perf/util/intel-pt-decoder/inat.h' differs from latest version at 'arch/x86/include/asm/inat.h'" >&2)) && \
- ((diff -B -I'^#include' util/intel-pt-decoder/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) || \
- (echo "Warning: Intel PT: x86 instruction decoder header at 'tools/perf/util/intel-pt-decoder/inat_types.h' differs from latest version at 'arch/x86/include/asm/inat_types.h'" >&2)))) || true
+$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
deleted file mode 100644
index ddd5c4c21129..000000000000
--- a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
+++ /dev/null
@@ -1,392 +0,0 @@
-#!/bin/awk -f
-# SPDX-License-Identifier: GPL-2.0
-# gen-insn-attr-x86.awk: Instruction attribute table generator
-# Written by Masami Hiramatsu <mhiramat@redhat.com>
-#
-# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
-
-# Awk implementation sanity check
-function check_awk_implement() {
- if (sprintf("%x", 0) != "0")
- return "Your awk has a printf-format problem."
- return ""
-}
-
-# Clear working vars
-function clear_vars() {
- delete table
- delete lptable2
- delete lptable1
- delete lptable3
- eid = -1 # escape id
- gid = -1 # group id
- aid = -1 # AVX id
- tname = ""
-}
-
-BEGIN {
- # Implementation error checking
- awkchecked = check_awk_implement()
- if (awkchecked != "") {
- print "Error: " awkchecked > "/dev/stderr"
- print "Please try to use gawk." > "/dev/stderr"
- exit 1
- }
-
- # Setup generating tables
- print "/* x86 opcode map generated from x86-opcode-map.txt */"
- print "/* Do not change this code. */\n"
- ggid = 1
- geid = 1
- gaid = 0
- delete etable
- delete gtable
- delete atable
-
- opnd_expr = "^[A-Za-z/]"
- ext_expr = "^\\("
- sep_expr = "^\\|$"
- group_expr = "^Grp[0-9A-Za-z]+"
-
- imm_expr = "^[IJAOL][a-z]"
- imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
- imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
- imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
- imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
- imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
- imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
- imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
- imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
- imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
- imm_flag["Ob"] = "INAT_MOFFSET"
- imm_flag["Ov"] = "INAT_MOFFSET"
- imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
-
- modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
- force64_expr = "\\([df]64\\)"
- rex_expr = "^REX(\\.[XRWB]+)*"
- fpu_expr = "^ESC" # TODO
-
- lprefix1_expr = "\\((66|!F3)\\)"
- lprefix2_expr = "\\(F3\\)"
- lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
- lprefix_expr = "\\((66|F2|F3)\\)"
- max_lprefix = 4
-
- # All opcodes starting with lower-case 'v', 'k' or with (v1) superscript
- # accepts VEX prefix
- vexok_opcode_expr = "^[vk].*"
- vexok_expr = "\\(v1\\)"
- # All opcodes with (v) superscript supports *only* VEX prefix
- vexonly_expr = "\\(v\\)"
- # All opcodes with (ev) superscript supports *only* EVEX prefix
- evexonly_expr = "\\(ev\\)"
-
- prefix_expr = "\\(Prefix\\)"
- prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
- prefix_num["REPNE"] = "INAT_PFX_REPNE"
- prefix_num["REP/REPE"] = "INAT_PFX_REPE"
- prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
- prefix_num["XRELEASE"] = "INAT_PFX_REPE"
- prefix_num["LOCK"] = "INAT_PFX_LOCK"
- prefix_num["SEG=CS"] = "INAT_PFX_CS"
- prefix_num["SEG=DS"] = "INAT_PFX_DS"
- prefix_num["SEG=ES"] = "INAT_PFX_ES"
- prefix_num["SEG=FS"] = "INAT_PFX_FS"
- prefix_num["SEG=GS"] = "INAT_PFX_GS"
- prefix_num["SEG=SS"] = "INAT_PFX_SS"
- prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
- prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
- prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
- prefix_num["EVEX"] = "INAT_PFX_EVEX"
-
- clear_vars()
-}
-
-function semantic_error(msg) {
- print "Semantic error at " NR ": " msg > "/dev/stderr"
- exit 1
-}
-
-function debug(msg) {
- print "DEBUG: " msg
-}
-
-function array_size(arr, i,c) {
- c = 0
- for (i in arr)
- c++
- return c
-}
-
-/^Table:/ {
- print "/* " $0 " */"
- if (tname != "")
- semantic_error("Hit Table: before EndTable:.");
-}
-
-/^Referrer:/ {
- if (NF != 1) {
- # escape opcode table
- ref = ""
- for (i = 2; i <= NF; i++)
- ref = ref $i
- eid = escape[ref]
- tname = sprintf("inat_escape_table_%d", eid)
- }
-}
-
-/^AVXcode:/ {
- if (NF != 1) {
- # AVX/escape opcode table
- aid = $2
- if (gaid <= aid)
- gaid = aid + 1
- if (tname == "") # AVX only opcode table
- tname = sprintf("inat_avx_table_%d", $2)
- }
- if (aid == -1 && eid == -1) # primary opcode table
- tname = "inat_primary_table"
-}
-
-/^GrpTable:/ {
- print "/* " $0 " */"
- if (!($2 in group))
- semantic_error("No group: " $2 )
- gid = group[$2]
- tname = "inat_group_table_" gid
-}
-
-function print_table(tbl,name,fmt,n)
-{
- print "const insn_attr_t " name " = {"
- for (i = 0; i < n; i++) {
- id = sprintf(fmt, i)
- if (tbl[id])
- print " [" id "] = " tbl[id] ","
- }
- print "};"
-}
-
-/^EndTable/ {
- if (gid != -1) {
- # print group tables
- if (array_size(table) != 0) {
- print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
- "0x%x", 8)
- gtable[gid,0] = tname
- }
- if (array_size(lptable1) != 0) {
- print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
- "0x%x", 8)
- gtable[gid,1] = tname "_1"
- }
- if (array_size(lptable2) != 0) {
- print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
- "0x%x", 8)
- gtable[gid,2] = tname "_2"
- }
- if (array_size(lptable3) != 0) {
- print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
- "0x%x", 8)
- gtable[gid,3] = tname "_3"
- }
- } else {
- # print primary/escaped tables
- if (array_size(table) != 0) {
- print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
- "0x%02x", 256)
- etable[eid,0] = tname
- if (aid >= 0)
- atable[aid,0] = tname
- }
- if (array_size(lptable1) != 0) {
- print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
- "0x%02x", 256)
- etable[eid,1] = tname "_1"
- if (aid >= 0)
- atable[aid,1] = tname "_1"
- }
- if (array_size(lptable2) != 0) {
- print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
- "0x%02x", 256)
- etable[eid,2] = tname "_2"
- if (aid >= 0)
- atable[aid,2] = tname "_2"
- }
- if (array_size(lptable3) != 0) {
- print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
- "0x%02x", 256)
- etable[eid,3] = tname "_3"
- if (aid >= 0)
- atable[aid,3] = tname "_3"
- }
- }
- print ""
- clear_vars()
-}
-
-function add_flags(old,new) {
- if (old && new)
- return old " | " new
- else if (old)
- return old
- else
- return new
-}
-
-# convert operands to flags.
-function convert_operands(count,opnd, i,j,imm,mod)
-{
- imm = null
- mod = null
- for (j = 1; j <= count; j++) {
- i = opnd[j]
- if (match(i, imm_expr) == 1) {
- if (!imm_flag[i])
- semantic_error("Unknown imm opnd: " i)
- if (imm) {
- if (i != "Ib")
- semantic_error("Second IMM error")
- imm = add_flags(imm, "INAT_SCNDIMM")
- } else
- imm = imm_flag[i]
- } else if (match(i, modrm_expr))
- mod = "INAT_MODRM"
- }
- return add_flags(imm, mod)
-}
-
-/^[0-9a-f]+\:/ {
- if (NR == 1)
- next
- # get index
- idx = "0x" substr($1, 1, index($1,":") - 1)
- if (idx in table)
- semantic_error("Redefine " idx " in " tname)
-
- # check if escaped opcode
- if ("escape" == $2) {
- if ($3 != "#")
- semantic_error("No escaped name")
- ref = ""
- for (i = 4; i <= NF; i++)
- ref = ref $i
- if (ref in escape)
- semantic_error("Redefine escape (" ref ")")
- escape[ref] = geid
- geid++
- table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
- next
- }
-
- variant = null
- # converts
- i = 2
- while (i <= NF) {
- opcode = $(i++)
- delete opnds
- ext = null
- flags = null
- opnd = null
- # parse one opcode
- if (match($i, opnd_expr)) {
- opnd = $i
- count = split($(i++), opnds, ",")
- flags = convert_operands(count, opnds)
- }
- if (match($i, ext_expr))
- ext = $(i++)
- if (match($i, sep_expr))
- i++
- else if (i < NF)
- semantic_error($i " is not a separator")
-
- # check if group opcode
- if (match(opcode, group_expr)) {
- if (!(opcode in group)) {
- group[opcode] = ggid
- ggid++
- }
- flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
- }
- # check force(or default) 64bit
- if (match(ext, force64_expr))
- flags = add_flags(flags, "INAT_FORCE64")
-
- # check REX prefix
- if (match(opcode, rex_expr))
- flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
-
- # check coprocessor escape : TODO
- if (match(opcode, fpu_expr))
- flags = add_flags(flags, "INAT_MODRM")
-
- # check VEX codes
- if (match(ext, evexonly_expr))
- flags = add_flags(flags, "INAT_VEXOK | INAT_EVEXONLY")
- else if (match(ext, vexonly_expr))
- flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
- else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
- flags = add_flags(flags, "INAT_VEXOK")
-
- # check prefixes
- if (match(ext, prefix_expr)) {
- if (!prefix_num[opcode])
- semantic_error("Unknown prefix: " opcode)
- flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
- }
- if (length(flags) == 0)
- continue
- # check if last prefix
- if (match(ext, lprefix1_expr)) {
- lptable1[idx] = add_flags(lptable1[idx],flags)
- variant = "INAT_VARIANT"
- }
- if (match(ext, lprefix2_expr)) {
- lptable2[idx] = add_flags(lptable2[idx],flags)
- variant = "INAT_VARIANT"
- }
- if (match(ext, lprefix3_expr)) {
- lptable3[idx] = add_flags(lptable3[idx],flags)
- variant = "INAT_VARIANT"
- }
- if (!match(ext, lprefix_expr)){
- table[idx] = add_flags(table[idx],flags)
- }
- }
- if (variant)
- table[idx] = add_flags(table[idx],variant)
-}
-
-END {
- if (awkchecked != "")
- exit 1
- # print escape opcode map's array
- print "/* Escape opcode map array */"
- print "const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1]" \
- "[INAT_LSTPFX_MAX + 1] = {"
- for (i = 0; i < geid; i++)
- for (j = 0; j < max_lprefix; j++)
- if (etable[i,j])
- print " ["i"]["j"] = "etable[i,j]","
- print "};\n"
- # print group opcode map's array
- print "/* Group opcode map array */"
- print "const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1]"\
- "[INAT_LSTPFX_MAX + 1] = {"
- for (i = 0; i < ggid; i++)
- for (j = 0; j < max_lprefix; j++)
- if (gtable[i,j])
- print " ["i"]["j"] = "gtable[i,j]","
- print "};\n"
- # print AVX opcode map's array
- print "/* AVX opcode map array */"
- print "const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1]"\
- "[INAT_LSTPFX_MAX + 1] = {"
- for (i = 0; i < gaid; i++)
- for (j = 0; j < max_lprefix; j++)
- if (atable[i,j])
- print " ["i"]["j"] = "atable[i,j]","
- print "};"
-}
diff --git a/tools/perf/util/intel-pt-decoder/inat.c b/tools/perf/util/intel-pt-decoder/inat.c
deleted file mode 100644
index 446c0413a27c..000000000000
--- a/tools/perf/util/intel-pt-decoder/inat.c
+++ /dev/null
@@ -1,82 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * x86 instruction attribute tables
- *
- * Written by Masami Hiramatsu <mhiramat@redhat.com>
- */
-#include "insn.h"
-
-/* Attribute tables are generated from opcode map */
-#include "inat-tables.c"
-
-/* Attribute search APIs */
-insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
-{
- return inat_primary_table[opcode];
-}
-
-int inat_get_last_prefix_id(insn_byte_t last_pfx)
-{
- insn_attr_t lpfx_attr;
-
- lpfx_attr = inat_get_opcode_attribute(last_pfx);
- return inat_last_prefix_id(lpfx_attr);
-}
-
-insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
- insn_attr_t esc_attr)
-{
- const insn_attr_t *table;
- int n;
-
- n = inat_escape_id(esc_attr);
-
- table = inat_escape_tables[n][0];
- if (!table)
- return 0;
- if (inat_has_variant(table[opcode]) && lpfx_id) {
- table = inat_escape_tables[n][lpfx_id];
- if (!table)
- return 0;
- }
- return table[opcode];
-}
-
-insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
- insn_attr_t grp_attr)
-{
- const insn_attr_t *table;
- int n;
-
- n = inat_group_id(grp_attr);
-
- table = inat_group_tables[n][0];
- if (!table)
- return inat_group_common_attribute(grp_attr);
- if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) {
- table = inat_group_tables[n][lpfx_id];
- if (!table)
- return inat_group_common_attribute(grp_attr);
- }
- return table[X86_MODRM_REG(modrm)] |
- inat_group_common_attribute(grp_attr);
-}
-
-insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
- insn_byte_t vex_p)
-{
- const insn_attr_t *table;
- if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX)
- return 0;
- /* At first, this checks the master table */
- table = inat_avx_tables[vex_m][0];
- if (!table)
- return 0;
- if (!inat_is_group(table[opcode]) && vex_p) {
- /* If this is not a group, get attribute directly */
- table = inat_avx_tables[vex_m][vex_p];
- if (!table)
- return 0;
- }
- return table[opcode];
-}
diff --git a/tools/perf/util/intel-pt-decoder/inat_types.h b/tools/perf/util/intel-pt-decoder/inat_types.h
deleted file mode 100644
index b047efa9ddc2..000000000000
--- a/tools/perf/util/intel-pt-decoder/inat_types.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_X86_INAT_TYPES_H
-#define _ASM_X86_INAT_TYPES_H
-/*
- * x86 instruction attributes
- *
- * Written by Masami Hiramatsu <mhiramat@redhat.com>
- */
-
-/* Instruction attributes */
-typedef unsigned int insn_attr_t;
-typedef unsigned char insn_byte_t;
-typedef signed int insn_value_t;
-
-#endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 3bfdf2b7a96a..f8ccfd6be0ee 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -14,9 +14,9 @@
#include <stdint.h>
#include <inttypes.h>
#include <linux/compiler.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
-#include "../cache.h"
#include "../auxtrace.h"
#include "intel-pt-insn-decoder.h"
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 598f56be9f17..fb8a3558d3d5 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -4,17 +4,17 @@
* Copyright (c) 2013-2014, Intel Corporation.
*/
+#include <linux/kernel.h>
#include <stdio.h>
#include <string.h>
#include <endian.h>
#include <byteswap.h>
+#include "../../../arch/x86/include/asm/insn.h"
-#include "event.h"
-
-#include "insn.h"
+#include "../../../arch/x86/lib/inat.c"
+#include "../../../arch/x86/lib/insn.c"
-#include "inat.c"
-#include "insn.c"
+#include "event.h"
#include "intel-pt-insn-decoder.h"
#include "dump-insn.h"
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
deleted file mode 100644
index e0b85930dd77..000000000000
--- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
+++ /dev/null
@@ -1,1072 +0,0 @@
-# x86 Opcode Maps
-#
-# This is (mostly) based on following documentations.
-# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
-# (#326018-047US, June 2013)
-#
-#<Opcode maps>
-# Table: table-name
-# Referrer: escaped-name
-# AVXcode: avx-code
-# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
-# (or)
-# opcode: escape # escaped-name
-# EndTable
-#
-# mnemonics that begin with lowercase 'v' accept a VEX or EVEX prefix
-# mnemonics that begin with lowercase 'k' accept a VEX prefix
-#
-#<group maps>
-# GrpTable: GrpXXX
-# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
-# EndTable
-#
-# AVX Superscripts
-# (ev): this opcode requires EVEX prefix.
-# (evo): this opcode is changed by EVEX prefix (EVEX opcode)
-# (v): this opcode requires VEX prefix.
-# (v1): this opcode only supports 128bit VEX.
-#
-# Last Prefix Superscripts
-# - (66): the last prefix is 0x66
-# - (F3): the last prefix is 0xF3
-# - (F2): the last prefix is 0xF2
-# - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
-# - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
-
-Table: one byte opcode
-Referrer:
-AVXcode:
-# 0x00 - 0x0f
-00: ADD Eb,Gb
-01: ADD Ev,Gv
-02: ADD Gb,Eb
-03: ADD Gv,Ev
-04: ADD AL,Ib
-05: ADD rAX,Iz
-06: PUSH ES (i64)
-07: POP ES (i64)
-08: OR Eb,Gb
-09: OR Ev,Gv
-0a: OR Gb,Eb
-0b: OR Gv,Ev
-0c: OR AL,Ib
-0d: OR rAX,Iz
-0e: PUSH CS (i64)
-0f: escape # 2-byte escape
-# 0x10 - 0x1f
-10: ADC Eb,Gb
-11: ADC Ev,Gv
-12: ADC Gb,Eb
-13: ADC Gv,Ev
-14: ADC AL,Ib
-15: ADC rAX,Iz
-16: PUSH SS (i64)
-17: POP SS (i64)
-18: SBB Eb,Gb
-19: SBB Ev,Gv
-1a: SBB Gb,Eb
-1b: SBB Gv,Ev
-1c: SBB AL,Ib
-1d: SBB rAX,Iz
-1e: PUSH DS (i64)
-1f: POP DS (i64)
-# 0x20 - 0x2f
-20: AND Eb,Gb
-21: AND Ev,Gv
-22: AND Gb,Eb
-23: AND Gv,Ev
-24: AND AL,Ib
-25: AND rAx,Iz
-26: SEG=ES (Prefix)
-27: DAA (i64)
-28: SUB Eb,Gb
-29: SUB Ev,Gv
-2a: SUB Gb,Eb
-2b: SUB Gv,Ev
-2c: SUB AL,Ib
-2d: SUB rAX,Iz
-2e: SEG=CS (Prefix)
-2f: DAS (i64)
-# 0x30 - 0x3f
-30: XOR Eb,Gb
-31: XOR Ev,Gv
-32: XOR Gb,Eb
-33: XOR Gv,Ev
-34: XOR AL,Ib
-35: XOR rAX,Iz
-36: SEG=SS (Prefix)
-37: AAA (i64)
-38: CMP Eb,Gb
-39: CMP Ev,Gv
-3a: CMP Gb,Eb
-3b: CMP Gv,Ev
-3c: CMP AL,Ib
-3d: CMP rAX,Iz
-3e: SEG=DS (Prefix)
-3f: AAS (i64)
-# 0x40 - 0x4f
-40: INC eAX (i64) | REX (o64)
-41: INC eCX (i64) | REX.B (o64)
-42: INC eDX (i64) | REX.X (o64)
-43: INC eBX (i64) | REX.XB (o64)
-44: INC eSP (i64) | REX.R (o64)
-45: INC eBP (i64) | REX.RB (o64)
-46: INC eSI (i64) | REX.RX (o64)
-47: INC eDI (i64) | REX.RXB (o64)
-48: DEC eAX (i64) | REX.W (o64)
-49: DEC eCX (i64) | REX.WB (o64)
-4a: DEC eDX (i64) | REX.WX (o64)
-4b: DEC eBX (i64) | REX.WXB (o64)
-4c: DEC eSP (i64) | REX.WR (o64)
-4d: DEC eBP (i64) | REX.WRB (o64)
-4e: DEC eSI (i64) | REX.WRX (o64)
-4f: DEC eDI (i64) | REX.WRXB (o64)
-# 0x50 - 0x5f
-50: PUSH rAX/r8 (d64)
-51: PUSH rCX/r9 (d64)
-52: PUSH rDX/r10 (d64)
-53: PUSH rBX/r11 (d64)
-54: PUSH rSP/r12 (d64)
-55: PUSH rBP/r13 (d64)
-56: PUSH rSI/r14 (d64)
-57: PUSH rDI/r15 (d64)
-58: POP rAX/r8 (d64)
-59: POP rCX/r9 (d64)
-5a: POP rDX/r10 (d64)
-5b: POP rBX/r11 (d64)
-5c: POP rSP/r12 (d64)
-5d: POP rBP/r13 (d64)
-5e: POP rSI/r14 (d64)
-5f: POP rDI/r15 (d64)
-# 0x60 - 0x6f
-60: PUSHA/PUSHAD (i64)
-61: POPA/POPAD (i64)
-62: BOUND Gv,Ma (i64) | EVEX (Prefix)
-63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
-64: SEG=FS (Prefix)
-65: SEG=GS (Prefix)
-66: Operand-Size (Prefix)
-67: Address-Size (Prefix)
-68: PUSH Iz (d64)
-69: IMUL Gv,Ev,Iz
-6a: PUSH Ib (d64)
-6b: IMUL Gv,Ev,Ib
-6c: INS/INSB Yb,DX
-6d: INS/INSW/INSD Yz,DX
-6e: OUTS/OUTSB DX,Xb
-6f: OUTS/OUTSW/OUTSD DX,Xz
-# 0x70 - 0x7f
-70: JO Jb
-71: JNO Jb
-72: JB/JNAE/JC Jb
-73: JNB/JAE/JNC Jb
-74: JZ/JE Jb
-75: JNZ/JNE Jb
-76: JBE/JNA Jb
-77: JNBE/JA Jb
-78: JS Jb
-79: JNS Jb
-7a: JP/JPE Jb
-7b: JNP/JPO Jb
-7c: JL/JNGE Jb
-7d: JNL/JGE Jb
-7e: JLE/JNG Jb
-7f: JNLE/JG Jb
-# 0x80 - 0x8f
-80: Grp1 Eb,Ib (1A)
-81: Grp1 Ev,Iz (1A)
-82: Grp1 Eb,Ib (1A),(i64)
-83: Grp1 Ev,Ib (1A)
-84: TEST Eb,Gb
-85: TEST Ev,Gv
-86: XCHG Eb,Gb
-87: XCHG Ev,Gv
-88: MOV Eb,Gb
-89: MOV Ev,Gv
-8a: MOV Gb,Eb
-8b: MOV Gv,Ev
-8c: MOV Ev,Sw
-8d: LEA Gv,M
-8e: MOV Sw,Ew
-8f: Grp1A (1A) | POP Ev (d64)
-# 0x90 - 0x9f
-90: NOP | PAUSE (F3) | XCHG r8,rAX
-91: XCHG rCX/r9,rAX
-92: XCHG rDX/r10,rAX
-93: XCHG rBX/r11,rAX
-94: XCHG rSP/r12,rAX
-95: XCHG rBP/r13,rAX
-96: XCHG rSI/r14,rAX
-97: XCHG rDI/r15,rAX
-98: CBW/CWDE/CDQE
-99: CWD/CDQ/CQO
-9a: CALLF Ap (i64)
-9b: FWAIT/WAIT
-9c: PUSHF/D/Q Fv (d64)
-9d: POPF/D/Q Fv (d64)
-9e: SAHF
-9f: LAHF
-# 0xa0 - 0xaf
-a0: MOV AL,Ob
-a1: MOV rAX,Ov
-a2: MOV Ob,AL
-a3: MOV Ov,rAX
-a4: MOVS/B Yb,Xb
-a5: MOVS/W/D/Q Yv,Xv
-a6: CMPS/B Xb,Yb
-a7: CMPS/W/D Xv,Yv
-a8: TEST AL,Ib
-a9: TEST rAX,Iz
-aa: STOS/B Yb,AL
-ab: STOS/W/D/Q Yv,rAX
-ac: LODS/B AL,Xb
-ad: LODS/W/D/Q rAX,Xv
-ae: SCAS/B AL,Yb
-# Note: The May 2011 Intel manual shows Xv for the second parameter of the
-# next instruction but Yv is correct
-af: SCAS/W/D/Q rAX,Yv
-# 0xb0 - 0xbf
-b0: MOV AL/R8L,Ib
-b1: MOV CL/R9L,Ib
-b2: MOV DL/R10L,Ib
-b3: MOV BL/R11L,Ib
-b4: MOV AH/R12L,Ib
-b5: MOV CH/R13L,Ib
-b6: MOV DH/R14L,Ib
-b7: MOV BH/R15L,Ib
-b8: MOV rAX/r8,Iv
-b9: MOV rCX/r9,Iv
-ba: MOV rDX/r10,Iv
-bb: MOV rBX/r11,Iv
-bc: MOV rSP/r12,Iv
-bd: MOV rBP/r13,Iv
-be: MOV rSI/r14,Iv
-bf: MOV rDI/r15,Iv
-# 0xc0 - 0xcf
-c0: Grp2 Eb,Ib (1A)
-c1: Grp2 Ev,Ib (1A)
-c2: RETN Iw (f64)
-c3: RETN
-c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
-c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
-c6: Grp11A Eb,Ib (1A)
-c7: Grp11B Ev,Iz (1A)
-c8: ENTER Iw,Ib
-c9: LEAVE (d64)
-ca: RETF Iw
-cb: RETF
-cc: INT3
-cd: INT Ib
-ce: INTO (i64)
-cf: IRET/D/Q
-# 0xd0 - 0xdf
-d0: Grp2 Eb,1 (1A)
-d1: Grp2 Ev,1 (1A)
-d2: Grp2 Eb,CL (1A)
-d3: Grp2 Ev,CL (1A)
-d4: AAM Ib (i64)
-d5: AAD Ib (i64)
-d6:
-d7: XLAT/XLATB
-d8: ESC
-d9: ESC
-da: ESC
-db: ESC
-dc: ESC
-dd: ESC
-de: ESC
-df: ESC
-# 0xe0 - 0xef
-# Note: "forced64" is Intel CPU behavior: they ignore 0x66 prefix
-# in 64-bit mode. AMD CPUs accept 0x66 prefix, it causes RIP truncation
-# to 16 bits. In 32-bit mode, 0x66 is accepted by both Intel and AMD.
-e0: LOOPNE/LOOPNZ Jb (f64)
-e1: LOOPE/LOOPZ Jb (f64)
-e2: LOOP Jb (f64)
-e3: JrCXZ Jb (f64)
-e4: IN AL,Ib
-e5: IN eAX,Ib
-e6: OUT Ib,AL
-e7: OUT Ib,eAX
-# With 0x66 prefix in 64-bit mode, for AMD CPUs immediate offset
-# in "near" jumps and calls is 16-bit. For CALL,
-# push of return address is 16-bit wide, RSP is decremented by 2
-# but is not truncated to 16 bits, unlike RIP.
-e8: CALL Jz (f64)
-e9: JMP-near Jz (f64)
-ea: JMP-far Ap (i64)
-eb: JMP-short Jb (f64)
-ec: IN AL,DX
-ed: IN eAX,DX
-ee: OUT DX,AL
-ef: OUT DX,eAX
-# 0xf0 - 0xff
-f0: LOCK (Prefix)
-f1:
-f2: REPNE (Prefix) | XACQUIRE (Prefix)
-f3: REP/REPE (Prefix) | XRELEASE (Prefix)
-f4: HLT
-f5: CMC
-f6: Grp3_1 Eb (1A)
-f7: Grp3_2 Ev (1A)
-f8: CLC
-f9: STC
-fa: CLI
-fb: STI
-fc: CLD
-fd: STD
-fe: Grp4 (1A)
-ff: Grp5 (1A)
-EndTable
-
-Table: 2-byte opcode (0x0f)
-Referrer: 2-byte escape
-AVXcode: 1
-# 0x0f 0x00-0x0f
-00: Grp6 (1A)
-01: Grp7 (1A)
-02: LAR Gv,Ew
-03: LSL Gv,Ew
-04:
-05: SYSCALL (o64)
-06: CLTS
-07: SYSRET (o64)
-08: INVD
-09: WBINVD
-0a:
-0b: UD2 (1B)
-0c:
-# AMD's prefetch group. Intel supports prefetchw(/1) only.
-0d: GrpP
-0e: FEMMS
-# 3DNow! uses the last imm byte as opcode extension.
-0f: 3DNow! Pq,Qq,Ib
-# 0x0f 0x10-0x1f
-# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands
-# but it actually has operands. And also, vmovss and vmovsd only accept 128bit.
-# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form.
-# Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming
-# Reference A.1
-10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1)
-11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1)
-12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
-13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
-14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
-15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
-16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3)
-17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
-18: Grp16 (1A)
-19:
-# Intel SDM opcode map does not list MPX instructions. For now using Gv for
-# bnd registers and Ev for everything else is OK because the instruction
-# decoder does not use the information except as an indication that there is
-# a ModR/M byte.
-1a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev
-1b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv
-1c:
-1d:
-1e:
-1f: NOP Ev
-# 0x0f 0x20-0x2f
-20: MOV Rd,Cd
-21: MOV Rd,Dd
-22: MOV Cd,Rd
-23: MOV Dd,Rd
-24:
-25:
-26:
-27:
-28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
-29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
-2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
-2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
-2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
-2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
-2e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1)
-2f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1)
-# 0x0f 0x30-0x3f
-30: WRMSR
-31: RDTSC
-32: RDMSR
-33: RDPMC
-34: SYSENTER
-35: SYSEXIT
-36:
-37: GETSEC
-38: escape # 3-byte escape 1
-39:
-3a: escape # 3-byte escape 2
-3b:
-3c:
-3d:
-3e:
-3f:
-# 0x0f 0x40-0x4f
-40: CMOVO Gv,Ev
-41: CMOVNO Gv,Ev | kandw/q Vk,Hk,Uk | kandb/d Vk,Hk,Uk (66)
-42: CMOVB/C/NAE Gv,Ev | kandnw/q Vk,Hk,Uk | kandnb/d Vk,Hk,Uk (66)
-43: CMOVAE/NB/NC Gv,Ev
-44: CMOVE/Z Gv,Ev | knotw/q Vk,Uk | knotb/d Vk,Uk (66)
-45: CMOVNE/NZ Gv,Ev | korw/q Vk,Hk,Uk | korb/d Vk,Hk,Uk (66)
-46: CMOVBE/NA Gv,Ev | kxnorw/q Vk,Hk,Uk | kxnorb/d Vk,Hk,Uk (66)
-47: CMOVA/NBE Gv,Ev | kxorw/q Vk,Hk,Uk | kxorb/d Vk,Hk,Uk (66)
-48: CMOVS Gv,Ev
-49: CMOVNS Gv,Ev
-4a: CMOVP/PE Gv,Ev | kaddw/q Vk,Hk,Uk | kaddb/d Vk,Hk,Uk (66)
-4b: CMOVNP/PO Gv,Ev | kunpckbw Vk,Hk,Uk (66) | kunpckwd/dq Vk,Hk,Uk
-4c: CMOVL/NGE Gv,Ev
-4d: CMOVNL/GE Gv,Ev
-4e: CMOVLE/NG Gv,Ev
-4f: CMOVNLE/G Gv,Ev
-# 0x0f 0x50-0x5f
-50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
-51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
-52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
-53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
-54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
-55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
-56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
-57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
-58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
-59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
-5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
-5b: vcvtdq2ps Vps,Wdq | vcvtqq2ps Vps,Wqq (evo) | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
-5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
-5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
-5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
-5f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
-# 0x0f 0x60-0x6f
-60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
-61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
-62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
-63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
-64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
-65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
-66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
-67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
-68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
-69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
-6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
-6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
-6c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
-6d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
-6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
-6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqa32/64 Vx,Wx (66),(evo) | vmovdqu Vx,Wx (F3) | vmovdqu32/64 Vx,Wx (F3),(evo) | vmovdqu8/16 Vx,Wx (F2),(ev)
-# 0x0f 0x70-0x7f
-70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
-71: Grp12 (1A)
-72: Grp13 (1A)
-73: Grp14 (1A)
-74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
-75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
-76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
-# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
-77: emms | vzeroupper | vzeroall
-78: VMREAD Ey,Gy | vcvttps2udq/pd2udq Vx,Wpd (evo) | vcvttsd2usi Gv,Wx (F2),(ev) | vcvttss2usi Gv,Wx (F3),(ev) | vcvttps2uqq/pd2uqq Vx,Wx (66),(ev)
-79: VMWRITE Gy,Ey | vcvtps2udq/pd2udq Vx,Wpd (evo) | vcvtsd2usi Gv,Wx (F2),(ev) | vcvtss2usi Gv,Wx (F3),(ev) | vcvtps2uqq/pd2uqq Vx,Wx (66),(ev)
-7a: vcvtudq2pd/uqq2pd Vpd,Wx (F3),(ev) | vcvtudq2ps/uqq2ps Vpd,Wx (F2),(ev) | vcvttps2qq/pd2qq Vx,Wx (66),(ev)
-7b: vcvtusi2sd Vpd,Hpd,Ev (F2),(ev) | vcvtusi2ss Vps,Hps,Ev (F3),(ev) | vcvtps2qq/pd2qq Vx,Wx (66),(ev)
-7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
-7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
-7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
-7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqa32/64 Wx,Vx (66),(evo) | vmovdqu Wx,Vx (F3) | vmovdqu32/64 Wx,Vx (F3),(evo) | vmovdqu8/16 Wx,Vx (F2),(ev)
-# 0x0f 0x80-0x8f
-# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
-80: JO Jz (f64)
-81: JNO Jz (f64)
-82: JB/JC/JNAE Jz (f64)
-83: JAE/JNB/JNC Jz (f64)
-84: JE/JZ Jz (f64)
-85: JNE/JNZ Jz (f64)
-86: JBE/JNA Jz (f64)
-87: JA/JNBE Jz (f64)
-88: JS Jz (f64)
-89: JNS Jz (f64)
-8a: JP/JPE Jz (f64)
-8b: JNP/JPO Jz (f64)
-8c: JL/JNGE Jz (f64)
-8d: JNL/JGE Jz (f64)
-8e: JLE/JNG Jz (f64)
-8f: JNLE/JG Jz (f64)
-# 0x0f 0x90-0x9f
-90: SETO Eb | kmovw/q Vk,Wk | kmovb/d Vk,Wk (66)
-91: SETNO Eb | kmovw/q Mv,Vk | kmovb/d Mv,Vk (66)
-92: SETB/C/NAE Eb | kmovw Vk,Rv | kmovb Vk,Rv (66) | kmovq/d Vk,Rv (F2)
-93: SETAE/NB/NC Eb | kmovw Gv,Uk | kmovb Gv,Uk (66) | kmovq/d Gv,Uk (F2)
-94: SETE/Z Eb
-95: SETNE/NZ Eb
-96: SETBE/NA Eb
-97: SETA/NBE Eb
-98: SETS Eb | kortestw/q Vk,Uk | kortestb/d Vk,Uk (66)
-99: SETNS Eb | ktestw/q Vk,Uk | ktestb/d Vk,Uk (66)
-9a: SETP/PE Eb
-9b: SETNP/PO Eb
-9c: SETL/NGE Eb
-9d: SETNL/GE Eb
-9e: SETLE/NG Eb
-9f: SETNLE/G Eb
-# 0x0f 0xa0-0xaf
-a0: PUSH FS (d64)
-a1: POP FS (d64)
-a2: CPUID
-a3: BT Ev,Gv
-a4: SHLD Ev,Gv,Ib
-a5: SHLD Ev,Gv,CL
-a6: GrpPDLK
-a7: GrpRNG
-a8: PUSH GS (d64)
-a9: POP GS (d64)
-aa: RSM
-ab: BTS Ev,Gv
-ac: SHRD Ev,Gv,Ib
-ad: SHRD Ev,Gv,CL
-ae: Grp15 (1A),(1C)
-af: IMUL Gv,Ev
-# 0x0f 0xb0-0xbf
-b0: CMPXCHG Eb,Gb
-b1: CMPXCHG Ev,Gv
-b2: LSS Gv,Mp
-b3: BTR Ev,Gv
-b4: LFS Gv,Mp
-b5: LGS Gv,Mp
-b6: MOVZX Gv,Eb
-b7: MOVZX Gv,Ew
-b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
-b9: Grp10 (1A)
-ba: Grp8 Ev,Ib (1A)
-bb: BTC Ev,Gv
-bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
-bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
-be: MOVSX Gv,Eb
-bf: MOVSX Gv,Ew
-# 0x0f 0xc0-0xcf
-c0: XADD Eb,Gb
-c1: XADD Ev,Gv
-c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
-c3: movnti My,Gy
-c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
-c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
-c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
-c7: Grp9 (1A)
-c8: BSWAP RAX/EAX/R8/R8D
-c9: BSWAP RCX/ECX/R9/R9D
-ca: BSWAP RDX/EDX/R10/R10D
-cb: BSWAP RBX/EBX/R11/R11D
-cc: BSWAP RSP/ESP/R12/R12D
-cd: BSWAP RBP/EBP/R13/R13D
-ce: BSWAP RSI/ESI/R14/R14D
-cf: BSWAP RDI/EDI/R15/R15D
-# 0x0f 0xd0-0xdf
-d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
-d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
-d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
-d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
-d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
-d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
-d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
-d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
-d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
-d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
-da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
-db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | vpandd/q Vx,Hx,Wx (66),(evo)
-dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
-dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
-de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
-df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | vpandnd/q Vx,Hx,Wx (66),(evo)
-# 0x0f 0xe0-0xef
-e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
-e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
-e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
-e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
-e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
-e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
-e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtdq2pd/qq2pd Vx,Wdq (F3),(evo) | vcvtpd2dq Vx,Wpd (F2)
-e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
-e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
-e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
-ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
-eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | vpord/q Vx,Hx,Wx (66),(evo)
-ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
-ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
-ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
-ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | vpxord/q Vx,Hx,Wx (66),(evo)
-# 0x0f 0xf0-0xff
-f0: vlddqu Vx,Mx (F2)
-f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
-f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
-f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
-f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
-f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
-f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
-f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
-f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
-f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
-fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
-fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
-fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
-fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
-fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
-ff: UD0
-EndTable
-
-Table: 3-byte opcode 1 (0x0f 0x38)
-Referrer: 3-byte escape 1
-AVXcode: 2
-# 0x0f 0x38 0x00-0x0f
-00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
-01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
-02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
-03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
-04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
-05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
-06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
-07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
-08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
-09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
-0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
-0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
-0c: vpermilps Vx,Hx,Wx (66),(v)
-0d: vpermilpd Vx,Hx,Wx (66),(v)
-0e: vtestps Vx,Wx (66),(v)
-0f: vtestpd Vx,Wx (66),(v)
-# 0x0f 0x38 0x10-0x1f
-10: pblendvb Vdq,Wdq (66) | vpsrlvw Vx,Hx,Wx (66),(evo) | vpmovuswb Wx,Vx (F3),(ev)
-11: vpmovusdb Wx,Vd (F3),(ev) | vpsravw Vx,Hx,Wx (66),(ev)
-12: vpmovusqb Wx,Vq (F3),(ev) | vpsllvw Vx,Hx,Wx (66),(ev)
-13: vcvtph2ps Vx,Wx (66),(v) | vpmovusdw Wx,Vd (F3),(ev)
-14: blendvps Vdq,Wdq (66) | vpmovusqw Wx,Vq (F3),(ev) | vprorvd/q Vx,Hx,Wx (66),(evo)
-15: blendvpd Vdq,Wdq (66) | vpmovusqd Wx,Vq (F3),(ev) | vprolvd/q Vx,Hx,Wx (66),(evo)
-16: vpermps Vqq,Hqq,Wqq (66),(v) | vpermps/d Vqq,Hqq,Wqq (66),(evo)
-17: vptest Vx,Wx (66)
-18: vbroadcastss Vx,Wd (66),(v)
-19: vbroadcastsd Vqq,Wq (66),(v) | vbroadcastf32x2 Vqq,Wq (66),(evo)
-1a: vbroadcastf128 Vqq,Mdq (66),(v) | vbroadcastf32x4/64x2 Vqq,Wq (66),(evo)
-1b: vbroadcastf32x8/64x4 Vqq,Mdq (66),(ev)
-1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
-1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
-1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
-1f: vpabsq Vx,Wx (66),(ev)
-# 0x0f 0x38 0x20-0x2f
-20: vpmovsxbw Vx,Ux/Mq (66),(v1) | vpmovswb Wx,Vx (F3),(ev)
-21: vpmovsxbd Vx,Ux/Md (66),(v1) | vpmovsdb Wx,Vd (F3),(ev)
-22: vpmovsxbq Vx,Ux/Mw (66),(v1) | vpmovsqb Wx,Vq (F3),(ev)
-23: vpmovsxwd Vx,Ux/Mq (66),(v1) | vpmovsdw Wx,Vd (F3),(ev)
-24: vpmovsxwq Vx,Ux/Md (66),(v1) | vpmovsqw Wx,Vq (F3),(ev)
-25: vpmovsxdq Vx,Ux/Mq (66),(v1) | vpmovsqd Wx,Vq (F3),(ev)
-26: vptestmb/w Vk,Hx,Wx (66),(ev) | vptestnmb/w Vk,Hx,Wx (F3),(ev)
-27: vptestmd/q Vk,Hx,Wx (66),(ev) | vptestnmd/q Vk,Hx,Wx (F3),(ev)
-28: vpmuldq Vx,Hx,Wx (66),(v1) | vpmovm2b/w Vx,Uk (F3),(ev)
-29: vpcmpeqq Vx,Hx,Wx (66),(v1) | vpmovb2m/w2m Vk,Ux (F3),(ev)
-2a: vmovntdqa Vx,Mx (66),(v1) | vpbroadcastmb2q Vx,Uk (F3),(ev)
-2b: vpackusdw Vx,Hx,Wx (66),(v1)
-2c: vmaskmovps Vx,Hx,Mx (66),(v) | vscalefps/d Vx,Hx,Wx (66),(evo)
-2d: vmaskmovpd Vx,Hx,Mx (66),(v) | vscalefss/d Vx,Hx,Wx (66),(evo)
-2e: vmaskmovps Mx,Hx,Vx (66),(v)
-2f: vmaskmovpd Mx,Hx,Vx (66),(v)
-# 0x0f 0x38 0x30-0x3f
-30: vpmovzxbw Vx,Ux/Mq (66),(v1) | vpmovwb Wx,Vx (F3),(ev)
-31: vpmovzxbd Vx,Ux/Md (66),(v1) | vpmovdb Wx,Vd (F3),(ev)
-32: vpmovzxbq Vx,Ux/Mw (66),(v1) | vpmovqb Wx,Vq (F3),(ev)
-33: vpmovzxwd Vx,Ux/Mq (66),(v1) | vpmovdw Wx,Vd (F3),(ev)
-34: vpmovzxwq Vx,Ux/Md (66),(v1) | vpmovqw Wx,Vq (F3),(ev)
-35: vpmovzxdq Vx,Ux/Mq (66),(v1) | vpmovqd Wx,Vq (F3),(ev)
-36: vpermd Vqq,Hqq,Wqq (66),(v) | vpermd/q Vqq,Hqq,Wqq (66),(evo)
-37: vpcmpgtq Vx,Hx,Wx (66),(v1)
-38: vpminsb Vx,Hx,Wx (66),(v1) | vpmovm2d/q Vx,Uk (F3),(ev)
-39: vpminsd Vx,Hx,Wx (66),(v1) | vpminsd/q Vx,Hx,Wx (66),(evo) | vpmovd2m/q2m Vk,Ux (F3),(ev)
-3a: vpminuw Vx,Hx,Wx (66),(v1) | vpbroadcastmw2d Vx,Uk (F3),(ev)
-3b: vpminud Vx,Hx,Wx (66),(v1) | vpminud/q Vx,Hx,Wx (66),(evo)
-3c: vpmaxsb Vx,Hx,Wx (66),(v1)
-3d: vpmaxsd Vx,Hx,Wx (66),(v1) | vpmaxsd/q Vx,Hx,Wx (66),(evo)
-3e: vpmaxuw Vx,Hx,Wx (66),(v1)
-3f: vpmaxud Vx,Hx,Wx (66),(v1) | vpmaxud/q Vx,Hx,Wx (66),(evo)
-# 0x0f 0x38 0x40-0x8f
-40: vpmulld Vx,Hx,Wx (66),(v1) | vpmulld/q Vx,Hx,Wx (66),(evo)
-41: vphminposuw Vdq,Wdq (66),(v1)
-42: vgetexpps/d Vx,Wx (66),(ev)
-43: vgetexpss/d Vx,Hx,Wx (66),(ev)
-44: vplzcntd/q Vx,Wx (66),(ev)
-45: vpsrlvd/q Vx,Hx,Wx (66),(v)
-46: vpsravd Vx,Hx,Wx (66),(v) | vpsravd/q Vx,Hx,Wx (66),(evo)
-47: vpsllvd/q Vx,Hx,Wx (66),(v)
-# Skip 0x48-0x4b
-4c: vrcp14ps/d Vpd,Wpd (66),(ev)
-4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev)
-4e: vrsqrt14ps/d Vpd,Wpd (66),(ev)
-4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev)
-# Skip 0x50-0x57
-58: vpbroadcastd Vx,Wx (66),(v)
-59: vpbroadcastq Vx,Wx (66),(v) | vbroadcasti32x2 Vx,Wx (66),(evo)
-5a: vbroadcasti128 Vqq,Mdq (66),(v) | vbroadcasti32x4/64x2 Vx,Wx (66),(evo)
-5b: vbroadcasti32x8/64x4 Vqq,Mdq (66),(ev)
-# Skip 0x5c-0x63
-64: vpblendmd/q Vx,Hx,Wx (66),(ev)
-65: vblendmps/d Vx,Hx,Wx (66),(ev)
-66: vpblendmb/w Vx,Hx,Wx (66),(ev)
-# Skip 0x67-0x74
-75: vpermi2b/w Vx,Hx,Wx (66),(ev)
-76: vpermi2d/q Vx,Hx,Wx (66),(ev)
-77: vpermi2ps/d Vx,Hx,Wx (66),(ev)
-78: vpbroadcastb Vx,Wx (66),(v)
-79: vpbroadcastw Vx,Wx (66),(v)
-7a: vpbroadcastb Vx,Rv (66),(ev)
-7b: vpbroadcastw Vx,Rv (66),(ev)
-7c: vpbroadcastd/q Vx,Rv (66),(ev)
-7d: vpermt2b/w Vx,Hx,Wx (66),(ev)
-7e: vpermt2d/q Vx,Hx,Wx (66),(ev)
-7f: vpermt2ps/d Vx,Hx,Wx (66),(ev)
-80: INVEPT Gy,Mdq (66)
-81: INVVPID Gy,Mdq (66)
-82: INVPCID Gy,Mdq (66)
-83: vpmultishiftqb Vx,Hx,Wx (66),(ev)
-88: vexpandps/d Vpd,Wpd (66),(ev)
-89: vpexpandd/q Vx,Wx (66),(ev)
-8a: vcompressps/d Wx,Vx (66),(ev)
-8b: vpcompressd/q Wx,Vx (66),(ev)
-8c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
-8d: vpermb/w Vx,Hx,Wx (66),(ev)
-8e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
-# 0x0f 0x38 0x90-0xbf (FMA)
-90: vgatherdd/q Vx,Hx,Wx (66),(v) | vpgatherdd/q Vx,Wx (66),(evo)
-91: vgatherqd/q Vx,Hx,Wx (66),(v) | vpgatherqd/q Vx,Wx (66),(evo)
-92: vgatherdps/d Vx,Hx,Wx (66),(v)
-93: vgatherqps/d Vx,Hx,Wx (66),(v)
-94:
-95:
-96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
-97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
-98: vfmadd132ps/d Vx,Hx,Wx (66),(v)
-99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
-9a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
-9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
-9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
-9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
-9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
-9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
-a0: vpscatterdd/q Wx,Vx (66),(ev)
-a1: vpscatterqd/q Wx,Vx (66),(ev)
-a2: vscatterdps/d Wx,Vx (66),(ev)
-a3: vscatterqps/d Wx,Vx (66),(ev)
-a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
-a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
-a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
-a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
-aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
-ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
-ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
-ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
-ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
-af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
-b4: vpmadd52luq Vx,Hx,Wx (66),(ev)
-b5: vpmadd52huq Vx,Hx,Wx (66),(ev)
-b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
-b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
-b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
-b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
-ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
-bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
-bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
-bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
-be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
-bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
-# 0x0f 0x38 0xc0-0xff
-c4: vpconflictd/q Vx,Wx (66),(ev)
-c6: Grp18 (1A)
-c7: Grp19 (1A)
-c8: sha1nexte Vdq,Wdq | vexp2ps/d Vx,Wx (66),(ev)
-c9: sha1msg1 Vdq,Wdq
-ca: sha1msg2 Vdq,Wdq | vrcp28ps/d Vx,Wx (66),(ev)
-cb: sha256rnds2 Vdq,Wdq | vrcp28ss/d Vx,Hx,Wx (66),(ev)
-cc: sha256msg1 Vdq,Wdq | vrsqrt28ps/d Vx,Wx (66),(ev)
-cd: sha256msg2 Vdq,Wdq | vrsqrt28ss/d Vx,Hx,Wx (66),(ev)
-db: VAESIMC Vdq,Wdq (66),(v1)
-dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
-dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
-de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
-df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
-f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
-f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
-f2: ANDN Gy,By,Ey (v)
-f3: Grp17 (1A)
-f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
-f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
-f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
-EndTable
-
-Table: 3-byte opcode 2 (0x0f 0x3a)
-Referrer: 3-byte escape 2
-AVXcode: 3
-# 0x0f 0x3a 0x00-0xff
-00: vpermq Vqq,Wqq,Ib (66),(v)
-01: vpermpd Vqq,Wqq,Ib (66),(v)
-02: vpblendd Vx,Hx,Wx,Ib (66),(v)
-03: valignd/q Vx,Hx,Wx,Ib (66),(ev)
-04: vpermilps Vx,Wx,Ib (66),(v)
-05: vpermilpd Vx,Wx,Ib (66),(v)
-06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
-07:
-08: vroundps Vx,Wx,Ib (66) | vrndscaleps Vx,Wx,Ib (66),(evo)
-09: vroundpd Vx,Wx,Ib (66) | vrndscalepd Vx,Wx,Ib (66),(evo)
-0a: vroundss Vss,Wss,Ib (66),(v1) | vrndscaless Vx,Hx,Wx,Ib (66),(evo)
-0b: vroundsd Vsd,Wsd,Ib (66),(v1) | vrndscalesd Vx,Hx,Wx,Ib (66),(evo)
-0c: vblendps Vx,Hx,Wx,Ib (66)
-0d: vblendpd Vx,Hx,Wx,Ib (66)
-0e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
-0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
-14: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
-15: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
-16: vpextrd/q Ey,Vdq,Ib (66),(v1)
-17: vextractps Ed,Vdq,Ib (66),(v1)
-18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | vinsertf32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo)
-19: vextractf128 Wdq,Vqq,Ib (66),(v) | vextractf32x4/64x2 Wdq,Vqq,Ib (66),(evo)
-1a: vinsertf32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev)
-1b: vextractf32x8/64x4 Wdq,Vqq,Ib (66),(ev)
-1d: vcvtps2ph Wx,Vx,Ib (66),(v)
-1e: vpcmpud/q Vk,Hd,Wd,Ib (66),(ev)
-1f: vpcmpd/q Vk,Hd,Wd,Ib (66),(ev)
-20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
-21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
-22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
-23: vshuff32x4/64x2 Vx,Hx,Wx,Ib (66),(ev)
-25: vpternlogd/q Vx,Hx,Wx,Ib (66),(ev)
-26: vgetmantps/d Vx,Wx,Ib (66),(ev)
-27: vgetmantss/d Vx,Hx,Wx,Ib (66),(ev)
-30: kshiftrb/w Vk,Uk,Ib (66),(v)
-31: kshiftrd/q Vk,Uk,Ib (66),(v)
-32: kshiftlb/w Vk,Uk,Ib (66),(v)
-33: kshiftld/q Vk,Uk,Ib (66),(v)
-38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | vinserti32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo)
-39: vextracti128 Wdq,Vqq,Ib (66),(v) | vextracti32x4/64x2 Wdq,Vqq,Ib (66),(evo)
-3a: vinserti32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev)
-3b: vextracti32x8/64x4 Wdq,Vqq,Ib (66),(ev)
-3e: vpcmpub/w Vk,Hk,Wx,Ib (66),(ev)
-3f: vpcmpb/w Vk,Hk,Wx,Ib (66),(ev)
-40: vdpps Vx,Hx,Wx,Ib (66)
-41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
-42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | vdbpsadbw Vx,Hx,Wx,Ib (66),(evo)
-43: vshufi32x4/64x2 Vx,Hx,Wx,Ib (66),(ev)
-44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
-46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
-4a: vblendvps Vx,Hx,Wx,Lx (66),(v)
-4b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
-4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
-50: vrangeps/d Vx,Hx,Wx,Ib (66),(ev)
-51: vrangess/d Vx,Hx,Wx,Ib (66),(ev)
-54: vfixupimmps/d Vx,Hx,Wx,Ib (66),(ev)
-55: vfixupimmss/d Vx,Hx,Wx,Ib (66),(ev)
-56: vreduceps/d Vx,Wx,Ib (66),(ev)
-57: vreducess/d Vx,Hx,Wx,Ib (66),(ev)
-60: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
-61: vpcmpestri Vdq,Wdq,Ib (66),(v1)
-62: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
-63: vpcmpistri Vdq,Wdq,Ib (66),(v1)
-66: vfpclassps/d Vk,Wx,Ib (66),(ev)
-67: vfpclassss/d Vk,Wx,Ib (66),(ev)
-cc: sha1rnds4 Vdq,Wdq,Ib
-df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
-f0: RORX Gy,Ey,Ib (F2),(v)
-EndTable
-
-GrpTable: Grp1
-0: ADD
-1: OR
-2: ADC
-3: SBB
-4: AND
-5: SUB
-6: XOR
-7: CMP
-EndTable
-
-GrpTable: Grp1A
-0: POP
-EndTable
-
-GrpTable: Grp2
-0: ROL
-1: ROR
-2: RCL
-3: RCR
-4: SHL/SAL
-5: SHR
-6:
-7: SAR
-EndTable
-
-GrpTable: Grp3_1
-0: TEST Eb,Ib
-1: TEST Eb,Ib
-2: NOT Eb
-3: NEG Eb
-4: MUL AL,Eb
-5: IMUL AL,Eb
-6: DIV AL,Eb
-7: IDIV AL,Eb
-EndTable
-
-GrpTable: Grp3_2
-0: TEST Ev,Iz
-1:
-2: NOT Ev
-3: NEG Ev
-4: MUL rAX,Ev
-5: IMUL rAX,Ev
-6: DIV rAX,Ev
-7: IDIV rAX,Ev
-EndTable
-
-GrpTable: Grp4
-0: INC Eb
-1: DEC Eb
-EndTable
-
-GrpTable: Grp5
-0: INC Ev
-1: DEC Ev
-# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
-2: CALLN Ev (f64)
-3: CALLF Ep
-4: JMPN Ev (f64)
-5: JMPF Mp
-6: PUSH Ev (d64)
-7:
-EndTable
-
-GrpTable: Grp6
-0: SLDT Rv/Mw
-1: STR Rv/Mw
-2: LLDT Ew
-3: LTR Ew
-4: VERR Ew
-5: VERW Ew
-EndTable
-
-GrpTable: Grp7
-0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
-1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
-2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
-3: LIDT Ms
-4: SMSW Mw/Rv
-5: rdpkru (110),(11B) | wrpkru (111),(11B)
-6: LMSW Ew
-7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
-EndTable
-
-GrpTable: Grp8
-4: BT
-5: BTS
-6: BTR
-7: BTC
-EndTable
-
-GrpTable: Grp9
-1: CMPXCHG8B/16B Mq/Mdq
-3: xrstors
-4: xsavec
-5: xsaves
-6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
-7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
-EndTable
-
-GrpTable: Grp10
-# all are UD1
-0: UD1
-1: UD1
-2: UD1
-3: UD1
-4: UD1
-5: UD1
-6: UD1
-7: UD1
-EndTable
-
-# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
-GrpTable: Grp11A
-0: MOV Eb,Ib
-7: XABORT Ib (000),(11B)
-EndTable
-
-GrpTable: Grp11B
-0: MOV Eb,Iz
-7: XBEGIN Jz (000),(11B)
-EndTable
-
-GrpTable: Grp12
-2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
-4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
-6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
-EndTable
-
-GrpTable: Grp13
-0: vprord/q Hx,Wx,Ib (66),(ev)
-1: vprold/q Hx,Wx,Ib (66),(ev)
-2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
-4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | vpsrad/q Hx,Ux,Ib (66),(evo)
-6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
-EndTable
-
-GrpTable: Grp14
-2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
-3: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
-6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
-7: vpslldq Hx,Ux,Ib (66),(11B),(v1)
-EndTable
-
-GrpTable: Grp15
-0: fxsave | RDFSBASE Ry (F3),(11B)
-1: fxstor | RDGSBASE Ry (F3),(11B)
-2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
-3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
-4: XSAVE | ptwrite Ey (F3),(11B)
-5: XRSTOR | lfence (11B)
-6: XSAVEOPT | clwb (66) | mfence (11B)
-7: clflush | clflushopt (66) | sfence (11B)
-EndTable
-
-GrpTable: Grp16
-0: prefetch NTA
-1: prefetch T0
-2: prefetch T1
-3: prefetch T2
-EndTable
-
-GrpTable: Grp17
-1: BLSR By,Ey (v)
-2: BLSMSK By,Ey (v)
-3: BLSI By,Ey (v)
-EndTable
-
-GrpTable: Grp18
-1: vgatherpf0dps/d Wx (66),(ev)
-2: vgatherpf1dps/d Wx (66),(ev)
-5: vscatterpf0dps/d Wx (66),(ev)
-6: vscatterpf1dps/d Wx (66),(ev)
-EndTable
-
-GrpTable: Grp19
-1: vgatherpf0qps/d Wx (66),(ev)
-2: vgatherpf1qps/d Wx (66),(ev)
-5: vscatterpf0qps/d Wx (66),(ev)
-6: vscatterpf1qps/d Wx (66),(ev)
-EndTable
-
-# AMD's Prefetch Group
-GrpTable: GrpP
-0: PREFETCH
-1: PREFETCHW
-EndTable
-
-GrpTable: GrpPDLK
-0: MONTMUL
-1: XSHA1
-2: XSHA2
-EndTable
-
-GrpTable: GrpRNG
-0: xstore-rng
-1: xcrypt-ecb
-2: xcrypt-cbc
-4: xcrypt-cfb
-5: xcrypt-ofb
-EndTable
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index df061599fef4..9b56fb74bedf 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -9,10 +9,10 @@
#include <stdbool.h>
#include <errno.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/types.h>
#include <linux/zalloc.h>
-#include "../perf.h"
#include "session.h"
#include "machine.h"
#include "memswap.h"
@@ -56,7 +56,7 @@ struct intel_pt {
u32 auxtrace_type;
struct perf_session *session;
struct machine *machine;
- struct perf_evsel *switch_evsel;
+ struct evsel *switch_evsel;
struct thread *unknown_thread;
bool timeless_decoding;
bool sampling_mode;
@@ -104,7 +104,7 @@ struct intel_pt {
u64 cbr_id;
bool sample_pebs;
- struct perf_evsel *pebs_evsel;
+ struct evsel *pebs_evsel;
u64 tsc_bit;
u64 mtc_bit;
@@ -723,11 +723,11 @@ static bool intel_pt_get_config(struct intel_pt *pt,
static bool intel_pt_exclude_kernel(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
- !evsel->attr.exclude_kernel)
+ if (intel_pt_get_config(pt, &evsel->core.attr, NULL) &&
+ !evsel->core.attr.exclude_kernel)
return false;
}
return true;
@@ -735,14 +735,14 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt)
static bool intel_pt_return_compression(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u64 config;
if (!pt->noretcomp_bit)
return true;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, &config) &&
+ if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&
(config & pt->noretcomp_bit))
return false;
}
@@ -751,11 +751,11 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
static bool intel_pt_branch_enable(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
u64 config;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, &config) &&
+ if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&
(config & 1) && !(config & 0x2000))
return false;
}
@@ -764,7 +764,7 @@ static bool intel_pt_branch_enable(struct intel_pt *pt)
static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
unsigned int shift;
u64 config;
@@ -775,7 +775,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
config >>= 1;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, &config))
+ if (intel_pt_get_config(pt, &evsel->core.attr, &config))
return (config & pt->mtc_freq_bits) >> shift;
}
return 0;
@@ -783,7 +783,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
static bool intel_pt_timeless_decoding(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool timeless_decoding = true;
u64 config;
@@ -791,9 +791,9 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)
return true;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME))
+ if (!(evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
return true;
- if (intel_pt_get_config(pt, &evsel->attr, &config)) {
+ if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {
if (config & pt->tsc_bit)
timeless_decoding = false;
else
@@ -805,11 +805,11 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)
static bool intel_pt_tracing_kernel(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
- !evsel->attr.exclude_kernel)
+ if (intel_pt_get_config(pt, &evsel->core.attr, NULL) &&
+ !evsel->core.attr.exclude_kernel)
return true;
}
return false;
@@ -817,7 +817,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt)
static bool intel_pt_have_tsc(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool have_tsc = false;
u64 config;
@@ -825,7 +825,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt)
return false;
evlist__for_each_entry(pt->session->evlist, evsel) {
- if (intel_pt_get_config(pt, &evsel->attr, &config)) {
+ if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {
if (config & pt->tsc_bit)
have_tsc = true;
else
@@ -1702,8 +1702,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
struct perf_sample sample = { .ip = 0, };
union perf_event *event = ptq->event_buf;
struct intel_pt *pt = ptq->pt;
- struct perf_evsel *evsel = pt->pebs_evsel;
- u64 sample_type = evsel->attr.sample_type;
+ struct evsel *evsel = pt->pebs_evsel;
+ u64 sample_type = evsel->core.attr.sample_type;
u64 id = evsel->id[0];
u8 cpumode;
@@ -1715,8 +1715,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
sample.id = id;
sample.stream_id = id;
- if (!evsel->attr.freq)
- sample.period = evsel->attr.sample_period;
+ if (!evsel->core.attr.freq)
+ sample.period = evsel->core.attr.sample_period;
/* No support for non-zero CS base */
if (items->has_ip)
@@ -1757,7 +1757,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
if (sample_type & PERF_SAMPLE_REGS_INTR &&
items->mask[INTEL_PT_GP_REGS_POS]) {
u64 regs[sizeof(sample.intr_regs.mask)];
- u64 regs_mask = evsel->attr.sample_regs_intr;
+ u64 regs_mask = evsel->core.attr.sample_regs_intr;
u64 *pos;
sample.intr_regs.abi = items->is_32_bit ?
@@ -2401,7 +2401,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
static int intel_pt_process_switch(struct intel_pt *pt,
struct perf_sample *sample)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
pid_t tid;
int cpu, ret;
@@ -2713,10 +2713,10 @@ static int intel_pt_synth_event(struct perf_session *session, const char *name,
return err;
}
-static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id,
+static void intel_pt_set_event_name(struct evlist *evlist, u64 id,
const char *name)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (evsel->id && evsel->id[0] == id) {
@@ -2728,13 +2728,13 @@ static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id,
}
}
-static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt,
- struct perf_evlist *evlist)
+static struct evsel *intel_pt_evsel(struct intel_pt *pt,
+ struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type == pt->pmu_type && evsel->ids)
+ if (evsel->core.attr.type == pt->pmu_type && evsel->ids)
return evsel;
}
@@ -2744,8 +2744,8 @@ static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt,
static int intel_pt_synth_events(struct intel_pt *pt,
struct perf_session *session)
{
- struct perf_evlist *evlist = session->evlist;
- struct perf_evsel *evsel = intel_pt_evsel(pt, evlist);
+ struct evlist *evlist = session->evlist;
+ struct evsel *evsel = intel_pt_evsel(pt, evlist);
struct perf_event_attr attr;
u64 id;
int err;
@@ -2758,7 +2758,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.size = sizeof(struct perf_event_attr);
attr.type = PERF_TYPE_HARDWARE;
- attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK;
+ attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
PERF_SAMPLE_PERIOD;
if (pt->timeless_decoding)
@@ -2767,13 +2767,13 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_type |= PERF_SAMPLE_TIME;
if (!pt->per_cpu_mmaps)
attr.sample_type &= ~(u64)PERF_SAMPLE_CPU;
- attr.exclude_user = evsel->attr.exclude_user;
- attr.exclude_kernel = evsel->attr.exclude_kernel;
- attr.exclude_hv = evsel->attr.exclude_hv;
- attr.exclude_host = evsel->attr.exclude_host;
- attr.exclude_guest = evsel->attr.exclude_guest;
- attr.sample_id_all = evsel->attr.sample_id_all;
- attr.read_format = evsel->attr.read_format;
+ attr.exclude_user = evsel->core.attr.exclude_user;
+ attr.exclude_kernel = evsel->core.attr.exclude_kernel;
+ attr.exclude_hv = evsel->core.attr.exclude_hv;
+ attr.exclude_host = evsel->core.attr.exclude_host;
+ attr.exclude_guest = evsel->core.attr.exclude_guest;
+ attr.sample_id_all = evsel->core.attr.sample_id_all;
+ attr.read_format = evsel->core.attr.read_format;
id = evsel->id[0] + 1000000000;
if (!id)
@@ -2857,7 +2857,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
id += 1;
}
- if (pt->synth_opts.pwr_events && (evsel->attr.config & 0x10)) {
+ if (pt->synth_opts.pwr_events && (evsel->core.attr.config & 0x10)) {
attr.config = PERF_SYNTH_INTEL_MWAIT;
err = intel_pt_synth_event(session, "mwait", &attr, id);
if (err)
@@ -2894,9 +2894,25 @@ static int intel_pt_synth_events(struct intel_pt *pt,
return 0;
}
-static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
+static void intel_pt_setup_pebs_events(struct intel_pt *pt)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
+
+ if (!pt->synth_opts.other_events)
+ return;
+
+ evlist__for_each_entry(pt->session->evlist, evsel) {
+ if (evsel->core.attr.aux_output && evsel->id) {
+ pt->sample_pebs = true;
+ pt->pebs_evsel = evsel;
+ return;
+ }
+ }
+}
+
+static struct evsel *intel_pt_find_sched_switch(struct evlist *evlist)
+{
+ struct evsel *evsel;
evlist__for_each_entry_reverse(evlist, evsel) {
const char *name = perf_evsel__name(evsel);
@@ -2908,12 +2924,12 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
return NULL;
}
-static bool intel_pt_find_switch(struct perf_evlist *evlist)
+static bool intel_pt_find_switch(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.context_switch)
+ if (evsel->core.attr.context_switch)
return true;
}
@@ -3028,7 +3044,7 @@ static const char * const intel_pt_info_fmts[] = {
[INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n",
};
-static void intel_pt_print_info(u64 *arr, int start, int finish)
+static void intel_pt_print_info(__u64 *arr, int start, int finish)
{
int i;
@@ -3047,23 +3063,23 @@ static void intel_pt_print_info_str(const char *name, const char *str)
fprintf(stdout, " %-20s%s\n", name, str ? str : "");
}
-static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
+static bool intel_pt_has(struct perf_record_auxtrace_info *auxtrace_info, int pos)
{
return auxtrace_info->header.size >=
- sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
+ sizeof(struct perf_record_auxtrace_info) + (sizeof(u64) * (pos + 1));
}
int intel_pt_process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
struct intel_pt *pt;
void *info_end;
- u64 *info;
+ __u64 *info;
int err;
- if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
+ if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
min_sz)
return -EINVAL;
@@ -3263,6 +3279,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
if (err)
goto err_delete_thread;
+ intel_pt_setup_pebs_events(pt);
+
err = auxtrace_queues__process_index(&pt->queues, session);
if (err)
goto err_delete_thread;
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index 18c34f0c1966..b80f29bfc7bb 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -14,6 +14,7 @@
#include <sys/mman.h>
#include <linux/stringify.h>
+#include "build-id.h"
#include "util.h"
#include "event.h"
#include "debug.h"
@@ -118,13 +119,13 @@ jit_close(struct jit_buf_desc *jd)
static int
jit_validate_events(struct perf_session *session)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
/*
* check that all events use CLOCK_MONOTONIC
*/
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC)
+ if (evsel->core.attr.use_clockid == 0 || evsel->core.attr.clockid != CLOCK_MONOTONIC)
return -1;
}
return 0;
@@ -758,7 +759,7 @@ jit_process(struct perf_session *session,
pid_t pid,
u64 *nbytes)
{
- struct perf_evsel *first;
+ struct evsel *first;
struct jit_buf_desc jd;
int ret;
@@ -779,7 +780,7 @@ jit_process(struct perf_session *session,
* perf sets the same sample type to all events as of now
*/
first = perf_evlist__first(session->evlist);
- jd.sample_type = first->attr.sample_type;
+ jd.sample_type = first->core.attr.sample_type;
*nbytes = 0;
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 1403dec189b4..46913637085b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -2,12 +2,12 @@
#ifndef __PERF_KVM_STAT_H
#define __PERF_KVM_STAT_H
-#include "../perf.h"
#include "tool.h"
#include "stat.h"
+#include "record.h"
-struct perf_evsel;
-struct perf_evlist;
+struct evsel;
+struct evlist;
struct perf_session;
struct event_key {
@@ -45,17 +45,17 @@ struct kvm_event_key {
struct perf_kvm_stat;
struct child_event_ops {
- void (*get_key)(struct perf_evsel *evsel,
+ void (*get_key)(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
const char *name;
};
struct kvm_events_ops {
- bool (*is_begin_event)(struct perf_evsel *evsel,
+ bool (*is_begin_event)(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
- bool (*is_end_event)(struct perf_evsel *evsel,
+ bool (*is_end_event)(struct evsel *evsel,
struct perf_sample *sample, struct event_key *key);
struct child_event_ops *child_ops;
void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
@@ -74,7 +74,7 @@ struct exit_reasons_table {
struct perf_kvm_stat {
struct perf_tool tool;
struct record_opts opts;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct perf_session *session;
const char *file_name;
@@ -109,21 +109,21 @@ struct kvm_reg_events_ops {
struct kvm_events_ops *ops;
};
-void exit_event_get_key(struct perf_evsel *evsel,
+void exit_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
-bool exit_event_begin(struct perf_evsel *evsel,
+bool exit_event_begin(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
-bool exit_event_end(struct perf_evsel *evsel,
+bool exit_event_end(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
void exit_event_decode_key(struct perf_kvm_stat *kvm,
struct event_key *key,
char *decode);
-bool kvm_exit_event(struct perf_evsel *evsel);
-bool kvm_entry_event(struct perf_evsel *evsel);
+bool kvm_exit_event(struct evsel *evsel);
+bool kvm_entry_event(struct evsel *evsel);
int setup_kvm_events_tp(struct perf_kvm_stat *kvm);
#define define_exit_reasons_table(name, symbols) \
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 9f0470ecbca9..55fb4b3b1157 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include "debug.h"
#include "llvm-utils.h"
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index bf3f3f4c4fe2..7878a0e3fa98 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -6,7 +6,7 @@
#ifndef __LLVM_UTILS_H
#define __LLVM_UTILS_H
-#include "debug.h"
+#include <stdbool.h>
struct llvm_param {
/* Path of clang executable */
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index b1dd29a9d915..397447066033 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -9,6 +9,7 @@
#include "compress.h"
#include "util.h"
#include "debug.h"
+#include <string.h>
#include <unistd.h>
#define BUFSIZE 8192
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index cf826eca3aaf..b4749d3eed08 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -3,17 +3,26 @@
#include <errno.h>
#include <inttypes.h>
#include <regex.h>
+#include <stdlib.h>
#include "callchain.h"
#include "debug.h"
+#include "dso.h"
+#include "env.h"
#include "event.h"
#include "evsel.h"
#include "hist.h"
#include "machine.h"
#include "map.h"
+#include "map_symbol.h"
+#include "branch.h"
+#include "mem-events.h"
+#include "srcline.h"
#include "symbol.h"
#include "sort.h"
#include "strlist.h"
+#include "target.h"
#include "thread.h"
+#include "util.h"
#include "vdso.h"
#include <stdbool.h>
#include <sys/types.h>
@@ -27,6 +36,7 @@
#include <linux/ctype.h>
#include <symbol/kallsyms.h>
#include <linux/mman.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
@@ -642,7 +652,7 @@ int machine__process_namespaces_event(struct machine *machine __maybe_unused,
int machine__process_lost_event(struct machine *machine __maybe_unused,
union perf_event *event, struct perf_sample *sample __maybe_unused)
{
- dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
+ dump_printf(": id:%" PRI_lu64 ": lost:%" PRI_lu64 "\n",
event->lost.id, event->lost.lost);
return 0;
}
@@ -650,7 +660,7 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
int machine__process_lost_samples_event(struct machine *machine __maybe_unused,
union perf_event *event, struct perf_sample *sample)
{
- dump_printf(": id:%" PRIu64 ": lost samples :%" PRIu64 "\n",
+ dump_printf(": id:%" PRIu64 ": lost samples :%" PRI_lu64 "\n",
sample->id, event->lost_samples.lost);
return 0;
}
@@ -710,20 +720,20 @@ static int machine__process_ksymbol_register(struct machine *machine,
struct symbol *sym;
struct map *map;
- map = map_groups__find(&machine->kmaps, event->ksymbol_event.addr);
+ map = map_groups__find(&machine->kmaps, event->ksymbol.addr);
if (!map) {
- map = dso__new_map(event->ksymbol_event.name);
+ map = dso__new_map(event->ksymbol.name);
if (!map)
return -ENOMEM;
- map->start = event->ksymbol_event.addr;
- map->end = map->start + event->ksymbol_event.len;
+ map->start = event->ksymbol.addr;
+ map->end = map->start + event->ksymbol.len;
map_groups__insert(&machine->kmaps, map);
}
sym = symbol__new(map->map_ip(map, map->start),
- event->ksymbol_event.len,
- 0, 0, event->ksymbol_event.name);
+ event->ksymbol.len,
+ 0, 0, event->ksymbol.name);
if (!sym)
return -ENOMEM;
dso__insert_symbol(map->dso, sym);
@@ -736,7 +746,7 @@ static int machine__process_ksymbol_unregister(struct machine *machine,
{
struct map *map;
- map = map_groups__find(&machine->kmaps, event->ksymbol_event.addr);
+ map = map_groups__find(&machine->kmaps, event->ksymbol.addr);
if (map)
map_groups__remove(&machine->kmaps, map);
@@ -750,7 +760,7 @@ int machine__process_ksymbol(struct machine *machine __maybe_unused,
if (dump_trace)
perf_event__fprintf_ksymbol(event, stdout);
- if (event->ksymbol_event.flags & PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER)
+ if (event->ksymbol.flags & PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER)
return machine__process_ksymbol_unregister(machine, event,
sample);
return machine__process_ksymbol_register(machine, event, sample);
@@ -1378,6 +1388,7 @@ static int machine__set_modules_path(struct machine *machine)
return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
}
int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
+ u64 *size __maybe_unused,
const char *name __maybe_unused)
{
return 0;
@@ -1389,7 +1400,7 @@ static int machine__create_module(void *arg, const char *name, u64 start,
struct machine *machine = arg;
struct map *map;
- if (arch__fix_module_text_start(&start, name) < 0)
+ if (arch__fix_module_text_start(&start, &size, name) < 0)
return -1;
map = machine__findnew_module_map(machine, start, name);
@@ -1918,7 +1929,7 @@ int machine__process_event(struct machine *machine, union perf_event *event,
case PERF_RECORD_KSYMBOL:
ret = machine__process_ksymbol(machine, event, sample); break;
case PERF_RECORD_BPF_EVENT:
- ret = machine__process_bpf_event(machine, event, sample); break;
+ ret = machine__process_bpf(machine, event, sample); break;
default:
ret = -1;
break;
@@ -2287,7 +2298,7 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
static int thread__resolve_callchain_sample(struct thread *thread,
struct callchain_cursor *cursor,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct symbol **parent,
struct addr_location *root_al,
@@ -2493,13 +2504,13 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
static int thread__resolve_callchain_unwind(struct thread *thread,
struct callchain_cursor *cursor,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
int max_stack)
{
/* Can we do dwarf post unwind? */
- if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
- (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
+ if (!((evsel->core.attr.sample_type & PERF_SAMPLE_REGS_USER) &&
+ (evsel->core.attr.sample_type & PERF_SAMPLE_STACK_USER)))
return 0;
/* Bail out if nothing was captured. */
@@ -2513,7 +2524,7 @@ static int thread__resolve_callchain_unwind(struct thread *thread,
int thread__resolve_callchain(struct thread *thread,
struct callchain_cursor *cursor,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct symbol **parent,
struct addr_location *root_al,
@@ -2599,7 +2610,7 @@ int machines__for_each_thread(struct machines *machines,
}
int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
- struct target *target, struct thread_map *threads,
+ struct target *target, struct perf_thread_map *threads,
perf_event__handler_t process, bool data_mmap,
unsigned int nr_threads_synthesize)
{
@@ -2615,7 +2626,9 @@ int __machine__synthesize_threads(struct machine *machine, struct perf_tool *too
pid_t machine__get_current_tid(struct machine *machine, int cpu)
{
- if (cpu < 0 || cpu >= MAX_NR_CPUS || !machine->current_tid)
+ int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);
+
+ if (cpu < 0 || cpu >= nr_cpus || !machine->current_tid)
return -1;
return machine->current_tid[cpu];
@@ -2625,6 +2638,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
pid_t tid)
{
struct thread *thread;
+ int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);
if (cpu < 0)
return -EINVAL;
@@ -2632,14 +2646,14 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
if (!machine->current_tid) {
int i;
- machine->current_tid = calloc(MAX_NR_CPUS, sizeof(pid_t));
+ machine->current_tid = calloc(nr_cpus, sizeof(pid_t));
if (!machine->current_tid)
return -ENOMEM;
- for (i = 0; i < MAX_NR_CPUS; i++)
+ for (i = 0; i < nr_cpus; i++)
machine->current_tid[i] = -1;
}
- if (cpu >= MAX_NR_CPUS) {
+ if (cpu >= nr_cpus) {
pr_err("Requested CPU %d too large. ", cpu);
pr_err("Consider raising MAX_NR_CPUS\n");
return -EINVAL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index f70ab98a7bde..ffd391a925a6 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -5,15 +5,17 @@
#include <sys/types.h>
#include <linux/rbtree.h>
#include "map_groups.h"
-#include "dso.h"
+#include "dsos.h"
#include "event.h"
#include "rwsem.h"
struct addr_location;
struct branch_stack;
-struct perf_evsel;
+struct dso;
+struct evsel;
struct perf_sample;
struct symbol;
+struct target;
struct thread;
union perf_event;
@@ -175,7 +177,7 @@ struct callchain_cursor;
int thread__resolve_callchain(struct thread *thread,
struct callchain_cursor *cursor,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct perf_sample *sample,
struct symbol **parent,
struct addr_location *root_al,
@@ -222,7 +224,7 @@ struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
struct map *machine__findnew_module_map(struct machine *machine, u64 start,
const char *filename);
-int arch__fix_module_text_start(u64 *start, const char *name);
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name);
int machine__load_kallsyms(struct machine *machine, const char *filename);
@@ -251,12 +253,12 @@ int machines__for_each_thread(struct machines *machines,
void *priv);
int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
- struct target *target, struct thread_map *threads,
+ struct target *target, struct perf_thread_map *threads,
perf_event__handler_t process, bool data_mmap,
unsigned int nr_threads_synthesize);
static inline
int machine__synthesize_threads(struct machine *machine, struct target *target,
- struct thread_map *threads, bool data_mmap,
+ struct perf_thread_map *threads, bool data_mmap,
unsigned int nr_threads_synthesize)
{
return __machine__synthesize_threads(machine, NULL, target, threads,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 668410b1d426..5b83ed1ebbd6 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -8,7 +8,9 @@
#include <stdio.h>
#include <unistd.h>
#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
+#include "dso.h"
#include "map.h"
+#include "map_symbol.h"
#include "thread.h"
#include "vdso.h"
#include "build-id.h"
@@ -20,6 +22,7 @@
#include "namespaces.h"
#include "unwind.h"
#include "srccode.h"
+#include "ui/ui.h"
static void __maps__insert(struct maps *maps, struct map *map);
static void __maps__insert_name(struct maps *maps, struct map *map);
@@ -636,7 +639,7 @@ bool map_groups__empty(struct map_groups *mg)
struct map_groups *map_groups__new(struct machine *machine)
{
- struct map_groups *mg = malloc(sizeof(*mg));
+ struct map_groups *mg = zalloc(sizeof(*mg));
if (mg != NULL)
map_groups__init(mg, machine);
@@ -647,6 +650,7 @@ struct map_groups *map_groups__new(struct machine *machine)
void map_groups__delete(struct map_groups *mg)
{
map_groups__exit(mg);
+ unwind__finish_access(mg);
free(mg);
}
@@ -887,7 +891,7 @@ int map_groups__clone(struct thread *thread, struct map_groups *parent)
if (new == NULL)
goto out_unlock;
- err = unwind__prepare_access(thread, new, NULL);
+ err = unwind__prepare_access(mg, new, NULL);
if (err)
goto out_unlock;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index dc93787c74f0..c3614195ddc7 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -16,7 +16,7 @@ struct ip_callchain;
struct ref_reloc_sym;
struct map_groups;
struct machine;
-struct perf_evsel;
+struct evsel;
struct map {
union {
diff --git a/tools/perf/util/map_groups.h b/tools/perf/util/map_groups.h
index 5f25efa6d6bc..77252e14008f 100644
--- a/tools/perf/util/map_groups.h
+++ b/tools/perf/util/map_groups.h
@@ -31,6 +31,10 @@ struct map_groups {
struct maps maps;
struct machine *machine;
refcount_t refcnt;
+#ifdef HAVE_LIBUNWIND_SUPPORT
+ void *addr_space;
+ struct unwind_libunwind_ops *unwind_libunwind_ops;
+#endif
};
#define KMAP_NAME_LEN 256
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 42c3e5a229d2..3d391583f2ae 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -8,10 +8,10 @@
#include <unistd.h>
#include <api/fs/fs.h>
#include <linux/kernel.h>
+#include "map_symbol.h"
#include "mem-events.h"
#include "debug.h"
#include "symbol.h"
-#include "sort.h"
unsigned int perf_mem_events__loads_ldlat = 30;
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
index a889ec2fa9f5..f1389bdae7bf 100644
--- a/tools/perf/util/mem-events.h
+++ b/tools/perf/util/mem-events.h
@@ -6,6 +6,8 @@
#include <stdint.h>
#include <stdio.h>
#include <linux/types.h>
+#include <linux/refcount.h>
+#include <linux/perf_event.h>
#include "stat.h"
struct perf_mem_event {
@@ -16,6 +18,13 @@ struct perf_mem_event {
const char *sysfs_name;
};
+struct mem_info {
+ struct addr_map_symbol iaddr;
+ struct addr_map_symbol daddr;
+ union perf_mem_data_src data_src;
+ refcount_t refcnt;
+};
+
enum {
PERF_MEM_EVENTS__LOAD,
PERF_MEM_EVENTS__STORE,
diff --git a/tools/perf/util/mem2node.c b/tools/perf/util/mem2node.c
index cacc2fc4dcbd..797d86a1ab09 100644
--- a/tools/perf/util/mem2node.c
+++ b/tools/perf/util/mem2node.c
@@ -1,7 +1,10 @@
#include <errno.h>
#include <inttypes.h>
#include <linux/bitmap.h>
+#include <linux/kernel.h>
#include <linux/zalloc.h>
+#include "debug.h"
+#include "env.h"
#include "mem2node.h"
struct phys_entry {
diff --git a/tools/perf/util/mem2node.h b/tools/perf/util/mem2node.h
index 59c4752a2181..8dfa2b58d0cd 100644
--- a/tools/perf/util/mem2node.h
+++ b/tools/perf/util/mem2node.h
@@ -2,8 +2,9 @@
#define __MEM2NODE_H
#include <linux/rbtree.h>
-#include "env.h"
+#include <linux/types.h>
+struct perf_env;
struct phys_entry;
struct mem2node {
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 416a9015405e..a7c0424dbda3 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -6,22 +6,25 @@
/* Manage metrics and groups of metrics from JSON files */
#include "metricgroup.h"
+#include "debug.h"
#include "evlist.h"
+#include "evsel.h"
#include "strbuf.h"
#include "pmu.h"
#include "expr.h"
#include "rblist.h"
#include <string.h>
-#include <stdbool.h>
#include <errno.h>
#include "pmu-events/pmu-events.h"
#include "strlist.h"
#include <assert.h>
#include <linux/ctype.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
+#include <subcmd/parse-options.h>
struct metric_event *metricgroup__lookup(struct rblist *metric_events,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
bool create)
{
struct rb_node *nd;
@@ -84,63 +87,68 @@ struct egroup {
const char **ids;
const char *metric_name;
const char *metric_expr;
+ const char *metric_unit;
};
-static bool record_evsel(int *ind, struct perf_evsel **start,
- int idnum,
- struct perf_evsel **metric_events,
- struct perf_evsel *ev)
+static struct evsel *find_evsel_group(struct evlist *perf_evlist,
+ const char **ids,
+ int idnum,
+ struct evsel **metric_events)
{
- metric_events[*ind] = ev;
- if (*ind == 0)
- *start = ev;
- if (++*ind == idnum) {
- metric_events[*ind] = NULL;
- return true;
- }
- return false;
-}
-
-static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist,
- const char **ids,
- int idnum,
- struct perf_evsel **metric_events)
-{
- struct perf_evsel *ev, *start = NULL;
- int ind = 0;
+ struct evsel *ev;
+ int i = 0;
+ bool leader_found;
evlist__for_each_entry (perf_evlist, ev) {
- if (ev->collect_stat)
- continue;
- if (!strcmp(ev->name, ids[ind])) {
- if (record_evsel(&ind, &start, idnum,
- metric_events, ev))
- return start;
+ if (!strcmp(ev->name, ids[i])) {
+ if (!metric_events[i])
+ metric_events[i] = ev;
} else {
- /*
- * We saw some other event that is not
- * in our list of events. Discard
- * the whole match and start again.
- */
- ind = 0;
- start = NULL;
- if (!strcmp(ev->name, ids[ind])) {
- if (record_evsel(&ind, &start, idnum,
- metric_events, ev))
- return start;
+ if (++i == idnum) {
+ /* Discard the whole match and start again */
+ i = 0;
+ memset(metric_events, 0,
+ sizeof(struct evsel *) * idnum);
+ continue;
+ }
+
+ if (!strcmp(ev->name, ids[i]))
+ metric_events[i] = ev;
+ else {
+ /* Discard the whole match and start again */
+ i = 0;
+ memset(metric_events, 0,
+ sizeof(struct evsel *) * idnum);
+ continue;
}
}
}
- /*
- * This can happen when an alias expands to multiple
- * events, like for uncore events.
- * We don't support this case for now.
- */
- return NULL;
+
+ if (i != idnum - 1) {
+ /* Not whole match */
+ return NULL;
+ }
+
+ metric_events[idnum] = NULL;
+
+ for (i = 0; i < idnum; i++) {
+ leader_found = false;
+ evlist__for_each_entry(perf_evlist, ev) {
+ if (!leader_found && (ev == metric_events[i]))
+ leader_found = true;
+
+ if (leader_found &&
+ !strcmp(ev->name, metric_events[i]->name)) {
+ ev->metric_leader = metric_events[i];
+ }
+ }
+ }
+
+ return metric_events[0];
}
static int metricgroup__setup_events(struct list_head *groups,
- struct perf_evlist *perf_evlist,
+ struct evlist *perf_evlist,
struct rblist *metric_events_list)
{
struct metric_event *me;
@@ -148,10 +156,10 @@ static int metricgroup__setup_events(struct list_head *groups,
int i = 0;
int ret = 0;
struct egroup *eg;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
list_for_each_entry (eg, groups, nd) {
- struct perf_evsel **metric_events;
+ struct evsel **metric_events;
metric_events = calloc(sizeof(void *), eg->idnum + 1);
if (!metric_events) {
@@ -179,6 +187,7 @@ static int metricgroup__setup_events(struct list_head *groups,
}
expr->metric_expr = eg->metric_expr;
expr->metric_name = eg->metric_name;
+ expr->metric_unit = eg->metric_unit;
expr->metric_events = metric_events;
list_add(&expr->nd, &me->head);
}
@@ -450,6 +459,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
eg->idnum = idnum;
eg->metric_name = pe->metric_name;
eg->metric_expr = pe->metric_expr;
+ eg->metric_unit = pe->unit;
list_add_tail(&eg->nd, group_list);
ret = 0;
}
@@ -502,7 +512,7 @@ int metricgroup__parse_groups(const struct option *opt,
struct rblist *metric_events)
{
struct parse_events_error parse_error;
- struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value;
+ struct evlist *perf_evlist = *(struct evlist **)opt->value;
struct strbuf extra_events;
LIST_HEAD(group_list);
int ret;
diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h
index 5c52097a5c63..475c7f912864 100644
--- a/tools/perf/util/metricgroup.h
+++ b/tools/perf/util/metricgroup.h
@@ -1,15 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
#ifndef METRICGROUP_H
#define METRICGROUP_H 1
-#include "linux/list.h"
-#include "rblist.h"
-#include <subcmd/parse-options.h>
-#include "evlist.h"
-#include "strbuf.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <stdbool.h>
+
+struct evsel;
+struct option;
+struct rblist;
struct metric_event {
struct rb_node nd;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct list_head head; /* list of metric_expr */
};
@@ -17,11 +20,12 @@ struct metric_expr {
struct list_head nd;
const char *metric_expr;
const char *metric_name;
- struct perf_evsel **metric_events;
+ const char *metric_unit;
+ struct evsel **metric_events;
};
struct metric_event *metricgroup__lookup(struct rblist *metric_events,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
bool create);
int metricgroup__parse_groups(const struct option *opt,
const char *str,
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 9f0b6391af33..33c5b5495482 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -10,12 +10,16 @@
#include <inttypes.h>
#include <asm/bug.h>
#include <linux/zalloc.h>
+#include <stdlib.h>
+#include <string.h>
#ifdef HAVE_LIBNUMA_SUPPORT
#include <numaif.h>
#endif
+#include "cpumap.h"
#include "debug.h"
#include "event.h"
#include "mmap.h"
+#include "../perf.h"
#include "util.h" /* page_size */
size_t perf_mmap__mmap_len(struct perf_mmap *map)
@@ -150,7 +154,7 @@ void __weak auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp __maybe_u
}
void __weak auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp __maybe_unused,
- struct perf_evlist *evlist __maybe_unused,
+ struct evlist *evlist __maybe_unused,
int idx __maybe_unused,
bool per_cpu __maybe_unused)
{
@@ -325,13 +329,13 @@ void perf_mmap__munmap(struct perf_mmap *map)
static void build_node_mask(int node, cpu_set_t *mask)
{
int c, cpu, nr_cpus;
- const struct cpu_map *cpu_map = NULL;
+ const struct perf_cpu_map *cpu_map = NULL;
cpu_map = cpu_map__online();
if (!cpu_map)
return;
- nr_cpus = cpu_map__nr(cpu_map);
+ nr_cpus = perf_cpu_map__nr(cpu_map);
for (c = 0; c < nr_cpus; c++) {
cpu = cpu_map->map[c]; /* map c index to online cpu index */
if (cpu__get_node(cpu) == node)
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 274ce389cd84..3857a49e8f96 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -6,6 +6,7 @@
#include <linux/types.h>
#include <linux/ring_buffer.h>
#include <stdbool.h>
+#include <pthread.h> // for cpu_set_t
#ifdef HAVE_AIO_SUPPORT
#include <aio.h>
#endif
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 46d3a7754897..99be15dd2b6b 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -19,7 +19,7 @@
#include <asm/bug.h>
#include <linux/zalloc.h>
-struct namespaces *namespaces__new(struct namespaces_event *event)
+struct namespaces *namespaces__new(struct perf_record_namespaces *event)
{
struct namespaces *namespaces;
u64 link_info_size = ((event ? event->nr_namespaces : NR_NAMESPACES) *
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index 004430c0de93..40edef56cb52 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -17,7 +17,7 @@
int setns(int fd, int nstype);
#endif
-struct namespaces_event;
+struct perf_record_namespaces;
struct namespaces {
struct list_head list;
@@ -25,7 +25,7 @@ struct namespaces {
struct perf_ns_link_info link_info[];
};
-struct namespaces *namespaces__new(struct namespaces_event *event);
+struct namespaces *namespaces__new(struct perf_record_namespaces *event);
void namespaces__free(struct namespaces *namespaces);
struct nsinfo {
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index bb5f34b7ab44..359db2b1fcef 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -8,6 +8,7 @@
#include "session.h"
#include "asm/bug.h"
#include "debug.h"
+#include "ui/progress.h"
#define pr_N(n, fmt, ...) \
eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 726e8d9e8c54..bb4aa88c50a8 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
-#include "perf.h"
#include "util/debug.h"
+#include "util/event.h"
#include <subcmd/parse-options.h>
#include "util/parse-branch-options.h"
#include <stdlib.h>
+#include <string.h>
#define BRANCH_OPT(n, m) \
{ .name = n, .mode = (m) }
@@ -30,6 +31,7 @@ static const struct branch_mode branch_modes[] = {
BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
+ BRANCH_OPT("stack", PERF_SAMPLE_BRANCH_CALL_STACK),
BRANCH_END
};
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 371ff3aee769..5ec21d21113c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,20 +10,21 @@
#include <fcntl.h>
#include <sys/param.h>
#include "term.h"
-#include "../perf.h"
+#include "build-id.h"
#include "evlist.h"
#include "evsel.h"
+#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "parse-events.h"
#include <subcmd/exec-cmd.h>
#include "string2.h"
#include "strlist.h"
#include "symbol.h"
-#include "cache.h"
#include "header.h"
#include "bpf-loader.h"
#include "debug.h"
#include <api/fs/tracing_path.h>
+#include <perf/cpumap.h>
#include "parse-events-bison.h"
#define YY_EXTRA_TYPE int
#include "parse-events-flex.h"
@@ -314,16 +315,16 @@ static char *get_config_name(struct list_head *head_terms)
return NULL;
}
-static struct perf_evsel *
+static struct evsel *
__add_event(struct list_head *list, int *idx,
struct perf_event_attr *attr,
char *name, struct perf_pmu *pmu,
struct list_head *config_terms, bool auto_merge_stats,
const char *cpu_list)
{
- struct perf_evsel *evsel;
- struct cpu_map *cpus = pmu ? pmu->cpus :
- cpu_list ? cpu_map__new(cpu_list) : NULL;
+ struct evsel *evsel;
+ struct perf_cpu_map *cpus = pmu ? pmu->cpus :
+ cpu_list ? perf_cpu_map__new(cpu_list) : NULL;
event_attr_init(attr);
@@ -332,8 +333,8 @@ __add_event(struct list_head *list, int *idx,
return NULL;
(*idx)++;
- evsel->cpus = cpu_map__get(cpus);
- evsel->own_cpus = cpu_map__get(cpus);
+ evsel->core.cpus = perf_cpu_map__get(cpus);
+ evsel->core.own_cpus = perf_cpu_map__get(cpus);
evsel->system_wide = pmu ? pmu->is_uncore : false;
evsel->auto_merge_stats = auto_merge_stats;
@@ -343,7 +344,7 @@ __add_event(struct list_head *list, int *idx,
if (config_terms)
list_splice(config_terms, &evsel->config_terms);
- list_add_tail(&evsel->node, list);
+ list_add_tail(&evsel->core.node, list);
return evsel;
}
@@ -357,7 +358,7 @@ static int add_event(struct list_head *list, int *idx,
static int add_event_tool(struct list_head *list, int *idx,
enum perf_tool_event tool_event)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_DUMMY,
@@ -510,7 +511,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct parse_events_error *err,
struct list_head *head_config)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
if (IS_ERR(evsel)) {
@@ -526,7 +527,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
list_splice(&config_terms, &evsel->config_terms);
}
- list_add_tail(&evsel->node, list);
+ list_add_tail(&evsel->core.node, list);
return 0;
}
@@ -630,15 +631,24 @@ struct __add_bpf_event_param {
struct list_head *head_config;
};
-static int add_bpf_event(const char *group, const char *event, int fd,
+static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj,
void *_param)
{
LIST_HEAD(new_evsels);
struct __add_bpf_event_param *param = _param;
struct parse_events_state *parse_state = param->parse_state;
struct list_head *list = param->list;
- struct perf_evsel *pos;
+ struct evsel *pos;
int err;
+ /*
+ * Check if we should add the event, i.e. if it is a TP but starts with a '!',
+ * then don't add the tracepoint, this will be used for something else, like
+ * adding to a BPF_MAP_TYPE_PROG_ARRAY.
+ *
+ * See tools/perf/examples/bpf/augmented_raw_syscalls.c
+ */
+ if (group[0] == '!')
+ return 0;
pr_debug("add bpf event %s:%s and attach bpf program %d\n",
group, event, fd);
@@ -647,22 +657,23 @@ static int add_bpf_event(const char *group, const char *event, int fd,
event, parse_state->error,
param->head_config);
if (err) {
- struct perf_evsel *evsel, *tmp;
+ struct evsel *evsel, *tmp;
pr_debug("Failed to add BPF event %s:%s\n",
group, event);
- list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
- list_del_init(&evsel->node);
- perf_evsel__delete(evsel);
+ list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) {
+ list_del_init(&evsel->core.node);
+ evsel__delete(evsel);
}
return err;
}
pr_debug("adding %s:%s\n", group, event);
- list_for_each_entry(pos, &new_evsels, node) {
+ list_for_each_entry(pos, &new_evsels, core.node) {
pr_debug("adding %s:%s to %p\n",
group, event, pos);
pos->bpf_fd = fd;
+ pos->bpf_obj = obj;
}
list_splice(&new_evsels, list);
return 0;
@@ -952,6 +963,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
[PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
[PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
[PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore",
+ [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output",
};
static bool config_term_shrinked;
@@ -1072,6 +1084,9 @@ do { \
return -EINVAL;
}
break;
+ case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
+ CHECK_TYPE_VAL(NUM);
+ break;
default:
err->str = strdup("unknown term");
err->idx = term->err_term;
@@ -1122,6 +1137,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
+ case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
return config_term_common(attr, term, err);
default:
if (err) {
@@ -1214,6 +1230,9 @@ do { \
ADD_CONFIG_TERM(PERCORE, percore,
term->val.num ? true : false);
break;
+ case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
+ ADD_CONFIG_TERM(AUX_OUTPUT, aux_output, term->val.num ? 1 : 0);
+ break;
default:
break;
}
@@ -1296,7 +1315,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
struct perf_event_attr attr;
struct perf_pmu_info info;
struct perf_pmu *pmu;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct parse_events_error *err = parse_state->error;
bool use_uncore_alias;
LIST_HEAD(config_terms);
@@ -1443,13 +1462,13 @@ static int
parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list,
struct parse_events_state *parse_state)
{
- struct perf_evsel *evsel, *leader;
+ struct evsel *evsel, *leader;
uintptr_t *leaders;
bool is_leader = true;
int i, nr_pmu = 0, total_members, ret = 0;
- leader = list_first_entry(list, struct perf_evsel, node);
- evsel = list_last_entry(list, struct perf_evsel, node);
+ leader = list_first_entry(list, struct evsel, core.node);
+ evsel = list_last_entry(list, struct evsel, core.node);
total_members = evsel->idx - leader->idx + 1;
leaders = calloc(total_members, sizeof(uintptr_t));
@@ -1511,13 +1530,13 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list,
__evlist__for_each_entry(list, evsel) {
if (i >= nr_pmu)
i = 0;
- evsel->leader = (struct perf_evsel *) leaders[i++];
+ evsel->leader = (struct evsel *) leaders[i++];
}
/* The number of members and group name are same for each group */
for (i = 0; i < nr_pmu; i++) {
- evsel = (struct perf_evsel *) leaders[i];
- evsel->nr_members = total_members / nr_pmu;
+ evsel = (struct evsel *) leaders[i];
+ evsel->core.nr_members = total_members / nr_pmu;
evsel->group_name = name ? strdup(name) : NULL;
}
@@ -1534,7 +1553,7 @@ out:
void parse_events__set_leader(char *name, struct list_head *list,
struct parse_events_state *parse_state)
{
- struct perf_evsel *leader;
+ struct evsel *leader;
if (list_empty(list)) {
WARN_ONCE(true, "WARNING: failed to set leader: empty list");
@@ -1545,7 +1564,7 @@ void parse_events__set_leader(char *name, struct list_head *list,
return;
__perf_evlist__set_leader(list);
- leader = list_entry(list->next, struct perf_evsel, node);
+ leader = list_entry(list->next, struct evsel, core.node);
leader->group_name = name ? strdup(name) : NULL;
}
@@ -1578,18 +1597,18 @@ struct event_modifier {
};
static int get_event_modifier(struct event_modifier *mod, char *str,
- struct perf_evsel *evsel)
-{
- int eu = evsel ? evsel->attr.exclude_user : 0;
- int ek = evsel ? evsel->attr.exclude_kernel : 0;
- int eh = evsel ? evsel->attr.exclude_hv : 0;
- int eH = evsel ? evsel->attr.exclude_host : 0;
- int eG = evsel ? evsel->attr.exclude_guest : 0;
- int eI = evsel ? evsel->attr.exclude_idle : 0;
- int precise = evsel ? evsel->attr.precise_ip : 0;
+ struct evsel *evsel)
+{
+ int eu = evsel ? evsel->core.attr.exclude_user : 0;
+ int ek = evsel ? evsel->core.attr.exclude_kernel : 0;
+ int eh = evsel ? evsel->core.attr.exclude_hv : 0;
+ int eH = evsel ? evsel->core.attr.exclude_host : 0;
+ int eG = evsel ? evsel->core.attr.exclude_guest : 0;
+ int eI = evsel ? evsel->core.attr.exclude_idle : 0;
+ int precise = evsel ? evsel->core.attr.precise_ip : 0;
int precise_max = 0;
int sample_read = 0;
- int pinned = evsel ? evsel->attr.pinned : 0;
+ int pinned = evsel ? evsel->core.attr.pinned : 0;
int exclude = eu | ek | eh;
int exclude_GH = evsel ? evsel->exclude_GH : 0;
@@ -1691,7 +1710,7 @@ static int check_modifier(char *str)
int parse_events__modifier_event(struct list_head *list, char *str, bool add)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct event_modifier mod;
if (str == NULL)
@@ -1707,20 +1726,20 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
if (add && get_event_modifier(&mod, str, evsel))
return -EINVAL;
- evsel->attr.exclude_user = mod.eu;
- evsel->attr.exclude_kernel = mod.ek;
- evsel->attr.exclude_hv = mod.eh;
- evsel->attr.precise_ip = mod.precise;
- evsel->attr.exclude_host = mod.eH;
- evsel->attr.exclude_guest = mod.eG;
- evsel->attr.exclude_idle = mod.eI;
+ evsel->core.attr.exclude_user = mod.eu;
+ evsel->core.attr.exclude_kernel = mod.ek;
+ evsel->core.attr.exclude_hv = mod.eh;
+ evsel->core.attr.precise_ip = mod.precise;
+ evsel->core.attr.exclude_host = mod.eH;
+ evsel->core.attr.exclude_guest = mod.eG;
+ evsel->core.attr.exclude_idle = mod.eI;
evsel->exclude_GH = mod.exclude_GH;
evsel->sample_read = mod.sample_read;
evsel->precise_max = mod.precise_max;
evsel->weak_group = mod.weak;
if (perf_evsel__is_group_leader(evsel))
- evsel->attr.pinned = mod.pinned;
+ evsel->core.attr.pinned = mod.pinned;
}
return 0;
@@ -1728,7 +1747,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
int parse_events_name(struct list_head *list, char *name)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
__evlist__for_each_entry(list, evsel) {
if (!evsel->name)
@@ -1894,12 +1913,12 @@ int parse_events_terms(struct list_head *terms, const char *str)
return ret;
}
-int parse_events(struct perf_evlist *evlist, const char *str,
+int parse_events(struct evlist *evlist, const char *str,
struct parse_events_error *err)
{
struct parse_events_state parse_state = {
.list = LIST_HEAD_INIT(parse_state.list),
- .idx = evlist->nr_entries,
+ .idx = evlist->core.nr_entries,
.error = err,
.evlist = evlist,
};
@@ -1908,7 +1927,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS);
perf_pmu__parse_cleanup();
if (!ret) {
- struct perf_evsel *last;
+ struct evsel *last;
if (list_empty(&parse_state.list)) {
WARN_ONCE(true, "WARNING: event parser found nothing\n");
@@ -1925,7 +1944,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
/*
* There are 2 users - builtin-record and builtin-test objects.
- * Both call perf_evlist__delete in case of error, so we dont
+ * Both call evlist__delete in case of error, so we dont
* need to bother.
*/
return ret;
@@ -2003,7 +2022,7 @@ void parse_events_print_error(struct parse_events_error *err,
int parse_events_option(const struct option *opt, const char *str,
int unset __maybe_unused)
{
- struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+ struct evlist *evlist = *(struct evlist **)opt->value;
struct parse_events_error err = { .idx = 0, };
int ret = parse_events(evlist, str, &err);
@@ -2016,12 +2035,12 @@ int parse_events_option(const struct option *opt, const char *str,
}
static int
-foreach_evsel_in_last_glob(struct perf_evlist *evlist,
- int (*func)(struct perf_evsel *evsel,
+foreach_evsel_in_last_glob(struct evlist *evlist,
+ int (*func)(struct evsel *evsel,
const void *arg),
const void *arg)
{
- struct perf_evsel *last = NULL;
+ struct evsel *last = NULL;
int err;
/*
@@ -2030,7 +2049,7 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
*
* So no need to WARN here, let *func do this.
*/
- if (evlist->nr_entries > 0)
+ if (evlist->core.nr_entries > 0)
last = perf_evlist__last(evlist);
do {
@@ -2040,15 +2059,15 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
if (!last)
return 0;
- if (last->node.prev == &evlist->entries)
+ if (last->core.node.prev == &evlist->core.entries)
return 0;
- last = list_entry(last->node.prev, struct perf_evsel, node);
+ last = list_entry(last->core.node.prev, struct evsel, core.node);
} while (!last->cmdline_group_boundary);
return 0;
}
-static int set_filter(struct perf_evsel *evsel, const void *arg)
+static int set_filter(struct evsel *evsel, const void *arg)
{
const char *str = arg;
bool found = false;
@@ -2061,7 +2080,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
return -1;
}
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
if (perf_evsel__append_tp_filter(evsel, str) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
@@ -2072,7 +2091,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
}
while ((pmu = perf_pmu__scan(pmu)) != NULL)
- if (pmu->type == evsel->attr.type) {
+ if (pmu->type == evsel->core.attr.type) {
found = true;
break;
}
@@ -2099,18 +2118,18 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
int parse_filter(const struct option *opt, const char *str,
int unset __maybe_unused)
{
- struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+ struct evlist *evlist = *(struct evlist **)opt->value;
return foreach_evsel_in_last_glob(evlist, set_filter,
(const void *)str);
}
-static int add_exclude_perf_filter(struct perf_evsel *evsel,
+static int add_exclude_perf_filter(struct evsel *evsel,
const void *arg __maybe_unused)
{
char new_filter[64];
- if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
fprintf(stderr,
"--exclude-perf option should follow a -e tracepoint option\n");
return -1;
@@ -2131,7 +2150,7 @@ int exclude_perf(const struct option *opt,
const char *arg __maybe_unused,
int unset __maybe_unused)
{
- struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+ struct evlist *evlist = *(struct evlist **)opt->value;
return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
NULL);
@@ -2297,20 +2316,20 @@ static bool is_event_supported(u8 type, unsigned config)
{
bool ret = true;
int open_return;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_event_attr attr = {
.type = type,
.config = config,
.disabled = 1,
};
- struct thread_map *tmap = thread_map__new_by_tid(0);
+ struct perf_thread_map *tmap = thread_map__new_by_tid(0);
if (tmap == NULL)
return false;
- evsel = perf_evsel__new(&attr);
+ evsel = evsel__new(&attr);
if (evsel) {
- open_return = perf_evsel__open(evsel, NULL, tmap);
+ open_return = evsel__open(evsel, NULL, tmap);
ret = open_return >= 0;
if (open_return == -EACCES) {
@@ -2321,13 +2340,13 @@ static bool is_event_supported(u8 type, unsigned config)
* by default as some ARM machines do not support it.
*
*/
- evsel->attr.exclude_kernel = 1;
- ret = perf_evsel__open(evsel, NULL, tmap) >= 0;
+ evsel->core.attr.exclude_kernel = 1;
+ ret = evsel__open(evsel, NULL, tmap) >= 0;
}
- perf_evsel__delete(evsel);
+ evsel__delete(evsel);
}
- thread_map__put(tmap);
+ perf_thread_map__put(tmap);
return ret;
}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index f7139e1a2fd3..616ca1eda0eb 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -12,8 +12,8 @@
#include <string.h>
struct list_head;
-struct perf_evsel;
-struct perf_evlist;
+struct evsel;
+struct evlist;
struct parse_events_error;
struct option;
@@ -31,7 +31,7 @@ bool have_tracepoints(struct list_head *evlist);
const char *event_type(int type);
int parse_events_option(const struct option *opt, const char *str, int unset);
-int parse_events(struct perf_evlist *evlist, const char *str,
+int parse_events(struct evlist *evlist, const char *str,
struct parse_events_error *error);
int parse_events_terms(struct list_head *terms, const char *str);
int parse_filter(const struct option *opt, const char *str, int unset);
@@ -76,6 +76,7 @@ enum {
PARSE_EVENTS__TERM_TYPE_OVERWRITE,
PARSE_EVENTS__TERM_TYPE_DRV_CFG,
PARSE_EVENTS__TERM_TYPE_PERCORE,
+ PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT,
__PARSE_EVENTS__TERM_TYPE_NR,
};
@@ -119,7 +120,7 @@ struct parse_events_state {
int idx;
int nr_groups;
struct parse_events_error *error;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct list_head *terms;
};
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index ca6098874fe2..7469497cd28e 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -284,6 +284,7 @@ no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }
+aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index ca56ba2dd3da..caed0336429f 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -11,11 +11,12 @@
*
* which is what it's designed for.
*/
-#include "cache.h"
#include "path.h"
+#include "cache.h"
#include <linux/kernel.h>
#include <limits.h>
#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h
index f014f905df50..083429b7efa3 100644
--- a/tools/perf/util/path.h
+++ b/tools/perf/util/path.h
@@ -2,6 +2,9 @@
#ifndef _PERF_PATH_H
#define _PERF_PATH_H
+#include <stddef.h>
+#include <stdbool.h>
+
struct dirent;
int path__join(char *bf, size_t size, const char *path1, const char *path2);
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4f3aa8d99ef4..e635c594f773 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <setjmp.h>
#include <linux/err.h>
#include <linux/kernel.h>
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index f32b710347db..fb597fa94234 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -3,6 +3,7 @@
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/zalloc.h>
+#include <subcmd/pager.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
@@ -15,13 +16,15 @@
#include <api/fs/fs.h>
#include <locale.h>
#include <regex.h>
+#include <perf/cpumap.h>
+#include "debug.h"
#include "pmu.h"
#include "parse-events.h"
#include "cpumap.h"
#include "header.h"
#include "pmu-events/pmu-events.h"
-#include "cache.h"
#include "string2.h"
+#include "strbuf.h"
struct perf_pmu_format {
char *name;
@@ -99,7 +102,7 @@ static int pmu_format(const char *name, struct list_head *format)
return 0;
}
-static int convert_scale(const char *scale, char **end, double *sval)
+int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
{
char *lc;
int ret = 0;
@@ -162,7 +165,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
else
scale[sret] = '\0';
- ret = convert_scale(scale, NULL, &alias->scale);
+ ret = perf_pmu__convert_scale(scale, NULL, &alias->scale);
error:
close(fd);
return ret;
@@ -370,7 +373,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
desc ? strdup(desc) : NULL;
alias->topic = topic ? strdup(topic) : NULL;
if (unit) {
- if (convert_scale(unit, &unit, &alias->scale) < 0)
+ if (perf_pmu__convert_scale(unit, &unit, &alias->scale) < 0)
return -1;
snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
}
@@ -572,16 +575,16 @@ static void pmu_read_sysfs(void)
closedir(dir);
}
-static struct cpu_map *__pmu_cpumask(const char *path)
+static struct perf_cpu_map *__pmu_cpumask(const char *path)
{
FILE *file;
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
file = fopen(path, "r");
if (!file)
return NULL;
- cpus = cpu_map__read(file);
+ cpus = perf_cpu_map__read(file);
fclose(file);
return cpus;
}
@@ -593,10 +596,10 @@ static struct cpu_map *__pmu_cpumask(const char *path)
#define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask"
#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
-static struct cpu_map *pmu_cpumask(const char *name)
+static struct perf_cpu_map *pmu_cpumask(const char *name)
{
char path[PATH_MAX];
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
const char *sysfs = sysfs__mountpoint();
const char *templates[] = {
CPUS_TEMPLATE_UNCORE,
@@ -621,12 +624,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
static bool pmu_is_uncore(const char *name)
{
char path[PATH_MAX];
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
const char *sysfs = sysfs__mountpoint();
snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
cpus = __pmu_cpumask(path);
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
return !!cpus;
}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index bd9ec2704a57..f36ade6df76d 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -28,7 +28,7 @@ struct perf_pmu {
bool is_uncore;
int max_precise;
struct perf_event_attr *default_config;
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
struct list_head format; /* HEAD struct perf_pmu_format -> list */
struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
struct list_head list; /* ELEM */
@@ -96,4 +96,6 @@ struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
+int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
+
#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index cd1eb73cfe83..b8e0967c5c21 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,17 +19,17 @@
#include <limits.h>
#include <elf.h>
+#include "build-id.h"
#include "event.h"
#include "namespaces.h"
#include "strlist.h"
#include "strfilter.h"
#include "debug.h"
-#include "cache.h"
+#include "dso.h"
#include "color.h"
#include "map.h"
#include "map_groups.h"
#include "symbol.h"
-#include "thread.h"
#include <api/fs/fs.h>
#include "trace-event.h" /* For __maybe_unused */
#include "probe-event.h"
@@ -37,7 +37,9 @@
#include "probe-file.h"
#include "session.h"
#include "string2.h"
+#include "strbuf.h"
+#include <subcmd/pager.h>
#include <linux/ctype.h>
#include <linux/zalloc.h>
@@ -2230,6 +2232,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
field = next;
}
}
+ pev->nargs = 0;
zfree(&pev->args);
}
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 5b4d49382932..d13db55a2feb 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -16,10 +16,10 @@
#include "strlist.h"
#include "strfilter.h"
#include "debug.h"
-#include "cache.h"
+#include "dso.h"
#include "color.h"
#include "symbol.h"
-#include "thread.h"
+#include "strbuf.h"
#include <api/fs/tracing_path.h>
#include "probe-event.h"
#include "probe-file.h"
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 025fc4491993..505905fc21c5 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -24,6 +24,7 @@
#include "dso.h"
#include "debug.h"
#include "intlist.h"
+#include "strbuf.h"
#include "strlist.h"
#include "symbol.h"
#include "probe-finder.h"
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index 28de8a4c2ce8..80ff41fc45be 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>
#include <stdlib.h>
+#include <string.h>
struct pstack {
unsigned short top;
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index ceb8afdf9a89..c6dd478956f1 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -7,6 +7,7 @@
util/python.c
../lib/ctype.c
+util/cap.c
util/evlist.c
util/evsel.c
util/cpumap.c
@@ -18,10 +19,8 @@ util/namespaces.c
../lib/hweight.c
../lib/string.c
../lib/vsprintf.c
-../lib/zalloc.c
util/thread_map.c
util/util.c
-util/xyarray.c
util/cgroup.c
util/parse-branch-options.c
util/rblist.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 1e5b6718dcea..07ca4535e6f7 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -4,6 +4,9 @@
#include <inttypes.h>
#include <poll.h>
#include <linux/err.h>
+#include <perf/cpumap.h>
+#include <traceevent/event-parse.h>
+#include "debug.h"
#include "evlist.h"
#include "callchain.h"
#include "evsel.h"
@@ -11,8 +14,10 @@
#include "cpumap.h"
#include "print_binary.h"
#include "thread_map.h"
+#include "trace-event.h"
#include "mmap.h"
#include "util.h"
+#include "../perf-sys.h"
#if PY_MAJOR_VERSION < 3
#define _PyUnicode_FromString(arg) \
@@ -93,7 +98,7 @@ PyMODINIT_FUNC PyInit_perf(void);
struct pyrf_event {
PyObject_HEAD
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct perf_sample sample;
union perf_event event;
};
@@ -115,12 +120,12 @@ static PyMemberDef pyrf_mmap_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
member_def(perf_event_header, misc, T_UINT, "event misc"),
- member_def(mmap_event, pid, T_UINT, "event pid"),
- member_def(mmap_event, tid, T_UINT, "event tid"),
- member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
- member_def(mmap_event, len, T_ULONGLONG, "map length"),
- member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
- member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
+ member_def(perf_record_mmap, pid, T_UINT, "event pid"),
+ member_def(perf_record_mmap, tid, T_UINT, "event tid"),
+ member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"),
+ member_def(perf_record_mmap, len, T_ULONGLONG, "map length"),
+ member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"),
+ member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"),
{ .name = NULL, },
};
@@ -129,8 +134,8 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
PyObject *ret;
char *s;
- if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
- "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
+ if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", "
+ "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", "
"filename: %s }",
pevent->event.mmap.pid, pevent->event.mmap.tid,
pevent->event.mmap.start, pevent->event.mmap.len,
@@ -158,18 +163,18 @@ static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event obje
static PyMemberDef pyrf_task_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
- member_def(fork_event, pid, T_UINT, "event pid"),
- member_def(fork_event, ppid, T_UINT, "event ppid"),
- member_def(fork_event, tid, T_UINT, "event tid"),
- member_def(fork_event, ptid, T_UINT, "event ptid"),
- member_def(fork_event, time, T_ULONGLONG, "timestamp"),
+ member_def(perf_record_fork, pid, T_UINT, "event pid"),
+ member_def(perf_record_fork, ppid, T_UINT, "event ppid"),
+ member_def(perf_record_fork, tid, T_UINT, "event tid"),
+ member_def(perf_record_fork, ptid, T_UINT, "event ptid"),
+ member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"),
{ .name = NULL, },
};
static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
{
return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
- "ptid: %u, time: %" PRIu64 "}",
+ "ptid: %u, time: %" PRI_lu64 "}",
pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
pevent->event.fork.pid,
pevent->event.fork.ppid,
@@ -193,9 +198,9 @@ static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
static PyMemberDef pyrf_comm_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
- member_def(comm_event, pid, T_UINT, "event pid"),
- member_def(comm_event, tid, T_UINT, "event tid"),
- member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
+ member_def(perf_record_comm, pid, T_UINT, "event pid"),
+ member_def(perf_record_comm, tid, T_UINT, "event tid"),
+ member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"),
{ .name = NULL, },
};
@@ -222,18 +227,18 @@ static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."
static PyMemberDef pyrf_throttle_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
- member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
- member_def(throttle_event, id, T_ULONGLONG, "event id"),
- member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
+ member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"),
+ member_def(perf_record_throttle, id, T_ULONGLONG, "event id"),
+ member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"),
{ .name = NULL, },
};
static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
{
- struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
+ struct perf_record_throttle *te = (struct perf_record_throttle *)(&pevent->event.header + 1);
- return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
- ", stream_id: %" PRIu64 " }",
+ return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64
+ ", stream_id: %" PRI_lu64 " }",
pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
te->time, te->id, te->stream_id);
}
@@ -252,8 +257,8 @@ static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
static PyMemberDef pyrf_lost_event__members[] = {
sample_members
- member_def(lost_event, id, T_ULONGLONG, "event id"),
- member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
+ member_def(perf_record_lost, id, T_ULONGLONG, "event id"),
+ member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"),
{ .name = NULL, },
};
@@ -262,8 +267,8 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
PyObject *ret;
char *s;
- if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
- "lost: %#" PRIx64 " }",
+ if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", "
+ "lost: %#" PRI_lx64 " }",
pevent->event.lost.id, pevent->event.lost.lost) < 0) {
ret = PyErr_NoMemory();
} else {
@@ -287,8 +292,8 @@ static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
static PyMemberDef pyrf_read_event__members[] = {
sample_members
- member_def(read_event, pid, T_UINT, "event pid"),
- member_def(read_event, tid, T_UINT, "event tid"),
+ member_def(perf_record_read, pid, T_UINT, "event pid"),
+ member_def(perf_record_read, tid, T_UINT, "event tid"),
{ .name = NULL, },
};
@@ -337,7 +342,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
static bool is_tracepoint(struct pyrf_event *pevent)
{
- return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT;
+ return pevent->evsel->core.attr.type == PERF_TYPE_TRACEPOINT;
}
static PyObject*
@@ -383,13 +388,13 @@ static PyObject*
get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
{
const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
- struct perf_evsel *evsel = pevent->evsel;
+ struct evsel *evsel = pevent->evsel;
struct tep_format_field *field;
if (!evsel->tp_format) {
struct tep_event *tp_format;
- tp_format = trace_event__tp_format_id(evsel->attr.config);
+ tp_format = trace_event__tp_format_id(evsel->core.attr.config);
if (!tp_format)
return NULL;
@@ -430,8 +435,8 @@ static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch ev
static PyMemberDef pyrf_context_switch_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
- member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"),
- member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"),
+ member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"),
+ member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"),
{ .name = NULL, },
};
@@ -536,7 +541,7 @@ static PyObject *pyrf_event__new(union perf_event *event)
struct pyrf_cpu_map {
PyObject_HEAD
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
};
static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
@@ -549,7 +554,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
kwlist, &cpustr))
return -1;
- pcpus->cpus = cpu_map__new(cpustr);
+ pcpus->cpus = perf_cpu_map__new(cpustr);
if (pcpus->cpus == NULL)
return -1;
return 0;
@@ -557,7 +562,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
{
- cpu_map__put(pcpus->cpus);
+ perf_cpu_map__put(pcpus->cpus);
Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
}
@@ -605,7 +610,7 @@ static int pyrf_cpu_map__setup_types(void)
struct pyrf_thread_map {
PyObject_HEAD
- struct thread_map *threads;
+ struct perf_thread_map *threads;
};
static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
@@ -626,7 +631,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
{
- thread_map__put(pthreads->threads);
+ perf_thread_map__put(pthreads->threads);
Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
}
@@ -674,7 +679,7 @@ static int pyrf_thread_map__setup_types(void)
struct pyrf_evsel {
PyObject_HEAD
- struct perf_evsel evsel;
+ struct evsel evsel;
};
static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
@@ -782,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
attr.sample_id_all = sample_id_all;
attr.size = sizeof(attr);
- perf_evsel__init(&pevsel->evsel, &attr, idx);
+ evsel__init(&pevsel->evsel, &attr, idx);
return 0;
}
@@ -795,9 +800,9 @@ static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
PyObject *args, PyObject *kwargs)
{
- struct perf_evsel *evsel = &pevsel->evsel;
- struct cpu_map *cpus = NULL;
- struct thread_map *threads = NULL;
+ struct evsel *evsel = &pevsel->evsel;
+ struct perf_cpu_map *cpus = NULL;
+ struct perf_thread_map *threads = NULL;
PyObject *pcpus = NULL, *pthreads = NULL;
int group = 0, inherit = 0;
static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
@@ -812,12 +817,12 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
if (pcpus != NULL)
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
- evsel->attr.inherit = inherit;
+ evsel->core.attr.inherit = inherit;
/*
* This will group just the fds for this single evsel, to group
* multiple events, use evlist.open().
*/
- if (perf_evsel__open(evsel, cpus, threads) < 0) {
+ if (evsel__open(evsel, cpus, threads) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@@ -858,22 +863,22 @@ static int pyrf_evsel__setup_types(void)
struct pyrf_evlist {
PyObject_HEAD
- struct perf_evlist evlist;
+ struct evlist evlist;
};
static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs __maybe_unused)
{
PyObject *pcpus = NULL, *pthreads = NULL;
- struct cpu_map *cpus;
- struct thread_map *threads;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
return -1;
threads = ((struct pyrf_thread_map *)pthreads)->threads;
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
- perf_evlist__init(&pevlist->evlist, cpus, threads);
+ evlist__init(&pevlist->evlist, cpus, threads);
return 0;
}
@@ -886,7 +891,7 @@ static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
static char *kwlist[] = { "pages", "overwrite", NULL };
int pages = 128, overwrite = false;
@@ -906,7 +911,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
static char *kwlist[] = { "timeout", NULL };
int timeout = -1, n;
@@ -926,7 +931,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
PyObject *args __maybe_unused,
PyObject *kwargs __maybe_unused)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
PyObject *list = PyList_New(0);
int i;
@@ -964,22 +969,22 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
PyObject *args,
PyObject *kwargs __maybe_unused)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
PyObject *pevsel;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (!PyArg_ParseTuple(args, "O", &pevsel))
return NULL;
Py_INCREF(pevsel);
evsel = &((struct pyrf_evsel *)pevsel)->evsel;
- evsel->idx = evlist->nr_entries;
- perf_evlist__add(evlist, evsel);
+ evsel->idx = evlist->core.nr_entries;
+ evlist__add(evlist, evsel);
- return Py_BuildValue("i", evlist->nr_entries);
+ return Py_BuildValue("i", evlist->core.nr_entries);
}
-static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
+static struct perf_mmap *get_md(struct evlist *evlist, int cpu)
{
int i;
@@ -996,7 +1001,7 @@ static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
union perf_event *event;
int sample_id_all = 1, cpu;
static char *kwlist[] = { "cpu", "sample_id_all", NULL };
@@ -1018,7 +1023,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
if (event != NULL) {
PyObject *pyevent = pyrf_event__new(event);
struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
if (pyevent == NULL)
return PyErr_NoMemory();
@@ -1049,7 +1054,7 @@ end:
static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
- struct perf_evlist *evlist = &pevlist->evlist;
+ struct evlist *evlist = &pevlist->evlist;
int group = 0;
static char *kwlist[] = { "group", NULL };
@@ -1059,7 +1064,7 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
if (group)
perf_evlist__set_leader(evlist);
- if (perf_evlist__open(evlist) < 0) {
+ if (evlist__open(evlist) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@@ -1112,15 +1117,15 @@ static Py_ssize_t pyrf_evlist__length(PyObject *obj)
{
struct pyrf_evlist *pevlist = (void *)obj;
- return pevlist->evlist.nr_entries;
+ return pevlist->evlist.core.nr_entries;
}
static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
{
struct pyrf_evlist *pevlist = (void *)obj;
- struct perf_evsel *pos;
+ struct evsel *pos;
- if (i >= pevlist->evlist.nr_entries)
+ if (i >= pevlist->evlist.core.nr_entries)
return NULL;
evlist__for_each_entry(&pevlist->evlist, pos) {
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 9cfc7bf16531..286fe816c0f3 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -1,25 +1,31 @@
// SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
#include "evlist.h"
#include "evsel.h"
#include "cpumap.h"
#include "parse-events.h"
#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
#include <api/fs/fs.h>
#include <subcmd/parse-options.h>
+#include <perf/cpumap.h>
#include "util.h"
#include "cloexec.h"
+#include "record.h"
+#include "../perf-sys.h"
-typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
+typedef void (*setup_probe_fn_t)(struct evsel *evsel);
static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
{
- struct perf_evlist *evlist;
- struct perf_evsel *evsel;
+ struct evlist *evlist;
+ struct evsel *evsel;
unsigned long flags = perf_event_open_cloexec_flag();
int err = -EAGAIN, fd;
static pid_t pid = -1;
- evlist = perf_evlist__new();
+ evlist = evlist__new();
if (!evlist)
return -ENOMEM;
@@ -29,7 +35,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
evsel = perf_evlist__first(evlist);
while (1) {
- fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
+ fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags);
if (fd < 0) {
if (pid == -1 && errno == EACCES) {
pid = 0;
@@ -43,7 +49,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
fn(evsel);
- fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
+ fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags);
if (fd < 0) {
if (errno == EINVAL)
err = -EINVAL;
@@ -53,21 +59,21 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
err = 0;
out_delete:
- perf_evlist__delete(evlist);
+ evlist__delete(evlist);
return err;
}
static bool perf_probe_api(setup_probe_fn_t fn)
{
const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
int cpu, ret, i = 0;
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (!cpus)
return false;
cpu = cpus->map[0];
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
do {
ret = perf_do_probe_api(fn, cpu, try[i++]);
@@ -78,19 +84,19 @@ static bool perf_probe_api(setup_probe_fn_t fn)
return false;
}
-static void perf_probe_sample_identifier(struct perf_evsel *evsel)
+static void perf_probe_sample_identifier(struct evsel *evsel)
{
- evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
+ evsel->core.attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
}
-static void perf_probe_comm_exec(struct perf_evsel *evsel)
+static void perf_probe_comm_exec(struct evsel *evsel)
{
- evsel->attr.comm_exec = 1;
+ evsel->core.attr.comm_exec = 1;
}
-static void perf_probe_context_switch(struct perf_evsel *evsel)
+static void perf_probe_context_switch(struct evsel *evsel)
{
- evsel->attr.context_switch = 1;
+ evsel->core.attr.context_switch = 1;
}
bool perf_can_sample_identifier(void)
@@ -115,14 +121,14 @@ bool perf_can_record_cpu_wide(void)
.config = PERF_COUNT_SW_CPU_CLOCK,
.exclude_kernel = 1,
};
- struct cpu_map *cpus;
+ struct perf_cpu_map *cpus;
int cpu, fd;
- cpus = cpu_map__new(NULL);
+ cpus = perf_cpu_map__new(NULL);
if (!cpus)
return false;
cpu = cpus->map[0];
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
if (fd < 0)
@@ -132,10 +138,10 @@ bool perf_can_record_cpu_wide(void)
return true;
}
-void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
+void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
struct callchain_param *callchain)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool use_sample_identifier = false;
bool use_comm_exec;
bool sample_id = opts->sample_id;
@@ -147,7 +153,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
if (opts->group)
perf_evlist__set_leader(evlist);
- if (evlist->cpus->map[0] < 0)
+ if (evlist->core.cpus->map[0] < 0)
opts->no_inherit = true;
use_comm_exec = perf_can_comm_exec();
@@ -155,7 +161,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
evlist__for_each_entry(evlist, evsel) {
perf_evsel__config(evsel, opts, callchain);
if (evsel->tracking && use_comm_exec)
- evsel->attr.comm_exec = 1;
+ evsel->core.attr.comm_exec = 1;
}
if (opts->full_auxtrace) {
@@ -166,11 +172,11 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
*/
use_sample_identifier = perf_can_sample_identifier();
sample_id = true;
- } else if (evlist->nr_entries > 1) {
- struct perf_evsel *first = perf_evlist__first(evlist);
+ } else if (evlist->core.nr_entries > 1) {
+ struct evsel *first = perf_evlist__first(evlist);
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.sample_type == first->attr.sample_type)
+ if (evsel->core.attr.sample_type == first->core.attr.sample_type)
continue;
use_sample_identifier = perf_can_sample_identifier();
break;
@@ -256,15 +262,15 @@ int record_opts__config(struct record_opts *opts)
return record_opts__config_freq(opts);
}
-bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
+bool perf_evlist__can_select_event(struct evlist *evlist, const char *str)
{
- struct perf_evlist *temp_evlist;
- struct perf_evsel *evsel;
+ struct evlist *temp_evlist;
+ struct evsel *evsel;
int err, fd, cpu;
bool ret = false;
pid_t pid = -1;
- temp_evlist = perf_evlist__new();
+ temp_evlist = evlist__new();
if (!temp_evlist)
return false;
@@ -274,17 +280,17 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
evsel = perf_evlist__last(temp_evlist);
- if (!evlist || cpu_map__empty(evlist->cpus)) {
- struct cpu_map *cpus = cpu_map__new(NULL);
+ if (!evlist || perf_cpu_map__empty(evlist->core.cpus)) {
+ struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
cpu = cpus ? cpus->map[0] : 0;
- cpu_map__put(cpus);
+ perf_cpu_map__put(cpus);
} else {
- cpu = evlist->cpus->map[0];
+ cpu = evlist->core.cpus->map[0];
}
while (1) {
- fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
+ fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
if (pid == -1 && errno == EACCES) {
@@ -299,7 +305,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
ret = true;
out_delete:
- perf_evlist__delete(temp_evlist);
+ evlist__delete(temp_evlist);
return ret;
}
diff --git a/tools/perf/util/record.h b/tools/perf/util/record.h
new file mode 100644
index 000000000000..00275afc524d
--- /dev/null
+++ b/tools/perf/util/record.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _PERF_RECORD_H
+#define _PERF_RECORD_H
+
+#include <time.h>
+#include <stdbool.h>
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/perf_event.h>
+#include "util/target.h"
+
+struct option;
+
+struct record_opts {
+ struct target target;
+ bool group;
+ bool inherit_stat;
+ bool no_buffering;
+ bool no_inherit;
+ bool no_inherit_set;
+ bool no_samples;
+ bool raw_samples;
+ bool sample_address;
+ bool sample_phys_addr;
+ bool sample_weight;
+ bool sample_time;
+ bool sample_time_set;
+ bool sample_cpu;
+ bool period;
+ bool period_set;
+ bool running_time;
+ bool full_auxtrace;
+ bool auxtrace_snapshot_mode;
+ bool auxtrace_snapshot_on_exit;
+ bool record_namespaces;
+ bool record_switch_events;
+ bool all_kernel;
+ bool all_user;
+ bool kernel_callchains;
+ bool user_callchains;
+ bool tail_synthesize;
+ bool overwrite;
+ bool ignore_missing_thread;
+ bool strict_freq;
+ bool sample_id;
+ bool no_bpf_event;
+ unsigned int freq;
+ unsigned int mmap_pages;
+ unsigned int auxtrace_mmap_pages;
+ unsigned int user_freq;
+ u64 branch_stack;
+ u64 sample_intr_regs;
+ u64 sample_user_regs;
+ u64 default_interval;
+ u64 user_interval;
+ size_t auxtrace_snapshot_size;
+ const char *auxtrace_snapshot_opts;
+ bool sample_transaction;
+ unsigned initial_delay;
+ bool use_clockid;
+ clockid_t clockid;
+ u64 clockid_res_ns;
+ int nr_cblocks;
+ int affinity;
+ int mmap_flush;
+ unsigned int comp_level;
+};
+
+extern const char * const *record_usage;
+extern struct option *record_options;
+
+int record__parse_freq(const struct option *opt, const char *str, int unset);
+
+#endif // _PERF_RECORD_H
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
index 83d2e149ef19..24a99909d8b3 100644
--- a/tools/perf/util/s390-cpumsf.c
+++ b/tools/perf/util/s390-cpumsf.c
@@ -157,7 +157,7 @@
#include "evlist.h"
#include "machine.h"
#include "session.h"
-#include "thread.h"
+#include "tool.h"
#include "debug.h"
#include "auxtrace.h"
#include "s390-cpumsf.h"
@@ -918,7 +918,7 @@ s390_cpumsf_process_event(struct perf_session *session,
struct s390_cpumsf,
auxtrace);
u64 timestamp = sample->time;
- struct perf_evsel *ev_bc000;
+ struct evsel *ev_bc000;
int err = 0;
@@ -935,7 +935,7 @@ s390_cpumsf_process_event(struct perf_session *session,
/* Handle event with raw data */
ev_bc000 = perf_evlist__event2evsel(session->evlist, event);
if (ev_bc000 &&
- ev_bc000->attr.config == PERF_EVENT_CPUM_CF_DIAG)
+ ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG)
err = s390_cpumcf_dumpctr(sf, sample);
return err;
}
@@ -1109,11 +1109,11 @@ static int s390_cpumsf__config(const char *var, const char *value, void *cb)
int s390_cpumsf_process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
- struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
struct s390_cpumsf *sf;
int err;
- if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event))
+ if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info))
return -EINVAL;
sf = zalloc(sizeof(struct s390_cpumsf));
diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c
index 6650f599ed9c..4d9593e331ea 100644
--- a/tools/perf/util/s390-sample-raw.c
+++ b/tools/perf/util/s390-sample-raw.c
@@ -23,10 +23,8 @@
#include "debug.h"
#include "util.h"
-#include "auxtrace.h"
#include "session.h"
#include "evlist.h"
-#include "config.h"
#include "color.h"
#include "sample-raw.h"
#include "s390-cpumcf-kernel.h"
@@ -200,17 +198,17 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
* its raw data.
* The function is only invoked when the dump flag -D is set.
*/
-void perf_evlist__s390_sample_raw(struct perf_evlist *evlist, union perf_event *event,
+void perf_evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event,
struct perf_sample *sample)
{
- struct perf_evsel *ev_bc000;
+ struct evsel *ev_bc000;
if (event->header.type != PERF_RECORD_SAMPLE)
return;
ev_bc000 = perf_evlist__event2evsel(evlist, event);
if (ev_bc000 == NULL ||
- ev_bc000->attr.config != PERF_EVENT_CPUM_CF_DIAG)
+ ev_bc000->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
return;
/* Display raw data on screen */
diff --git a/tools/perf/util/sample-raw.c b/tools/perf/util/sample-raw.c
index c21e1311fb0f..e84bbe0e441a 100644
--- a/tools/perf/util/sample-raw.c
+++ b/tools/perf/util/sample-raw.c
@@ -9,7 +9,7 @@
* Check platform the perf data file was created on and perform platform
* specific interpretation.
*/
-void perf_evlist__init_trace_event_sample_raw(struct perf_evlist *evlist)
+void perf_evlist__init_trace_event_sample_raw(struct evlist *evlist)
{
const char *arch_pf = perf_env__arch(evlist->env);
diff --git a/tools/perf/util/sample-raw.h b/tools/perf/util/sample-raw.h
index 95d445c87e93..afe1491a117e 100644
--- a/tools/perf/util/sample-raw.h
+++ b/tools/perf/util/sample-raw.h
@@ -2,13 +2,13 @@
#ifndef __SAMPLE_RAW_H
#define __SAMPLE_RAW_H 1
-struct perf_evlist;
+struct evlist;
union perf_event;
struct perf_sample;
-void perf_evlist__s390_sample_raw(struct perf_evlist *evlist,
+void perf_evlist__s390_sample_raw(struct evlist *evlist,
union perf_event *event,
struct perf_sample *sample);
-void perf_evlist__init_trace_event_sample_raw(struct perf_evlist *evlist);
+void perf_evlist__init_trace_event_sample_raw(struct evlist *evlist);
#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 61aa7f3df915..15961854ba67 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -34,8 +34,8 @@
#include <EXTERN.h>
#include <perl.h>
-#include "../../perf.h"
#include "../callchain.h"
+#include "../dso.h"
#include "../machine.h"
#include "../map.h"
#include "../symbol.h"
@@ -258,7 +258,7 @@ static void define_event_symbols(struct tep_event *event,
}
static SV *perl_process_callchain(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
AV *list;
@@ -336,7 +336,7 @@ exit:
}
static void perl_process_tracepoint(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
struct thread *thread = al->thread;
@@ -353,11 +353,11 @@ static void perl_process_tracepoint(struct perf_sample *sample,
dSP;
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
return;
if (!event) {
- pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
+ pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config);
return;
}
@@ -431,7 +431,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
static void perl_process_event_generic(union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
dSP;
@@ -442,7 +442,7 @@ static void perl_process_event_generic(union perf_event *event,
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size)));
- XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
+ XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->core.attr, sizeof(evsel->core.attr))));
XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
PUTBACK;
@@ -455,7 +455,7 @@ static void perl_process_event_generic(union perf_event *event,
static void perl_process_event(union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
perl_process_tracepoint(sample, evsel, al);
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 25dc1d765553..666a56e88d8e 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -31,8 +31,10 @@
#include <linux/compiler.h>
#include <linux/time64.h>
-#include "../../perf.h"
+#include "../build-id.h"
+#include "../counts.h"
#include "../debug.h"
+#include "../dso.h"
#include "../callchain.h"
#include "../evsel.h"
#include "../util.h"
@@ -392,7 +394,7 @@ static const char *get_dsoname(struct map *map)
}
static PyObject *python_process_callchain(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
PyObject *pylist;
@@ -634,9 +636,9 @@ static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
static void set_sample_read_in_dict(PyObject *dict_sample,
struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
- u64 read_format = evsel->attr.read_format;
+ u64 read_format = evsel->core.attr.read_format;
PyObject *values;
unsigned int i;
@@ -705,9 +707,9 @@ static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size)
static void set_regs_in_dict(PyObject *dict,
struct perf_sample *sample,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
- struct perf_event_attr *attr = &evsel->attr;
+ struct perf_event_attr *attr = &evsel->core.attr;
char bf[512];
regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf));
@@ -722,7 +724,7 @@ static void set_regs_in_dict(PyObject *dict,
}
static PyObject *get_perf_sample_dict(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al,
PyObject *callchain)
{
@@ -737,7 +739,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
Py_FatalError("couldn't create Python dictionary");
pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel)));
- pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->attr, sizeof(evsel->attr)));
+ pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->core.attr, sizeof(evsel->core.attr)));
pydict_set_item_string_decref(dict_sample, "pid",
_PyLong_FromLong(sample->pid));
@@ -790,7 +792,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
}
static void python_process_tracepoint(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
struct tep_event *event = evsel->tp_format;
@@ -809,7 +811,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
if (!event) {
snprintf(handler_name, sizeof(handler_name),
- "ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
+ "ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config);
Py_FatalError(handler_name);
}
@@ -955,7 +957,7 @@ static int tuple_set_bytes(PyObject *t, unsigned int pos, void *bytes,
return PyTuple_SetItem(t, pos, _PyBytes_FromStringAndSize(bytes, sz));
}
-static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
+static int python_export_evsel(struct db_export *dbe, struct evsel *evsel)
{
struct tables *tables = container_of(dbe, struct tables, dbe);
PyObject *t;
@@ -1163,7 +1165,7 @@ static void python_export_synth(struct db_export *dbe, struct export_sample *es)
t = tuple_new(3);
tuple_set_u64(t, 0, es->db_id);
- tuple_set_u64(t, 1, es->evsel->attr.config);
+ tuple_set_u64(t, 1, es->evsel->core.attr.config);
tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size);
call_object(tables->synth_handler, t, "synth_data");
@@ -1178,7 +1180,7 @@ static int python_export_sample(struct db_export *dbe,
python_export_sample_table(dbe, es);
- if (es->evsel->attr.type == PERF_TYPE_SYNTH && tables->synth_handler)
+ if (es->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler)
python_export_synth(dbe, es);
return 0;
@@ -1275,7 +1277,7 @@ static int python_process_call_return(struct call_return *cr, u64 *parent_db_id,
}
static void python_process_general_event(struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
PyObject *handler, *t, *dict, *callchain;
@@ -1311,12 +1313,12 @@ static void python_process_general_event(struct perf_sample *sample,
static void python_process_event(union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al)
{
struct tables *tables = &tables_global;
- switch (evsel->attr.type) {
+ switch (evsel->core.attr.type) {
case PERF_TYPE_TRACEPOINT:
python_process_tracepoint(sample, evsel, al);
break;
@@ -1340,7 +1342,7 @@ static void python_process_switch(union perf_event *event,
}
static void get_handler_name(char *str, size_t size,
- struct perf_evsel *evsel)
+ struct evsel *evsel)
{
char *p = str;
@@ -1353,7 +1355,7 @@ static void get_handler_name(char *str, size_t size,
}
static void
-process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
+process_stat(struct evsel *counter, int cpu, int thread, u64 tstamp,
struct perf_counts_values *count)
{
PyObject *handler, *t;
@@ -1390,10 +1392,10 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
}
static void python_process_stat(struct perf_stat_config *config,
- struct perf_evsel *counter, u64 tstamp)
+ struct evsel *counter, u64 tstamp)
{
- struct thread_map *threads = counter->threads;
- struct cpu_map *cpus = counter->cpus;
+ struct perf_thread_map *threads = counter->core.threads;
+ struct perf_cpu_map *cpus = counter->core.cpus;
int cpu, thread;
if (config->aggr_mode == AGGR_GLOBAL) {
@@ -1405,7 +1407,7 @@ static void python_process_stat(struct perf_stat_config *config,
for (thread = 0; thread < threads->nr; thread++) {
for (cpu = 0; cpu < cpus->nr; cpu++) {
process_stat(counter, cpus->map[cpu],
- thread_map__pid(threads, thread), tstamp,
+ perf_thread_map__pid(threads, thread), tstamp,
perf_counts(counter->counts, cpu, thread));
}
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d0fd6c614e68..e9e4a04f15db 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,16 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <inttypes.h>
+#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/zalloc.h>
-#include <traceevent/event-parse.h>
#include <api/fs/fs.h>
#include <byteswap.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <perf/cpumap.h>
+#include "map_symbol.h"
+#include "branch.h"
+#include "debug.h"
#include "evlist.h"
#include "evsel.h"
#include "memswap.h"
@@ -18,7 +22,6 @@
#include "symbol.h"
#include "session.h"
#include "tool.h"
-#include "sort.h"
#include "cpumap.h"
#include "perf_regs.h"
#include "asm/bug.h"
@@ -27,6 +30,9 @@
#include "thread-stack.h"
#include "sample-raw.h"
#include "stat.h"
+#include "util.h"
+#include "ui/progress.h"
+#include "../perf.h"
#include "arch/common.h"
#ifdef HAVE_ZSTD_SUPPORT
@@ -36,10 +42,16 @@ static int perf_session__process_compressed_event(struct perf_session *session,
void *src;
size_t decomp_size, src_size;
u64 decomp_last_rem = 0;
- size_t decomp_len = session->header.env.comp_mmap_len;
+ size_t mmap_len, decomp_len = session->header.env.comp_mmap_len;
struct decomp *decomp, *decomp_last = session->decomp_last;
- decomp = mmap(NULL, sizeof(struct decomp) + decomp_len, PROT_READ|PROT_WRITE,
+ if (decomp_last) {
+ decomp_last_rem = decomp_last->size - decomp_last->head;
+ decomp_len += decomp_last_rem;
+ }
+
+ mmap_len = sizeof(struct decomp) + decomp_len;
+ decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (decomp == MAP_FAILED) {
pr_err("Couldn't allocate memory for decompression\n");
@@ -47,21 +59,21 @@ static int perf_session__process_compressed_event(struct perf_session *session,
}
decomp->file_pos = file_offset;
+ decomp->mmap_len = mmap_len;
decomp->head = 0;
- if (decomp_last) {
- decomp_last_rem = decomp_last->size - decomp_last->head;
+ if (decomp_last_rem) {
memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem);
decomp->size = decomp_last_rem;
}
- src = (void *)event + sizeof(struct compressed_event);
- src_size = event->pack.header.size - sizeof(struct compressed_event);
+ src = (void *)event + sizeof(struct perf_record_compressed);
+ src_size = event->pack.header.size - sizeof(struct perf_record_compressed);
decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size,
&(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem);
if (!decomp_size) {
- munmap(decomp, sizeof(struct decomp) + decomp_len);
+ munmap(decomp, mmap_len);
pr_err("Couldn't decompress data\n");
return -1;
}
@@ -145,10 +157,10 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
static bool perf_session__has_comm_exec(struct perf_session *session)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.comm_exec)
+ if (evsel->core.attr.comm_exec)
return true;
}
@@ -255,15 +267,15 @@ static void perf_session__delete_threads(struct perf_session *session)
static void perf_session__release_decomp_events(struct perf_session *session)
{
struct decomp *next, *decomp;
- size_t decomp_len;
+ size_t mmap_len;
next = session->decomp;
- decomp_len = session->header.env.comp_mmap_len;
do {
decomp = next;
if (decomp == NULL)
break;
next = decomp->next;
- munmap(decomp, decomp_len + sizeof(struct decomp));
+ mmap_len = decomp->mmap_len;
+ munmap(decomp, mmap_len);
} while (1);
}
@@ -294,7 +306,7 @@ static int process_event_synth_tracing_data_stub(struct perf_session *session
static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
- struct perf_evlist **pevlist
+ struct evlist **pevlist
__maybe_unused)
{
dump_printf(": unhandled!\n");
@@ -303,7 +315,7 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
- struct perf_evlist **pevlist
+ struct evlist **pevlist
__maybe_unused)
{
if (dump_trace)
@@ -316,7 +328,7 @@ static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_
static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct machine *machine __maybe_unused)
{
dump_printf(": unhandled!\n");
@@ -465,8 +477,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->context_switch = perf_event__process_switch;
if (tool->ksymbol == NULL)
tool->ksymbol = perf_event__process_ksymbol;
- if (tool->bpf_event == NULL)
- tool->bpf_event = perf_event__process_bpf_event;
+ if (tool->bpf == NULL)
+ tool->bpf = perf_event__process_bpf;
if (tool->read == NULL)
tool->read = process_event_sample_stub;
if (tool->throttle == NULL)
@@ -827,9 +839,9 @@ static void perf_event__thread_map_swap(union perf_event *event,
static void perf_event__cpu_map_swap(union perf_event *event,
bool sample_id_all __maybe_unused)
{
- struct cpu_map_data *data = &event->cpu_map.data;
+ struct perf_record_cpu_map_data *data = &event->cpu_map.data;
struct cpu_map_entries *cpus;
- struct cpu_map_mask *mask;
+ struct perf_record_record_cpu_map *mask;
unsigned i;
data->type = bswap_64(data->type);
@@ -844,7 +856,7 @@ static void perf_event__cpu_map_swap(union perf_event *event,
cpus->cpu[i] = bswap_16(cpus->cpu[i]);
break;
case PERF_CPU_MAP__MASK:
- mask = (struct cpu_map_mask *) data->data;
+ mask = (struct perf_record_record_cpu_map *)data->data;
mask->nr = bswap_16(mask->nr);
mask->long_size = bswap_16(mask->long_size);
@@ -1027,7 +1039,7 @@ static void callchain__lbr_callstack_printf(struct perf_sample *sample)
}
}
-static void callchain__printf(struct perf_evsel *evsel,
+static void callchain__printf(struct evsel *evsel,
struct perf_sample *sample)
{
unsigned int i;
@@ -1043,23 +1055,30 @@ static void callchain__printf(struct perf_evsel *evsel,
i, callchain->ips[i]);
}
-static void branch_stack__printf(struct perf_sample *sample)
+static void branch_stack__printf(struct perf_sample *sample, bool callstack)
{
uint64_t i;
- printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
+ printf("%s: nr:%" PRIu64 "\n",
+ !callstack ? "... branch stack" : "... branch callstack",
+ sample->branch_stack->nr);
for (i = 0; i < sample->branch_stack->nr; i++) {
struct branch_entry *e = &sample->branch_stack->entries[i];
- printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
- i, e->from, e->to,
- (unsigned short)e->flags.cycles,
- e->flags.mispred ? "M" : " ",
- e->flags.predicted ? "P" : " ",
- e->flags.abort ? "A" : " ",
- e->flags.in_tx ? "T" : " ",
- (unsigned)e->flags.reserved);
+ if (!callstack) {
+ printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
+ i, e->from, e->to,
+ (unsigned short)e->flags.cycles,
+ e->flags.mispred ? "M" : " ",
+ e->flags.predicted ? "P" : " ",
+ e->flags.abort ? "A" : " ",
+ e->flags.in_tx ? "T" : " ",
+ (unsigned)e->flags.reserved);
+ } else {
+ printf("..... %2"PRIu64": %016" PRIx64 "\n",
+ i, i > 0 ? e->from : e->to);
+ }
}
}
@@ -1123,7 +1142,7 @@ static void stack_user__printf(struct stack_dump *dump)
dump->size, dump->offset);
}
-static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
+static void perf_evlist__print_tstamp(struct evlist *evlist,
union perf_event *event,
struct perf_sample *sample)
{
@@ -1172,7 +1191,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
sample->read.one.id, sample->read.one.value);
}
-static void dump_event(struct perf_evlist *evlist, union perf_event *event,
+static void dump_event(struct evlist *evlist, union perf_event *event,
u64 file_offset, struct perf_sample *sample)
{
if (!dump_trace)
@@ -1192,7 +1211,7 @@ static void dump_event(struct perf_evlist *evlist, union perf_event *event,
event->header.size, perf_event__name(event->header.type));
}
-static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
+static void dump_sample(struct evsel *evsel, union perf_event *event,
struct perf_sample *sample)
{
u64 sample_type;
@@ -1204,13 +1223,13 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
event->header.misc, sample->pid, sample->tid, sample->ip,
sample->period, sample->addr);
- sample_type = evsel->attr.sample_type;
+ sample_type = evsel->core.attr.sample_type;
if (evsel__has_callchain(evsel))
callchain__printf(evsel, sample);
- if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
- branch_stack__printf(sample);
+ if (sample_type & PERF_SAMPLE_BRANCH_STACK)
+ branch_stack__printf(sample, perf_evsel__has_branch_callstack(evsel));
if (sample_type & PERF_SAMPLE_REGS_USER)
regs_user__printf(sample);
@@ -1234,34 +1253,34 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
printf("... transaction: %" PRIx64 "\n", sample->transaction);
if (sample_type & PERF_SAMPLE_READ)
- sample_read__printf(sample, evsel->attr.read_format);
+ sample_read__printf(sample, evsel->core.attr.read_format);
}
-static void dump_read(struct perf_evsel *evsel, union perf_event *event)
+static void dump_read(struct evsel *evsel, union perf_event *event)
{
- struct read_event *read_event = &event->read;
+ struct perf_record_read *read_event = &event->read;
u64 read_format;
if (!dump_trace)
return;
- printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
+ printf(": %d %d %s %" PRI_lu64 "\n", event->read.pid, event->read.tid,
perf_evsel__name(evsel),
event->read.value);
if (!evsel)
return;
- read_format = evsel->attr.read_format;
+ read_format = evsel->core.attr.read_format;
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
- printf("... time enabled : %" PRIu64 "\n", read_event->time_enabled);
+ printf("... time enabled : %" PRI_lu64 "\n", read_event->time_enabled);
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
- printf("... time running : %" PRIu64 "\n", read_event->time_running);
+ printf("... time running : %" PRI_lu64 "\n", read_event->time_running);
if (read_format & PERF_FORMAT_ID)
- printf("... id : %" PRIu64 "\n", read_event->id);
+ printf("... id : %" PRI_lu64 "\n", read_event->id);
}
static struct machine *machines__find_for_cpumode(struct machines *machines,
@@ -1290,7 +1309,7 @@ static struct machine *machines__find_for_cpumode(struct machines *machines,
return &machines->host;
}
-static int deliver_sample_value(struct perf_evlist *evlist,
+static int deliver_sample_value(struct evlist *evlist,
struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -1320,7 +1339,7 @@ static int deliver_sample_value(struct perf_evlist *evlist,
return tool->sample(tool, event, sample, sid->evsel, machine);
}
-static int deliver_sample_group(struct perf_evlist *evlist,
+static int deliver_sample_group(struct evlist *evlist,
struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -1341,16 +1360,16 @@ static int deliver_sample_group(struct perf_evlist *evlist,
}
static int
- perf_evlist__deliver_sample(struct perf_evlist *evlist,
+ perf_evlist__deliver_sample(struct evlist *evlist,
struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct machine *machine)
{
/* We know evsel != NULL. */
- u64 sample_type = evsel->attr.sample_type;
- u64 read_format = evsel->attr.read_format;
+ u64 sample_type = evsel->core.attr.sample_type;
+ u64 read_format = evsel->core.attr.read_format;
/* Standard sample delivery. */
if (!(sample_type & PERF_SAMPLE_READ))
@@ -1366,12 +1385,12 @@ static int
}
static int machines__deliver_event(struct machines *machines,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
union perf_event *event,
struct perf_sample *sample,
struct perf_tool *tool, u64 file_offset)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct machine *machine;
dump_event(evlist, event, file_offset, sample);
@@ -1437,7 +1456,7 @@ static int machines__deliver_event(struct machines *machines,
case PERF_RECORD_KSYMBOL:
return tool->ksymbol(tool, event, sample, machine);
case PERF_RECORD_BPF_EVENT:
- return tool->bpf_event(tool, event, sample, machine);
+ return tool->bpf(tool, event, sample, machine);
default:
++evlist->stats.nr_unknown_events;
return -1;
@@ -1547,7 +1566,7 @@ int perf_session__deliver_synth_event(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample)
{
- struct perf_evlist *evlist = session->evlist;
+ struct evlist *evlist = session->evlist;
struct perf_tool *tool = session->tool;
events_stats__inc(&evlist->stats, event->header.type);
@@ -1625,7 +1644,7 @@ out_parse_sample:
static s64 perf_session__process_event(struct perf_session *session,
union perf_event *event, u64 file_offset)
{
- struct perf_evlist *evlist = session->evlist;
+ struct evlist *evlist = session->evlist;
struct perf_tool *tool = session->tool;
int ret;
@@ -1699,11 +1718,11 @@ static void
perf_session__warn_order(const struct perf_session *session)
{
const struct ordered_events *oe = &session->ordered_events;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
bool should_warn = true;
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.write_backward)
+ if (evsel->core.attr.write_backward)
should_warn = false;
}
@@ -1948,7 +1967,9 @@ fetch_mmaped_event(struct perf_session *session,
/* We're not fetching the event so swap back again */
if (session->header.needs_swap)
perf_event_header__bswap(&event->header);
- return NULL;
+ pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx: fuzzed perf.data?\n",
+ __func__, head, event->header.size, mmap_size);
+ return ERR_PTR(-EINVAL);
}
return event;
@@ -1966,6 +1987,9 @@ static int __perf_session__process_decomp_events(struct perf_session *session)
while (decomp->head < decomp->size && !session_done()) {
union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data);
+ if (IS_ERR(event))
+ return PTR_ERR(event);
+
if (!event)
break;
@@ -2065,6 +2089,9 @@ remap:
more:
event = fetch_mmaped_event(session, head, mmap_size, buf);
+ if (IS_ERR(event))
+ return PTR_ERR(event);
+
if (!event) {
if (mmaps[map_idx]) {
munmap(mmaps[map_idx], mmap_size);
@@ -2177,10 +2204,10 @@ int perf_session__process_events(struct perf_session *session)
bool perf_session__has_traces(struct perf_session *session, const char *msg)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(session->evlist, evsel) {
- if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT)
return true;
}
@@ -2251,13 +2278,13 @@ size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
return machine__fprintf(&session->machines.host, fp);
}
-struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
+struct evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
evlist__for_each_entry(session->evlist, pos) {
- if (pos->attr.type == type)
+ if (pos->core.attr.type == type)
return pos;
}
return NULL;
@@ -2267,23 +2294,24 @@ int perf_session__cpu_bitmap(struct perf_session *session,
const char *cpu_list, unsigned long *cpu_bitmap)
{
int i, err = -1;
- struct cpu_map *map;
+ struct perf_cpu_map *map;
+ int nr_cpus = min(session->header.env.nr_cpus_online, MAX_NR_CPUS);
for (i = 0; i < PERF_TYPE_MAX; ++i) {
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = perf_session__find_first_evtype(session, i);
if (!evsel)
continue;
- if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
+ if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CPU)) {
pr_err("File does not contain CPU events. "
"Remove -C option to proceed.\n");
return -1;
}
}
- map = cpu_map__new(cpu_list);
+ map = perf_cpu_map__new(cpu_list);
if (map == NULL) {
pr_err("Invalid cpu_list\n");
return -1;
@@ -2292,7 +2320,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
for (i = 0; i < map->nr; i++) {
int cpu = map->map[i];
- if (cpu >= MAX_NR_CPUS) {
+ if (cpu >= nr_cpus) {
pr_err("Requested CPU %d too large. "
"Consider raising MAX_NR_CPUS\n", cpu);
goto out_delete_map;
@@ -2304,7 +2332,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
err = 0;
out_delete_map:
- cpu_map__put(map);
+ perf_cpu_map__put(map);
return err;
}
@@ -2321,10 +2349,10 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
int __perf_session__set_tracepoints_handlers(struct perf_session *session,
- const struct perf_evsel_str_handler *assocs,
+ const struct evsel_str_handler *assocs,
size_t nr_assocs)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
size_t i;
int err;
@@ -2351,11 +2379,11 @@ out:
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event)
{
- struct perf_evlist *evlist = session->evlist;
- struct id_index_event *ie = &event->id_index;
+ struct evlist *evlist = session->evlist;
+ struct perf_record_id_index *ie = &event->id_index;
size_t i, nr, max_nr;
- max_nr = (ie->header.size - sizeof(struct id_index_event)) /
+ max_nr = (ie->header.size - sizeof(struct perf_record_id_index)) /
sizeof(struct id_index_entry);
nr = ie->nr;
if (nr > max_nr)
@@ -2369,10 +2397,10 @@ int perf_event__process_id_index(struct perf_session *session,
struct perf_sample_id *sid;
if (dump_trace) {
- fprintf(stdout, " ... id: %"PRIu64, e->id);
- fprintf(stdout, " idx: %"PRIu64, e->idx);
- fprintf(stdout, " cpu: %"PRId64, e->cpu);
- fprintf(stdout, " tid: %"PRId64"\n", e->tid);
+ fprintf(stdout, " ... id: %"PRI_lu64, e->id);
+ fprintf(stdout, " idx: %"PRI_lu64, e->idx);
+ fprintf(stdout, " cpu: %"PRI_ld64, e->cpu);
+ fprintf(stdout, " tid: %"PRI_ld64"\n", e->tid);
}
sid = perf_evlist__id2sid(evlist, e->id);
@@ -2387,24 +2415,24 @@ int perf_event__process_id_index(struct perf_session *session,
int perf_event__synthesize_id_index(struct perf_tool *tool,
perf_event__handler_t process,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct machine *machine)
{
union perf_event *ev;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
size_t nr = 0, i = 0, sz, max_nr, n;
int err;
pr_debug2("Synthesizing id index\n");
- max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
+ max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) /
sizeof(struct id_index_entry);
evlist__for_each_entry(evlist, evsel)
nr += evsel->ids;
n = nr > max_nr ? max_nr : nr;
- sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
+ sz = sizeof(struct perf_record_id_index) + n * sizeof(struct id_index_entry);
ev = zalloc(sz);
if (!ev)
return -ENOMEM;
@@ -2444,7 +2472,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
}
}
- sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
+ sz = sizeof(struct perf_record_id_index) + nr * sizeof(struct id_index_entry);
ev->id_index.header.size = sz;
ev->id_index.nr = nr;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dd8920b745bc..b7aa076ab6fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -23,12 +23,12 @@ struct itrace_synth_opts;
struct perf_session {
struct perf_header header;
struct machines machines;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct auxtrace *auxtrace;
struct itrace_synth_opts *itrace_synth_opts;
struct list_head auxtrace_index;
struct trace_event tevent;
- struct time_conv_event time_conv;
+ struct perf_record_time_conv time_conv;
bool repipe;
bool one_mmap;
void *one_mmap_addr;
@@ -46,6 +46,7 @@ struct perf_session {
struct decomp {
struct decomp *next;
u64 file_pos;
+ size_t mmap_len;
u64 head;
size_t size;
char data[];
@@ -72,7 +73,7 @@ int perf_session__queue_event(struct perf_session *s, union perf_event *event,
void perf_tool__fill_defaults(struct perf_tool *tool);
int perf_session__resolve_callchain(struct perf_session *session,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct thread *thread,
struct ip_callchain *chain,
struct symbol **parent);
@@ -109,7 +110,7 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
-struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
+struct evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type);
int perf_session__cpu_bitmap(struct perf_session *session,
@@ -117,10 +118,10 @@ int perf_session__cpu_bitmap(struct perf_session *session,
void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
-struct perf_evsel_str_handler;
+struct evsel_str_handler;
int __perf_session__set_tracepoints_handlers(struct perf_session *session,
- const struct perf_evsel_str_handler *assocs,
+ const struct evsel_str_handler *assocs,
size_t nr_assocs);
#define perf_session__set_tracepoints_handlers(session, array) \
@@ -139,7 +140,7 @@ int perf_event__process_id_index(struct perf_session *session,
int perf_event__synthesize_id_index(struct perf_tool *tool,
perf_event__handler_t process,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
struct machine *machine);
#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index a1a68a2fa917..aa344a163eaf 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -48,6 +48,7 @@ build_lib = getenv('PYTHON_EXTBUILD_LIB')
build_tmp = getenv('PYTHON_EXTBUILD_TMP')
libtraceevent = getenv('LIBTRACEEVENT')
libapikfs = getenv('LIBAPI')
+libperf = getenv('LIBPERF')
ext_sources = [f.strip() for f in open('util/python-ext-sources')
if len(f.strip()) > 0 and f[0] != '#']
@@ -58,13 +59,15 @@ ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources))
extra_libraries = []
if '-DHAVE_LIBNUMA_SUPPORT' in cflags:
extra_libraries = [ 'numa' ]
+if '-DHAVE_LIBCAP_SUPPORT' in cflags:
+ extra_libraries += [ 'cap' ]
perf = Extension('perf',
sources = ext_sources,
include_dirs = ['util/include'],
libraries = extra_libraries,
extra_compile_args = cflags,
- extra_objects = [libtraceevent, libapikfs],
+ extra_objects = [libtraceevent, libapikfs, libperf],
)
setup(name='perf',
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5d2518e89fc4..a2308eb77681 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2,16 +2,23 @@
#include <errno.h>
#include <inttypes.h>
#include <regex.h>
+#include <stdlib.h>
#include <linux/mman.h>
#include <linux/time64.h>
+#include "debug.h"
+#include "dso.h"
#include "sort.h"
#include "hist.h"
+#include "cacheline.h"
#include "comm.h"
#include "map.h"
#include "symbol.h"
+#include "map_symbol.h"
+#include "branch.h"
#include "thread.h"
#include "evsel.h"
#include "evlist.h"
+#include "srcline.h"
#include "strlist.h"
#include "strbuf.h"
#include <traceevent/event-parse.h>
@@ -19,6 +26,7 @@
#include "annotate.h"
#include "time-utils.h"
#include <linux/kernel.h>
+#include <linux/string.h>
regex_t parent_regex;
const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -668,17 +676,11 @@ sort__time_cmp(struct hist_entry *left, struct hist_entry *right)
static int hist_entry__time_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
- unsigned long secs;
- unsigned long long nsecs;
char he_time[32];
- nsecs = he->time;
- secs = nsecs / NSEC_PER_SEC;
- nsecs -= secs * NSEC_PER_SEC;
-
if (symbol_conf.nanosecs)
- snprintf(he_time, sizeof he_time, "%5lu.%09llu: ",
- secs, nsecs);
+ timestamp__scnprintf_nsec(he->time, he_time,
+ sizeof(he_time));
else
timestamp__scnprintf_usec(he->time, he_time,
sizeof(he_time));
@@ -698,7 +700,7 @@ struct sort_entry sort_time = {
static char *get_trace_output(struct hist_entry *he)
{
struct trace_seq seq;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_record rec = {
.data = he->raw_data,
.size = he->raw_size,
@@ -711,7 +713,8 @@ static char *get_trace_output(struct hist_entry *he)
tep_print_fields(&seq, he->raw_data, he->raw_size,
evsel->tp_format);
} else {
- tep_event_info(&seq, evsel->tp_format, &rec);
+ tep_print_event(evsel->tp_format->tep,
+ &seq, &rec, "%s", TEP_PRINT_INFO);
}
/*
* Trim the buffer, it starts at 4KB and we're not going to
@@ -723,10 +726,10 @@ static char *get_trace_output(struct hist_entry *he)
static int64_t
sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = hists_to_evsel(left->hists);
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
return 0;
if (left->trace_output == NULL)
@@ -740,10 +743,10 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = hists_to_evsel(he->hists);
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
return scnprintf(bf, size, "%-.*s", width, "N/A");
if (he->trace_output == NULL)
@@ -1984,7 +1987,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
struct hpp_dynamic_entry {
struct perf_hpp_fmt hpp;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
unsigned dynamic_len;
bool raw_trace;
@@ -2218,7 +2221,7 @@ static void hde_free(struct perf_hpp_fmt *fmt)
}
static struct hpp_dynamic_entry *
-__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field,
+__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field,
int level)
{
struct hpp_dynamic_entry *hde;
@@ -2313,17 +2316,17 @@ static int parse_field_name(char *str, char **event, char **field, char **opt)
* 2. full event name (e.g. sched:sched_switch)
* 3. partial event name (should not contain ':')
*/
-static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
+static struct evsel *find_evsel(struct evlist *evlist, char *event_name)
{
- struct perf_evsel *evsel = NULL;
- struct perf_evsel *pos;
+ struct evsel *evsel = NULL;
+ struct evsel *pos;
bool full_name;
/* case 1 */
if (event_name[0] == '%') {
int nr = strtol(event_name+1, NULL, 0);
- if (nr > evlist->nr_entries)
+ if (nr > evlist->core.nr_entries)
return NULL;
evsel = perf_evlist__first(evlist);
@@ -2352,7 +2355,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
return evsel;
}
-static int __dynamic_dimension__add(struct perf_evsel *evsel,
+static int __dynamic_dimension__add(struct evsel *evsel,
struct tep_format_field *field,
bool raw_trace, int level)
{
@@ -2368,7 +2371,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
return 0;
}
-static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
+static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level)
{
int ret;
struct tep_format_field *field;
@@ -2384,14 +2387,14 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
return 0;
}
-static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
+static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace,
int level)
{
int ret;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
ret = add_evsel_fields(evsel, raw_trace, level);
@@ -2401,15 +2404,15 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
return 0;
}
-static int add_all_matching_fields(struct perf_evlist *evlist,
+static int add_all_matching_fields(struct evlist *evlist,
char *field_name, bool raw_trace, int level)
{
int ret = -ESRCH;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
field = tep_find_any_field(evsel->tp_format, field_name);
@@ -2423,11 +2426,11 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
return ret;
}
-static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
+static int add_dynamic_entry(struct evlist *evlist, const char *tok,
int level)
{
char *str, *event_name, *field_name, *opt_name;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
bool raw_trace = symbol_conf.raw_trace;
int ret = 0;
@@ -2470,7 +2473,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
goto out;
}
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
pr_debug("%s is not a tracepoint event\n", event_name);
ret = -EINVAL;
goto out;
@@ -2567,7 +2570,7 @@ int hpp_dimension__add_output(unsigned col)
}
int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int level)
{
unsigned int i;
@@ -2663,7 +2666,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
}
static int setup_sort_list(struct perf_hpp_list *list, char *str,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
char *tmp, *tok;
int ret = 0;
@@ -2709,7 +2712,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
return ret;
}
-static const char *get_default_sort_order(struct perf_evlist *evlist)
+static const char *get_default_sort_order(struct evlist *evlist)
{
const char *default_sort_orders[] = {
default_sort_order,
@@ -2720,7 +2723,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
default_tracepoint_sort_order,
};
bool use_trace = true;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
@@ -2728,7 +2731,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
goto out_no_evlist;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
use_trace = false;
break;
}
@@ -2743,7 +2746,7 @@ out_no_evlist:
return default_sort_orders[sort__mode];
}
-static int setup_sort_order(struct perf_evlist *evlist)
+static int setup_sort_order(struct evlist *evlist)
{
char *new_sort_order;
@@ -2804,7 +2807,7 @@ static char *setup_overhead(char *keys)
return keys;
}
-static int __setup_sorting(struct perf_evlist *evlist)
+static int __setup_sorting(struct evlist *evlist)
{
char *str;
const char *sort_keys;
@@ -3057,7 +3060,7 @@ out:
return ret;
}
-int setup_sorting(struct perf_evlist *evlist)
+int setup_sorting(struct evlist *evlist)
{
int err;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index a0f232151d6f..7b93f34ac1f4 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -1,29 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PERF_SORT_H
#define __PERF_SORT_H
-#include "../builtin.h"
-
#include <regex.h>
-
-#include "color.h"
+#include <stdbool.h>
#include <linux/list.h>
-#include "cache.h"
#include <linux/rbtree.h>
#include "map_symbol.h"
#include "symbol_conf.h"
-#include "string.h"
#include "callchain.h"
#include "values.h"
-
-#include "../perf.h"
-#include "debug.h"
-#include "header.h"
-
-#include <subcmd/parse-options.h>
-#include "parse-events.h"
#include "hist.h"
-#include "srcline.h"
+struct option;
struct thread;
extern regex_t parent_regex;
@@ -204,18 +192,6 @@ static inline float hist_entry__get_percent_limit(struct hist_entry *he)
return period * 100.0 / total_period;
}
-static inline u64 cl_address(u64 address)
-{
- /* return the cacheline of the address */
- return (address & ~(cacheline_size() - 1));
-}
-
-static inline u64 cl_offset(u64 address)
-{
- /* return the cacheline of the address */
- return (address & (cacheline_size() - 1));
-}
-
enum sort_mode {
SORT_MODE__NORMAL,
SORT_MODE__BRANCH,
@@ -301,9 +277,9 @@ struct block_hist {
extern struct sort_entry sort_thread;
extern struct list_head hist_entry__sort_list;
-struct perf_evlist;
+struct evlist;
struct tep_handle;
-int setup_sorting(struct perf_evlist *evlist);
+int setup_sorting(struct evlist *evlist);
int setup_output_field(void);
void reset_output_field(void);
void sort__setup_elide(FILE *fp);
@@ -318,7 +294,7 @@ bool is_strict_order(const char *order);
int hpp_dimension__add_output(unsigned col);
void reset_dimensions(void);
int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int level);
int output_field_add(struct perf_hpp_list *list, char *tok);
int64_t
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
index 58df6a0dbb9f..ed3b0ac2f785 100644
--- a/tools/perf/util/stat-display.c
+++ b/tools/perf/util/stat-display.c
@@ -1,9 +1,11 @@
+#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <linux/string.h>
#include <linux/time64.h>
#include <math.h>
#include "color.h"
+#include "counts.h"
#include "evlist.h"
#include "evsel.h"
#include "stat.h"
@@ -13,7 +15,6 @@
#include "string2.h"
#include <linux/ctype.h>
#include "cgroup.h"
-#include <math.h>
#include <api/fs/fs.h>
#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -45,7 +46,7 @@ static void print_noise_pct(struct perf_stat_config *config,
}
static void print_noise(struct perf_stat_config *config,
- struct perf_evsel *evsel, double avg)
+ struct evsel *evsel, double avg)
{
struct perf_stat_evsel *ps;
@@ -56,7 +57,7 @@ static void print_noise(struct perf_stat_config *config,
print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
}
-static void print_cgroup(struct perf_stat_config *config, struct perf_evsel *evsel)
+static void print_cgroup(struct perf_stat_config *config, struct evsel *evsel)
{
if (nr_cgroups) {
const char *cgrp_name = evsel->cgrp ? evsel->cgrp->name : "";
@@ -66,7 +67,7 @@ static void print_cgroup(struct perf_stat_config *config, struct perf_evsel *evs
static void aggr_printout(struct perf_stat_config *config,
- struct perf_evsel *evsel, int id, int nr)
+ struct evsel *evsel, int id, int nr)
{
switch (config->aggr_mode) {
case AGGR_CORE:
@@ -109,16 +110,16 @@ static void aggr_printout(struct perf_stat_config *config,
} else {
fprintf(config->output, "CPU%*d%s ",
config->csv_output ? 0 : -5,
- perf_evsel__cpus(evsel)->map[id],
+ evsel__cpus(evsel)->map[id],
config->csv_sep);
}
break;
case AGGR_THREAD:
fprintf(config->output, "%*s-%*d%s",
config->csv_output ? 0 : 16,
- thread_map__comm(evsel->threads, id),
+ perf_thread_map__comm(evsel->core.threads, id),
config->csv_output ? 0 : -8,
- thread_map__pid(evsel->threads, id),
+ perf_thread_map__pid(evsel->core.threads, id),
config->csv_sep);
break;
case AGGR_GLOBAL:
@@ -134,7 +135,7 @@ struct outstate {
const char *prefix;
int nfields;
int id, nr;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
};
#define METRIC_LEN 35
@@ -233,7 +234,7 @@ static bool valid_only_metric(const char *unit)
return true;
}
-static const char *fixunit(char *buf, struct perf_evsel *evsel,
+static const char *fixunit(char *buf, struct evsel *evsel,
const char *unit)
{
if (!strncmp(unit, "of all", 6)) {
@@ -310,9 +311,9 @@ static void print_metric_header(struct perf_stat_config *config,
}
static int first_shadow_cpu(struct perf_stat_config *config,
- struct perf_evsel *evsel, int id)
+ struct evsel *evsel, int id)
{
- struct perf_evlist *evlist = evsel->evlist;
+ struct evlist *evlist = evsel->evlist;
int i;
if (!config->aggr_get_id)
@@ -325,16 +326,16 @@ static int first_shadow_cpu(struct perf_stat_config *config,
return 0;
for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
- int cpu2 = perf_evsel__cpus(evsel)->map[i];
+ int cpu2 = evsel__cpus(evsel)->map[i];
- if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
+ if (config->aggr_get_id(config, evlist->core.cpus, cpu2) == id)
return cpu2;
}
return 0;
}
static void abs_printout(struct perf_stat_config *config,
- int id, int nr, struct perf_evsel *evsel, double avg)
+ int id, int nr, struct evsel *evsel, double avg)
{
FILE *output = config->output;
double sc = evsel->scale;
@@ -363,24 +364,24 @@ static void abs_printout(struct perf_stat_config *config,
print_cgroup(config, evsel);
}
-static bool is_mixed_hw_group(struct perf_evsel *counter)
+static bool is_mixed_hw_group(struct evsel *counter)
{
- struct perf_evlist *evlist = counter->evlist;
- u32 pmu_type = counter->attr.type;
- struct perf_evsel *pos;
+ struct evlist *evlist = counter->evlist;
+ u32 pmu_type = counter->core.attr.type;
+ struct evsel *pos;
- if (counter->nr_members < 2)
+ if (counter->core.nr_members < 2)
return false;
evlist__for_each_entry(evlist, pos) {
/* software events can be part of any hardware group */
- if (pos->attr.type == PERF_TYPE_SOFTWARE)
+ if (pos->core.attr.type == PERF_TYPE_SOFTWARE)
continue;
if (pmu_type == PERF_TYPE_SOFTWARE) {
- pmu_type = pos->attr.type;
+ pmu_type = pos->core.attr.type;
continue;
}
- if (pmu_type != pos->attr.type)
+ if (pmu_type != pos->core.attr.type)
return true;
}
@@ -388,7 +389,7 @@ static bool is_mixed_hw_group(struct perf_evsel *counter)
}
static void printout(struct perf_stat_config *config, int id, int nr,
- struct perf_evsel *counter, double uval,
+ struct evsel *counter, double uval,
char *prefix, u64 run, u64 ena, double noise,
struct runtime_stat *st)
{
@@ -489,18 +490,18 @@ static void printout(struct perf_stat_config *config, int id, int nr,
}
static void aggr_update_shadow(struct perf_stat_config *config,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
int cpu, s2, id, s;
u64 val;
- struct perf_evsel *counter;
+ struct evsel *counter;
for (s = 0; s < config->aggr_map->nr; s++) {
id = config->aggr_map->map[s];
evlist__for_each_entry(evlist, counter) {
val = 0;
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
- s2 = config->aggr_get_id(config, evlist->cpus, cpu);
+ s2 = config->aggr_get_id(config, evlist->core.cpus, cpu);
if (s2 != id)
continue;
val += perf_counts(counter->counts, cpu, 0)->val;
@@ -512,7 +513,7 @@ static void aggr_update_shadow(struct perf_stat_config *config,
}
}
-static void uniquify_event_name(struct perf_evsel *counter)
+static void uniquify_event_name(struct evsel *counter)
{
char *new_name;
char *config;
@@ -540,16 +541,16 @@ static void uniquify_event_name(struct perf_evsel *counter)
counter->uniquified_name = true;
}
-static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
- void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+static void collect_all_aliases(struct perf_stat_config *config, struct evsel *counter,
+ void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
bool first),
void *data)
{
- struct perf_evlist *evlist = counter->evlist;
- struct perf_evsel *alias;
+ struct evlist *evlist = counter->evlist;
+ struct evsel *alias;
- alias = list_prepare_entry(counter, &(evlist->entries), node);
- list_for_each_entry_continue (alias, &evlist->entries, node) {
+ alias = list_prepare_entry(counter, &(evlist->core.entries), core.node);
+ list_for_each_entry_continue (alias, &evlist->core.entries, core.node) {
if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
alias->scale != counter->scale ||
alias->cgrp != counter->cgrp ||
@@ -562,8 +563,8 @@ static void collect_all_aliases(struct perf_stat_config *config, struct perf_evs
}
}
-static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
- void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
+ void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
bool first),
void *data)
{
@@ -585,7 +586,7 @@ struct aggr_data {
};
static void aggr_cb(struct perf_stat_config *config,
- struct perf_evsel *counter, void *data, bool first)
+ struct evsel *counter, void *data, bool first)
{
struct aggr_data *ad = data;
int cpu, s2;
@@ -593,7 +594,7 @@ static void aggr_cb(struct perf_stat_config *config,
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
struct perf_counts_values *counts;
- s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
+ s2 = config->aggr_get_id(config, evsel__cpus(counter), cpu);
if (s2 != ad->id)
continue;
if (first)
@@ -616,7 +617,7 @@ static void aggr_cb(struct perf_stat_config *config,
}
static void print_counter_aggrdata(struct perf_stat_config *config,
- struct perf_evsel *counter, int s,
+ struct evsel *counter, int s,
char *prefix, bool metric_only,
bool *first)
{
@@ -651,12 +652,12 @@ static void print_counter_aggrdata(struct perf_stat_config *config,
}
static void print_aggr(struct perf_stat_config *config,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
char *prefix)
{
bool metric_only = config->metric_only;
FILE *output = config->output;
- struct perf_evsel *counter;
+ struct evsel *counter;
int s;
bool first;
@@ -691,7 +692,7 @@ static int cmp_val(const void *a, const void *b)
}
static struct perf_aggr_thread_value *sort_aggr_thread(
- struct perf_evsel *counter,
+ struct evsel *counter,
int nthreads, int ncpus,
int *ret,
struct target *_target)
@@ -741,11 +742,11 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
static void print_aggr_thread(struct perf_stat_config *config,
struct target *_target,
- struct perf_evsel *counter, char *prefix)
+ struct evsel *counter, char *prefix)
{
FILE *output = config->output;
- int nthreads = thread_map__nr(counter->threads);
- int ncpus = cpu_map__nr(counter->cpus);
+ int nthreads = perf_thread_map__nr(counter->core.threads);
+ int ncpus = perf_cpu_map__nr(counter->core.cpus);
int thread, sorted_threads, id;
struct perf_aggr_thread_value *buf;
@@ -779,7 +780,7 @@ struct caggr_data {
};
static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
- struct perf_evsel *counter, void *data,
+ struct evsel *counter, void *data,
bool first __maybe_unused)
{
struct caggr_data *cd = data;
@@ -795,7 +796,7 @@ static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
* aggregated counts in system-wide mode
*/
static void print_counter_aggr(struct perf_stat_config *config,
- struct perf_evsel *counter, char *prefix)
+ struct evsel *counter, char *prefix)
{
bool metric_only = config->metric_only;
FILE *output = config->output;
@@ -816,7 +817,7 @@ static void print_counter_aggr(struct perf_stat_config *config,
}
static void counter_cb(struct perf_stat_config *config __maybe_unused,
- struct perf_evsel *counter, void *data,
+ struct evsel *counter, void *data,
bool first __maybe_unused)
{
struct aggr_data *ad = data;
@@ -831,7 +832,7 @@ static void counter_cb(struct perf_stat_config *config __maybe_unused,
* does not use aggregated count in system-wide
*/
static void print_counter(struct perf_stat_config *config,
- struct perf_evsel *counter, char *prefix)
+ struct evsel *counter, char *prefix)
{
FILE *output = config->output;
u64 ena, run, val;
@@ -859,16 +860,16 @@ static void print_counter(struct perf_stat_config *config,
}
static void print_no_aggr_metric(struct perf_stat_config *config,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
char *prefix)
{
int cpu;
int nrcpus = 0;
- struct perf_evsel *counter;
+ struct evsel *counter;
u64 ena, run, val;
double uval;
- nrcpus = evlist->cpus->nr;
+ nrcpus = evlist->core.cpus->nr;
for (cpu = 0; cpu < nrcpus; cpu++) {
bool first = true;
@@ -910,11 +911,11 @@ static const char *aggr_header_csv[] = {
};
static void print_metric_headers(struct perf_stat_config *config,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
const char *prefix, bool no_indent)
{
struct perf_stat_output_ctx out;
- struct perf_evsel *counter;
+ struct evsel *counter;
struct outstate os = {
.fh = config->output
};
@@ -949,7 +950,7 @@ static void print_metric_headers(struct perf_stat_config *config,
}
static void print_interval(struct perf_stat_config *config,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
char *prefix, struct timespec *ts)
{
bool metric_only = config->metric_only;
@@ -1132,7 +1133,7 @@ static void print_footer(struct perf_stat_config *config)
}
static void print_percore(struct perf_stat_config *config,
- struct perf_evsel *counter, char *prefix)
+ struct evsel *counter, char *prefix)
{
bool metric_only = config->metric_only;
FILE *output = config->output;
@@ -1156,7 +1157,7 @@ static void print_percore(struct perf_stat_config *config,
}
void
-perf_evlist__print_counters(struct perf_evlist *evlist,
+perf_evlist__print_counters(struct evlist *evlist,
struct perf_stat_config *config,
struct target *_target,
struct timespec *ts,
@@ -1164,7 +1165,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
{
bool metric_only = config->metric_only;
int interval = config->interval;
- struct perf_evsel *counter;
+ struct evsel *counter;
char buf[64], *prefix = NULL;
if (interval)
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 656065af4971..70c87fdb2a43 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -25,12 +25,14 @@ struct stats walltime_nsecs_stats;
struct saved_value {
struct rb_node rb_node;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
enum stat_type type;
int ctx;
int cpu;
struct runtime_stat *stat;
struct stats stats;
+ u64 metric_total;
+ int metric_other;
};
static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
@@ -94,7 +96,7 @@ static void saved_value_delete(struct rblist *rblist __maybe_unused,
free(v);
}
-static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
+static struct saved_value *saved_value_lookup(struct evsel *evsel,
int cpu,
bool create,
enum stat_type type,
@@ -146,19 +148,19 @@ void perf_stat__init_shadow_stats(void)
runtime_stat__init(&rt_stat);
}
-static int evsel_context(struct perf_evsel *evsel)
+static int evsel_context(struct evsel *evsel)
{
int ctx = 0;
- if (evsel->attr.exclude_kernel)
+ if (evsel->core.attr.exclude_kernel)
ctx |= CTX_BIT_KERNEL;
- if (evsel->attr.exclude_user)
+ if (evsel->core.attr.exclude_user)
ctx |= CTX_BIT_USER;
- if (evsel->attr.exclude_hv)
+ if (evsel->core.attr.exclude_hv)
ctx |= CTX_BIT_HV;
- if (evsel->attr.exclude_host)
+ if (evsel->core.attr.exclude_host)
ctx |= CTX_BIT_HOST;
- if (evsel->attr.exclude_idle)
+ if (evsel->core.attr.exclude_idle)
ctx |= CTX_BIT_IDLE;
return ctx;
@@ -207,11 +209,12 @@ static void update_runtime_stat(struct runtime_stat *st,
* more semantic information such as miss/hit ratios,
* instruction rates, etc:
*/
-void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
+void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
int cpu, struct runtime_stat *st)
{
int ctx = evsel_context(counter);
u64 count_ns = count;
+ struct saved_value *v;
count *= counter->scale;
@@ -266,9 +269,15 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
update_runtime_stat(st, STAT_APERF, ctx, cpu, count);
if (counter->collect_stat) {
- struct saved_value *v = saved_value_lookup(counter, cpu, true,
- STAT_NONE, 0, st);
+ v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st);
update_stats(&v->stats, count);
+ if (counter->metric_leader)
+ v->metric_total += count;
+ } else if (counter->metric_leader) {
+ v = saved_value_lookup(counter->metric_leader,
+ cpu, true, STAT_NONE, 0, st);
+ v->metric_total += count;
+ v->metric_other++;
}
}
@@ -299,10 +308,10 @@ static const char *get_ratio_color(enum grc_type type, double ratio)
return color;
}
-static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list,
+static struct evsel *perf_stat__find_event(struct evlist *evsel_list,
const char *name)
{
- struct perf_evsel *c2;
+ struct evsel *c2;
evlist__for_each_entry (evsel_list, c2) {
if (!strcasecmp(c2->name, name) && !c2->collect_stat)
@@ -312,9 +321,9 @@ static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list,
}
/* Mark MetricExpr target events and link events using them to them. */
-void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list)
+void perf_stat__collect_metric_expr(struct evlist *evsel_list)
{
- struct perf_evsel *counter, *leader, **metric_events, *oc;
+ struct evsel *counter, *leader, **metric_events, *oc;
bool found;
const char **metric_names;
int i;
@@ -332,7 +341,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list)
&metric_names, &num_metric_names) < 0)
continue;
- metric_events = calloc(sizeof(struct perf_evsel *),
+ metric_events = calloc(sizeof(struct evsel *),
num_metric_names + 1);
if (!metric_events)
return;
@@ -415,7 +424,7 @@ static double runtime_stat_n(struct runtime_stat *st,
static void print_stalled_cycles_frontend(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel, double avg,
+ struct evsel *evsel, double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
{
@@ -439,7 +448,7 @@ static void print_stalled_cycles_frontend(struct perf_stat_config *config,
static void print_stalled_cycles_backend(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel, double avg,
+ struct evsel *evsel, double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
{
@@ -459,7 +468,7 @@ static void print_stalled_cycles_backend(struct perf_stat_config *config,
static void print_branch_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -480,7 +489,7 @@ static void print_branch_misses(struct perf_stat_config *config,
static void print_l1_dcache_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -502,7 +511,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config,
static void print_l1_icache_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -523,7 +532,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config,
static void print_dtlb_cache_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -543,7 +552,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config,
static void print_itlb_cache_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -563,7 +572,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config,
static void print_ll_cache_misses(struct perf_stat_config *config,
int cpu,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -686,7 +695,7 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
}
static void print_smi_cost(struct perf_stat_config *config,
- int cpu, struct perf_evsel *evsel,
+ int cpu, struct evsel *evsel,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
{
@@ -712,9 +721,10 @@ static void print_smi_cost(struct perf_stat_config *config,
static void generic_metric(struct perf_stat_config *config,
const char *metric_expr,
- struct perf_evsel **metric_events,
+ struct evsel **metric_events,
char *name,
const char *metric_name,
+ const char *metric_unit,
double avg,
int cpu,
struct perf_stat_output_ctx *out,
@@ -722,17 +732,16 @@ static void generic_metric(struct perf_stat_config *config,
{
print_metric_t print_metric = out->print_metric;
struct parse_ctx pctx;
- double ratio;
+ double ratio, scale;
int i;
void *ctxp = out->ctx;
char *n, *pn;
expr__ctx_init(&pctx);
- expr__add_id(&pctx, name, avg);
for (i = 0; metric_events[i]; i++) {
struct saved_value *v;
struct stats *stats;
- double scale;
+ u64 metric_total = 0;
if (!strcmp(metric_events[i]->name, "duration_time")) {
stats = &walltime_nsecs_stats;
@@ -744,6 +753,9 @@ static void generic_metric(struct perf_stat_config *config,
break;
stats = &v->stats;
scale = 1.0;
+
+ if (v->metric_other)
+ metric_total = v->metric_total;
}
n = strdup(metric_events[i]->name);
@@ -757,21 +769,44 @@ static void generic_metric(struct perf_stat_config *config,
pn = strchr(n, ' ');
if (pn)
*pn = 0;
- expr__add_id(&pctx, n, avg_stats(stats)*scale);
+
+ if (metric_total)
+ expr__add_id(&pctx, n, metric_total);
+ else
+ expr__add_id(&pctx, n, avg_stats(stats)*scale);
}
+
+ expr__add_id(&pctx, name, avg);
+
if (!metric_events[i]) {
const char *p = metric_expr;
- if (expr__parse(&ratio, &pctx, &p) == 0)
- print_metric(config, ctxp, NULL, "%8.1f",
- metric_name ?
- metric_name :
- out->force_header ? name : "",
- ratio);
- else
+ if (expr__parse(&ratio, &pctx, &p) == 0) {
+ char *unit;
+ char metric_bf[64];
+
+ if (metric_unit && metric_name) {
+ if (perf_pmu__convert_scale(metric_unit,
+ &unit, &scale) >= 0) {
+ ratio *= scale;
+ }
+
+ scnprintf(metric_bf, sizeof(metric_bf),
+ "%s %s", unit, metric_name);
+ print_metric(config, ctxp, NULL, "%8.1f",
+ metric_bf, ratio);
+ } else {
+ print_metric(config, ctxp, NULL, "%8.1f",
+ metric_name ?
+ metric_name :
+ out->force_header ? name : "",
+ ratio);
+ }
+ } else {
print_metric(config, ctxp, NULL, NULL,
out->force_header ?
(metric_name ? metric_name : name) : "", 0);
+ }
} else
print_metric(config, ctxp, NULL, NULL, "", 0);
@@ -780,7 +815,7 @@ static void generic_metric(struct perf_stat_config *config,
}
void perf_stat__print_shadow_stats(struct perf_stat_config *config,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg, int cpu,
struct perf_stat_output_ctx *out,
struct rblist *metric_events,
@@ -819,7 +854,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
"stalled cycles per insn",
ratio);
} else if (have_frontend_stalled) {
- print_metric(config, ctxp, NULL, NULL,
+ out->new_line(config, ctxp);
+ print_metric(config, ctxp, NULL, "%7.2f ",
"stalled cycles per insn", 0);
}
} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
@@ -828,8 +864,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
else
print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
} else if (
- evsel->attr.type == PERF_TYPE_HW_CACHE &&
- evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
+ evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
+ evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1D |
((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
@@ -838,8 +874,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
else
print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
} else if (
- evsel->attr.type == PERF_TYPE_HW_CACHE &&
- evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
+ evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
+ evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1I |
((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
@@ -848,8 +884,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
else
print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
} else if (
- evsel->attr.type == PERF_TYPE_HW_CACHE &&
- evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
+ evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
+ evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
@@ -858,8 +894,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
else
print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
} else if (
- evsel->attr.type == PERF_TYPE_HW_CACHE &&
- evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
+ evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
+ evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
@@ -868,8 +904,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
else
print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
} else if (
- evsel->attr.type == PERF_TYPE_HW_CACHE &&
- evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
+ evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
+ evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_LL |
((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
@@ -991,7 +1027,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
print_metric(config, ctxp, NULL, NULL, name, 0);
} else if (evsel->metric_expr) {
generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
- evsel->metric_name, avg, cpu, out, st);
+ evsel->metric_name, NULL, avg, cpu, out, st);
} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
char unit = 'M';
char unit_buf[10];
@@ -1020,7 +1056,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
out->new_line(config, ctxp);
generic_metric(config, mexp->metric_expr, mexp->metric_events,
evsel->name, mexp->metric_name,
- avg, cpu, out, st);
+ mexp->metric_unit, avg, cpu, out, st);
}
}
if (num == 0)
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index db8a6cf336be..8f1ea27f976f 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -2,7 +2,13 @@
#include <errno.h>
#include <inttypes.h>
#include <math.h>
+#include <string.h>
+#include "counts.h"
+#include "debug.h"
+#include "header.h"
#include "stat.h"
+#include "session.h"
+#include "target.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
@@ -68,7 +74,7 @@ double rel_stddev_stats(double stddev, double avg)
return pct;
}
-bool __perf_evsel_stat__is(struct perf_evsel *evsel,
+bool __perf_evsel_stat__is(struct evsel *evsel,
enum perf_stat_evsel_id id)
{
struct perf_stat_evsel *ps = evsel->stats;
@@ -93,7 +99,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
};
#undef ID
-static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
+static void perf_stat_evsel_id_init(struct evsel *evsel)
{
struct perf_stat_evsel *ps = evsel->stats;
int i;
@@ -108,7 +114,7 @@ static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
}
}
-static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
+static void perf_evsel__reset_stat_priv(struct evsel *evsel)
{
int i;
struct perf_stat_evsel *ps = evsel->stats;
@@ -119,7 +125,7 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
perf_stat_evsel_id_init(evsel);
}
-static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
+static int perf_evsel__alloc_stat_priv(struct evsel *evsel)
{
evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
if (evsel->stats == NULL)
@@ -128,7 +134,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
return 0;
}
-static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
+static void perf_evsel__free_stat_priv(struct evsel *evsel)
{
struct perf_stat_evsel *ps = evsel->stats;
@@ -137,7 +143,7 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
zfree(&evsel->stats);
}
-static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+static int perf_evsel__alloc_prev_raw_counts(struct evsel *evsel,
int ncpus, int nthreads)
{
struct perf_counts *counts;
@@ -149,16 +155,16 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
return counts ? 0 : -ENOMEM;
}
-static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
+static void perf_evsel__free_prev_raw_counts(struct evsel *evsel)
{
perf_counts__delete(evsel->prev_raw_counts);
evsel->prev_raw_counts = NULL;
}
-static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
+static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw)
{
int ncpus = perf_evsel__nr_cpus(evsel);
- int nthreads = thread_map__nr(evsel->threads);
+ int nthreads = perf_thread_map__nr(evsel->core.threads);
if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
@@ -168,9 +174,9 @@ static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
return 0;
}
-int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
+int perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (perf_evsel__alloc_stats(evsel, alloc_raw))
@@ -184,9 +190,9 @@ out_free:
return -1;
}
-void perf_evlist__free_stats(struct perf_evlist *evlist)
+void perf_evlist__free_stats(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
perf_evsel__free_stat_priv(evsel);
@@ -195,9 +201,9 @@ void perf_evlist__free_stats(struct perf_evlist *evlist)
}
}
-void perf_evlist__reset_stats(struct perf_evlist *evlist)
+void perf_evlist__reset_stats(struct evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
perf_evsel__reset_stat_priv(evsel);
@@ -205,17 +211,17 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist)
}
}
-static void zero_per_pkg(struct perf_evsel *counter)
+static void zero_per_pkg(struct evsel *counter)
{
if (counter->per_pkg_mask)
- memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
+ memset(counter->per_pkg_mask, 0, cpu__max_cpu());
}
-static int check_per_pkg(struct perf_evsel *counter,
+static int check_per_pkg(struct evsel *counter,
struct perf_counts_values *vals, int cpu, bool *skip)
{
unsigned long *mask = counter->per_pkg_mask;
- struct cpu_map *cpus = perf_evsel__cpus(counter);
+ struct perf_cpu_map *cpus = evsel__cpus(counter);
int s;
*skip = false;
@@ -223,11 +229,11 @@ static int check_per_pkg(struct perf_evsel *counter,
if (!counter->per_pkg)
return 0;
- if (cpu_map__empty(cpus))
+ if (perf_cpu_map__empty(cpus))
return 0;
if (!mask) {
- mask = zalloc(MAX_NR_CPUS);
+ mask = zalloc(cpu__max_cpu());
if (!mask)
return -ENOMEM;
@@ -254,7 +260,7 @@ static int check_per_pkg(struct perf_evsel *counter,
}
static int
-process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
+process_counter_values(struct perf_stat_config *config, struct evsel *evsel,
int cpu, int thread,
struct perf_counts_values *count)
{
@@ -306,9 +312,9 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
}
static int process_counter_maps(struct perf_stat_config *config,
- struct perf_evsel *counter)
+ struct evsel *counter)
{
- int nthreads = thread_map__nr(counter->threads);
+ int nthreads = perf_thread_map__nr(counter->core.threads);
int ncpus = perf_evsel__nr_cpus(counter);
int cpu, thread;
@@ -327,7 +333,7 @@ static int process_counter_maps(struct perf_stat_config *config,
}
int perf_stat_process_counter(struct perf_stat_config *config,
- struct perf_evsel *counter)
+ struct evsel *counter)
{
struct perf_counts_values *aggr = &counter->counts->aggr;
struct perf_stat_evsel *ps = counter->stats;
@@ -380,8 +386,8 @@ int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event)
{
struct perf_counts_values count;
- struct stat_event *st = &event->stat;
- struct perf_evsel *counter;
+ struct perf_record_stat *st = &event->stat;
+ struct evsel *counter;
count.val = st->val;
count.ena = st->ena;
@@ -400,12 +406,12 @@ int perf_event__process_stat_event(struct perf_session *session,
size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
{
- struct stat_event *st = (struct stat_event *) event;
+ struct perf_record_stat *st = (struct perf_record_stat *)event;
size_t ret;
- ret = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
+ ret = fprintf(fp, "\n... id %" PRI_lu64 ", cpu %d, thread %d\n",
st->id, st->cpu, st->thread);
- ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
+ ret += fprintf(fp, "... value %" PRI_lu64 ", enabled %" PRI_lu64 ", running %" PRI_lu64 "\n",
st->val, st->ena, st->run);
return ret;
@@ -413,10 +419,10 @@ size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
{
- struct stat_round_event *rd = (struct stat_round_event *)event;
+ struct perf_record_stat_round *rd = (struct perf_record_stat_round *)event;
size_t ret;
- ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
+ ret = fprintf(fp, "\n... time %" PRI_lu64 ", type %s\n", rd->time,
rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
return ret;
@@ -437,12 +443,12 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
return ret;
}
-int create_perf_stat_counter(struct perf_evsel *evsel,
+int create_perf_stat_counter(struct evsel *evsel,
struct perf_stat_config *config,
struct target *target)
{
- struct perf_event_attr *attr = &evsel->attr;
- struct perf_evsel *leader = evsel->leader;
+ struct perf_event_attr *attr = &evsel->core.attr;
+ struct evsel *leader = evsel->leader;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
@@ -452,7 +458,7 @@ int create_perf_stat_counter(struct perf_evsel *evsel,
* the group read (for leader) and ID retrieval for all
* members.
*/
- if (leader->nr_members > 1)
+ if (leader->core.nr_members > 1)
attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
attr->inherit = !config->no_inherit;
@@ -483,14 +489,14 @@ int create_perf_stat_counter(struct perf_evsel *evsel,
}
if (target__has_cpu(target) && !target__has_per_thread(target))
- return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
+ return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel));
- return perf_evsel__open_per_thread(evsel, evsel->threads);
+ return perf_evsel__open_per_thread(evsel, evsel->core.threads);
}
int perf_stat_synthesize_config(struct perf_stat_config *config,
struct perf_tool *tool,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process,
bool attrs)
{
@@ -507,14 +513,14 @@ int perf_stat_synthesize_config(struct perf_stat_config *config,
err = perf_event__synthesize_extra_attr(tool, evlist, process,
attrs);
- err = perf_event__synthesize_thread_map2(tool, evlist->threads,
+ err = perf_event__synthesize_thread_map2(tool, evlist->core.threads,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
return err;
}
- err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
+ err = perf_event__synthesize_cpu_map(tool, evlist->core.cpus,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 7032dd1eeac2..14fe3e548229 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -5,14 +5,12 @@
#include <linux/types.h>
#include <stdio.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/resource.h>
-#include <sys/wait.h>
-#include "xyarray.h"
#include "rblist.h"
-#include "perf.h"
#include "event.h"
+struct timespec;
+
struct stats {
double n, mean, M2;
u64 max, min;
@@ -92,7 +90,7 @@ struct runtime_stat {
};
typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
- struct cpu_map *m, int cpu);
+ struct perf_cpu_map *m, int cpu);
struct perf_stat_config {
enum aggr_mode aggr_mode;
@@ -122,9 +120,9 @@ struct perf_stat_config {
const char *csv_sep;
struct stats *walltime_nsecs_stats;
struct rusage ru_data;
- struct cpu_map *aggr_map;
+ struct perf_cpu_map *aggr_map;
aggr_get_id_t aggr_get_id;
- struct cpu_map *cpus_aggr_map;
+ struct perf_cpu_map *cpus_aggr_map;
u64 *walltime_run;
struct rblist metric_events;
};
@@ -143,11 +141,11 @@ static inline void init_stats(struct stats *stats)
stats->max = 0;
}
-struct perf_evsel;
-struct perf_evlist;
+struct evsel;
+struct evlist;
struct perf_aggr_thread_value {
- struct perf_evsel *counter;
+ struct evsel *counter;
int id;
double uval;
u64 val;
@@ -155,7 +153,7 @@ struct perf_aggr_thread_value {
u64 ena;
};
-bool __perf_evsel_stat__is(struct perf_evsel *evsel,
+bool __perf_evsel_stat__is(struct evsel *evsel,
enum perf_stat_evsel_id id);
#define perf_stat_evsel__is(evsel, id) \
@@ -174,7 +172,7 @@ void runtime_stat__exit(struct runtime_stat *st);
void perf_stat__init_shadow_stats(void);
void perf_stat__reset_shadow_stats(void);
void perf_stat__reset_shadow_per_stat(struct runtime_stat *st);
-void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
+void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
int cpu, struct runtime_stat *st);
struct perf_stat_output_ctx {
void *ctx;
@@ -184,22 +182,24 @@ struct perf_stat_output_ctx {
};
void perf_stat__print_shadow_stats(struct perf_stat_config *config,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
double avg, int cpu,
struct perf_stat_output_ctx *out,
struct rblist *metric_events,
struct runtime_stat *st);
-void perf_stat__collect_metric_expr(struct perf_evlist *);
+void perf_stat__collect_metric_expr(struct evlist *);
-int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
-void perf_evlist__free_stats(struct perf_evlist *evlist);
-void perf_evlist__reset_stats(struct perf_evlist *evlist);
+int perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw);
+void perf_evlist__free_stats(struct evlist *evlist);
+void perf_evlist__reset_stats(struct evlist *evlist);
int perf_stat_process_counter(struct perf_stat_config *config,
- struct perf_evsel *counter);
+ struct evsel *counter);
struct perf_tool;
union perf_event;
struct perf_session;
+struct target;
+
int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event);
@@ -207,16 +207,16 @@ size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
-int create_perf_stat_counter(struct perf_evsel *evsel,
+int create_perf_stat_counter(struct evsel *evsel,
struct perf_stat_config *config,
struct target *target);
int perf_stat_synthesize_config(struct perf_stat_config *config,
struct perf_tool *tool,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
perf_event__handler_t process,
bool attrs);
void
-perf_evlist__print_counters(struct perf_evlist *evlist,
+perf_evlist__print_counters(struct evlist *evlist,
struct perf_stat_config *config,
struct target *_target,
struct timespec *ts,
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 2ce0dc887364..a64a37628f12 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,9 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
+#include "cache.h"
#include "debug.h"
+#include "strbuf.h"
#include <linux/kernel.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include <errno.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
/*
* Used as the default ->buf value, so that people can always assume
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 76cc54000483..582f4a69cd48 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -14,10 +14,12 @@
#include <unistd.h>
#include <string.h>
#include <linux/bitmap.h>
+#include <linux/string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
+#include <perf/cpumap.h>
-#include "perf.h"
+#include "env.h"
#include "svghelper.h"
#include "cpumap.h"
@@ -694,7 +696,8 @@ struct topology {
int sib_thr_nr;
};
-static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos)
+static void scan_thread_topology(int *map, struct topology *t, int cpu,
+ int *pos, int nr_cpus)
{
int i;
int thr;
@@ -703,41 +706,37 @@ static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos
if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
continue;
- for_each_set_bit(thr,
- cpumask_bits(&t->sib_thr[i]),
- MAX_NR_CPUS)
+ for_each_set_bit(thr, cpumask_bits(&t->sib_thr[i]), nr_cpus)
if (map[thr] == -1)
map[thr] = (*pos)++;
}
}
-static void scan_core_topology(int *map, struct topology *t)
+static void scan_core_topology(int *map, struct topology *t, int nr_cpus)
{
int pos = 0;
int i;
int cpu;
for (i = 0; i < t->sib_core_nr; i++)
- for_each_set_bit(cpu,
- cpumask_bits(&t->sib_core[i]),
- MAX_NR_CPUS)
- scan_thread_topology(map, t, cpu, &pos);
+ for_each_set_bit(cpu, cpumask_bits(&t->sib_core[i]), nr_cpus)
+ scan_thread_topology(map, t, cpu, &pos, nr_cpus);
}
-static int str_to_bitmap(char *s, cpumask_t *b)
+static int str_to_bitmap(char *s, cpumask_t *b, int nr_cpus)
{
int i;
int ret = 0;
- struct cpu_map *m;
+ struct perf_cpu_map *m;
int c;
- m = cpu_map__new(s);
+ m = perf_cpu_map__new(s);
if (!m)
return -1;
for (i = 0; i < m->nr; i++) {
c = m->map[i];
- if (c >= MAX_NR_CPUS) {
+ if (c >= nr_cpus) {
ret = -1;
break;
}
@@ -745,29 +744,34 @@ static int str_to_bitmap(char *s, cpumask_t *b)
set_bit(c, cpumask_bits(b));
}
- cpu_map__put(m);
+ perf_cpu_map__put(m);
return ret;
}
-int svg_build_topology_map(char *sib_core, int sib_core_nr,
- char *sib_thr, int sib_thr_nr)
+int svg_build_topology_map(struct perf_env *env)
{
- int i;
+ int i, nr_cpus;
struct topology t;
+ char *sib_core, *sib_thr;
+
+ nr_cpus = min(env->nr_cpus_online, MAX_NR_CPUS);
+
+ t.sib_core_nr = env->nr_sibling_cores;
+ t.sib_thr_nr = env->nr_sibling_threads;
+ t.sib_core = calloc(env->nr_sibling_cores, sizeof(cpumask_t));
+ t.sib_thr = calloc(env->nr_sibling_threads, sizeof(cpumask_t));
- t.sib_core_nr = sib_core_nr;
- t.sib_thr_nr = sib_thr_nr;
- t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t));
- t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t));
+ sib_core = env->sibling_cores;
+ sib_thr = env->sibling_threads;
if (!t.sib_core || !t.sib_thr) {
fprintf(stderr, "topology: no memory\n");
goto exit;
}
- for (i = 0; i < sib_core_nr; i++) {
- if (str_to_bitmap(sib_core, &t.sib_core[i])) {
+ for (i = 0; i < env->nr_sibling_cores; i++) {
+ if (str_to_bitmap(sib_core, &t.sib_core[i], nr_cpus)) {
fprintf(stderr, "topology: can't parse siblings map\n");
goto exit;
}
@@ -775,8 +779,8 @@ int svg_build_topology_map(char *sib_core, int sib_core_nr,
sib_core += strlen(sib_core) + 1;
}
- for (i = 0; i < sib_thr_nr; i++) {
- if (str_to_bitmap(sib_thr, &t.sib_thr[i])) {
+ for (i = 0; i < env->nr_sibling_threads; i++) {
+ if (str_to_bitmap(sib_thr, &t.sib_thr[i], nr_cpus)) {
fprintf(stderr, "topology: can't parse siblings map\n");
goto exit;
}
@@ -784,16 +788,16 @@ int svg_build_topology_map(char *sib_core, int sib_core_nr,
sib_thr += strlen(sib_thr) + 1;
}
- topology_map = malloc(sizeof(int) * MAX_NR_CPUS);
+ topology_map = malloc(sizeof(int) * nr_cpus);
if (!topology_map) {
fprintf(stderr, "topology: no memory\n");
goto exit;
}
- for (i = 0; i < MAX_NR_CPUS; i++)
+ for (i = 0; i < nr_cpus; i++)
topology_map[i] = -1;
- scan_core_topology(topology_map, &t);
+ scan_core_topology(topology_map, &t, nr_cpus);
return 0;
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index e55338d5c3bd..81823e8bae3e 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -4,6 +4,8 @@
#include <linux/types.h>
+struct perf_env;
+
void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
void svg_ubox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges);
void svg_lbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges);
@@ -28,7 +30,7 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
void svg_interrupt(u64 start, int row, const char *backtrace);
void svg_text(int Yslot, u64 start, const char *text);
void svg_close(void);
-int svg_build_topology_map(char *sib_core, int sib_core_nr, char *sib_thr, int sib_thr_nr);
+int svg_build_topology_map(struct perf_env *env);
extern int svg_page_width;
extern u64 svg_highlight;
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 7d504dc22108..9428639872a6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -10,6 +10,7 @@
#include "map.h"
#include "map_groups.h"
#include "symbol.h"
+#include "symsrc.h"
#include "demangle-java.h"
#include "demangle-rust.h"
#include "machine.h"
@@ -40,6 +41,12 @@
typedef Elf64_Nhdr GElf_Nhdr;
+#ifndef DMGL_PARAMS
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+#endif
+
#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
extern char *cplus_demangle(const char *, int);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 3bc8b7e3300e..7e2813ec9498 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+#include "dso.h"
#include "symbol.h"
+#include "symsrc.h"
#include "util.h"
#include <errno.h>
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 173f3378aaa0..765c75df2904 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -4,8 +4,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/mman.h>
+#include <linux/string.h>
#include <linux/time64.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -15,11 +17,17 @@
#include <inttypes.h>
#include "annotate.h"
#include "build-id.h"
+#include "cap.h"
+#include "dso.h"
#include "util.h"
#include "debug.h"
+#include "event.h"
#include "machine.h"
#include "map.h"
#include "symbol.h"
+#include "map_symbol.h"
+#include "mem-events.h"
+#include "symsrc.h"
#include "strlist.h"
#include "intlist.h"
#include "namespaces.h"
@@ -92,6 +100,11 @@ static int prefix_underscores_count(const char *str)
return tail - str;
}
+void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+ p->end = c->start;
+}
+
const char * __weak arch__normalize_symbol_name(const char *name)
{
return name;
@@ -218,7 +231,7 @@ void symbols__fixup_end(struct rb_root_cached *symbols)
curr = rb_entry(nd, struct symbol, rb_node);
if (prev->end == prev->start && prev->end != curr->start)
- prev->end = curr->start;
+ arch__symbols__fixup_end(prev, curr);
}
/* Last entry */
@@ -2190,13 +2203,19 @@ static bool symbol__read_kptr_restrict(void)
char line[8];
if (fgets(line, sizeof(line), fp) != NULL)
- value = ((geteuid() != 0) || (getuid() != 0)) ?
- (atoi(line) != 0) :
- (atoi(line) == 2);
+ value = perf_cap__capable(CAP_SYSLOG) ?
+ (atoi(line) >= 2) :
+ (atoi(line) != 0);
fclose(fp);
}
+ /* Per kernel/kallsyms.c:
+ * we also restrict when perf_event_paranoid > 1 w/o CAP_SYSLOG
+ */
+ if (perf_event_paranoid() > 1 && !perf_cap__capable(CAP_SYSLOG))
+ value = true;
+
return value;
}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 12755b42ea93..0b0c6b5b1899 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -3,13 +3,12 @@
#define __PERF_SYMBOL 1
#include <linux/types.h>
+#include <linux/refcount.h>
#include <stdbool.h>
#include <stdint.h>
#include <linux/list.h>
#include <linux/rbtree.h>
#include <stdio.h>
-#include "map_symbol.h"
-#include "branch.h"
#include "path.h"
#include "symbol_conf.h"
@@ -19,8 +18,7 @@
#endif
#include <elf.h>
-#include "dso.h"
-
+struct dso;
struct map;
struct map_groups;
struct option;
@@ -40,15 +38,6 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
GElf_Shdr *shp, const char *name, size_t *idx);
#endif
-#ifndef DMGL_PARAMS
-#define DMGL_NO_OPTS 0 /* For readability... */
-#define DMGL_PARAMS (1 << 0) /* Include function args */
-#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
-#endif
-
-#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"
-#define DSO__NAME_KCORE "[kernel.kcore]"
-
/** struct symbol - symtab entry
*
* @ignore - resolvable but tools ignore it (e.g. idle routines)
@@ -116,21 +105,6 @@ struct ref_reloc_sym {
u64 unrelocated_addr;
};
-struct branch_info {
- struct addr_map_symbol from;
- struct addr_map_symbol to;
- struct branch_flags flags;
- char *srcline_from;
- char *srcline_to;
-};
-
-struct mem_info {
- struct addr_map_symbol iaddr;
- struct addr_map_symbol daddr;
- union perf_mem_data_src data_src;
- refcount_t refcnt;
-};
-
struct block_info {
struct symbol *sym;
u64 start;
@@ -156,37 +130,6 @@ struct addr_location {
s32 socket;
};
-struct symsrc {
- char *name;
- int fd;
- enum dso_binary_type type;
-
-#ifdef HAVE_LIBELF_SUPPORT
- Elf *elf;
- GElf_Ehdr ehdr;
-
- Elf_Scn *opdsec;
- size_t opdidx;
- GElf_Shdr opdshdr;
-
- Elf_Scn *symtab;
- GElf_Shdr symshdr;
-
- Elf_Scn *dynsym;
- size_t dynsym_idx;
- GElf_Shdr dynshdr;
-
- bool adjust_symbols;
- bool is_64_bit;
-#endif
-};
-
-void symsrc__destroy(struct symsrc *ss);
-int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
- enum dso_binary_type type);
-bool symsrc__has_symtab(struct symsrc *ss);
-bool symsrc__possibly_runtime(struct symsrc *ss);
-
int dso__load(struct dso *dso, struct map *map);
int dso__load_vmlinux(struct dso *dso, struct map *map,
const char *vmlinux, bool vmlinux_allocated);
@@ -240,6 +183,8 @@ bool symbol__restricted_filename(const char *filename,
int symbol__config_symfs(const struct option *opt __maybe_unused,
const char *dir, int unset __maybe_unused);
+struct symsrc;
+
int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
struct symsrc *runtime_ss, int kmodule);
int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss);
@@ -288,6 +233,7 @@ const char *arch__normalize_symbol_name(const char *name);
#define SYMBOL_A 0
#define SYMBOL_B 1
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c);
int arch__compare_symbol_names(const char *namea, const char *nameb);
int arch__compare_symbol_names_n(const char *namea, const char *nameb,
unsigned int n);
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index 02e89b02c2ce..35c936ce33ef 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <stdio.h>
+#include "dso.h"
#include "map.h"
#include "symbol.h"
diff --git a/tools/perf/util/symsrc.h b/tools/perf/util/symsrc.h
new file mode 100644
index 000000000000..2665b4bde751
--- /dev/null
+++ b/tools/perf/util/symsrc.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_SYMSRC_
+#define __PERF_SYMSRC_ 1
+
+#include <stdbool.h>
+#include <stddef.h>
+#include "dso.h"
+
+#ifdef HAVE_LIBELF_SUPPORT
+#include <libelf.h>
+#include <gelf.h>
+#endif
+#include <elf.h>
+
+struct symsrc {
+ char *name;
+ int fd;
+ enum dso_binary_type type;
+
+#ifdef HAVE_LIBELF_SUPPORT
+ Elf *elf;
+ GElf_Ehdr ehdr;
+
+ Elf_Scn *opdsec;
+ size_t opdidx;
+ GElf_Shdr opdshdr;
+
+ Elf_Scn *symtab;
+ GElf_Shdr symshdr;
+
+ Elf_Scn *dynsym;
+ size_t dynsym_idx;
+ GElf_Shdr dynshdr;
+
+ bool adjust_symbols;
+ bool is_64_bit;
+#endif
+};
+
+int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, enum dso_binary_type type);
+void symsrc__destroy(struct symsrc *ss);
+
+bool symsrc__has_symtab(struct symsrc *ss);
+bool symsrc__possibly_runtime(struct symsrc *ss);
+
+#endif /* __PERF_SYMSRC_ */
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 022a9c670338..820fceeb19a9 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -79,6 +79,7 @@ static int syscalltbl__init_native(struct syscalltbl *tbl)
qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
tbl->syscalls.nr_entries = nr_entries;
+ tbl->syscalls.max_id = syscalltbl_native_max_id;
return 0;
}
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index c8e7e9ce0f01..9172613028d0 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -6,6 +6,7 @@ struct syscalltbl {
union {
int audit_machine;
struct {
+ int max_id;
int nr_entries;
void *entries;
} syscalls;
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 3adc65480349..565f7aef7e6c 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -10,8 +10,11 @@
#include "debug.h"
#include <pwd.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
enum target_errno target__validate(struct target *target)
{
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 15134ac9b8f1..cd8a948d03ec 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -10,6 +10,7 @@
#include <linux/zalloc.h>
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include "thread.h"
#include "event.h"
#include "machine.h"
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 873ab505ca80..b64e9e049636 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../perf.h"
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/kernel.h>
#include <linux/zalloc.h>
+#include "dso.h"
#include "session.h"
#include "thread.h"
#include "thread-stack.h"
@@ -105,7 +105,6 @@ void thread__delete(struct thread *thread)
}
up_write(&thread->comm_lock);
- unwind__finish_access(thread);
nsinfo__zput(thread->nsinfo);
srccode_state_free(&thread->srccode_state);
@@ -170,7 +169,7 @@ struct namespaces *thread__namespaces(struct thread *thread)
}
static int __thread__set_namespaces(struct thread *thread, u64 timestamp,
- struct namespaces_event *event)
+ struct perf_record_namespaces *event)
{
struct namespaces *new, *curr = __thread__namespaces(thread);
@@ -194,7 +193,7 @@ static int __thread__set_namespaces(struct thread *thread, u64 timestamp,
}
int thread__set_namespaces(struct thread *thread, u64 timestamp,
- struct namespaces_event *event)
+ struct perf_record_namespaces *event)
{
int ret;
@@ -214,14 +213,24 @@ struct comm *thread__comm(const struct thread *thread)
struct comm *thread__exec_comm(const struct thread *thread)
{
- struct comm *comm, *last = NULL;
+ struct comm *comm, *last = NULL, *second_last = NULL;
list_for_each_entry(comm, &thread->comm_list, list) {
if (comm->exec)
return comm;
+ second_last = last;
last = comm;
}
+ /*
+ * 'last' with no start time might be the parent's comm of a synthesized
+ * thread (created by processing a synthesized fork event). For a main
+ * thread, that is very probably wrong. Prefer a later comm to avoid
+ * that case.
+ */
+ if (second_last && !last->start && thread->pid_ == thread->tid)
+ return second_last;
+
return last;
}
@@ -242,7 +251,7 @@ static int ____thread__set_comm(struct thread *thread, const char *str,
list_add(&new->list, &thread->comm_list);
if (exec)
- unwind__flush_access(thread);
+ unwind__flush_access(thread->mg);
}
thread->comm_set = true;
@@ -322,7 +331,7 @@ int thread__insert_map(struct thread *thread, struct map *map)
{
int ret;
- ret = unwind__prepare_access(thread, map, NULL);
+ ret = unwind__prepare_access(thread->mg, map, NULL);
if (ret)
return ret;
@@ -342,7 +351,7 @@ static int __thread__prepare_access(struct thread *thread)
down_read(&maps->lock);
for (map = maps__first(maps); map; map = map__next(map)) {
- err = unwind__prepare_access(thread, map, &initialized);
+ err = unwind__prepare_access(thread->mg, map, &initialized);
if (err || initialized)
break;
}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e97ef6977eb9..51bdb9a7af7f 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -16,7 +16,7 @@
struct addr_location;
struct map;
-struct namespaces_event;
+struct perf_record_namespaces;
struct thread_stack;
struct unwind_libunwind_ops;
@@ -44,10 +44,6 @@ struct thread {
struct thread_stack *ts;
struct nsinfo *nsinfo;
struct srccode_state srccode_state;
-#ifdef HAVE_LIBUNWIND_SUPPORT
- void *addr_space;
- struct unwind_libunwind_ops *unwind_libunwind_ops;
-#endif
bool filter;
int filter_entry_depth;
};
@@ -78,7 +74,7 @@ static inline void thread__exited(struct thread *thread)
struct namespaces *thread__namespaces(struct thread *thread);
int thread__set_namespaces(struct thread *thread, u64 timestamp,
- struct namespaces_event *event);
+ struct perf_record_namespaces *event);
int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
bool exec);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 5b3511f2b6b1..c9bfe4696943 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -28,34 +28,11 @@ static int filter(const struct dirent *dir)
return 1;
}
-static void thread_map__reset(struct thread_map *map, int start, int nr)
-{
- size_t size = (nr - start) * sizeof(map->map[0]);
-
- memset(&map->map[start], 0, size);
- map->err_thread = -1;
-}
+#define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr)
-static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
+struct perf_thread_map *thread_map__new_by_pid(pid_t pid)
{
- size_t size = sizeof(*map) + sizeof(map->map[0]) * nr;
- int start = map ? map->nr : 0;
-
- map = realloc(map, size);
- /*
- * We only realloc to add more items, let's reset new items.
- */
- if (map)
- thread_map__reset(map, start, nr);
-
- return map;
-}
-
-#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
-
-struct thread_map *thread_map__new_by_pid(pid_t pid)
-{
- struct thread_map *threads;
+ struct perf_thread_map *threads;
char name[256];
int items;
struct dirent **namelist = NULL;
@@ -69,7 +46,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
threads = thread_map__alloc(items);
if (threads != NULL) {
for (i = 0; i < items; i++)
- thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
+ perf_thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
threads->nr = items;
refcount_set(&threads->refcnt, 1);
}
@@ -81,12 +58,12 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
return threads;
}
-struct thread_map *thread_map__new_by_tid(pid_t tid)
+struct perf_thread_map *thread_map__new_by_tid(pid_t tid)
{
- struct thread_map *threads = thread_map__alloc(1);
+ struct perf_thread_map *threads = thread_map__alloc(1);
if (threads != NULL) {
- thread_map__set_pid(threads, 0, tid);
+ perf_thread_map__set_pid(threads, 0, tid);
threads->nr = 1;
refcount_set(&threads->refcnt, 1);
}
@@ -94,13 +71,13 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
return threads;
}
-static struct thread_map *__thread_map__new_all_cpus(uid_t uid)
+static struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid)
{
DIR *proc;
int max_threads = 32, items, i;
char path[NAME_MAX + 1 + 6];
struct dirent *dirent, **namelist = NULL;
- struct thread_map *threads = thread_map__alloc(max_threads);
+ struct perf_thread_map *threads = thread_map__alloc(max_threads);
if (threads == NULL)
goto out;
@@ -140,9 +117,9 @@ static struct thread_map *__thread_map__new_all_cpus(uid_t uid)
}
if (grow) {
- struct thread_map *tmp;
+ struct perf_thread_map *tmp;
- tmp = thread_map__realloc(threads, max_threads);
+ tmp = perf_thread_map__realloc(threads, max_threads);
if (tmp == NULL)
goto out_free_namelist;
@@ -150,8 +127,8 @@ static struct thread_map *__thread_map__new_all_cpus(uid_t uid)
}
for (i = 0; i < items; i++) {
- thread_map__set_pid(threads, threads->nr + i,
- atoi(namelist[i]->d_name));
+ perf_thread_map__set_pid(threads, threads->nr + i,
+ atoi(namelist[i]->d_name));
}
for (i = 0; i < items; i++)
@@ -180,17 +157,17 @@ out_free_closedir:
goto out_closedir;
}
-struct thread_map *thread_map__new_all_cpus(void)
+struct perf_thread_map *thread_map__new_all_cpus(void)
{
return __thread_map__new_all_cpus(UINT_MAX);
}
-struct thread_map *thread_map__new_by_uid(uid_t uid)
+struct perf_thread_map *thread_map__new_by_uid(uid_t uid)
{
return __thread_map__new_all_cpus(uid);
}
-struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
+struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
{
if (pid != -1)
return thread_map__new_by_pid(pid);
@@ -201,9 +178,9 @@ struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
return thread_map__new_by_tid(tid);
}
-static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
+static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str)
{
- struct thread_map *threads = NULL, *nt;
+ struct perf_thread_map *threads = NULL, *nt;
char name[256];
int items, total_tasks = 0;
struct dirent **namelist = NULL;
@@ -233,14 +210,14 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
goto out_free_threads;
total_tasks += items;
- nt = thread_map__realloc(threads, total_tasks);
+ nt = perf_thread_map__realloc(threads, total_tasks);
if (nt == NULL)
goto out_free_namelist;
threads = nt;
for (i = 0; i < items; i++) {
- thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name));
+ perf_thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name));
zfree(&namelist[i]);
}
threads->nr = total_tasks;
@@ -263,21 +240,9 @@ out_free_threads:
goto out;
}
-struct thread_map *thread_map__new_dummy(void)
-{
- struct thread_map *threads = thread_map__alloc(1);
-
- if (threads != NULL) {
- thread_map__set_pid(threads, 0, -1);
- threads->nr = 1;
- refcount_set(&threads->refcnt, 1);
- }
- return threads;
-}
-
-struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
+struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str)
{
- struct thread_map *threads = NULL, *nt;
+ struct perf_thread_map *threads = NULL, *nt;
int ntasks = 0;
pid_t tid, prev_tid = INT_MAX;
char *end_ptr;
@@ -287,7 +252,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
/* perf-stat expects threads to be generated even if tid not given */
if (!tid_str)
- return thread_map__new_dummy();
+ return perf_thread_map__new_dummy();
slist = strlist__new(tid_str, &slist_config);
if (!slist)
@@ -304,13 +269,13 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
continue;
ntasks++;
- nt = thread_map__realloc(threads, ntasks);
+ nt = perf_thread_map__realloc(threads, ntasks);
if (nt == NULL)
goto out_free_threads;
threads = nt;
- thread_map__set_pid(threads, ntasks - 1, tid);
+ perf_thread_map__set_pid(threads, ntasks - 1, tid);
threads->nr = ntasks;
}
out:
@@ -324,7 +289,7 @@ out_free_threads:
goto out;
}
-struct thread_map *thread_map__new_str(const char *pid, const char *tid,
+struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid,
uid_t uid, bool all_threads)
{
if (pid)
@@ -339,39 +304,13 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
return thread_map__new_by_tid_str(tid);
}
-static void thread_map__delete(struct thread_map *threads)
-{
- if (threads) {
- int i;
-
- WARN_ONCE(refcount_read(&threads->refcnt) != 0,
- "thread map refcnt unbalanced\n");
- for (i = 0; i < threads->nr; i++)
- free(thread_map__comm(threads, i));
- free(threads);
- }
-}
-
-struct thread_map *thread_map__get(struct thread_map *map)
-{
- if (map)
- refcount_inc(&map->refcnt);
- return map;
-}
-
-void thread_map__put(struct thread_map *map)
-{
- if (map && refcount_dec_and_test(&map->refcnt))
- thread_map__delete(map);
-}
-
-size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
+size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp)
{
int i;
size_t printed = fprintf(fp, "%d thread%s: ",
threads->nr, threads->nr > 1 ? "s" : "");
for (i = 0; i < threads->nr; ++i)
- printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i));
+ printed += fprintf(fp, "%s%d", i ? ", " : "", perf_thread_map__pid(threads, i));
return printed + fprintf(fp, "\n");
}
@@ -400,9 +339,9 @@ static int get_comm(char **comm, pid_t pid)
return err;
}
-static void comm_init(struct thread_map *map, int i)
+static void comm_init(struct perf_thread_map *map, int i)
{
- pid_t pid = thread_map__pid(map, i);
+ pid_t pid = perf_thread_map__pid(map, i);
char *comm = NULL;
/* dummy pid comm initialization */
@@ -421,7 +360,7 @@ static void comm_init(struct thread_map *map, int i)
map->map[i].comm = comm;
}
-void thread_map__read_comms(struct thread_map *threads)
+void thread_map__read_comms(struct perf_thread_map *threads)
{
int i;
@@ -429,24 +368,24 @@ void thread_map__read_comms(struct thread_map *threads)
comm_init(threads, i);
}
-static void thread_map__copy_event(struct thread_map *threads,
- struct thread_map_event *event)
+static void thread_map__copy_event(struct perf_thread_map *threads,
+ struct perf_record_thread_map *event)
{
unsigned i;
threads->nr = (int) event->nr;
for (i = 0; i < event->nr; i++) {
- thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid);
+ perf_thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid);
threads->map[i].comm = strndup(event->entries[i].comm, 16);
}
refcount_set(&threads->refcnt, 1);
}
-struct thread_map *thread_map__new_event(struct thread_map_event *event)
+struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event)
{
- struct thread_map *threads;
+ struct perf_thread_map *threads;
threads = thread_map__alloc(event->nr);
if (threads)
@@ -455,7 +394,7 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event)
return threads;
}
-bool thread_map__has(struct thread_map *threads, pid_t pid)
+bool thread_map__has(struct perf_thread_map *threads, pid_t pid)
{
int i;
@@ -467,7 +406,7 @@ bool thread_map__has(struct thread_map *threads, pid_t pid)
return false;
}
-int thread_map__remove(struct thread_map *threads, int idx)
+int thread_map__remove(struct perf_thread_map *threads, int idx)
{
int i;
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 2f689c90a8c6..3bb860a32b8e 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -5,61 +5,27 @@
#include <sys/types.h>
#include <stdio.h>
#include <linux/refcount.h>
+#include <internal/threadmap.h>
+#include <perf/threadmap.h>
-struct thread_map_data {
- pid_t pid;
- char *comm;
-};
+struct perf_record_thread_map;
-struct thread_map {
- refcount_t refcnt;
- int nr;
- int err_thread;
- struct thread_map_data map[];
-};
+struct perf_thread_map *thread_map__new_dummy(void);
+struct perf_thread_map *thread_map__new_by_pid(pid_t pid);
+struct perf_thread_map *thread_map__new_by_tid(pid_t tid);
+struct perf_thread_map *thread_map__new_by_uid(uid_t uid);
+struct perf_thread_map *thread_map__new_all_cpus(void);
+struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
+struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event);
-struct thread_map_event;
-
-struct thread_map *thread_map__new_dummy(void);
-struct thread_map *thread_map__new_by_pid(pid_t pid);
-struct thread_map *thread_map__new_by_tid(pid_t tid);
-struct thread_map *thread_map__new_by_uid(uid_t uid);
-struct thread_map *thread_map__new_all_cpus(void);
-struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
-struct thread_map *thread_map__new_event(struct thread_map_event *event);
-
-struct thread_map *thread_map__get(struct thread_map *map);
-void thread_map__put(struct thread_map *map);
-
-struct thread_map *thread_map__new_str(const char *pid,
+struct perf_thread_map *thread_map__new_str(const char *pid,
const char *tid, uid_t uid, bool all_threads);
-struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
-
-size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
-
-static inline int thread_map__nr(struct thread_map *threads)
-{
- return threads ? threads->nr : 1;
-}
-
-static inline pid_t thread_map__pid(struct thread_map *map, int thread)
-{
- return map->map[thread].pid;
-}
-
-static inline void
-thread_map__set_pid(struct thread_map *map, int thread, pid_t pid)
-{
- map->map[thread].pid = pid;
-}
+struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str);
-static inline char *thread_map__comm(struct thread_map *map, int thread)
-{
- return map->map[thread].comm;
-}
+size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp);
-void thread_map__read_comms(struct thread_map *threads);
-bool thread_map__has(struct thread_map *threads, pid_t pid);
-int thread_map__remove(struct thread_map *threads, int idx);
+void thread_map__read_comms(struct perf_thread_map *threads);
+bool thread_map__has(struct perf_thread_map *threads, pid_t pid);
+int thread_map__remove(struct perf_thread_map *threads, int idx);
#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index c2abc259b51d..9796a2e43f67 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -10,7 +10,6 @@
#include <math.h>
#include <linux/ctype.h>
-#include "perf.h"
#include "debug.h"
#include "time-utils.h"
#include "session.h"
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index 72a42ea1d513..4f42988eb2f7 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -3,6 +3,7 @@
#define _TIME_UTILS_H_
#include <stddef.h>
+#include <time.h>
#include <linux/types.h>
struct perf_time_interval {
@@ -34,4 +35,12 @@ int timestamp__scnprintf_nsec(u64 timestamp, char *buf, size_t sz);
int fetch_current_timestamp(char *buf, size_t sz);
+static inline unsigned long long rdclock(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+}
+
#endif
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 9096a6e3de59..2abbf668b8de 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -8,8 +8,8 @@
struct perf_session;
union perf_event;
-struct perf_evlist;
-struct perf_evsel;
+struct evlist;
+struct evsel;
struct perf_sample;
struct perf_tool;
struct machine;
@@ -17,14 +17,14 @@ struct ordered_events;
typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel, struct machine *machine);
+ struct evsel *evsel, struct machine *machine);
typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct machine *machine);
typedef int (*event_attr_op)(struct perf_tool *tool,
union perf_event *event,
- struct perf_evlist **pevlist);
+ struct evlist **pevlist);
typedef int (*event_op2)(struct perf_session *session, union perf_event *event);
typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event);
@@ -56,7 +56,7 @@ struct perf_tool {
throttle,
unthrottle,
ksymbol,
- bpf_event;
+ bpf;
event_attr_op attr;
event_attr_op event_update;
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 251bbf124fb0..51fb574998bb 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -12,6 +12,7 @@
#include "parse-events.h"
#include "symbol.h"
#include "top.h"
+#include "../perf.h"
#include <inttypes.h>
#define SNPRINTF(buf, size, fmt, args...) \
@@ -70,10 +71,10 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
esamples_percent);
}
- if (top->evlist->nr_entries == 1) {
- struct perf_evsel *first = perf_evlist__first(top->evlist);
+ if (top->evlist->core.nr_entries == 1) {
+ struct evsel *first = perf_evlist__first(top->evlist);
ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
- (uint64_t)first->attr.sample_period,
+ (uint64_t)first->core.attr.sample_period,
opts->freq ? "Hz" : "");
}
@@ -95,15 +96,15 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
if (target->cpu_list)
ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
- top->evlist->cpus->nr > 1 ? "s" : "",
+ top->evlist->core.cpus->nr > 1 ? "s" : "",
target->cpu_list);
else {
if (target->tid)
ret += SNPRINTF(bf + ret, size - ret, ")");
else
ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
- top->evlist->cpus->nr,
- top->evlist->cpus->nr > 1 ? "s" : "");
+ top->evlist->core.cpus->nr,
+ top->evlist->core.cpus->nr > 1 ? "s" : "");
}
perf_top__reset_sample_counters(top);
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 19f95eaf75c8..f117d4f4821e 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -3,21 +3,25 @@
#define __PERF_TOP_H 1
#include "tool.h"
+#include "evswitch.h"
#include "annotate.h"
+#include "ordered-events.h"
+#include "record.h"
#include <linux/types.h>
#include <stddef.h>
#include <stdbool.h>
#include <sys/ioctl.h>
-struct perf_evlist;
-struct perf_evsel;
+struct evlist;
+struct evsel;
struct perf_session;
struct perf_top {
struct perf_tool tool;
- struct perf_evlist *evlist;
+ struct evlist *evlist;
struct record_opts record_opts;
struct annotation_options annotation_opts;
+ struct evswitch evswitch;
/*
* Symbols will be added here in perf_event__process_sample and will
* get out after decayed.
@@ -33,7 +37,7 @@ struct perf_top {
bool vmlinux_warned;
bool dump_symtab;
struct hist_entry *sym_filter_entry;
- struct perf_evsel *sym_evsel;
+ struct evsel *sym_evsel;
struct perf_session *session;
struct winsize winsize;
int realtime_prio;
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 4550015b9d5d..d63d542b2cde 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>
-#include "../perf.h"
#include "trace-event.h"
#include <api/fs/tracing_path.h>
#include "evsel.h"
@@ -405,11 +404,11 @@ static struct tracepoint_path *
get_tracepoints_path(struct list_head *pattrs)
{
struct tracepoint_path path, *ppath = &path;
- struct perf_evsel *pos;
+ struct evsel *pos;
int nr_tracepoints = 0;
- list_for_each_entry(pos, pattrs, node) {
- if (pos->attr.type != PERF_TYPE_TRACEPOINT)
+ list_for_each_entry(pos, pattrs, core.node) {
+ if (pos->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
++nr_tracepoints;
@@ -425,7 +424,7 @@ get_tracepoints_path(struct list_head *pattrs)
}
try_id:
- ppath->next = tracepoint_id_to_path(pos->attr.config);
+ ppath->next = tracepoint_id_to_path(pos->core.attr.config);
if (!ppath->next) {
error:
pr_debug("No memory to alloc tracepoints list\n");
@@ -441,10 +440,10 @@ next:
bool have_tracepoints(struct list_head *pattrs)
{
- struct perf_evsel *pos;
+ struct evsel *pos;
- list_for_each_entry(pos, pattrs, node)
- if (pos->attr.type == PERF_TYPE_TRACEPOINT)
+ list_for_each_entry(pos, pattrs, core.node)
+ if (pos->core.attr.type == PERF_TYPE_TRACEPOINT)
return true;
return false;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index b3982e1bb4c5..5d6bfc70b210 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -7,7 +7,6 @@
#include <string.h>
#include <errno.h>
-#include "../perf.h"
#include "debug.h"
#include "trace-event.h"
@@ -110,7 +109,7 @@ void event_format__fprintf(struct tep_event *event,
record.data = data;
trace_seq_init(&s);
- tep_event_info(&s, event, &record);
+ tep_print_event(event->tep, &s, &record, "%s", TEP_PRINT_INFO);
trace_seq_do_fprintf(&s, fp);
trace_seq_destroy(&s);
}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 13c1cf60d1bc..b6c0db068be0 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -15,7 +15,6 @@
#include <unistd.h>
#include <errno.h>
-#include "../perf.h"
#include "util.h"
#include "trace-event.h"
#include "debug.h"
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index ba58f69777a1..714581b0de65 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -10,7 +10,6 @@
#include <string.h>
#include <errno.h>
-#include "../perf.h"
#include "debug.h"
#include "trace-event.h"
#include <linux/zalloc.h>
@@ -29,7 +28,7 @@ static int stop_script_unsupported(void)
static void process_event_unsupported(union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
- struct perf_evsel *evsel __maybe_unused,
+ struct evsel *evsel __maybe_unused,
struct addr_location *al __maybe_unused)
{
}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index c7002fe11673..2e158387b3d7 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,7 +3,6 @@
#define _PERF_UTIL_TRACE_EVENT_H
#include <traceevent/event-parse.h>
-#include <traceevent/trace-seq.h>
#include "parse-events.h"
struct machine;
@@ -79,13 +78,13 @@ struct scripting_ops {
int (*stop_script) (void);
void (*process_event) (union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
+ struct evsel *evsel,
struct addr_location *al);
void (*process_switch)(union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
void (*process_stat)(struct perf_stat_config *config,
- struct perf_evsel *evsel, u64 tstamp);
+ struct evsel *evsel, u64 tstamp);
void (*process_stat_interval)(u64 tstamp);
int (*generate_script) (struct tep_handle *pevent, const char *outfile);
};
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
index 88223bc7c82b..33e997f9ccc8 100644
--- a/tools/perf/util/trigger.h
+++ b/tools/perf/util/trigger.h
@@ -2,7 +2,6 @@
#ifndef __TRIGGER_H_
#define __TRIGGER_H_ 1
-#include "util/debug.h"
#include "asm/bug.h"
/*
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 28f71ca6ce1c..9ece188ae48a 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -5,6 +5,7 @@
#include <inttypes.h>
#include <errno.h>
#include "debug.h"
+#include "dso.h"
#include "unwind.h"
#include "unwind-libdw.h"
#include "machine.h"
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 71a788921b62..ebdbb056510c 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -616,26 +616,26 @@ static unw_accessors_t accessors = {
.get_proc_name = get_proc_name,
};
-static int _unwind__prepare_access(struct thread *thread)
+static int _unwind__prepare_access(struct map_groups *mg)
{
- thread->addr_space = unw_create_addr_space(&accessors, 0);
- if (!thread->addr_space) {
+ mg->addr_space = unw_create_addr_space(&accessors, 0);
+ if (!mg->addr_space) {
pr_err("unwind: Can't create unwind address space.\n");
return -ENOMEM;
}
- unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
+ unw_set_caching_policy(mg->addr_space, UNW_CACHE_GLOBAL);
return 0;
}
-static void _unwind__flush_access(struct thread *thread)
+static void _unwind__flush_access(struct map_groups *mg)
{
- unw_flush_cache(thread->addr_space, 0, 0);
+ unw_flush_cache(mg->addr_space, 0, 0);
}
-static void _unwind__finish_access(struct thread *thread)
+static void _unwind__finish_access(struct map_groups *mg)
{
- unw_destroy_addr_space(thread->addr_space);
+ unw_destroy_addr_space(mg->addr_space);
}
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
@@ -660,7 +660,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
*/
if (max_stack - 1 > 0) {
WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
- addr_space = ui->thread->addr_space;
+ addr_space = ui->thread->mg->addr_space;
if (addr_space == NULL)
return -1;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index c0811977d7d5..a24fb57c9b2c 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "unwind.h"
+#include "dso.h"
#include "map.h"
#include "thread.h"
#include "session.h"
@@ -11,13 +12,13 @@ struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
-static void unwind__register_ops(struct thread *thread,
+static void unwind__register_ops(struct map_groups *mg,
struct unwind_libunwind_ops *ops)
{
- thread->unwind_libunwind_ops = ops;
+ mg->unwind_libunwind_ops = ops;
}
-int unwind__prepare_access(struct thread *thread, struct map *map,
+int unwind__prepare_access(struct map_groups *mg, struct map *map,
bool *initialized)
{
const char *arch;
@@ -28,7 +29,7 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
if (!dwarf_callchain_users)
return 0;
- if (thread->addr_space) {
+ if (mg->addr_space) {
pr_debug("unwind: thread map already set, dso=%s\n",
map->dso->name);
if (initialized)
@@ -37,14 +38,14 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
}
/* env->arch is NULL for live-mode (i.e. perf top) */
- if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
+ if (!mg->machine->env || !mg->machine->env->arch)
goto out_register;
- dso_type = dso__type(map->dso, thread->mg->machine);
+ dso_type = dso__type(map->dso, mg->machine);
if (dso_type == DSO__TYPE_UNKNOWN)
return 0;
- arch = perf_env__arch(thread->mg->machine->env);
+ arch = perf_env__arch(mg->machine->env);
if (!strcmp(arch, "x86")) {
if (dso_type != DSO__TYPE_64BIT)
@@ -59,37 +60,31 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
return 0;
}
out_register:
- unwind__register_ops(thread, ops);
+ unwind__register_ops(mg, ops);
- err = thread->unwind_libunwind_ops->prepare_access(thread);
+ err = mg->unwind_libunwind_ops->prepare_access(mg);
if (initialized)
*initialized = err ? false : true;
return err;
}
-void unwind__flush_access(struct thread *thread)
+void unwind__flush_access(struct map_groups *mg)
{
- if (!dwarf_callchain_users)
- return;
-
- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->flush_access(thread);
+ if (mg->unwind_libunwind_ops)
+ mg->unwind_libunwind_ops->flush_access(mg);
}
-void unwind__finish_access(struct thread *thread)
+void unwind__finish_access(struct map_groups *mg)
{
- if (!dwarf_callchain_users)
- return;
-
- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->finish_access(thread);
+ if (mg->unwind_libunwind_ops)
+ mg->unwind_libunwind_ops->finish_access(mg);
}
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack)
{
- if (thread->unwind_libunwind_ops)
- return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
+ if (thread->mg->unwind_libunwind_ops)
+ return thread->mg->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
return 0;
}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 8a44a1569a21..3a7d00c20d86 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -6,6 +6,7 @@
#include <linux/types.h>
struct map;
+struct map_groups;
struct perf_sample;
struct symbol;
struct thread;
@@ -19,9 +20,9 @@ struct unwind_entry {
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
struct unwind_libunwind_ops {
- int (*prepare_access)(struct thread *thread);
- void (*flush_access)(struct thread *thread);
- void (*finish_access)(struct thread *thread);
+ int (*prepare_access)(struct map_groups *mg);
+ void (*flush_access)(struct map_groups *mg);
+ void (*finish_access)(struct map_groups *mg);
int (*get_entries)(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack);
@@ -46,20 +47,20 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
#endif
int LIBUNWIND__ARCH_REG_ID(int regnum);
-int unwind__prepare_access(struct thread *thread, struct map *map,
+int unwind__prepare_access(struct map_groups *mg, struct map *map,
bool *initialized);
-void unwind__flush_access(struct thread *thread);
-void unwind__finish_access(struct thread *thread);
+void unwind__flush_access(struct map_groups *mg);
+void unwind__finish_access(struct map_groups *mg);
#else
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused,
struct map *map __maybe_unused,
bool *initialized __maybe_unused)
{
return 0;
}
-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__flush_access(struct map_groups *mg __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif
#else
static inline int
@@ -72,14 +73,14 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
return 0;
}
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused,
struct map *map __maybe_unused,
bool *initialized __maybe_unused)
{
return 0;
}
-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__flush_access(struct map_groups *mg __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
deleted file mode 100644
index 80a99e458d4e..000000000000
--- a/tools/perf/util/util-cxx.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Support C++ source use utilities defined in util.h
- */
-
-#ifndef PERF_UTIL_UTIL_CXX_H
-#define PERF_UTIL_UTIL_CXX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Now 'new' is the only C++ keyword found in util.h:
- * in tools/include/linux/rbtree.h
- *
- * Other keywords, like class and delete, should be
- * redefined if necessary.
- */
-#define new _new
-#include "util.h"
-#undef new
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index a61535cf1bca..32322a20a68b 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-#include "../perf.h"
#include "util.h"
#include "debug.h"
+#include "event.h"
#include "namespaces.h"
#include <api/fs/fs.h>
#include <sys/mman.h>
@@ -16,10 +16,12 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/time64.h>
#include <unistd.h>
+#include "cap.h"
#include "strlist.h"
#include "string2.h"
@@ -41,26 +43,6 @@ void perf_set_multithreaded(void)
unsigned int page_size;
-#ifdef _SC_LEVEL1_DCACHE_LINESIZE
-#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
-#else
-static void cache_line_size(int *cacheline_sizep)
-{
- if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
- pr_debug("cannot determine cache line size");
-}
-#endif
-
-int cacheline_size(void)
-{
- static int size;
-
- if (!size)
- cache_line_size(&size);
-
- return size;
-}
-
int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
@@ -384,46 +366,6 @@ int copyfile(const char *from, const char *to)
return copyfile_mode(from, to, 0755);
}
-static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
-{
- void *buf_start = buf;
- size_t left = n;
-
- while (left) {
- /* buf must be treated as const if !is_read. */
- ssize_t ret = is_read ? read(fd, buf, left) :
- write(fd, buf, left);
-
- if (ret < 0 && errno == EINTR)
- continue;
- if (ret <= 0)
- return ret;
-
- left -= ret;
- buf += ret;
- }
-
- BUG_ON((size_t)(buf - buf_start) != n);
- return n;
-}
-
-/*
- * Read exactly 'n' bytes or return an error.
- */
-ssize_t readn(int fd, void *buf, size_t n)
-{
- return ion(true, fd, buf, n);
-}
-
-/*
- * Write exactly 'n' bytes or return an error.
- */
-ssize_t writen(int fd, const void *buf, size_t n)
-{
- /* ion does not modify buf. */
- return ion(false, fd, (void *)buf, n);
-}
-
size_t hex_width(u64 v)
{
size_t n = 1;
@@ -443,6 +385,13 @@ int perf_event_paranoid(void)
return value;
}
+
+bool perf_event_paranoid_check(int max_level)
+{
+ return perf_cap__capable(CAP_SYS_ADMIN) ||
+ perf_event_paranoid() <= max_level;
+}
+
static int
fetch_ubuntu_kernel_version(unsigned int *puint)
{
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index dc7a469921e9..45a5c6f20197 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -11,6 +11,7 @@
#include <stddef.h>
#include <linux/compiler.h>
#include <sys/types.h>
+#include <internal/lib.h>
/* General helper functions */
void usage(const char *err) __noreturn;
@@ -30,13 +31,9 @@ int copyfile_mode(const char *from, const char *to, mode_t mode);
int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size);
-ssize_t readn(int fd, void *buf, size_t n);
-ssize_t writen(int fd, const void *buf, size_t n);
-
size_t hex_width(u64 v);
extern unsigned int page_size;
-int __pure cacheline_size(void);
int sysctl__max_stack(void);
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index c59154e2d124..b9823f414f10 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -2,6 +2,7 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include <linux/zalloc.h>
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 7f427bab6c12..e5e6599603f4 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include "vdso.h"
+#include "dso.h"
#include "util.h"
#include "map.h"
#include "symbol.h"
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
index 512ad7c09b13..59d456f716e9 100644
--- a/tools/perf/util/zlib.c
+++ b/tools/perf/util/zlib.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <fcntl.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index 23bdb9884576..d2202392ffdb 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -99,8 +99,8 @@ size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size
while (input.pos < input.size) {
ret = ZSTD_decompressStream(data->dstream, &output, &input);
if (ZSTD_isError(ret)) {
- pr_err("failed to decompress (B): %ld -> %ld : %s\n",
- src_size, output.size, ZSTD_getErrorName(ret));
+ pr_err("failed to decompress (B): %ld -> %ld, dst_size %ld : %s\n",
+ src_size, output.size, dst_size, ZSTD_getErrorName(ret));
break;
}
output.dst = dst + output.pos;
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
index 91c5ad1685a1..59753b3917bb 100644
--- a/tools/power/x86/intel-speed-select/isst-config.c
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -304,7 +304,7 @@ static void set_cpu_present_cpu_mask(void)
int get_cpu_count(int pkg_id, int die_id)
{
if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
- return cpu_cnt[pkg_id][die_id] + 1;
+ return cpu_cnt[pkg_id][die_id];
return 0;
}
@@ -603,6 +603,10 @@ static int isst_fill_platform_info(void)
close(fd);
+ if (isst_platform_info.api_version > supported_api_ver) {
+ printf("Incompatible API versions; Upgrade of tool is required\n");
+ return -1;
+ }
return 0;
}
@@ -1491,7 +1495,7 @@ static void usage(void)
printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
- printf("\nFor help on each feature, use --h|--help\n");
+ printf("\nFor help on each feature, use -h|--help\n");
printf("\tFor example: intel-speed-select perf-profile -h\n");
printf("\nFor additional help on each command for a feature, use --h|--help\n");
@@ -1514,7 +1518,6 @@ static void usage(void)
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
printf("\t\tPackage, Die, CPU, and command specific results.\n");
- printf("\t\t\tFor Set commands, status is 0 for success and rest for failures\n");
exit(1);
}
@@ -1529,6 +1532,7 @@ static void cmdline(int argc, char **argv)
{
int opt;
int option_index = 0;
+ int ret;
static struct option long_options[] = {
{ "cpu", required_argument, 0, 'c' },
@@ -1590,13 +1594,14 @@ static void cmdline(int argc, char **argv)
set_max_cpu_num();
set_cpu_present_cpu_mask();
set_cpu_target_cpu_mask();
- isst_fill_platform_info();
- if (isst_platform_info.api_version > supported_api_ver) {
- printf("Incompatible API versions; Upgrade of tool is required\n");
- exit(0);
- }
+ ret = isst_fill_platform_info();
+ if (ret)
+ goto out;
process_command(argc, argv);
+out:
+ free_cpu_set(present_cpumask);
+ free_cpu_set(target_cpumask);
}
int main(int argc, char **argv)
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index 8de4ac39a008..0bf341ad9697 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -188,8 +188,27 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
return 0;
}
+int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
+{
+ int ret;
+
+ debug_printf("cpu:%d bucket info via MSR\n", cpu);
+
+ *buckets_info = 0;
+
+ ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
+ *buckets_info);
+
+ return 0;
+}
+
int isst_set_tdp_level_msr(int cpu, int tdp_level)
{
+ unsigned long long level = tdp_level;
int ret;
debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
@@ -202,8 +221,7 @@ int isst_set_tdp_level_msr(int cpu, int tdp_level)
if (tdp_level > 2)
return -1; /* invalid value */
- ret = isst_send_msr_command(cpu, 0x64b, 1,
- (unsigned long long *)&tdp_level);
+ ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
if (ret)
return ret;
@@ -563,6 +581,10 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
if (ret)
return ret;
+ ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ if (ret)
+ return ret;
+
ret = isst_get_get_trl(cpu, i, 0,
ctdp_level->trl_sse_active_cores);
if (ret)
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
index f368b8323742..df4aa99c4e92 100644
--- a/tools/power/x86/intel-speed-select/isst-display.c
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -6,7 +6,34 @@
#include "isst.h"
-#define DISP_FREQ_MULTIPLIER 100000
+#define DISP_FREQ_MULTIPLIER 100
+
+static void printcpulist(int str_len, char *str, int mask_size,
+ cpu_set_t *cpu_mask)
+{
+ int i, first, curr_index, index;
+
+ if (!CPU_COUNT_S(mask_size, cpu_mask)) {
+ snprintf(str, str_len, "none");
+ return;
+ }
+
+ curr_index = 0;
+ first = 1;
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (!CPU_ISSET_S(i, mask_size, cpu_mask))
+ continue;
+ if (!first) {
+ index = snprintf(&str[curr_index],
+ str_len - curr_index, ",");
+ curr_index += index;
+ }
+ index = snprintf(&str[curr_index], str_len - curr_index, "%d",
+ i);
+ curr_index += index;
+ first = 0;
+ }
+}
static void printcpumask(int str_len, char *str, int mask_size,
cpu_set_t *cpu_mask)
@@ -133,7 +160,7 @@ static void format_and_print(FILE *outf, int level, char *header, char *value)
last_level = level;
}
-static void print_packag_info(int cpu, FILE *outf)
+static void print_package_info(int cpu, FILE *outf)
{
char header[256];
@@ -156,7 +183,7 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
snprintf(header, sizeof(header), "speed-select-base-freq");
format_and_print(outf, disp_level, header, NULL);
- snprintf(header, sizeof(header), "high-priority-base-frequency(KHz)");
+ snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
format_and_print(outf, disp_level + 1, header, value);
@@ -166,7 +193,13 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
pbf_info->core_cpumask);
format_and_print(outf, disp_level + 1, header, value);
- snprintf(header, sizeof(header), "low-priority-base-frequency(KHz)");
+ snprintf(header, sizeof(header), "high-priority-cpu-list");
+ printcpulist(sizeof(value), value,
+ pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
format_and_print(outf, disp_level + 1, header, value);
@@ -209,7 +242,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
if (fact_avx & 0x01) {
snprintf(header, sizeof(header),
- "high-priority-max-frequency(KHz)");
+ "high-priority-max-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 2, header, value);
@@ -217,7 +250,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
if (fact_avx & 0x02) {
snprintf(header, sizeof(header),
- "high-priority-max-avx2-frequency(KHz)");
+ "high-priority-max-avx2-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 2, header, value);
@@ -225,7 +258,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
if (fact_avx & 0x04) {
snprintf(header, sizeof(header),
- "high-priority-max-avx512-frequency(KHz)");
+ "high-priority-max-avx512-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
bucket_info[j].avx512_trl *
DISP_FREQ_MULTIPLIER);
@@ -235,19 +268,19 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
snprintf(header, sizeof(header),
"speed-select-turbo-freq-clip-frequencies");
format_and_print(outf, base_level + 1, header, NULL);
- snprintf(header, sizeof(header), "low-priority-max-frequency(KHz)");
+ snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
fact_info->lp_clipping_ratio_license_sse *
DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 2, header, value);
snprintf(header, sizeof(header),
- "low-priority-max-avx2-frequency(KHz)");
+ "low-priority-max-avx2-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
fact_info->lp_clipping_ratio_license_avx2 *
DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 2, header, value);
snprintf(header, sizeof(header),
- "low-priority-max-avx512-frequency(KHz)");
+ "low-priority-max-avx512-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
fact_info->lp_clipping_ratio_license_avx512 *
DISP_FREQ_MULTIPLIER);
@@ -261,7 +294,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
char value[256];
int i, base_level = 1;
- print_packag_info(cpu, outf);
+ print_package_info(cpu, outf);
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
@@ -287,33 +320,41 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
ctdp_level->core_cpumask);
format_and_print(outf, base_level + 4, header, value);
+ snprintf(header, sizeof(header), "enable-cpu-list");
+ printcpulist(sizeof(value), value,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ format_and_print(outf, base_level + 4, header, value);
+
snprintf(header, sizeof(header), "thermal-design-power-ratio");
snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
format_and_print(outf, base_level + 4, header, value);
- snprintf(header, sizeof(header), "base-frequency(KHz)");
+ snprintf(header, sizeof(header), "base-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header),
- "speed-select-turbo-freq-support");
- snprintf(value, sizeof(value), "%d", ctdp_level->fact_support);
+ "speed-select-turbo-freq");
+ if (ctdp_level->fact_support) {
+ if (ctdp_level->fact_enabled)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ } else
+ snprintf(value, sizeof(value), "unsupported");
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header),
- "speed-select-base-freq-support");
- snprintf(value, sizeof(value), "%d", ctdp_level->pbf_support);
- format_and_print(outf, base_level + 4, header, value);
-
- snprintf(header, sizeof(header),
- "speed-select-base-freq-enabled");
- snprintf(value, sizeof(value), "%d", ctdp_level->pbf_enabled);
- format_and_print(outf, base_level + 4, header, value);
-
- snprintf(header, sizeof(header),
- "speed-select-turbo-freq-enabled");
- snprintf(value, sizeof(value), "%d", ctdp_level->fact_enabled);
+ "speed-select-base-freq");
+ if (ctdp_level->pbf_support) {
+ if (ctdp_level->pbf_enabled)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ } else
+ snprintf(value, sizeof(value), "unsupported");
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "thermal-design-power(W)");
@@ -331,12 +372,14 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%d", j);
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
- snprintf(header, sizeof(header), "turbo-ratio");
+ snprintf(header, sizeof(header),
+ "max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_sse_active_cores[j]);
+ ctdp_level->trl_sse_active_cores[j] *
+ DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
@@ -346,12 +389,14 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%d", j);
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
- snprintf(header, sizeof(header), "turbo-ratio");
+ snprintf(header, sizeof(header),
+ "max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_avx_active_cores[j]);
+ ctdp_level->trl_avx_active_cores[j] *
+ DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
@@ -362,12 +407,14 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%d", j);
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
- snprintf(header, sizeof(header), "turbo-ratio");
+ snprintf(header, sizeof(header),
+ "max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_avx_512_active_cores[j]);
+ ctdp_level->trl_avx_512_active_cores[j] *
+ DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
if (ctdp_level->pbf_support)
@@ -397,7 +444,7 @@ void isst_ctdp_display_information_end(FILE *outf)
void isst_pbf_display_information(int cpu, FILE *outf, int level,
struct isst_pbf_info *pbf_info)
{
- print_packag_info(cpu, outf);
+ print_package_info(cpu, outf);
_isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
format_and_print(outf, 1, NULL, NULL);
}
@@ -406,7 +453,7 @@ void isst_fact_display_information(int cpu, FILE *outf, int level,
int fact_bucket, int fact_avx,
struct isst_fact_info *fact_info)
{
- print_packag_info(cpu, outf);
+ print_package_info(cpu, outf);
_isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
fact_info, 4);
format_and_print(outf, 1, NULL, NULL);
@@ -472,7 +519,10 @@ void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
snprintf(header, sizeof(header), "%s", feature);
format_and_print(outf, 4, header, NULL);
snprintf(header, sizeof(header), "%s", cmd);
- snprintf(value, sizeof(value), "%d", result);
+ if (!result)
+ snprintf(value, sizeof(value), "success");
+ else
+ snprintf(value, sizeof(value), "failed(error %d)", result);
format_and_print(outf, 5, header, value);
format_and_print(outf, 1, NULL, NULL);
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
index 221881761609..2f7f62765eb6 100644
--- a/tools/power/x86/intel-speed-select/isst.h
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -134,6 +134,7 @@ struct isst_pkg_ctdp_level_info {
size_t core_cpumask_size;
cpu_set_t *core_cpumask;
int cpu_count;
+ unsigned long long buckets_info;
int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 045f5f7d68ab..13f1e8b9ac52 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -9,9 +9,10 @@ ifeq ("$(origin O)", "command line")
endif
turbostat : turbostat.c
-override CFLAGS += -Wall -I../../../include
+override CFLAGS += -O2 -Wall -I../../../include
override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
override CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
+override CFLAGS += -D_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 75fc4fb9901c..5d0fddda842c 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -39,7 +39,6 @@ FILE *outf;
int *fd_percpu;
struct timeval interval_tv = {5, 0};
struct timespec interval_ts = {5, 0};
-struct timespec one_msec = {0, 1000000};
unsigned int num_iterations;
unsigned int debug;
unsigned int quiet;
@@ -60,6 +59,7 @@ unsigned int do_irtl_hsw;
unsigned int units = 1000000; /* MHz etc */
unsigned int genuine_intel;
unsigned int authentic_amd;
+unsigned int hygon_genuine;
unsigned int max_level, max_extended_level;
unsigned int has_invariant_tsc;
unsigned int do_nhm_platform_info;
@@ -100,6 +100,7 @@ unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
unsigned int has_misc_feature_control;
unsigned int first_counter_read = 1;
+int ignore_stdin;
#define RAPL_PKG (1 << 0)
/* 0x610 MSR_PKG_POWER_LIMIT */
@@ -166,6 +167,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
struct thread_data {
struct timeval tv_begin;
struct timeval tv_end;
+ struct timeval tv_delta;
unsigned long long tsc;
unsigned long long aperf;
unsigned long long mperf;
@@ -506,6 +508,7 @@ unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAU
unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
+#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
@@ -849,7 +852,6 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
- outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg);
@@ -911,7 +913,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_TOD))
outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
- interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
+ interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
tsc = t->tsc * tsc_tweak;
@@ -1287,6 +1289,14 @@ delta_core(struct core_data *new, struct core_data *old)
}
}
+int soft_c1_residency_display(int bic)
+{
+ if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr)
+ return 0;
+
+ return DO_BIC_READ(bic);
+}
+
/*
* old = new - old
*/
@@ -1309,6 +1319,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
* over-write old w/ new so we can print end of interval values
*/
+ timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
old->tv_begin = new->tv_begin;
old->tv_end = new->tv_end;
@@ -1322,7 +1333,8 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->c1 = new->c1 - old->c1;
- if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
+ soft_c1_residency_display(BIC_Avg_MHz)) {
if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
old->aperf = new->aperf - old->aperf;
old->mperf = new->mperf - old->mperf;
@@ -1404,6 +1416,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
t->tv_begin.tv_usec = 0;
t->tv_end.tv_sec = 0;
t->tv_end.tv_usec = 0;
+ t->tv_delta.tv_sec = 0;
+ t->tv_delta.tv_usec = 0;
t->tsc = 0;
t->aperf = 0;
@@ -1573,6 +1587,9 @@ void compute_average(struct thread_data *t, struct core_data *c,
for_all_cpus(sum_counters, t, c, p);
+ /* Use the global time delta for the average. */
+ average.threads.tv_delta = tv_delta;
+
average.threads.tsc /= topo.num_cpus;
average.threads.aperf /= topo.num_cpus;
average.threads.mperf /= topo.num_cpus;
@@ -1714,7 +1731,7 @@ void get_apic_id(struct thread_data *t)
if (!DO_BIC(BIC_X2APIC))
return;
- if (authentic_amd) {
+ if (authentic_amd || hygon_genuine) {
unsigned int topology_extensions;
if (max_extended_level < 0x8000001e)
@@ -1762,19 +1779,20 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
struct msr_counter *mp;
int i;
- gettimeofday(&t->tv_begin, (struct timezone *)NULL);
-
if (cpu_migrate(cpu)) {
fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1;
}
+ gettimeofday(&t->tv_begin, (struct timezone *)NULL);
+
if (first_counter_read)
get_apic_id(t);
retry:
t->tsc = rdtsc(); /* we are running on local CPU of interest */
- if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
+ soft_c1_residency_display(BIC_Avg_MHz)) {
unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
/*
@@ -1851,20 +1869,20 @@ retry:
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
- if (DO_BIC(BIC_CPU_c3)) {
+ if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
return -6;
}
- if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) {
+ if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
return -7;
- } else if (do_knl_cstates) {
+ } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) {
if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
return -7;
}
- if (DO_BIC(BIC_CPU_c7))
+ if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7))
if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
return -8;
@@ -2150,7 +2168,7 @@ int has_turbo_ratio_group_limits(int family, int model)
switch (model) {
case INTEL_FAM6_ATOM_GOLDMONT:
case INTEL_FAM6_SKYLAKE_X:
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
return 1;
}
return 0;
@@ -2912,6 +2930,7 @@ int snapshot_cpu_lpi_us(void)
if (retval != 1) {
fprintf(stderr, "Disabling Low Power Idle CPU output\n");
BIC_NOT_PRESENT(BIC_CPU_LPI);
+ fclose(fp);
return -1;
}
@@ -2938,6 +2957,7 @@ int snapshot_sys_lpi_us(void)
if (retval != 1) {
fprintf(stderr, "Disabling Low Power Idle System output\n");
BIC_NOT_PRESENT(BIC_SYS_LPI);
+ fclose(fp);
return -1;
}
fclose(fp);
@@ -2985,8 +3005,6 @@ static void signal_handler (int signal)
fprintf(stderr, "SIGUSR1\n");
break;
}
- /* make sure this manually-invoked interval is at least 1ms long */
- nanosleep(&one_msec, NULL);
}
void setup_signal_handler(void)
@@ -3005,29 +3023,38 @@ void setup_signal_handler(void)
void do_sleep(void)
{
- struct timeval select_timeout;
+ struct timeval tout;
+ struct timespec rest;
fd_set readfds;
int retval;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
- if (!isatty(fileno(stdin))) {
+ if (ignore_stdin) {
nanosleep(&interval_ts, NULL);
return;
}
- select_timeout = interval_tv;
- retval = select(1, &readfds, NULL, NULL, &select_timeout);
+ tout = interval_tv;
+ retval = select(1, &readfds, NULL, NULL, &tout);
if (retval == 1) {
switch (getc(stdin)) {
case 'q':
exit_requested = 1;
break;
+ case EOF:
+ /*
+ * 'stdin' is a pipe closed on the other end. There
+ * won't be any further input.
+ */
+ ignore_stdin = 1;
+ /* Sleep the rest of the time */
+ rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
+ rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
+ nanosleep(&rest, NULL);
}
- /* make sure this manually-invoked interval is at least 1ms long */
- nanosleep(&one_msec, NULL);
}
}
@@ -3207,14 +3234,15 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
pkg_cstate_limits = snb_pkg_cstate_limits;
has_misc_feature_control = 1;
break;
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
case INTEL_FAM6_HASWELL_X: /* HSX */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
pkg_cstate_limits = hsw_pkg_cstate_limits;
has_misc_feature_control = 1;
break;
@@ -3224,7 +3252,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
break;
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
no_MSR_MISC_PWR_MGMT = 1;
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
pkg_cstate_limits = slv_pkg_cstate_limits;
break;
case INTEL_FAM6_ATOM_AIRMONT: /* AMT */
@@ -3236,7 +3264,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
pkg_cstate_limits = glm_pkg_cstate_limits;
break;
default:
@@ -3279,7 +3307,7 @@ int is_dnv(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
return 1;
}
return 0;
@@ -3403,14 +3431,15 @@ int has_config_tdp(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_IVYBRIDGE: /* IVB */
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
case INTEL_FAM6_HASWELL_X: /* HSX */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_SKYLAKE_X: /* SKX */
case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */
@@ -3792,7 +3821,7 @@ double get_tdp_intel(unsigned int model)
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT:
- case INTEL_FAM6_ATOM_SILVERMONT_X:
+ case INTEL_FAM6_ATOM_SILVERMONT_D:
return 30.0;
default:
return 135.0;
@@ -3803,6 +3832,7 @@ double get_tdp_amd(unsigned int family)
{
switch (family) {
case 0x17:
+ case 0x18:
default:
/* This is the max stock TDP of HEDT/Server Fam17h chips */
return 250.0;
@@ -3840,10 +3870,11 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_SANDYBRIDGE:
case INTEL_FAM6_IVYBRIDGE:
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
@@ -3863,8 +3894,8 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
else
BIC_PRESENT(BIC_PkgWatt);
break;
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
@@ -3911,7 +3942,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
}
break;
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
do_rapl = RAPL_PKG | RAPL_CORES;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
@@ -3921,7 +3952,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
BIC_PRESENT(BIC_CorWatt);
}
break;
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
@@ -3982,6 +4013,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
switch (family) {
case 0x17: /* Zen, Zen+ */
+ case 0x18: /* Hygon Dhyana */
do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
@@ -4002,7 +4034,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
rapl_power_units = ldexp(1.0, -(msr & 0xf));
- tdp = get_tdp_amd(model);
+ tdp = get_tdp_amd(family);
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
if (!quiet)
@@ -4018,7 +4050,7 @@ void rapl_probe(unsigned int family, unsigned int model)
{
if (genuine_intel)
rapl_probe_intel(family, model);
- if (authentic_amd)
+ if (authentic_amd || hygon_genuine)
rapl_probe_amd(family, model);
}
@@ -4031,8 +4063,9 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model)
return;
switch (model) {
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
do_gfx_perf_limit_reasons = 1;
case INTEL_FAM6_HASWELL_X: /* HSX */
do_core_perf_limit_reasons = 1;
@@ -4247,27 +4280,28 @@ int has_snb_msrs(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_SANDYBRIDGE:
case INTEL_FAM6_SANDYBRIDGE_X:
- case INTEL_FAM6_IVYBRIDGE: /* IVB */
- case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_X: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
- case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
- case INTEL_FAM6_SKYLAKE_X: /* SKX */
- case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_IVYBRIDGE: /* IVB */
+ case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_X: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
+ case INTEL_FAM6_BROADWELL_X: /* BDX */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
+ case INTEL_FAM6_SKYLAKE_X: /* SKX */
+ case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
return 1;
}
return 0;
}
/*
- * HSW adds support for additional MSRs:
+ * HSW ULT added support for C8/C9/C10 MSRs:
*
* MSR_PKG_C8_RESIDENCY 0x00000630
* MSR_PKG_C9_RESIDENCY 0x00000631
@@ -4278,16 +4312,16 @@ int has_snb_msrs(unsigned int family, unsigned int model)
* MSR_PKGC10_IRTL 0x00000635
*
*/
-int has_hsw_msrs(unsigned int family, unsigned int model)
+int has_c8910_msrs(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
switch (model) {
- case INTEL_FAM6_HASWELL_CORE:
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
return 1;
@@ -4309,8 +4343,8 @@ int has_skl_msrs(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
return 1;
}
return 0;
@@ -4322,7 +4356,7 @@ int is_slm(unsigned int family, unsigned int model)
return 0;
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
return 1;
}
return 0;
@@ -4345,7 +4379,7 @@ int is_cnl(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
return 1;
}
@@ -4568,21 +4602,22 @@ unsigned int intel_model_duplicates(unsigned int model)
case INTEL_FAM6_XEON_PHI_KNM:
return INTEL_FAM6_XEON_PHI_KNL;
- case INTEL_FAM6_HASWELL_ULT:
- return INTEL_FAM6_HASWELL_CORE;
-
case INTEL_FAM6_BROADWELL_X:
- case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */
+ case INTEL_FAM6_BROADWELL_D: /* BDX-DE */
return INTEL_FAM6_BROADWELL_X;
- case INTEL_FAM6_SKYLAKE_MOBILE:
- case INTEL_FAM6_SKYLAKE_DESKTOP:
- case INTEL_FAM6_KABYLAKE_MOBILE:
- case INTEL_FAM6_KABYLAKE_DESKTOP:
- return INTEL_FAM6_SKYLAKE_MOBILE;
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
+ return INTEL_FAM6_SKYLAKE_L;
+
+ case INTEL_FAM6_ICELAKE_L:
+ case INTEL_FAM6_ICELAKE_NNPI:
+ return INTEL_FAM6_CANNONLAKE_L;
- case INTEL_FAM6_ICELAKE_MOBILE:
- return INTEL_FAM6_CANNONLAKE_MOBILE;
+ case INTEL_FAM6_ATOM_TREMONT_D:
+ return INTEL_FAM6_ATOM_GOLDMONT_D;
}
return model;
}
@@ -4600,6 +4635,8 @@ void process_cpuid()
genuine_intel = 1;
else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
authentic_amd = 1;
+ else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
+ hygon_genuine = 1;
if (!quiet)
fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
@@ -4731,10 +4768,10 @@ void process_cpuid()
if (crystal_hz == 0)
switch(model) {
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
crystal_hz = 24000000; /* 24.0 MHz */
break;
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
crystal_hz = 25000000; /* 25.0 MHz */
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
@@ -4820,12 +4857,12 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_CPU_c7);
BIC_NOT_PRESENT(BIC_Pkgpc7);
}
- if (has_hsw_msrs(family, model)) {
+ if (has_c8910_msrs(family, model)) {
BIC_PRESENT(BIC_Pkgpc8);
BIC_PRESENT(BIC_Pkgpc9);
BIC_PRESENT(BIC_Pkgpc10);
}
- do_irtl_hsw = has_hsw_msrs(family, model);
+ do_irtl_hsw = has_c8910_msrs(family, model);
if (has_skl_msrs(family, model)) {
BIC_PRESENT(BIC_Totl_c0);
BIC_PRESENT(BIC_Any_c0);
@@ -5123,7 +5160,7 @@ int initialize_counters(int cpu_id)
void allocate_output_buffer()
{
- output_buffer = calloc(1, (1 + topo.num_cpus) * 1024);
+ output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
outp = output_buffer;
if (outp == NULL)
err(-1, "calloc output buffer");
@@ -5269,7 +5306,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 19.03.20"
+ fprintf(outf, "turbostat version 19.08.31"
" - Len Brown <lenb@kernel.org>\n");
}
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index 1fdeef864e7c..666b325a62a2 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -9,8 +9,9 @@ ifeq ("$(origin O)", "command line")
endif
x86_energy_perf_policy : x86_energy_perf_policy.c
-override CFLAGS += -Wall -I../../../include
+override CFLAGS += -O2 -Wall -I../../../include
override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
+override CFLAGS += -D_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
index 17db1c3af4d0..78c6361898b1 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
@@ -40,7 +40,7 @@ in the same processor package.
Hardware P-States (HWP) are effectively an expansion of hardware
P-state control from the opportunistic turbo-mode P-state range
to include the entire range of available P-states.
-On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP.
+On Broadwell Xeon, the initial HWP implementation, EPB influenced HWP.
That influence was removed in subsequent generations,
where it was moved to the
Energy_Performance_Preference (EPP) field in
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 34a796b303fe..3fe1eed900d4 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -545,7 +545,7 @@ void cmdline(int argc, char **argv)
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw",
+ while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:",
long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
@@ -1259,6 +1259,15 @@ void probe_dev_msr(void)
if (system("/sbin/modprobe msr > /dev/null 2>&1"))
err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
}
+
+static void get_cpuid_or_exit(unsigned int leaf,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
+ errx(1, "Processor not supported\n");
+}
+
/*
* early_cpuid()
* initialize turbo_is_enabled, has_hwp, has_epb
@@ -1266,15 +1275,10 @@ void probe_dev_msr(void)
*/
void early_cpuid(void)
{
- unsigned int eax, ebx, ecx, edx, max_level;
+ unsigned int eax, ebx, ecx, edx;
unsigned int fms, family, model;
- __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
-
- if (max_level < 6)
- errx(1, "Processor not supported\n");
-
- __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
family = (fms >> 8) & 0xf;
model = (fms >> 4) & 0xf;
if (family == 6 || family == 0xf)
@@ -1288,7 +1292,7 @@ void early_cpuid(void)
bdx_highest_ratio = msr & 0xFF;
}
- __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
turbo_is_enabled = (eax >> 1) & 1;
has_hwp = (eax >> 7) & 1;
has_epb = (ecx >> 3) & 1;
@@ -1306,7 +1310,7 @@ void parse_cpuid(void)
eax = ebx = ecx = edx = 0;
- __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
genuine_intel = 1;
@@ -1315,7 +1319,7 @@ void parse_cpuid(void)
fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
(char *)&ebx, (char *)&edx, (char *)&ecx);
- __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
family = (fms >> 8) & 0xf;
model = (fms >> 4) & 0xf;
stepping = fms & 0xf;
@@ -1340,7 +1344,7 @@ void parse_cpuid(void)
errx(1, "CPUID: no MSR");
- __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
/* turbo_is_enabled already set */
/* has_hwp already set */
has_hwp_notify = eax & (1 << 8);
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 495066bafbe3..ded7a950dc40 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -32,7 +32,6 @@ EXTRA_WARNINGS += -Wno-system-headers
EXTRA_WARNINGS += -Wold-style-definition
EXTRA_WARNINGS += -Wpacked
EXTRA_WARNINGS += -Wredundant-decls
-EXTRA_WARNINGS += -Wshadow
EXTRA_WARNINGS += -Wstrict-prototypes
EXTRA_WARNINGS += -Wswitch-default
EXTRA_WARNINGS += -Wswitch-enum
@@ -69,8 +68,16 @@ endif
# will do for now and keep the above -Wstrict-aliasing=3 in place
# in newer systems.
# Needed for the __raw_cmpxchg in tools/arch/x86/include/asm/cmpxchg.h
+#
+# See https://lkml.org/lkml/2006/11/28/253 and https://gcc.gnu.org/gcc-4.8/changes.html,
+# that takes into account Linus's comments (search for Wshadow) for the reasoning about
+# -Wshadow not being interesting before gcc 4.8.
+
ifneq ($(filter 3.%,$(MAKE_VERSION)),) # make-3
EXTRA_WARNINGS += -fno-strict-aliasing
+EXTRA_WARNINGS += -Wno-shadow
+else
+EXTRA_WARNINGS += -Wshadow
endif
ifneq ($(findstring $(MAKEFLAGS), w),w)
diff --git a/tools/testing/ktest/config-bisect.pl b/tools/testing/ktest/config-bisect.pl
index 72525426654b..6fd864935319 100755
--- a/tools/testing/ktest/config-bisect.pl
+++ b/tools/testing/ktest/config-bisect.pl
@@ -663,7 +663,7 @@ while ($#ARGV >= 0) {
}
else {
- die "Unknow option $opt\n";
+ die "Unknown option $opt\n";
}
}
@@ -732,7 +732,7 @@ if ($start) {
}
}
run_command "cp $good_start $good" or die "failed to copy to $good\n";
- run_command "cp $bad_start $bad" or die "faield to copy to $bad\n";
+ run_command "cp $bad_start $bad" or die "failed to copy to $bad\n";
} else {
if ( ! -f $good ) {
die "Can not find file $good\n";
diff --git a/tools/testing/selftests/arm64/.gitignore b/tools/testing/selftests/arm64/.gitignore
new file mode 100644
index 000000000000..e8fae8d61ed6
--- /dev/null
+++ b/tools/testing/selftests/arm64/.gitignore
@@ -0,0 +1 @@
+tags_test
diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
new file mode 100644
index 000000000000..a61b2e743e99
--- /dev/null
+++ b/tools/testing/selftests/arm64/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# ARCH can be overridden by the user for cross compiling
+ARCH ?= $(shell uname -m 2>/dev/null || echo not)
+
+ifneq (,$(filter $(ARCH),aarch64 arm64))
+TEST_GEN_PROGS := tags_test
+TEST_PROGS := run_tags_test.sh
+endif
+
+include ../lib.mk
diff --git a/tools/testing/selftests/arm64/run_tags_test.sh b/tools/testing/selftests/arm64/run_tags_test.sh
new file mode 100755
index 000000000000..745f11379930
--- /dev/null
+++ b/tools/testing/selftests/arm64/run_tags_test.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+echo "--------------------"
+echo "running tags test"
+echo "--------------------"
+./tags_test
+if [ $? -ne 0 ]; then
+ echo "[FAIL]"
+else
+ echo "[PASS]"
+fi
diff --git a/tools/testing/selftests/arm64/tags_test.c b/tools/testing/selftests/arm64/tags_test.c
new file mode 100644
index 000000000000..5701163460ef
--- /dev/null
+++ b/tools/testing/selftests/arm64/tags_test.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/prctl.h>
+#include <sys/utsname.h>
+
+#define SHIFT_TAG(tag) ((uint64_t)(tag) << 56)
+#define SET_TAG(ptr, tag) (((uint64_t)(ptr) & ~SHIFT_TAG(0xff)) | \
+ SHIFT_TAG(tag))
+
+int main(void)
+{
+ static int tbi_enabled = 0;
+ unsigned long tag = 0;
+ struct utsname *ptr;
+ int err;
+
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0)
+ tbi_enabled = 1;
+ ptr = (struct utsname *)malloc(sizeof(*ptr));
+ if (tbi_enabled)
+ tag = 0x42;
+ ptr = (struct utsname *)SET_TAG(ptr, tag);
+ err = uname(ptr);
+ free(ptr);
+
+ return err;
+}
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 11c9c62c3362..96752ebd938f 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -34,6 +34,9 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
TEST_GEN_FILES = $(BPF_OBJ_FILES)
+BTF_C_FILES = $(wildcard progs/btf_dump_test_case_*.c)
+TEST_FILES = $(BTF_C_FILES)
+
# Also test sub-register code-gen if LLVM has eBPF v3 processor support which
# contains both ALU32 and JMP32 instructions.
SUBREG_CODEGEN := $(shell echo "int cal(int a) { return a > 0; }" | \
@@ -57,7 +60,8 @@ TEST_PROGS := test_kmod.sh \
test_lirc_mode2.sh \
test_skb_cgroup_id.sh \
test_flow_dissector.sh \
- test_xdp_vlan.sh \
+ test_xdp_vlan_mode_generic.sh \
+ test_xdp_vlan_mode_native.sh \
test_lwt_ip_encap.sh \
test_tcp_check_syncookie.sh \
test_tc_tunnel.sh \
@@ -67,7 +71,8 @@ TEST_PROGS := test_kmod.sh \
TEST_PROGS_EXTENDED := with_addr.sh \
with_tunnels.sh \
tcp_client.py \
- tcp_server.py
+ tcp_server.py \
+ test_xdp_vlan.sh
# Compile but not part of 'make run_tests'
TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index f7a0744db31e..5dc109f4c097 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -34,3 +34,4 @@ CONFIG_NET_MPLS_GSO=m
CONFIG_MPLS_ROUTING=m
CONFIG_MPLS_IPTUNNEL=m
CONFIG_IPV6_SIT=m
+CONFIG_BPF_JIT=y
diff --git a/tools/testing/selftests/bpf/progs/sendmsg6_prog.c b/tools/testing/selftests/bpf/progs/sendmsg6_prog.c
index 5aeaa284fc47..a68062820410 100644
--- a/tools/testing/selftests/bpf/progs/sendmsg6_prog.c
+++ b/tools/testing/selftests/bpf/progs/sendmsg6_prog.c
@@ -41,8 +41,7 @@ int sendmsg_v6_prog(struct bpf_sock_addr *ctx)
}
/* Rewrite destination. */
- if ((ctx->user_ip6[0] & 0xFFFF) == bpf_htons(0xFACE) &&
- ctx->user_ip6[0] >> 16 == bpf_htons(0xB00C)) {
+ if (ctx->user_ip6[0] == bpf_htonl(0xFACEB00C)) {
ctx->user_ip6[0] = bpf_htonl(DST_REWRITE_IP6_0);
ctx->user_ip6[1] = bpf_htonl(DST_REWRITE_IP6_1);
ctx->user_ip6[2] = bpf_htonl(DST_REWRITE_IP6_2);
diff --git a/tools/testing/selftests/bpf/test_btf_dump.c b/tools/testing/selftests/bpf/test_btf_dump.c
index 8f850823d35f..6e75dd3cb14f 100644
--- a/tools/testing/selftests/bpf/test_btf_dump.c
+++ b/tools/testing/selftests/bpf/test_btf_dump.c
@@ -97,6 +97,13 @@ int test_btf_dump_case(int n, struct btf_dump_test_case *test_case)
}
snprintf(test_file, sizeof(test_file), "progs/%s.c", test_case->name);
+ if (access(test_file, R_OK) == -1)
+ /*
+ * When the test is run with O=, kselftest copies TEST_FILES
+ * without preserving the directory structure.
+ */
+ snprintf(test_file, sizeof(test_file), "%s.c",
+ test_case->name);
/*
* Diff test output and expected test output, contained between
* START-EXPECTED-OUTPUT and END-EXPECTED-OUTPUT lines in test case.
diff --git a/tools/testing/selftests/bpf/test_cgroup_storage.c b/tools/testing/selftests/bpf/test_cgroup_storage.c
index 2fc4625c1a15..655729004391 100644
--- a/tools/testing/selftests/bpf/test_cgroup_storage.c
+++ b/tools/testing/selftests/bpf/test_cgroup_storage.c
@@ -20,9 +20,9 @@ int main(int argc, char **argv)
BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_get_local_storage),
- BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1),
- BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0),
+ BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0),
BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */
BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
BPF_FUNC_get_local_storage),
BPF_MOV64_IMM(BPF_REG_1, 1),
BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_1, 0),
- BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0x1),
BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
BPF_EXIT_INSN(),
diff --git a/tools/testing/selftests/bpf/test_sock.c b/tools/testing/selftests/bpf/test_sock.c
index fb679ac3d4b0..0e6652733462 100644
--- a/tools/testing/selftests/bpf/test_sock.c
+++ b/tools/testing/selftests/bpf/test_sock.c
@@ -13,6 +13,7 @@
#include <bpf/bpf.h>
#include "cgroup_helpers.h"
+#include "bpf_endian.h"
#include "bpf_rlimit.h"
#include "bpf_util.h"
@@ -232,7 +233,8 @@ static struct sock_test tests[] = {
/* if (ip == expected && port == expected) */
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock, src_ip6[3])),
- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x01000000, 4),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7,
+ __bpf_constant_ntohl(0x00000001), 4),
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock, src_port)),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x2001, 2),
@@ -261,7 +263,8 @@ static struct sock_test tests[] = {
/* if (ip == expected && port == expected) */
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock, src_ip4)),
- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x0100007F, 4),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7,
+ __bpf_constant_ntohl(0x7F000001), 4),
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock, src_port)),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x1002, 2),
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan.sh b/tools/testing/selftests/bpf/test_xdp_vlan.sh
index 51a3a31d1aac..bb8b0da91686 100755
--- a/tools/testing/selftests/bpf/test_xdp_vlan.sh
+++ b/tools/testing/selftests/bpf/test_xdp_vlan.sh
@@ -1,6 +1,14 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Author: Jesper Dangaard Brouer <hawk@kernel.org>
-TESTNAME=xdp_vlan
+# Allow wrapper scripts to name test
+if [ -z "$TESTNAME" ]; then
+ TESTNAME=xdp_vlan
+fi
+
+# Default XDP mode
+XDP_MODE=xdpgeneric
usage() {
echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
@@ -9,9 +17,23 @@ usage() {
echo " -v | --verbose : Verbose"
echo " --flush : Flush before starting (e.g. after --interactive)"
echo " --interactive : Keep netns setup running after test-run"
+ echo " --mode=XXX : Choose XDP mode (xdp | xdpgeneric | xdpdrv)"
echo ""
}
+valid_xdp_mode()
+{
+ local mode=$1
+
+ case "$mode" in
+ xdpgeneric | xdpdrv | xdp)
+ return 0
+ ;;
+ *)
+ return 1
+ esac
+}
+
cleanup()
{
local status=$?
@@ -37,7 +59,7 @@ cleanup()
# Using external program "getopt" to get --long-options
OPTIONS=$(getopt -o hvfi: \
- --long verbose,flush,help,interactive,debug -- "$@")
+ --long verbose,flush,help,interactive,debug,mode: -- "$@")
if (( $? != 0 )); then
usage
echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
@@ -60,6 +82,11 @@ while true; do
cleanup
shift
;;
+ --mode )
+ shift
+ XDP_MODE=$1
+ shift
+ ;;
-- )
shift
break
@@ -81,8 +108,14 @@ if [ "$EUID" -ne 0 ]; then
exit 1
fi
-ip link set dev lo xdp off 2>/dev/null > /dev/null
-if [ $? -ne 0 ];then
+valid_xdp_mode $XDP_MODE
+if [ $? -ne 0 ]; then
+ echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"
+ exit 1
+fi
+
+ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
+if [ $? -ne 0 ]; then
echo "selftests: $TESTNAME [SKIP] need ip xdp support"
exit 0
fi
@@ -155,7 +188,7 @@ ip netns exec ns2 ip link set lo up
# At this point, the hosts cannot reach each-other,
# because ns2 are using VLAN tags on the packets.
-ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Okay ping fails"'
+ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First ping must fail"'
# Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
@@ -166,7 +199,7 @@ export FILE=test_xdp_vlan.o
# First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
export XDP_PROG=xdp_vlan_change
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
# In ns1: egress use TC to add back VLAN tag 4011
# (del cmd)
@@ -177,8 +210,8 @@ ip netns exec ns1 tc filter add dev $DEVNS1 egress \
prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
# Now the namespaces can reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
# Second test: Replace xdp prog, that fully remove vlan header
#
@@ -187,9 +220,9 @@ ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
# ETH_P_8021Q indication, and this cause overwriting of our changes.
#
export XDP_PROG=xdp_vlan_remove_outer2
-ip netns exec ns1 ip link set $DEVNS1 xdp off
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE off
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
# Now the namespaces should still be able reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
new file mode 100755
index 000000000000..c515326d6d59
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test generic-XDP
+export TESTNAME=xdp_vlan_mode_generic
+./test_xdp_vlan.sh --mode=xdpgeneric
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
new file mode 100755
index 000000000000..5cf7ce1f16c1
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test native-XDP
+export TESTNAME=xdp_vlan_mode_native
+./test_xdp_vlan.sh --mode=xdpdrv
diff --git a/tools/testing/selftests/bpf/verifier/ctx_skb.c b/tools/testing/selftests/bpf/verifier/ctx_skb.c
index b0fda2877119..d438193804b2 100644
--- a/tools/testing/selftests/bpf/verifier/ctx_skb.c
+++ b/tools/testing/selftests/bpf/verifier/ctx_skb.c
@@ -975,6 +975,17 @@
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
},
{
+ "read gso_segs from CGROUP_SKB",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
+ offsetof(struct __sk_buff, gso_segs)),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+},
+{
"write gso_segs from CGROUP_SKB",
.insns = {
BPF_MOV64_IMM(BPF_REG_0, 0),
diff --git a/tools/testing/selftests/bpf/verifier/loops1.c b/tools/testing/selftests/bpf/verifier/loops1.c
index 5e980a5ab69d..1fc4e61e9f9f 100644
--- a/tools/testing/selftests/bpf/verifier/loops1.c
+++ b/tools/testing/selftests/bpf/verifier/loops1.c
@@ -159,3 +159,31 @@
.errstr = "loop detected",
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
+{
+ "not-taken loop with back jump to 1st insn",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_0, 123),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, -2),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_XDP,
+ .retval = 123,
+},
+{
+ "taken loop with back jump to 1st insn",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_1, 10),
+ BPF_MOV64_IMM(BPF_REG_2, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1),
+ BPF_EXIT_INSN(),
+ BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
+ BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, -3),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_XDP,
+ .retval = 55,
+},
diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c
index 4c223266299a..bdb69599c4bd 100644
--- a/tools/testing/selftests/cgroup/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/cgroup_util.c
@@ -191,8 +191,7 @@ int cg_find_unified_root(char *root, size_t len)
strtok(NULL, delim);
strtok(NULL, delim);
- if (strcmp(fs, "cgroup") == 0 &&
- strcmp(type, "cgroup2") == 0) {
+ if (strcmp(type, "cgroup2") == 0) {
strncpy(root, mount, len);
return 0;
}
diff --git a/tools/testing/selftests/cgroup/test_freezer.c b/tools/testing/selftests/cgroup/test_freezer.c
index 8219a30853d2..0fc1b6d4b0f9 100644
--- a/tools/testing/selftests/cgroup/test_freezer.c
+++ b/tools/testing/selftests/cgroup/test_freezer.c
@@ -448,6 +448,59 @@ cleanup:
}
/*
+ * The test creates a cgroups and freezes it. Then it creates a child cgroup
+ * and populates it with a task. After that it checks that the child cgroup
+ * is frozen and the parent cgroup remains frozen too.
+ */
+static int test_cgfreezer_mkdir(const char *root)
+{
+ int ret = KSFT_FAIL;
+ char *parent, *child = NULL;
+ int pid;
+
+ parent = cg_name(root, "cg_test_mkdir_A");
+ if (!parent)
+ goto cleanup;
+
+ child = cg_name(parent, "cg_test_mkdir_B");
+ if (!child)
+ goto cleanup;
+
+ if (cg_create(parent))
+ goto cleanup;
+
+ if (cg_freeze_wait(parent, true))
+ goto cleanup;
+
+ if (cg_create(child))
+ goto cleanup;
+
+ pid = cg_run_nowait(child, child_fn, NULL);
+ if (pid < 0)
+ goto cleanup;
+
+ if (cg_wait_for_proc_count(child, 1))
+ goto cleanup;
+
+ if (cg_check_frozen(child, true))
+ goto cleanup;
+
+ if (cg_check_frozen(parent, true))
+ goto cleanup;
+
+ ret = KSFT_PASS;
+
+cleanup:
+ if (child)
+ cg_destroy(child);
+ free(child);
+ if (parent)
+ cg_destroy(parent);
+ free(parent);
+ return ret;
+}
+
+/*
* The test creates two nested cgroups, freezes the parent
* and removes the child. Then it checks that the parent cgroup
* remains frozen and it's possible to create a new child
@@ -815,6 +868,7 @@ struct cgfreezer_test {
T(test_cgfreezer_simple),
T(test_cgfreezer_tree),
T(test_cgfreezer_forkbomb),
+ T(test_cgfreezer_mkdir),
T(test_cgfreezer_rmdir),
T(test_cgfreezer_migrate),
T(test_cgfreezer_ptrace),
diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
index 71231ad2dbfb..47315fe48d5a 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
@@ -262,7 +262,7 @@ test_mc_aware()
stop_traffic
- log_test "UC performace under MC overload"
+ log_test "UC performance under MC overload"
echo "UC-only throughput $(humanize $ucth1)"
echo "UC+MC throughput $(humanize $ucth2)"
@@ -316,7 +316,7 @@ test_uc_aware()
stop_traffic
- log_test "MC performace under UC overload"
+ log_test "MC performance under UC overload"
echo " ingress UC throughput $(humanize ${uc_ir})"
echo " egress UC throughput $(humanize ${uc_er})"
echo " sent $attempts BC ARPs, got $passes responses"
diff --git a/tools/testing/selftests/kmod/kmod.sh b/tools/testing/selftests/kmod/kmod.sh
index 0a76314b4414..8b944cf042f6 100755
--- a/tools/testing/selftests/kmod/kmod.sh
+++ b/tools/testing/selftests/kmod/kmod.sh
@@ -28,7 +28,7 @@
# override by exporting to your environment prior running this script.
# For instance this script assumes you do not have xfs loaded upon boot.
# If this is false, export DEFAULT_KMOD_FS="ext4" prior to running this
-# script if the filesyste module you don't have loaded upon bootup
+# script if the filesystem module you don't have loaded upon bootup
# is ext4 instead. Refer to allow_user_defaults() for a list of user
# override variables possible.
#
@@ -263,7 +263,7 @@ config_get_test_result()
config_reset()
{
if ! echo -n "1" >"$DIR"/reset; then
- echo "$0: reset shuld have worked" >&2
+ echo "$0: reset should have worked" >&2
exit 1
fi
}
@@ -488,7 +488,7 @@ usage()
echo Example uses:
echo
echo "${TEST_NAME}.sh -- executes all tests"
- echo "${TEST_NAME}.sh -t 0008 -- Executes test ID 0008 number of times is recomended"
+ echo "${TEST_NAME}.sh -t 0008 -- Executes test ID 0008 number of times is recommended"
echo "${TEST_NAME}.sh -w 0008 -- Watch test ID 0008 run until an error occurs"
echo "${TEST_NAME}.sh -s 0008 -- Run test ID 0008 once"
echo "${TEST_NAME}.sh -c 0008 3 -- Run test ID 0008 three times"
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index ec15c4f6af55..0ac49d91a260 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -10,6 +10,7 @@
#ifndef __KSELFTEST_H
#define __KSELFTEST_H
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
@@ -81,58 +82,68 @@ static inline void ksft_print_cnts(void)
static inline void ksft_print_msg(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
va_start(args, msg);
printf("# ");
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
static inline void ksft_test_result_pass(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
ksft_cnt.ksft_pass++;
va_start(args, msg);
printf("ok %d ", ksft_test_num());
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
static inline void ksft_test_result_fail(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
ksft_cnt.ksft_fail++;
va_start(args, msg);
printf("not ok %d ", ksft_test_num());
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
static inline void ksft_test_result_skip(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
ksft_cnt.ksft_xskip++;
va_start(args, msg);
printf("not ok %d # SKIP ", ksft_test_num());
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
static inline void ksft_test_result_error(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
ksft_cnt.ksft_error++;
va_start(args, msg);
printf("not ok %d # error ", ksft_test_num());
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
}
@@ -152,10 +163,12 @@ static inline int ksft_exit_fail(void)
static inline int ksft_exit_fail_msg(const char *msg, ...)
{
+ int saved_errno = errno;
va_list args;
va_start(args, msg);
printf("Bail out! ");
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
@@ -178,10 +191,12 @@ static inline int ksft_exit_xpass(void)
static inline int ksft_exit_skip(const char *msg, ...)
{
if (msg) {
+ int saved_errno = errno;
va_list args;
va_start(args, msg);
printf("not ok %d # SKIP ", 1 + ksft_test_num());
+ errno = saved_errno;
vprintf(msg, args);
va_end(args);
} else {
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 41266af0d3dc..b35da375530a 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -1,7 +1,7 @@
+/s390x/sync_regs_test
/x86_64/cr4_cpuid_sync_test
/x86_64/evmcs_test
/x86_64/hyperv_cpuid
-/x86_64/kvm_create_max_vcpus
/x86_64/mmio_warning_test
/x86_64/platform_info_test
/x86_64/set_sregs_test
@@ -13,3 +13,4 @@
/x86_64/vmx_tsc_adjust_test
/clear_dirty_log_test
/dirty_log_test
+/kvm_create_max_vcpus
diff --git a/tools/testing/selftests/kvm/config b/tools/testing/selftests/kvm/config
new file mode 100644
index 000000000000..63ed533f73d6
--- /dev/null
+++ b/tools/testing/selftests/kvm/config
@@ -0,0 +1,3 @@
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
diff --git a/tools/testing/selftests/kvm/include/evmcs.h b/tools/testing/selftests/kvm/include/evmcs.h
index 4059014d93ea..4912d23844bc 100644
--- a/tools/testing/selftests/kvm/include/evmcs.h
+++ b/tools/testing/selftests/kvm/include/evmcs.h
@@ -220,6 +220,8 @@ struct hv_enlightened_vmcs {
struct hv_enlightened_vmcs *current_evmcs;
struct hv_vp_assist_page *current_vp_assist;
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id);
+
static inline int enable_vp_assist(uint64_t vp_assist_pa, void *vp_assist)
{
u64 val = (vp_assist_pa & HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK) |
diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
index 6cb34a0fa200..0a5e487dbc50 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
@@ -1060,9 +1060,11 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
r);
- r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
- TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
- r);
+ if (kvm_check_cap(KVM_CAP_XCRS)) {
+ r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
+ TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
+ r);
+ }
r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
@@ -1103,9 +1105,11 @@ void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *s
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
r);
- r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
- TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
- r);
+ if (kvm_check_cap(KVM_CAP_XCRS)) {
+ r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
+ TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
+ r);
+ }
r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
diff --git a/tools/testing/selftests/kvm/lib/x86_64/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
index 204f847bd065..9cef0455b819 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/vmx.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
@@ -12,6 +12,26 @@
bool enable_evmcs;
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id)
+{
+ uint16_t evmcs_ver;
+
+ struct kvm_enable_cap enable_evmcs_cap = {
+ .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
+ .args[0] = (unsigned long)&evmcs_ver
+ };
+
+ vcpu_ioctl(vm, vcpu_id, KVM_ENABLE_CAP, &enable_evmcs_cap);
+
+ /* KVM should return supported EVMCS version range */
+ TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
+ (evmcs_ver & 0xff) > 0,
+ "Incorrect EVMCS version range: %x:%x\n",
+ evmcs_ver & 0xff, evmcs_ver >> 8);
+
+ return evmcs_ver;
+}
+
/* Allocate memory regions for nested VMX tests.
*
* Input Args:
diff --git a/tools/testing/selftests/kvm/x86_64/evmcs_test.c b/tools/testing/selftests/kvm/x86_64/evmcs_test.c
index f95c08343b48..92915e6408e7 100644
--- a/tools/testing/selftests/kvm/x86_64/evmcs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/evmcs_test.c
@@ -79,11 +79,6 @@ int main(int argc, char *argv[])
struct kvm_x86_state *state;
struct ucall uc;
int stage;
- uint16_t evmcs_ver;
- struct kvm_enable_cap enable_evmcs_cap = {
- .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
- .args[0] = (unsigned long)&evmcs_ver
- };
/* Create VM */
vm = vm_create_default(VCPU_ID, 0, guest_code);
@@ -96,13 +91,7 @@ int main(int argc, char *argv[])
exit(KSFT_SKIP);
}
- vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
- /* KVM should return supported EVMCS version range */
- TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
- (evmcs_ver & 0xff) > 0,
- "Incorrect EVMCS version range: %x:%x\n",
- evmcs_ver & 0xff, evmcs_ver >> 8);
+ vcpu_enable_evmcs(vm, VCPU_ID);
run = vcpu_state(vm, VCPU_ID);
@@ -146,7 +135,7 @@ int main(int argc, char *argv[])
kvm_vm_restart(vm, O_RDWR);
vm_vcpu_add(vm, VCPU_ID);
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
- vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
+ vcpu_enable_evmcs(vm, VCPU_ID);
vcpu_load_state(vm, VCPU_ID, state);
run = vcpu_state(vm, VCPU_ID);
free(state);
diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
index f72b3043db0e..ee59831fbc98 100644
--- a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
+++ b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
@@ -18,6 +18,7 @@
#include "test_util.h"
#include "kvm_util.h"
#include "processor.h"
+#include "vmx.h"
#define VCPU_ID 0
@@ -106,12 +107,7 @@ int main(int argc, char *argv[])
{
struct kvm_vm *vm;
int rv;
- uint16_t evmcs_ver;
struct kvm_cpuid2 *hv_cpuid_entries;
- struct kvm_enable_cap enable_evmcs_cap = {
- .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
- .args[0] = (unsigned long)&evmcs_ver
- };
/* Tell stdout not to buffer its content */
setbuf(stdout, NULL);
@@ -136,14 +132,14 @@ int main(int argc, char *argv[])
free(hv_cpuid_entries);
- rv = _vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
- if (rv) {
+ if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
fprintf(stderr,
"Enlightened VMCS is unsupported, skip related test\n");
goto vm_free;
}
+ vcpu_enable_evmcs(vm, VCPU_ID);
+
hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
if (!hv_cpuid_entries)
return 1;
diff --git a/tools/testing/selftests/kvm/x86_64/platform_info_test.c b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
index 40050e44ec0a..f9334bd3cce9 100644
--- a/tools/testing/selftests/kvm/x86_64/platform_info_test.c
+++ b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
@@ -99,8 +99,8 @@ int main(int argc, char *argv[])
msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
- test_msr_platform_info_disabled(vm);
test_msr_platform_info_enabled(vm);
+ test_msr_platform_info_disabled(vm);
vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
index ed7218d166da..853e370e8a39 100644
--- a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
+++ b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
@@ -25,24 +25,17 @@
#define VMCS12_REVISION 0x11e57ed0
#define VCPU_ID 5
+bool have_evmcs;
+
void test_nested_state(struct kvm_vm *vm, struct kvm_nested_state *state)
{
- volatile struct kvm_run *run;
-
vcpu_nested_state_set(vm, VCPU_ID, state, false);
- run = vcpu_state(vm, VCPU_ID);
- vcpu_run(vm, VCPU_ID);
- TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
- "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
- run->exit_reason,
- exit_reason_str(run->exit_reason));
}
void test_nested_state_expect_errno(struct kvm_vm *vm,
struct kvm_nested_state *state,
int expected_errno)
{
- volatile struct kvm_run *run;
int rv;
rv = vcpu_nested_state_set(vm, VCPU_ID, state, true);
@@ -50,12 +43,6 @@ void test_nested_state_expect_errno(struct kvm_vm *vm,
"Expected %s (%d) from vcpu_nested_state_set but got rv: %i errno: %s (%d)",
strerror(expected_errno), expected_errno, rv, strerror(errno),
errno);
- run = vcpu_state(vm, VCPU_ID);
- vcpu_run(vm, VCPU_ID);
- TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
- "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
- run->exit_reason,
- exit_reason_str(run->exit_reason));
}
void test_nested_state_expect_einval(struct kvm_vm *vm,
@@ -90,8 +77,9 @@ void set_default_vmx_state(struct kvm_nested_state *state, int size)
{
memset(state, 0, size);
state->flags = KVM_STATE_NESTED_GUEST_MODE |
- KVM_STATE_NESTED_RUN_PENDING |
- KVM_STATE_NESTED_EVMCS;
+ KVM_STATE_NESTED_RUN_PENDING;
+ if (have_evmcs)
+ state->flags |= KVM_STATE_NESTED_EVMCS;
state->format = 0;
state->size = size;
state->hdr.vmx.vmxon_pa = 0x1000;
@@ -141,13 +129,19 @@ void test_vmx_nested_state(struct kvm_vm *vm)
/*
* Setting vmxon_pa == -1ull and vmcs_pa == -1ull exits early without
* setting the nested state but flags other than eVMCS must be clear.
+ * The eVMCS flag can be set if the enlightened VMCS capability has
+ * been enabled.
*/
set_default_vmx_state(state, state_sz);
state->hdr.vmx.vmxon_pa = -1ull;
state->hdr.vmx.vmcs12_pa = -1ull;
test_nested_state_expect_einval(vm, state);
- state->flags = KVM_STATE_NESTED_EVMCS;
+ state->flags &= KVM_STATE_NESTED_EVMCS;
+ if (have_evmcs) {
+ test_nested_state_expect_einval(vm, state);
+ vcpu_enable_evmcs(vm, VCPU_ID);
+ }
test_nested_state(vm, state);
/* It is invalid to have vmxon_pa == -1ull and SMM flags non-zero. */
@@ -232,6 +226,8 @@ int main(int argc, char *argv[])
struct kvm_nested_state state;
struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
+ have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS);
+
if (!kvm_check_cap(KVM_CAP_NESTED_STATE)) {
printf("KVM_CAP_NESTED_STATE not available, skipping test\n");
exit(KSFT_SKIP);
diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh
index 30195449c63c..79b0affd21fb 100644
--- a/tools/testing/selftests/livepatch/functions.sh
+++ b/tools/testing/selftests/livepatch/functions.sh
@@ -13,6 +13,14 @@ function log() {
echo "$1" > /dev/kmsg
}
+# skip(msg) - testing can't proceed
+# msg - explanation
+function skip() {
+ log "SKIP: $1"
+ echo "SKIP: $1" >&2
+ exit 4
+}
+
# die(msg) - game over, man
# msg - dying words
function die() {
@@ -21,13 +29,27 @@ function die() {
exit 1
}
-# set_dynamic_debug() - setup kernel dynamic debug
-# TODO - push and pop this config?
+function push_dynamic_debug() {
+ DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \
+ awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}')
+}
+
+function pop_dynamic_debug() {
+ if [[ -n "$DYNAMIC_DEBUG" ]]; then
+ echo -n "$DYNAMIC_DEBUG" > /sys/kernel/debug/dynamic_debug/control
+ fi
+}
+
+# set_dynamic_debug() - save the current dynamic debug config and tweak
+# it for the self-tests. Set a script exit trap
+# that restores the original config.
function set_dynamic_debug() {
- cat << EOF > /sys/kernel/debug/dynamic_debug/control
-file kernel/livepatch/* +p
-func klp_try_switch_task -p
-EOF
+ push_dynamic_debug
+ trap pop_dynamic_debug EXIT INT TERM HUP
+ cat <<-EOF > /sys/kernel/debug/dynamic_debug/control
+ file kernel/livepatch/* +p
+ func klp_try_switch_task -p
+ EOF
}
# loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES,
@@ -43,6 +65,12 @@ function loop_until() {
done
}
+function assert_mod() {
+ local mod="$1"
+
+ modprobe --dry-run "$mod" &>/dev/null
+}
+
function is_livepatch_mod() {
local mod="$1"
@@ -75,6 +103,9 @@ function __load_mod() {
function load_mod() {
local mod="$1"; shift
+ assert_mod "$mod" ||
+ skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root"
+
is_livepatch_mod "$mod" &&
die "use load_lp() to load the livepatch module $mod"
@@ -88,6 +119,9 @@ function load_mod() {
function load_lp_nowait() {
local mod="$1"; shift
+ assert_mod "$mod" ||
+ skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root"
+
is_livepatch_mod "$mod" ||
die "module $mod is not a livepatch"
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 4ce0bc1612f5..c7cced739c34 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -17,7 +17,7 @@ tcp_inq
tls
txring_overwrite
ip_defrag
+ipv6_flowlabel
+ipv6_flowlabel_mgr
so_txtime
-flowlabel
-flowlabel_mgr
tcp_fastopen_backup_key
diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
index c5c93d5fb3ad..f9ebeac1e6f2 100755
--- a/tools/testing/selftests/net/fib_nexthops.sh
+++ b/tools/testing/selftests/net/fib_nexthops.sh
@@ -212,6 +212,8 @@ check_output()
printf " ${out}\n"
printf " Expected:\n"
printf " ${expected}\n\n"
+ else
+ echo " WARNING: Unexpected route entry"
fi
fi
@@ -274,7 +276,7 @@ ipv6_fcnal()
run_cmd "$IP nexthop get id 52"
log_test $? 0 "Get nexthop by id"
- check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1"
+ check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
run_cmd "$IP nexthop del id 52"
log_test $? 0 "Delete nexthop by id"
@@ -479,12 +481,12 @@ ipv6_fcnal_runtime()
run_cmd "$IP -6 nexthop add id 85 dev veth1"
run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
log_test $? 0 "IPv6 route with device only nexthop"
- check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1"
+ check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024 pref medium"
run_cmd "$IP nexthop add id 123 group 81/85"
run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
- check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 nexthop via 2001:db8:91::2 dev veth1 nexthop dev veth1"
+ check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 123 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop dev veth1 weight 1 pref medium"
#
# IPv6 route with v4 nexthop - not allowed
@@ -538,7 +540,7 @@ ipv4_fcnal()
run_cmd "$IP nexthop get id 12"
log_test $? 0 "Get nexthop by id"
- check_nexthop "id 12" "id 12 via 172.16.1.2 src 172.16.1.1 dev veth1 scope link"
+ check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
run_cmd "$IP nexthop del id 12"
log_test $? 0 "Delete nexthop by id"
@@ -685,7 +687,7 @@ ipv4_withv6_fcnal()
set +e
run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
log_test $? 0 "IPv6 nexthop with IPv4 route"
- check_route "172.16.101.1" "172.16.101.1 nhid 11 via ${lladdr} dev veth1"
+ check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
set -e
run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
@@ -694,11 +696,11 @@ ipv4_withv6_fcnal()
run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
log_test $? 0 "IPv6 nexthop with IPv4 route"
- check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
+ check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
log_test $? 0 "IPv4 route with IPv6 gateway"
- check_route "172.16.101.1" "172.16.101.1 via ${lladdr} dev veth1"
+ check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
log_test $? 2 "IPv4 route with invalid IPv6 gateway"
@@ -785,10 +787,10 @@ ipv4_fcnal_runtime()
log_test $? 0 "IPv4 route with device only nexthop"
check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
- run_cmd "$IP nexthop add id 122 group 21/85"
- run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
+ run_cmd "$IP nexthop add id 123 group 21/85"
+ run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
- check_route "172.16.101.1" "172.16.101.1 nhid 85 nexthop via 172.16.1.2 dev veth1 nexthop dev veth1"
+ check_route "172.16.101.1" "172.16.101.1 nhid 123 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop dev veth1 weight 1"
#
# IPv4 with IPv6
@@ -820,7 +822,7 @@ ipv4_fcnal_runtime()
run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
- check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
+ check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
log_test $? 0 "IPv6 nexthop with IPv4 route"
diff --git a/tools/testing/selftests/net/forwarding/gre_multipath.sh b/tools/testing/selftests/net/forwarding/gre_multipath.sh
index cca2baa03fb8..a8d8e8b3dc81 100755
--- a/tools/testing/selftests/net/forwarding/gre_multipath.sh
+++ b/tools/testing/selftests/net/forwarding/gre_multipath.sh
@@ -93,18 +93,10 @@ sw1_create()
ip route add vrf v$ol1 192.0.2.16/28 \
nexthop dev g1a \
nexthop dev g1b
-
- tc qdisc add dev $ul1 clsact
- tc filter add dev $ul1 egress pref 111 prot ipv4 \
- flower dst_ip 192.0.2.66 action pass
- tc filter add dev $ul1 egress pref 222 prot ipv4 \
- flower dst_ip 192.0.2.82 action pass
}
sw1_destroy()
{
- tc qdisc del dev $ul1 clsact
-
ip route del vrf v$ol1 192.0.2.16/28
ip route del vrf v$ol1 192.0.2.82/32 via 192.0.2.146
@@ -139,10 +131,18 @@ sw2_create()
ip route add vrf v$ol2 192.0.2.0/28 \
nexthop dev g2a \
nexthop dev g2b
+
+ tc qdisc add dev $ul2 clsact
+ tc filter add dev $ul2 ingress pref 111 prot 802.1Q \
+ flower vlan_id 111 action pass
+ tc filter add dev $ul2 ingress pref 222 prot 802.1Q \
+ flower vlan_id 222 action pass
}
sw2_destroy()
{
+ tc qdisc del dev $ul2 clsact
+
ip route del vrf v$ol2 192.0.2.0/28
ip route del vrf v$ol2 192.0.2.81/32 via 192.0.2.145
@@ -187,12 +187,16 @@ setup_prepare()
sw1_create
sw2_create
h2_create
+
+ forwarding_enable
}
cleanup()
{
pre_cleanup
+ forwarding_restore
+
h2_destroy
sw2_destroy
sw1_destroy
@@ -211,15 +215,15 @@ multipath4_test()
nexthop dev g1a weight $weight1 \
nexthop dev g1b weight $weight2
- local t0_111=$(tc_rule_stats_get $ul1 111 egress)
- local t0_222=$(tc_rule_stats_get $ul1 222 egress)
+ local t0_111=$(tc_rule_stats_get $ul2 111 ingress)
+ local t0_222=$(tc_rule_stats_get $ul2 222 ingress)
ip vrf exec v$h1 \
$MZ $h1 -q -p 64 -A 192.0.2.1 -B 192.0.2.18 \
-d 1msec -t udp "sp=1024,dp=0-32768"
- local t1_111=$(tc_rule_stats_get $ul1 111 egress)
- local t1_222=$(tc_rule_stats_get $ul1 222 egress)
+ local t1_111=$(tc_rule_stats_get $ul2 111 ingress)
+ local t1_222=$(tc_rule_stats_get $ul2 222 ingress)
local d111=$((t1_111 - t0_111))
local d222=$((t1_222 - t0_222))
diff --git a/tools/testing/selftests/net/tcp_fastopen_backup_key.sh b/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
index 41476399e184..f6e65674b83c 100755
--- a/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
+++ b/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
@@ -30,7 +30,7 @@ do_test() {
ip netns exec "${NETNS}" ./tcp_fastopen_backup_key "$1"
val=$(ip netns exec "${NETNS}" nstat -az | \
grep TcpExtTCPFastOpenPassiveFail | awk '{print $2}')
- if [ $val -ne 0 ]; then
+ if [ "$val" != 0 ]; then
echo "FAIL: TcpExtTCPFastOpenPassiveFail non-zero"
return 1
fi
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 090fff9dbc48..4c285b6e1db8 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -25,6 +25,80 @@
#define TLS_PAYLOAD_MAX_LEN 16384
#define SOL_TLS 282
+#ifndef ENOTSUPP
+#define ENOTSUPP 524
+#endif
+
+FIXTURE(tls_basic)
+{
+ int fd, cfd;
+ bool notls;
+};
+
+FIXTURE_SETUP(tls_basic)
+{
+ struct sockaddr_in addr;
+ socklen_t len;
+ int sfd, ret;
+
+ self->notls = false;
+ len = sizeof(addr);
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+
+ self->fd = socket(AF_INET, SOCK_STREAM, 0);
+ sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ ret = bind(sfd, &addr, sizeof(addr));
+ ASSERT_EQ(ret, 0);
+ ret = listen(sfd, 10);
+ ASSERT_EQ(ret, 0);
+
+ ret = getsockname(sfd, &addr, &len);
+ ASSERT_EQ(ret, 0);
+
+ ret = connect(self->fd, &addr, sizeof(addr));
+ ASSERT_EQ(ret, 0);
+
+ self->cfd = accept(sfd, &addr, &len);
+ ASSERT_GE(self->cfd, 0);
+
+ close(sfd);
+
+ ret = setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ if (ret != 0) {
+ ASSERT_EQ(errno, ENOENT);
+ self->notls = true;
+ printf("Failure setting TCP_ULP, testing without tls\n");
+ return;
+ }
+
+ ret = setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ ASSERT_EQ(ret, 0);
+}
+
+FIXTURE_TEARDOWN(tls_basic)
+{
+ close(self->fd);
+ close(self->cfd);
+}
+
+/* Send some data through with ULP but no keys */
+TEST_F(tls_basic, base_base)
+{
+ char const *test_str = "test_read";
+ int send_len = 10;
+ char buf[10];
+
+ ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+ EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
FIXTURE(tls)
{
int fd, cfd;
@@ -165,6 +239,16 @@ TEST_F(tls, msg_more)
EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
}
+TEST_F(tls, msg_more_unsent)
+{
+ char const *test_str = "test_read";
+ int send_len = 10;
+ char buf[10];
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+ EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_DONTWAIT), -1);
+}
+
TEST_F(tls, sendmsg_single)
{
struct msghdr msg;
@@ -610,6 +694,42 @@ TEST_F(tls, recv_lowat)
EXPECT_EQ(memcmp(send_mem, recv_mem + 10, 5), 0);
}
+TEST_F(tls, bidir)
+{
+ char const *test_str = "test_read";
+ int send_len = 10;
+ char buf[10];
+ int ret;
+
+ if (!self->notls) {
+ struct tls12_crypto_info_aes_gcm_128 tls12;
+
+ memset(&tls12, 0, sizeof(tls12));
+ tls12.info.version = TLS_1_3_VERSION;
+ tls12.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+
+ ret = setsockopt(self->fd, SOL_TLS, TLS_RX, &tls12,
+ sizeof(tls12));
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(self->cfd, SOL_TLS, TLS_TX, &tls12,
+ sizeof(tls12));
+ ASSERT_EQ(ret, 0);
+ }
+
+ ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+ EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+ memset(buf, 0, sizeof(buf));
+
+ EXPECT_EQ(send(self->cfd, test_str, send_len, 0), send_len);
+ EXPECT_NE(recv(self->fd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
TEST_F(tls, pollin)
{
char const *test_str = "test_poll";
@@ -837,6 +957,109 @@ TEST_F(tls, control_msg)
EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
}
+TEST_F(tls, shutdown)
+{
+ char const *test_str = "test_read";
+ int send_len = 10;
+ char buf[10];
+
+ ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+ EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+ shutdown(self->fd, SHUT_RDWR);
+ shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_unsent)
+{
+ char const *test_str = "test_read";
+ int send_len = 10;
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+
+ shutdown(self->fd, SHUT_RDWR);
+ shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_reuse)
+{
+ struct sockaddr_in addr;
+ int ret;
+
+ shutdown(self->fd, SHUT_RDWR);
+ shutdown(self->cfd, SHUT_RDWR);
+ close(self->cfd);
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+
+ ret = bind(self->fd, &addr, sizeof(addr));
+ EXPECT_EQ(ret, 0);
+ ret = listen(self->fd, 10);
+ EXPECT_EQ(ret, -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ ret = connect(self->fd, &addr, sizeof(addr));
+ EXPECT_EQ(ret, -1);
+ EXPECT_EQ(errno, EISCONN);
+}
+
+TEST(non_established) {
+ struct tls12_crypto_info_aes_gcm_256 tls12;
+ struct sockaddr_in addr;
+ int sfd, ret, fd;
+ socklen_t len;
+
+ len = sizeof(addr);
+
+ memset(&tls12, 0, sizeof(tls12));
+ tls12.info.version = TLS_1_2_VERSION;
+ tls12.info.cipher_type = TLS_CIPHER_AES_GCM_256;
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ ret = bind(sfd, &addr, sizeof(addr));
+ ASSERT_EQ(ret, 0);
+ ret = listen(sfd, 10);
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ EXPECT_EQ(ret, -1);
+ /* TLS ULP not supported */
+ if (errno == ENOENT)
+ return;
+ EXPECT_EQ(errno, ENOTSUPP);
+
+ ret = setsockopt(sfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ EXPECT_EQ(ret, -1);
+ EXPECT_EQ(errno, ENOTSUPP);
+
+ ret = getsockname(sfd, &addr, &len);
+ ASSERT_EQ(ret, 0);
+
+ ret = connect(fd, &addr, sizeof(addr));
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+ EXPECT_EQ(ret, -1);
+ EXPECT_EQ(errno, EEXIST);
+
+ close(fd);
+ close(sfd);
+}
+
TEST(keysizes) {
struct tls12_crypto_info_aes_gcm_256 tls12;
struct sockaddr_in addr;
diff --git a/tools/testing/selftests/net/xfrm_policy.sh b/tools/testing/selftests/net/xfrm_policy.sh
index 5445943bf07f..7a1bf94c5bd3 100755
--- a/tools/testing/selftests/net/xfrm_policy.sh
+++ b/tools/testing/selftests/net/xfrm_policy.sh
@@ -106,6 +106,13 @@ do_overlap()
#
# 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
+
+ # similar to above: add policies (with partially random address), with shrinking prefixes.
+ for p in 29 28 27;do
+ for k in $(seq 1 32); do
+ ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null
+ done
+ done
}
do_esp_policy_get_check() {
diff --git a/tools/testing/selftests/netfilter/nft_flowtable.sh b/tools/testing/selftests/netfilter/nft_flowtable.sh
index fe52488a6f72..16571ac1dab4 100755
--- a/tools/testing/selftests/netfilter/nft_flowtable.sh
+++ b/tools/testing/selftests/netfilter/nft_flowtable.sh
@@ -321,4 +321,52 @@ else
ip netns exec nsr1 nft list ruleset
fi
+KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
+KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
+SPI1=$RANDOM
+SPI2=$RANDOM
+
+if [ $SPI1 -eq $SPI2 ]; then
+ SPI2=$((SPI2+1))
+fi
+
+do_esp() {
+ local ns=$1
+ local me=$2
+ local remote=$3
+ local lnet=$4
+ local rnet=$5
+ local spi_out=$6
+ local spi_in=$7
+
+ ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet
+ ip -net $ns xfrm state add src $me dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
+
+ # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+ ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
+ # to fwd decrypted packets after esp processing:
+ ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 1 action allow
+
+}
+
+do_esp nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
+
+do_esp nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
+
+ip netns exec nsr1 nft delete table ip nat
+
+# restore default routes
+ip -net ns2 route del 192.168.10.1 via 10.0.2.1
+ip -net ns2 route add default via 10.0.2.1
+ip -net ns2 route add default via dead:2::1
+
+test_tcp_forwarding ns1 ns2
+if [ $? -eq 0 ] ;then
+ echo "PASS: ipsec tunnel mode for ns1/ns2"
+else
+ echo "FAIL: ipsec tunnel mode for ns1/ns2"
+ ip netns exec nsr1 nft list ruleset 1>&2
+ ip netns exec nsr1 cat /proc/net/xfrm_stat 1>&2
+fi
+
exit $ret
diff --git a/tools/testing/selftests/pidfd/.gitignore b/tools/testing/selftests/pidfd/.gitignore
index 16d84d117bc0..8d069490e17b 100644
--- a/tools/testing/selftests/pidfd/.gitignore
+++ b/tools/testing/selftests/pidfd/.gitignore
@@ -1,2 +1,4 @@
pidfd_open_test
+pidfd_poll_test
pidfd_test
+pidfd_wait
diff --git a/tools/testing/selftests/pidfd/Makefile b/tools/testing/selftests/pidfd/Makefile
index 720b2d884b3c..464c9b76148f 100644
--- a/tools/testing/selftests/pidfd/Makefile
+++ b/tools/testing/selftests/pidfd/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
CFLAGS += -g -I../../../../usr/include/ -lpthread
-TEST_GEN_PROGS := pidfd_test pidfd_open_test
+TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_poll_test pidfd_wait
include ../lib.mk
diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h
index 8452e910463f..c6bc68329f4b 100644
--- a/tools/testing/selftests/pidfd/pidfd.h
+++ b/tools/testing/selftests/pidfd/pidfd.h
@@ -16,6 +16,26 @@
#include "../kselftest.h"
+#ifndef P_PIDFD
+#define P_PIDFD 3
+#endif
+
+#ifndef CLONE_PIDFD
+#define CLONE_PIDFD 0x00001000
+#endif
+
+#ifndef __NR_pidfd_open
+#define __NR_pidfd_open -1
+#endif
+
+#ifndef __NR_pidfd_send_signal
+#define __NR_pidfd_send_signal -1
+#endif
+
+#ifndef __NR_clone3
+#define __NR_clone3 -1
+#endif
+
/*
* The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c
* That means, when it wraps around any pid < 300 will be skipped.
@@ -53,5 +73,15 @@ again:
return WEXITSTATUS(status);
}
+static inline int sys_pidfd_open(pid_t pid, unsigned int flags)
+{
+ return syscall(__NR_pidfd_open, pid, flags);
+}
+
+static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
+ unsigned int flags)
+{
+ return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
+}
#endif /* __PIDFD_H */
diff --git a/tools/testing/selftests/pidfd/pidfd_open_test.c b/tools/testing/selftests/pidfd/pidfd_open_test.c
index 0377133dd6dc..b9fe75fc3e51 100644
--- a/tools/testing/selftests/pidfd/pidfd_open_test.c
+++ b/tools/testing/selftests/pidfd/pidfd_open_test.c
@@ -22,11 +22,6 @@
#include "pidfd.h"
#include "../kselftest.h"
-static inline int sys_pidfd_open(pid_t pid, unsigned int flags)
-{
- return syscall(__NR_pidfd_open, pid, flags);
-}
-
static int safe_int(const char *numstr, int *converted)
{
char *err = NULL;
diff --git a/tools/testing/selftests/pidfd/pidfd_poll_test.c b/tools/testing/selftests/pidfd/pidfd_poll_test.c
new file mode 100644
index 000000000000..4b115444dfe9
--- /dev/null
+++ b/tools/testing/selftests/pidfd/pidfd_poll_test.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "pidfd.h"
+#include "../kselftest.h"
+
+static bool timeout;
+
+static void handle_alarm(int sig)
+{
+ timeout = true;
+}
+
+int main(int argc, char **argv)
+{
+ struct pollfd fds;
+ int iter, nevents;
+ int nr_iterations = 10000;
+
+ fds.events = POLLIN;
+
+ if (argc > 2)
+ ksft_exit_fail_msg("Unexpected command line argument\n");
+
+ if (argc == 2) {
+ nr_iterations = atoi(argv[1]);
+ if (nr_iterations <= 0)
+ ksft_exit_fail_msg("invalid input parameter %s\n",
+ argv[1]);
+ }
+
+ ksft_print_msg("running pidfd poll test for %d iterations\n",
+ nr_iterations);
+
+ for (iter = 0; iter < nr_iterations; iter++) {
+ int pidfd;
+ int child_pid = fork();
+
+ if (child_pid < 0) {
+ if (errno == EAGAIN) {
+ iter--;
+ continue;
+ }
+ ksft_exit_fail_msg(
+ "%s - failed to fork a child process\n",
+ strerror(errno));
+ }
+
+ if (child_pid == 0) {
+ /* Child process just sleeps for a min and exits */
+ sleep(60);
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Parent kills the child and waits for its death */
+ pidfd = sys_pidfd_open(child_pid, 0);
+ if (pidfd < 0)
+ ksft_exit_fail_msg("%s - pidfd_open failed\n",
+ strerror(errno));
+
+ /* Setup 3 sec alarm - plenty of time */
+ if (signal(SIGALRM, handle_alarm) == SIG_ERR)
+ ksft_exit_fail_msg("%s - signal failed\n",
+ strerror(errno));
+ alarm(3);
+
+ /* Send SIGKILL to the child */
+ if (sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0))
+ ksft_exit_fail_msg("%s - pidfd_send_signal failed\n",
+ strerror(errno));
+
+ /* Wait for the death notification */
+ fds.fd = pidfd;
+ nevents = poll(&fds, 1, -1);
+
+ /* Check for error conditions */
+ if (nevents < 0)
+ ksft_exit_fail_msg("%s - poll failed\n",
+ strerror(errno));
+
+ if (nevents != 1)
+ ksft_exit_fail_msg("unexpected poll result: %d\n",
+ nevents);
+
+ if (!(fds.revents & POLLIN))
+ ksft_exit_fail_msg(
+ "unexpected event type received: 0x%x\n",
+ fds.revents);
+
+ if (timeout)
+ ksft_exit_fail_msg(
+ "death notification wait timeout\n");
+
+ close(pidfd);
+ /* Wait for child to prevent zombies */
+ if (waitpid(child_pid, NULL, 0) < 0)
+ ksft_exit_fail_msg("%s - waitpid failed\n",
+ strerror(errno));
+
+ }
+
+ ksft_test_result_pass("pidfd poll test: pass\n");
+ return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c
index 7eaa8a3de262..7aff2d3b42c0 100644
--- a/tools/testing/selftests/pidfd/pidfd_test.c
+++ b/tools/testing/selftests/pidfd/pidfd_test.c
@@ -21,20 +21,12 @@
#include "pidfd.h"
#include "../kselftest.h"
-#ifndef __NR_pidfd_send_signal
-#define __NR_pidfd_send_signal -1
-#endif
-
#define str(s) _str(s)
#define _str(s) #s
#define CHILD_THREAD_MIN_WAIT 3 /* seconds */
#define MAX_EVENTS 5
-#ifndef CLONE_PIDFD
-#define CLONE_PIDFD 0x00001000
-#endif
-
static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
{
size_t stack_size = 1024;
@@ -47,12 +39,6 @@ static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
#endif
}
-static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
- unsigned int flags)
-{
- return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
-}
-
static int signal_received;
static void set_signal_received_on_sigusr1(int sig)
@@ -339,13 +325,9 @@ static int test_pidfd_send_signal_syscall_support(void)
ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
if (ret < 0) {
- /*
- * pidfd_send_signal() will currently return ENOSYS when
- * CONFIG_PROC_FS is not set.
- */
if (errno == ENOSYS)
ksft_exit_skip(
- "%s test: pidfd_send_signal() syscall not supported (Ensure that CONFIG_PROC_FS=y is set)\n",
+ "%s test: pidfd_send_signal() syscall not supported\n",
test_name);
ksft_exit_fail_msg("%s test: Failed to send signal\n",
diff --git a/tools/testing/selftests/pidfd/pidfd_wait.c b/tools/testing/selftests/pidfd/pidfd_wait.c
new file mode 100644
index 000000000000..7079f8eef792
--- /dev/null
+++ b/tools/testing/selftests/pidfd/pidfd_wait.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "pidfd.h"
+#include "../kselftest.h"
+
+#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
+
+static pid_t sys_clone3(struct clone_args *args)
+{
+ return syscall(__NR_clone3, args, sizeof(struct clone_args));
+}
+
+static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
+ struct rusage *ru)
+{
+ return syscall(__NR_waitid, which, pid, info, options, ru);
+}
+
+static int test_pidfd_wait_simple(void)
+{
+ const char *test_name = "pidfd wait simple";
+ int pidfd = -1, status = 0;
+ pid_t parent_tid = -1;
+ struct clone_args args = {
+ .parent_tid = ptr_to_u64(&parent_tid),
+ .pidfd = ptr_to_u64(&pidfd),
+ .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
+ .exit_signal = SIGCHLD,
+ };
+ int ret;
+ pid_t pid;
+ siginfo_t info = {
+ .si_signo = 0,
+ };
+
+ pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+ if (pidfd < 0)
+ ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n",
+ test_name, strerror(errno));
+
+ pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
+ if (pid == 0)
+ ksft_exit_fail_msg(
+ "%s test: succeeded to wait on invalid pidfd %s\n",
+ test_name, strerror(errno));
+ close(pidfd);
+ pidfd = -1;
+
+ pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+ if (pidfd == 0)
+ ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n",
+ test_name, strerror(errno));
+
+ pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
+ if (pid == 0)
+ ksft_exit_fail_msg(
+ "%s test: succeeded to wait on invalid pidfd %s\n",
+ test_name, strerror(errno));
+ close(pidfd);
+ pidfd = -1;
+
+ pid = sys_clone3(&args);
+ if (pid < 0)
+ ksft_exit_fail_msg("%s test: failed to create new process %s\n",
+ test_name, strerror(errno));
+
+ if (pid == 0)
+ exit(EXIT_SUCCESS);
+
+ pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
+ if (pid < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to wait on process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status))
+ ksft_exit_fail_msg(
+ "%s test: unexpected status received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+ close(pidfd);
+
+ if (info.si_signo != SIGCHLD)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_signo, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_code != CLD_EXITED)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_code, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_pid != parent_tid)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_pid, parent_tid, pidfd,
+ strerror(errno));
+
+ ksft_test_result_pass("%s test: Passed\n", test_name);
+ return 0;
+}
+
+static int test_pidfd_wait_states(void)
+{
+ const char *test_name = "pidfd wait states";
+ int pidfd = -1, status = 0;
+ pid_t parent_tid = -1;
+ struct clone_args args = {
+ .parent_tid = ptr_to_u64(&parent_tid),
+ .pidfd = ptr_to_u64(&pidfd),
+ .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
+ .exit_signal = SIGCHLD,
+ };
+ int ret;
+ pid_t pid;
+ siginfo_t info = {
+ .si_signo = 0,
+ };
+
+ pid = sys_clone3(&args);
+ if (pid < 0)
+ ksft_exit_fail_msg("%s test: failed to create new process %s\n",
+ test_name, strerror(errno));
+
+ if (pid == 0) {
+ kill(getpid(), SIGSTOP);
+ kill(getpid(), SIGSTOP);
+ exit(EXIT_SUCCESS);
+ }
+
+ ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to wait on WSTOPPED process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ if (info.si_signo != SIGCHLD)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_signo, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_code != CLD_STOPPED)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_code, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_pid != parent_tid)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_pid, parent_tid, pidfd,
+ strerror(errno));
+
+ ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to send signal to process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to wait WCONTINUED on process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ if (info.si_signo != SIGCHLD)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_signo, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_code != CLD_CONTINUED)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_code, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_pid != parent_tid)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_pid, parent_tid, pidfd,
+ strerror(errno));
+
+ ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to wait on WUNTRACED process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ if (info.si_signo != SIGCHLD)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_signo, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_code != CLD_STOPPED)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_code, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_pid != parent_tid)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_pid, parent_tid, pidfd,
+ strerror(errno));
+
+ ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to send SIGKILL to process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
+ if (ret < 0)
+ ksft_exit_fail_msg(
+ "%s test: failed to wait on WEXITED process with pid %d and pidfd %d: %s\n",
+ test_name, parent_tid, pidfd, strerror(errno));
+
+ if (info.si_signo != SIGCHLD)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_signo, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_code != CLD_KILLED)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_code, parent_tid, pidfd,
+ strerror(errno));
+
+ if (info.si_pid != parent_tid)
+ ksft_exit_fail_msg(
+ "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
+ test_name, info.si_pid, parent_tid, pidfd,
+ strerror(errno));
+
+ close(pidfd);
+
+ ksft_test_result_pass("%s test: Passed\n", test_name);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ ksft_print_header();
+ ksft_set_plan(2);
+
+ test_pidfd_wait_simple();
+ test_pidfd_wait_states();
+
+ return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 27b7b5693ede..33c669619736 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -227,7 +227,7 @@ then
must_continue=yes
fi
last_ts="`tail $resdir/console.log | grep '^\[ *[0-9]\+\.[0-9]\+]' | tail -1 | sed -e 's/^\[ *//' -e 's/\..*$//'`"
- if test -z "last_ts"
+ if test -z "$last_ts"
then
last_ts=0
fi
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
index 5c3213cc3ad7..1c218944b1e9 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
@@ -3,3 +3,4 @@ rcutree.gp_preinit_delay=12
rcutree.gp_init_delay=3
rcutree.gp_cleanup_delay=3
rcutree.kthread_prio=2
+threadirqs
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
index affa7f2d9670..9539cffa9e5e 100644
--- a/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
+++ b/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
@@ -64,7 +64,7 @@ class SubPlugin(TdcPlugin):
cmdlist.insert(0, self.args.NAMES['NS'])
cmdlist.insert(0, 'exec')
cmdlist.insert(0, 'netns')
- cmdlist.insert(0, 'ip')
+ cmdlist.insert(0, self.args.NAMES['IP'])
else:
pass
@@ -78,16 +78,16 @@ class SubPlugin(TdcPlugin):
return command
def _ports_create(self):
- cmd = 'ip link add $DEV0 type veth peer name $DEV1'
+ cmd = '$IP link add $DEV0 type veth peer name $DEV1'
self._exec_cmd('pre', cmd)
- cmd = 'ip link set $DEV0 up'
+ cmd = '$IP link set $DEV0 up'
self._exec_cmd('pre', cmd)
if not self.args.namespace:
- cmd = 'ip link set $DEV1 up'
+ cmd = '$IP link set $DEV1 up'
self._exec_cmd('pre', cmd)
def _ports_destroy(self):
- cmd = 'ip link del $DEV0'
+ cmd = '$IP link del $DEV0'
self._exec_cmd('post', cmd)
def _ns_create(self):
@@ -97,16 +97,16 @@ class SubPlugin(TdcPlugin):
'''
self._ports_create()
if self.args.namespace:
- cmd = 'ip netns add {}'.format(self.args.NAMES['NS'])
+ cmd = '$IP netns add {}'.format(self.args.NAMES['NS'])
self._exec_cmd('pre', cmd)
- cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
+ cmd = '$IP link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
self._exec_cmd('pre', cmd)
- cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
+ cmd = '$IP -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
self._exec_cmd('pre', cmd)
if self.args.device:
- cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
+ cmd = '$IP link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
self._exec_cmd('pre', cmd)
- cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
+ cmd = '$IP -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
self._exec_cmd('pre', cmd)
def _ns_destroy(self):
@@ -115,7 +115,7 @@ class SubPlugin(TdcPlugin):
devices as well)
'''
if self.args.namespace:
- cmd = 'ip netns delete {}'.format(self.args.NAMES['NS'])
+ cmd = '$IP netns delete {}'.format(self.args.NAMES['NS'])
self._exec_cmd('post', cmd)
def _exec_cmd(self, stage, command):
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
index bf5ebf59c2d4..9cdd2e31ac2c 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
@@ -670,5 +670,52 @@
"teardown": [
"$TC actions flush action skbedit"
]
+ },
+ {
+ "id": "630c",
+ "name": "Add batch of 32 skbedit actions with all parameters and cookie",
+ "category": [
+ "actions",
+ "skbedit"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action skbedit",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action skbedit",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "32",
+ "teardown": [
+ "$TC actions flush action skbedit"
+ ]
+ },
+ {
+ "id": "706d",
+ "name": "Delete batch of 32 skbedit actions with all parameters",
+ "category": [
+ "actions",
+ "skbedit"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action skbedit",
+ 0,
+ 1,
+ 255
+ ],
+ "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action skbedit",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "0",
+ "teardown": []
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
index cc7c7d758008..6503b1ce091f 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
@@ -713,5 +713,99 @@
"teardown": [
"$TC actions flush action vlan"
]
+ },
+ {
+ "id": "294e",
+ "name": "Add batch of 32 vlan push actions with cookie",
+ "category": [
+ "actions",
+ "vlan"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action vlan",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action vlan",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "32",
+ "teardown": [
+ "$TC actions flush action vlan"
+ ]
+ },
+ {
+ "id": "56f7",
+ "name": "Delete batch of 32 vlan push actions",
+ "category": [
+ "actions",
+ "vlan"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action vlan",
+ 0,
+ 1,
+ 255
+ ],
+ "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action vlan",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "759f",
+ "name": "Add batch of 32 vlan pop actions with cookie",
+ "category": [
+ "actions",
+ "vlan"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action vlan",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop continue index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action vlan",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "32",
+ "teardown": [
+ "$TC actions flush action vlan"
+ ]
+ },
+ {
+ "id": "c84a",
+ "name": "Delete batch of 32 vlan pop actions",
+ "category": [
+ "actions",
+ "vlan"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action vlan",
+ 0,
+ 1,
+ 255
+ ],
+ "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+ ],
+ "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action vlan",
+ "matchPattern": "^[ \t]+index [0-9]+ ref",
+ "matchCount": "0",
+ "teardown": []
}
]
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index fa07d526fe39..5d49bfec1e9a 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -11,13 +11,13 @@ CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie)
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
- check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \
+ check_initial_reg_state sigreturn iopl ioperm \
protection_keys test_vdso test_vsyscall mov_ss_trap \
syscall_arg_fault
TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \
test_FCMOV test_FCOMI test_FISTTP \
vdso_restorer
-TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip
+TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip syscall_numbering
# Some selftests require 32bit support enabled also on 64bit systems
TARGETS_C_32BIT_NEEDED := ldt_gdt ptrace_syscall
diff --git a/tools/testing/selftests/x86/mpx-debug.h b/tools/testing/selftests/x86/mpx-debug.h
deleted file mode 100644
index 7546eba7f17a..000000000000
--- a/tools/testing/selftests/x86/mpx-debug.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _MPX_DEBUG_H
-#define _MPX_DEBUG_H
-
-#ifndef DEBUG_LEVEL
-#define DEBUG_LEVEL 0
-#endif
-#define dprintf_level(level, args...) do { if(level <= DEBUG_LEVEL) printf(args); } while(0)
-#define dprintf1(args...) dprintf_level(1, args)
-#define dprintf2(args...) dprintf_level(2, args)
-#define dprintf3(args...) dprintf_level(3, args)
-#define dprintf4(args...) dprintf_level(4, args)
-#define dprintf5(args...) dprintf_level(5, args)
-
-#endif /* _MPX_DEBUG_H */
diff --git a/tools/testing/selftests/x86/mpx-dig.c b/tools/testing/selftests/x86/mpx-dig.c
deleted file mode 100644
index 880fbf676968..000000000000
--- a/tools/testing/selftests/x86/mpx-dig.c
+++ /dev/null
@@ -1,497 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Written by Dave Hansen <dave.hansen@intel.com>
- */
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <fcntl.h>
-#include "mpx-debug.h"
-#include "mpx-mm.h"
-#include "mpx-hw.h"
-
-unsigned long bounds_dir_global;
-
-#define mpx_dig_abort() __mpx_dig_abort(__FILE__, __func__, __LINE__)
-static void inline __mpx_dig_abort(const char *file, const char *func, int line)
-{
- fprintf(stderr, "MPX dig abort @ %s::%d in %s()\n", file, line, func);
- printf("MPX dig abort @ %s::%d in %s()\n", file, line, func);
- abort();
-}
-
-/*
- * run like this (BDIR finds the probably bounds directory):
- *
- * BDIR="$(cat /proc/$pid/smaps | grep -B1 2097152 \
- * | head -1 | awk -F- '{print $1}')";
- * ./mpx-dig $pid 0x$BDIR
- *
- * NOTE:
- * assumes that the only 2097152-kb VMA is the bounds dir
- */
-
-long nr_incore(void *ptr, unsigned long size_bytes)
-{
- int i;
- long ret = 0;
- long vec_len = size_bytes / PAGE_SIZE;
- unsigned char *vec = malloc(vec_len);
- int incore_ret;
-
- if (!vec)
- mpx_dig_abort();
-
- incore_ret = mincore(ptr, size_bytes, vec);
- if (incore_ret) {
- printf("mincore ret: %d\n", incore_ret);
- perror("mincore");
- mpx_dig_abort();
- }
- for (i = 0; i < vec_len; i++)
- ret += vec[i];
- free(vec);
- return ret;
-}
-
-int open_proc(int pid, char *file)
-{
- static char buf[100];
- int fd;
-
- snprintf(&buf[0], sizeof(buf), "/proc/%d/%s", pid, file);
- fd = open(&buf[0], O_RDONLY);
- if (fd < 0)
- perror(buf);
-
- return fd;
-}
-
-struct vaddr_range {
- unsigned long start;
- unsigned long end;
-};
-struct vaddr_range *ranges;
-int nr_ranges_allocated;
-int nr_ranges_populated;
-int last_range = -1;
-
-int __pid_load_vaddrs(int pid)
-{
- int ret = 0;
- int proc_maps_fd = open_proc(pid, "maps");
- char linebuf[10000];
- unsigned long start;
- unsigned long end;
- char rest[1000];
- FILE *f = fdopen(proc_maps_fd, "r");
-
- if (!f)
- mpx_dig_abort();
- nr_ranges_populated = 0;
- while (!feof(f)) {
- char *readret = fgets(linebuf, sizeof(linebuf), f);
- int parsed;
-
- if (readret == NULL) {
- if (feof(f))
- break;
- mpx_dig_abort();
- }
-
- parsed = sscanf(linebuf, "%lx-%lx%s", &start, &end, rest);
- if (parsed != 3)
- mpx_dig_abort();
-
- dprintf4("result[%d]: %lx-%lx<->%s\n", parsed, start, end, rest);
- if (nr_ranges_populated >= nr_ranges_allocated) {
- ret = -E2BIG;
- break;
- }
- ranges[nr_ranges_populated].start = start;
- ranges[nr_ranges_populated].end = end;
- nr_ranges_populated++;
- }
- last_range = -1;
- fclose(f);
- close(proc_maps_fd);
- return ret;
-}
-
-int pid_load_vaddrs(int pid)
-{
- int ret;
-
- dprintf2("%s(%d)\n", __func__, pid);
- if (!ranges) {
- nr_ranges_allocated = 4;
- ranges = malloc(nr_ranges_allocated * sizeof(ranges[0]));
- dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__, pid,
- nr_ranges_allocated, ranges);
- assert(ranges != NULL);
- }
- do {
- ret = __pid_load_vaddrs(pid);
- if (!ret)
- break;
- if (ret == -E2BIG) {
- dprintf2("%s(%d) need to realloc\n", __func__, pid);
- nr_ranges_allocated *= 2;
- ranges = realloc(ranges,
- nr_ranges_allocated * sizeof(ranges[0]));
- dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__,
- pid, nr_ranges_allocated, ranges);
- assert(ranges != NULL);
- dprintf1("reallocating to hold %d ranges\n", nr_ranges_allocated);
- }
- } while (1);
-
- dprintf2("%s(%d) done\n", __func__, pid);
-
- return ret;
-}
-
-static inline int vaddr_in_range(unsigned long vaddr, struct vaddr_range *r)
-{
- if (vaddr < r->start)
- return 0;
- if (vaddr >= r->end)
- return 0;
- return 1;
-}
-
-static inline int vaddr_mapped_by_range(unsigned long vaddr)
-{
- int i;
-
- if (last_range > 0 && vaddr_in_range(vaddr, &ranges[last_range]))
- return 1;
-
- for (i = 0; i < nr_ranges_populated; i++) {
- struct vaddr_range *r = &ranges[i];
-
- if (vaddr_in_range(vaddr, r))
- continue;
- last_range = i;
- return 1;
- }
- return 0;
-}
-
-const int bt_entry_size_bytes = sizeof(unsigned long) * 4;
-
-void *read_bounds_table_into_buf(unsigned long table_vaddr)
-{
-#ifdef MPX_DIG_STANDALONE
- static char bt_buf[MPX_BOUNDS_TABLE_SIZE_BYTES];
- off_t seek_ret = lseek(fd, table_vaddr, SEEK_SET);
- if (seek_ret != table_vaddr)
- mpx_dig_abort();
-
- int read_ret = read(fd, &bt_buf, sizeof(bt_buf));
- if (read_ret != sizeof(bt_buf))
- mpx_dig_abort();
- return &bt_buf;
-#else
- return (void *)table_vaddr;
-#endif
-}
-
-int dump_table(unsigned long table_vaddr, unsigned long base_controlled_vaddr,
- unsigned long bde_vaddr)
-{
- unsigned long offset_inside_bt;
- int nr_entries = 0;
- int do_abort = 0;
- char *bt_buf;
-
- dprintf3("%s() base_controlled_vaddr: 0x%012lx bde_vaddr: 0x%012lx\n",
- __func__, base_controlled_vaddr, bde_vaddr);
-
- bt_buf = read_bounds_table_into_buf(table_vaddr);
-
- dprintf4("%s() read done\n", __func__);
-
- for (offset_inside_bt = 0;
- offset_inside_bt < MPX_BOUNDS_TABLE_SIZE_BYTES;
- offset_inside_bt += bt_entry_size_bytes) {
- unsigned long bt_entry_index;
- unsigned long bt_entry_controls;
- unsigned long this_bt_entry_for_vaddr;
- unsigned long *bt_entry_buf;
- int i;
-
- dprintf4("%s() offset_inside_bt: 0x%lx of 0x%llx\n", __func__,
- offset_inside_bt, MPX_BOUNDS_TABLE_SIZE_BYTES);
- bt_entry_buf = (void *)&bt_buf[offset_inside_bt];
- if (!bt_buf) {
- printf("null bt_buf\n");
- mpx_dig_abort();
- }
- if (!bt_entry_buf) {
- printf("null bt_entry_buf\n");
- mpx_dig_abort();
- }
- dprintf4("%s() reading *bt_entry_buf @ %p\n", __func__,
- bt_entry_buf);
- if (!bt_entry_buf[0] &&
- !bt_entry_buf[1] &&
- !bt_entry_buf[2] &&
- !bt_entry_buf[3])
- continue;
-
- nr_entries++;
-
- bt_entry_index = offset_inside_bt/bt_entry_size_bytes;
- bt_entry_controls = sizeof(void *);
- this_bt_entry_for_vaddr =
- base_controlled_vaddr + bt_entry_index*bt_entry_controls;
- /*
- * We sign extend vaddr bits 48->63 which effectively
- * creates a hole in the virtual address space.
- * This calculation corrects for the hole.
- */
- if (this_bt_entry_for_vaddr > 0x00007fffffffffffUL)
- this_bt_entry_for_vaddr |= 0xffff800000000000;
-
- if (!vaddr_mapped_by_range(this_bt_entry_for_vaddr)) {
- printf("bt_entry_buf: %p\n", bt_entry_buf);
- printf("there is a bte for %lx but no mapping\n",
- this_bt_entry_for_vaddr);
- printf(" bde vaddr: %016lx\n", bde_vaddr);
- printf("base_controlled_vaddr: %016lx\n", base_controlled_vaddr);
- printf(" table_vaddr: %016lx\n", table_vaddr);
- printf(" entry vaddr: %016lx @ offset %lx\n",
- table_vaddr + offset_inside_bt, offset_inside_bt);
- do_abort = 1;
- mpx_dig_abort();
- }
- if (DEBUG_LEVEL < 4)
- continue;
-
- printf("table entry[%lx]: ", offset_inside_bt);
- for (i = 0; i < bt_entry_size_bytes; i += sizeof(unsigned long))
- printf("0x%016lx ", bt_entry_buf[i]);
- printf("\n");
- }
- if (do_abort)
- mpx_dig_abort();
- dprintf4("%s() done\n", __func__);
- return nr_entries;
-}
-
-int search_bd_buf(char *buf, int len_bytes, unsigned long bd_offset_bytes,
- int *nr_populated_bdes)
-{
- unsigned long i;
- int total_entries = 0;
-
- dprintf3("%s(%p, %x, %lx, ...) buf end: %p\n", __func__, buf,
- len_bytes, bd_offset_bytes, buf + len_bytes);
-
- for (i = 0; i < len_bytes; i += sizeof(unsigned long)) {
- unsigned long bd_index = (bd_offset_bytes + i) / sizeof(unsigned long);
- unsigned long *bounds_dir_entry_ptr = (unsigned long *)&buf[i];
- unsigned long bounds_dir_entry;
- unsigned long bd_for_vaddr;
- unsigned long bt_start;
- unsigned long bt_tail;
- int nr_entries;
-
- dprintf4("%s() loop i: %ld bounds_dir_entry_ptr: %p\n", __func__, i,
- bounds_dir_entry_ptr);
-
- bounds_dir_entry = *bounds_dir_entry_ptr;
- if (!bounds_dir_entry) {
- dprintf4("no bounds dir at index 0x%lx / 0x%lx "
- "start at offset:%lx %lx\n", bd_index, bd_index,
- bd_offset_bytes, i);
- continue;
- }
- dprintf3("found bounds_dir_entry: 0x%lx @ "
- "index 0x%lx buf ptr: %p\n", bounds_dir_entry, i,
- &buf[i]);
- /* mask off the enable bit: */
- bounds_dir_entry &= ~0x1;
- (*nr_populated_bdes)++;
- dprintf4("nr_populated_bdes: %p\n", nr_populated_bdes);
- dprintf4("*nr_populated_bdes: %d\n", *nr_populated_bdes);
-
- bt_start = bounds_dir_entry;
- bt_tail = bounds_dir_entry + MPX_BOUNDS_TABLE_SIZE_BYTES - 1;
- if (!vaddr_mapped_by_range(bt_start)) {
- printf("bounds directory 0x%lx points to nowhere\n",
- bounds_dir_entry);
- mpx_dig_abort();
- }
- if (!vaddr_mapped_by_range(bt_tail)) {
- printf("bounds directory end 0x%lx points to nowhere\n",
- bt_tail);
- mpx_dig_abort();
- }
- /*
- * Each bounds directory entry controls 1MB of virtual address
- * space. This variable is the virtual address in the process
- * of the beginning of the area controlled by this bounds_dir.
- */
- bd_for_vaddr = bd_index * (1UL<<20);
-
- nr_entries = dump_table(bounds_dir_entry, bd_for_vaddr,
- bounds_dir_global+bd_offset_bytes+i);
- total_entries += nr_entries;
- dprintf5("dir entry[%4ld @ %p]: 0x%lx %6d entries "
- "total this buf: %7d bd_for_vaddrs: 0x%lx -> 0x%lx\n",
- bd_index, buf+i,
- bounds_dir_entry, nr_entries, total_entries,
- bd_for_vaddr, bd_for_vaddr + (1UL<<20));
- }
- dprintf3("%s(%p, %x, %lx, ...) done\n", __func__, buf, len_bytes,
- bd_offset_bytes);
- return total_entries;
-}
-
-int proc_pid_mem_fd = -1;
-
-void *fill_bounds_dir_buf_other(long byte_offset_inside_bounds_dir,
- long buffer_size_bytes, void *buffer)
-{
- unsigned long seekto = bounds_dir_global + byte_offset_inside_bounds_dir;
- int read_ret;
- off_t seek_ret = lseek(proc_pid_mem_fd, seekto, SEEK_SET);
-
- if (seek_ret != seekto)
- mpx_dig_abort();
-
- read_ret = read(proc_pid_mem_fd, buffer, buffer_size_bytes);
- /* there shouldn't practically be short reads of /proc/$pid/mem */
- if (read_ret != buffer_size_bytes)
- mpx_dig_abort();
-
- return buffer;
-}
-void *fill_bounds_dir_buf_self(long byte_offset_inside_bounds_dir,
- long buffer_size_bytes, void *buffer)
-
-{
- unsigned char vec[buffer_size_bytes / PAGE_SIZE];
- char *dig_bounds_dir_ptr =
- (void *)(bounds_dir_global + byte_offset_inside_bounds_dir);
- /*
- * use mincore() to quickly find the areas of the bounds directory
- * that have memory and thus will be worth scanning.
- */
- int incore_ret;
-
- int incore = 0;
- int i;
-
- dprintf4("%s() dig_bounds_dir_ptr: %p\n", __func__, dig_bounds_dir_ptr);
-
- incore_ret = mincore(dig_bounds_dir_ptr, buffer_size_bytes, &vec[0]);
- if (incore_ret) {
- printf("mincore ret: %d\n", incore_ret);
- perror("mincore");
- mpx_dig_abort();
- }
- for (i = 0; i < sizeof(vec); i++)
- incore += vec[i];
- dprintf4("%s() total incore: %d\n", __func__, incore);
- if (!incore)
- return NULL;
- dprintf3("%s() total incore: %d\n", __func__, incore);
- return dig_bounds_dir_ptr;
-}
-
-int inspect_pid(int pid)
-{
- static int dig_nr;
- long offset_inside_bounds_dir;
- char bounds_dir_buf[sizeof(unsigned long) * (1UL << 15)];
- char *dig_bounds_dir_ptr;
- int total_entries = 0;
- int nr_populated_bdes = 0;
- int inspect_self;
-
- if (getpid() == pid) {
- dprintf4("inspecting self\n");
- inspect_self = 1;
- } else {
- dprintf4("inspecting pid %d\n", pid);
- mpx_dig_abort();
- }
-
- for (offset_inside_bounds_dir = 0;
- offset_inside_bounds_dir < MPX_BOUNDS_TABLE_SIZE_BYTES;
- offset_inside_bounds_dir += sizeof(bounds_dir_buf)) {
- static int bufs_skipped;
- int this_entries;
-
- if (inspect_self) {
- dig_bounds_dir_ptr =
- fill_bounds_dir_buf_self(offset_inside_bounds_dir,
- sizeof(bounds_dir_buf),
- &bounds_dir_buf[0]);
- } else {
- dig_bounds_dir_ptr =
- fill_bounds_dir_buf_other(offset_inside_bounds_dir,
- sizeof(bounds_dir_buf),
- &bounds_dir_buf[0]);
- }
- if (!dig_bounds_dir_ptr) {
- bufs_skipped++;
- continue;
- }
- this_entries = search_bd_buf(dig_bounds_dir_ptr,
- sizeof(bounds_dir_buf),
- offset_inside_bounds_dir,
- &nr_populated_bdes);
- total_entries += this_entries;
- }
- printf("mpx dig (%3d) complete, SUCCESS (%8d / %4d)\n", ++dig_nr,
- total_entries, nr_populated_bdes);
- return total_entries + nr_populated_bdes;
-}
-
-#ifdef MPX_DIG_REMOTE
-int main(int argc, char **argv)
-{
- int err;
- char *c;
- unsigned long bounds_dir_entry;
- int pid;
-
- printf("mpx-dig starting...\n");
- err = sscanf(argv[1], "%d", &pid);
- printf("parsing: '%s', err: %d\n", argv[1], err);
- if (err != 1)
- mpx_dig_abort();
-
- err = sscanf(argv[2], "%lx", &bounds_dir_global);
- printf("parsing: '%s': %d\n", argv[2], err);
- if (err != 1)
- mpx_dig_abort();
-
- proc_pid_mem_fd = open_proc(pid, "mem");
- if (proc_pid_mem_fd < 0)
- mpx_dig_abort();
-
- inspect_pid(pid);
- return 0;
-}
-#endif
-
-long inspect_me(struct mpx_bounds_dir *bounds_dir)
-{
- int pid = getpid();
-
- pid_load_vaddrs(pid);
- bounds_dir_global = (unsigned long)bounds_dir;
- dprintf4("enter %s() bounds dir: %p\n", __func__, bounds_dir);
- return inspect_pid(pid);
-}
diff --git a/tools/testing/selftests/x86/mpx-hw.h b/tools/testing/selftests/x86/mpx-hw.h
deleted file mode 100644
index d1b61ab870f8..000000000000
--- a/tools/testing/selftests/x86/mpx-hw.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _MPX_HW_H
-#define _MPX_HW_H
-
-#include <assert.h>
-
-/* Describe the MPX Hardware Layout in here */
-
-#define NR_MPX_BOUNDS_REGISTERS 4
-
-#ifdef __i386__
-
-#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 16 /* 4 * 32-bits */
-#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 14) /* 16k */
-#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 4
-#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 22) /* 4MB */
-
-#define MPX_BOUNDS_TABLE_BOTTOM_BIT 2
-#define MPX_BOUNDS_TABLE_TOP_BIT 11
-#define MPX_BOUNDS_DIR_BOTTOM_BIT 12
-#define MPX_BOUNDS_DIR_TOP_BIT 31
-
-#else
-
-/*
- * Linear Address of "pointer" (LAp)
- * 0 -> 2: ignored
- * 3 -> 19: index in to bounds table
- * 20 -> 47: index in to bounds directory
- * 48 -> 63: ignored
- */
-
-#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 32
-#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 22) /* 4MB */
-#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 8
-#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 31) /* 2GB */
-
-#define MPX_BOUNDS_TABLE_BOTTOM_BIT 3
-#define MPX_BOUNDS_TABLE_TOP_BIT 19
-#define MPX_BOUNDS_DIR_BOTTOM_BIT 20
-#define MPX_BOUNDS_DIR_TOP_BIT 47
-
-#endif
-
-#define MPX_BOUNDS_DIR_NR_ENTRIES \
- (MPX_BOUNDS_DIR_SIZE_BYTES/MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES)
-#define MPX_BOUNDS_TABLE_NR_ENTRIES \
- (MPX_BOUNDS_TABLE_SIZE_BYTES/MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES)
-
-#define MPX_BOUNDS_TABLE_ENTRY_VALID_BIT 0x1
-
-struct mpx_bd_entry {
- union {
- char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES];
- void *contents[0];
- };
-} __attribute__((packed));
-
-struct mpx_bt_entry {
- union {
- char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES];
- unsigned long contents[0];
- };
-} __attribute__((packed));
-
-struct mpx_bounds_dir {
- struct mpx_bd_entry entries[MPX_BOUNDS_DIR_NR_ENTRIES];
-} __attribute__((packed));
-
-struct mpx_bounds_table {
- struct mpx_bt_entry entries[MPX_BOUNDS_TABLE_NR_ENTRIES];
-} __attribute__((packed));
-
-static inline unsigned long GET_BITS(unsigned long val, int bottombit, int topbit)
-{
- int total_nr_bits = topbit - bottombit;
- unsigned long mask = (1UL << total_nr_bits)-1;
- return (val >> bottombit) & mask;
-}
-
-static inline unsigned long __vaddr_bounds_table_index(void *vaddr)
-{
- return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_TABLE_BOTTOM_BIT,
- MPX_BOUNDS_TABLE_TOP_BIT);
-}
-
-static inline unsigned long __vaddr_bounds_directory_index(void *vaddr)
-{
- return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_DIR_BOTTOM_BIT,
- MPX_BOUNDS_DIR_TOP_BIT);
-}
-
-static inline struct mpx_bd_entry *mpx_vaddr_to_bd_entry(void *vaddr,
- struct mpx_bounds_dir *bounds_dir)
-{
- unsigned long index = __vaddr_bounds_directory_index(vaddr);
- return &bounds_dir->entries[index];
-}
-
-static inline int bd_entry_valid(struct mpx_bd_entry *bounds_dir_entry)
-{
- unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents;
- return (__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT);
-}
-
-static inline struct mpx_bounds_table *
-__bd_entry_to_bounds_table(struct mpx_bd_entry *bounds_dir_entry)
-{
- unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents;
- assert(__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT);
- __bd_entry &= ~MPX_BOUNDS_TABLE_ENTRY_VALID_BIT;
- return (struct mpx_bounds_table *)__bd_entry;
-}
-
-static inline struct mpx_bt_entry *
-mpx_vaddr_to_bt_entry(void *vaddr, struct mpx_bounds_dir *bounds_dir)
-{
- struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(vaddr, bounds_dir);
- struct mpx_bounds_table *bt = __bd_entry_to_bounds_table(bde);
- unsigned long index = __vaddr_bounds_table_index(vaddr);
- return &bt->entries[index];
-}
-
-#endif /* _MPX_HW_H */
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
deleted file mode 100644
index 23ddd453f362..000000000000
--- a/tools/testing/selftests/x86/mpx-mini-test.c
+++ /dev/null
@@ -1,1613 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * mpx-mini-test.c: routines to test Intel MPX (Memory Protection eXtentions)
- *
- * Written by:
- * "Ren, Qiaowei" <qiaowei.ren@intel.com>
- * "Wei, Gang" <gang.wei@intel.com>
- * "Hansen, Dave" <dave.hansen@intel.com>
- */
-
-/*
- * 2014-12-05: Dave Hansen: fixed all of the compiler warnings, and made sure
- * it works on 32-bit.
- */
-
-int inspect_every_this_many_mallocs = 100;
-int zap_all_every_this_many_mallocs = 1000;
-
-#define _GNU_SOURCE
-#define _LARGEFILE64_SOURCE
-
-#include <string.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ucontext.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "mpx-hw.h"
-#include "mpx-debug.h"
-#include "mpx-mm.h"
-
-#ifndef __always_inline
-#define __always_inline inline __attribute__((always_inline)
-#endif
-
-#ifndef TEST_DURATION_SECS
-#define TEST_DURATION_SECS 3
-#endif
-
-void write_int_to(char *prefix, char *file, int int_to_write)
-{
- char buf[100];
- int fd = open(file, O_RDWR);
- int len;
- int ret;
-
- assert(fd >= 0);
- len = snprintf(buf, sizeof(buf), "%s%d", prefix, int_to_write);
- assert(len >= 0);
- assert(len < sizeof(buf));
- ret = write(fd, buf, len);
- assert(ret == len);
- ret = close(fd);
- assert(!ret);
-}
-
-void write_pid_to(char *prefix, char *file)
-{
- write_int_to(prefix, file, getpid());
-}
-
-void trace_me(void)
-{
-/* tracing events dir */
-#define TED "/sys/kernel/debug/tracing/events/"
-/*
- write_pid_to("common_pid=", TED "signal/filter");
- write_pid_to("common_pid=", TED "exceptions/filter");
- write_int_to("", TED "signal/enable", 1);
- write_int_to("", TED "exceptions/enable", 1);
-*/
- write_pid_to("", "/sys/kernel/debug/tracing/set_ftrace_pid");
- write_int_to("", "/sys/kernel/debug/tracing/trace", 0);
-}
-
-#define test_failed() __test_failed(__FILE__, __LINE__)
-static void __test_failed(char *f, int l)
-{
- fprintf(stderr, "abort @ %s::%d\n", f, l);
- abort();
-}
-
-/* Error Printf */
-#define eprintf(args...) fprintf(stderr, args)
-
-#ifdef __i386__
-
-/* i386 directory size is 4MB */
-#define REG_IP_IDX REG_EIP
-#define REX_PREFIX
-
-#define XSAVE_OFFSET_IN_FPMEM sizeof(struct _libc_fpstate)
-
-/*
- * __cpuid() is from the Linux Kernel:
- */
-static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- /* ecx is often an input as well as an output. */
- asm volatile(
- "push %%ebx;"
- "cpuid;"
- "mov %%ebx, %1;"
- "pop %%ebx"
- : "=a" (*eax),
- "=g" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (*eax), "2" (*ecx));
-}
-
-#else /* __i386__ */
-
-#define REG_IP_IDX REG_RIP
-#define REX_PREFIX "0x48, "
-
-#define XSAVE_OFFSET_IN_FPMEM 0
-
-/*
- * __cpuid() is from the Linux Kernel:
- */
-static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- /* ecx is often an input as well as an output. */
- asm volatile(
- "cpuid;"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (*eax), "2" (*ecx));
-}
-
-#endif /* !__i386__ */
-
-struct xsave_hdr_struct {
- uint64_t xstate_bv;
- uint64_t reserved1[2];
- uint64_t reserved2[5];
-} __attribute__((packed));
-
-struct bndregs_struct {
- uint64_t bndregs[8];
-} __attribute__((packed));
-
-struct bndcsr_struct {
- uint64_t cfg_reg_u;
- uint64_t status_reg;
-} __attribute__((packed));
-
-struct xsave_struct {
- uint8_t fpu_sse[512];
- struct xsave_hdr_struct xsave_hdr;
- uint8_t ymm[256];
- uint8_t lwp[128];
- struct bndregs_struct bndregs;
- struct bndcsr_struct bndcsr;
-} __attribute__((packed));
-
-uint8_t __attribute__((__aligned__(64))) buffer[4096];
-struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer;
-
-uint8_t __attribute__((__aligned__(64))) test_buffer[4096];
-struct xsave_struct *xsave_test_buf = (struct xsave_struct *)test_buffer;
-
-uint64_t num_bnd_chk;
-
-static __always_inline void xrstor_state(struct xsave_struct *fx, uint64_t mask)
-{
- uint32_t lmask = mask;
- uint32_t hmask = mask >> 32;
-
- asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
- : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
- : "memory");
-}
-
-static __always_inline void xsave_state_1(void *_fx, uint64_t mask)
-{
- uint32_t lmask = mask;
- uint32_t hmask = mask >> 32;
- unsigned char *fx = _fx;
-
- asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
- : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
- : "memory");
-}
-
-static inline uint64_t xgetbv(uint32_t index)
-{
- uint32_t eax, edx;
-
- asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
- : "=a" (eax), "=d" (edx)
- : "c" (index));
- return eax + ((uint64_t)edx << 32);
-}
-
-static uint64_t read_mpx_status_sig(ucontext_t *uctxt)
-{
- memset(buffer, 0, sizeof(buffer));
- memcpy(buffer,
- (uint8_t *)uctxt->uc_mcontext.fpregs + XSAVE_OFFSET_IN_FPMEM,
- sizeof(struct xsave_struct));
-
- return xsave_buf->bndcsr.status_reg;
-}
-
-#include <pthread.h>
-
-static uint8_t *get_next_inst_ip(uint8_t *addr)
-{
- uint8_t *ip = addr;
- uint8_t sib;
- uint8_t rm;
- uint8_t mod;
- uint8_t base;
- uint8_t modrm;
-
- /* determine the prefix. */
- switch(*ip) {
- case 0xf2:
- case 0xf3:
- case 0x66:
- ip++;
- break;
- }
-
- /* look for rex prefix */
- if ((*ip & 0x40) == 0x40)
- ip++;
-
- /* Make sure we have a MPX instruction. */
- if (*ip++ != 0x0f)
- return addr;
-
- /* Skip the op code byte. */
- ip++;
-
- /* Get the modrm byte. */
- modrm = *ip++;
-
- /* Break it down into parts. */
- rm = modrm & 7;
- mod = (modrm >> 6);
-
- /* Init the parts of the address mode. */
- base = 8;
-
- /* Is it a mem mode? */
- if (mod != 3) {
- /* look for scaled indexed addressing */
- if (rm == 4) {
- /* SIB addressing */
- sib = *ip++;
- base = sib & 7;
- switch (mod) {
- case 0:
- if (base == 5)
- ip += 4;
- break;
-
- case 1:
- ip++;
- break;
-
- case 2:
- ip += 4;
- break;
- }
-
- } else {
- /* MODRM addressing */
- switch (mod) {
- case 0:
- /* DISP32 addressing, no base */
- if (rm == 5)
- ip += 4;
- break;
-
- case 1:
- ip++;
- break;
-
- case 2:
- ip += 4;
- break;
- }
- }
- }
- return ip;
-}
-
-#ifdef si_lower
-static inline void *__si_bounds_lower(siginfo_t *si)
-{
- return si->si_lower;
-}
-
-static inline void *__si_bounds_upper(siginfo_t *si)
-{
- return si->si_upper;
-}
-#else
-
-/*
- * This deals with old version of _sigfault in some distros:
- *
-
-old _sigfault:
- struct {
- void *si_addr;
- } _sigfault;
-
-new _sigfault:
- struct {
- void __user *_addr;
- int _trapno;
- short _addr_lsb;
- union {
- struct {
- void __user *_lower;
- void __user *_upper;
- } _addr_bnd;
- __u32 _pkey;
- };
- } _sigfault;
- *
- */
-
-static inline void **__si_bounds_hack(siginfo_t *si)
-{
- void *sigfault = &si->_sifields._sigfault;
- void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault);
- int *trapno = (int*)end_sigfault;
- /* skip _trapno and _addr_lsb */
- void **__si_lower = (void**)(trapno + 2);
-
- return __si_lower;
-}
-
-static inline void *__si_bounds_lower(siginfo_t *si)
-{
- return *__si_bounds_hack(si);
-}
-
-static inline void *__si_bounds_upper(siginfo_t *si)
-{
- return *(__si_bounds_hack(si) + 1);
-}
-#endif
-
-static int br_count;
-static int expected_bnd_index = -1;
-uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */
-unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS];
-
-/* Failed address bound checks: */
-#ifndef SEGV_BNDERR
-# define SEGV_BNDERR 3
-#endif
-
-/*
- * The kernel is supposed to provide some information about the bounds
- * exception in the siginfo. It should match what we have in the bounds
- * registers that we are checking against. Just check against the shadow copy
- * since it is easily available, and we also check that *it* matches the real
- * registers.
- */
-void check_siginfo_vs_shadow(siginfo_t* si)
-{
- int siginfo_ok = 1;
- void *shadow_lower = (void *)(unsigned long)shadow_plb[expected_bnd_index][0];
- void *shadow_upper = (void *)(unsigned long)shadow_plb[expected_bnd_index][1];
-
- if ((expected_bnd_index < 0) ||
- (expected_bnd_index >= NR_MPX_BOUNDS_REGISTERS)) {
- fprintf(stderr, "ERROR: invalid expected_bnd_index: %d\n",
- expected_bnd_index);
- exit(6);
- }
- if (__si_bounds_lower(si) != shadow_lower)
- siginfo_ok = 0;
- if (__si_bounds_upper(si) != shadow_upper)
- siginfo_ok = 0;
-
- if (!siginfo_ok) {
- fprintf(stderr, "ERROR: siginfo bounds do not match "
- "shadow bounds for register %d\n", expected_bnd_index);
- exit(7);
- }
-}
-
-void handler(int signum, siginfo_t *si, void *vucontext)
-{
- int i;
- ucontext_t *uctxt = vucontext;
- int trapno;
- unsigned long ip;
-
- dprintf1("entered signal handler\n");
-
- trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
- ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
-
- if (trapno == 5) {
- typeof(si->si_addr) *si_addr_ptr = &si->si_addr;
- uint64_t status = read_mpx_status_sig(uctxt);
- uint64_t br_reason = status & 0x3;
-
- br_count++;
- dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
-
- dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
- status, ip, br_reason);
- dprintf2("si_signo: %d\n", si->si_signo);
- dprintf2(" signum: %d\n", signum);
- dprintf2("info->si_code == SEGV_BNDERR: %d\n",
- (si->si_code == SEGV_BNDERR));
- dprintf2("info->si_code: %d\n", si->si_code);
- dprintf2("info->si_lower: %p\n", __si_bounds_lower(si));
- dprintf2("info->si_upper: %p\n", __si_bounds_upper(si));
-
- for (i = 0; i < 8; i++)
- dprintf3("[%d]: %p\n", i, si_addr_ptr[i]);
- switch (br_reason) {
- case 0: /* traditional BR */
- fprintf(stderr,
- "Undefined status with bound exception:%jx\n",
- status);
- exit(5);
- case 1: /* #BR MPX bounds exception */
- /* these are normal and we expect to see them */
-
- check_siginfo_vs_shadow(si);
-
- dprintf1("bounds exception (normal): status 0x%jx at %p si_addr: %p\n",
- status, (void *)ip, si->si_addr);
- num_bnd_chk++;
- uctxt->uc_mcontext.gregs[REG_IP_IDX] =
- (greg_t)get_next_inst_ip((uint8_t *)ip);
- break;
- case 2:
- fprintf(stderr, "#BR status == 2, missing bounds table,"
- "kernel should have handled!!\n");
- exit(4);
- break;
- default:
- fprintf(stderr, "bound check error: status 0x%jx at %p\n",
- status, (void *)ip);
- num_bnd_chk++;
- uctxt->uc_mcontext.gregs[REG_IP_IDX] =
- (greg_t)get_next_inst_ip((uint8_t *)ip);
- fprintf(stderr, "bound check error: si_addr %p\n", si->si_addr);
- exit(3);
- }
- } else if (trapno == 14) {
- eprintf("ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n",
- trapno, ip);
- eprintf("si_addr %p\n", si->si_addr);
- eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
- test_failed();
- } else {
- eprintf("unexpected trap %d! at 0x%lx\n", trapno, ip);
- eprintf("si_addr %p\n", si->si_addr);
- eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
- test_failed();
- }
-}
-
-static inline void cpuid_count(unsigned int op, int count,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = count;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-#define XSTATE_CPUID 0x0000000d
-
-/*
- * List of XSAVE features Linux knows about:
- */
-enum xfeature_bit {
- XSTATE_BIT_FP,
- XSTATE_BIT_SSE,
- XSTATE_BIT_YMM,
- XSTATE_BIT_BNDREGS,
- XSTATE_BIT_BNDCSR,
- XSTATE_BIT_OPMASK,
- XSTATE_BIT_ZMM_Hi256,
- XSTATE_BIT_Hi16_ZMM,
-
- XFEATURES_NR_MAX,
-};
-
-#define XSTATE_FP (1 << XSTATE_BIT_FP)
-#define XSTATE_SSE (1 << XSTATE_BIT_SSE)
-#define XSTATE_YMM (1 << XSTATE_BIT_YMM)
-#define XSTATE_BNDREGS (1 << XSTATE_BIT_BNDREGS)
-#define XSTATE_BNDCSR (1 << XSTATE_BIT_BNDCSR)
-#define XSTATE_OPMASK (1 << XSTATE_BIT_OPMASK)
-#define XSTATE_ZMM_Hi256 (1 << XSTATE_BIT_ZMM_Hi256)
-#define XSTATE_Hi16_ZMM (1 << XSTATE_BIT_Hi16_ZMM)
-
-#define MPX_XSTATES (XSTATE_BNDREGS | XSTATE_BNDCSR) /* 0x18 */
-
-bool one_bit(unsigned int x, int bit)
-{
- return !!(x & (1<<bit));
-}
-
-void print_state_component(int state_bit_nr, char *name)
-{
- unsigned int eax, ebx, ecx, edx;
- unsigned int state_component_size;
- unsigned int state_component_supervisor;
- unsigned int state_component_user;
- unsigned int state_component_aligned;
-
- /* See SDM Section 13.2 */
- cpuid_count(XSTATE_CPUID, state_bit_nr, &eax, &ebx, &ecx, &edx);
- assert(eax || ebx || ecx);
- state_component_size = eax;
- state_component_supervisor = ((!ebx) && one_bit(ecx, 0));
- state_component_user = !one_bit(ecx, 0);
- state_component_aligned = one_bit(ecx, 1);
- printf("%8s: size: %d user: %d supervisor: %d aligned: %d\n",
- name,
- state_component_size, state_component_user,
- state_component_supervisor, state_component_aligned);
-
-}
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (ecx) */
-#define XSAVE_FEATURE_BIT (26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
-#define OSXSAVE_FEATURE_BIT (27) /* XSAVE enabled in the OS */
-
-bool check_mpx_support(void)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid_count(1, 0, &eax, &ebx, &ecx, &edx);
-
- /* We can't do much without XSAVE, so just make these assert()'s */
- if (!one_bit(ecx, XSAVE_FEATURE_BIT)) {
- fprintf(stderr, "processor lacks XSAVE, can not run MPX tests\n");
- exit(0);
- }
-
- if (!one_bit(ecx, OSXSAVE_FEATURE_BIT)) {
- fprintf(stderr, "processor lacks OSXSAVE, can not run MPX tests\n");
- exit(0);
- }
-
- /* CPUs not supporting the XSTATE CPUID leaf do not support MPX */
- /* Is this redundant with the feature bit checks? */
- cpuid_count(0, 0, &eax, &ebx, &ecx, &edx);
- if (eax < XSTATE_CPUID) {
- fprintf(stderr, "processor lacks XSTATE CPUID leaf,"
- " can not run MPX tests\n");
- exit(0);
- }
-
- printf("XSAVE is supported by HW & OS\n");
-
- cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
-
- printf("XSAVE processor supported state mask: 0x%x\n", eax);
- printf("XSAVE OS supported state mask: 0x%jx\n", xgetbv(0));
-
- /* Make sure that the MPX states are enabled in in XCR0 */
- if ((eax & MPX_XSTATES) != MPX_XSTATES) {
- fprintf(stderr, "processor lacks MPX XSTATE(s), can not run MPX tests\n");
- exit(0);
- }
-
- /* Make sure the MPX states are supported by XSAVE* */
- if ((xgetbv(0) & MPX_XSTATES) != MPX_XSTATES) {
- fprintf(stderr, "MPX XSTATE(s) no enabled in XCR0, "
- "can not run MPX tests\n");
- exit(0);
- }
-
- print_state_component(XSTATE_BIT_BNDREGS, "BNDREGS");
- print_state_component(XSTATE_BIT_BNDCSR, "BNDCSR");
-
- return true;
-}
-
-void enable_mpx(void *l1base)
-{
- /* enable point lookup */
- memset(buffer, 0, sizeof(buffer));
- xrstor_state(xsave_buf, 0x18);
-
- xsave_buf->xsave_hdr.xstate_bv = 0x10;
- xsave_buf->bndcsr.cfg_reg_u = (unsigned long)l1base | 1;
- xsave_buf->bndcsr.status_reg = 0;
-
- dprintf2("bf xrstor\n");
- dprintf2("xsave cndcsr: status %jx, configu %jx\n",
- xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
- xrstor_state(xsave_buf, 0x18);
- dprintf2("after xrstor\n");
-
- xsave_state_1(xsave_buf, 0x18);
-
- dprintf1("xsave bndcsr: status %jx, configu %jx\n",
- xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
-}
-
-#include <sys/prctl.h>
-
-struct mpx_bounds_dir *bounds_dir_ptr;
-
-unsigned long __bd_incore(const char *func, int line)
-{
- unsigned long ret = nr_incore(bounds_dir_ptr, MPX_BOUNDS_DIR_SIZE_BYTES);
- return ret;
-}
-#define bd_incore() __bd_incore(__func__, __LINE__)
-
-void check_clear(void *ptr, unsigned long sz)
-{
- unsigned long *i;
-
- for (i = ptr; (void *)i < ptr + sz; i++) {
- if (*i) {
- dprintf1("%p is NOT clear at %p\n", ptr, i);
- assert(0);
- }
- }
- dprintf1("%p is clear for %lx\n", ptr, sz);
-}
-
-void check_clear_bd(void)
-{
- check_clear(bounds_dir_ptr, 2UL << 30);
-}
-
-#define USE_MALLOC_FOR_BOUNDS_DIR 1
-bool process_specific_init(void)
-{
- unsigned long size;
- unsigned long *dir;
- /* Guarantee we have the space to align it, add padding: */
- unsigned long pad = getpagesize();
-
- size = 2UL << 30; /* 2GB */
- if (sizeof(unsigned long) == 4)
- size = 4UL << 20; /* 4MB */
- dprintf1("trying to allocate %ld MB bounds directory\n", (size >> 20));
-
- if (USE_MALLOC_FOR_BOUNDS_DIR) {
- unsigned long _dir;
-
- dir = malloc(size + pad);
- assert(dir);
- _dir = (unsigned long)dir;
- _dir += 0xfffUL;
- _dir &= ~0xfffUL;
- dir = (void *)_dir;
- } else {
- /*
- * This makes debugging easier because the address
- * calculations are simpler:
- */
- dir = mmap((void *)0x200000000000, size + pad,
- PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- if (dir == (void *)-1) {
- perror("unable to allocate bounds directory");
- abort();
- }
- check_clear(dir, size);
- }
- bounds_dir_ptr = (void *)dir;
- madvise(bounds_dir_ptr, size, MADV_NOHUGEPAGE);
- bd_incore();
- dprintf1("bounds directory: 0x%p -> 0x%p\n", bounds_dir_ptr,
- (char *)bounds_dir_ptr + size);
- check_clear(dir, size);
- enable_mpx(dir);
- check_clear(dir, size);
- if (prctl(43, 0, 0, 0, 0)) {
- printf("no MPX support\n");
- abort();
- return false;
- }
- return true;
-}
-
-bool process_specific_finish(void)
-{
- if (prctl(44)) {
- printf("no MPX support\n");
- return false;
- }
- return true;
-}
-
-void setup_handler()
-{
- int r, rs;
- struct sigaction newact;
- struct sigaction oldact;
-
- /* #BR is mapped to sigsegv */
- int signum = SIGSEGV;
-
- newact.sa_handler = 0; /* void(*)(int)*/
- newact.sa_sigaction = handler; /* void (*)(int, siginfo_t*, void *) */
-
- /*sigset_t - signals to block while in the handler */
- /* get the old signal mask. */
- rs = sigprocmask(SIG_SETMASK, 0, &newact.sa_mask);
- assert(rs == 0);
-
- /* call sa_sigaction, not sa_handler*/
- newact.sa_flags = SA_SIGINFO;
-
- newact.sa_restorer = 0; /* void(*)(), obsolete */
- r = sigaction(signum, &newact, &oldact);
- assert(r == 0);
-}
-
-void mpx_prepare(void)
-{
- dprintf2("%s()\n", __func__);
- setup_handler();
- process_specific_init();
-}
-
-void mpx_cleanup(void)
-{
- printf("%s(): %jd BRs. bye...\n", __func__, num_bnd_chk);
- process_specific_finish();
-}
-
-/*-------------- the following is test case ---------------*/
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-uint64_t num_lower_brs;
-uint64_t num_upper_brs;
-
-#define MPX_CONFIG_OFFSET 1024
-#define MPX_BOUNDS_OFFSET 960
-#define MPX_HEADER_OFFSET 512
-#define MAX_ADDR_TESTED (1<<28)
-#define TEST_ROUNDS 100
-
-/*
- 0F 1A /r BNDLDX-Load
- 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation
- 66 0F 1A /r BNDMOV bnd1, bnd2/m128
- 66 0F 1B /r BNDMOV bnd1/m128, bnd2
- F2 0F 1A /r BNDCU bnd, r/m64
- F2 0F 1B /r BNDCN bnd, r/m64
- F3 0F 1A /r BNDCL bnd, r/m64
- F3 0F 1B /r BNDMK bnd, m64
-*/
-
-static __always_inline void xsave_state(void *_fx, uint64_t mask)
-{
- uint32_t lmask = mask;
- uint32_t hmask = mask >> 32;
- unsigned char *fx = _fx;
-
- asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
- : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
- : "memory");
-}
-
-static __always_inline void mpx_clear_bnd0(void)
-{
- long size = 0;
- void *ptr = NULL;
- /* F3 0F 1B /r BNDMK bnd, m64 */
- /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
- asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
- : : "c" (ptr), "d" (size-1)
- : "memory");
-}
-
-static __always_inline void mpx_make_bound_helper(unsigned long ptr,
- unsigned long size)
-{
- /* F3 0F 1B /r BNDMK bnd, m64 */
- /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
- asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
- : : "c" (ptr), "d" (size-1)
- : "memory");
-}
-
-static __always_inline void mpx_check_lowerbound_helper(unsigned long ptr)
-{
- /* F3 0F 1A /r NDCL bnd, r/m64 */
- /* f3 0f 1a 01 bndcl (%rcx),%bnd0 */
- asm volatile(".byte 0xf3,0x0f,0x1a,0x01\n\t"
- : : "c" (ptr)
- : "memory");
-}
-
-static __always_inline void mpx_check_upperbound_helper(unsigned long ptr)
-{
- /* F2 0F 1A /r BNDCU bnd, r/m64 */
- /* f2 0f 1a 01 bndcu (%rcx),%bnd0 */
- asm volatile(".byte 0xf2,0x0f,0x1a,0x01\n\t"
- : : "c" (ptr)
- : "memory");
-}
-
-static __always_inline void mpx_movbndreg_helper()
-{
- /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
- /* 66 0f 1b c2 bndmov %bnd0,%bnd2 */
-
- asm volatile(".byte 0x66,0x0f,0x1b,0xc2\n\t");
-}
-
-static __always_inline void mpx_movbnd2mem_helper(uint8_t *mem)
-{
- /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
- /* 66 0f 1b 01 bndmov %bnd0,(%rcx) */
- asm volatile(".byte 0x66,0x0f,0x1b,0x01\n\t"
- : : "c" (mem)
- : "memory");
-}
-
-static __always_inline void mpx_movbnd_from_mem_helper(uint8_t *mem)
-{
- /* 66 0F 1A /r BNDMOV bnd1, bnd2/m128 */
- /* 66 0f 1a 01 bndmov (%rcx),%bnd0 */
- asm volatile(".byte 0x66,0x0f,0x1a,0x01\n\t"
- : : "c" (mem)
- : "memory");
-}
-
-static __always_inline void mpx_store_dsc_helper(unsigned long ptr_addr,
- unsigned long ptr_val)
-{
- /* 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation */
- /* 0f 1b 04 11 bndstx %bnd0,(%rcx,%rdx,1) */
- asm volatile(".byte 0x0f,0x1b,0x04,0x11\n\t"
- : : "c" (ptr_addr), "d" (ptr_val)
- : "memory");
-}
-
-static __always_inline void mpx_load_dsc_helper(unsigned long ptr_addr,
- unsigned long ptr_val)
-{
- /* 0F 1A /r BNDLDX-Load */
- /*/ 0f 1a 04 11 bndldx (%rcx,%rdx,1),%bnd0 */
- asm volatile(".byte 0x0f,0x1a,0x04,0x11\n\t"
- : : "c" (ptr_addr), "d" (ptr_val)
- : "memory");
-}
-
-void __print_context(void *__print_xsave_buffer, int line)
-{
- uint64_t *bounds = (uint64_t *)(__print_xsave_buffer + MPX_BOUNDS_OFFSET);
- uint64_t *cfg = (uint64_t *)(__print_xsave_buffer + MPX_CONFIG_OFFSET);
-
- int i;
- eprintf("%s()::%d\n", "print_context", line);
- for (i = 0; i < 4; i++) {
- eprintf("bound[%d]: 0x%016lx 0x%016lx(0x%016lx)\n", i,
- (unsigned long)bounds[i*2],
- ~(unsigned long)bounds[i*2+1],
- (unsigned long)bounds[i*2+1]);
- }
-
- eprintf("cpcfg: %jx cpstatus: %jx\n", cfg[0], cfg[1]);
-}
-#define print_context(x) __print_context(x, __LINE__)
-#ifdef DEBUG
-#define dprint_context(x) print_context(x)
-#else
-#define dprint_context(x) do{}while(0)
-#endif
-
-void init()
-{
- int i;
-
- srand((unsigned int)time(NULL));
-
- for (i = 0; i < 4; i++) {
- shadow_plb[i][0] = 0;
- shadow_plb[i][1] = ~(unsigned long)0;
- }
-}
-
-long int __mpx_random(int line)
-{
-#ifdef NOT_SO_RANDOM
- static long fake = 722122311;
- fake += 563792075;
- return fakse;
-#else
- return random();
-#endif
-}
-#define mpx_random() __mpx_random(__LINE__)
-
-uint8_t *get_random_addr()
-{
- uint8_t*addr = (uint8_t *)(unsigned long)(rand() % MAX_ADDR_TESTED);
- return (addr - (unsigned long)addr % sizeof(uint8_t *));
-}
-
-static inline bool compare_context(void *__xsave_buffer)
-{
- uint64_t *bounds = (uint64_t *)(__xsave_buffer + MPX_BOUNDS_OFFSET);
-
- int i;
- for (i = 0; i < 4; i++) {
- dprintf3("shadow[%d]{%016lx/%016lx}\nbounds[%d]{%016lx/%016lx}\n",
- i, (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
- i, (unsigned long)bounds[i*2], ~(unsigned long)bounds[i*2+1]);
- if ((shadow_plb[i][0] != bounds[i*2]) ||
- (shadow_plb[i][1] != ~(unsigned long)bounds[i*2+1])) {
- eprintf("ERROR comparing shadow to real bound register %d\n", i);
- eprintf("shadow{0x%016lx/0x%016lx}\nbounds{0x%016lx/0x%016lx}\n",
- (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
- (unsigned long)bounds[i*2], (unsigned long)bounds[i*2+1]);
- return false;
- }
- }
-
- return true;
-}
-
-void mkbnd_shadow(uint8_t *ptr, int index, long offset)
-{
- uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
- uint64_t *upper = (uint64_t *)&(shadow_plb[index][1]);
- *lower = (unsigned long)ptr;
- *upper = (unsigned long)ptr + offset - 1;
-}
-
-void check_lowerbound_shadow(uint8_t *ptr, int index)
-{
- uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
- if (*lower > (uint64_t)(unsigned long)ptr)
- num_lower_brs++;
- else
- dprintf1("LowerBoundChk passed:%p\n", ptr);
-}
-
-void check_upperbound_shadow(uint8_t *ptr, int index)
-{
- uint64_t upper = *(uint64_t *)&(shadow_plb[index][1]);
- if (upper < (uint64_t)(unsigned long)ptr)
- num_upper_brs++;
- else
- dprintf1("UpperBoundChk passed:%p\n", ptr);
-}
-
-__always_inline void movbndreg_shadow(int src, int dest)
-{
- shadow_plb[dest][0] = shadow_plb[src][0];
- shadow_plb[dest][1] = shadow_plb[src][1];
-}
-
-__always_inline void movbnd2mem_shadow(int src, unsigned long *dest)
-{
- unsigned long *lower = (unsigned long *)&(shadow_plb[src][0]);
- unsigned long *upper = (unsigned long *)&(shadow_plb[src][1]);
- *dest = *lower;
- *(dest+1) = *upper;
-}
-
-__always_inline void movbnd_from_mem_shadow(unsigned long *src, int dest)
-{
- unsigned long *lower = (unsigned long *)&(shadow_plb[dest][0]);
- unsigned long *upper = (unsigned long *)&(shadow_plb[dest][1]);
- *lower = *src;
- *upper = *(src+1);
-}
-
-__always_inline void stdsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
-{
- shadow_map[0] = (unsigned long)shadow_plb[index][0];
- shadow_map[1] = (unsigned long)shadow_plb[index][1];
- shadow_map[2] = (unsigned long)ptr_val;
- dprintf3("%s(%d, %p, %p) set shadow map[2]: %p\n", __func__,
- index, ptr, ptr_val, ptr_val);
- /*ptr ignored */
-}
-
-void lddsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
-{
- uint64_t lower = shadow_map[0];
- uint64_t upper = shadow_map[1];
- uint8_t *value = (uint8_t *)shadow_map[2];
-
- if (value != ptr_val) {
- dprintf2("%s(%d, %p, %p) init shadow bounds[%d] "
- "because %p != %p\n", __func__, index, ptr,
- ptr_val, index, value, ptr_val);
- shadow_plb[index][0] = 0;
- shadow_plb[index][1] = ~(unsigned long)0;
- } else {
- shadow_plb[index][0] = lower;
- shadow_plb[index][1] = upper;
- }
- /* ptr ignored */
-}
-
-static __always_inline void mpx_test_helper0(uint8_t *buf, uint8_t *ptr)
-{
- mpx_make_bound_helper((unsigned long)ptr, 0x1800);
-}
-
-static __always_inline void mpx_test_helper0_shadow(uint8_t *buf, uint8_t *ptr)
-{
- mkbnd_shadow(ptr, 0, 0x1800);
-}
-
-static __always_inline void mpx_test_helper1(uint8_t *buf, uint8_t *ptr)
-{
- /* these are hard-coded to check bnd0 */
- expected_bnd_index = 0;
- mpx_check_lowerbound_helper((unsigned long)(ptr-1));
- mpx_check_upperbound_helper((unsigned long)(ptr+0x1800));
- /* reset this since we do not expect any more bounds exceptions */
- expected_bnd_index = -1;
-}
-
-static __always_inline void mpx_test_helper1_shadow(uint8_t *buf, uint8_t *ptr)
-{
- check_lowerbound_shadow(ptr-1, 0);
- check_upperbound_shadow(ptr+0x1800, 0);
-}
-
-static __always_inline void mpx_test_helper2(uint8_t *buf, uint8_t *ptr)
-{
- mpx_make_bound_helper((unsigned long)ptr, 0x1800);
- mpx_movbndreg_helper();
- mpx_movbnd2mem_helper(buf);
- mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
-}
-
-static __always_inline void mpx_test_helper2_shadow(uint8_t *buf, uint8_t *ptr)
-{
- mkbnd_shadow(ptr, 0, 0x1800);
- movbndreg_shadow(0, 2);
- movbnd2mem_shadow(0, (unsigned long *)buf);
- mkbnd_shadow(ptr+0x12, 0, 0x1800);
-}
-
-static __always_inline void mpx_test_helper3(uint8_t *buf, uint8_t *ptr)
-{
- mpx_movbnd_from_mem_helper(buf);
-}
-
-static __always_inline void mpx_test_helper3_shadow(uint8_t *buf, uint8_t *ptr)
-{
- movbnd_from_mem_shadow((unsigned long *)buf, 0);
-}
-
-static __always_inline void mpx_test_helper4(uint8_t *buf, uint8_t *ptr)
-{
- mpx_store_dsc_helper((unsigned long)buf, (unsigned long)ptr);
- mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
-}
-
-static __always_inline void mpx_test_helper4_shadow(uint8_t *buf, uint8_t *ptr)
-{
- stdsc_shadow(0, buf, ptr);
- mkbnd_shadow(ptr+0x12, 0, 0x1800);
-}
-
-static __always_inline void mpx_test_helper5(uint8_t *buf, uint8_t *ptr)
-{
- mpx_load_dsc_helper((unsigned long)buf, (unsigned long)ptr);
-}
-
-static __always_inline void mpx_test_helper5_shadow(uint8_t *buf, uint8_t *ptr)
-{
- lddsc_shadow(0, buf, ptr);
-}
-
-#define NR_MPX_TEST_FUNCTIONS 6
-
-/*
- * For compatibility reasons, MPX will clear the bounds registers
- * when you make function calls (among other things). We have to
- * preserve the registers in between calls to the "helpers" since
- * they build on each other.
- *
- * Be very careful not to make any function calls inside the
- * helpers, or anywhere else beween the xrstor and xsave.
- */
-#define run_helper(helper_nr, buf, buf_shadow, ptr) do { \
- xrstor_state(xsave_test_buf, flags); \
- mpx_test_helper##helper_nr(buf, ptr); \
- xsave_state(xsave_test_buf, flags); \
- mpx_test_helper##helper_nr##_shadow(buf_shadow, ptr); \
-} while (0)
-
-static void run_helpers(int nr, uint8_t *buf, uint8_t *buf_shadow, uint8_t *ptr)
-{
- uint64_t flags = 0x18;
-
- dprint_context(xsave_test_buf);
- switch (nr) {
- case 0:
- run_helper(0, buf, buf_shadow, ptr);
- break;
- case 1:
- run_helper(1, buf, buf_shadow, ptr);
- break;
- case 2:
- run_helper(2, buf, buf_shadow, ptr);
- break;
- case 3:
- run_helper(3, buf, buf_shadow, ptr);
- break;
- case 4:
- run_helper(4, buf, buf_shadow, ptr);
- break;
- case 5:
- run_helper(5, buf, buf_shadow, ptr);
- break;
- default:
- test_failed();
- break;
- }
- dprint_context(xsave_test_buf);
-}
-
-unsigned long buf_shadow[1024]; /* used to check load / store descriptors */
-extern long inspect_me(struct mpx_bounds_dir *bounds_dir);
-
-long cover_buf_with_bt_entries(void *buf, long buf_len)
-{
- int i;
- long nr_to_fill;
- int ratio = 1000;
- unsigned long buf_len_in_ptrs;
-
- /* Fill about 1/100 of the space with bt entries */
- nr_to_fill = buf_len / (sizeof(unsigned long) * ratio);
-
- if (!nr_to_fill)
- dprintf3("%s() nr_to_fill: %ld\n", __func__, nr_to_fill);
-
- /* Align the buffer to pointer size */
- while (((unsigned long)buf) % sizeof(void *)) {
- buf++;
- buf_len--;
- }
- /* We are storing pointers, so make */
- buf_len_in_ptrs = buf_len / sizeof(void *);
-
- for (i = 0; i < nr_to_fill; i++) {
- long index = (mpx_random() % buf_len_in_ptrs);
- void *ptr = buf + index * sizeof(unsigned long);
- unsigned long ptr_addr = (unsigned long)ptr;
-
- /* ptr and size can be anything */
- mpx_make_bound_helper((unsigned long)ptr, 8);
-
- /*
- * take bnd0 and put it in to bounds tables "buf + index" is an
- * address inside the buffer where we are pretending that we
- * are going to put a pointer We do not, though because we will
- * never load entries from the table, so it doesn't matter.
- */
- mpx_store_dsc_helper(ptr_addr, (unsigned long)ptr);
- dprintf4("storing bound table entry for %lx (buf start @ %p)\n",
- ptr_addr, buf);
- }
- return nr_to_fill;
-}
-
-unsigned long align_down(unsigned long alignme, unsigned long align_to)
-{
- return alignme & ~(align_to-1);
-}
-
-unsigned long align_up(unsigned long alignme, unsigned long align_to)
-{
- return (alignme + align_to - 1) & ~(align_to-1);
-}
-
-/*
- * Using 1MB alignment guarantees that each no allocation
- * will overlap with another's bounds tables.
- *
- * We have to cook our own allocator here. malloc() can
- * mix other allocation with ours which means that even
- * if we free all of our allocations, there might still
- * be bounds tables for the *areas* since there is other
- * valid memory there.
- *
- * We also can't use malloc() because a free() of an area
- * might not free it back to the kernel. We want it
- * completely unmapped an malloc() does not guarantee
- * that.
- */
-#ifdef __i386__
-long alignment = 4096;
-long sz_alignment = 4096;
-#else
-long alignment = 1 * MB;
-long sz_alignment = 1 * MB;
-#endif
-void *mpx_mini_alloc(unsigned long sz)
-{
- unsigned long long tries = 0;
- static void *last;
- void *ptr;
- void *try_at;
-
- sz = align_up(sz, sz_alignment);
-
- try_at = last + alignment;
- while (1) {
- ptr = mmap(try_at, sz, PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- if (ptr == (void *)-1)
- return NULL;
- if (ptr == try_at)
- break;
-
- munmap(ptr, sz);
- try_at += alignment;
-#ifdef __i386__
- /*
- * This isn't quite correct for 32-bit binaries
- * on 64-bit kernels since they can use the
- * entire 32-bit address space, but it's close
- * enough.
- */
- if (try_at > (void *)0xC0000000)
-#else
- if (try_at > (void *)0x0000800000000000)
-#endif
- try_at = (void *)0x0;
- if (!(++tries % 10000))
- dprintf1("stuck in %s(), tries: %lld\n", __func__, tries);
- continue;
- }
- last = ptr;
- dprintf3("mpx_mini_alloc(0x%lx) returning: %p\n", sz, ptr);
- return ptr;
-}
-void mpx_mini_free(void *ptr, long sz)
-{
- dprintf2("%s() ptr: %p\n", __func__, ptr);
- if ((unsigned long)ptr > 0x100000000000) {
- dprintf1("uh oh !!!!!!!!!!!!!!! pointer too high: %p\n", ptr);
- test_failed();
- }
- sz = align_up(sz, sz_alignment);
- dprintf3("%s() ptr: %p before munmap\n", __func__, ptr);
- munmap(ptr, sz);
- dprintf3("%s() ptr: %p DONE\n", __func__, ptr);
-}
-
-#define NR_MALLOCS 100
-struct one_malloc {
- char *ptr;
- int nr_filled_btes;
- unsigned long size;
-};
-struct one_malloc mallocs[NR_MALLOCS];
-
-void free_one_malloc(int index)
-{
- unsigned long free_ptr;
- unsigned long mask;
-
- if (!mallocs[index].ptr)
- return;
-
- mpx_mini_free(mallocs[index].ptr, mallocs[index].size);
- dprintf4("freed[%d]: %p\n", index, mallocs[index].ptr);
-
- free_ptr = (unsigned long)mallocs[index].ptr;
- mask = alignment-1;
- dprintf4("lowerbits: %lx / %lx mask: %lx\n", free_ptr,
- (free_ptr & mask), mask);
- assert((free_ptr & mask) == 0);
-
- mallocs[index].ptr = NULL;
-}
-
-#ifdef __i386__
-#define MPX_BOUNDS_TABLE_COVERS 4096
-#else
-#define MPX_BOUNDS_TABLE_COVERS (1 * MB)
-#endif
-void zap_everything(void)
-{
- long after_zap;
- long before_zap;
- int i;
-
- before_zap = inspect_me(bounds_dir_ptr);
- dprintf1("zapping everything start: %ld\n", before_zap);
- for (i = 0; i < NR_MALLOCS; i++)
- free_one_malloc(i);
-
- after_zap = inspect_me(bounds_dir_ptr);
- dprintf1("zapping everything done: %ld\n", after_zap);
- /*
- * We only guarantee to empty the thing out if our allocations are
- * exactly aligned on the boundaries of a boudns table.
- */
- if ((alignment >= MPX_BOUNDS_TABLE_COVERS) &&
- (sz_alignment >= MPX_BOUNDS_TABLE_COVERS)) {
- if (after_zap != 0)
- test_failed();
-
- assert(after_zap == 0);
- }
-}
-
-void do_one_malloc(void)
-{
- static int malloc_counter;
- long sz;
- int rand_index = (mpx_random() % NR_MALLOCS);
- void *ptr = mallocs[rand_index].ptr;
-
- dprintf3("%s() enter\n", __func__);
-
- if (ptr) {
- dprintf3("freeing one malloc at index: %d\n", rand_index);
- free_one_malloc(rand_index);
- if (mpx_random() % (NR_MALLOCS*3) == 3) {
- int i;
- dprintf3("zapping some more\n");
- for (i = rand_index; i < NR_MALLOCS; i++)
- free_one_malloc(i);
- }
- if ((mpx_random() % zap_all_every_this_many_mallocs) == 4)
- zap_everything();
- }
-
- /* 1->~1M */
- sz = (1 + mpx_random() % 1000) * 1000;
- ptr = mpx_mini_alloc(sz);
- if (!ptr) {
- /*
- * If we are failing allocations, just assume we
- * are out of memory and zap everything.
- */
- dprintf3("zapping everything because out of memory\n");
- zap_everything();
- goto out;
- }
-
- dprintf3("malloc: %p size: 0x%lx\n", ptr, sz);
- mallocs[rand_index].nr_filled_btes = cover_buf_with_bt_entries(ptr, sz);
- mallocs[rand_index].ptr = ptr;
- mallocs[rand_index].size = sz;
-out:
- if ((++malloc_counter) % inspect_every_this_many_mallocs == 0)
- inspect_me(bounds_dir_ptr);
-}
-
-void run_timed_test(void (*test_func)(void))
-{
- int done = 0;
- long iteration = 0;
- static time_t last_print;
- time_t now;
- time_t start;
-
- time(&start);
- while (!done) {
- time(&now);
- if ((now - start) > TEST_DURATION_SECS)
- done = 1;
-
- test_func();
- iteration++;
-
- if ((now - last_print > 1) || done) {
- printf("iteration %ld complete, OK so far\n", iteration);
- last_print = now;
- }
- }
-}
-
-void check_bounds_table_frees(void)
-{
- printf("executing unmaptest\n");
- inspect_me(bounds_dir_ptr);
- run_timed_test(&do_one_malloc);
- printf("done with malloc() fun\n");
-}
-
-void insn_test_failed(int test_nr, int test_round, void *buf,
- void *buf_shadow, void *ptr)
-{
- print_context(xsave_test_buf);
- eprintf("ERROR: test %d round %d failed\n", test_nr, test_round);
- while (test_nr == 5) {
- struct mpx_bt_entry *bte;
- struct mpx_bounds_dir *bd = (void *)bounds_dir_ptr;
- struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(buf, bd);
-
- printf(" bd: %p\n", bd);
- printf("&bde: %p\n", bde);
- printf("*bde: %lx\n", *(unsigned long *)bde);
- if (!bd_entry_valid(bde))
- break;
-
- bte = mpx_vaddr_to_bt_entry(buf, bd);
- printf(" te: %p\n", bte);
- printf("bte[0]: %lx\n", bte->contents[0]);
- printf("bte[1]: %lx\n", bte->contents[1]);
- printf("bte[2]: %lx\n", bte->contents[2]);
- printf("bte[3]: %lx\n", bte->contents[3]);
- break;
- }
- test_failed();
-}
-
-void check_mpx_insns_and_tables(void)
-{
- int successes = 0;
- int failures = 0;
- int buf_size = (1024*1024);
- unsigned long *buf = malloc(buf_size);
- const int total_nr_tests = NR_MPX_TEST_FUNCTIONS * TEST_ROUNDS;
- int i, j;
-
- memset(buf, 0, buf_size);
- memset(buf_shadow, 0, sizeof(buf_shadow));
-
- for (i = 0; i < TEST_ROUNDS; i++) {
- uint8_t *ptr = get_random_addr() + 8;
-
- for (j = 0; j < NR_MPX_TEST_FUNCTIONS; j++) {
- if (0 && j != 5) {
- successes++;
- continue;
- }
- dprintf2("starting test %d round %d\n", j, i);
- dprint_context(xsave_test_buf);
- /*
- * test5 loads an address from the bounds tables.
- * The load will only complete if 'ptr' matches
- * the load and the store, so with random addrs,
- * the odds of this are very small. Make it
- * higher by only moving 'ptr' 1/10 times.
- */
- if (random() % 10 <= 0)
- ptr = get_random_addr() + 8;
- dprintf3("random ptr{%p}\n", ptr);
- dprint_context(xsave_test_buf);
- run_helpers(j, (void *)buf, (void *)buf_shadow, ptr);
- dprint_context(xsave_test_buf);
- if (!compare_context(xsave_test_buf)) {
- insn_test_failed(j, i, buf, buf_shadow, ptr);
- failures++;
- goto exit;
- }
- successes++;
- dprint_context(xsave_test_buf);
- dprintf2("finished test %d round %d\n", j, i);
- dprintf3("\n");
- dprint_context(xsave_test_buf);
- }
- }
-
-exit:
- dprintf2("\nabout to free:\n");
- free(buf);
- dprintf1("successes: %d\n", successes);
- dprintf1(" failures: %d\n", failures);
- dprintf1(" tests: %d\n", total_nr_tests);
- dprintf1(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
- dprintf1(" saw: %d #BRs\n", br_count);
- if (failures) {
- eprintf("ERROR: non-zero number of failures\n");
- exit(20);
- }
- if (successes != total_nr_tests) {
- eprintf("ERROR: succeeded fewer than number of tries (%d != %d)\n",
- successes, total_nr_tests);
- exit(21);
- }
- if (num_upper_brs + num_lower_brs != br_count) {
- eprintf("ERROR: unexpected number of #BRs: %jd %jd %d\n",
- num_upper_brs, num_lower_brs, br_count);
- eprintf("successes: %d\n", successes);
- eprintf(" failures: %d\n", failures);
- eprintf(" tests: %d\n", total_nr_tests);
- eprintf(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
- eprintf(" saw: %d #BRs\n", br_count);
- exit(22);
- }
-}
-
-/*
- * This is supposed to SIGSEGV nicely once the kernel
- * can no longer allocate vaddr space.
- */
-void exhaust_vaddr_space(void)
-{
- unsigned long ptr;
- /* Try to make sure there is no room for a bounds table anywhere */
- unsigned long skip = MPX_BOUNDS_TABLE_SIZE_BYTES - PAGE_SIZE;
-#ifdef __i386__
- unsigned long max_vaddr = 0xf7788000UL;
-#else
- unsigned long max_vaddr = 0x800000000000UL;
-#endif
-
- dprintf1("%s() start\n", __func__);
- /* do not start at 0, we aren't allowed to map there */
- for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
- void *ptr_ret;
- int ret = madvise((void *)ptr, PAGE_SIZE, MADV_NORMAL);
-
- if (!ret) {
- dprintf1("madvise() %lx ret: %d\n", ptr, ret);
- continue;
- }
- ptr_ret = mmap((void *)ptr, PAGE_SIZE, PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- if (ptr_ret != (void *)ptr) {
- perror("mmap");
- dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
- break;
- }
- if (!(ptr & 0xffffff))
- dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
- }
- for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
- dprintf2("covering 0x%lx with bounds table entries\n", ptr);
- cover_buf_with_bt_entries((void *)ptr, PAGE_SIZE);
- }
- dprintf1("%s() end\n", __func__);
- printf("done with vaddr space fun\n");
-}
-
-void mpx_table_test(void)
-{
- printf("starting mpx bounds table test\n");
- run_timed_test(check_mpx_insns_and_tables);
- printf("done with mpx bounds table test\n");
-}
-
-int main(int argc, char **argv)
-{
- int unmaptest = 0;
- int vaddrexhaust = 0;
- int tabletest = 0;
- int i;
-
- check_mpx_support();
- mpx_prepare();
- srandom(11179);
-
- bd_incore();
- init();
- bd_incore();
-
- trace_me();
-
- xsave_state((void *)xsave_test_buf, 0x1f);
- if (!compare_context(xsave_test_buf))
- printf("Init failed\n");
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "unmaptest"))
- unmaptest = 1;
- if (!strcmp(argv[i], "vaddrexhaust"))
- vaddrexhaust = 1;
- if (!strcmp(argv[i], "tabletest"))
- tabletest = 1;
- }
- if (!(unmaptest || vaddrexhaust || tabletest)) {
- unmaptest = 1;
- /* vaddrexhaust = 1; */
- tabletest = 1;
- }
- if (unmaptest)
- check_bounds_table_frees();
- if (tabletest)
- mpx_table_test();
- if (vaddrexhaust)
- exhaust_vaddr_space();
- printf("%s completed successfully\n", argv[0]);
- exit(0);
-}
-
-#include "mpx-dig.c"
diff --git a/tools/testing/selftests/x86/mpx-mm.h b/tools/testing/selftests/x86/mpx-mm.h
deleted file mode 100644
index 6dbdd66b8242..000000000000
--- a/tools/testing/selftests/x86/mpx-mm.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _MPX_MM_H
-#define _MPX_MM_H
-
-#define PAGE_SIZE 4096
-#define MB (1UL<<20)
-
-extern long nr_incore(void *ptr, unsigned long size_bytes);
-
-#endif /* _MPX_MM_H */
diff --git a/tools/testing/selftests/x86/syscall_numbering.c b/tools/testing/selftests/x86/syscall_numbering.c
new file mode 100644
index 000000000000..d6b09cb1aa2c
--- /dev/null
+++ b/tools/testing/selftests/x86/syscall_numbering.c
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * syscall_arg_fault.c - tests faults 32-bit fast syscall stack args
+ * Copyright (c) 2018 Andrew Lutomirski
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <syscall.h>
+
+static int nerrs;
+
+#define X32_BIT 0x40000000UL
+
+static void check_enosys(unsigned long nr, bool *ok)
+{
+ /* If this fails, a segfault is reasonably likely. */
+ fflush(stdout);
+
+ long ret = syscall(nr, 0, 0, 0, 0, 0, 0);
+ if (ret == 0) {
+ printf("[FAIL]\tsyscall %lu succeeded, but it should have failed\n", nr);
+ *ok = false;
+ } else if (errno != ENOSYS) {
+ printf("[FAIL]\tsyscall %lu had error code %d, but it should have reported ENOSYS\n", nr, errno);
+ *ok = false;
+ }
+}
+
+static void test_x32_without_x32_bit(void)
+{
+ bool ok = true;
+
+ /*
+ * Syscalls 512-547 are "x32" syscalls. They are intended to be
+ * called with the x32 (0x40000000) bit set. Calling them without
+ * the x32 bit set is nonsense and should not work.
+ */
+ printf("[RUN]\tChecking syscalls 512-547\n");
+ for (int i = 512; i <= 547; i++)
+ check_enosys(i, &ok);
+
+ /*
+ * Check that a handful of 64-bit-only syscalls are rejected if the x32
+ * bit is set.
+ */
+ printf("[RUN]\tChecking some 64-bit syscalls in x32 range\n");
+ check_enosys(16 | X32_BIT, &ok); /* ioctl */
+ check_enosys(19 | X32_BIT, &ok); /* readv */
+ check_enosys(20 | X32_BIT, &ok); /* writev */
+
+ /*
+ * Check some syscalls with high bits set.
+ */
+ printf("[RUN]\tChecking numbers above 2^32-1\n");
+ check_enosys((1UL << 32), &ok);
+ check_enosys(X32_BIT | (1UL << 32), &ok);
+
+ if (!ok)
+ nerrs++;
+ else
+ printf("[OK]\tThey all returned -ENOSYS\n");
+}
+
+int main()
+{
+ /*
+ * Anyone diagnosing a failure will want to know whether the kernel
+ * supports x32. Tell them.
+ */
+ printf("\tChecking for x32...");
+ fflush(stdout);
+ if (syscall(39 | X32_BIT, 0, 0, 0, 0, 0, 0) >= 0) {
+ printf(" supported\n");
+ } else if (errno == ENOSYS) {
+ printf(" not supported\n");
+ } else {
+ printf(" confused\n");
+ }
+
+ test_x32_without_x32_bit();
+
+ return nerrs ? 1 : 0;
+}
diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c
index 4602326b8f5b..a4f4d4cf22c3 100644
--- a/tools/testing/selftests/x86/test_vsyscall.c
+++ b/tools/testing/selftests/x86/test_vsyscall.c
@@ -451,7 +451,7 @@ static int test_vsys_x(void)
printf("[OK]\tExecuting the vsyscall page failed: #PF(0x%lx)\n",
segv_err);
} else {
- printf("[FAILT]\tExecution failed with the wrong error: #PF(0x%lx)\n",
+ printf("[FAIL]\tExecution failed with the wrong error: #PF(0x%lx)\n",
segv_err);
return 1;
}
diff --git a/usr/include/Makefile b/usr/include/Makefile
index aa316d99e035..1fb6abe29b2f 100644
--- a/usr/include/Makefile
+++ b/usr/include/Makefile
@@ -101,10 +101,6 @@ ifeq ($(SRCARCH),riscv)
header-test- += linux/bpf_perf_event.h
endif
-ifeq ($(SRCARCH),s390)
-header-test- += asm/zcrypt.h
-endif
-
ifeq ($(SRCARCH),sparc)
header-test- += asm/stat.h
header-test- += asm/uctx.h
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index f645c0fbf7ec..35a069815baf 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -144,11 +144,6 @@ out_fail_alloc:
return ret;
}
-bool kvm_arch_has_vcpu_debugfs(void)
-{
- return false;
-}
-
int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
{
return 0;
@@ -323,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
{
+ /*
+ * If we're about to block (most likely because we've just hit a
+ * WFI), we need to sync back the state of the GIC CPU interface
+ * so that we have the lastest PMR and group enables. This ensures
+ * that kvm_arch_vcpu_runnable has up-to-date data to decide
+ * whether we have pending interrupts.
+ */
+ preempt_disable();
+ kvm_vgic_vmcr_sync(vcpu);
+ preempt_enable();
+
kvm_vgic_v4_enable_doorbell(vcpu);
}
@@ -340,6 +346,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
/* Set up the timer */
kvm_timer_vcpu_init(vcpu);
+ kvm_pmu_vcpu_init(vcpu);
+
kvm_arm_reset_debug_ptr(vcpu);
return kvm_vgic_vcpu_init(vcpu);
@@ -727,7 +735,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
* Ensure we set mode to IN_GUEST_MODE after we disable
* interrupts and before the final VCPU requests check.
* See the comment in kvm_vcpu_exiting_guest_mode() and
- * Documentation/virtual/kvm/vcpu-requests.rst
+ * Documentation/virt/kvm/vcpu-requests.rst
*/
smp_store_mb(vcpu->mode, IN_GUEST_MODE);
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 254c5f190a3d..ccf1fde9836c 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -349,8 +349,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
case 7:
cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
+ /* Fall through */
case 6:
cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
+ /* Fall through */
default:
cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
}
@@ -359,8 +361,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
case 7:
cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
+ /* Fall through */
case 6:
cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
+ /* Fall through */
default:
cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
}
@@ -382,8 +386,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
case 7:
__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
+ /* Fall through */
case 6:
__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
+ /* Fall through */
default:
__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
}
@@ -392,8 +398,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
case 7:
__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
+ /* Fall through */
case 6:
__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
+ /* Fall through */
default:
__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
}
diff --git a/virt/kvm/arm/mmio.c b/virt/kvm/arm/mmio.c
index a8a6a0c883f1..6af5c91337f2 100644
--- a/virt/kvm/arm/mmio.c
+++ b/virt/kvm/arm/mmio.c
@@ -86,6 +86,12 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
unsigned int len;
int mask;
+ /* Detect an already handled MMIO return */
+ if (unlikely(!vcpu->mmio_needed))
+ return 0;
+
+ vcpu->mmio_needed = 0;
+
if (!run->mmio.is_write) {
len = run->mmio.len;
if (len > sizeof(unsigned long))
@@ -188,6 +194,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
run->mmio.is_write = is_write;
run->mmio.phys_addr = fault_ipa;
run->mmio.len = len;
+ vcpu->mmio_needed = 1;
if (!ret) {
/* We handled the access successfully in the kernel. */
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 3dd8238ed246..362a01886bab 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -215,6 +215,20 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
}
/**
+ * kvm_pmu_vcpu_init - assign pmu counter idx for cpu
+ * @vcpu: The vcpu pointer
+ *
+ */
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+ for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
+ pmu->pmc[i].idx = i;
+}
+
+/**
* kvm_pmu_vcpu_reset - reset pmu state for cpu
* @vcpu: The vcpu pointer
*
@@ -224,10 +238,8 @@ void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
int i;
struct kvm_pmu *pmu = &vcpu->arch.pmu;
- for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+ for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
- pmu->pmc[i].idx = i;
- }
bitmap_zero(vcpu->arch.pmu.chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
}
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bdbc297d06fb..e621b5d45b27 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -8,6 +8,7 @@
#include <linux/cpu.h>
#include <linux/kvm_host.h>
#include <kvm/arm_vgic.h>
+#include <asm/kvm_emulate.h>
#include <asm/kvm_mmu.h>
#include "vgic.h"
@@ -164,12 +165,18 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
irq->vcpu = NULL;
irq->target_vcpu = vcpu0;
kref_init(&irq->refcount);
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+ switch (dist->vgic_model) {
+ case KVM_DEV_TYPE_ARM_VGIC_V2:
irq->targets = 0;
irq->group = 0;
- } else {
+ break;
+ case KVM_DEV_TYPE_ARM_VGIC_V3:
irq->mpidr = 0;
irq->group = 1;
+ break;
+ default:
+ kfree(dist->spis);
+ return -EINVAL;
}
}
return 0;
@@ -209,7 +216,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
irq->intid = i;
irq->vcpu = NULL;
irq->target_vcpu = vcpu;
- irq->targets = 1U << vcpu->vcpu_id;
kref_init(&irq->refcount);
if (vgic_irq_is_sgi(i)) {
/* SGIs */
@@ -219,11 +225,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
/* PPIs */
irq->config = VGIC_CONFIG_LEVEL;
}
-
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
- irq->group = 1;
- else
- irq->group = 0;
}
if (!irqchip_in_kernel(vcpu->kvm))
@@ -286,10 +287,19 @@ int vgic_init(struct kvm *kvm)
for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+ switch (dist->vgic_model) {
+ case KVM_DEV_TYPE_ARM_VGIC_V3:
irq->group = 1;
- else
+ irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+ break;
+ case KVM_DEV_TYPE_ARM_VGIC_V2:
irq->group = 0;
+ irq->targets = 1U << idx;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
}
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 936962abc38d..c45e2d7e942f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -250,7 +250,7 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
* pending state of interrupt is latched in pending_latch variable.
* Userspace will save and restore pending state and line_level
* separately.
- * Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+ * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.txt
* for handling of ISPENDR and ICPENDR.
*/
for (i = 0; i < len * 8; i++) {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 3ba7278fb533..0d090482720d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ if (vgic_irq_is_mapped_level(irq)) {
+ bool was_high = irq->line_level;
+
+ /*
+ * We need to update the state of the interrupt because
+ * the guest might have changed the state of the device
+ * while the interrupt was disabled at the VGIC level.
+ */
+ irq->line_level = vgic_get_phys_line_level(irq);
+ /*
+ * Deactivate the physical interrupt so the GIC will let
+ * us know when it is asserted again.
+ */
+ if (!irq->active && was_high && !irq->line_level)
+ vgic_irq_set_phys_active(irq, false);
+ }
irq->enabled = true;
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
@@ -195,6 +211,12 @@ static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
vgic_irq_set_phys_active(irq, true);
}
+static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
+{
+ return (vgic_irq_is_sgi(irq->intid) &&
+ vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
+}
+
void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
@@ -207,6 +229,12 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
for_each_set_bit(i, &val, len * 8) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ /* GICD_ISPENDR0 SGI bits are WI */
+ if (is_vgic_v2_sgi(vcpu, irq)) {
+ vgic_put_irq(vcpu->kvm, irq);
+ continue;
+ }
+
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw)
vgic_hw_irq_spending(vcpu, irq, is_uaccess);
@@ -254,6 +282,12 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
for_each_set_bit(i, &val, len * 8) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ /* GICD_ICPENDR0 SGI bits are WI */
+ if (is_vgic_v2_sgi(vcpu, irq)) {
+ vgic_put_irq(vcpu->kvm, irq);
+ continue;
+ }
+
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 6dd5ad706c92..b00aa304c260 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -184,7 +184,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
if (vgic_irq_is_sgi(irq->intid)) {
u32 src = ffs(irq->source);
- BUG_ON(!src);
+ if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+ irq->intid))
+ return;
+
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
irq->source &= ~(1 << (src - 1));
if (irq->source) {
@@ -484,10 +487,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
kvm_vgic_global_state.vctrl_base + GICH_APR);
}
-void vgic_v2_put(struct kvm_vcpu *vcpu)
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
{
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
+}
+
+void vgic_v2_put(struct kvm_vcpu *vcpu)
+{
+ struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+
+ vgic_v2_vmcr_sync(vcpu);
cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index c2c9ce009f63..a4ad431c92a9 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -167,7 +167,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
model == KVM_DEV_TYPE_ARM_VGIC_V2) {
u32 src = ffs(irq->source);
- BUG_ON(!src);
+ if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+ irq->intid))
+ return;
+
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
irq->source &= ~(1 << (src - 1));
if (irq->source) {
@@ -662,12 +665,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
__vgic_v3_activate_traps(vcpu);
}
-void vgic_v3_put(struct kvm_vcpu *vcpu)
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
{
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
if (likely(cpu_if->vgic_sre))
cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
+}
+
+void vgic_v3_put(struct kvm_vcpu *vcpu)
+{
+ vgic_v3_vmcr_sync(vcpu);
kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 04786c8ec77e..e7bde65ba67c 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -254,6 +254,13 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
bool penda, pendb;
int ret;
+ /*
+ * list_sort may call this function with the same element when
+ * the list is fairly long.
+ */
+ if (unlikely(irqa == irqb))
+ return 0;
+
raw_spin_lock(&irqa->irq_lock);
raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
@@ -919,6 +926,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
vgic_v3_put(vcpu);
}
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu)
+{
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
+ return;
+
+ if (kvm_vgic_global_state.type == VGIC_V2)
+ vgic_v2_vmcr_sync(vcpu);
+ else
+ vgic_v3_vmcr_sync(vcpu);
+}
+
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 57205beaa981..797e05004d80 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -42,7 +42,7 @@
VGIC_AFFINITY_LEVEL(val, 3))
/*
- * As per Documentation/virtual/kvm/devices/arm-vgic-v3.txt,
+ * As per Documentation/virt/kvm/devices/arm-vgic-v3.txt,
* below macros are defined for CPUREG encoding.
*/
#define KVM_REG_ARM_VGIC_SYSREG_OP0_MASK 0x000000000000c000
@@ -63,7 +63,7 @@
KVM_REG_ARM_VGIC_SYSREG_OP2_MASK)
/*
- * As per Documentation/virtual/kvm/devices/arm-vgic-its.txt,
+ * As per Documentation/virt/kvm/devices/arm-vgic-its.txt,
* below macros are defined for ITS table entry encoding.
*/
#define KVM_ITS_CTE_VALID_SHIFT 63
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
void vgic_v2_init_lrs(void);
void vgic_v2_load(struct kvm_vcpu *vcpu);
void vgic_v2_put(struct kvm_vcpu *vcpu);
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
void vgic_v2_save_state(struct kvm_vcpu *vcpu);
void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
void vgic_v3_load(struct kvm_vcpu *vcpu);
void vgic_v3_put(struct kvm_vcpu *vcpu);
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
bool vgic_has_its(struct kvm *kvm);
int kvm_vgic_register_its_device(void);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 887f3b0c2b60..c6a91b044d8d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1855,8 +1855,7 @@ void kvm_set_pfn_dirty(kvm_pfn_t pfn)
if (!kvm_is_reserved_pfn(pfn)) {
struct page *page = pfn_to_page(pfn);
- if (!PageReserved(page))
- SetPageDirty(page);
+ SetPageDirty(page);
}
}
EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
@@ -2477,6 +2476,29 @@ static bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu)
#endif
}
+/*
+ * Unlike kvm_arch_vcpu_runnable, this function is called outside
+ * a vcpu_load/vcpu_put pair. However, for most architectures
+ * kvm_arch_vcpu_runnable does not require vcpu_load.
+ */
+bool __weak kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+ return kvm_arch_vcpu_runnable(vcpu);
+}
+
+static bool vcpu_dy_runnable(struct kvm_vcpu *vcpu)
+{
+ if (kvm_arch_dy_runnable(vcpu))
+ return true;
+
+#ifdef CONFIG_KVM_ASYNC_PF
+ if (!list_empty_careful(&vcpu->async_pf.done))
+ return true;
+#endif
+
+ return false;
+}
+
void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
{
struct kvm *kvm = me->kvm;
@@ -2506,9 +2528,10 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
continue;
if (vcpu == me)
continue;
- if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
+ if (swait_active(&vcpu->wq) && !vcpu_dy_runnable(vcpu))
continue;
- if (yield_to_kernel_mode && !kvm_arch_vcpu_in_kernel(vcpu))
+ if (READ_ONCE(vcpu->preempted) && yield_to_kernel_mode &&
+ !kvm_arch_vcpu_in_kernel(vcpu))
continue;
if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
continue;
@@ -2591,30 +2614,20 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
return anon_inode_getfd(name, &kvm_vcpu_fops, vcpu, O_RDWR | O_CLOEXEC);
}
-static int kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+static void kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
{
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
char dir_name[ITOA_MAX_LEN * 2];
- int ret;
-
- if (!kvm_arch_has_vcpu_debugfs())
- return 0;
if (!debugfs_initialized())
- return 0;
+ return;
snprintf(dir_name, sizeof(dir_name), "vcpu%d", vcpu->vcpu_id);
vcpu->debugfs_dentry = debugfs_create_dir(dir_name,
- vcpu->kvm->debugfs_dentry);
- if (!vcpu->debugfs_dentry)
- return -ENOMEM;
-
- ret = kvm_arch_create_vcpu_debugfs(vcpu);
- if (ret < 0) {
- debugfs_remove_recursive(vcpu->debugfs_dentry);
- return ret;
- }
+ vcpu->kvm->debugfs_dentry);
- return 0;
+ kvm_arch_create_vcpu_debugfs(vcpu);
+#endif
}
/*
@@ -2649,9 +2662,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
if (r)
goto vcpu_destroy;
- r = kvm_create_vcpu_debugfs(vcpu);
- if (r)
- goto vcpu_destroy;
+ kvm_create_vcpu_debugfs(vcpu);
mutex_lock(&kvm->lock);
if (kvm_get_vcpu_by_id(kvm, id)) {
@@ -4205,7 +4216,7 @@ static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
{
struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
- vcpu->preempted = false;
+ WRITE_ONCE(vcpu->preempted, false);
WRITE_ONCE(vcpu->ready, false);
kvm_arch_sched_in(vcpu, cpu);
@@ -4219,7 +4230,7 @@ static void kvm_sched_out(struct preempt_notifier *pn,
struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
if (current->state == TASK_RUNNING) {
- vcpu->preempted = true;
+ WRITE_ONCE(vcpu->preempted, true);
WRITE_ONCE(vcpu->ready, true);
}
kvm_arch_vcpu_put(vcpu);